aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/InkStrokeProperties.ts
diff options
context:
space:
mode:
authorvkalev <vjk1883@gmail.com>2021-07-10 11:13:42 -0500
committervkalev <vjk1883@gmail.com>2021-07-10 11:13:42 -0500
commit8bc17cecdfce184e5a426dc2332d3c9ad0406f58 (patch)
treeb93de76fb5cf384b973fa9747ea466114b571bf7 /src/client/views/InkStrokeProperties.ts
parent5ab81f49a11bd8a74725228a887a90c88a3848ff (diff)
fixed adding point bug with breaking handle tangency
Diffstat (limited to 'src/client/views/InkStrokeProperties.ts')
-rw-r--r--src/client/views/InkStrokeProperties.ts69
1 files changed, 51 insertions, 18 deletions
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index 812e8ff6e..4ec03c560 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -1,7 +1,7 @@
import { action, computed, observable } from "mobx";
import { Doc, Field, Opt } from "../../fields/Doc";
import { Document } from "../../fields/documentSchemas";
-import { InkField, InkData, PointData } from "../../fields/InkField";
+import { InkField, InkData, PointData, ControlPoint } from "../../fields/InkField";
import { Cast, NumCast } from "../../fields/Types";
import { DocumentType } from "../documents/DocumentTypes";
import { SelectionManager } from "../util/SelectionManager";
@@ -13,6 +13,7 @@ export class InkStrokeProperties {
@observable _lock = false;
@observable _controlButton = false;
@observable _currentPoint = -1;
+ @observable _brokenIndices: number[] = [];
constructor() {
InkStrokeProperties.Instance = this;
@@ -73,6 +74,7 @@ export class InkStrokeProperties {
addPoints = (x: number, y: number, pts: { X: number, Y: number }[], index: number, control: { X: number, Y: number }[]) => {
this.selectedInk?.forEach(action(inkView => {
if (this.selectedInk?.length === 1) {
+ const newPoint = { X: x, Y: y };
const doc = Document(inkView.rootDoc);
if (doc.type === DocumentType.INK) {
const ink = Cast(doc.data, InkField)?.inkData;
@@ -88,12 +90,25 @@ export class InkStrokeProperties {
for (var i = 0; i < spNum; i++) {
ink[i] && newPoints.push({ X: ink[i].X, Y: ink[i].Y });
}
- for (var j = 0; j < 4; j++) {
- newPoints.push({ X: x, Y: y });
- }
+ // Updating the indices of the control points whose handle tangency has been broken.
+ this._brokenIndices = this._brokenIndices.map((control) => {
+ if (control >= spNum) {
+ return control + 4;
+ } else {
+ return control;
+ }
+ });
+
+ // const [handleA, handleB] = this.getNewHandlePoints(newPoint, pts[index-1], pts[index+1]);
+ newPoints.push(newPoint);
+ newPoints.push(newPoint);
+ newPoints.push(newPoint);
+ newPoints.push(newPoint);
+
for (var i = spNum; i < ink.length; i++) {
newPoints.push({ X: ink[i].X, Y: ink[i].Y });
+
}
this._currentPoint = -1;
Doc.GetProto(doc).data = new InkField(newPoints);
@@ -103,6 +118,20 @@ export class InkStrokeProperties {
}));
}
+ getNewHandlePoints = (newControl: PointData, a: PointData, b: PointData) => {
+ // find midpoint between the left and right control point of new control
+ // rotate midpoint by +-pi/2 to get new handle points
+ // multiplying x-y coordinates of both by 10/L where L is its current magnitude
+ const angle = this.angleChange(a, b, newControl);
+ const midpoint = this.rotatePoint(a, newControl, angle/2);
+ // const handleA = this.rotatePoint(midpoint, newControl, -Math.PI/2);
+ // const handleB = this.rotatePoint(midpoint, newControl, -Math.PI/2);
+ const handleA = { X: midpoint.X + (20 * Math.cos(-Math.PI/2)), Y: midpoint.Y + (20 * Math.sin(-Math.PI/2)) };
+ const handleB = { X: midpoint.X + (20 * Math.cos(Math.PI/2)), Y: midpoint.Y + (20 * Math.sin(Math.PI/2)) };
+
+ return [handleA, handleB];
+ }
+
/**
* Deletes the points of the current ink instance.
* @returns The changed x- and y-coordinates of the control points.
@@ -195,23 +224,27 @@ export class InkStrokeProperties {
return target;
}
+ angleBetweenTwoVectors = (vectorA: PointData, vectorB: PointData) => {
+ const magnitudeA = Math.sqrt(vectorA.X * vectorA.X + vectorA.Y * vectorA.Y);
+ const magnitudeB = Math.sqrt(vectorB.X * vectorB.X + vectorB.Y * vectorB.Y);
+ // Normalizing the vectors.
+ vectorA = { X: vectorA.X / magnitudeA, Y: vectorA.Y / magnitudeA };
+ vectorB = { X: vectorB.X / magnitudeB, Y: vectorB.Y / magnitudeB };
+ const dotProduct = vectorB.X * vectorA.X + vectorB.Y * vectorA.Y;
+ return Math.acos(dotProduct);
+ }
+
/**
* Finds the angle difference (in radians) between two vectors relative to an arbitrary origin.
*/
angleChange = (a: PointData, b: PointData, origin: PointData) => {
// Finding vector representation of inputted points relative to new origin.
- let vectorA = { X: a.X - origin.X, Y: a.Y - origin.Y };
- let vectorB = { X: b.X - origin.X, Y: b.Y - origin.Y };
+ const vectorA = { X: a.X - origin.X, Y: a.Y - origin.Y };
+ const vectorB = { X: b.X - origin.X, Y: b.Y - origin.Y };
const crossProduct = vectorB.X * vectorA.Y - vectorB.Y * vectorA.X;
// Determining whether rotation is clockwise or counterclockwise.
const sign = crossProduct < 0 ? 1 : -1;
- const magnitudeA = Math.sqrt(vectorA.X * vectorA.X + vectorA.Y * vectorA.Y);
- const magnitudeB = Math.sqrt(vectorB.X * vectorB.X + vectorB.Y * vectorB.Y);
- // Normalizing the vectors.
- vectorA = { X: vectorA.X / magnitudeA, Y: vectorA.Y / magnitudeA };
- vectorB = { X: vectorB.X / magnitudeB, Y: vectorB.Y / magnitudeB };
- const dotProduct = vectorB.X * vectorA.X + vectorB.Y * vectorA.Y;
- const theta = Math.acos(dotProduct);
+ const theta = this.angleBetweenTwoVectors(vectorA, vectorB);
return sign * theta;
}
@@ -220,20 +253,20 @@ export class InkStrokeProperties {
*/
@undoBatch
@action
- moveHandle = (deltaX: number, deltaY: number, handleIndex: number, brokenIndices: number[]) =>
+ moveHandle = (deltaX: number, deltaY: number, handleIndex: number, oppositeHandleIndex: number, controlIndex: number) =>
this.applyFunction((doc: Doc, ink: InkData, xScale: number, yScale: number) => {
const order = handleIndex % 4;
const oldHandlePoint = ink[handleIndex];
+ let oppositeHandlePoint = ink[oppositeHandleIndex];
+ const controlPoint = ink[controlIndex];
const newHandlePoint = { X: ink[handleIndex].X - deltaX / xScale, Y: ink[handleIndex].Y - deltaY / yScale };
ink[handleIndex] = newHandlePoint;
// Rotate opposite handle if user hasn't held 'Alt' key or not first/final control (which have only 1 handle).
- if (!brokenIndices.includes(handleIndex) && handleIndex !== 1 && handleIndex !== ink.length - 2) {
- let oppositeHandlePoint = order === 1 ? ink[handleIndex - 3] : ink[handleIndex + 3];
- const controlPoint = order === 1 ? ink[handleIndex - 1] : ink[handleIndex + 1];
+ if (!this._brokenIndices.includes(controlIndex) && handleIndex !== 1 && handleIndex !== ink.length - 2) {
const angle = this.angleChange(oldHandlePoint, newHandlePoint, controlPoint);
oppositeHandlePoint = this.rotatePoint(oppositeHandlePoint, controlPoint, angle);
- order === 1 ? ink[handleIndex - 3] = oppositeHandlePoint : ink[handleIndex + 3] = oppositeHandlePoint;
+ ink[oppositeHandleIndex] = oppositeHandlePoint;
}
return ink;