From 0c33bc8033c9877abbe6e4074a687559bc4948d0 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Tue, 23 Apr 2024 15:16:06 -0400 Subject: erase multiple segments bug --- .../collectionFreeForm/CollectionFreeFormView.tsx | 167 ++++++++++++++------- 1 file changed, 114 insertions(+), 53 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 60f7662ff..78dae87c3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -749,10 +749,7 @@ export class CollectionFreeFormView extends CollectionSubView this.forceStrokeGesture( e, @@ -763,7 +760,7 @@ export class CollectionFreeFormView extends CollectionSubView this._eraserLock--); } // Lower ink opacity to give the user a visual indicator of deletion. - intersect.inkView.layoutDoc.opacity = 0.0; + intersect.inkView.layoutDoc.opacity = 0.2; intersect.inkView.layoutDoc.dontIntersect = true; } }); @@ -831,63 +828,86 @@ export class CollectionFreeFormView extends CollectionSubView { + radiusErase = (ink: DocumentView, startPt: { X: number; Y: number }, screenEraserPt: { X: number; Y: number }): Segment[] => { const segments: Segment[] = []; + const startInkCoords = ink.ComponentView?.ptFromScreen?.(startPt); const inkCoords = ink.ComponentView?.ptFromScreen?.(screenEraserPt); // coordinates in ink space if (!inkCoords) return []; - var segment1: Segment = []; - var segment2: Segment = []; - const eraseRadius = ActiveInkWidth() / 2; + var eraseSegment: Segment = []; // for eraser visualization const inkStroke = ink?.ComponentView as InkingStroke; - const { inkData } = inkStroke.inkScaledData(); - - const eraserInkData = inkStroke.splitByEraser(inkCoords, eraseRadius); - const tVals: number[] = []; // should be the tvals of the intersections + const eraserStroke: InkData = inkStroke.splitByEraser(startInkCoords, inkCoords).inkData; + const strokeToTVals: Map = new Map(); + for (var i = 0; i < eraserStroke.length - 3; i +=4) { + eraseSegment.push(InkField.Segment(eraserStroke, i)); // for eraser visualization + this.getOtherInkIntersections(i, eraserStroke, strokeToTVals); + } + strokeToTVals.forEach((tVals, inkStroke) => { + var segment1: Segment = []; + var segment2: Segment = []; + const { inkData } = inkStroke.inkScaledData(); + tVals.sort(); + console.log('TVALS', inkStroke, tVals); - for (var i = 0; i < eraserInkData.length - 3; i += 4) { - const eraserBezier: Bezier = InkField.Segment(eraserInkData, i); - segment1.push(eraserBezier); - for (var j = 0; j < inkData.length; j += 4) { - const inkSegment: Bezier = InkField.Segment(inkData, i); - // this.bintersects(inkSegment, eraserBezier).forEach((val: string | number, i: number) => { - // // Converting the Bezier.js Split type to a t-value number. - // const t = +val.toString().split('/')[0]; - // if (i % 2 === 0 && !tVals.includes(t)) tVals.push(t); // bcz: Hack! don't know why but intersection points are doubled from bezier.js (but not identical). - // }); + 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); + + if (tVals.length === 2) { + if (tVals[0] > currCurveT && tVals[0] < currCurveT + 1) { + segment1.push(inkSegment.split(0, tVals[0] - 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) { + if (tVals[0] < Math.floor(inkData.length / 4) - tVals[0]) { + // if it's on the first end + segment1.push(inkSegment.split(tVals[0] - currCurveT, 1)); + hasSplit = true; + } else { + segment1.push(inkSegment.split(0, tVals[0] - currCurveT)); + 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); + } + } + } + } } - } - // segment1.push(eraserBezier); - - // for (var i = 0; i < inkData.length - 3; i += 4) { - // const currCurveT = Math.floor(i/4); - // const inkSegment: Bezier = InkField.Segment(inkData, i); - // if (tVals[0] >= currCurveT && tVals[0] < currCurveT+1) { - // tVals.shift() - // i -= 4; - // if (eraseT - eraseWidth > currCurveT && eraseT + eraseWidth < currCurveT + 1) { - // segment1.push(inkSegment.split(0, eraseT - currCurveT - eraseWidth)); - // segment2.push(inkSegment.split(eraseT - currCurveT + eraseWidth, 1)); - // } else if (eraseT - eraseWidth < currCurveT) { - // segment2.push(inkSegment.split(eraseT - currCurveT + eraseWidth, 1)); - // } else if (eraseT + eraseWidth > currCurveT + 1) { - // segment1.push(inkSegment.split(0, eraseT - currCurveT - eraseWidth)); - // } - // } else if (eraseT > currCurveT + 1) { - // segment1.push(inkSegment); - // } else { - // segment2.push(inkSegment); - // } - // } + 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); + } + }); - // 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); - } - 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); - } + segments.push(eraseSegment); // for eraser visualization return segments; }; @@ -1114,6 +1134,47 @@ export class CollectionFreeFormView extends CollectionSubView): Map => { + // const tVals: [InkingStroke, number[]] = []; + // Iterating through all ink strokes in the current freeform collection. + this.childDocs + .filter(doc => doc.type === DocumentType.INK && !doc.dontIntersect) + .forEach(doc => { + // InkingStroke of other ink strokes + const otherInk = DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())?.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