Line.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. class Line
  10. {
  11. private List<Point> linePoints;
  12. private int identifier;
  13. public Line(List<Point> points)
  14. {
  15. linePoints = new List<Point>(points);
  16. }
  17. public Line(List<Point> points, int id)
  18. {
  19. linePoints = new List<Point>(points);
  20. identifier = id;
  21. CleanPoints();
  22. }
  23. public Point GetStartPoint()
  24. {
  25. return linePoints.First();
  26. }
  27. public Point GetEndPoint()
  28. {
  29. return linePoints.Last();
  30. }
  31. /// <summary>
  32. /// A function that takes a Graphics element and returns it with
  33. /// the line drawn on it.
  34. /// </summary>
  35. /// <param name="canvas">The Graphics element on which the line shall be drawn</param>
  36. /// <returns>The given Graphics element with the additional line</returns>
  37. public Graphics DrawLine(Graphics canvas)
  38. {
  39. Pen thePen = new Pen(Color.Black);
  40. for(int i = 0; i < linePoints.Count - 1 ; i++)
  41. {
  42. canvas.DrawLine(thePen, linePoints[i], linePoints[i + 1]);
  43. }
  44. return canvas;
  45. }
  46. /// <summary>
  47. /// A function that will take to matrixes and populate the with the line data of this line object
  48. /// Exceptions:
  49. /// Will throw IndexOutOfRangeException if any of the points of this line are
  50. /// outside of the given matrixes.
  51. /// </summary>
  52. /// <param name="boolMatrix">The Matrix of booleans, in which is saved wether there is a line at this position.</param>
  53. /// <param name="listMatrix">The Matrix of Lists of integers, in which is saved which lines are at this position</param>
  54. public void PopulateMatrixes(bool[,] boolMatrix, List<int>[,] listMatrix)
  55. {
  56. foreach(Point currPoint in linePoints)
  57. {
  58. try
  59. {
  60. boolMatrix[currPoint.X, currPoint.Y] = true;
  61. if (listMatrix[currPoint.X, currPoint.Y] == null)
  62. {
  63. listMatrix[currPoint.X, currPoint.Y] = new List<int>();
  64. }
  65. listMatrix[currPoint.X, currPoint.Y].Add(identifier);
  66. }
  67. catch(IndexOutOfRangeException e)
  68. {
  69. }
  70. }
  71. }
  72. /// <summary>
  73. /// Removes duplicate points from the line object
  74. /// </summary>
  75. private void CleanPoints()
  76. {
  77. List<Point> newList = new List<Point>();
  78. List<Point> tempList = new List<Point>();
  79. Point nullPoint = new Point(-1, -1);
  80. //Remove duplicate points
  81. for (int i = 1; i < linePoints.Count; i++)
  82. {
  83. if ((linePoints[i].X == linePoints[i - 1].X) && (linePoints[i].Y == linePoints[i - 1].Y))
  84. {
  85. linePoints[i - 1] = nullPoint;
  86. }
  87. }
  88. foreach(Point linepoint in linePoints)
  89. {
  90. if (!(linepoint.X == -1))
  91. {
  92. tempList.Add(linepoint);
  93. }
  94. }
  95. //Fill the gaps between points
  96. for (int i = 0; i < tempList.Count - 1; i++)
  97. {
  98. List<Point> partialList = BresenhamLineAlgorithm(tempList[i], tempList[i + 1]);
  99. partialList.RemoveAt(partialList.Count - 1);
  100. newList.AddRange(partialList);
  101. }
  102. newList.Add(tempList.Last<Point>());
  103. linePoints = newList;
  104. }
  105. /// <summary>
  106. /// An implementation of the Bresenham Line Algorithm,
  107. /// which calculates all points between two points in a straight line.
  108. /// </summary>
  109. /// <param name="p0">The start point</param>
  110. /// <param name="p1">The end point</param>
  111. /// <returns>All points between p0 and p1 (including p0 and p1)</returns>
  112. public static List<Point> BresenhamLineAlgorithm(Point p0, Point p1)
  113. {
  114. List<Point> returnList = new List<Point>();
  115. int deltaX = p1.X - p0.X;
  116. int deltaY = p1.Y - p0.Y;
  117. if(deltaX != 0 && deltaY != 0)
  118. {
  119. //line is not horizontal or vertical
  120. //Bresenham Implementation taken from Wikipedia
  121. float deltaErr = Math.Abs(deltaY / deltaX);
  122. float error = 0;
  123. int y = p0.Y;
  124. if (deltaX > 0)
  125. {
  126. for (int x = p0.X; x <= p1.X; x++)
  127. {
  128. returnList.Add(new Point(x, y));
  129. error += deltaErr;
  130. if (error >= 0.5)
  131. {
  132. y = y + Math.Sign(deltaY) * 1;
  133. error -= 1;
  134. }
  135. }
  136. }
  137. else if(deltaX < 0)
  138. {
  139. for (int x = p0.X; x >= p1.X; x--)
  140. {
  141. returnList.Add(new Point(x, y));
  142. error += deltaErr;
  143. if (error >= 0.5)
  144. {
  145. y = y + Math.Sign(deltaY) * 1;
  146. error -= 1;
  147. }
  148. }
  149. }
  150. return returnList;
  151. }
  152. else if(deltaX == 0 && deltaY != 0)
  153. {
  154. //line is vertical
  155. if (deltaY < 0)
  156. {
  157. //p1 is above of p0
  158. for (int i = p0.Y; i >= p1.Y; i--)
  159. {
  160. returnList.Add(new Point(p0.X, i));
  161. }
  162. return returnList;
  163. }
  164. else
  165. {
  166. //p1 is below of p0
  167. for (int i = p0.Y; i <= p1.Y; i++)
  168. {
  169. returnList.Add(new Point(p0.X, i));
  170. }
  171. return returnList;
  172. }
  173. }
  174. else if(deltaX != 0 && deltaY == 0)
  175. {
  176. //line is horizontal
  177. if(deltaX < 0)
  178. {
  179. //p1 is left of p0
  180. for(int i = p0.X; i >= p1.X; i--)
  181. {
  182. returnList.Add(new Point(i, p0.Y));
  183. }
  184. return returnList;
  185. }
  186. else
  187. {
  188. //p1 is right of p0
  189. for (int i = p0.X; i <= p1.X; i++)
  190. {
  191. returnList.Add(new Point(i, p0.Y));
  192. }
  193. return returnList;
  194. }
  195. }
  196. else
  197. {
  198. //both points are the same
  199. returnList.Add(p0);
  200. return returnList;
  201. }
  202. }
  203. }
  204. }