diff options
Diffstat (limited to 'src/client/views/GestureOverlay.tsx')
| -rw-r--r-- | src/client/views/GestureOverlay.tsx | 152 |
1 files changed, 86 insertions, 66 deletions
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 0c797adf2..c1ac3ab06 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -33,8 +33,6 @@ import { returnEmptyDocViewList } from './StyleProvider'; import { ActiveFillColor, DocumentView } from './nodes/DocumentView'; import { CollectionFreeFormView } from './collections/collectionFreeForm'; import { InkingStroke } from './InkingStroke'; -import { NullLiteral } from 'typescript'; -import { isNull } from 'lodash'; export enum ToolglassTools { InkToText = 'inktotext', IgnoreGesture = 'ignoregesture', @@ -45,10 +43,12 @@ interface GestureOverlayProps { isActive: boolean; } @observer +/** + * class for gestures. will determine if what the user drew is a gesture, and will transform the ink stroke into the shape the user + * drew or perform the gesture's action + */ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChildren<GestureOverlayProps>> { - // eslint-disable-next-line no-use-before-define static Instance: GestureOverlay; - // eslint-disable-next-line no-use-before-define static Instances: GestureOverlay[] = []; @observable public InkShape: Opt<Gestures> = undefined; @@ -131,20 +131,24 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil // SetActiveArrowEnd('none'); } } - isScribble(inkPoints: any) { + /** + * this method returns if what the user drew is a scribble. if it is, it will determine what documents need + * to be deleted and then it will delete them. + * @returns + */ + isScribble() { const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView); - const points = this._points.map(p => ({ X: p.X, Y: p.Y })); - const cuspArray = this.getNumberOfCusps(points); - let cuspBooleanArray: boolean[] = []; - let docsToDelete: Doc[] = []; + const cuspArray = this.getCusps(); + const cuspBooleanArray: boolean[] = []; + const docsToDelete: Doc[] = []; const childDocs = (ffView?.ComponentView as CollectionFreeFormView).childDocs; 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) { - console.log('there are enough cusps'); for (let i = 0; i < cuspArray.length - 2; i++) { let hasDocInTriangle = false; - for (let doc of childDocs) { + for (const doc of childDocs) { const point1 = cuspArray[i]; const point2 = cuspArray[i + 1]; const point3 = cuspArray[i + 2]; @@ -152,9 +156,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil const otherInk = DocumentView.getDocumentView(doc)?.ComponentView as InkingStroke; const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] }; const otherScreenPts = otherInkData.map(point => otherInk.ptToScreen(point)); - console.log(otherScreenPts); - console.log((DocumentView.getDocumentView(doc)?.ComponentView as InkingStroke).inkScaledData().inkData.map(point => ({ X: point.X, Y: point.Y }))); - console.log(triangleObject); if (doc.title === 'line') { if (this.doesLineIntersectTriangle(otherScreenPts, triangleObject)) { docsToDelete.push(doc); @@ -182,6 +183,12 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil } return false; } + /** + * this method determines if what the user drew is a scribble based on certain criteria. + * @param cuspBooleanArray will take in an array of booleans tht represent what triangles in the scribble + * has an object in it. the 1st triangle is the 0th index, 2nd triangle is the 1st index and so on. + * @returns + */ determineIfScribble(cuspBooleanArray: boolean[]) { if (!cuspBooleanArray) { return false; @@ -193,21 +200,29 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil hasObjectInFirstAndLast25 = false; } } - console.log(cuspBooleanArray); - console.log(hasObjectInFirstAndLast25); const trueCount = cuspBooleanArray.filter(value => value).length; const percentageTrues = trueCount / cuspBooleanArray.length; - if (percentageTrues > 0.65 || hasObjectInFirstAndLast25) { - console.log('requirements are met'); - } return percentageTrues > 0.65 || hasObjectInFirstAndLast25; } + /** + * determines if two rectangles are overlapping each other + * @param rect1 the rectangle object has has a minX,maxX,minY, and maxY + * @param rect2 + * @returns + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any isRectangleOverlap(rect1: any, rect2: any): boolean { const noOverlap = rect1.maxX < rect2.minX || rect1.minX > rect2.maxX || rect1.maxY < rect2.minY || rect1.minY > rect2.maxY; return !noOverlap; } - isPointInTriangle(pt: { X: number; Y: number }, triangle: any): boolean { + /** + * 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); @@ -218,16 +233,29 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil 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) { - //console.log(point.X + ' ' + point.Y); - //console.log(triangle); 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 + * @param triangle triangle with 3 points + * @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 }, @@ -243,6 +271,14 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil return false; } + /** + * used in doesLineIntersectTriangle, splits up the triangle into 3 lines and runs this method + * individually + * @param line1 point data where 0th index is the coordinate of beginnning of line and last index is the coordinate of end of limne + * @param line2 same thing + * @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]; @@ -260,7 +296,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil } @action onPointerUp = () => { - console.log('pointer up'); DocumentView.DownDocView = undefined; if (this._points.length > 1) { const B = this.svgBounds; @@ -277,7 +312,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil // need to decide when to turn gestures back on const result = points.length > 2 && GestureUtils.GestureRecognizer.Recognize([points]); let actionPerformed = false; - //console.log(result); if (Doc.UserDoc().recognizeGestures && result && result.Score > 0.7) { switch (result.Name) { case Gestures.Line: @@ -286,21 +320,17 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil case Gestures.Circle: this.makeBezierPolygon(result.Name, true); actionPerformed = this.dispatchGesture(result.Name); - console.log(result.Name); - console.log(); break; case Gestures.Scribble: - console.log('scribble'); break; case Gestures.RightAngle: this.convertToText(); this._points = []; - console.log('RightAngle'); return; default: } } - if (this.isScribble(points)) { + if (this.isScribble()) { this._points = []; return; } @@ -323,7 +353,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil const dist = Math.sqrt( (controlPoints[0].X - controlPoints.lastElement().X) * (controlPoints[0].X - controlPoints.lastElement().X) + (controlPoints[0].Y - controlPoints.lastElement().Y) * (controlPoints[0].Y - controlPoints.lastElement().Y) ); - // eslint-disable-next-line prefer-destructuring if (controlPoints.length > 4 && dist < 10) controlPoints[controlPoints.length - 1] = controlPoints[0]; this._points.length = 0; this._points.push(...controlPoints); @@ -333,9 +362,12 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil } this._points.length = 0; }; + /** + * used in the rightAngle gesture to convert handwriting into text. will only work on collections + * TODO: make it work on individual ink docs. + */ convertToText() { const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView); - let docsToBeConverted: Doc[] = []; let minX = 999999999; let maxX = -999999999; let minY = 999999999; @@ -345,15 +377,9 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil .forEach(doc => { if (typeof doc.width === 'number' && typeof doc.height === 'number' && typeof doc.x === 'number' && typeof doc.y === 'number') { const bounds = DocumentView.getDocumentView(doc)?.getBounds; - console.log(DocumentView.getDocumentView(doc)); - console.log(bounds); if (bounds) { const rect1 = { minX: bounds.left, maxX: bounds.right, minY: bounds.top, maxY: bounds.bottom }; - console.log(rect1); - console.log(this.getExtremeCoordinates(this._points)); - const points = this._points.map(p => ({ X: p.X, Y: p.Y })); - console.log(points); - if (this.isRectangleOverlap(rect1, this.getExtremeCoordinates(this._points))) { + if (this.isRectangleOverlap(rect1, this.getExtremeCoordinates())) { if (doc.x < minX) { minX = doc.x; } @@ -373,35 +399,23 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil ffView.ComponentView.addDocument(newDoc); ffView.ComponentView.removeDocument(doc); } - //docsToBeConverted.push(doc); } } } }); - // const collectionDoc = Docs.Create.FreeformDocument(docsToBeConverted, { title: '', x: minX as number, y: maxY as number }); - // collectionDoc.height = 50; - // collectionDoc.width = 50; - // if (ffView?.ComponentView?.addDocument) { - // ffView.ComponentView.addDocument(collectionDoc); - // } - // DocumentView.getDocumentView(collectionDoc)?.ComponentView?.updateIcon; - // const newDoc = Docs.Create.TextDocument(doc.transcription as string, { title: '', x: doc.x as number, y: maxY }); - // newDoc.height = 50; - // if (ffView?.ComponentView?.addDocument) { - // ffView.ComponentView.addDocument(newDoc); - // } } - getNumberOfCusps(points: any) { - let arrayOfPoints: any[] = []; + /** + * 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 })); + const arrayOfPoints: { X: number; Y: number }[] = []; arrayOfPoints.push(points[0]); for (let i = 0; i < points.length - 2; i++) { const point1 = points[i]; const point2 = points[i + 1]; const point3 = points[i + 2]; - // console.log(point1); - // console.log(point2); - // console.log(point3); - // console.log(this.find_angle(point1, point2, point3)); if (this.find_angle(point1, point2, point3) < 90) { arrayOfPoints.push(point2); } @@ -409,7 +423,12 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil arrayOfPoints.push(points[points.length - 1]); return arrayOfPoints; } - getExtremeCoordinates(coordinates: any[]) { + /** + * 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; if (coordinates.length === 0) { throw new Error('Coordinates array is empty'); } @@ -432,10 +451,15 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil maxY, }; } - find_angle(A: any, B: any, C: any) { - let AB = Math.sqrt(Math.pow(B.X - A.X, 2) + Math.pow(B.Y - A.Y, 2)); - let BC = Math.sqrt(Math.pow(B.X - C.X, 2) + Math.pow(B.Y - C.Y, 2)); - let AC = Math.sqrt(Math.pow(C.X - A.X, 2) + Math.pow(C.Y - A.Y, 2)); + /** + * takes in three points and then determines the angle of the points. used to determine if the cusp + * is sharp enoug + * @returns + */ + find_angle(A: { X: number; Y: number }, B: { X: number; Y: number }, C: { X: number; Y: number }) { + const AB = Math.sqrt(Math.pow(B.X - A.X, 2) + Math.pow(B.Y - A.Y, 2)); + const BC = Math.sqrt(Math.pow(B.X - C.X, 2) + Math.pow(B.Y - C.Y, 2)); + const AC = Math.sqrt(Math.pow(C.X - A.X, 2) + Math.pow(C.Y - A.Y, 2)); return Math.acos((BC * BC + AB * AB - AC * AC) / (2 * BC * AB)) * (180 / Math.PI); } makeBezierPolygon = (shape: string, gesture: boolean) => { @@ -636,7 +660,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil this._strokes.map((l, i) => { const b = { left: -20000, right: 20000, top: -20000, bottom: 20000, width: 40000, height: 40000 }; // this.getBounds(l, true); return ( - // eslint-disable-next-line react/no-array-index-key <svg key={i} width={b.width} height={b.height} style={{ top: 0, left: 0, transform: `translate(${b.left}px, ${b.top}px)`, pointerEvents: 'none', position: 'absolute', zIndex: 30000, overflow: 'visible' }}> {InteractionUtils.CreatePolyline( l, @@ -758,7 +781,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil } ScriptingGlobals.add('GestureOverlay', GestureOverlay); -// eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setPen(width: string, color: string, fill: string, arrowStart: string, arrowEnd: string, dash: string) { runInAction(() => { GestureOverlay.Instance.SavedColor = ActiveInkColor(); @@ -771,7 +793,6 @@ ScriptingGlobals.add(function setPen(width: string, color: string, fill: string, SetActiveDash(dash); }); }); -// eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function resetPen() { runInAction(() => { SetActiveInkColor(GestureOverlay.Instance.SavedColor ?? 'rgb(0, 0, 0)'); @@ -779,7 +800,6 @@ ScriptingGlobals.add(function resetPen() { }); }, 'resets the pen tool'); ScriptingGlobals.add( - // eslint-disable-next-line prefer-arrow-callback function createText(text: string, X: number, Y: number) { GestureOverlay.Instance.dispatchGesture(Gestures.Text, [{ X, Y }], text); }, |
