using System; using System.Collections.Generic; using System.Collections; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; namespace SketchAssistant { public class RedrawAssistant { /// /// 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. /// List> linesToRedraw; /// /// The Start and End points of all lines in linesToRedraw in the same order. /// List, HashSet>> startAndEndPoints; /// /// A Hashtable for quick lookup for a line id and its respective tuple in linesToRedraw /// Hashtable redrawnLineLookupTable; /// /// The position of the line currently being redrawn in the startAndEndPoints /// & linesToRedraw lists. -1 if no line is being redrawn. /// int lineBeingRedrawn; /// /// The id of the line being drawn on the right side. -1 if no line is being drawn. /// int currentLineID; /// /// Whether or not the user is currently redrawing a line. /// bool currentlyRedrawing; /// /// Whether or not the RedrawAssistant is active. /// bool isActive; /// /// The radius of the markers for redrawing. /// int markerRadius = 5; /// /// The Constructor for an inactive RedrawAssistant. /// public RedrawAssistant() { isActive = false; } /// /// The constructor for an active RedrawAssistant /// /// The lines that shall be redrawn public RedrawAssistant(List redrawItem) { linesToRedraw = new List>(); startAndEndPoints = new List, HashSet>>(); isActive = true; currentlyRedrawing = false; lineBeingRedrawn = -1; redrawnLineLookupTable = new Hashtable(); foreach (Line line in redrawItem) { linesToRedraw.Add(new Tuple(line, false, -1)); } SetMarkerRadius(5); } /// /// Initialization function that returns the initial list of overlay points. /// /// The radius of the points. /// The list of overlay points. public List>> Initialize(int mRad) { if (isActive) { List>> retList = new List>>(); SetMarkerRadius(mRad); foreach(Tuple, HashSet> tup in startAndEndPoints) { retList.Add(new Tuple>(false, tup.Item1)); retList.Add(new Tuple>(false, tup.Item2)); } return retList; } return null; } /// /// The main functionality of the RedrawAssistant, which updates the Assistant according to the inputs given. /// /// The current position of the cursor, as a point /// The lines on the right canvas /// The id of the line currently being drawn. /// A boolean to indicate that the line is finished /// A list containing the overlay items and if they should be drawn. /// The updated List of overlay items, or the same list if no changes need to be done, /// along with a boolean indicating if something was changed public Tuple>>> Tick(Point currentPoint, List> rightLines, int currLineID, bool lineFinished, List>> overlayItems) { if (!isActive) { return new Tuple>>>(false, overlayItems); } if (!currentlyRedrawing) { } /* Tuple newLineTuple = null; var returnAllStartPoints = true; CheckForUndrawnLines(rightLines); // Checking if a startpoint is intersected if (!currentlyRedrawing) { for (int i = 0; i < linesToRedraw.Count; i++) { Tuple tup = linesToRedraw[i]; if (!tup.Item2) { if (startAndEndPoints[i].Item1.Contains(currentPoint)) { currentlyRedrawing = true; lineBeingRedrawn = i; currentLineID = currLineID; returnList.Add(startAndEndPoints[i].Item1); returnList.Add(startAndEndPoints[i].Item2); returnAllStartPoints = false; } } } } //Currently redrawing a line, but a line hasn't been finished drawing. else if (!lineFinished) { returnList.Add(startAndEndPoints[lineBeingRedrawn].Item1); returnList.Add(startAndEndPoints[lineBeingRedrawn].Item2); returnAllStartPoints = false; } //Line is finished, check if it is in the correct endpoint else if (currLineID == currentLineID && startAndEndPoints[lineBeingRedrawn].Item2.Contains(currentPoint)) { newLineTuple = new Tuple(linesToRedraw[lineBeingRedrawn].Item1, true, currLineID); currentlyRedrawing = false; lineBeingRedrawn = -1; currentLineID = -1; } //Line is finished, but not in the correct endpoint else { currentlyRedrawing = false; lineBeingRedrawn = -1; currentLineID = -1; } //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())) { redrawnLineLookupTable.Add(currLineID, i); 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; */ return new Tuple>>>(false, overlayItems); } /// /// A helping function which checks for lines where previously redrawn, but were removed from the image again. /// /// The lines in the right image. private void CheckForUndrawnLines(List> rightLines) { for (int i = 0; i < rightLines.Count; i++) { if (redrawnLineLookupTable.ContainsKey(rightLines[i].Item2.GetID())) { if (!rightLines[i].Item1) { int listPos = (int)redrawnLineLookupTable[rightLines[i].Item2.GetID()]; var oldTup = linesToRedraw[listPos]; linesToRedraw[listPos] = new Tuple(oldTup.Item1, false, -1); } else { int listPos = (int)redrawnLineLookupTable[rightLines[i].Item2.GetID()]; var oldTup = linesToRedraw[listPos]; linesToRedraw[listPos] = new Tuple(oldTup.Item1, true, rightLines[i].Item2.GetID()); } } } } /// /// A function to set the marker radius for the markers returned by the RedrawAssistant /// /// The Radius of the markers. public void SetMarkerRadius(int markerRad) { markerRadius = markerRad; if (isActive) { startAndEndPoints = new List, HashSet>>(); foreach (Tuple tup in linesToRedraw) { startAndEndPoints.Add(CalculateStartAndEnd(tup.Item1)); } } } /// /// Will calculate the start and endpoints of the given line. /// /// The given line. private Tuple, HashSet> CalculateStartAndEnd(Line line) { var circle0 = GeometryCalculator.FilledCircleAlgorithm(line.GetStartPoint(), markerRadius); var circle1 = GeometryCalculator.FilledCircleAlgorithm(line.GetEndPoint(), markerRadius); var currentLineEndings = new Tuple, HashSet>(circle0, circle1); return currentLineEndings; } } }