From 627e436b16745df6982dec3954f2b385f180bad8 Mon Sep 17 00:00:00 2001
From: eleanor-park <eleanor_park@brown.edu>
Date: Wed, 20 Mar 2024 23:27:21 -0400
Subject: tried to start closed curve management

---
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 53 +++++++++++++++-------
 1 file changed, 36 insertions(+), 17 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

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];
-- 
cgit v1.2.3-70-g09d2

