diff options
Diffstat (limited to 'src/client/views')
-rw-r--r-- | src/client/views/InkControlPtHandles.tsx | 2 | ||||
-rw-r--r-- | src/client/views/InkStrokeProperties.ts | 41 | ||||
-rw-r--r-- | src/client/views/InkingStroke.tsx | 2 |
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))); } } |