diff options
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 76e1646e2..b8d74dff2 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -838,8 +838,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection }; /** - * Performs segmentation of the ink stroke - creates "segments" or subsections of the current ink stroke at points in which the - * ink stroke intersects any other ink stroke (including itself). + * Erases ink strokes by segments. Locates intersections of the current ink stroke with all other ink strokes (including itself), + * then erases the segment that was intersected by the eraser. This is done by creating either 1 or two resulting segments + * (this depends on whether the eraser his the middle or end of a stroke), and returning the segments to "redraw." * @param ink The ink DocumentView intersected by the eraser. * @param excludeT The index of the curve in the ink document that the eraser intersection occurred. * @returns The ink stroke represented as a list of segments, excluding the segment in which the eraser intersection occurred. @@ -851,29 +852,34 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection var segment1: Segment = []; var segment2: Segment = []; const { inkData } = (ink?.ComponentView as InkingStroke).inkScaledData(); - // This iterates through all segments of the curve and splits them where they intersect another curve. - // if 'excludeT' is specified, then any segment containing excludeT will be skipped (ie, deleted) - - // find all t values of the curve's intersections - var intersections: number[] = []; - var segmentIndexes: number[] = []; + var intersections: number[] = []; // list of the ink stroke's intersections + var segmentIndexes: number[] = []; // list of indexes of the curve's segment where each intersection occured + + // loops through each segment and adds intersections to the list for (var i = 0; i < inkData.length - 3; i += 4) { const inkSegment: Bezier = InkField.Segment(inkData, i); var currIntersects = this.getInkIntersections(i, ink, inkSegment).sort(); // get current segments intersections (if any) and add the curve index currIntersects = currIntersects.map(tVal => tVal + Math.floor(i/4)); if (currIntersects.length) { - intersections = [...intersections, ...currIntersects]; - // segmentIndexes is to keep track of the segment index that corresponds to an intersection + intersections = [...intersections, ...currIntersects] for (var j = 0; j < currIntersects.length; j++) { segmentIndexes.push(Math.floor(i / 4)); } } } + // for closed curve bookkeeping + var isClosedCurve = false; + if (intersections[0] === 0) { + isClosedCurve = true; + intersections = intersections.slice(1, intersections.length ); // take the 0 intersection out + segmentIndexes = segmentIndexes.slice(1, segmentIndexes.length); // same for indexes + } + if (intersections.length) { - // this is the indexes of the closest Ts - const closestTs = this.getClosestTs(intersections, excludeT, 0, intersections.length - 1); + // this is the indexes of the closest intersection(s) + var closestTs = this.getClosestTs(intersections, excludeT, 0, intersections.length - 1); // find the segments that need to be split var splitSegment1 = -1; // stays -1 if left end is deleted @@ -882,9 +888,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection // if not on the ends splitSegment1 = segmentIndexes[closestTs[0]]; splitSegment2 = segmentIndexes[closestTs[1]]; - } else if (closestTs[0] === -1) { // for a curve left of intersection + } else if (closestTs[0] === -1) { // for a curve before an intersection splitSegment2 = segmentIndexes[closestTs[1]]; - } else { // for a curve right of intersection + } else { // for a curve after an intersection splitSegment1 = segmentIndexes[closestTs[0]]; } @@ -892,7 +898,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection var hasSplit = false; var continueErasing = false; - // loop through segments again and split if they match the split segments + // loop through segments again and split them if they match the split segments for (var i = 0; i < inkData.length - 3; i += 4) { const currCurveT = Math.floor(i / 4); const inkSegment: Bezier = InkField.Segment(inkData, i); @@ -924,7 +930,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection segment2.push(inkSegment.split(intersections[closestTs[1]] - currCurveT, 1)); hasSplit = true; } else { - if (hasSplit) { + if (isClosedCurve && currCurveT === segmentIndexes.lastElement()) { + segment2.push(inkSegment.split(0, intersections.lastElement() - currCurveT)); + continueErasing = true; + } else if (hasSplit && !continueErasing) { segment2.push(inkSegment); } } @@ -932,8 +941,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection if (currCurveT === splitSegment1) { segment1.push(inkSegment.split(0, intersections[closestTs[0]] - currCurveT)); hasSplit = true; + } else if (isClosedCurve && currCurveT === segmentIndexes[1]) { + segment1.push(inkSegment.split(intersections[0] - currCurveT, 1)); } else { - if (!hasSplit) { + if (!hasSplit && !isClosedCurve) { segment1.push(inkSegment); } } @@ -1114,6 +1125,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection return segments; }; + /** + * Standard logarithmic search function to search a sorted list of tVals for the ones closest to excludeT. + * @param tVals list of tvalues (usage is for intersection t values) to search within + * @param excludeT the t value of where the eraser intersected the curve + * @param startIndex the start index to search from + * @param endIndex the end index to search to + * @returns 2-item array of the closest tVals indexes + */ getClosestTs = (tVals: number[], excludeT: number, startIndex: number, endIndex: number): number[] => { if (tVals[startIndex] >= excludeT) { return [-1, startIndex]; |