aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/InkStrokeProperties.ts
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-08-29 13:59:00 -0400
committerbobzel <zzzman@gmail.com>2024-08-29 13:59:00 -0400
commitb1692a7435ae9698eff618bef0e370fe3eb89572 (patch)
tree20664940b2774a4b0fffdecaafdd40bfd08c4251 /src/client/views/InkStrokeProperties.ts
parent0ac79ba6a7ab19b4aafbc11dac9bab4781d4bd40 (diff)
from last cleanup
Diffstat (limited to 'src/client/views/InkStrokeProperties.ts')
-rw-r--r--src/client/views/InkStrokeProperties.ts140
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