aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/InkStrokeProperties.ts
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2022-07-08 00:17:26 -0400
committerbobzel <zzzman@gmail.com>2022-07-08 00:17:26 -0400
commit146f8622d5bac2edc6b09f57c173bd057dfbcfad (patch)
treef871089c438a476543ca96bac163c0532b9557c7 /src/client/views/InkStrokeProperties.ts
parentb7e66da6b23cdb41c127000dfe13843d35f7d0cc (diff)
restructured currentUserUtils to avoid having import cycles.
Diffstat (limited to 'src/client/views/InkStrokeProperties.ts')
-rw-r--r--src/client/views/InkStrokeProperties.ts278
1 files changed, 147 insertions, 131 deletions
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index 471ad09e9..821e2f739 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -1,23 +1,23 @@
-import { Bezier } from "bezier-js";
-import { Normalize, Distance } from "../util/bezierFit";
-import { action, observable, reaction } from "mobx";
-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 { Bezier } from 'bezier-js';
+import { action, observable, reaction } from 'mobx';
+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 { DocumentManager } from '../util/DocumentManager';
+import { undoBatch } from '../util/UndoManager';
+import { InkingStroke } from './InkingStroke';
+import { DocumentView } from './nodes/DocumentView';
export class InkStrokeProperties {
static _Instance: InkStrokeProperties | undefined;
- public static get Instance() { return this._Instance || new InkStrokeProperties(); }
+ public static get Instance() {
+ return this._Instance || new InkStrokeProperties();
+ }
@observable _lock = false;
@observable _controlButton = false;
@@ -25,8 +25,14 @@ export class InkStrokeProperties {
constructor() {
InkStrokeProperties._Instance = this;
- reaction(() => this._controlButton, button => button && (CurrentUserUtils.ActiveTool = InkTool.None));
- reaction(() => CurrentUserUtils.ActiveTool, tool => (tool !== InkTool.None) && (this._controlButton = false));
+ reaction(
+ () => this._controlButton,
+ button => button && (Doc.ActiveTool = InkTool.None)
+ );
+ reaction(
+ () => Doc.ActiveTool,
+ tool => tool !== InkTool.None && (this._controlButton = false)
+ );
}
/**
@@ -34,35 +40,41 @@ export class InkStrokeProperties {
* @param func The inputted function.
* @param requireCurrPoint Indicates whether the current selected point is needed.
*/
- applyFunction = (strokes: Opt<DocumentView | DocumentView[]>, func: (view: DocumentView, ink: InkData, ptsXscale: number, ptsYscale: number, inkStrokeWidth: number) => { X: number, Y: number }[] | undefined, requireCurrPoint: boolean = false) => {
+ applyFunction = (
+ strokes: Opt<DocumentView | DocumentView[]>,
+ func: (view: DocumentView, ink: InkData, ptsXscale: number, ptsYscale: number, inkStrokeWidth: number) => { X: number; Y: number }[] | undefined,
+ requireCurrPoint: boolean = false
+ ) => {
var appliedFunc = false;
- (strokes instanceof DocumentView ? [strokes] : strokes)?.forEach(action(inkView => {
- if (!requireCurrPoint || this._currentPoint !== -1) {
- const doc = inkView.rootDoc;
- if (doc.type === DocumentType.INK && doc.width && doc.height) {
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
- const oldXrange = (xs => ({ coord: NumCast(doc.x), min: Math.min(...xs), max: Math.max(...xs) }))(ink.map(p => p.X));
- const oldYrange = (ys => ({ coord: NumCast(doc.y), min: Math.min(...ys), max: Math.max(...ys) }))(ink.map(p => p.Y));
- const ptsXscale = ((NumCast(doc._width) - NumCast(doc.strokeWidth)) / ((oldXrange.max - oldXrange.min) || 1)) || 1;
- const ptsYscale = ((NumCast(doc._height) - NumCast(doc.strokeWidth)) / ((oldYrange.max - oldYrange.min) || 1)) || 1;
- const newPoints = func(inkView, ink, ptsXscale, ptsYscale, NumCast(doc.strokeWidth));
- if (newPoints) {
- const newXrange = (xs => ({ min: Math.min(...xs), max: Math.max(...xs) }))(newPoints.map(p => p.X));
- const newYrange = (ys => ({ min: Math.min(...ys), max: Math.max(...ys) }))(newPoints.map(p => p.Y));
- doc._width = (newXrange.max - newXrange.min) * ptsXscale + NumCast(doc.strokeWidth);
- doc._height = (newYrange.max - newYrange.min) * ptsYscale + NumCast(doc.strokeWidth);
- doc.x = (oldXrange.coord + (newXrange.min - oldXrange.min) * ptsXscale);
- doc.y = (oldYrange.coord + (newYrange.min - oldYrange.min) * ptsYscale);
- Doc.GetProto(doc).data = new InkField(newPoints);
- appliedFunc = true;
+ (strokes instanceof DocumentView ? [strokes] : strokes)?.forEach(
+ action(inkView => {
+ if (!requireCurrPoint || this._currentPoint !== -1) {
+ const doc = inkView.rootDoc;
+ if (doc.type === DocumentType.INK && doc.width && doc.height) {
+ const ink = Cast(doc.data, InkField)?.inkData;
+ if (ink) {
+ const oldXrange = (xs => ({ coord: NumCast(doc.x), min: Math.min(...xs), max: Math.max(...xs) }))(ink.map(p => p.X));
+ const oldYrange = (ys => ({ coord: NumCast(doc.y), min: Math.min(...ys), max: Math.max(...ys) }))(ink.map(p => p.Y));
+ const ptsXscale = (NumCast(doc._width) - NumCast(doc.strokeWidth)) / (oldXrange.max - oldXrange.min || 1) || 1;
+ const ptsYscale = (NumCast(doc._height) - NumCast(doc.strokeWidth)) / (oldYrange.max - oldYrange.min || 1) || 1;
+ const newPoints = func(inkView, ink, ptsXscale, ptsYscale, NumCast(doc.strokeWidth));
+ if (newPoints) {
+ const newXrange = (xs => ({ min: Math.min(...xs), max: Math.max(...xs) }))(newPoints.map(p => p.X));
+ const newYrange = (ys => ({ min: Math.min(...ys), max: Math.max(...ys) }))(newPoints.map(p => p.Y));
+ doc._width = (newXrange.max - newXrange.min) * ptsXscale + NumCast(doc.strokeWidth);
+ doc._height = (newYrange.max - newYrange.min) * ptsYscale + NumCast(doc.strokeWidth);
+ doc.x = oldXrange.coord + (newXrange.min - oldXrange.min) * ptsXscale;
+ doc.y = oldYrange.coord + (newYrange.min - oldYrange.min) * ptsYscale;
+ Doc.GetProto(doc).data = new InkField(newPoints);
+ appliedFunc = true;
+ }
}
}
}
- }
- }));
+ })
+ );
return appliedFunc;
- }
+ };
/**
* Adds a new control point to the ink instance when editing its format.
@@ -72,7 +84,7 @@ export class InkStrokeProperties {
*/
@undoBatch
@action
- addPoints = (inkView: DocumentView, t: number, i: number, controls: { X: number, Y: number }[]) => {
+ addPoints = (inkView: DocumentView, t: number, i: number, controls: { X: number; Y: number }[]) => {
this.applyFunction(inkView, (view: DocumentView, ink: InkData) => {
const doc = view.rootDoc;
const array = [controls[i], controls[i + 1], controls[i + 2], controls[i + 3]];
@@ -81,12 +93,12 @@ export class InkStrokeProperties {
controls.splice(i, 4, ...splicepts.map(p => ({ X: p.x, Y: p.y })));
// 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));
+ doc.brokenInkIndices = new List(Cast(doc.brokenInkIndices, listSpec('number'), []).map(control => (control > i ? control + 4 : control)));
this._currentPoint = -1;
return controls;
});
- }
+ };
/**
* Scales a handle point of a control point that is adjacent to a newly added one.
@@ -107,15 +119,15 @@ export class InkStrokeProperties {
* the tangent vector to a control point is equivalent to the first/last (depending on the direction
* of the curve) leg of the Bézier curve's derivative.
* (Source: https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-der.html)
- *
+ *
* @param C The curve represented by all points from the previous control until the newly added point.
* @param D The curve represented by all points from the newly added point to the next control.
* @param newControl The newly added control point.
*/
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(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));
// 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) {
@@ -131,50 +143,55 @@ export class InkStrokeProperties {
}
// Finding the last leg of the derivative curve of C.
const dC = { X: (handleSizeA / n) * (C[m - 1].X - C[m - 2].X), Y: (handleSizeA / n) * (C[m - 1].Y - C[m - 2].Y) };
- // Finding the first leg of the derivative curve of D.
+ // Finding the first leg of the derivative curve of D.
const dD = { X: (handleSizeB / m) * (D[1].X - D[0].X), Y: (handleSizeB / m) * (D[1].Y - D[0].Y) };
const handleA = { X: newControl.X - dC.X, Y: newControl.Y - dC.Y };
const handleB = { X: newControl.X + dD.X, Y: newControl.Y + dD.Y };
return [handleA, handleB];
- }
+ };
/**
* Deletes the current control point of the selected ink instance.
*/
@undoBatch
@action
- deletePoints = (inkView: DocumentView, preserve: boolean) => this.applyFunction(inkView, (view: DocumentView, ink: InkData) => {
- const doc = view.rootDoc;
- 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[] = [];
- var startDir = { x: 0, y: 0 };
- var endDir = { x: 0, y: 0 };
- for (var 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) {
- const pt = bez.compute(t);
- samples.push(new Point(pt.x, pt.y));
+ deletePoints = (inkView: DocumentView, preserve: boolean) =>
+ this.applyFunction(
+ inkView,
+ (view: DocumentView, ink: InkData) => {
+ const doc = view.rootDoc;
+ 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[] = [];
+ var startDir = { x: 0, y: 0 };
+ var endDir = { x: 0, y: 0 };
+ for (var 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) {
+ 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);
+ }
}
- }
- 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));
- this._currentPoint = -1;
- return newPoints.length < 4 ? undefined : newPoints;
- }, true)
+ doc.brokenInkIndices = new List(brokenIndices.map(control => (control >= this._currentPoint ? control - 4 : control)));
+ this._currentPoint = -1;
+ return newPoints.length < 4 ? undefined : newPoints;
+ },
+ true
+ );
/**
* Rotates ink stroke(s) about a point
@@ -188,15 +205,16 @@ export class InkStrokeProperties {
this.applyFunction(inkStrokes, (view: DocumentView, ink: InkData, xScale: number, yScale: number, inkStrokeWidth: number) => {
view.rootDoc.rotation = NumCast(view.rootDoc.rotation) + angle;
const inkCenterPt = view.ComponentView?.ptFromScreen?.(scrpt);
- return !inkCenterPt ? ink :
- ink.map(i => {
- const pt = { X: i.X - inkCenterPt.X, Y: i.Y - inkCenterPt.Y };
- const newX = Math.cos(angle) * pt.X - Math.sin(angle) * pt.Y * yScale / xScale;
- const newY = Math.sin(angle) * pt.X * xScale / yScale + Math.cos(angle) * pt.Y;
- return { X: newX + inkCenterPt.X, Y: newY + inkCenterPt.Y };
- });
+ return !inkCenterPt
+ ? ink
+ : ink.map(i => {
+ const pt = { X: i.X - inkCenterPt.X, Y: i.Y - inkCenterPt.Y };
+ const newX = Math.cos(angle) * pt.X - (Math.sin(angle) * pt.Y * yScale) / xScale;
+ const newY = (Math.sin(angle) * pt.X * xScale) / yScale + Math.cos(angle) * pt.Y;
+ return { X: newX + inkCenterPt.X, Y: newY + inkCenterPt.Y };
+ });
});
- }
+ };
/**
* Rotates ink stroke(s) about a point
@@ -210,16 +228,17 @@ export class InkStrokeProperties {
this.applyFunction(inkStrokes, (view: DocumentView, ink: InkData) => {
const ptFromScreen = view.ComponentView?.ptFromScreen;
const ptToScreen = view.ComponentView?.ptToScreen;
- return !ptToScreen || !ptFromScreen ? ink :
- ink.map(ptToScreen).map(i => {
- const pvec = { X: i.X - scrpt.X, Y: i.Y - scrpt.Y };
- const svec = pvec.X * scrVec.X * scaling + pvec.Y * scrVec.Y * scaling;
- const ovec = -pvec.X * scrVec.Y * (scaleUniformly ? scaling : 1) + pvec.Y * scrVec.X * (scaleUniformly ? scaling : 1);
- const newscrpt = { X: scrpt.X + svec * scrVec.X - ovec * scrVec.Y, Y: scrpt.Y + svec * scrVec.Y + ovec * scrVec.X };
- return ptFromScreen(newscrpt);
- });
+ return !ptToScreen || !ptFromScreen
+ ? ink
+ : ink.map(ptToScreen).map(i => {
+ const pvec = { X: i.X - scrpt.X, Y: i.Y - scrpt.Y };
+ const svec = pvec.X * scrVec.X * scaling + pvec.Y * scrVec.Y * scaling;
+ const ovec = -pvec.X * scrVec.Y * (scaleUniformly ? scaling : 1) + pvec.Y * scrVec.X * (scaleUniformly ? scaling : 1);
+ const newscrpt = { X: scrpt.X + svec * scrVec.X - ovec * scrVec.Y, Y: scrpt.Y + svec * scrVec.Y + ovec * scrVec.X };
+ return ptFromScreen(newscrpt);
+ });
});
- }
+ };
/**
* Handles the movement/scaling of a control point.
@@ -230,7 +249,7 @@ export class InkStrokeProperties {
this.applyFunction(inkView, (view: DocumentView, ink: InkData) => {
const order = controlIndex % 4;
const closed = InkingStroke.IsClosed(ink);
- const brokenIndices = Cast(inkView.props.Document.brokenInkIndices, listSpec("number"), []);
+ const brokenIndices = Cast(inkView.props.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 };
@@ -238,7 +257,7 @@ export class InkStrokeProperties {
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)) return ink.slice();
const samplesLeft: Point[] = [];
const samplesRight: Point[] = [];
var startDir = { x: 0, y: 0 };
@@ -247,7 +266,7 @@ export class InkStrokeProperties {
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 === nearestSeg / 4) endDir = bez.derivative(nearestT);
- for (var t = 0; t < (i === nearestSeg / 4 ? nearestT + .05 : 1); t += 0.05) {
+ for (var 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));
}
@@ -257,7 +276,7 @@ export class InkStrokeProperties {
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(1);
- for (var t = i === nearestSeg / 4 ? nearestT : 0; t < (i === nearestSeg / 4 ? 1 + .05 + 1e-7 : 1 + 1e-7); t += 0.05) {
+ for (var 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));
}
@@ -271,12 +290,11 @@ export class InkStrokeProperties {
return ink.map((pt, i) => {
const leftHandlePoint = order === 0 && i === controlIndex + 1;
const rightHandlePoint = order === 0 && controlIndex !== 0 && i === controlIndex - 2;
- if (controlIndex === i ||
- (order === 0 && controlIndex !== 0 && i === controlIndex - 1) ||
- (order === 3 && i === controlIndex - 1)) {
- return ({ X: pt.X + deltaX, Y: pt.Y + deltaY });
+ if (controlIndex === i || (order === 0 && controlIndex !== 0 && i === controlIndex - 1) || (order === 3 && i === controlIndex - 1)) {
+ return { X: pt.X + deltaX, Y: pt.Y + deltaY };
}
- if (controlIndex === i ||
+ if (
+ controlIndex === i ||
leftHandlePoint ||
rightHandlePoint ||
(order === 0 && controlIndex !== 0 && i === controlIndex - 1) ||
@@ -284,15 +302,15 @@ export class InkStrokeProperties {
(order === 3 && i === controlIndex - 1) ||
(order === 3 && controlIndex !== ink.length - 1 && i === controlIndex + 1) ||
(order === 3 && controlIndex !== ink.length - 1 && i === controlIndex + 2) ||
- ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlIndex === 0 || controlIndex === ink.length - 1))) {
- return ({ X: pt.X + deltaX, Y: pt.Y + deltaY });
+ (ink[0].X === ink[ink.length - 1].X && ink[0].Y === ink[ink.length - 1].Y && (i === 0 || i === ink.length - 1) && (controlIndex === 0 || controlIndex === ink.length - 1))
+ ) {
+ return { X: pt.X + deltaX, Y: pt.Y + deltaY };
}
return pt;
});
- })
-
+ });
- public static nearestPtToStroke(ctrlPoints: { X: number, Y: number }[], refInkSpacePt: { X: number, Y: number }, excludeSegs?: number[]) {
+ 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;
@@ -326,16 +344,16 @@ export class InkStrokeProperties {
if (screenDragPt) {
const snapData = this.snapToAllCurves(screenDragPt, inkView, { nearestPt: { X: 0, Y: 0 }, distance: 10 }, ink, controlIndex);
if (snapData.distance < 10) {
- const deltaX = (snapData.nearestPt.X - ink[controlIndex].X);
- const deltaY = (snapData.nearestPt.Y - ink[controlIndex].Y);
+ const deltaX = snapData.nearestPt.X - ink[controlIndex].X;
+ const deltaY = snapData.nearestPt.Y - ink[controlIndex].Y;
const res = this.moveControlPtHandle(inkView, deltaX, deltaY, controlIndex, ink.slice());
- console.log("X = " + snapData.nearestPt.X + " " + snapData.nearestPt.Y);
+ console.log('X = ' + snapData.nearestPt.X + ' ' + snapData.nearestPt.Y);
return res;
}
}
}
return false;
- }
+ };
excludeSelfSnapSegs = (ink: InkData, controlIndex: number) => {
const closed = InkingStroke.IsClosed(ink);
@@ -346,9 +364,9 @@ export class InkStrokeProperties {
const nextseg = which > 1 && (closed || controlIndex < ink.length - 1) ? (thisseg + 4) % ink.length : -1;
const prevseg = which < 2 && (closed || controlIndex > 0) ? (thisseg - 4 + ink.length) % ink.length : -1;
return [thisseg, prevseg, nextseg];
- }
+ };
- snapToAllCurves = (screenDragPt: { X: number, Y: number }, inkView: DocumentView, snapData: { nearestPt: { X: number, Y: number }, distance: number }, ink: InkData, controlIndex: number) => {
+ snapToAllCurves = (screenDragPt: { X: number; Y: number }, inkView: DocumentView, snapData: { nearestPt: { X: number; Y: number }; distance: number }, ink: InkData, controlIndex: number) => {
const containingCollection = inkView.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
containingCollection?.childDocs
.filter(doc => doc.type === DocumentType.INK)
@@ -356,8 +374,7 @@ export class InkStrokeProperties {
const testInkView = DocumentManager.Instance.getDocumentView(doc, containingCollection?.props.CollectionView);
const snapped = testInkView?.ComponentView?.snapPt?.(screenDragPt, doc === inkView.rootDoc ? this.excludeSelfSnapSegs(ink, controlIndex) : []);
if (snapped && snapped.distance < snapData.distance) {
- const snappedInkPt = doc === inkView.rootDoc ? 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
+ const snappedInkPt = doc === inkView.rootDoc ? 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) {
snapData = { nearestPt: snappedInkPt, distance: snapped.distance };
@@ -365,7 +382,7 @@ export class InkStrokeProperties {
}
});
return snapData;
- }
+ };
/**
* Snaps a control point with broken tangency back to synced rotation.
@@ -375,7 +392,7 @@ export class InkStrokeProperties {
snapHandleTangent = (inkView: DocumentView, controlIndex: number, handleIndexA: number, handleIndexB: number) => {
this.applyFunction(inkView, (view: DocumentView, ink: InkData) => {
const doc = view.rootDoc;
- const brokenIndices = Cast(doc.brokenInkIndices, listSpec("number"), []);
+ const brokenIndices = Cast(doc.brokenInkIndices, listSpec('number'), []);
const ind = brokenIndices.findIndex(value => value === controlIndex);
if (ind !== -1) {
brokenIndices.splice(ind, 1);
@@ -387,7 +404,7 @@ export class InkStrokeProperties {
return inkCopy;
}
});
- }
+ };
/**
* Rotates the target point about the origin point for a given angle (radians).
@@ -398,11 +415,11 @@ export class InkStrokeProperties {
const newX = Math.cos(angle) * rotatedTarget.X - Math.sin(angle) * rotatedTarget.Y;
const newY = Math.sin(angle) * rotatedTarget.X + Math.cos(angle) * rotatedTarget.Y;
return { X: newX + origin.X, Y: newY + origin.Y };
- }
+ };
/**
* Finds the angle (in radians) between two inputted vectors.
- *
+ *
* α = arccos(a·b / |a|·|b|), where a and b are both vectors.
*/
public static angleBetweenTwoVectors(vectorA: PointData, vectorB: PointData) {
@@ -444,14 +461,13 @@ export class InkStrokeProperties {
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 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))) {
+ 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;
- })
-} \ No newline at end of file
+ });
+}