Keine Cache-Version

Caching deaktiviert Standardeinstellung für diese Seite:aktiviert (code LNG204)
Wenn die Anzeige zu langsam ist, können Sie den Benutzermodus deaktivieren, um die zwischengespeicherte Version anzuzeigen.

PieSlice.cs

Description du code

PieSlice.cs est un fichier du projet BrolDev.
Ce fichier est situé dans /var/www/bin/sniplets/bibliobrol/broldev/src/.

Projet BrolDev : Librairie de composants réutilisables pour les applications BrolDev en CSharp.

Code source ou contenu du fichier

  1. using System;
  2. using System.Collections;
  3. using System.Diagnostics;
  4. using System.Drawing;
  5. using System.Drawing.Drawing2D;
  6.  
  7. namespace be.gaudry.model.drawing.chart
  8. {
  9. /// <summary>
  10. /// Object representing 3D pie.
  11. /// </summary>
  12. public class PieSlice : IDisposable, ICloneable {
  13.  
  14. /// <summary>
  15. /// Initializes an empty instance of <c>PieSlice</c>.
  16. /// </summary>
  17. protected PieSlice() : base() {
  18. }
  19.  
  20. /// <summary>
  21. /// Initializes a new instance of flat <c>PieSlice</c> class with given
  22. /// bounds and visual style.
  23. /// </summary>
  24. /// <param name="xBoundingRect">
  25. /// x-coordinate of the upper-left corner of the rectangle that is
  26. /// used to draw the top surface of the pie slice.
  27. /// </param>
  28. /// <param name="yBoundingRect">
  29. /// y-coordinate of the upper-left corner of the rectangle that is
  30. /// used to draw the top surface of the pie slice.
  31. /// </param>
  32. /// <param name="widthBoundingRect">
  33. /// Width of the rectangle that is used to draw the top surface of
  34. /// the pie slice.
  35. /// </param>
  36. /// <param name="heightBoundingRect">
  37. /// Height of the rectangle that is used to draw the top surface of
  38. /// the pie slice.
  39. /// </param>
  40. /// <param name="startAngle">
  41. /// Starting angle (in degrees) of the pie slice.
  42. /// </param>
  43. /// <param name="sweepAngle">
  44. /// Sweep angle (in degrees) of the pie slice.
  45. /// </param>
  46. /// <param name="surfaceColor">
  47. /// Color used to paint the pie slice.
  48. /// </param>
  49. public PieSlice(float xBoundingRect, float yBoundingRect, float widthBoundingRect, float heightBoundingRect, float startAngle, float sweepAngle, Color surfaceColor)
  50. : this (xBoundingRect, yBoundingRect, widthBoundingRect, heightBoundingRect, 0F, startAngle, sweepAngle, surfaceColor, ShadowStyle.NoShadow, EdgeColorType.NoEdge) {
  51. }
  52.  
  53. /// <summary>
  54. /// Initializes a new instance of <c>PieSlice</c> class with given
  55. /// bounds and visual style.
  56. /// </summary>
  57. /// <param name="xBoundingRect">
  58. /// x-coordinate of the upper-left corner of the rectangle that is
  59. /// used to draw the top surface of the pie slice.
  60. /// </param>
  61. /// <param name="yBoundingRect">
  62. /// y-coordinate of the upper-left corner of the rectangle that is
  63. /// used to draw the top surface of the pie slice.
  64. /// </param>
  65. /// <param name="widthBoundingRect">
  66. /// Width of the rectangle that is used to draw the top surface of
  67. /// the pie slice.
  68. /// </param>
  69. /// <param name="heightBoundingRect">
  70. /// Height of the rectangle that is used to draw the top surface of
  71. /// the pie slice.
  72. /// </param>
  73. /// <param name="sliceHeight">
  74. /// Height of the pie slice.
  75. /// </param>
  76. /// <param name="startAngle">
  77. /// Starting angle (in degrees) of the pie slice.
  78. /// </param>
  79. /// <param name="sweepAngle">
  80. /// Sweep angle (in degrees) of the pie slice.
  81. /// </param>
  82. /// <param name="surfaceColor">
  83. /// Color used to paint the pie slice.
  84. /// </param>
  85. /// <param name="shadowStyle">
  86. /// Shadow style used for slice rendering.
  87. /// </param>
  88. /// <param name="edgeColorType">
  89. /// Edge color style used for slice rendering.
  90. /// </param>
  91. public PieSlice(float xBoundingRect, float yBoundingRect, float widthBoundingRect, float heightBoundingRect, float sliceHeight, float startAngle, float sweepAngle, Color surfaceColor, ShadowStyle shadowStyle, EdgeColorType edgeColorType) : this() {
  92. // set some persistent values
  93. m_actualStartAngle = startAngle;
  94. m_actualSweepAngle = sweepAngle;
  95. m_surfaceColor = surfaceColor;
  96. m_shadowStyle = shadowStyle;
  97. m_edgeColorType = edgeColorType;
  98. // create pens for rendering
  99. Color edgeLineColor = EdgeColor.GetRenderingColor(edgeColorType, surfaceColor);
  100. m_pen = new Pen(edgeLineColor);
  101. m_pen.LineJoin = LineJoin.Round;
  102. InitializePieSlice(xBoundingRect, yBoundingRect, widthBoundingRect, heightBoundingRect, sliceHeight);
  103. }
  104.  
  105. /// <summary>
  106. /// Initializes a new instance of <c>PieSlice</c> class with given
  107. /// bounds and visual style.
  108. /// </summary>
  109. /// <param name="boundingRect">
  110. /// Bounding rectangle used to draw the top surface of the slice.
  111. /// </param>
  112. /// <param name="sliceHeight">
  113. /// Pie slice height.
  114. /// </param>
  115. /// <param name="startAngle">
  116. /// Starting angle (in degrees) of the pie slice.
  117. /// </param>
  118. /// <param name="sweepAngle">
  119. /// Sweep angle (in degrees) of the pie slice.
  120. /// </param>
  121. /// <param name="surfaceColor">
  122. /// Color used to render pie slice surface.
  123. /// </param>
  124. /// <param name="shadowStyle">
  125. /// Shadow style used in rendering.
  126. /// </param>
  127. /// <param name="edgeColorType">
  128. /// Edge color type used for rendering.
  129. /// </param>
  130. public PieSlice(RectangleF boundingRect, float sliceHeight, float startAngle, float sweepAngle, Color surfaceColor, ShadowStyle shadowStyle, EdgeColorType edgeColorType)
  131. : this(boundingRect.X, boundingRect.Y, boundingRect.Width, boundingRect.Height, sliceHeight, startAngle, sweepAngle, surfaceColor, shadowStyle, edgeColorType) {
  132. }
  133.  
  134. /// <summary>
  135. /// Initializes a new instance of <c>PieSlice</c> class with given
  136. /// bounds and visual style.
  137. /// </summary>
  138. /// <param name="xBoundingRect">
  139. /// x-coordinate of the upper-left corner of the rectangle that is
  140. /// used to draw the top surface of the pie slice.
  141. /// </param>
  142. /// <param name="yBoundingRect">
  143. /// y-coordinate of the upper-left corner of the rectangle that is
  144. /// used to draw the top surface of the pie slice.
  145. /// </param>
  146. /// <param name="widthBoundingRect">
  147. /// Width of the rectangle that is used to draw the top surface of
  148. /// the pie slice.
  149. /// </param>
  150. /// <param name="heightBoundingRect">
  151. /// Height of the rectangle that is used to draw the top surface of
  152. /// the pie slice.
  153. /// </param>
  154. /// <param name="sliceHeight">
  155. /// Height of the pie slice.
  156. /// </param>
  157. /// <param name="startAngle">
  158. /// Starting angle (in degrees) of the pie slice.
  159. /// </param>
  160. /// <param name="sweepAngle">
  161. /// Sweep angle (in degrees) of the pie slice.
  162. /// </param>
  163. /// <param name="surfaceColor">
  164. /// Color used to render pie slice surface.
  165. /// </param>
  166. /// <param name="shadowStyle">
  167. /// Shadow style used in rendering.
  168. /// </param>
  169. /// <param name="edgeColorType">
  170. /// Edge color type used for rendering.
  171. /// </param>
  172. /// <param name="edgeLineWidth">
  173. /// Edge line width.
  174. /// </param>
  175. public PieSlice(float xBoundingRect, float yBoundingRect, float widthBoundingRect, float heightBoundingRect, float sliceHeight, float startAngle, float sweepAngle, Color surfaceColor, ShadowStyle shadowStyle, EdgeColorType edgeColorType, float edgeLineWidth)
  176. : this (xBoundingRect, yBoundingRect, widthBoundingRect, heightBoundingRect, sliceHeight, startAngle, sweepAngle, surfaceColor, shadowStyle, edgeColorType) {
  177. m_pen.Width = edgeLineWidth;
  178. }
  179.  
  180. /// <summary>
  181. /// Initializes a new instance of <c>PieSlice</c> class with given
  182. /// bounds and visual style.
  183. /// </summary>
  184. /// <param name="boundingRect">
  185. /// Bounding rectangle used to draw the top surface of the pie slice.
  186. /// </param>
  187. /// <param name="sliceHeight">
  188. /// Pie slice height.
  189. /// </param>
  190. /// <param name="startAngle">
  191. /// Starting angle (in degrees) of the pie slice.
  192. /// </param>
  193. /// <param name="sweepAngle">
  194. /// Sweep angle (in degrees) of the pie slice.
  195. /// </param>
  196. /// <param name="surfaceColor">
  197. /// Color used to render pie slice surface.
  198. /// </param>
  199. /// <param name="shadowStyle">
  200. /// Shadow style used in rendering.
  201. /// </param>
  202. /// <param name="edgeColorType">
  203. /// Edge color type used for rendering.
  204. /// </param>
  205. /// <param name="edgeLineWidth">
  206. /// Edge line width.
  207. /// </param>
  208. public PieSlice(Rectangle boundingRect, float sliceHeight, float startAngle, float sweepAngle, Color surfaceColor, ShadowStyle shadowStyle, EdgeColorType edgeColorType, float edgeLineWidth)
  209. : this(boundingRect.X, boundingRect.Y, boundingRect.Width, boundingRect.Height, sliceHeight, startAngle, sweepAngle, surfaceColor, shadowStyle, edgeColorType, edgeLineWidth) {
  210. }
  211.  
  212. /// <summary>
  213. /// <c>Finalize</c> implementation
  214. /// </summary>
  215. ~PieSlice() {
  216. Dispose(false);
  217. }
  218.  
  219. /// <summary>
  220. /// Implementation of <c>IDisposable</c> interface.
  221. /// </summary>
  222. public void Dispose() {
  223. Dispose(true);
  224. GC.SuppressFinalize(this);
  225. }
  226.  
  227. /// <summary>
  228. /// Disposes of all resources used by <c>PieSlice</c> object.
  229. /// </summary>
  230. /// <param name="disposing"></param>
  231. protected virtual void Dispose(bool disposing) {
  232. if (!m_disposed) {
  233. if (disposing) {
  234. Debug.Assert(m_pen != null);
  235. m_pen.Dispose();
  236. DisposeBrushes();
  237. Debug.Assert(m_startSide != null);
  238. m_startSide.Dispose();
  239. Debug.Assert(m_endSide != null);
  240. m_endSide.Dispose();
  241. }
  242. m_disposed = true;
  243. }
  244. }
  245.  
  246. /// <summary>
  247. /// Implementation of ICloneable interface.
  248. /// </summary>
  249. /// <returns>
  250. /// A deep copy of this object.
  251. /// </returns>
  252. public object Clone() {
  253. return new PieSlice(BoundingRectangle, SliceHeight, StartAngle, SweepAngle, m_surfaceColor, m_shadowStyle, m_edgeColorType);
  254. }
  255.  
  256. /// <summary>
  257. /// Gets starting angle (in degrees) of the pie slice.
  258. /// </summary>
  259. public float StartAngle {
  260. get { return m_startAngle; }
  261. }
  262.  
  263. /// <summary>
  264. /// Gets sweep angle (in degrees) of the pie slice.
  265. /// </summary>
  266. public float SweepAngle {
  267. get { return m_sweepAngle; }
  268. }
  269.  
  270. /// <summary>
  271. /// Gets ending angle (in degrees) of the pie slice.
  272. /// </summary>
  273. public float EndAngle {
  274. get { return (m_startAngle + m_sweepAngle) % 360; }
  275. }
  276.  
  277. public string Text {
  278. get { return m_text; }
  279. set { m_text = value; }
  280. }
  281.  
  282. /// <summary>
  283. /// Draws the pie slice.
  284. /// </summary>
  285. /// <param name="graphics">
  286. /// <c>Graphics</c> used to draw the pie slice.
  287. /// </param>
  288. public void Draw(Graphics graphics) {
  289. DrawBottom(graphics);
  290. DrawSides(graphics);
  291. DrawTop(graphics);
  292. }
  293.  
  294. /// <summary>
  295. /// Checks if given pie slice contains given point.
  296. /// </summary>
  297. /// <param name="point">
  298. /// <c>PointF</c> to check.
  299. /// </param>
  300. /// <returns>
  301. /// <c>true</c> if point given is contained within the slice.
  302. /// </returns>
  303. public bool Contains(PointF point) {
  304. if (PieSliceContainsPoint(point))
  305. return true;
  306. if (PeripheryContainsPoint(point))
  307. return true;
  308. if (m_startSide.Contains(point))
  309. return true;
  310. if (m_endSide.Contains(point))
  311. return true;
  312. return false;
  313. }
  314.  
  315. /// <summary>
  316. /// Evaluates the point in the middle of the slice.
  317. /// </summary>
  318. /// <returns>
  319. /// <c>PointF</c> in the middle of the pie top.
  320. /// </returns>
  321. public virtual PointF GetTextPosition() {
  322. if (SweepAngle >= 180)
  323. return PeripheralPoint(m_center.X, m_center.Y, m_boundingRectangle.Width / 3, m_boundingRectangle.Height / 3, GetActualAngle(StartAngle) + SweepAngle / 2);
  324. float x = (m_pointStart.X + m_pointEnd.X) / 2;
  325. float y = (m_pointStart.Y + m_pointEnd.Y) / 2;
  326. float angle = (float)(Math.Atan2(y - m_center.Y, x - m_center.X) * 180 / Math.PI);
  327. return PeripheralPoint(m_center.X, m_center.Y, m_boundingRectangle.Width / 3, m_boundingRectangle.Height / 3, GetActualAngle(angle));
  328. }
  329.  
  330. /// <summary>
  331. /// Gets or sets the bounding rectangle.
  332. /// </summary>
  333. internal RectangleF BoundingRectangle {
  334. get { return m_boundingRectangle; }
  335. set { m_boundingRectangle = value; }
  336. }
  337.  
  338. /// <summary>
  339. /// Gets or sets the slice height.
  340. /// </summary>
  341. internal float SliceHeight {
  342. get { return m_sliceHeight; }
  343. set { m_sliceHeight = value; }
  344. }
  345.  
  346. /// <summary>
  347. /// Draws pie slice sides.
  348. /// </summary>
  349. /// <param name="graphics">
  350. /// <c>Graphics</c> used to draw the pie slice.
  351. /// </param>
  352. internal void DrawSides(Graphics graphics) {
  353. DrawHiddenPeriphery(graphics);
  354. // draw wegde sides
  355. if (StartAngle > 90 && StartAngle < 270) {
  356. DrawEndSide(graphics);
  357. DrawStartSide(graphics);
  358. }
  359. else {
  360. DrawStartSide(graphics);
  361. DrawEndSide(graphics);
  362. }
  363. DrawVisiblePeriphery(graphics);
  364. }
  365.  
  366. /// <summary>
  367. /// Splits a pie slice into two on the split angle.
  368. /// </summary>
  369. /// <param name="splitAngle">
  370. /// Angle at which splitting is performed.
  371. /// </param>
  372. /// <returns>
  373. /// An array of two pie slices.
  374. /// </returns>
  375. internal PieSlice[] Split(float splitAngle) {
  376. // if split angle equals one of bounding angles, then nothing to split
  377. if (StartAngle == splitAngle || this.EndAngle == splitAngle)
  378. return new PieSlice[] { (PieSlice)Clone() };
  379.  
  380. float transformedSplitAngle = TransformAngle(splitAngle);
  381.  
  382. float actualStartAngle = GetActualAngle(StartAngle);
  383. float newSweepAngle = (splitAngle - actualStartAngle + 360) % 360;
  384. PieSlice pieSlice1 = new PieSlice(BoundingRectangle, SliceHeight, actualStartAngle, newSweepAngle, m_surfaceColor, m_shadowStyle, m_edgeColorType);
  385. pieSlice1.InitializeSides(true, false);
  386.  
  387. newSweepAngle = GetActualAngle(EndAngle) - splitAngle;
  388. PieSlice pieSlice2 = new PieSlice(BoundingRectangle, SliceHeight, splitAngle, newSweepAngle, m_surfaceColor, m_shadowStyle, m_edgeColorType);
  389. pieSlice2.InitializeSides(false, true);
  390. return new PieSlice[] { pieSlice1, pieSlice2 };
  391. }
  392.  
  393. /// <summary>
  394. /// Reajusts the pie slice to fit new bounding rectangle provided.
  395. /// </summary>
  396. /// <param name="xBoundingRect">
  397. /// x-coordinate of the upper-left corner of the rectangle that is
  398. /// used to draw the top surface of the pie slice.
  399. /// </param>
  400. /// <param name="yBoundingRect">
  401. /// y-coordinate of the upper-left corner of the rectangle that is
  402. /// used to draw the top surface of the pie slice.
  403. /// </param>
  404. /// <param name="widthBoundingRect">
  405. /// Width of the rectangle that is used to draw the top surface of
  406. /// the pie slice.
  407. /// </param>
  408. /// <param name="heightBoundingRect">
  409. /// Height of the rectangle that is used to draw the top surface of
  410. /// the pie slice.
  411. /// </param>
  412. /// <param name="sliceHeight">
  413. /// Height of the pie slice.
  414. /// </param>
  415. internal void Readjust(float xBoundingRect, float yBoundingRect, float widthBoundingRect, float heightBoundingRect, float sliceHeight) {
  416. InitializePieSlice(xBoundingRect, yBoundingRect, widthBoundingRect, heightBoundingRect, sliceHeight);
  417. }
  418.  
  419. /// <summary>
  420. /// Draws visible start side.
  421. /// </summary>
  422. /// <param name="graphics">
  423. /// <c>Graphics</c> used to draw the pie slice.
  424. /// </param>
  425. internal void DrawStartSide(Graphics graphics) {
  426. if (m_startSide != null) {
  427. // checks if the side is visible
  428. if (StartAngle > 90 && StartAngle < 270)
  429. m_startSide.Draw(graphics, m_pen, m_brushStartSide);
  430. else
  431. m_startSide.Draw(graphics, m_pen, m_brushSurface);
  432. }
  433. }
  434.  
  435. /// <summary>
  436. /// Draws visible end side.
  437. /// </summary>
  438. /// <param name="graphics">
  439. /// <c>Graphics</c> used to draw the pie slice.
  440. /// </param>
  441. internal void DrawEndSide(Graphics graphics) {
  442. if (m_endSide != null) {
  443. // checks if the side is visible
  444. if (EndAngle > 90 && EndAngle < 270)
  445. m_endSide.Draw(graphics, m_pen, m_brushSurface);
  446. else
  447. m_endSide.Draw(graphics, m_pen, m_brushEndSide);
  448. }
  449. }
  450.  
  451. /// <summary>
  452. /// Draws visible outer periphery of the pie slice.
  453. /// </summary>
  454. /// <param name="graphics">
  455. /// <c>Graphics</c> used to draw the pie slice.
  456. /// </param>
  457. internal void DrawVisiblePeriphery(Graphics graphics) {
  458. PeripherySurfaceBounds[] peripherySurfaceBounds = GetVisiblePeripherySurfaceBounds();
  459. foreach (PeripherySurfaceBounds surfaceBounds in peripherySurfaceBounds) {
  460. DrawCylinderSurfaceSection(graphics, m_pen, m_brushPeripherySurface, surfaceBounds.StartAngle, surfaceBounds.EndAngle, surfaceBounds.StartPoint, surfaceBounds.EndPoint);
  461. }
  462. }
  463.  
  464. /// <summary>
  465. /// Draws hidden outer periphery of the pie slice.
  466. /// </summary>
  467. /// <param name="graphics">
  468. /// <c>Graphics</c> used to draw the pie slice.
  469. /// </param>
  470. internal void DrawHiddenPeriphery(Graphics graphics) {
  471. PeripherySurfaceBounds[] peripherySurfaceBounds = GetHiddenPeripherySurfaceBounds();
  472. foreach (PeripherySurfaceBounds surfaceBounds in peripherySurfaceBounds) {
  473. DrawCylinderSurfaceSection(graphics, m_pen, m_brushSurface, surfaceBounds.StartAngle, surfaceBounds.EndAngle, surfaceBounds.StartPoint, surfaceBounds.EndPoint);
  474. }
  475. }
  476.  
  477. /// <summary>
  478. /// Draws the bottom of the pie slice.
  479. /// </summary>
  480. /// <param name="graphics">
  481. /// <c>Graphics</c> used to draw the pie slice.
  482. /// </param>
  483. internal void DrawBottom(Graphics graphics) {
  484. graphics.FillPie(m_brushSurface, m_boundingRectangle.X, m_boundingRectangle.Y + m_sliceHeight, m_boundingRectangle.Width, m_boundingRectangle.Height, m_startAngle, m_sweepAngle);
  485. graphics.DrawPie(m_pen, m_boundingRectangle.X, m_boundingRectangle.Y + m_sliceHeight, m_boundingRectangle.Width, m_boundingRectangle.Height, m_startAngle, m_sweepAngle);
  486. }
  487.  
  488. /// <summary>
  489. /// Draws the top of the pie slice.
  490. /// </summary>
  491. /// <param name="graphics">
  492. /// <c>Graphics</c> used to draw the pie slice.
  493. /// </param>
  494. internal void DrawTop(Graphics graphics) {
  495. graphics.FillPie(m_brushSurface, m_boundingRectangle.X, m_boundingRectangle.Y, m_boundingRectangle.Width, m_boundingRectangle.Height, m_startAngle, m_sweepAngle);
  496. graphics.DrawPie(m_pen, m_boundingRectangle, m_startAngle, m_sweepAngle);
  497. }
  498.  
  499. /// <summary>
  500. /// Calculates the smallest rectangle into which this pie slice fits.
  501. /// </summary>
  502. /// <returns>
  503. /// <c>RectangleF</c> into which this pie slice fits exactly.
  504. /// </returns>
  505. internal RectangleF GetFittingRectangle() {
  506. RectangleF boundingRectangle = new RectangleF(m_pointStart.X, m_pointStart.Y, 0, 0);
  507. if ((m_startAngle == 0F) || (m_startAngle + m_sweepAngle >= 360))
  508. GraphicsUtil.IncludePointX(ref boundingRectangle, m_boundingRectangle.Right);
  509. if ((m_startAngle <= 90) && (m_startAngle + m_sweepAngle >= 90) || (m_startAngle + m_sweepAngle >= 450))
  510. GraphicsUtil.IncludePointY(ref boundingRectangle, m_boundingRectangle.Bottom + SliceHeight);
  511. if ((m_startAngle <= 180) && (m_startAngle + m_sweepAngle >= 180) || (m_startAngle + m_sweepAngle >= 540))
  512. GraphicsUtil.IncludePointX(ref boundingRectangle, m_boundingRectangle.Left);
  513. if ((m_startAngle <= 270) && (m_startAngle + m_sweepAngle >= 270) || (m_startAngle + m_sweepAngle >= 630))
  514. GraphicsUtil.IncludePointY(ref boundingRectangle, m_boundingRectangle.Top);
  515. GraphicsUtil.IncludePoint(ref boundingRectangle, m_center);
  516. GraphicsUtil.IncludePoint(ref boundingRectangle, m_centerBelow);
  517. GraphicsUtil.IncludePoint(ref boundingRectangle, m_pointStart);
  518. GraphicsUtil.IncludePoint(ref boundingRectangle, m_pointStartBelow);
  519. GraphicsUtil.IncludePoint(ref boundingRectangle, m_pointEnd);
  520. GraphicsUtil.IncludePoint(ref boundingRectangle, m_pointEndBelow);
  521. return boundingRectangle;
  522. }
  523.  
  524. /// <summary>
  525. /// Checks if given point is contained inside the pie slice.
  526. /// </summary>
  527. /// <param name="point">
  528. /// <c>PointF</c> to check for.
  529. /// </param>
  530. /// <returns>
  531. /// <c>true</c> if given point is inside the pie slice.
  532. /// </returns>
  533. internal bool PieSliceContainsPoint(PointF point) {
  534. return PieSliceContainsPoint(point, m_boundingRectangle.X, m_boundingRectangle.Y, m_boundingRectangle.Width, m_boundingRectangle.Height, m_startAngle, m_sweepAngle);
  535. }
  536.  
  537. /// <summary>
  538. /// Checks if given point is contained by cylinder periphery.
  539. /// </summary>
  540. /// <param name="point">
  541. /// <c>PointF</c> to check for.
  542. /// </param>
  543. /// <returns>
  544. /// <c>true</c> if given point is inside the cylinder periphery.
  545. /// </returns>
  546. internal bool PeripheryContainsPoint(PointF point) {
  547. PeripherySurfaceBounds[] peripherySurfaceBounds = GetVisiblePeripherySurfaceBounds();
  548. foreach (PeripherySurfaceBounds surfaceBounds in peripherySurfaceBounds) {
  549. if (CylinderSurfaceSectionContainsPoint(point, surfaceBounds.StartAngle, surfaceBounds.EndAngle, surfaceBounds.StartPoint, surfaceBounds.EndPoint))
  550. return true;
  551. }
  552. return false;
  553. }
  554.  
  555. /// <summary>
  556. /// Checks if point provided is inside pie slice start cut side.
  557. /// </summary>
  558. /// <param name="point">
  559. /// <c>PointF</c> to check.
  560. /// </param>
  561. /// <returns>
  562. /// <c>true</c> if point is inside the start side.
  563. /// </returns>
  564. internal bool StartSideContainsPoint(PointF point) {
  565. if (m_sliceHeight > 0)
  566. return (m_startSide.Contains(point));
  567. return false;
  568. }
  569.  
  570. /// <summary>
  571. /// Checks if point provided is inside pie slice end cut side.
  572. /// </summary>
  573. /// <param name="point">
  574. /// <c>PointF</c> to check.
  575. /// </param>
  576. /// <returns>
  577. /// <c>true</c> if point is inside the end side.
  578. /// </returns>
  579. internal bool EndSideContainsPoint(PointF point) {
  580. if (m_sliceHeight > 0)
  581. return (m_endSide.Contains(point));
  582. return false;
  583. }
  584.  
  585. /// <summary>
  586. /// Checks if bottom side of the pie slice contains the point.
  587. /// </summary>
  588. /// <param name="point">
  589. /// <c>PointF</c> to check.
  590. /// </param>
  591. /// <returns>
  592. /// <c>true</c> if point is inside the bottom of the pie slice.
  593. /// </returns>
  594. internal bool BottomSurfaceSectionContainsPoint(PointF point) {
  595. if (m_sliceHeight > 0) {
  596. return (PieSliceContainsPoint(point, m_boundingRectangle.X, m_boundingRectangle.Y + m_sliceHeight, m_boundingRectangle.Width, m_boundingRectangle.Height, m_startAngle, m_sweepAngle));
  597. }
  598. return false;
  599. }
  600.  
  601. /// <summary>
  602. /// Creates brushes used to render the pie slice.
  603. /// </summary>
  604. /// <param name="surfaceColor">
  605. /// Color used for rendering.
  606. /// </param>
  607. /// <param name="shadowStyle">
  608. /// Shadow style used for rendering.
  609. /// </param>
  610. protected virtual void CreateSurfaceBrushes(Color surfaceColor, ShadowStyle shadowStyle) {
  611. m_brushSurface = new SolidBrush(surfaceColor);
  612. m_brushSurfaceHighlighted = new SolidBrush(ColorUtil.CreateColorWithCorrectedLightness(surfaceColor, ColorUtil.BrightnessEnhancementFactor1));
  613. switch (shadowStyle) {
  614. case ShadowStyle.NoShadow:
  615. m_brushStartSide = m_brushEndSide = m_brushPeripherySurface = new SolidBrush(surfaceColor);
  616. break;
  617. case ShadowStyle.UniformShadow:
  618. m_brushStartSide = m_brushEndSide = m_brushPeripherySurface = new SolidBrush(ColorUtil.CreateColorWithCorrectedLightness(surfaceColor, -ColorUtil.BrightnessEnhancementFactor1));
  619. break;
  620. case ShadowStyle.GradualShadow:
  621. double angle = m_startAngle - 180 - s_shadowAngle;
  622. if (angle < 0)
  623. angle += 360;
  624. m_brushStartSide = CreateBrushForSide(surfaceColor, angle);
  625. angle = m_startAngle + m_sweepAngle - s_shadowAngle;
  626. if (angle < 0)
  627. angle += 360;
  628. m_brushEndSide = CreateBrushForSide(surfaceColor, angle);
  629. m_brushPeripherySurface = CreateBrushForPeriphery(surfaceColor);
  630. break;
  631. }
  632. }
  633.  
  634. /// <summary>
  635. /// Disposes brush objects.
  636. /// </summary>
  637. protected void DisposeBrushes() {
  638. Debug.Assert(m_brushSurface != null);
  639. Debug.Assert(m_brushStartSide != null);
  640. Debug.Assert(m_brushEndSide != null);
  641. Debug.Assert(m_brushPeripherySurface != null);
  642. Debug.Assert(m_brushSurfaceHighlighted != null);
  643.  
  644. m_brushSurface.Dispose();
  645. m_brushStartSide.Dispose();
  646. m_brushEndSide.Dispose();
  647. m_brushPeripherySurface.Dispose();
  648. m_brushSurfaceHighlighted.Dispose();
  649. }
  650.  
  651. /// <summary>
  652. /// Creates a brush for start and end sides of the pie slice for
  653. /// gradual shade.
  654. /// </summary>
  655. /// <param name="color">
  656. /// Color used for pie slice rendering.
  657. /// </param>
  658. /// <param name="angle">
  659. /// Angle of the surface.
  660. /// </param>
  661. /// <returns>
  662. /// <c>Brush</c> object.
  663. /// </returns>
  664. protected virtual Brush CreateBrushForSide(Color color, double angle) {
  665. return new SolidBrush(ColorUtil.CreateColorWithCorrectedLightness(color, -(float)(ColorUtil.BrightnessEnhancementFactor1 * (1 - 0.8 * Math.Cos(angle * Math.PI / 180)))));
  666. }
  667.  
  668. /// <summary>
  669. /// Creates a brush for outer periphery of the pie slice used for
  670. /// gradual shadow.
  671. /// </summary>
  672. /// <param name="color">
  673. /// Color used for pie slice rendering.
  674. /// </param>
  675. /// <returns>
  676. /// <c>Brush</c> object.
  677. /// </returns>
  678. protected virtual Brush CreateBrushForPeriphery(Color color) {
  679. ColorBlend colorBlend = new ColorBlend();
  680. colorBlend.Colors = new Color[] {
  681. ColorUtil.CreateColorWithCorrectedLightness(color, -ColorUtil.BrightnessEnhancementFactor1 / 2),
  682. color,
  683. ColorUtil.CreateColorWithCorrectedLightness(color, -ColorUtil.BrightnessEnhancementFactor1),
  684. };
  685. colorBlend.Positions = new float[] { 0F, 0.1F, 1.0F };
  686. LinearGradientBrush brush = new LinearGradientBrush(m_boundingRectangle, Color.Blue, Color.White, LinearGradientMode.Horizontal);
  687. brush.InterpolationColors = colorBlend;
  688. return brush;
  689. }
  690.  
  691. /// <summary>
  692. /// Draws the outer periphery of the pie slice.
  693. /// </summary>
  694. /// <param name="graphics">
  695. /// <c>Graphics</c> object used to draw the surface.
  696. /// </param>
  697. /// <param name="pen">
  698. /// <c>Pen</c> used to draw outline.
  699. /// </param>
  700. /// <param name="brush">
  701. /// <c>Brush</c> used to fill the quadrilateral.
  702. /// </param>
  703. /// <param name="boundingRect">
  704. /// Bounding rectangle that is used to draw the top surface of the
  705. /// pie slice.
  706. /// </param>
  707. /// <param name="startAngle">
  708. /// Start angle (in degrees) of the periphery section.
  709. /// </param>
  710. /// <param name="endAngle">
  711. /// End angle (in degrees) of the periphery section.
  712. /// </param>
  713. /// <param name="pointStart">
  714. /// Point representing the start of the periphery.
  715. /// </param>
  716. /// <param name="pointEnd">
  717. /// Point representing the end of the periphery.
  718. /// </param>
  719. protected void DrawCylinderSurfaceSection(Graphics graphics, Pen pen, Brush brush, float startAngle, float endAngle, PointF pointStart, PointF pointEnd) {
  720. GraphicsPath path = CreatePathForCylinderSurfaceSection(startAngle, endAngle, pointStart, pointEnd);
  721. graphics.FillPath(brush, path);
  722. graphics.DrawPath(pen, path);
  723. }
  724.  
  725. /// <summary>
  726. /// Transforms actual angle to angle used for rendering. They are
  727. /// different because of perspective.
  728. /// </summary>
  729. /// <param name="angle">
  730. /// Actual angle.
  731. /// </param>
  732. /// <returns>
  733. /// Rendering angle.
  734. /// </returns>
  735. protected float TransformAngle(float angle) {
  736. double x = m_boundingRectangle.Width * Math.Cos(angle * Math.PI / 180);
  737. double y = m_boundingRectangle.Height * Math.Sin(angle * Math.PI / 180);
  738. float result = (float)(Math.Atan2(y, x) * 180 / Math.PI);
  739. if (result < 0)
  740. return result + 360;
  741. return result;
  742. }
  743.  
  744. /// <summary>
  745. /// Gets the actual angle from the rendering angle.
  746. /// </summary>
  747. /// <param name="transformedAngle">
  748. /// Transformed angle for which actual angle has to be evaluated.
  749. /// </param>
  750. /// <returns>
  751. /// Actual angle.
  752. /// </returns>
  753. protected float GetActualAngle(float transformedAngle) {
  754. double x = m_boundingRectangle.Height * Math.Cos(transformedAngle * Math.PI / 180);
  755. double y = m_boundingRectangle.Width * Math.Sin(transformedAngle * Math.PI / 180);
  756. float result = (float)(Math.Atan2(y, x) * 180 / Math.PI);
  757. if (result < 0)
  758. return result + 360;
  759. return result;
  760. }
  761.  
  762. /// <summary>
  763. /// Calculates the point on ellipse periphery for angle.
  764. /// </summary>
  765. /// <param name="xCenter">
  766. /// x-coordinate of the center of the ellipse.
  767. /// </param>
  768. /// <param name="yCenter">
  769. /// y-coordinate of the center of the ellipse.
  770. /// </param>
  771. /// <param name="semiMajor">
  772. /// Horizontal semi-axis.
  773. /// </param>
  774. /// <param name="semiMinor">
  775. /// Vertical semi-axis.
  776. /// </param>
  777. /// <param name="angleDegrees">
  778. /// Angle (in degrees) for which corresponding periphery point has to
  779. /// be obtained.
  780. /// </param>
  781. /// <returns>
  782. /// <c>PointF</c> on the ellipse.
  783. /// </returns>
  784. protected PointF PeripheralPoint(float xCenter, float yCenter, float semiMajor, float semiMinor, float angleDegrees) {
  785. double angleRadians = angleDegrees * Math.PI / 180;
  786. return new PointF(xCenter + (float)(semiMajor * Math.Cos(angleRadians)), yCenter + (float)(semiMinor * Math.Sin(angleRadians)));
  787. }
  788.  
  789. /// <summary>
  790. /// Initializes pie bounding rectangle, pie height, corners
  791. /// coordinates and brushes used for rendering.
  792. /// </summary>
  793. /// <param name="xBoundingRect">
  794. /// x-coordinate of the upper-left corner of the rectangle that is
  795. /// used to draw the top surface of the pie slice.
  796. /// </param>
  797. /// <param name="yBoundingRect">
  798. /// y-coordinate of the upper-left corner of the rectangle that is
  799. /// used to draw the top surface of the pie slice.
  800. /// </param>
  801. /// <param name="widthBoundingRect">
  802. /// Width of the rectangle that is used to draw the top surface of
  803. /// the pie slice.
  804. /// </param>
  805. /// <param name="heightBoundingRect">
  806. /// Height of the rectangle that is used to draw the top surface of
  807. /// the pie slice.
  808. /// </param>
  809. /// <param name="sliceHeight">
  810. /// Height of the pie slice.
  811. /// </param>
  812. private void InitializePieSlice(float xBoundingRect, float yBoundingRect, float widthBoundingRect, float heightBoundingRect, float sliceHeight) {
  813. // stores bounding rectangle and pie slice height
  814. m_boundingRectangle = new RectangleF(xBoundingRect, yBoundingRect, widthBoundingRect, heightBoundingRect);
  815. m_sliceHeight = sliceHeight;
  816. // recalculates start and sweep angle used for rendering
  817. m_startAngle = TransformAngle(m_actualStartAngle);
  818. m_sweepAngle = m_actualSweepAngle;
  819. if (m_sweepAngle % 180 != 0F)
  820. m_sweepAngle = TransformAngle(m_actualStartAngle + m_actualSweepAngle) - m_startAngle;
  821. if (m_sweepAngle < 0)
  822. m_sweepAngle += 360;
  823. // creates brushes
  824. CreateSurfaceBrushes(m_surfaceColor, m_shadowStyle);
  825. // calculates center and end points on periphery
  826. float xCenter = xBoundingRect + widthBoundingRect / 2;
  827. float yCenter = yBoundingRect + heightBoundingRect / 2;
  828. m_center = new PointF(xCenter, yCenter);
  829. m_centerBelow = new PointF(xCenter, yCenter + sliceHeight);
  830. m_pointStart = PeripheralPoint(xCenter, yCenter, widthBoundingRect / 2, heightBoundingRect / 2, m_actualStartAngle);
  831. m_pointStartBelow = new PointF(m_pointStart.X, m_pointStart.Y + sliceHeight);
  832. m_pointEnd = PeripheralPoint(xCenter, yCenter, widthBoundingRect / 2, heightBoundingRect / 2, m_actualStartAngle + m_actualSweepAngle);
  833. m_pointEndBelow = new PointF(m_pointEnd.X, m_pointEnd.Y + sliceHeight);
  834. InitializeSides();
  835. }
  836.  
  837. /// <summary>
  838. /// Initializes start and end pie slice sides.
  839. /// </summary>
  840. private void InitializeSides() {
  841. InitializeSides(true, true);
  842. }
  843.  
  844. /// <summary>
  845. /// Initializes start and end pie slice sides.
  846. /// </summary>
  847. /// <param name="startSideExists">
  848. /// Does start side exists.
  849. /// </param>
  850. /// <param name="endSideExists">
  851. /// Does end side exists.
  852. /// </param>
  853. private void InitializeSides(bool startSideExists, bool endSideExists) {
  854. if (startSideExists)
  855. m_startSide = new Quadrilateral(m_center, m_pointStart, m_pointStartBelow, m_centerBelow, m_sweepAngle != 180);
  856. else
  857. m_startSide = Quadrilateral.Empty;
  858. if (endSideExists)
  859. m_endSide = new Quadrilateral(m_center, m_pointEnd, m_pointEndBelow, m_centerBelow, m_sweepAngle != 180);
  860. else
  861. m_endSide = Quadrilateral.Empty;
  862. }
  863.  
  864. /// <summary>
  865. /// Gets an array of visible periphery bounds.
  866. /// </summary>
  867. /// <returns>
  868. /// Array of <c>PeripherySurfaceBounds</c> objects.
  869. /// </returns>
  870. private PeripherySurfaceBounds[] GetVisiblePeripherySurfaceBounds() {
  871. ArrayList peripherySurfaceBounds = new ArrayList();
  872. // outer periphery side is visible only when startAngle or endAngle
  873. // is between 0 and 180 degrees
  874. if (!(m_sweepAngle == 0 || (m_startAngle >= 180 && m_startAngle + m_sweepAngle <= 360))) {
  875. // draws the periphery from start angle to the end angle or left
  876. // edge, whichever comes first
  877. if (StartAngle < 180) {
  878. float fi1 = m_startAngle;
  879. PointF x1 = new PointF(m_pointStart.X, m_pointStart.Y);
  880. float fi2 = EndAngle;
  881. PointF x2 = new PointF(m_pointEnd.X, m_pointEnd.Y);
  882. if (m_startAngle + m_sweepAngle > 180) {
  883. fi2 = 180;
  884. x2.X = m_boundingRectangle.X;
  885. x2.Y = m_center.Y;
  886. }
  887. peripherySurfaceBounds.Add(new PeripherySurfaceBounds(fi1, fi2, x1, x2));
  888. }
  889. // if lateral surface is visible from the right edge
  890. if (m_startAngle + m_sweepAngle > 360) {
  891. float fi1 = 0;
  892. PointF x1 = new PointF(m_boundingRectangle.Right, m_center.Y);
  893. float fi2 = EndAngle;
  894. PointF x2 = new PointF(m_pointEnd.X, m_pointEnd.Y);
  895. if (fi2 > 180) {
  896. fi2 = 180;
  897. x2.X = m_boundingRectangle.Left;
  898. x2.Y = m_center.Y;
  899. }
  900. peripherySurfaceBounds.Add(new PeripherySurfaceBounds(fi1, fi2, x1, x2));
  901. }
  902. }
  903. return (PeripherySurfaceBounds[])peripherySurfaceBounds.ToArray(typeof(PeripherySurfaceBounds));
  904. }
  905.  
  906. /// <summary>
  907. /// Gets an array of hidden periphery bounds.
  908. /// </summary>
  909. /// <returns>
  910. /// Array of <c>PeripherySurfaceBounds</c> objects.
  911. /// </returns>
  912. private PeripherySurfaceBounds[] GetHiddenPeripherySurfaceBounds() {
  913. ArrayList peripherySurfaceBounds = new ArrayList();
  914. // outer periphery side is not visible when startAngle or endAngle
  915. // is between 180 and 360 degrees
  916. if (!(m_sweepAngle == 0 || (m_startAngle >= 0 && m_startAngle + m_sweepAngle <= 180))) {
  917. // draws the periphery from start angle to the end angle or right
  918. // edge, whichever comes first
  919. if (m_startAngle + m_sweepAngle > 180) {
  920. float fi1 = m_startAngle;
  921. PointF x1 = new PointF(m_pointStart.X, m_pointStart.Y);
  922. float fi2 = m_startAngle + m_sweepAngle;
  923. PointF x2 = new PointF(m_pointEnd.X, m_pointEnd.Y);
  924. if (fi1 < 180) {
  925. fi1 = 180;
  926. x1.X = m_boundingRectangle.Left;
  927. x1.Y = m_center.Y;
  928. }
  929. if (fi2 > 360) {
  930. fi2 = 360;
  931. x2.X = m_boundingRectangle.Right;
  932. x2.Y = m_center.Y;
  933. }
  934. peripherySurfaceBounds.Add(new PeripherySurfaceBounds(fi1, fi2, x1, x2));
  935. // if pie is crossing 360 & 180 deg. boundary, we have to
  936. // invisible peripheries
  937. if (m_startAngle < 360 && m_startAngle + m_sweepAngle > 540) {
  938. fi1 = 180;
  939. x1 = new PointF(m_boundingRectangle.Left, m_center.Y);
  940. fi2 = EndAngle;
  941. x2 = new PointF(m_pointEnd.X, m_pointEnd.Y);
  942. peripherySurfaceBounds.Add(new PeripherySurfaceBounds(fi1, fi2, x1, x2));
  943. }
  944. }
  945. }
  946. return (PeripherySurfaceBounds[])peripherySurfaceBounds.ToArray(typeof(PeripherySurfaceBounds));
  947. }
  948.  
  949. /// <summary>
  950. /// Creates <c>GraphicsPath</c> for cylinder surface section. This
  951. /// path consists of two arcs and two vertical lines.
  952. /// </summary>
  953. /// <param name="startAngle">
  954. /// Starting angle of the surface.
  955. /// </param>
  956. /// <param name="endAngle">
  957. /// Ending angle of the surface.
  958. /// </param>
  959. /// <param name="pointStart">
  960. /// Starting point on the cylinder surface.
  961. /// </param>
  962. /// <param name="pointEnd">
  963. /// Ending point on the cylinder surface.
  964. /// </param>
  965. /// <returns>
  966. /// <c>GraphicsPath</c> object representing the cylinder surface.
  967. /// </returns>
  968. private GraphicsPath CreatePathForCylinderSurfaceSection(float startAngle, float endAngle, PointF pointStart, PointF pointEnd) {
  969. GraphicsPath path = new GraphicsPath();
  970. path.AddArc(m_boundingRectangle, startAngle, endAngle - startAngle);
  971. path.AddLine(pointEnd.X, pointEnd.Y, pointEnd.X, pointEnd.Y + m_sliceHeight);
  972. path.AddArc(m_boundingRectangle.X, m_boundingRectangle.Y + m_sliceHeight, m_boundingRectangle.Width, m_boundingRectangle.Height, endAngle, startAngle - endAngle);
  973. path.AddLine(pointStart.X, pointStart.Y + m_sliceHeight, pointStart.X, pointStart.Y);
  974. return path;
  975. }
  976.  
  977. /// <summary>
  978. /// Checks if given point is contained within upper and lower pie
  979. /// slice surfaces or within the outer slice brink.
  980. /// </summary>
  981. /// <param name="point">
  982. /// <c>PointF</c> structure to check for.
  983. /// </param>
  984. /// <param name="startAngle">
  985. /// Start angle of the slice.
  986. /// </param>
  987. /// <param name="endAngle">
  988. /// End angle of the slice.
  989. /// </param>
  990. /// <param name="point1">
  991. /// Starting point on the periphery.
  992. /// </param>
  993. /// <param name="point2">
  994. /// Ending point on the periphery.
  995. /// </param>
  996. /// <returns>
  997. /// <c>true</c> if point given is contained.
  998. /// </returns>
  999. private bool CylinderSurfaceSectionContainsPoint(PointF point, float startAngle, float endAngle, PointF point1, PointF point2) {
  1000. if (m_sliceHeight > 0) {
  1001. return Quadrilateral.Contains(point, new PointF[] { point1, new PointF(point1.X, point1.Y + m_sliceHeight), new PointF(point2.X, point2.Y + m_sliceHeight), point2 } );
  1002. }
  1003. return false;
  1004. }
  1005.  
  1006. /// <summary>
  1007. /// Checks if point given is contained within the pie slice.
  1008. /// </summary>
  1009. /// <param name="point">
  1010. /// <c>PointF</c> to check for.
  1011. /// </param>
  1012. /// <param name="xBoundingRectangle">
  1013. /// x-coordinate of the rectangle that bounds the ellipse from which
  1014. /// slice is cut.
  1015. /// </param>
  1016. /// <param name="yBoundingRectangle">
  1017. /// y-coordinate of the rectangle that bounds the ellipse from which
  1018. /// slice is cut.
  1019. /// </param>
  1020. /// <param name="widthBoundingRectangle">
  1021. /// Width of the rectangle that bounds the ellipse from which
  1022. /// slice is cut.
  1023. /// </param>
  1024. /// <param name="heightBoundingRectangle">
  1025. /// Height of the rectangle that bounds the ellipse from which
  1026. /// slice is cut.
  1027. /// </param>
  1028. /// <param name="startAngle">
  1029. /// Start angle of the slice.
  1030. /// </param>
  1031. /// <param name="sweepAngle">
  1032. /// Sweep angle of the slice.
  1033. /// </param>
  1034. /// <returns>
  1035. /// <c>true</c> if point is contained within the slice.
  1036. /// </returns>
  1037. private bool PieSliceContainsPoint(PointF point, float xBoundingRectangle, float yBoundingRectangle, float widthBoundingRectangle, float heightBoundingRectangle, float startAngle, float sweepAngle) {
  1038. double x = point.X - xBoundingRectangle - widthBoundingRectangle / 2;
  1039. double y = point.Y - yBoundingRectangle - heightBoundingRectangle / 2;
  1040. double angle = Math.Atan2(y, x);
  1041. if (angle < 0)
  1042. angle += (2 * Math.PI);
  1043. double angleDegrees = angle * 180 / Math.PI;
  1044. // point is inside the pie slice only if between start and end angle
  1045. if ((angleDegrees >= startAngle && angleDegrees <= (startAngle + sweepAngle)) ||
  1046. (startAngle + sweepAngle > 360) && ((angleDegrees + 360) <= (startAngle + sweepAngle))) {
  1047. // distance of the point from the ellipse centre
  1048. double r = Math.Sqrt(y * y + x * x);
  1049. return GetEllipseRadius(angle) > r;
  1050. }
  1051. return false;
  1052. }
  1053.  
  1054. /// <summary>
  1055. /// Evaluates the distance of an ellipse perimeter point for a
  1056. /// given angle.
  1057. /// </summary>
  1058. /// <param name="angle">
  1059. /// Angle for which distance has to be evaluated.
  1060. /// </param>
  1061. /// <returns>
  1062. /// Distance of the point from the ellipse centre.
  1063. /// </returns>
  1064. private double GetEllipseRadius(double angle) {
  1065. double a = m_boundingRectangle.Width / 2;
  1066. double b = m_boundingRectangle.Height / 2;
  1067. double a2 = a * a;
  1068. double b2 = b * b;
  1069. double cosFi = Math.Cos(angle);
  1070. double sinFi = Math.Sin(angle);
  1071. // distance of the ellipse perimeter point
  1072. return (a * b) / Math.Sqrt(b2 * cosFi * cosFi + a2 * sinFi * sinFi);
  1073. }
  1074.  
  1075. /// <summary>
  1076. /// Internal structure used to store periphery bounds data.
  1077. /// </summary>
  1078. private struct PeripherySurfaceBounds {
  1079. public PeripherySurfaceBounds(float startAngle, float endAngle, PointF startPoint, PointF endPoint) {
  1080. m_startAngle = startAngle;
  1081. m_endAngle = endAngle;
  1082. m_startPoint = startPoint;
  1083. m_endPoint = endPoint;
  1084. }
  1085.  
  1086. public float StartAngle {
  1087. get { return m_startAngle; }
  1088. }
  1089.  
  1090. public float EndAngle {
  1091. get { return m_endAngle; }
  1092. }
  1093.  
  1094. public PointF StartPoint {
  1095. get { return m_startPoint; }
  1096. }
  1097.  
  1098. public PointF EndPoint {
  1099. get { return m_endPoint; }
  1100. }
  1101.  
  1102. private float m_startAngle;
  1103. private float m_endAngle;
  1104. private PointF m_startPoint;
  1105. private PointF m_endPoint;
  1106. }
  1107.  
  1108. /// <summary>
  1109. /// Bounding rectangle that bounds the ellipse from which pie slice
  1110. /// is cut.
  1111. /// </summary>
  1112. protected RectangleF m_boundingRectangle;
  1113. /// <summary>
  1114. /// Pie slice height.
  1115. /// </summary>
  1116. protected float m_sliceHeight;
  1117. /// <summary>
  1118. /// Start angle.
  1119. /// </summary>
  1120. protected float m_startAngle;
  1121. /// <summary>
  1122. /// Sweep angle.
  1123. /// </summary>
  1124. protected float m_sweepAngle;
  1125. /// <summary>
  1126. /// Actual start angle.
  1127. /// </summary>
  1128. private float m_actualStartAngle;
  1129. /// <summary>
  1130. /// Actual sweep angle.
  1131. /// </summary>
  1132. private float m_actualSweepAngle;
  1133. /// <summary>
  1134. /// Color of the surface.
  1135. /// </summary>
  1136. private Color m_surfaceColor = Color.Empty;
  1137. /// <summary>
  1138. /// Style used for shadow.
  1139. /// </summary>
  1140. private ShadowStyle m_shadowStyle = ShadowStyle.NoShadow;
  1141. /// <summary>
  1142. /// <c>EdgeColorType</c> used to draw pie sliece edges.
  1143. /// </summary>
  1144. private EdgeColorType m_edgeColorType = EdgeColorType.NoEdge;
  1145. /// <summary>
  1146. /// <c>Brush</c> used to render slice top surface.
  1147. /// </summary>
  1148. protected Brush m_brushSurface = null;
  1149. /// <summary>
  1150. /// <c>Brush</c> used to render slice top surface when highlighted.
  1151. /// </summary>
  1152. protected Brush m_brushSurfaceHighlighted = null;
  1153. /// <summary>
  1154. /// <c>Brush</c> used to render slice starting cut side.
  1155. /// </summary>
  1156. protected Brush m_brushStartSide = null;
  1157. /// <summary>
  1158. /// <c>Brush</c> used to render slice ending cut side.
  1159. /// </summary>
  1160. protected Brush m_brushEndSide = null;
  1161. /// <summary>
  1162. /// <c>Brush</c> used to render pie slice periphery (cylinder outer surface).
  1163. /// </summary>
  1164. protected Brush m_brushPeripherySurface = null;
  1165. /// <summary>
  1166. /// <c>Pen</c> object used to draw pie slice edges.
  1167. /// </summary>
  1168. protected Pen m_pen = null;
  1169. /// <summary>
  1170. /// <c>PointF</c> corresponding to pie slice center.
  1171. /// </summary>
  1172. protected PointF m_center;
  1173. /// <summary>
  1174. /// <c>PointF</c> corresponding to the lower pie slice center.
  1175. /// </summary>
  1176. protected PointF m_centerBelow;
  1177. /// <summary>
  1178. /// <c>PointF</c> on the periphery corresponding to the start cut
  1179. /// side.
  1180. /// </summary>
  1181. protected PointF m_pointStart;
  1182. /// <summary>
  1183. /// <c>PointF</c> on the periphery corresponding to the start cut
  1184. /// side.
  1185. /// </summary>
  1186. protected PointF m_pointStartBelow;
  1187. /// <summary>
  1188. /// <c>PointF</c> on the periphery corresponding to the end cut
  1189. /// side.
  1190. /// </summary>
  1191. protected PointF m_pointEnd;
  1192. /// <summary>
  1193. /// <c>PointF</c> on the periphery corresponding to the end cut
  1194. /// side.
  1195. /// </summary>
  1196. protected PointF m_pointEndBelow;
  1197. /// <summary>
  1198. /// <c>Quadrilateral</c> representing the start side.
  1199. /// </summary>
  1200. protected Quadrilateral m_startSide = Quadrilateral.Empty;
  1201. /// <summary>
  1202. /// <c>Quadrilateral</c> representing the end side.
  1203. /// </summary>
  1204. protected Quadrilateral m_endSide = Quadrilateral.Empty;
  1205. /// <summary>
  1206. /// Text attached to the slice.
  1207. /// </summary>
  1208. private string m_text;
  1209. /// <summary>
  1210. /// Flag indicating if object has been disposed.
  1211. /// </summary>
  1212. private bool m_disposed = false;
  1213. /// <summary>
  1214. /// Angle offset used to define reference angle for gradual shadow.
  1215. /// </summary>
  1216. private static float s_shadowAngle = 20F;
  1217. }
  1218. }

Structure et Fichiers du projet

Afficher/masquer...


Répertoires contenus dans /var/www/bin/sniplets/bibliobrol/broldev/src/model/drawing/chart/ 
IcôneNomTailleModification
Pas de sous-répertoires.
IcôneNomTailleModification
| _ Répertoire parent0 octets1716249507 21/05/2024 01:58:27
Fichiers contenus dans /var/www/bin/sniplets/bibliobrol/broldev/src/model/drawing/chart/ 
IcôneNomTailleModificationAction
IcôneNomTailleModificationAction
Afficher le fichier .cs|.csShadowStyle.cs620 octets31/10/2018 18:33:22-refusé-
Afficher le fichier .cs|.csEdgeColor.cs2.92 Ko31/10/2018 18:33:21-refusé-
Afficher le fichier .cs|.csPieChart.cs44.97 Ko31/10/2018 18:33:22-refusé-
Afficher le fichier .cs|.csColorUtil.cs2.05 Ko31/10/2018 18:33:21-refusé-
Afficher le fichier .resx|.resxPieChartControl.resx1.69 Ko31/10/2018 18:33:22-refusé-
Afficher le fichier .cs|.csPieChartControl.cs14.04 Ko31/10/2018 18:33:22-refusé-
Afficher le fichier .cs|.csPieSlice.cs52.86 Ko31/10/2018 18:33:22-refusé-
Afficher le fichier .cs|.csGraphicsUtil.cs2.33 Ko31/10/2018 18:33:21-refusé-
Afficher le fichier .cs|.csQuadrilateral.cs6.42 Ko31/10/2018 18:33:22-refusé-
Afficher le fichier .cs|.csEdgeColorType.cs1.64 Ko31/10/2018 18:33:21-refusé-

Utilisation de l'explorateur de code

  • Navigation :
    • Un clic sur une icône de répertoire ouvre ce répertoire pour en afficher les fichiers.
    • Lorsque le répertoire en cours ne contient pas de sous-répertoires il est possible de remonter vers le répertoire parent.
    • La structure de répertoires en treetable (tableau en forme d'arborescence) n'est plus possibledans cette version.
    • Un clic sur une icône de fichier ouvre ce fichier pour en afficher le code avec la coloration syntaxique adaptée en fonction du langage principal utilisé dans le fichier.
  • Affichage :
    • Il est possible de trier les répertoires ou les fichiers selon certains critères (nom, taille, date).
  • Actions :
    • Les actions possible sur les fichiers dépendent de vos droits d'utilisateur sur le site. Veuillez activer le mode utilisateur pour activer les actions.

Deutsche Übersetzung

Sie haben gebeten, diese Seite auf Deutsch zu besuchen. Momentan ist nur die Oberfläche übersetzt, aber noch nicht der gesamte Inhalt.

Wenn Sie mir bei Übersetzungen helfen wollen, ist Ihr Beitrag willkommen. Alles, was Sie tun müssen, ist, sich auf der Website zu registrieren und mir eine Nachricht zu schicken, in der Sie gebeten werden, Sie der Gruppe der Übersetzer hinzuzufügen, die Ihnen die Möglichkeit gibt, die gewünschten Seiten zu übersetzen. Ein Link am Ende jeder übersetzten Seite zeigt an, dass Sie der Übersetzer sind und einen Link zu Ihrem Profil haben.

Vielen Dank im Voraus.

Dokument erstellt 16/10/2009, zuletzt geändert 26/10/2018
Quelle des gedruckten Dokuments:https://www.gaudry.be/de/cs-broldev-source-rf-model/drawing/chart/PieSlice.cs.html

Die Infobro ist eine persönliche Seite, deren Inhalt in meiner alleinigen Verantwortung liegt. Der Text ist unter der CreativeCommons-Lizenz (BY-NC-SA) verfügbar. Weitere Informationen auf die Nutzungsbedingungen und dem Autor.