GeometryCalculator.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Drawing;
  7. namespace SketchAssistant
  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 deltaX = p1.X - p0.X;
  95. int deltaY = p1.Y - p0.Y;
  96. List<Point> returnList;
  97. if (Math.Abs(deltaY) < Math.Abs(deltaX))
  98. {
  99. if (p0.X > p1.X)
  100. {
  101. returnList = GetLineLow(p1.X, p1.Y, p0.X, p0.Y);
  102. returnList.Reverse();
  103. }
  104. else
  105. {
  106. returnList = GetLineLow(p0.X, p0.Y, p1.X, p1.Y);
  107. }
  108. }
  109. else
  110. {
  111. if (p0.Y > p1.Y)
  112. {
  113. returnList = GetLineHigh(p1.X, p1.Y, p0.X, p0.Y);
  114. returnList.Reverse();
  115. }
  116. else
  117. {
  118. returnList = GetLineHigh(p0.X, p0.Y, p1.X, p1.Y);
  119. }
  120. }
  121. return returnList;
  122. }
  123. /// <summary>
  124. /// Helping function of the Bresenham Line algorithm,
  125. /// under the assumption that abs(deltaY) is smaller than abs(deltX)
  126. /// and x0 is smaller than x1
  127. /// </summary>
  128. /// <param name="x0">x value of point 0</param>
  129. /// <param name="y0">y value of point 0</param>
  130. /// <param name="x1">x value of point 1</param>
  131. /// <param name="y1">y value of point 1</param>
  132. /// <returns>All points on the line between the two points</returns>
  133. private static List<Point> GetLineLow(int x0, int y0, int x1, int y1)
  134. {
  135. List<Point> returnList = new List<Point>();
  136. int dx = x1 - x0;
  137. int dy = y1 - y0;
  138. int yi = 1;
  139. if (dy < 0)
  140. {
  141. yi = -1;
  142. dy = -dy;
  143. }
  144. int D = 2 * dy - dx;
  145. int y = y0;
  146. for (int x = x0; x <= x1; x++)
  147. {
  148. returnList.Add(new Point(x, y));
  149. if (D > 0)
  150. {
  151. y = y + yi;
  152. D = D - 2 * dx;
  153. }
  154. D = D + 2 * dy;
  155. }
  156. return returnList;
  157. }
  158. /// <summary>
  159. /// Helping function of the Bresenham Line algorithm,
  160. /// under the assumption that abs(deltaY) is larger or equal than abs(deltX)
  161. /// and y0 is smaller than y1
  162. /// </summary>
  163. /// <param name="x0">x value of point 0</param>
  164. /// <param name="y0">y value of point 0</param>
  165. /// <param name="x1">x value of point 1</param>
  166. /// <param name="y1">y value of point 1</param>
  167. /// <returns>All points on the line between the two points</returns>
  168. private static List<Point> GetLineHigh(int x0, int y0, int x1, int y1)
  169. {
  170. List<Point> returnList = new List<Point>();
  171. int dx = x1 - x0;
  172. int dy = y1 - y0;
  173. int xi = 1;
  174. if (dx < 0)
  175. {
  176. xi = -1;
  177. dx = -dx;
  178. }
  179. int D = 2 * dx - dy;
  180. int x = x0;
  181. for (int y = y0; y <= y1; y++)
  182. {
  183. returnList.Add(new Point(x, y));
  184. if (D > 0)
  185. {
  186. x = x + xi;
  187. D = D - 2 * dy;
  188. }
  189. D = D + 2 * dx;
  190. }
  191. return returnList;
  192. }
  193. }
  194. }