Line.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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. Point nullPoint = new Point(-1, -1);
  98. //Remove duplicate points
  99. for (int i = 1; i < linePoints.Count; i++)
  100. {
  101. if ((linePoints[i].X == linePoints[i - 1].X) && (linePoints[i].Y == linePoints[i - 1].Y))
  102. {
  103. linePoints[i - 1] = nullPoint;
  104. }
  105. }
  106. foreach(Point linepoint in linePoints)
  107. {
  108. if (!(linepoint.X == -1))
  109. {
  110. tempList.Add(linepoint);
  111. }
  112. }
  113. //Fill the gaps between points
  114. for (int i = 0; i < tempList.Count - 1; i++)
  115. {
  116. List<Point> partialList = BresenhamLineAlgorithm(tempList[i], tempList[i + 1]);
  117. partialList.RemoveAt(partialList.Count - 1);
  118. newList.AddRange(partialList);
  119. }
  120. newList.Add(tempList.Last<Point>());
  121. linePoints = newList;
  122. }
  123. /// <summary>
  124. /// An implementation of the Bresenham Line Algorithm,
  125. /// which calculates all points between two points in a straight line.
  126. /// </summary>
  127. /// <param name="p0">The start point</param>
  128. /// <param name="p1">The end point</param>
  129. /// <returns>All points between p0 and p1 (including p0 and p1)</returns>
  130. public static List<Point> BresenhamLineAlgorithm(Point p0, Point p1)
  131. {
  132. List<Point> returnList = new List<Point>();
  133. int deltaX = p1.X - p0.X;
  134. int deltaY = p1.Y - p0.Y;
  135. if(deltaX != 0 && deltaY != 0)
  136. {
  137. //line is not horizontal or vertical
  138. //Bresenham Implementation taken from Wikipedia
  139. float deltaErr = Math.Abs(deltaY / deltaX);
  140. float error = 0;
  141. int y = p0.Y;
  142. if (deltaX > 0)
  143. {
  144. for (int x = p0.X; x <= p1.X; x++)
  145. {
  146. returnList.Add(new Point(x, y));
  147. error += deltaErr;
  148. if (error >= 0.5)
  149. {
  150. y = y + Math.Sign(deltaY) * 1;
  151. error -= 1;
  152. }
  153. }
  154. }
  155. else if(deltaX < 0)
  156. {
  157. for (int x = p0.X; x >= p1.X; x--)
  158. {
  159. returnList.Add(new Point(x, y));
  160. error += deltaErr;
  161. if (error >= 0.5)
  162. {
  163. y = y + Math.Sign(deltaY) * 1;
  164. error -= 1;
  165. }
  166. }
  167. }
  168. return returnList;
  169. }
  170. else if(deltaX == 0 && deltaY != 0)
  171. {
  172. //line is vertical
  173. if (deltaY < 0)
  174. {
  175. //p1 is above of p0
  176. for (int i = p0.Y; i >= p1.Y; i--)
  177. {
  178. returnList.Add(new Point(p0.X, i));
  179. }
  180. return returnList;
  181. }
  182. else
  183. {
  184. //p1 is below of p0
  185. for (int i = p0.Y; i <= p1.Y; i++)
  186. {
  187. returnList.Add(new Point(p0.X, i));
  188. }
  189. return returnList;
  190. }
  191. }
  192. else if(deltaX != 0 && deltaY == 0)
  193. {
  194. //line is horizontal
  195. if(deltaX < 0)
  196. {
  197. //p1 is left of p0
  198. for(int i = p0.X; i >= p1.X; i--)
  199. {
  200. returnList.Add(new Point(i, p0.Y));
  201. }
  202. return returnList;
  203. }
  204. else
  205. {
  206. //p1 is right of p0
  207. for (int i = p0.X; i <= p1.X; i++)
  208. {
  209. returnList.Add(new Point(i, p0.Y));
  210. }
  211. return returnList;
  212. }
  213. }
  214. else
  215. {
  216. //both points are the same
  217. returnList.Add(p0);
  218. return returnList;
  219. }
  220. }
  221. }
  222. }