GeometryCalculator.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace SketchAssistantWPF
  8. {
  9. /// <summary>
  10. /// A class that contains all algorithms related to geometry.
  11. /// </summary>
  12. public static class GeometryCalculator
  13. {
  14. /// <summary>
  15. /// An implementation of the Bresenham Line Algorithm,
  16. /// which calculates the points of a circle in a radius around a center point.
  17. /// Implemented with the help of code examples on Wikipedia.
  18. /// </summary>
  19. /// <param name="center">The center of the circle.</param>
  20. /// <param name="radius">The radius of the circle,
  21. /// when it is zero or less, only the midpoint is returned</param>
  22. /// <returns>The HashSet containing all Points on the circle.</returns>
  23. public static HashSet<Point> BresenhamCircleAlgorithm(Point center, int radius)
  24. {
  25. if (radius <= 0) { return new HashSet<Point> { center }; }
  26. int x = radius - 1;
  27. int y = 0;
  28. int dx = 1;
  29. int dy = 1;
  30. int err = dx - (radius * 2);
  31. HashSet<Point> returnSet = new HashSet<Point>();
  32. while (x >= y)
  33. {
  34. returnSet.Add(new Point(center.X + x, center.Y + y));
  35. returnSet.Add(new Point(center.X + y, center.Y + x));
  36. returnSet.Add(new Point(center.X - y, center.Y + x));
  37. returnSet.Add(new Point(center.X - x, center.Y + y));
  38. returnSet.Add(new Point(center.X - x, center.Y - y));
  39. returnSet.Add(new Point(center.X - y, center.Y - x));
  40. returnSet.Add(new Point(center.X + y, center.Y - x));
  41. returnSet.Add(new Point(center.X + x, center.Y - y));
  42. if (err <= 0)
  43. {
  44. y++;
  45. err += dy;
  46. dy += 2;
  47. }
  48. if (err > 0)
  49. {
  50. x--;
  51. dx += 2;
  52. err += dx - (radius * 2);
  53. }
  54. }
  55. return returnSet;
  56. }
  57. /// <summary>
  58. /// A simple algorithm that returns a filled circle with a radius and a center point.
  59. /// </summary>
  60. /// <param name="center">The center point of the alorithm </param>
  61. /// <param name="radius">The radius of the circle, if its less or equal to 1
  62. /// only the center point is returned. </param>
  63. /// <returns>All the points in or on the circle.</returns>
  64. public static HashSet<Point> FilledCircleAlgorithm(Point center, int radius)
  65. {
  66. HashSet<Point> returnSet = new HashSet<Point> { center };
  67. //Fill the circle
  68. for (int x = 0; x < radius; x++)
  69. {
  70. for (int y = 0; y < radius; y++)
  71. {
  72. //Check if point is on or in the circle
  73. if ((x * x + y * y - radius * radius) <= 0)
  74. {
  75. returnSet.Add(new Point(center.X + x, center.Y + y));
  76. returnSet.Add(new Point(center.X - x, center.Y + y));
  77. returnSet.Add(new Point(center.X + x, center.Y - y));
  78. returnSet.Add(new Point(center.X - x, center.Y - y));
  79. }
  80. }
  81. }
  82. return returnSet;
  83. }
  84. /// <summary>
  85. /// An implementation of the Bresenham Line Algorithm,
  86. /// which calculates all points between two points in a straight line.
  87. /// Implemented using the pseudocode on Wikipedia.
  88. /// </summary>
  89. /// <param name="p0">The start point</param>
  90. /// <param name="p1">The end point</param>
  91. /// <returns>All points between p0 and p1 (including p0 and p1)</returns>
  92. public static List<Point> BresenhamLineAlgorithm(Point p0, Point p1)
  93. {
  94. int p1x = (int)p1.X;
  95. int p1y = (int)p1.Y;
  96. int p0x = (int)p0.X;
  97. int p0y = (int)p0.Y;
  98. int deltaX = p1x - p0x;
  99. int deltaY = p1y - p0y;
  100. List<Point> returnList;
  101. if (Math.Abs(deltaY) < Math.Abs(deltaX))
  102. {
  103. if (p0.X > p1.X)
  104. {
  105. returnList = GetLineLow(p1x, p1y, p0x, p0y);
  106. returnList.Reverse();
  107. }
  108. else
  109. {
  110. returnList = GetLineLow(p0x, p0y, p1x, p1y);
  111. }
  112. }
  113. else
  114. {
  115. if (p0.Y > p1.Y)
  116. {
  117. returnList = GetLineHigh(p1x, p1y, p0x, p0y);
  118. returnList.Reverse();
  119. }
  120. else
  121. {
  122. returnList = GetLineHigh(p0x, p0y, p1x, p1y);
  123. }
  124. }
  125. return returnList;
  126. }
  127. /// <summary>
  128. /// Helping function of the Bresenham Line algorithm,
  129. /// under the assumption that abs(deltaY) is smaller than abs(deltX)
  130. /// and x0 is smaller than x1
  131. /// </summary>
  132. /// <param name="x0">x value of point 0</param>
  133. /// <param name="y0">y value of point 0</param>
  134. /// <param name="x1">x value of point 1</param>
  135. /// <param name="y1">y value of point 1</param>
  136. /// <returns>All points on the line between the two points</returns>
  137. private static List<Point> GetLineLow(int x0, int y0, int x1, int y1)
  138. {
  139. List<Point> returnList = new List<Point>();
  140. int dx = x1 - x0;
  141. int dy = y1 - y0;
  142. int yi = 1;
  143. if (dy < 0)
  144. {
  145. yi = -1;
  146. dy = -dy;
  147. }
  148. int D = 2 * dy - dx;
  149. int y = y0;
  150. for (int x = x0; x <= x1; x++)
  151. {
  152. returnList.Add(new Point(x, y));
  153. if (D > 0)
  154. {
  155. y = y + yi;
  156. D = D - 2 * dx;
  157. }
  158. D = D + 2 * dy;
  159. }
  160. return returnList;
  161. }
  162. /// <summary>
  163. /// Helping function of the Bresenham Line algorithm,
  164. /// under the assumption that abs(deltaY) is larger or equal than abs(deltX)
  165. /// and y0 is smaller than y1
  166. /// </summary>
  167. /// <param name="x0">x value of point 0</param>
  168. /// <param name="y0">y value of point 0</param>
  169. /// <param name="x1">x value of point 1</param>
  170. /// <param name="y1">y value of point 1</param>
  171. /// <returns>All points on the line between the two points</returns>
  172. private static List<Point> GetLineHigh(int x0, int y0, int x1, int y1)
  173. {
  174. List<Point> returnList = new List<Point>();
  175. int dx = x1 - x0;
  176. int dy = y1 - y0;
  177. int xi = 1;
  178. if (dx < 0)
  179. {
  180. xi = -1;
  181. dx = -dx;
  182. }
  183. int D = 2 * dx - dy;
  184. int x = x0;
  185. for (int y = y0; y <= y1; y++)
  186. {
  187. returnList.Add(new Point(x, y));
  188. if (D > 0)
  189. {
  190. x = x + xi;
  191. D = D - 2 * dy;
  192. }
  193. D = D + 2 * dx;
  194. }
  195. return returnList;
  196. }
  197. }
  198. }