Browse Source

Fixed Errors with Deletion.

Bugfixes:
- Reimplemented the Bresenham Line Algorithm using the pseudocode from
wikipedia
- Fixed an issue where the deletion matrixes where reset to empty
matrixes when redrawing the image.
Status:
- Deletion is now in a working state, checking deletion matrixes should
also occur on all points traveled by the cursor between timer ticks.
Use the Line algorithm to determine traveled path between ticks and
check those points in matrixes.
Martin Edlund 5 years ago
parent
commit
1859a7731c
2 changed files with 107 additions and 88 deletions
  1. 6 4
      SketchAssistant/SketchAssistant/Form1.cs
  2. 101 84
      SketchAssistant/SketchAssistant/Line.cs

+ 6 - 4
SketchAssistant/SketchAssistant/Form1.cs

@@ -48,6 +48,8 @@ namespace SketchAssistant
         bool mousePressed = false;
         //The Position of the Cursor in the right picture box
         Point currentCursorPosition;
+        //The Previous Cursor Position in the right picture box
+        Point previousCursorPosition;
         //The graphic representation of the right image
         Graphics graph = null;
         //Deletion Matrixes for checking postions of lines in the image
@@ -122,7 +124,6 @@ namespace SketchAssistant
         private void pictureBoxRight_MouseMove(object sender, MouseEventArgs e)
         {
             currentCursorPosition = ConvertCoordinates(new Point(e.X, e.Y));
-            Console.WriteLine(currentCursorPosition.ToString());
         }
 
         //hold left mouse button to draw.
@@ -153,11 +154,15 @@ namespace SketchAssistant
         private void canvasButton_Click(object sender, EventArgs e)
         {
             DrawEmptyCanvas();
+            //The following lines cannot be in DrawEmptyCanvas()
+            isFilledMatrix = new bool[rightImage.Width, rightImage.Height];
+            linesMatrix = new List<int>[rightImage.Width, rightImage.Height];
         }
 
         //add a Point on every tick to the Drawpath
         private void mouseTimer_Tick(object sender, EventArgs e)
         {
+
             if (currentState.Equals(ProgramState.Draw) && mousePressed)
             {
                 currentLine.Add(currentCursorPosition);
@@ -170,7 +175,6 @@ namespace SketchAssistant
                 if (currentCursorPosition.X < rightImage.Width - 1 && currentCursorPosition.Y < rightImage.Height- 1
                     && currentCursorPosition.X >= 0 && currentCursorPosition.Y >= 0)
                 {
-
                     if (isFilledMatrix[currentCursorPosition.X, currentCursorPosition.Y])
                     {
                         foreach (int lineid in linesMatrix[currentCursorPosition.X, currentCursorPosition.Y])
@@ -207,8 +211,6 @@ namespace SketchAssistant
                 graph.FillRectangle(Brushes.White, 0, 0, leftImage.Width + 10, leftImage.Height + 10);
                 pictureBoxRight.Image = rightImage;
             }
-            isFilledMatrix = new bool[rightImage.Width, rightImage.Height];
-            linesMatrix = new List<int>[rightImage.Width, rightImage.Height];
             this.Refresh();
             pictureBoxRight.Refresh();
         }

+ 101 - 84
SketchAssistant/SketchAssistant/Line.cs

@@ -104,130 +104,147 @@ namespace SketchAssistant
         {
             List<Point> newList = new List<Point>();
             List<Point> tempList = new List<Point>();
-            Point nullPoint = new Point(-1, -1);
-            //Remove duplicate points
-            for (int i = 1; i < linePoints.Count; i++)
+            //Since Point is non-nullable, we must ensure the nullPoints, 
+            //which we remove can not possibly be points of the original given line.
+            int nullValue = linePoints[0].X + 1;
+            //Fill the gaps between points
+            for (int i = 0; i < linePoints.Count - 1; i++)
             {
-                if ((linePoints[i].X == linePoints[i - 1].X) && (linePoints[i].Y == linePoints[i - 1].Y))
-                {
-                    linePoints[i - 1] = nullPoint;
-                }
+                nullValue += linePoints[i + 1].X;
+                List<Point> partialList = BresenhamLineAlgorithm(linePoints[i], linePoints[i + 1]);
+                tempList.AddRange(partialList);
             }
-            foreach(Point linepoint in linePoints)
+            Point nullPoint = new Point(nullValue, 0);
+            //Set duplicate points to the null point
+            for (int i = 1; i < tempList.Count; i++)
             {
-                if (!(linepoint.X == -1))
+                if ((tempList[i].X == tempList[i - 1].X) && (tempList[i].Y == tempList[i - 1].Y))
                 {
-                    tempList.Add(linepoint);
+                    tempList[i - 1] = nullPoint;
                 }
             }
-            //Fill the gaps between points
-            for (int i = 0; i < tempList.Count - 1; i++)
+            //remove the null points
+            foreach(Point tempPoint in tempList)
             {
-                List<Point> partialList = BresenhamLineAlgorithm(tempList[i], tempList[i + 1]);
-                partialList.RemoveAt(partialList.Count - 1);
-                newList.AddRange(partialList);
+                if (tempPoint.X != nullValue)
+                {
+                    newList.Add(tempPoint);
+                }
             }
-            newList.Add(tempList.Last<Point>());
-            linePoints = newList;
+            linePoints = new List<Point>(newList);
         }
 
         /// <summary>
         /// An implementation of the Bresenham Line Algorithm, 
         /// which calculates all points between two points in a straight line.
+        /// Implemented using the pseudocode on Wikipedia.
         /// </summary>
         /// <param name="p0">The start point</param>
         /// <param name="p1">The end point</param>
         /// <returns>All points between p0 and p1 (including p0 and p1)</returns>
         public static List<Point> BresenhamLineAlgorithm(Point p0, Point p1)
         {
-            List<Point> returnList = new List<Point>();
             int deltaX = p1.X - p0.X;
             int deltaY = p1.Y - p0.Y;
-            if(deltaX != 0 && deltaY != 0)
+            List<Point> returnList;
+
+            if (Math.Abs(deltaY) < Math.Abs(deltaX))
             {
-                //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)
+                if(p0.X > p1.X)
                 {
-                    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;
-                        }
-                    }
+                    returnList = GetLineLow(p1.X, p1.Y, p0.X, p0.Y);
+                    returnList.Reverse();
                 }
-                else if(deltaX < 0)
+                else
                 {
-                    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;
-                        }
-                    }
+                    returnList = GetLineLow(p0.X, p0.Y, p1.X, p1.Y);
                 }
-                return returnList;
             }
-            else if(deltaX == 0 && deltaY != 0)
+            else
             {
-                //line is vertical
-                if (deltaY < 0)
+                if (p0.Y > p1.Y)
                 {
-                    //p1 is above of p0
-                    for (int i = p0.Y; i >= p1.Y; i--)
-                    {
-                        returnList.Add(new Point(p0.X, i));
-                    }
-                    return returnList;
+                    returnList = GetLineHigh(p1.X, p1.Y, p0.X, p0.Y);
+                    returnList.Reverse();
                 }
                 else
                 {
-                    //p1 is below of p0
-                    for (int i = p0.Y; i <= p1.Y; i++)
-                    {
-                        returnList.Add(new Point(p0.X, i));
-                    }
-                    return returnList;
+                    returnList = GetLineHigh(p0.X, p0.Y, p1.X, p1.Y);
                 }
             }
-            else if(deltaX != 0 && deltaY == 0)
+            return returnList;
+        }
+
+        /// <summary>
+        /// Helping function of the Bresenham Line algorithm,
+        /// under the assumption that abs(deltaY) is smaller than abs(deltX)
+        /// and x0 is smaller than x1
+        /// </summary>
+        /// <param name="x0">x value of point 0</param>
+        /// <param name="y0">y value of point 0</param>
+        /// <param name="x1">x value of point 1</param>
+        /// <param name="y1">y value of point 1</param>
+        /// <returns>All points on the line between the two points</returns>
+        private static List<Point> GetLineLow(int x0, int y0, int x1, int y1)
+        {
+            List<Point> returnList = new List<Point>();
+            int dx = x1 - x0;
+            int dy = y1 - y0;
+            int yi = 1;
+            if(dy < 0)
+            {
+                yi = -1;
+                dy = -dy;
+            }
+            int D = 2 * dy - dx;
+            int y = y0;
+            for (int x = x0; x <= x1; x++)
             {
-                //line is horizontal
-                if(deltaX < 0)
+                returnList.Add(new Point(x, y));
+                if (D > 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;
+                    y = y + yi;
+                    D = D - 2 * dx;
                 }
+                D = D + 2 * dy;
             }
-            else
+            return returnList;
+        }
+
+        /// <summary>
+        /// Helping function of the Bresenham Line algorithm,
+        /// under the assumption that abs(deltaY) is larger or equal than abs(deltX)
+        /// and y0 is smaller than y1
+        /// </summary>
+        /// <param name="x0">x value of point 0</param>
+        /// <param name="y0">y value of point 0</param>
+        /// <param name="x1">x value of point 1</param>
+        /// <param name="y1">y value of point 1</param>
+        /// <returns>All points on the line between the two points</returns>
+        private static List<Point> GetLineHigh(int x0, int y0, int x1, int y1)
+        {
+            List<Point> returnList = new List<Point>();
+            int dx = x1 - x0;
+            int dy = y1 - y0;
+            int xi = 1;
+            if (dx < 0)
+            {
+                xi = -1;
+                dx = -dx;
+            }
+            int D = 2 * dx - dy;
+            int x = x0;
+            for (int y = y0; y <= y1; y++)
             {
-                //both points are the same
-                returnList.Add(p0);
-                return returnList;
+                returnList.Add(new Point(x, y));
+                if (D > 0)
+                {
+                    x = x + xi;
+                    D = D - 2 * dy;
+                }
+                D = D + 2 * dx;
             }
+            return returnList;
         }
     }
 }