aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/collectionFreeForm
diff options
context:
space:
mode:
authoreleanor-park <eleanor_park@brown.edu>2024-04-23 15:16:06 -0400
committereleanor-park <eleanor_park@brown.edu>2024-04-23 15:16:06 -0400
commit0c33bc8033c9877abbe6e4074a687559bc4948d0 (patch)
tree8fdbf32e1766201e97ed6a22058fb0235617f714 /src/client/views/collections/collectionFreeForm
parenta374ab9992962ebb6c4af43b82348c706330b58e (diff)
erase multiple segments bug
Diffstat (limited to 'src/client/views/collections/collectionFreeForm')
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx167
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;