From 4a01680bd22a0652dbdd0da5c3a7167ca8117440 Mon Sep 17 00:00:00 2001
From: eleanor-park <eleanor_park@brown.edu>
Date: Wed, 8 May 2024 22:22:29 -0400
Subject: close curve and bounding box fixes

---
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 347 ++++++++++++---------
 1 file changed, 207 insertions(+), 140 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 eedee0b18..2e174be30 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,5 +1,7 @@
+import { inside } from '@turf/turf';
 import { Bezier } from 'bezier-js';
 import { Colors } from 'browndash-components';
+import { validationResult } from 'express-validator';
 import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import { computedFn } from 'mobx-utils';
@@ -35,7 +37,7 @@ import { Timeline } from '../../animationtimeline/Timeline';
 import { ContextMenu } from '../../ContextMenu';
 import { GestureOverlay } from '../../GestureOverlay';
 import { CtrlKey } from '../../GlobalKeyHandler';
-import { ActiveInkWidth, InkingStroke, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke';
+import { ActiveEraserWidth, ActiveInkWidth, InkingStroke, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke';
 import { LightboxView } from '../../LightboxView';
 import { CollectionFreeFormDocumentView } from '../../nodes/CollectionFreeFormDocumentView';
 import { SchemaCSVPopUp } from '../../nodes/DataVizBox/SchemaCSVPopUp';
@@ -618,11 +620,15 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                         break; // the GestureOverlay handles ink stroke input -- either as gestures, or drying as ink strokes that are added to document views
                     case InkTool.StrokeEraser:
                     case InkTool.SegmentEraser:
-                    case InkTool.RadiusEraser:
                         this._batch = UndoManager.StartBatch('collectionErase');
                         this._eraserPts.length = 0;
                         setupMoveUpEvents(this, e, this.onEraserMove, this.onEraserUp, emptyFunction);
                         break;
+                    case InkTool.RadiusEraser:
+                        this._batch = UndoManager.StartBatch('collectionErase');
+                        this._eraserPts.length = 0;
+                        setupMoveUpEvents(this, e, this.onRadiusEraserMove, this.onEraserUp, emptyFunction);
+                        break;
                     case InkTool.None:
                         if (!(this._props.layoutEngine?.() || StrCast(this.layoutDoc._layoutEngine))) {
                             this._hitCluster = this.pickCluster(this.screenToFreeformContentsXf.transformPoint(e.clientX, e.clientY));
@@ -734,7 +740,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
      * Erases strokes by intersecting them with an invisible "eraser stroke".
      *  By default this iterates through all intersected ink strokes, determines their segmentation, draws back the non-intersected segments,
      * and deletes the original stroke.
-     *  However, if Shift is held, then no segmentation is done -- instead any intersected stroke is deleted in its entirety.
      */
     @action
     onEraserMove = (e: PointerEvent, down: number[], delta: number[]) => {
@@ -750,10 +755,7 @@ 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 (Doc.ActiveTool !== InkTool.StrokeEraser) {
                     this._eraserLock++;
-                    const segments =
-                        Doc.ActiveTool === InkTool.SegmentEraser
-                            ? this.segmentErase(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
-                            : this.radiusErase(intersect.inkView, { X: this._eraserPts[0][0], Y: this._eraserPts[0][1] }, currPoint);
+                    const segments = this.segmentErase(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
                     segments?.forEach(segment =>
                         this.forceStrokeGesture(
                             e,
@@ -764,12 +766,44 @@ 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.2;
+                intersect.inkView.layoutDoc.opacity = 0;
                 intersect.inkView.layoutDoc.dontIntersect = true;
             }
         });
         return false;
     };
+
+    @action
+    onRadiusEraserMove = (e: PointerEvent, down: number[], delta: number[]) => {
+        const currPoint = { X: e.clientX, Y: e.clientY };
+        this._eraserPts.push([currPoint.X, currPoint.Y]);
+        this._eraserPts = this._eraserPts.slice(Math.max(0, this._eraserPts.length - 5));
+        if (this._eraserLock) return false; // bcz: should be fixed by putting it on a queue to be processed after the last eraser movement is processed.
+        const strokeMap: Map<DocumentView, number[]> = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint);
+        strokeMap.forEach((intersects, stroke) => {
+            if (!this._deleteList.includes(stroke)) {
+                this._deleteList.push(stroke);
+                SetActiveInkWidth(StrCast(stroke.Document.stroke_width?.toString()) || '1');
+                SetActiveInkColor(StrCast(stroke.Document.color?.toString()) || 'black');
+                this._eraserLock++;
+                // create a new curve by appending all curves of the current segment together in order to render a single new stroke.
+                const segments = this.radiusErase(stroke, intersects.sort());
+                segments?.forEach(segment =>
+                    this.forceStrokeGesture(
+                        e,
+                        GestureUtils.Gestures.Stroke,
+                        segment.reduce((data, curve) => [...data, ...curve.points.map(p => stroke.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[])
+                    )
+                );
+                setTimeout(() => this._eraserLock--);
+            }
+            // Lower ink opacity to give the user a visual indicator of deletion.
+            stroke.layoutDoc.opacity = 0;
+            stroke.layoutDoc.dontIntersect = true;
+        });
+        return false;
+    };
+
     forceStrokeGesture = (e: PointerEvent, gesture: GestureUtils.Gestures, points: InkData, text?: any) => {
         this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, GestureOverlay.getBounds(points), text));
     };
@@ -788,7 +822,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     };
 
     createEraserOutline = (startInkCoordsIn: { X: number; Y: number }, endInkCoordsIn: { X: number; Y: number }) => {
-        const radius = ActiveEraserWidth() / 2 + 3; // reduce values to avoid extreme radii
+        const radius = ActiveEraserWidth() + 3; // add 3 to avoid eraser being too thin
         const c = 0.551915024494; // circle tangent length to side ratio
         const movement = { x: endInkCoordsIn.X - startInkCoordsIn.X, y: endInkCoordsIn.Y - startInkCoordsIn.Y };
         const moveLen = Math.sqrt(movement.x ** 2 + movement.y ** 2);
@@ -836,6 +870,39 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         ]);
     };
 
+    /**
+     * Ray-tracing algorithm to determine whether a point is inside the eraser outline
+     * @param eraserOutline 
+     * @param point 
+     * @returns 
+     */
+    insideEraserOutline = (eraserOutline: InkData, point: { X: number; Y: number }) => {
+        var isInside = false;
+        if (!isNaN(eraserOutline[0].X) && !isNaN(eraserOutline[0].Y)) {
+            var minX = eraserOutline[0].X, maxX = eraserOutline[0].X;
+            var minY = eraserOutline[0].Y, maxY = eraserOutline[0].Y;
+            for (var i = 1; i < eraserOutline.length; i++) {
+                const currPoint: {X: number, Y: number} = eraserOutline[i];
+                minX = Math.min(currPoint.X, minX);
+                maxX = Math.max(currPoint.X, maxX);
+                minY = Math.min(currPoint.Y, minY);
+                maxY = Math.max(currPoint.Y, maxY);
+            }
+
+            if (point.X < minX || point.X > maxX || point.Y < minY || point.Y > maxY) {
+                return false;
+            }
+
+            for (var i = 0, j = eraserOutline.length - 1; i < eraserOutline.length; j = i, i++) {
+                if ((eraserOutline[i].Y > point.Y) != (eraserOutline[j].Y > point.Y) &&
+                    point.X < (eraserOutline[j].X - eraserOutline[i].X) * (point.Y - eraserOutline[i].Y) / (eraserOutline[j].Y - eraserOutline[i].Y) + eraserOutline[i].X ) {
+                    isInside = !isInside;
+                }
+            }
+        }
+        return isInside;
+    };
+
     /**
      * Determines if the Eraser tool has intersected with an ink stroke in the current freeform collection.
      * @returns an array of tuples containing the intersected ink DocumentView and the t-value where it was intersected
@@ -880,94 +947,141 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             );
     };
 
+    getRadiusEraserIntersections = (lastPoint: { X: number; Y: number }, currPoint: { X: number; Y: number }) => {
+        const eraserRadius = ActiveEraserWidth() + 3;
+        const eraserMin = { X: Math.min(lastPoint.X, currPoint.X) - eraserRadius, Y: Math.min(lastPoint.Y, currPoint.Y) - eraserRadius };
+        const eraserMax = { X: Math.max(lastPoint.X, currPoint.X) + eraserRadius, Y: Math.max(lastPoint.Y, currPoint.Y) + eraserRadius};
+        const strokeToTVals = new Map<DocumentView, number[]>();
+        const intersectingStrokes = this.childDocs
+            .map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.()))
+            .filter(inkView => inkView?.ComponentView instanceof InkingStroke) // filter to all inking strokes
+            .map(inkView => ({ inkViewBounds: inkView!.getBounds, inkStroke: inkView!.ComponentView as InkingStroke, inkView: inkView! }))
+            .filter(
+                ({ inkViewBounds }) =>
+                    inkViewBounds && // bounding box of eraser segment and ink stroke overlap
+                    eraserMin.X <= inkViewBounds.right &&
+                    eraserMin.Y <= inkViewBounds.bottom &&
+                    eraserMax.X >= inkViewBounds.left &&
+                    eraserMax.Y >= inkViewBounds.top
+            );
+        console.log("itersectnig strokes", intersectingStrokes);
+        intersectingStrokes.forEach(({ inkStroke, inkView }) => {
+            const { inkData } = inkStroke.inkScaledData();
+            const prevPointInkSpace = inkStroke.ptFromScreen(lastPoint);
+            const currPointInkSpace = inkStroke.ptFromScreen(currPoint);
+            const eraserInkData = this.createEraserOutline(prevPointInkSpace, currPointInkSpace).inkData;
+            // add the ends of the stroke in as "intersections"
+            if (this.insideEraserOutline(eraserInkData, inkData[0])) {
+                strokeToTVals.set(inkView, [0]);
+            }
+            if (this.insideEraserOutline(eraserInkData, inkData[inkData.length - 1])) {
+                const inkList = strokeToTVals.get(inkView);
+                if (inkList !== undefined) {
+                    inkList.push(Math.floor(inkData.length / 4) + 1);
+                } else {
+                    strokeToTVals.set(inkView, [Math.floor(inkData.length / 4) + 1]);
+                }
+            }
+            for (var i = 0; i < inkData.length - 3; i += 4) {
+                // iterate over each segment of bezier curve
+                for (var j = 0; j < eraserInkData.length - 3; j += 4) {
+                    const intersectCurve: Bezier = InkField.Segment(inkData, i); // other curve
+                    const eraserCurve: Bezier = InkField.Segment(eraserInkData, j); // eraser curve
+                    this.bintersects(intersectCurve, eraserCurve).forEach((val: string | number, k: number) => {
+                        // Converting the Bezier.js Split type to a t-value number.
+                        const t = +val.toString().split('/')[0];
+                        if (k % 2 === 0) {
+                            // here, add to the map
+                            const inkList = strokeToTVals.get(inkView);
+                            if (inkList !== undefined) {
+                                const tValOffset = ActiveEraserWidth() / 1030; // to prevent tVals from being added when too close, but scaled by eraser width
+                                const inList = inkList.some(val => Math.abs(val - (t + Math.floor(i / 4))) <= tValOffset);
+                                if (!inList) {
+                                    inkList.push(t + Math.floor(i / 4));
+                                }
+                            } else {
+                                strokeToTVals.set(inkView, [t + Math.floor(i / 4)]);
+                            }
+                        }
+                    });
+                }
+            }
+        });
+        console.log("strokeToTVals", strokeToTVals);
+        return strokeToTVals;
+    };
+
+    /**
+     * Splits the passed in ink stroke at the intersection t values. Generally operates in pairs of t values, where
+     * the first t value is the start of the erased portion and the following t value is the end.
+     * @param ink the ink stroke DocumentView to split
+     * @param tVals all the t values to split the ink stroke at
+     * @returns a list of the new segments with the erased part removed
+     */
     @action
-    radiusErase = (ink: DocumentView, startPt: { X: number; Y: number }, screenEraserPt: { X: number; Y: number }): Segment[] => {
+    radiusErase = (ink: DocumentView, tVals: number[]): Segment[] => {
         const segments: Segment[] = [];
-        const startInkCoords = ink.ComponentView?.ptFromScreen?.(startPt);
-        const inkCoords = ink.ComponentView?.ptFromScreen?.(screenEraserPt); // coordinates in ink space
-        if (!inkCoords || !startInkCoords) return [];
-
-        var eraseSegment: Segment = []; // for eraser visualization
         const inkStroke = ink?.ComponentView as InkingStroke;
-
-        const eraserStroke: InkData = inkStroke.splitByEraser(startInkCoords, inkCoords).inkData;
-        const strokeToTVals: Map<InkingStroke, number[]> = new Map<InkingStroke, number[]>();
-        for (var i = 0; i < eraserStroke.length - 3; i += 4) {
-            eraseSegment.push(InkField.Segment(eraserStroke, i)); // for eraser visualization
-            this.getOtherInkIntersections(ink, i, eraserStroke, strokeToTVals);
+        const { inkData } = inkStroke.inkScaledData();
+        var currSegment: Segment = [];
+        if (tVals.length % 2 !== 0) { // should always have even tVals
+            for (var i = 0; i < inkData.length - 3; i +=4) {
+                currSegment.push(InkField.Segment(inkData, i));
+            }
+            if (currSegment.length > 0) {
+                segments.push(currSegment);
+                return segments;
+            }
         }
-        strokeToTVals.forEach((tVals, inkStroke) => {
-            var segment1: Segment = [];
-            var segment2: Segment = [];
-            const { inkData } = inkStroke.inkScaledData();
-            tVals.sort();
-            console.log('TVALS', inkStroke, tVals);
 
-            var hasSplit = false;
-            var continueErasing = false;
-
-            // below is curve splitting logic
-            if (tVals.length) {
-                for (var i = 0; i < inkData.length - 3; i += 4) {
-                    const inkSegment: Bezier = InkField.Segment(inkData, i);
-                    const currCurveT = Math.floor(i / 4);
+        var continueErasing = false;
+        var firstSegment: Segment = [];
+        // early return if nothing to split on
+        if (tVals.length === 0 || (tVals.length === 1 && tVals[0] === 0)) {
+            return segments;
+        }
 
-                    if (tVals.length === 2) {
-                        if (tVals[0] > currCurveT && tVals[0] < currCurveT + 1) {
-                            segment1.push(inkSegment.split(0, tVals[0] - currCurveT));
+        for (var i = 0; i < inkData.length - 3; i += 4) {
+            const currCurveT = Math.floor(i/4);
+            const inkBezier: Bezier = InkField.Segment(inkData, i);
+            const segmentTs = tVals.filter(t => t >= currCurveT && t < currCurveT + 1);
+
+            if (segmentTs.length > 0) {
+                for (var j = 0; j < segmentTs.length; j++) {
+                    // if the first end of the segment is within the eraser
+                    if (segmentTs[j] === 0 ) {
+                        continueErasing = true;
+                    } else if (segmentTs[j] === Math.floor(inkData.length / 4) + 1) {
+                        break;
+                    }else {
+                        if (!continueErasing) {
+                            currSegment.push(inkBezier.split(0, segmentTs[j] - currCurveT));
                             continueErasing = true;
-                            if (tVals[1] > currCurveT && tVals[1] < currCurveT + 1) {
-                                segment2.push(inkSegment.split(tVals[1] - currCurveT, 1));
-                                continueErasing = false;
-                                hasSplit = true;
-                            }
-                        } else if (tVals[1] > currCurveT && tVals[1] < currCurveT + 1) {
-                            segment2.push(inkSegment.split(tVals[1] - currCurveT, 1));
-                            continueErasing = false;
-                            hasSplit = true;
-                        } else if (!continueErasing) {
-                            if (hasSplit) {
-                                segment2.push(inkSegment);
-                            } else {
-                                segment1.push(inkSegment);
-                            }
-                        }
-                    } else if (tVals.length === 1) {
-                        if (tVals[0] > currCurveT && tVals[0] < currCurveT + 1) {
-                            // this heuristic for determine which segment to keep is not quite right even though it will work most of the time.
-                            // We should really store the eraser intersection normal in getOtherInkIntersections,
-                            // and then test its dot product with the tangent of the stroke at the intersection point.
-                            // if the dot product is positive, then erase the first part of the stroke, otherwise the second.
-                            const leftDist = Utils.ptDistance({ x: inkCoords.X, y: inkCoords.Y }, inkSegment.points.lastElement());
-                            const rightDist = Utils.ptDistance({ x: inkCoords.X, y: inkCoords.Y }, inkSegment.points[0]);
-                            const splits = inkSegment.split(tVals[0] - currCurveT);
-                            if (leftDist < rightDist) {
-                                // if it's on the first end
-                                segment1.push(splits.left);
-                                hasSplit = true;
-                            } else {
-                                segment1.push(splits.right);
-                                hasSplit = true;
-                            }
                         } else {
-                            if (tVals[0] < Math.floor(inkData.length / 4) - tVals[0] && hasSplit) {
-                                segment1.push(inkSegment);
-                            } else if (tVals[0] >= Math.floor(inkData.length / 4) - tVals[0] && !hasSplit) {
-                                segment1.push(inkSegment);
+                            continueErasing = false;
+                            if (currSegment.length > 0) {
+                                segments.push(currSegment);
+                                if (firstSegment.length === 0) {
+                                    firstSegment = currSegment;
+                                }
+                                currSegment = [];
                             }
+                            currSegment.push(inkBezier.split(segmentTs[j] - currCurveT, 1));
                         }
                     }
                 }
+            } else {
+                if (!continueErasing) { // push the bezier piece if not in the eraser circle
+                    currSegment.push(inkBezier);
+                }
             }
-            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 (currSegment.length > 0) {
+            if (InkingStroke.IsClosed(inkData)) {
+                currSegment = currSegment.concat(firstSegment);
             }
-        });
-
-        segments.push(eraseSegment); // for eraser visualization
+            segments.push(currSegment);
+        }
         return segments;
     };
 
@@ -993,7 +1107,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             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));
+            currIntersects = currIntersects.filter(tVal => tVal > 0 && tVal < 1).map(tVal => tVal + Math.floor(i / 4));
             if (currIntersects.length) {
                 intersections = [...intersections, ...currIntersects];
                 for (var j = 0; j < currIntersects.length; j++) {
@@ -1002,19 +1116,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             }
         }
 
-        // for closed curve bookkeeping
         var isClosedCurve = false;
-        if (intersections[0] === 0) {
+        if (InkingStroke.IsClosed(inkData)) {
             isClosedCurve = true;
-
-            // now reduce intersections list to the actual intersections because closed curves have additional ones with itself
-            const indices = intersections.map((value, index) => (value > 0.0001 && value < Math.floor(inkData.length / 4) ? index : -1)).filter(index => index !== -1);
-
-            // Filter intersections and segmentIndexes based on validIndices
-            intersections = indices.map(index => intersections[index]);
-            segmentIndexes = indices.map(index => segmentIndexes[index]);
-            // intersections = intersections.slice(1, intersections.length ); // take the 0 intersection out
-            // segmentIndexes = segmentIndexes.slice(1, segmentIndexes.length); // same for indexes
         }
 
         if (intersections.length) {
@@ -1068,7 +1172,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                         }
                     }
                 } else if (splitSegment1 === -1) {
-                    // case where left end is erased
+                    // case where first end is erased
                     if (currCurveT === splitSegment2) {
                         segment2.push(inkSegment.split(intersections[closestTs[1]] - currCurveT, 1));
                         hasSplit = true;
@@ -1081,15 +1185,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                         }
                     }
                 } else {
-                    // case where right end is erased
+                    // case where last end is erased
                     if (currCurveT === segmentIndexes[0] && isClosedCurve) {
                         segment1.push(inkSegment.split(intersections[0] - currCurveT, 1));
                         hasSplit = true;
                     } else if (currCurveT === splitSegment1) {
                         segment1.push(inkSegment.split(0, intersections[closestTs[0]] - currCurveT));
-                        hasSplit = false; // although this is not technically true, we set to false so the segments after don't get added
-                        // } else if (isClosedCurve && currCurveT === segmentIndexes[1]) {
-                        //     segment1.push(inkSegment.split(intersections[0] - currCurveT, 1));
+                        hasSplit = true; 
                     } else {
                         if ((isClosedCurve && hasSplit) || (!isClosedCurve && !hasSplit)) {
                             segment1.push(inkSegment);
@@ -1099,6 +1201,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             }
         }
 
+        if (isClosedCurve && segment1.length > 0 && segment2.length > 0) {
+            segment2 = segment2.concat(segment1);
+            segment1 = [];
+        }
+
         // push 1 or both segments if they are not empty
         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);
@@ -1203,46 +1310,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         return tVals;
     };
 
-    /**
-     * For radius erase, a function to find an eraser's intersections with a single ink stroke
-     * @param otherInkDocVIew the ink document that is being erased
-     * @param i the index of the eraser's segment
-     * @param points the eraser's ink data points
-     * @param strokeToTVals Map of InkingStroke to the tVals of its intersections with the eraser
-     * @returns
-     */
-    getOtherInkIntersections = (otherInkDocView: DocumentView, i: number, points: InkData, strokeToTVals: Map<InkingStroke, number[]>): Map<InkingStroke, number[]> => {
-        this.childDocs
-            .filter(doc => doc.type === DocumentType.INK && !doc.dontIntersect)
-            .forEach(doc => {
-                // InkingStroke of other ink strokes
-                const otherInk = otherInkDocView.ComponentView as InkingStroke;
-                // ink Data of other ink strokes
-                const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] };
-                for (var j = 0; j < otherInkData.length - 3; j += 4) {
-                    const curve: Bezier = InkField.Segment(points, i); // eraser curve
-                    const otherCurve: Bezier = InkField.Segment(otherInkData, j); // other curve
-                    this.bintersects(otherCurve, curve).forEach((val: string | number, k: number) => {
-                        // Converting the Bezier.js Split type to a t-value number.
-                        const t = +val.toString().split('/')[0];
-                        if (k % 2 === 0) {
-                            // here, add to the map
-                            const inkList = strokeToTVals.get(otherInk);
-                            if (inkList !== undefined) {
-                                const inList = inkList.some(val => Math.abs(val - (t + Math.floor(j / 4))) <= 0.01);
-                                if (!inList) {
-                                    inkList.push(t + Math.floor(j / 4));
-                                }
-                            } else {
-                                strokeToTVals.set(otherInk, [t + Math.floor(j / 4)]);
-                            }
-                        }
-                    });
-                }
-            });
-        return strokeToTVals;
-    };
-
     @action
     zoom = (pointX: number, pointY: number, deltaY: number): void => {
         if (this.Document.isGroup || this.Document[(this._props.viewField ?? '_') + 'freeform_noZoom']) return;
-- 
cgit v1.2.3-70-g09d2

