Pārlūkot izejas kodu

Added working Redraw Functionality

Martin Edlund 6 gadi atpakaļ
vecāks
revīzija
4393adeeb2

+ 71 - 24
SketchAssistant/SketchAssistant/Form1.cs

@@ -107,13 +107,13 @@ namespace SketchAssistant
         /// </summary>
         ActionHistory historyOfActions;
         /// <summary>
-        /// A boolean value indicating whether or not the redraw mode is active.
+        /// List of items which will be overlayed over the right canvas.
         /// </summary>
-        bool redrawModeActive = false;
+        List<HashSet<Point>> overlayItems;
         /// <summary>
-        /// A tuple containing the areas around the end points of the current line in the left graphic.
+        /// The assistant responsible for the redraw mode
         /// </summary>
-        Tuple<HashSet<Point>, HashSet<Point>> currentLineEndings;
+        RedrawAssistant redrawAss;
         /// <summary>
         /// Size of areas marking endpoints of lines in the redraw mode.
         /// </summary>
@@ -128,6 +128,7 @@ namespace SketchAssistant
             currentState = ProgramState.Idle;
             this.DoubleBuffered = true;
             historyOfActions = new ActionHistory(null);
+            redrawAss = new RedrawAssistant();
             UpdateButtonStatus();
         }
 
@@ -176,9 +177,11 @@ namespace SketchAssistant
                         isFilledMatrix = new bool[rightImage.Width, rightImage.Height];
                         linesMatrix = new HashSet<int>[rightImage.Width, rightImage.Height];
                         rightLineList = new List<Tuple<bool, Line>>();
-                        //Show the start and ends of lines
-                        CalculateAndDisplayStartAndEnd(leftLineList[0], markerRadius);
-
+                        //Start the redraw mode
+                        redrawAss = new RedrawAssistant(leftLineList);
+                        UpdateSizes();
+                        overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1);
+                        RedrawRightImage();
                         this.Refresh();
                     }
                     catch (FileImporterException ex)
@@ -187,6 +190,7 @@ namespace SketchAssistant
                     }
                 }
             }
+            UpdateButtonStatus();
         }
 
         //Changes the state of the program to drawing
@@ -312,6 +316,9 @@ namespace SketchAssistant
                 rightLineList.Add(new Tuple<bool, Line>(true, newLine));
                 newLine.PopulateMatrixes(isFilledMatrix, linesMatrix);
                 historyOfActions.AddNewAction(new SketchAction(SketchAction.ActionType.Draw, newLine.GetID()));
+                //Execute a RedrawAssistant tick with the currently finished Line
+                overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, newLine.GetID());
+                RedrawRightImage();
             }
             UpdateButtonStatus();
         }
@@ -329,6 +336,14 @@ namespace SketchAssistant
                 isFilledMatrix = new bool[rightImage.Width, rightImage.Height];
                 linesMatrix = new HashSet<int>[rightImage.Width, rightImage.Height];
                 rightLineList = new List<Tuple<bool, Line>>();
+                //Reinitialise the Redraw Assistant.
+                if(leftLineList != null)
+                {
+                    redrawAss = new RedrawAssistant(leftLineList);
+                    UpdateSizes();
+                    overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1);
+                    RedrawRightImage();
+                }
             }
             UpdateButtonStatus();
             UpdateSizes();
@@ -348,6 +363,9 @@ namespace SketchAssistant
                 Line drawline = new Line(currentLine);
                 drawline.DrawLine(rightGraph);
                 pictureBoxRight.Image = rightImage;
+                //RedrawTick
+                overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1);
+                RedrawRightImage();
             }
             //Deleting
             if (currentState.Equals(ProgramState.Delete) && mousePressed)
@@ -427,6 +445,7 @@ namespace SketchAssistant
         {
             var workingCanvas = GetEmptyCanvas(rightImage.Width, rightImage.Height);
             var workingGraph = Graphics.FromImage(workingCanvas);
+            //Lines
             foreach (Tuple<bool, Line> lineBoolTuple in rightLineList)
             {
                 if (lineBoolTuple.Item1)
@@ -434,6 +453,20 @@ namespace SketchAssistant
                     lineBoolTuple.Item2.DrawLine(workingGraph);
                 }
             }
+            //The Line being currently drawn
+            if(currentLine != null && currentLine.Count > 0 && currentState.Equals(ProgramState.Draw) && mousePressed)
+            {
+                var currLine = new Line(currentLine);
+                currLine.DrawLine(workingGraph);
+            }
+            //Overlay Items
+            foreach (HashSet<Point> item in overlayItems)
+            {
+                foreach(Point p in item)
+                {
+                    workingGraph.FillRectangle(Brushes.Green, p.X, p.Y, 1, 1);
+                }
+            }
             SetAndRefreshRightImage(workingCanvas);
         }
 
@@ -598,9 +631,12 @@ namespace SketchAssistant
 
             foreach(Point pnt in GeometryCalculator.FilledCircleAlgorithm(p, (int)range))
             {
-                if (isFilledMatrix[pnt.X, pnt.Y])
+                if(pnt.X >= 0 && pnt.Y >= 0 && pnt.X < rightImage.Width && pnt.Y < rightImage.Height)
                 {
-                    returnSet.UnionWith(linesMatrix[pnt.X, pnt.Y]);
+                    if (isFilledMatrix[pnt.X, pnt.Y])
+                    {
+                        returnSet.UnionWith(linesMatrix[pnt.X, pnt.Y]);
+                    }
                 }
             }
             return returnSet;
@@ -630,21 +666,16 @@ namespace SketchAssistant
         }
         
         /// <summary>
-        /// Will calculate and mark the start and endpoints of the given line on the right canvas.
+        /// Will calculate the start and endpoints of the given line on the right canvas.
         /// </summary>
         /// <param name="line">The line.</param>
         /// <param name="size">The size of the circle with which the endpoints of the line are marked.</param>
-        private void CalculateAndDisplayStartAndEnd(Line line, int size)
+        private Tuple<HashSet<Point>, HashSet<Point>> CalculateStartAndEnd(Line line, int size)
         {
             var circle0 = GeometryCalculator.FilledCircleAlgorithm(line.GetStartPoint(), size);
-            var circle1 = GeometryCalculator.BresenhamCircleAlgorithm(line.GetEndPoint(), size);
-            currentLineEndings = new Tuple<HashSet<Point>, HashSet<Point>>(circle0, circle1);
-
-            rightGraph = Graphics.FromImage(rightImage);
-            foreach(Point p in circle0) { rightGraph.FillRectangle(Brushes.Red, p.X, p.Y, 1, 1); }
-            foreach(Point p in circle1) { rightGraph.FillRectangle(Brushes.Blue, p.X, p.Y, 1, 1); }
-
-            SetAndRefreshRightImage(rightImage);
+            var circle1 = GeometryCalculator.FilledCircleAlgorithm(line.GetEndPoint(), size);
+            var currentLineEndings = new Tuple<HashSet<Point>, HashSet<Point>>(circle0, circle1);
+            return currentLineEndings;
         }
 
         /// <summary>
@@ -654,11 +685,27 @@ namespace SketchAssistant
         {
             if (rightImage != null)
             {
-                double widthProp = pictureBoxRight.Width / rightImage.Width;
-                double heightProp = pictureBoxRight.Height / rightImage.Height;
-                double scaling = (widthProp + heightProp) / 2;
-                markerRadius = (int)(10 / scaling);
-                deletionRadius = (int)(5 / scaling);
+                int widthImage = pictureBoxRight.Image.Width;
+                int heightImage = pictureBoxRight.Image.Height;
+                int widthBox = pictureBoxRight.Width;
+                int heightBox = pictureBoxRight.Height;
+                
+                float imageRatio = (float)widthImage / (float)heightImage;
+                float containerRatio = (float)widthBox / (float)heightBox;
+                float zoomFactor = 0;
+                if (imageRatio >= containerRatio)
+                {
+                    //Image is wider than it is high
+                    zoomFactor = (float)widthImage / (float)widthBox;
+                }
+                else
+                {
+                    //Image is higher than it is wide
+                    zoomFactor = (float)heightImage / (float)heightBox;
+                }
+                markerRadius = (int)(10 * zoomFactor);
+                redrawAss.SetMarkerRadius(markerRadius);
+                deletionRadius = (int)(5 * zoomFactor);
             }
         }
 

+ 172 - 0
SketchAssistant/SketchAssistant/RedrawAssistant.cs

@@ -0,0 +1,172 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Drawing;
+
+namespace SketchAssistant
+{
+    class RedrawAssistant
+    {
+        /// <summary>
+        /// The lines of the left image, with a boolean indicating if they have been redrawn
+        /// and an integer that is the same as the line id of the respective line in the right image.
+        /// </summary>
+        List<Tuple<Line, bool, int>> linesToRedraw;
+        /// <summary>
+        /// The Start and End points of all lines in linesToRedraw in the same order.
+        /// </summary>
+        List<Tuple<HashSet<Point>, HashSet<Point>>> startAndEndPoints;
+        /// <summary>
+        /// The position of the line currently being redrawn in the startAndEndPoints 
+        /// & linesToRedraw lists. -1 if no line is being redrawn.
+        /// </summary>
+        int lineBeingRedrawn;
+        /// <summary>
+        /// Whether or not the user is currently redrawing a line.
+        /// </summary>
+        bool currentlyRedrawing;
+        /// <summary>
+        /// The id of the Line currently being redrawn
+        /// </summary>
+        int redrawingID;
+        /// <summary>
+        /// Whether or not the RedrawAssistant is active.
+        /// </summary>
+        bool isActive;
+        /// <summary>
+        /// The radius of the markers for redrawing.
+        /// </summary>
+        int markerRadius = 5;
+
+        /// <summary>
+        /// The Constructor for an inactive RedrawAssistant.
+        /// </summary>
+        public RedrawAssistant()
+        {
+            isActive = false;
+        }
+
+        /// <summary>
+        /// The constructor for an active RedrawAssistant
+        /// </summary>
+        /// <param name="redrawItem">The lines that shall be redrawn</param>
+        public RedrawAssistant(List<Line> redrawItem)
+        {
+            linesToRedraw = new List<Tuple<Line, bool, int>>();
+            startAndEndPoints = new List<Tuple<HashSet<Point>, HashSet<Point>>>();
+            isActive = true;
+            currentlyRedrawing = false;
+            lineBeingRedrawn = -1;
+            foreach (Line line in redrawItem)
+            {
+                linesToRedraw.Add(new Tuple<Line, bool, int>(line, false, -1));
+            }
+            SetMarkerRadius(5);
+        }
+        /// <summary>
+        /// The main functionality of the RedrawAssistant, which updates the Assistant according to the inputs given.
+        /// </summary>
+        /// <param name="currentPoint"></param>
+        /// <param name="rightLines"></param>
+        /// <param name="currLineID"></param>
+        /// <param name="markerRad"></param>
+        /// <returns></returns>
+        public List<HashSet<Point>> Tick(Point currentPoint, List<Tuple<bool, Line>> rightLines, int currLineID)
+        {
+            List<HashSet<Point>> returnList = new List<HashSet<Point>>();
+            if (!isActive) { return returnList; }
+            Tuple<Line, bool, int> newLineTuple = null;
+            var returnAllStartPoints = true;
+
+            // The current Endpoint has been intersected, and a line was finished here
+            if (currentlyRedrawing && startAndEndPoints[lineBeingRedrawn].Item2.Contains(currentPoint) && currLineID != -1)
+            {
+                newLineTuple = new Tuple<Line, bool, int>(linesToRedraw[lineBeingRedrawn].Item1, true, currLineID);
+                currentlyRedrawing = false;
+                lineBeingRedrawn = -1;
+            }
+            else if (currentlyRedrawing)
+            {
+                returnList.Add(startAndEndPoints[lineBeingRedrawn].Item1);
+                returnList.Add(startAndEndPoints[lineBeingRedrawn].Item2);
+                returnAllStartPoints = false;
+            }
+            else if (!currentlyRedrawing)
+            {
+                for (int i = 0; i < linesToRedraw.Count; i++)
+                {
+                    Tuple<Line, bool, int> tup = linesToRedraw[i];
+                    if (!tup.Item2)
+                    {
+                        // A Starpoint has been intersected
+                        if (!currentlyRedrawing && startAndEndPoints[i].Item1.Contains(currentPoint))
+                        {
+                            currentlyRedrawing = true;
+                            lineBeingRedrawn = i;
+                            returnList.Add(startAndEndPoints[i].Item1);
+                            returnList.Add(startAndEndPoints[i].Item2);
+                            returnAllStartPoints = false;
+                        }
+                    }
+                }
+            }
+
+            //Replace the changed line tuple in linesToRedraw
+            if(newLineTuple != null)
+            {
+                var newLine = newLineTuple.Item1;
+                for (int i = 0; i < linesToRedraw.Count; i++)
+                {
+                    var redrawLine = linesToRedraw[i].Item1;
+                    if (redrawLine.GetID() == newLine.GetID() 
+                        && redrawLine.GetStartPoint().Equals(newLine.GetStartPoint())
+                        && redrawLine.GetEndPoint().Equals(newLine.GetEndPoint()))
+                    {
+                        linesToRedraw[i] = newLineTuple;
+                    }
+                }
+            }
+
+            //Add all the startpoints to the list being returned
+            if (returnAllStartPoints)
+            {
+                for (int i = 0; i < linesToRedraw.Count; i++)
+                {
+                    if (!linesToRedraw[i].Item2)
+                    {
+                        returnList.Add(startAndEndPoints[i].Item1);
+                    }
+                }
+            }
+
+            return returnList;
+        }
+
+        public void SetMarkerRadius(int markerRad)
+        {
+            markerRadius = markerRad;
+            if (isActive)
+            {
+                startAndEndPoints = new List<Tuple<HashSet<Point>, HashSet<Point>>>();
+                foreach (Tuple<Line, bool, int> tup in linesToRedraw)
+                {
+                    startAndEndPoints.Add(CalculateStartAndEnd(tup.Item1));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Will calculate the start and endpoints of the given line.
+        /// </summary>
+        /// <param name="line">The line.</param>
+        private Tuple<HashSet<Point>, HashSet<Point>> CalculateStartAndEnd(Line line)
+        {
+            var circle0 = GeometryCalculator.FilledCircleAlgorithm(line.GetStartPoint(), markerRadius);
+            var circle1 = GeometryCalculator.FilledCircleAlgorithm(line.GetEndPoint(), markerRadius);
+            var currentLineEndings = new Tuple<HashSet<Point>, HashSet<Point>>(circle0, circle1);
+            return currentLineEndings;
+        }
+    }
+}

+ 1 - 0
SketchAssistant/SketchAssistant/SketchAssistant.csproj

@@ -69,6 +69,7 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="RedrawAssistant.cs" />
     <Compile Include="FileImporter.cs" />
     <Compile Include="FileImporterException.cs" />
     <Compile Include="GeometryCalculator.cs" />