From 6ddfdb20e6a0b2c896594ad2c20292c6cfea0c1a Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 24 Apr 2024 00:36:30 -0400 Subject: several fixes to radius ink eraser to fix eraser shap, intersections with straight lines --- .../collectionFreeForm/CollectionFreeFormView.tsx | 91 +++++++++++++--------- 1 file changed, 53 insertions(+), 38 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 78dae87c3..9df9c5492 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -620,6 +620,7 @@ export class CollectionFreeFormView extends CollectionSubView { 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. this.getEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint).forEach(intersect => { if (!this._deleteList.includes(intersect.inkView)) { @@ -749,7 +753,7 @@ export class CollectionFreeFormView extends CollectionSubView this.forceStrokeGesture( e, @@ -832,16 +836,16 @@ export class CollectionFreeFormView extends CollectionSubView = new Map(); - for (var i = 0; i < eraserStroke.length - 3; i +=4) { + for (var i = 0; i < eraserStroke.length - 3; i += 4) { eraseSegment.push(InkField.Segment(eraserStroke, i)); // for eraser visualization - this.getOtherInkIntersections(i, eraserStroke, strokeToTVals); + this.getOtherInkIntersections(ink, i, eraserStroke, strokeToTVals); } strokeToTVals.forEach((tVals, inkStroke) => { var segment1: Segment = []; @@ -852,7 +856,7 @@ export class CollectionFreeFormView extends CollectionSubView currCurveT && tVals[0] < currCurveT + 1) { - if (tVals[0] < Math.floor(inkData.length / 4) - tVals[0]) { + // 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(inkSegment.split(tVals[0] - currCurveT, 1)); + segment1.push(splits.left); hasSplit = true; } else { - segment1.push(inkSegment.split(0, tVals[0] - currCurveT)); + segment1.push(splits.right); hasSplit = true; } } else { @@ -1084,6 +1095,15 @@ export class CollectionFreeFormView extends CollectionSubView { + if ((curve as any)._linear) { + // bezier.js doesn't intersect properly if the curve is actually a line -- so get intersect other curve against this line, then figure out the t coordinates of the intersection on this line + const intersections = otherCurve.lineIntersects({ p1: curve.points[0], p2: curve.points[3] }); + if (intersections.length) { + const intPt = otherCurve.get(intersections[0]); + const intT = curve.project(intPt).t; + return intT ? [intT] : []; + } + } if ((otherCurve as any)._linear) { return curve.lineIntersects({ p1: otherCurve.points[0], p2: otherCurve.points[3] }); } @@ -1135,43 +1155,38 @@ 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)]); - } + getOtherInkIntersections = (otherInkDocView: DocumentView, i: number, points: InkData, strokeToTVals: Map): Map => { + // 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; }; -- cgit v1.2.3-70-g09d2