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 octets1717859405 08/06/2024 17:10:05
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.

Document créé le 16/10/2009, dernière modification le 26/10/2018
Source du document imprimé : https://www.gaudry.be/cs-broldev-source-rf-model/drawing/chart//PieSlice.cs.html

L'infobrol est un site personnel dont le contenu n'engage que moi. Le texte est mis à disposition sous licence CreativeCommons(BY-NC-SA). Plus d'info sur les conditions d'utilisation et sur l'auteur.