aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/InkControlPtHandles.tsx2
-rw-r--r--src/client/views/InkStrokeProperties.ts41
-rw-r--r--src/client/views/InkingStroke.tsx2
3 files changed, 32 insertions, 13 deletions
diff --git a/src/client/views/InkControlPtHandles.tsx b/src/client/views/InkControlPtHandles.tsx
index df803ba31..a91e74c44 100644
--- a/src/client/views/InkControlPtHandles.tsx
+++ b/src/client/views/InkControlPtHandles.tsx
@@ -102,7 +102,7 @@ export class InkControlPtHandles extends React.Component<InkControlProps> {
@action
onDelete = (e: KeyboardEvent) => {
if (["-", "Backspace", "Delete"].includes(e.key)) {
- InkStrokeProperties.Instance?.deletePoints(this.props.inkView);
+ InkStrokeProperties.Instance?.deletePoints(this.props.inkView, e.shiftKey);
e.stopPropagation();
}
}
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index 8ad4864f9..4808bbc77 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -1,16 +1,18 @@
import { Bezier } from "bezier-js";
import { action, observable, reaction } from "mobx";
-import { Doc, Opt, DocListCast } from "../../fields/Doc";
+import { Doc, NumListCast, Opt } from "../../fields/Doc";
import { InkData, InkField, InkTool, PointData } from "../../fields/InkField";
import { List } from "../../fields/List";
import { listSpec } from "../../fields/Schema";
import { Cast, NumCast } from "../../fields/Types";
+import { Point } from "../../pen-gestures/ndollar";
import { DocumentType } from "../documents/DocumentTypes";
+import { FitOneCurve } from "../util/bezierFit";
import { CurrentUserUtils } from "../util/CurrentUserUtils";
+import { DocumentManager } from "../util/DocumentManager";
import { undoBatch } from "../util/UndoManager";
import { InkingStroke } from "./InkingStroke";
import { DocumentView } from "./nodes/DocumentView";
-import { DocumentManager } from "../util/DocumentManager";
export class InkStrokeProperties {
static Instance: InkStrokeProperties | undefined;
@@ -139,18 +141,35 @@ export class InkStrokeProperties {
*/
@undoBatch
@action
- deletePoints = (inkView: DocumentView) => this.applyFunction(inkView, (view: DocumentView, ink: InkData) => {
+ deletePoints = (inkView: DocumentView, preserve: boolean) => this.applyFunction(inkView, (view: DocumentView, ink: InkData) => {
const doc = view.rootDoc;
- const newPoints: { X: number, Y: number }[] = [];
- const toRemove = Math.floor((this._currentPoint + 2) / 4);
- const last = this._currentPoint === ink.length - 1;
- for (let i = 0; i < ink.length; i++) {
- if (Math.floor((i + 2) / 4) !== toRemove && (toRemove !== 0 || i > 3)) {
- newPoints.push({ X: ink[i].X, Y: ink[i].Y });
+ const newPoints = ink.slice();
+ const brokenIndices = NumListCast(doc.brokenInkIndices);
+ if (preserve || this._currentPoint === 0 || this._currentPoint === ink.length - 1 || brokenIndices.includes(this._currentPoint)) {
+ newPoints.splice(this._currentPoint === 0 ? 0 : this._currentPoint === ink.length - 1 ? this._currentPoint - 3 : this._currentPoint - 2, 4);
+ } else {
+ const start = this._currentPoint === 0 ? 0 : this._currentPoint - 4;
+ const splicedPoints = ink.slice(start, start + (this._currentPoint === 0 || this._currentPoint === ink.length - 1 ? 4 : 8));
+ var samples: Point[] = [];
+ var startDir = { x: 0, y: 0 };
+ var endDir = { x: 0, y: 0 };
+ for (var i = 0; i < splicedPoints.length / 4; i++) {
+ var bez = new Bezier(splicedPoints.slice(i * 4, i * 4 + 4).map(p => ({ x: p.X, y: p.Y })));
+ if (i === 0) startDir = bez.derivative(0);
+ if (i === splicedPoints.length / 4 - 1) endDir = bez.derivative(1);
+ for (var t = 0; t < (i === splicedPoints.length / 4 - 1 ? 1 + 1e-7 : 1); t += 0.05) {
+ var pt = bez.compute(t);
+ samples.push(new Point(pt.x, pt.y));
+ }
+ }
+ const { finalCtrls, error } = FitOneCurve(samples, { X: startDir.x, Y: startDir.y }, { X: endDir.x, Y: endDir.y });
+ if (error < 100) {
+ newPoints.splice(this._currentPoint - 4, 8, ...finalCtrls);
+ } else {
+ newPoints.splice(this._currentPoint - 2, 4);
}
}
- doc.brokenInkIndices = new List(Cast(doc.brokenInkIndices, listSpec("number"), []).map(control => control >= toRemove * 4 ? control - 4 : control));
- if (last) newPoints.splice(newPoints.length - 3, 2);
+ doc.brokenInkIndices = new List(brokenIndices.map(control => control >= this._currentPoint ? control - 4 : control));
this._currentPoint = -1;
return newPoints.length < 4 ? undefined : newPoints;
}, true)
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index ecc82a580..8ff080f81 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -132,7 +132,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
} else if (isEditing) {
this._nearestT && this._nearestSeg !== undefined && InkStrokeProperties.Instance?.addPoints(this.props.docViewPath().lastElement(), this._nearestT, this._nearestSeg, this.inkScaledData().inkData.slice());
}
- }), isEditing, isEditing, () => wasSelected && InkStrokeProperties.Instance && (InkStrokeProperties.Instance._currentPoint = -1));
+ }), isEditing, isEditing, action(() => wasSelected && InkStrokeProperties.Instance && (InkStrokeProperties.Instance._currentPoint = -1)));
}
}