aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/GestureOverlay.tsx196
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx1
2 files changed, 91 insertions, 106 deletions
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 935eeb251..7e396d475 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -1,4 +1,5 @@
import * as fitCurve from 'fit-curve';
+import { Bezier } from 'bezier-js';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -95,7 +96,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
componentDidMount() {
GestureOverlay.Instance = this;
}
-
@action
onPointerDown = (e: React.PointerEvent) => {
if (!(e.target as HTMLElement)?.className?.toString().startsWith('lm_')) {
@@ -139,52 +139,52 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
* to be deleted and then it will delete them.
* @returns
*/
- isScribble() {
+ isScribble(inkData: InkData) {
const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView);
- const cuspArray = this.getCusps();
- const cuspBooleanArray: boolean[] = [];
+ console.log(inkData.map(ink => ({ x: ink.X, y: ink.Y })));
+ let intersectArray: boolean[] = [];
+ const cuspArray = this.getCusps(inkData);
+ console.log(cuspArray.length);
+ for (let i = 0; i < cuspArray.length; i++) {
+ intersectArray[i] = false;
+ }
const docsToDelete: Doc[] = [];
- const childDocs = (ffView?.ComponentView as CollectionFreeFormView).childDocs;
+ const childDocs = (ffView?.ComponentView as CollectionFreeFormView).childDocs.slice(0, -1);
childDocs.filter(doc => doc.type === 'ink').map(doc => DocumentView.getDocumentView(doc, DocumentView.getDocumentView(doc)));
if ((ffView?.ComponentView as CollectionFreeFormView).childDocs) {
//how many cusps the scribble hsa
- if (cuspArray.length > 4) {
- for (let i = 0; i < cuspArray.length - 2; i++) {
- let hasDocInTriangle = false;
- for (const doc of childDocs) {
- const point1 = cuspArray[i];
- const point2 = cuspArray[i + 1];
- const point3 = cuspArray[i + 2];
- const triangleObject = { p1: { X: point1.X, Y: point1.Y }, p2: { X: point2.X, Y: point2.Y }, p3: { X: point3.X, Y: point3.Y } };
- const otherInk = DocumentView.getDocumentView(doc)?.ComponentView as InkingStroke;
- if (otherInk instanceof InkingStroke) {
- const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] };
- const otherScreenPts = otherInkData.map(point => otherInk.ptToScreen(point));
- if (doc.title === 'line') {
- if (this.doesLineIntersectTriangle(otherScreenPts, triangleObject)) {
- docsToDelete.push(doc);
- hasDocInTriangle = true;
- cuspBooleanArray.push(true);
- }
+ for (const doc of childDocs) {
+ const otherInk = DocumentView.getDocumentView(doc)?.ComponentView as InkingStroke;
+ if (otherInk instanceof InkingStroke) {
+ const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] };
+ const otherScreenPts = otherInkData.map(point => otherInk.ptToScreen(point));
+ if (this.isRectangleOverlap(this.getExtremeCoordinates(otherScreenPts), this.getExtremeCoordinates(inkData))) {
+ console.log('somethings in');
+ const intersects = this.doInksIntersect(inkData, otherScreenPts);
+ console.log(intersects);
+ intersects.forEach(intersect => {
+ let percentage = '';
+ if (intersect.includes('/')) {
+ const leftOfSlash = intersect.split('/')[0];
+ percentage = leftOfSlash;
} else {
- if (this.isAnyPointInTriangle(triangleObject, otherScreenPts)) {
- docsToDelete.push(doc);
- hasDocInTriangle = true;
- cuspBooleanArray.push(true);
- }
+ percentage = intersect;
}
- }
+ intersectArray[Math.floor((percentage as unknown as number) * cuspArray.length)] = true;
+ docsToDelete.push(doc);
+ });
}
- cuspBooleanArray.push(hasDocInTriangle);
- }
- if (this.determineIfScribble(cuspBooleanArray)) {
- docsToDelete.forEach(doc => {
- ffView?.ComponentView?.removeDocument?.(doc);
- });
- this._points = [];
- return true;
}
}
+ console.log(intersectArray);
+ if (intersectArray.length > 3 && this.determineIfScribble(intersectArray)) {
+ console.log('is a scribble');
+ docsToDelete.forEach(doc => {
+ ffView?.ComponentView?.removeDocument?.(doc);
+ });
+ this._points = [];
+ return true;
+ }
}
return false;
}
@@ -198,7 +198,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
if (!cuspBooleanArray) {
return false;
}
- const quarterArrayLength = Math.ceil((cuspBooleanArray.length - 2) * 0.25);
+ const quarterArrayLength = Math.ceil((cuspBooleanArray.length - 2) * 0.3);
let hasObjectInFirstAndLast25 = true;
for (let i = 0; i < quarterArrayLength; i++) {
if (cuspBooleanArray[i] == false || cuspBooleanArray[cuspBooleanArray.length - 1 - i] == false) {
@@ -207,7 +207,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
}
const trueCount = cuspBooleanArray.filter(value => value).length;
const percentageTrues = trueCount / cuspBooleanArray.length;
- return percentageTrues > 0.65 || hasObjectInFirstAndLast25;
+ return percentageTrues > 0.5 || hasObjectInFirstAndLast25;
}
/**
* determines if two rectangles are overlapping each other
@@ -222,38 +222,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
return !noOverlap;
}
/**
- * determines if there is a point in a triangle used to determine what triangles in the scribble have an object
- * @param pt the point in question
- * @param triangle the triangle with 3 points
- * @returns true or false if point is in triangle
- */
- isPointInTriangle(pt: { X: number; Y: number }, triangle: { p1: { X: number; Y: number }; p2: { X: number; Y: number }; p3: { X: number; Y: number } }): boolean {
- const area = (v1: { X: number; Y: number }, v2: { X: number; Y: number }, v3: { X: number; Y: number }) => Math.abs((v1.X * (v2.Y - v3.Y) + v2.X * (v3.Y - v1.Y) + v3.X * (v1.Y - v2.Y)) / 2.0);
-
- const A = area(triangle.p1, triangle.p2, triangle.p3);
-
- const A1 = area(pt, triangle.p2, triangle.p3);
- const A2 = area(triangle.p1, pt, triangle.p3);
- const A3 = area(triangle.p1, triangle.p2, pt);
-
- return A === A1 + A2 + A3;
- }
- /**
- * determines if any points in an array are in a triangle
- * @param triangle the triangle with 3 points
- * @param points the point in question
- * @returns true or false if point is in triangle
- */
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- isAnyPointInTriangle(triangle: any, points: any[]): boolean {
- for (const point of points) {
- if (this.isPointInTriangle(point, triangle)) {
- return true;
- }
- }
- return false;
- }
- /**
* determines if a line intersects a triangle. used for scribble gesture since the line doesnt have a lot
* of points across is so isPointInTriangle will not work for it.
* @param line is pointData
@@ -261,20 +229,25 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
* @returns true or false if it intersects
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- doesLineIntersectTriangle(line: any, triangle: any): boolean {
- const edges = [
- { start: triangle.p1, end: triangle.p2 },
- { start: triangle.p2, end: triangle.p3 },
- { start: triangle.p3, end: triangle.p1 },
- ];
-
- for (const edge of edges) {
- if (this.doLinesIntersect(line, edge)) {
- return true;
+ doInksIntersect(scribble: InkData, inkStroke: InkData): string[] {
+ let intersectArray: string[] = [];
+ const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView);
+ if (ffView && ffView.ComponentView instanceof CollectionFreeFormView) {
+ for (let i = 0; i < scribble.length - 3; i += 4) {
+ // iterate over each segment of bezier curve
+ for (let j = 0; j < inkStroke.length - 3; j += 4) {
+ const intersectCurve: Bezier = InkField.Segment(scribble, i); // other curve
+ const eraserCurve: Bezier = InkField.Segment(inkStroke, j); // eraser curve
+ if (ffView && ffView.ComponentView instanceof CollectionFreeFormView) {
+ const result = (ffView.ComponentView as CollectionFreeFormView).bintersects(intersectCurve, eraserCurve)[0];
+ if (result !== undefined) {
+ intersectArray.push(result.toString());
+ }
+ }
+ }
}
}
-
- return false;
+ return intersectArray;
}
/**
* used in doesLineIntersectTriangle, splits up the triangle into 3 lines and runs this method
@@ -284,20 +257,21 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
* @returns
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- doLinesIntersect(line1: any, line2: any): boolean {
- const A = line1[0];
- const B = line1[line1.length - 1];
- const { start: C, end: D } = line2;
- const denominator = (B.X - A.X) * (D.Y - C.Y) - (B.Y - A.Y) * (D.X - C.X);
- if (denominator === 0) return false;
-
- const numerator1 = (A.Y - C.Y) * (D.X - C.X) - (A.X - C.X) * (D.Y - C.Y);
- const numerator2 = (A.Y - C.Y) * (B.X - A.X) - (A.X - C.X) * (B.Y - A.Y);
-
- const r = numerator1 / denominator;
- const s = numerator2 / denominator;
-
- return r >= 0 && r <= 1 && s >= 0 && s <= 1;
+ doLinesIntersect(points: any, line: any): boolean {
+ const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView);
+ if (ffView && ffView.ComponentView instanceof CollectionFreeFormView) {
+ for (let i = 0; i < points.length - 3; i += 4) {
+ // iterate over each segment of bezier curve
+ for (let j = 0; j < line.length - 3; j += 4) {
+ const intersectCurve: Bezier = InkField.Segment(points, i); // other curve
+ const eraserCurve: Bezier = InkField.Segment(line, j); // eraser curve
+ if (ffView && ffView.ComponentView instanceof CollectionFreeFormView) {
+ //(ffView.ComponentView as CollectionFreeFormView).bintersects();
+ }
+ }
+ }
+ }
+ return false;
}
dryInk = () => {
@@ -343,18 +317,31 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
case Gestures.Rectangle:
case Gestures.Circle:
this.makeBezierPolygon(Name, true);
+ setTimeout(() => {
+ const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView);
+ const scribbleInk = (ffView?.ComponentView as CollectionFreeFormView).childDocs[(ffView?.ComponentView as CollectionFreeFormView).childDocs.length - 1];
+ //this.isScribble((DocumentView.getDocumentView(scribbleInk)?.ComponentView as InkingStroke).inkScaledData().inkData);
+ }, 1);
return this.dispatchGesture(name);
case Gestures.RightAngle:
return this.convertToText().length > 0;
default:
- case Gestures.Stroke:
- return this.isScribble();
}
})(Score < 0.7 ? Gestures.Stroke : (Name as Gestures));
// if no gesture (or if the gesture was unsuccessful), "dry" the stroke into an ink document
- if (!actionPerformed) this.dryInk();
+ if (!actionPerformed) {
+ this.dryInk();
+ setTimeout(() => {
+ const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView);
+ const scribbleInk = (ffView?.ComponentView as CollectionFreeFormView).childDocs[(ffView?.ComponentView as CollectionFreeFormView).childDocs.length - 1];
+ if (this.isScribble((DocumentView.getDocumentView(scribbleInk)?.ComponentView as InkingStroke).inkScaledData().inkData)) {
+ ffView?.ComponentView?.removeDocument?.(scribbleInk);
+ }
+ }, 1);
+ }
}
this._points.length = 0;
+ //console.log((DocumentView.getDocumentView(scribbleInk)?.ComponentView as InkingStroke).inkScaledData());
};
/**
* used in the rightAngle gesture to convert handwriting into text. will only work on collections
@@ -374,7 +361,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
const bounds = DocumentView.getDocumentView(doc)?.getBounds;
if (bounds) {
const rect1 = { minX: bounds.left, maxX: bounds.right, minY: bounds.top, maxY: bounds.bottom };
- if (this.isRectangleOverlap(rect1, this.getExtremeCoordinates())) {
+ if (this.isRectangleOverlap(rect1, this.getExtremeCoordinates(this._points))) {
if (doc.x < minX) {
minX = doc.x;
}
@@ -405,8 +392,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
* used to determine how many cusps and where the cusps are in order
* @returns will return an array containing the coordinates of the sharp cusps
*/
- getCusps() {
- const points = this._points.map(p => ({ X: p.X, Y: p.Y }));
+ getCusps(points: InkData) {
const arrayOfPoints: { X: number; Y: number }[] = [];
arrayOfPoints.push(points[0]);
for (let i = 0; i < points.length - 2; i++) {
@@ -424,8 +410,8 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
* will look through an array of point data and return the coordinates of the smallest box that can fit all the points
* @returns the minX,maxX,minY,maxY of the box
*/
- getExtremeCoordinates() {
- const coordinates = this._points;
+ getExtremeCoordinates(points: { X: number; Y: number }[]) {
+ const coordinates = points;
if (coordinates.length === 0) {
throw new Error('Coordinates array is empty');
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index e63c00f17..3e2c55114 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -889,7 +889,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
strokeToTVals.set(inkView, [Math.floor(inkData.length / 4) + 1]);
}
}
-
for (let i = 0; i < inkData.length - 3; i += 4) {
// iterate over each segment of bezier curve
for (let j = 0; j < eraserInkData.length - 3; j += 4) {