diff options
| author | eleanor-park <eleanor_park@brown.edu> | 2024-04-23 15:16:06 -0400 |
|---|---|---|
| committer | eleanor-park <eleanor_park@brown.edu> | 2024-04-23 15:16:06 -0400 |
| commit | 0c33bc8033c9877abbe6e4074a687559bc4948d0 (patch) | |
| tree | 8fdbf32e1766201e97ed6a22058fb0235617f714 /src/client/views/collections/collectionFreeForm | |
| parent | a374ab9992962ebb6c4af43b82348c706330b58e (diff) | |
erase multiple segments bug
Diffstat (limited to 'src/client/views/collections/collectionFreeForm')
| -rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 167 |
1 files changed, 114 insertions, 53 deletions
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<Partial<collection 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, intersect.t, currPoint); - // } else if (Doc.ActiveTool === InkTool.RadiusEraser) { - // segments = undefined; - // } + : this.radiusErase(intersect.inkView, { X: down[0], Y: down[1] }, currPoint); segments?.forEach(segment => this.forceStrokeGesture( e, @@ -763,7 +760,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.0; + intersect.inkView.layoutDoc.opacity = 0.2; intersect.inkView.layoutDoc.dontIntersect = true; } }); @@ -831,63 +828,86 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection }; @action - radiusErase = (ink: DocumentView, eraseT: number, screenEraserPt: { X: number; Y: number }): Segment[] => { + 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<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(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<Partial<collection return tVals; }; + /** + * For radius erase, a function to find an eraser's intersections with all ink strokes on the freeform canvas. + * @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 = (i: number, points: InkData, strokeToTVals: Map<InkingStroke, number[]>): Map<InkingStroke, number[]> => { + // 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; |
