diff options
| author | bobzel <zzzman@gmail.com> | 2024-08-29 13:59:00 -0400 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2024-08-29 13:59:00 -0400 |
| commit | b1692a7435ae9698eff618bef0e370fe3eb89572 (patch) | |
| tree | 20664940b2774a4b0fffdecaafdd40bfd08c4251 /src/client/views/InkStrokeProperties.ts | |
| parent | 0ac79ba6a7ab19b4aafbc11dac9bab4781d4bd40 (diff) | |
from last cleanup
Diffstat (limited to 'src/client/views/InkStrokeProperties.ts')
| -rw-r--r-- | src/client/views/InkStrokeProperties.ts | 140 |
1 files changed, 67 insertions, 73 deletions
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index b5cd72fa7..13807c25f 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -1,22 +1,22 @@ import { Bezier } from 'bezier-js'; import * as _ from 'lodash'; import { action, makeObservable, observable, reaction, runInAction } from 'mobx'; +import simplify from 'simplify-js'; import { Doc, NumListCast, Opt } from '../../fields/Doc'; import { InkData, InkField, InkTool } from '../../fields/InkField'; import { List } from '../../fields/List'; import { listSpec } from '../../fields/Schema'; -import { Cast, NumCast, toList } from '../../fields/Types'; +import { Cast, NumCast } from '../../fields/Types'; import { Gestures, PointData } from '../../pen-gestures/GestureTypes'; +import { GestureUtils } from '../../pen-gestures/GestureUtils'; import { Point } from '../../pen-gestures/ndollar'; import { DocumentType } from '../documents/DocumentTypes'; -import { undoBatch, undoable } from '../util/UndoManager'; +import { undoable } from '../util/UndoManager'; import { FitOneCurve } from '../util/bezierFit'; +import { GestureOverlay } from './GestureOverlay'; import { InkingStroke } from './InkingStroke'; import { CollectionFreeFormView } from './collections/collectionFreeForm'; import { DocumentView } from './nodes/DocumentView'; -import simplify from 'simplify-js'; -import { GestureUtils } from '../../pen-gestures/GestureUtils'; -import { GestureOverlay } from './GestureOverlay'; export class InkStrokeProperties { // eslint-disable-next-line no-use-before-define @@ -163,48 +163,46 @@ export class InkStrokeProperties { /** * Deletes the current control point of the selected ink instance. */ - deletePoints = undoable( - (inkView: DocumentView, preserve: boolean) => - this.applyFunction( - inkView, - (view: DocumentView, ink: InkData) => { - const doc = view.Document; - 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)); - const samples: Point[] = []; - let startDir = { x: 0, y: 0 }; - let endDir = { x: 0, y: 0 }; - for (let i = 0; i < splicedPoints.length / 4; i++) { - const 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 (let t = 0; t < (i === splicedPoints.length / 4 - 1 ? 1 + 1e-7 : 1); t += 0.05) { - const 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); + deletePoints = undoable((inkView: DocumentView, preserve: boolean) => { + this.applyFunction( + inkView, + (view: DocumentView, ink: InkData) => { + const doc = view.Document; + 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)); + const samples: Point[] = []; + let startDir = { x: 0, y: 0 }; + let endDir = { x: 0, y: 0 }; + for (let i = 0; i < splicedPoints.length / 4; i++) { + const 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 (let t = 0; t < (i === splicedPoints.length / 4 - 1 ? 1 + 1e-7 : 1); t += 0.05) { + const pt = bez.compute(t); + samples.push(new Point(pt.x, pt.y)); } } - doc.brokenInkIndices = new List(brokenIndices.map(control => (control >= this._currentPoint ? control - 4 : control))); - runInAction(() => { - this._currentPoint = -1; - }); - return newPoints.length < 4 ? undefined : newPoints; - }, - true - ), - 'delete ink points' - ); + 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(brokenIndices.map(control => (control >= this._currentPoint ? control - 4 : control))); + runInAction(() => { + this._currentPoint = -1; + }); + return newPoints.length < 4 ? undefined : newPoints; + }, + true + ); + }, 'delete ink points'); /** * Rotates ink stroke(s) about a point @@ -251,9 +249,8 @@ export class InkStrokeProperties { /** * Handles the movement/scaling of a control point. */ - moveControlPtHandle = undoable( - (inkView: DocumentView, deltaX: number, deltaY: number, controlIndex: number, origInk?: InkData) => - inkView && + moveControlPtHandle = undoable((inkView: DocumentView, deltaX: number, deltaY: number, controlIndex: number, origInk?: InkData) => { + inkView && this.applyFunction(inkView, (view: DocumentView, ink: InkData) => { const order = controlIndex % 4; const closed = InkingStroke.IsClosed(ink); @@ -316,9 +313,8 @@ export class InkStrokeProperties { } return pt; }); - }), - 'move ink ctrl pt' - ); + }); + }, 'move ink ctrl pt'); public static nearestPtToStroke(ctrlPoints: { X: number; Y: number }[], refInkSpacePt: { X: number; Y: number }, excludeSegs?: number[]) { let distance = Number.MAX_SAFE_INTEGER; @@ -471,28 +467,26 @@ export class InkStrokeProperties { /** * Handles the movement/scaling of a handle point. */ - moveTangentHandle = undoable( - (inkView: DocumentView, deltaX: number, deltaY: number, handleIndex: number, oppositeHandleIndex: number, controlIndex: number) => - this.applyFunction(inkView, (view: DocumentView, ink: InkData) => { - const doc = view.Document; - const closed = InkingStroke.IsClosed(ink); - const oldHandlePoint = ink[handleIndex]; - const oppositeHandlePoint = ink[oppositeHandleIndex]; - const controlPoint = ink[controlIndex]; - const newHandlePoint = { X: ink[handleIndex].X - deltaX, Y: ink[handleIndex].Y - deltaY }; - const inkCopy = ink.slice(); - inkCopy[handleIndex] = newHandlePoint; - const brokenIndices = Cast(doc.brokenInkIndices, listSpec('number')); - const equivIndex = closed ? (controlIndex === 0 ? ink.length - 1 : controlIndex === ink.length - 1 ? 0 : -1) : -1; - // Rotate opposite handle if user hasn't held 'Alt' key or not first/final control (which have only 1 handle). - if ((!brokenIndices || (!brokenIndices?.includes(controlIndex) && !brokenIndices?.includes(equivIndex))) && (closed || (handleIndex !== 1 && handleIndex !== ink.length - 2))) { - const angle = InkStrokeProperties.angleChange(oldHandlePoint, newHandlePoint, controlPoint); - inkCopy[oppositeHandleIndex] = this.rotatePoint(oppositeHandlePoint, controlPoint, angle); - } - return inkCopy; - }), - 'move ink tangent' - ); + moveTangentHandle = undoable((inkView: DocumentView, deltaX: number, deltaY: number, handleIndex: number, oppositeHandleIndex: number, controlIndex: number) => { + this.applyFunction(inkView, (view: DocumentView, ink: InkData) => { + const doc = view.Document; + const closed = InkingStroke.IsClosed(ink); + const oldHandlePoint = ink[handleIndex]; + const oppositeHandlePoint = ink[oppositeHandleIndex]; + const controlPoint = ink[controlIndex]; + const newHandlePoint = { X: ink[handleIndex].X - deltaX, Y: ink[handleIndex].Y - deltaY }; + const inkCopy = ink.slice(); + inkCopy[handleIndex] = newHandlePoint; + const brokenIndices = Cast(doc.brokenInkIndices, listSpec('number')); + const equivIndex = closed ? (controlIndex === 0 ? ink.length - 1 : controlIndex === ink.length - 1 ? 0 : -1) : -1; + // Rotate opposite handle if user hasn't held 'Alt' key or not first/final control (which have only 1 handle). + if ((!brokenIndices || (!brokenIndices?.includes(controlIndex) && !brokenIndices?.includes(equivIndex))) && (closed || (handleIndex !== 1 && handleIndex !== ink.length - 2))) { + const angle = InkStrokeProperties.angleChange(oldHandlePoint, newHandlePoint, controlPoint); + inkCopy[oppositeHandleIndex] = this.rotatePoint(oppositeHandlePoint, controlPoint, angle); + } + return inkCopy; + }); + }, 'move ink tangent'); /** * Function that "smooths" ink strokes by using the gesture recognizer to detect shapes and |
