From 33cb02498a330ede6a90e67bdaf0ff56aed21819 Mon Sep 17 00:00:00 2001
From: eleanor-park <eleanor_park@brown.edu>
Date: Tue, 12 Mar 2024 16:26:00 -0400
Subject: i have an error

---
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 181 +++++++++++++++++++--
 1 file changed, 171 insertions(+), 10 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 e4c71a086..70b21309e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,3 +1,4 @@
+import { findSegment } from '@turf/turf';
 import { Bezier } from 'bezier-js';
 import { Colors } from 'browndash-components';
 import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
@@ -739,7 +740,25 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 // create a new curve by appending all curves of the current segment together in order to render a single new stroke.
                 if (!e.shiftKey) {
                     this._eraserLock++;
-                    const segments = this.segmentInkStroke(intersect.inkView, intersect.t);
+                    const segments = this.segmentInkStroke(intersect.inkView, intersect.t); // intersect.t is where the eraser intersected the ink stroke - want to remove the segment that starts at the intersection just before this t value and goes to the one just after it
+                    // we delete the original ink stroke, then create new strokes for each of the remaining segments
+                    // we do this through the hack of calling the stroke Gesture code as if the strokes had just be drawn by hand
+                    // [[(0,0), (3,7), (9,4), (4,5)],[(4,5), (13,17), (19,14), (14,15)],       [(23,19),(...}]]
+                    // [[(0,0), (3,7), (9,4), (4,5), (13,17), (19,14), (14,15)],       [(23,19),(...}]]
+                    // segments.map(segment => segment.map(pt => pt))
+                    // segments[0][3].x === segments[1][0].x
+
+                    //   3 == "3"   true
+                    //   3 === "3" falsen   !==
+
+                    // for (var i = 0; i < segments.length; i ++) {
+                    //     if (segments[i][0].points.lastElement().x === segments[i+1][0].points.lastElement().x && segments[i][0].points.lastElement().y === segments[i+1][0].points.lastElement().y) {
+                    //         segments[i][0].points.pop();
+                    //         segments[i][0].points = segments[i][0].points.concat(segments[i+1][0].points);
+                    //         segments.splice(i+1, 1);
+                    //     }
+                    //     i++;
+                    // }
                     segments.forEach(segment =>
                         this.forceStrokeGesture(
                             e,
@@ -750,7 +769,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     setTimeout(() => this._eraserLock--);
                 }
                 // Lower ink opacity to give the user a visual indicator of deletion.
-                intersect.inkView.layoutDoc.opacity = 0.5;
+                intersect.inkView.layoutDoc.opacity = 0.0;
                 intersect.inkView.layoutDoc.dontIntersect = true;
             }
         });
@@ -796,12 +815,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             )
             .reduce(
                 (intersections, { inkStroke, inkView }) => {
-                    const { inkData } = inkStroke.inkScaledData();
+                    const { inkData } = inkStroke.inkScaledData(); // get bezier curve as set of control points
                     // Convert from screen space to ink space for the intersection.
                     const prevPointInkSpace = inkStroke.ptFromScreen(lastPoint);
                     const currPointInkSpace = inkStroke.ptFromScreen(currPoint);
                     for (var i = 0; i < inkData.length - 3; i += 4) {
+                        // iterate over each segment of bezier curve
                         const rawIntersects = InkField.Segment(inkData, i).intersects({
+                            // segment's are indexed by 0, 4, 8,
                             // compute all unique intersections
                             p1: { x: prevPointInkSpace.X, y: prevPointInkSpace.Y },
                             p2: { x: currPointInkSpace.X, y: currPointInkSpace.Y },
@@ -825,9 +846,106 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
      */
     @action
     segmentInkStroke = (ink: DocumentView, excludeT: number): Segment[] => {
+        // const segments: Segment[] = [];
+        // var segment: Segment = [];
+        // var segment2: Segment = [];
+        // var startSegmentT = 0;
+        // 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)
+
+        // var hasSplit = false;
+        // var continueErasing = false;
+        // for (var i = 0; i < inkData.length - 3; i += 4) {
+        //     const inkSegment: Bezier = InkField.Segment(inkData, i);
+        //     const tVals: number[] = this.getInkIntersections(i, ink, inkSegment).sort();
+        //     console.log("TVALS", tVals);
+        //     if (tVals.length) {
+        //         if ((!hasSplit) && ((excludeT <= tVals[0]) ||
+        //             (excludeT > tVals[0] && excludeT < tVals.lastElement()) || continueErasing)) {
+
+        //             const closestTs = this.getClosestTs(tVals, excludeT, 0, tVals.length - 1);
+        //             if (closestTs[0] != -1 && closestTs[1] != -1) {
+        //                 segment1.push(inkSegment.split(0, closestTs[0]));
+        //                 segment2.push(inkSegment.split(closestTs[1]).right);
+        //             } else if (closestTs[0] == -1) {
+        //                 segment2.push(inkSegment.split(closestTs[1]).right);
+        //                 continueErasing = !continueErasing;
+        //             } else {
+        //                 segment1.push(inkSegment.split(0, closestTs[0]));
+        //                 continueErasing = !continueErasing;
+        //             }
+        //             if (!continueErasing) {
+        //                 hasSplit = true;
+        //             }
+        //             // segment1 = [];
+        //             // segment2 = [];
+        //         }
+        //         else {
+        //             if (hasSplit) {
+        //                 segment2.push(inkSegment);
+        //             } else {
+        //                 segment1.push(inkSegment);
+        //             }
+        //         }
+        //     } else if (hasSplit) {
+        //         segment2.push(inkSegment);
+        //     } else {
+        //         continueErasing = true;
+        //     }
+        // }
+
+        // if (segment1.length && (Math.abs(segment1[0].points[0].x - segment1[0].points.lastElement().x) > 0.5 || Math.abs(segment1[0].points[0].y - segment1[0].points.lastElement().y) > 0.5)) {
+        //     segments.push(segment1);
+        // }
+        // if (segment2.length && (Math.abs(segment2[0].points[0].x - segment2[0].points.lastElement().x) > 0.5 || Math.abs(segment2[0].points[0].y - segment2[0].points.lastElement().y) > 0.5)) {
+        //     segments.push(segment2);
+        // }
+        // if (excludeT < startSegmentT || excludeT > inkData.length / 4) {
+        //     segment1.length && segments.push(segment1);
+        // }
+        //     const tVals  = []
+        // for (var i = 0; i < inkData.length - 3; i += 4) {
+        //     const inkSegment = InkField.Segment(inkData, i);
+        //     // Getting all t-value intersections of the current curve with all other curves.
+        //     tVals.push(this.getInkIntersections(i, ink, inkSegment));
+        //     tVals.sort();
+
+        // if (tVals.length) {
+        //     const docCurveTVal = tVals.lastElement() + Math.floor(i / 4);
+        //     if (excludeT > docCurveTVal) {
+        //         continue;
+        //     } else {
+        //         const closestTs = this.getClosestTs(tVals, excludeT, 0, tVals.length - 1);
+        //         segment.push(inkSegment.split(0, closestTs[0]));
+        //         if (segment.length && (Math.abs(segment[0].points[0].x - segment[0].points.lastElement().x) > 0.5 || Math.abs(segment[0].points[0].y - segment[0].points.lastElement().y) > 0.5)) {
+        //             segments.push(segment);
+        //         }
+        //     }
+
+        //         const closestT = this.getClosestT(tVals, excludeT, 0, tVals.length - 1);
+        //         if (closestT != undefined) {
+        //             var startSegmentT = closestT[0]
+        //             const localStartTVal = startSegmentT - Math.floor(i / 4);
+        //             segment.push(inkSegment.split(localStartTVal < 0 ? 0 : localStartTVal, startSegmentT))
+        //             if (segment.length && (Math.abs(segment[0].points[0].x - segment[0].points.lastElement().x) > 0.5 || Math.abs(segment[0].points[0].y - segment[0].points.lastElement().y) > 0.5)) {
+        //                 segments.push(segment);
+        //             }
+        //             const split = inkSegment.split(closestT[1]).right;
+        //             if (split && (Math.abs(split.points[0].x - split.points.lastElement().x) > 0.5 || Math.abs(split.points[0].y - split.points.lastElement().y) > 0.5)) {
+        //                 segments.push([split]);
+        //             }
+        //         }
+        //     } else {
+        //         segment.push(inkSegment);
+        //         segments.push(segment);
+        //     }
+        // }
         const segments: Segment[] = [];
-        var segment: Segment = [];
+        var segment1: Segment = [];
+        var segment2: Segment = [];
         var startSegmentT = 0;
+        var hasSplit = false;
         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)
@@ -840,23 +958,66 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     const docCurveTVal = t + Math.floor(i / 4);
                     if (excludeT < startSegmentT || excludeT > docCurveTVal) {
                         const localStartTVal = startSegmentT - Math.floor(i / 4);
-                        t !== (localStartTVal < 0 ? 0 : localStartTVal) && segment.push(inkSegment.split(localStartTVal < 0 ? 0 : localStartTVal, t));
-                        segment.length && segments.push(segment);
+                        if (!hasSplit) {
+                            t !== (localStartTVal < 0 ? 0 : localStartTVal) && segment1.push(inkSegment.split(localStartTVal < 0 ? 0 : localStartTVal, t));
+                        } else {
+                            t !== (localStartTVal < 0 ? 0 : localStartTVal) && segment2.push(inkSegment.split(localStartTVal < 0 ? 0 : localStartTVal, t));
+                        }
+                        // if (segment.length && (Math.abs(segment[0].points[0].x - segment[0].points.lastElement().x) > 0.5 || Math.abs(segment[0].points[0].y - segment[0].points.lastElement().y) > 0.5)) segments.push(segment);
                     }
                     // start a new segment from the intersection t value
-                    segment = tVals.length - 1 === index ? [inkSegment.split(t).right] : [];
+                    if (tVals.length - 1 === index) {
+                        const split = inkSegment.split(t).right;
+                        if (!hasSplit) {
+                            if (split && (Math.abs(split.points[0].x - split.points.lastElement().x) > 0.5 || Math.abs(split.points[0].y - split.points.lastElement().y) > 0.5)) segment1.push(split);
+                        } else {
+                            if (split && (Math.abs(split.points[0].x - split.points.lastElement().x) > 0.5 || Math.abs(split.points[0].y - split.points.lastElement().y) > 0.5)) segment2.push(split);
+                        }
+                    }
                     startSegmentT = docCurveTVal;
                 });
             } else {
-                segment.push(inkSegment);
+                if (!hasSplit) {
+                    segment1.push(inkSegment);
+                } else {
+                    segment2.push(inkSegment);
+                }
             }
         }
-        if (excludeT < startSegmentT || excludeT > inkData.length / 4) {
-            segment.length && segments.push(segment);
+        if (segment1.length && (Math.abs(segment1[0].points[0].x - segment1[0].points.lastElement().x) > 0.5 || Math.abs(segment1[0].points[0].y - segment1[0].points.lastElement().y) > 0.5)) {
+            segments.push(segment1);
+        }
+        if (segment2.length && (Math.abs(segment2[0].points[0].x - segment2[0].points.lastElement().x) > 0.5 || Math.abs(segment2[0].points[0].y - segment2[0].points.lastElement().y) > 0.5)) {
+            segments.push(segment2);
         }
         return segments;
     };
 
+    getClosestTs = (tVals: number[], excludeT: number, startIndex: number, endIndex: number): number[] => {
+        if (tVals[startIndex] >= excludeT) {
+            return [-1, tVals[startIndex]];
+        }
+        else if (tVals[endIndex] < excludeT) {
+            return [tVals[endIndex], -1];
+        }
+        else {
+            const mid = Math.floor(startIndex + endIndex / 2);
+            if (excludeT >= tVals[mid]) {
+                if (mid + 1 <= endIndex && tVals[mid + 1] > excludeT) {
+                    return [tVals[mid], tVals[mid + 1]];
+                } else {
+                    return this.getClosestTs(tVals, excludeT, mid + 1, endIndex);
+                }
+            } else {
+                if (mid - 1 <= startIndex && tVals[mid - 1] < excludeT) {
+                    return [tVals[mid - 1], tVals[mid]];
+                } else {
+                    return this.getClosestTs(tVals, excludeT, startIndex, mid - 1);
+                }
+            }
+        }
+    };
+
     // for some reason bezier.js doesn't handle the case of intersecting a linear curve, so we wrap the intersection
     // call in a test for linearity
     bintersects = (curve: Bezier, otherCurve: Bezier) => {
-- 
cgit v1.2.3-70-g09d2

