aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/InkStrokeProperties.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/InkStrokeProperties.ts')
-rw-r--r--src/client/views/InkStrokeProperties.ts85
1 files changed, 50 insertions, 35 deletions
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index 52ea89cde..3920ecc2a 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -1,20 +1,22 @@
import { Bezier } from 'bezier-js';
+import * as _ from 'lodash';
import { action, makeObservable, observable, reaction, runInAction } from 'mobx';
import { Doc, NumListCast, Opt } from '../../fields/Doc';
-import { InkData, InkField, InkTool, PointData } from '../../fields/InkField';
+import { InkData, InkField, InkTool } from '../../fields/InkField';
import { List } from '../../fields/List';
import { listSpec } from '../../fields/Schema';
import { Cast, NumCast } from '../../fields/Types';
+import { PointData } from '../../pen-gestures/GestureTypes';
import { Point } from '../../pen-gestures/ndollar';
import { DocumentType } from '../documents/DocumentTypes';
-import { FitOneCurve } from '../util/bezierFit';
-import { DocumentManager } from '../util/DocumentManager';
import { undoBatch } from '../util/UndoManager';
+import { FitOneCurve } from '../util/bezierFit';
import { InkingStroke } from './InkingStroke';
+import { CollectionFreeFormView } from './collections/collectionFreeForm';
import { DocumentView } from './nodes/DocumentView';
-import * as _ from 'lodash';
export class InkStrokeProperties {
+ // eslint-disable-next-line no-use-before-define
static _Instance: InkStrokeProperties | undefined;
public static get Instance() {
return this._Instance || new InkStrokeProperties();
@@ -28,11 +30,15 @@ export class InkStrokeProperties {
makeObservable(this);
reaction(
() => this._controlButton,
- button => button && (Doc.ActiveTool = InkTool.None)
+ button => {
+ button && (Doc.ActiveTool = InkTool.None);
+ }
);
reaction(
() => Doc.ActiveTool,
- tool => tool !== InkTool.None && (this._controlButton = false)
+ tool => {
+ tool !== InkTool.None && (this._controlButton = false);
+ }
);
}
@@ -46,7 +52,7 @@ export class InkStrokeProperties {
func: (view: DocumentView, ink: InkData, ptsXscale: number, ptsYscale: number, inkStrokeWidth: number) => { X: number; Y: number }[] | undefined,
requireCurrPoint: boolean = false
) => {
- var appliedFunc = false;
+ let appliedFunc = false;
(strokes instanceof DocumentView ? [strokes] : strokes)?.forEach(
action(inkView => {
if (!requireCurrPoint || this._currentPoint !== -1) {
@@ -85,7 +91,7 @@ export class InkStrokeProperties {
*/
@undoBatch
addPoints = (inkView: DocumentView, t: number, i: number, controls: { X: number; Y: number }[]) => {
- this.applyFunction(inkView, (view: DocumentView, ink: InkData) => {
+ this.applyFunction(inkView, (view: DocumentView /* , ink: InkData */) => {
const doc = view.Document;
const array = [controls[i], controls[i + 1], controls[i + 2], controls[i + 3]];
const newsegs = new Bezier(array.map(p => ({ x: p.X, y: p.Y }))).split(t);
@@ -94,7 +100,9 @@ export class InkStrokeProperties {
// Updating the indices of the control points whose handle tangency has been broken.
doc.brokenInkIndices = new List(Cast(doc.brokenInkIndices, listSpec('number'), []).map(control => (control > i ? control + 4 : control)));
- runInAction(() => (this._currentPoint = -1));
+ runInAction(() => {
+ this._currentPoint = -1;
+ });
return controls;
});
@@ -126,8 +134,8 @@ export class InkStrokeProperties {
*/
getNewHandlePoints = (C: PointData[], D: PointData[], newControl: PointData) => {
const [m, n] = [C.length, D.length];
- let handleSizeA = Math.sqrt(Math.pow(newControl.X - C[0].X, 2) + Math.pow(newControl.Y - C[0].Y, 2));
- let handleSizeB = Math.sqrt(Math.pow(D[n - 1].X - newControl.X, 2) + Math.pow(D[n - 1].Y - newControl.Y, 2));
+ let handleSizeA = Math.sqrt((newControl.X - C[0].X) ** 2 + (newControl.Y - C[0].Y) ** 2);
+ let handleSizeB = Math.sqrt((D[n - 1].X - newControl.X) ** 2 + (D[n - 1].Y - newControl.Y) ** 2);
// Scaling adjustments to improve the ratio between the magnitudes of the two handle lines.
// (Ensures that the new point added doesn't augment the inital shape of the curve much).
if (handleSizeA < 75 && handleSizeB < 75) {
@@ -167,13 +175,13 @@ export class InkStrokeProperties {
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[] = [];
- var startDir = { x: 0, y: 0 };
- var endDir = { x: 0, y: 0 };
- for (var i = 0; i < splicedPoints.length / 4; i++) {
+ 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 (var t = 0; t < (i === splicedPoints.length / 4 - 1 ? 1 + 1e-7 : 1); t += 0.05) {
+ 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));
}
@@ -186,7 +194,9 @@ export class InkStrokeProperties {
}
}
doc.brokenInkIndices = new List(brokenIndices.map(control => (control >= this._currentPoint ? control - 4 : control)));
- runInAction(() => (this._currentPoint = -1));
+ runInAction(() => {
+ this._currentPoint = -1;
+ });
return newPoints.length < 4 ? undefined : newPoints;
},
true
@@ -200,7 +210,7 @@ export class InkStrokeProperties {
*/
@undoBatch
rotateInk = (inkStrokes: DocumentView[], angle: number, scrpt: PointData) => {
- this.applyFunction(inkStrokes, (view: DocumentView, ink: InkData, xScale: number, yScale: number, inkStrokeWidth: number) => {
+ this.applyFunction(inkStrokes, (view: DocumentView, ink: InkData, xScale: number, yScale: number /* , inkStrokeWidth: number */) => {
const inkCenterPt = view.ComponentView?.ptFromScreen?.(scrpt);
return !inkCenterPt
? ink
@@ -247,37 +257,37 @@ export class InkStrokeProperties {
const closed = InkingStroke.IsClosed(ink);
const brokenIndices = Cast(inkView.Document.brokenInkIndices, listSpec('number'), []);
if (origInk && this._currentPoint > 0 && this._currentPoint < ink.length - 1 && brokenIndices.findIndex(value => value === controlIndex) === -1) {
- const cpt_before = ink[controlIndex];
- const cpt = { X: cpt_before.X + deltaX, Y: cpt_before.Y + deltaY };
+ const cptBefore = ink[controlIndex];
+ const cpt = { X: cptBefore.X + deltaX, Y: cptBefore.Y + deltaY };
const newink = origInk.slice();
const start = this._currentPoint === 0 ? 0 : this._currentPoint - 4;
const splicedPoints = origInk.slice(start, start + (this._currentPoint === 0 || this._currentPoint === ink.length - 1 ? 4 : 8));
const { nearestT, nearestSeg } = InkStrokeProperties.nearestPtToStroke(splicedPoints, cpt);
- if ((nearestSeg === 0 && nearestT < 1e-1) || (nearestSeg === 4 && 1 - nearestT < 1e-1)) return ink.slice();
+ if ((nearestSeg === 0 && nearestT < 1e-1) || (nearestSeg === 4 && 1 - nearestT < 1e-1) || nearestSeg < 0) return ink.slice();
const samplesLeft: Point[] = [];
const samplesRight: Point[] = [];
- var startDir = { x: 0, y: 0 };
- var endDir = { x: 0, y: 0 };
- for (var i = 0; i < nearestSeg / 4 + 1; i++) {
+ let startDir = { x: 0, y: 0 };
+ let endDir = { x: 0, y: 0 };
+ for (let i = 0; i < nearestSeg / 4 + 1; 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(_.isEqual(bez.derivative(0), { x: 0, y: 0, t: 0 }) ? 1e-8 : 0);
if (i === nearestSeg / 4) endDir = bez.derivative(nearestT);
- for (var t = 0; t < (i === nearestSeg / 4 ? nearestT + 0.05 : 1); t += 0.05) {
+ for (let t = 0; t < (i === nearestSeg / 4 ? nearestT + 0.05 : 1); t += 0.05) {
const pt = bez.compute(i !== nearestSeg / 4 ? t : Math.min(nearestT, t));
samplesLeft.push(new Point(pt.x, pt.y));
}
}
- var { finalCtrls } = FitOneCurve(samplesLeft, { X: startDir.x, Y: startDir.y }, { X: endDir.x, Y: endDir.y });
- for (var i = nearestSeg / 4; i < splicedPoints.length / 4; i++) {
+ let { finalCtrls } = FitOneCurve(samplesLeft, { X: startDir.x, Y: startDir.y }, { X: endDir.x, Y: endDir.y });
+ for (let i = nearestSeg / 4; 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 === nearestSeg / 4) startDir = bez.derivative(nearestT);
if (i === splicedPoints.length / 4 - 1) endDir = bez.derivative(_.isEqual(bez.derivative(1), { x: 0, y: 0, t: 1 }) ? 1 - 1e-8 : 1);
- for (var t = i === nearestSeg / 4 ? nearestT : 0; t < (i === nearestSeg / 4 ? 1 + 0.05 + 1e-7 : 1 + 1e-7); t += 0.05) {
+ for (let t = i === nearestSeg / 4 ? nearestT : 0; t < (i === nearestSeg / 4 ? 1 + 0.05 + 1e-7 : 1 + 1e-7); t += 0.05) {
const pt = bez.compute(Math.min(1, t));
samplesRight.push(new Point(pt.x, pt.y));
}
}
- const { finalCtrls: rightCtrls, error: errorRight } = FitOneCurve(samplesRight, { X: startDir.x, Y: startDir.y }, { X: endDir.x, Y: endDir.y });
+ const { finalCtrls: rightCtrls /* , error: errorRight */ } = FitOneCurve(samplesRight, { X: startDir.x, Y: startDir.y }, { X: endDir.x, Y: endDir.y });
finalCtrls = finalCtrls.concat(rightCtrls);
newink.splice(this._currentPoint - 4, 8, ...finalCtrls);
return newink;
@@ -307,11 +317,12 @@ export class InkStrokeProperties {
});
public static nearestPtToStroke(ctrlPoints: { X: number; Y: number }[], refInkSpacePt: { X: number; Y: number }, excludeSegs?: number[]) {
- var distance = Number.MAX_SAFE_INTEGER;
- var nearestT = -1;
- var nearestSeg = -1;
- var nearestPt = { X: 0, Y: 0 };
- for (var i = 0; i < ctrlPoints.length - 3; i += 4) {
+ let distance = Number.MAX_SAFE_INTEGER;
+ let nearestT = -1;
+ let nearestSeg = -1;
+ let nearestPt = { X: 0, Y: 0 };
+ for (let i = 0; i < ctrlPoints.length - 3; i += 4) {
+ // eslint-disable-next-line no-continue
if (excludeSegs?.includes(i)) continue;
const array = [ctrlPoints[i], ctrlPoints[i + 1], ctrlPoints[i + 2], ctrlPoints[i + 3]];
const point = new Bezier(array.map(p => ({ x: p.X, y: p.Y }))).project({ x: refInkSpacePt.X, y: refInkSpacePt.Y });
@@ -369,17 +380,18 @@ export class InkStrokeProperties {
};
snapToAllCurves = (screenDragPt: { X: number; Y: number }, inkView: DocumentView, snapData: { nearestPt: { X: number; Y: number }; distance: number }, ink: InkData, controlIndex: number) => {
- const containingCollection = inkView.CollectionFreeFormView;
+ const containingCollection = CollectionFreeFormView.from(inkView);
const containingDocView = containingCollection?.DocumentView?.();
containingCollection?.childDocs
.filter(doc => doc.type === DocumentType.INK)
.forEach(doc => {
- const testInkView = DocumentManager.Instance.getDocumentView(doc, containingDocView);
+ const testInkView = DocumentView.getDocumentView(doc, containingDocView);
const snapped = testInkView?.ComponentView?.snapPt?.(screenDragPt, doc === inkView.Document ? this.excludeSelfSnapSegs(ink, controlIndex) : []);
if (snapped && snapped.distance < snapData.distance) {
const snappedInkPt = doc === inkView.Document ? snapped.nearestPt : inkView.ComponentView?.ptFromScreen?.(testInkView?.ComponentView?.ptToScreen?.(snapped.nearestPt) ?? { X: 0, Y: 0 }); // convert from snapped ink coordinate system to dragged ink coordinate system by converting to/from screen space
if (snappedInkPt) {
+ // eslint-disable-next-line no-param-reassign
snapData = { nearestPt: snappedInkPt, distance: snapped.distance };
}
}
@@ -406,6 +418,7 @@ export class InkStrokeProperties {
inkCopy[handleIndexB] = this.rotatePoint(handleB, controlPoint, angleDifference);
return inkCopy;
}
+ return undefined;
});
};
@@ -430,7 +443,9 @@ export class InkStrokeProperties {
const magnitudeB = Math.sqrt(vectorB.X * vectorB.X + vectorB.Y * vectorB.Y);
if (magnitudeA === 0 || magnitudeB === 0) return 0;
// Normalizing the vectors.
+ // eslint-disable-next-line no-param-reassign
vectorA = { X: vectorA.X / magnitudeA, Y: vectorA.Y / magnitudeA };
+ // eslint-disable-next-line no-param-reassign
vectorB = { X: vectorB.X / magnitudeB, Y: vectorB.Y / magnitudeB };
return Math.acos(vectorB.X * vectorA.X + vectorB.Y * vectorA.Y);
}