using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; namespace SketchAssistant { class Line { private List linePoints; private int identifier; public Line(List points) { linePoints = new List(points); } public Line(List points, int id) { linePoints = new List(points); identifier = id; CleanPoints(); } public Point GetStartPoint() { return linePoints.First(); } public Point GetEndPoint() { return linePoints.Last(); } /// /// A function that takes a Graphics element and returns it with /// the line drawn on it. /// /// The Graphics element on which the line shall be drawn /// The given Graphics element with the additional line public Graphics DrawLine(Graphics canvas) { Pen thePen = new Pen(Color.Black); for(int i = 0; i < linePoints.Count - 1 ; i++) { canvas.DrawLine(thePen, linePoints[i], linePoints[i + 1]); } return canvas; } /// /// A function that will take to matrixes and populate the with the line data of this line object /// Exceptions: /// Will throw IndexOutOfRangeException if any of the points of this line are /// outside of the given matrixes. /// /// The Matrix of booleans, in which is saved wether there is a line at this position. /// The Matrix of Lists of integers, in which is saved which lines are at this position public void PopulateMatrixes(bool[,] boolMatrix, List[,] listMatrix) { foreach(Point currPoint in linePoints) { try { boolMatrix[currPoint.X, currPoint.Y] = true; if (listMatrix[currPoint.X, currPoint.Y] == null) { listMatrix[currPoint.X, currPoint.Y] = new List(); } listMatrix[currPoint.X, currPoint.Y].Add(identifier); } catch(IndexOutOfRangeException e) { } } } /// /// Removes duplicate points from the line object /// private void CleanPoints() { List newList = new List(); List tempList = new List(); Point nullPoint = new Point(-1, -1); //Remove duplicate points for (int i = 1; i < linePoints.Count; i++) { if ((linePoints[i].X == linePoints[i - 1].X) && (linePoints[i].Y == linePoints[i - 1].Y)) { linePoints[i - 1] = nullPoint; } } foreach(Point linepoint in linePoints) { if (!(linepoint.X == -1)) { tempList.Add(linepoint); } } //Fill the gaps between points for (int i = 0; i < tempList.Count - 1; i++) { List partialList = BresenhamLineAlgorithm(tempList[i], tempList[i + 1]); partialList.RemoveAt(partialList.Count - 1); newList.AddRange(partialList); } newList.Add(tempList.Last()); linePoints = newList; } /// /// An implementation of the Bresenham Line Algorithm, /// which calculates all points between two points in a straight line. /// /// The start point /// The end point /// All points between p0 and p1 (including p0 and p1) public static List BresenhamLineAlgorithm(Point p0, Point p1) { List returnList = new List(); int deltaX = p1.X - p0.X; int deltaY = p1.Y - p0.Y; if(deltaX != 0 && deltaY != 0) { //line is not horizontal or vertical //Bresenham Implementation taken from Wikipedia float deltaErr = Math.Abs(deltaY / deltaX); float error = 0; int y = p0.Y; if (deltaX > 0) { for (int x = p0.X; x <= p1.X; x++) { returnList.Add(new Point(x, y)); error += deltaErr; if (error >= 0.5) { y = y + Math.Sign(deltaY) * 1; error -= 1; } } } else if(deltaX < 0) { for (int x = p0.X; x >= p1.X; x--) { returnList.Add(new Point(x, y)); error += deltaErr; if (error >= 0.5) { y = y + Math.Sign(deltaY) * 1; error -= 1; } } } return returnList; } else if(deltaX == 0 && deltaY != 0) { //line is vertical if (deltaY < 0) { //p1 is above of p0 for (int i = p0.Y; i >= p1.Y; i--) { returnList.Add(new Point(p0.X, i)); } return returnList; } else { //p1 is below of p0 for (int i = p0.Y; i <= p1.Y; i++) { returnList.Add(new Point(p0.X, i)); } return returnList; } } else if(deltaX != 0 && deltaY == 0) { //line is horizontal if(deltaX < 0) { //p1 is left of p0 for(int i = p0.X; i >= p1.X; i--) { returnList.Add(new Point(i, p0.Y)); } return returnList; } else { //p1 is right of p0 for (int i = p0.X; i <= p1.X; i++) { returnList.Add(new Point(i, p0.Y)); } return returnList; } } else { //both points are the same returnList.Add(p0); return returnList; } } } }