Line.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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. public class Line
  10. {
  11. private List<Point> linePoints;
  12. private int identifier;
  13. private bool isTemporary;
  14. /// <summary>
  15. /// The constructor for lines which are only temporary.
  16. /// If you want nice lines use the other constructor.
  17. /// </summary>
  18. /// <param name="points">The points of the line</param>
  19. public Line(List<Point> points)
  20. {
  21. linePoints = new List<Point>(points);
  22. isTemporary = true;
  23. }
  24. /// <summary>
  25. /// The constructor for lines, which will be more resource efficient
  26. /// and have the ability to populate deletion matrixes.
  27. /// </summary>
  28. /// <param name="points">The points of the line</param>
  29. /// <param name="id">The identifier of the line</param>
  30. public Line(List<Point> points, int id)
  31. {
  32. linePoints = new List<Point>(points);
  33. identifier = id;
  34. CleanPoints();
  35. isTemporary = false;
  36. }
  37. public Point GetStartPoint()
  38. {
  39. return linePoints.First();
  40. }
  41. public Point GetEndPoint()
  42. {
  43. return linePoints.Last();
  44. }
  45. public List<Point> GetPoints()
  46. {
  47. return linePoints;
  48. }
  49. /// <summary>
  50. /// A function that takes a Graphics element and returns it with
  51. /// the line drawn on it.
  52. /// </summary>
  53. /// <param name="canvas">The Graphics element on which the line shall be drawn</param>
  54. /// <returns>The given Graphics element with the additional line</returns>
  55. public Graphics DrawLine(Graphics canvas)
  56. {
  57. Pen thePen = new Pen(Color.Black);
  58. for(int i = 0; i < linePoints.Count - 1 ; i++)
  59. {
  60. canvas.DrawLine(thePen, linePoints[i], linePoints[i + 1]);
  61. }
  62. return canvas;
  63. }
  64. /// <summary>
  65. /// A function that will take to matrixes and populate the with the line data of this line object
  66. /// </summary>
  67. /// <param name="boolMatrix">The Matrix of booleans, in which is saved wether there is a line at this position.</param>
  68. /// <param name="listMatrix">The Matrix of Lists of integers, in which is saved which lines are at this position</param>
  69. public void PopulateMatrixes(bool[,] boolMatrix, List<int>[,] listMatrix)
  70. {
  71. if(!isTemporary)
  72. {
  73. foreach (Point currPoint in linePoints)
  74. {
  75. try
  76. {
  77. boolMatrix[currPoint.X, currPoint.Y] = true;
  78. if (listMatrix[currPoint.X, currPoint.Y] == null)
  79. {
  80. listMatrix[currPoint.X, currPoint.Y] = new List<int>();
  81. }
  82. listMatrix[currPoint.X, currPoint.Y].Add(identifier);
  83. }
  84. catch (IndexOutOfRangeException e)
  85. {
  86. }
  87. }
  88. }
  89. }
  90. /// <summary>
  91. /// Removes duplicate points from the line object
  92. /// </summary>
  93. private void CleanPoints()
  94. {
  95. List<Point> newList = new List<Point>();
  96. List<Point> tempList = new List<Point>();
  97. //Since Point is non-nullable, we must ensure the nullPoints,
  98. //which we remove can not possibly be points of the original given line.
  99. int nullValue = linePoints[0].X + 1;
  100. //Fill the gaps between points
  101. for (int i = 0; i < linePoints.Count - 1; i++)
  102. {
  103. nullValue += linePoints[i + 1].X;
  104. List<Point> partialList = BresenhamLineAlgorithm(linePoints[i], linePoints[i + 1]);
  105. tempList.AddRange(partialList);
  106. }
  107. Point nullPoint = new Point(nullValue, 0);
  108. //Set duplicate points to the null point
  109. for (int i = 1; i < tempList.Count; i++)
  110. {
  111. if ((tempList[i].X == tempList[i - 1].X) && (tempList[i].Y == tempList[i - 1].Y))
  112. {
  113. tempList[i - 1] = nullPoint;
  114. }
  115. }
  116. //remove the null points
  117. foreach(Point tempPoint in tempList)
  118. {
  119. if (tempPoint.X != nullValue)
  120. {
  121. newList.Add(tempPoint);
  122. }
  123. }
  124. linePoints = new List<Point>(newList);
  125. }
  126. /// <summary>
  127. /// An implementation of the Bresenham Line Algorithm,
  128. /// which calculates all points between two points in a straight line.
  129. /// Implemented using the pseudocode on Wikipedia.
  130. /// </summary>
  131. /// <param name="p0">The start point</param>
  132. /// <param name="p1">The end point</param>
  133. /// <returns>All points between p0 and p1 (including p0 and p1)</returns>
  134. public static List<Point> BresenhamLineAlgorithm(Point p0, Point p1)
  135. {
  136. int deltaX = p1.X - p0.X;
  137. int deltaY = p1.Y - p0.Y;
  138. List<Point> returnList;
  139. if (Math.Abs(deltaY) < Math.Abs(deltaX))
  140. {
  141. if(p0.X > p1.X)
  142. {
  143. returnList = GetLineLow(p1.X, p1.Y, p0.X, p0.Y);
  144. returnList.Reverse();
  145. }
  146. else
  147. {
  148. returnList = GetLineLow(p0.X, p0.Y, p1.X, p1.Y);
  149. }
  150. }
  151. else
  152. {
  153. if (p0.Y > p1.Y)
  154. {
  155. returnList = GetLineHigh(p1.X, p1.Y, p0.X, p0.Y);
  156. returnList.Reverse();
  157. }
  158. else
  159. {
  160. returnList = GetLineHigh(p0.X, p0.Y, p1.X, p1.Y);
  161. }
  162. }
  163. return returnList;
  164. }
  165. /// <summary>
  166. /// Helping function of the Bresenham Line algorithm,
  167. /// under the assumption that abs(deltaY) is smaller than abs(deltX)
  168. /// and x0 is smaller than x1
  169. /// </summary>
  170. /// <param name="x0">x value of point 0</param>
  171. /// <param name="y0">y value of point 0</param>
  172. /// <param name="x1">x value of point 1</param>
  173. /// <param name="y1">y value of point 1</param>
  174. /// <returns>All points on the line between the two points</returns>
  175. private static List<Point> GetLineLow(int x0, int y0, int x1, int y1)
  176. {
  177. List<Point> returnList = new List<Point>();
  178. int dx = x1 - x0;
  179. int dy = y1 - y0;
  180. int yi = 1;
  181. if(dy < 0)
  182. {
  183. yi = -1;
  184. dy = -dy;
  185. }
  186. int D = 2 * dy - dx;
  187. int y = y0;
  188. for (int x = x0; x <= x1; x++)
  189. {
  190. returnList.Add(new Point(x, y));
  191. if (D > 0)
  192. {
  193. y = y + yi;
  194. D = D - 2 * dx;
  195. }
  196. D = D + 2 * dy;
  197. }
  198. return returnList;
  199. }
  200. /// <summary>
  201. /// Helping function of the Bresenham Line algorithm,
  202. /// under the assumption that abs(deltaY) is larger or equal than abs(deltX)
  203. /// and y0 is smaller than y1
  204. /// </summary>
  205. /// <param name="x0">x value of point 0</param>
  206. /// <param name="y0">y value of point 0</param>
  207. /// <param name="x1">x value of point 1</param>
  208. /// <param name="y1">y value of point 1</param>
  209. /// <returns>All points on the line between the two points</returns>
  210. private static List<Point> GetLineHigh(int x0, int y0, int x1, int y1)
  211. {
  212. List<Point> returnList = new List<Point>();
  213. int dx = x1 - x0;
  214. int dy = y1 - y0;
  215. int xi = 1;
  216. if (dx < 0)
  217. {
  218. xi = -1;
  219. dx = -dx;
  220. }
  221. int D = 2 * dx - dy;
  222. int x = x0;
  223. for (int y = y0; y <= y1; y++)
  224. {
  225. returnList.Add(new Point(x, y));
  226. if (D > 0)
  227. {
  228. x = x + xi;
  229. D = D - 2 * dy;
  230. }
  231. D = D + 2 * dx;
  232. }
  233. return returnList;
  234. }
  235. }
  236. }