diff options
author | Lauren <victor_kalev@brown.edu> | 2021-10-26 15:51:02 -0400 |
---|---|---|
committer | Lauren <victor_kalev@brown.edu> | 2021-10-26 15:51:02 -0400 |
commit | 2155d39fbc4a9bac3945e40ee10f95f41df466d3 (patch) | |
tree | 03c8688e46a79ab6f685e0dc136533fa1719e5d6 /src | |
parent | bf896f7f7c287c9a78cca91d7ceab88f66613b61 (diff) |
refactoring snapping slightly
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/InkStrokeProperties.ts | 74 |
1 files changed, 48 insertions, 26 deletions
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index ba85b851c..712459125 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -1,6 +1,7 @@ import { Bezier } from "bezier-js"; import { action, computed, observable, reaction } from "mobx"; import { Doc } from "../../fields/Doc"; +import { DocumentView } from "./nodes/DocumentView"; import { Document } from "../../fields/documentSchemas"; import { InkData, InkField, InkTool, PointData } from "../../fields/InkField"; import { List } from "../../fields/List"; @@ -232,43 +233,64 @@ export class InkStrokeProperties { return { distance, nearestT, nearestSeg, nearestPt }; } - /** - * Handles the movement/scaling of a control point. - */ snapControl = (inkDoc: Doc, controlIndex: number) => { const ink = Cast(inkDoc.data, InkField)?.inkData; - if (ink) { - const closed = InkingStroke.IsClosed(ink); - - // figure out which segments we don't want to snap to - avoid the dragged control point's segment and the next and prev segments (when they exist -- ie not for endpoints of unclosed curve) - const thisseg = Math.floor(controlIndex / 4) * 4; - const which = controlIndex % 4; - 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; - const refPt = ink[controlIndex]; - const { nearestPt } = InkStrokeProperties.nearestPtToStroke(ink, refPt, [thisseg, prevseg, nextseg]); - - // nearestPt is in inkDoc coordinates -- we need to compute the distance in screen coordinates. - // so we scale the X & Y distances by the internal ink scale factor and then transform the final distance by the ScreenToLocal.Scale of the inkDoc itself. - const oldXrange = (xs => ({ coord: NumCast(inkDoc.x), min: Math.min(...xs), max: Math.max(...xs) }))(ink.map(p => p.X)); - const oldYrange = (ys => ({ coord: NumCast(inkDoc.y), min: Math.min(...ys), max: Math.max(...ys) }))(ink.map(p => p.Y)); - const ptsXscale = ((NumCast(inkDoc._width) - NumCast(inkDoc.strokeWidth)) / ((oldXrange.max - oldXrange.min) || 1)) || 1; - const ptsYscale = ((NumCast(inkDoc._height) - NumCast(inkDoc.strokeWidth)) / ((oldYrange.max - oldYrange.min) || 1)) || 1; - const near = Math.sqrt((nearestPt.X - refPt.X) * (nearestPt.X - refPt.X) * ptsXscale * ptsXscale + - (nearestPt.Y - refPt.Y) * (nearestPt.Y - refPt.Y) * ptsYscale * ptsYscale); + if (ink) { + const { near, nearestPt, ptsXscale, ptsYscale } = this.snapWithinCurve(ink, inkDoc, controlIndex); if (near / (this.selectedInk?.lastElement().props.ScreenToLocalTransform().Scale || 1) < 10) { - return this.moveControlPtHandle((nearestPt.X - ink[controlIndex].X) * ptsXscale, (nearestPt.Y - ink[controlIndex].Y) * ptsYscale, controlIndex); + const deltaX = (nearestPt.X - ink[controlIndex].X) * ptsXscale; + const deltaY = (nearestPt.Y - ink[controlIndex].Y) * ptsYscale; + return this.moveControlPtHandle(deltaX, deltaY, controlIndex); } else { - return + return this.snapBetweenCurves(ink, inkDoc, controlIndex); } } return false; } - // snapControlBetweenCurves = (ink, controlIndex) => { + snapWithinCurve = (ink: InkData, inkDoc: Doc, controlIndex: number) => { + const closed = InkingStroke.IsClosed(ink); + + // figure out which segments we don't want to snap to - avoid the dragged control point's segment and the next and prev segments (when they exist -- ie not for endpoints of unclosed curve) + const thisseg = Math.floor(controlIndex / 4) * 4; + const which = controlIndex % 4; + 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; + const refPt = ink[controlIndex]; + const { nearestPt } = InkStrokeProperties.nearestPtToStroke(ink, refPt, [thisseg, prevseg, nextseg]); + + // nearestPt is in inkDoc coordinates -- we need to compute the distance in screen coordinates. + // so we scale the X & Y distances by the internal ink scale factor and then transform the final distance by the ScreenToLocal.Scale of the inkDoc itself. + const { ptsXscale, ptsYscale } = this.inkToScreenScale(ink, inkDoc); + const near = Math.sqrt((nearestPt.X - refPt.X) * (nearestPt.X - refPt.X) * ptsXscale * ptsXscale + + (nearestPt.Y - refPt.Y) * (nearestPt.Y - refPt.Y) * ptsYscale * ptsYscale); + + return { near, nearestPt, ptsXscale, ptsYscale }; + } + + snapBetweenCurves = (ink: InkData, inkDoc: Doc, controlIndex: number) => { + const inkContext = Cast(inkDoc.context, Doc, null); + // Cast(inkContext.data) - // } + // .filter(doc => doc.type === DocumentType.INK) + // .map(doc => { + // if (InkStrokeProperties.Instance?._lock) { + // Doc.SetNativeHeight(doc, NumCast(doc._height)); + // Doc.SetNativeWidth(doc, NumCast(doc._width)); + // } + // return ({ doc, x: NumCast(doc.x), y: NumCast(doc.y), width: NumCast(doc._width), height: NumCast(doc._height) }); + // }); + return false; + } + + inkToScreenScale = (ink: InkData, inkDoc: Doc) => { + const oldXrange = (xs => ({ coord: NumCast(inkDoc.x), min: Math.min(...xs), max: Math.max(...xs) }))(ink.map(p => p.X)); + const oldYrange = (ys => ({ coord: NumCast(inkDoc.y), min: Math.min(...ys), max: Math.max(...ys) }))(ink.map(p => p.Y)); + const ptsXscale = ((NumCast(inkDoc._width) - NumCast(inkDoc.strokeWidth)) / ((oldXrange.max - oldXrange.min) || 1)) || 1; + const ptsYscale = ((NumCast(inkDoc._height) - NumCast(inkDoc.strokeWidth)) / ((oldYrange.max - oldYrange.min) || 1)) || 1; + return { ptsXscale, ptsYscale }; + } /** * Snaps a control point with broken tangency back to synced rotation. |