minor utils tweaks

This commit is contained in:
Steve Ruiz 2021-10-25 09:38:11 +01:00
parent ac4849a360
commit 8d6fe119a5
4 changed files with 38 additions and 29 deletions

View file

@ -15,6 +15,8 @@ import { Vec } from '@tldraw/vec'
import './polyfills'
import type { Patch, TLBoundsWithCenter } from '+index'
const TAU = Math.PI * 2
export class Utils {
/* -------------------------------------------------- */
/* Math & Geometry */
@ -467,9 +469,9 @@ export class Utils {
*/
static isAngleBetween(a: number, b: number, c: number): boolean {
if (c === a || c === b) return true
const PI2 = Math.PI * 2
const AB = (b - a + PI2) % PI2
const AC = (c - a + PI2) % PI2
const AB = (b - a + TAU) % TAU
const AC = (c - a + TAU) % TAU
return AB <= Math.PI !== AC > AB
}
@ -497,10 +499,24 @@ export class Utils {
* @param B
*/
static getArcLength(C: number[], r: number, A: number[], B: number[]): number {
const sweep = Utils.getSweep(C, A, B)
const sweep = Utils.getSweepFlag(C, A, B)
return r * (2 * Math.PI) * (sweep / (2 * Math.PI))
}
static getSweepFlag(A: number[], B: number[], C: number[]) {
const angleAC = Vec.angle(A, C)
const angleAB = Vec.angle(A, B)
const angleCAB = ((angleAB - angleAC + 3 * Math.PI) % (2 * Math.PI)) - Math.PI
return angleCAB > 0 ? 0 : 1
}
static getLargeArcFlag(A: number[], C: number[], P: number[]) {
const anglePA = Vec.angle(P, A)
const anglePC = Vec.angle(P, C)
const angleAPC = ((anglePC - anglePA + 3 * Math.PI) % (2 * Math.PI)) - Math.PI
return Math.abs(angleAPC) > Math.PI / 2 ? 0 : 1
}
/**
* Get a dash offset for an arc, based on its length.
* @param C
@ -510,7 +526,7 @@ export class Utils {
* @param step
*/
static getArcDashOffset(C: number[], r: number, A: number[], B: number[], step: number): number {
const del0 = Utils.getSweep(C, A, B)
const del0 = Utils.getSweepFlag(C, A, B)
const len0 = Utils.getArcLength(C, r, A, B)
const off0 = del0 < 0 ? len0 : 2 * Math.PI * C[2] - len0
return -off0 / 2 + step

View file

@ -728,6 +728,7 @@ function getCurvedArrowHeadPoints(
sweep: boolean
) {
const ints = intersectCircleCircle(A, r1 * 0.618, C, r2).points
if (!ints) {
console.warn('Could not find an intersection for the arrow head.')
return { left: A, right: A }
@ -754,6 +755,7 @@ function getStraightArrowHeadPoints(A: number[], B: number[], r: number) {
const left = int ? Vec.rotWith(int, A, Math.PI / 6) : A
const right = int ? Vec.rotWith(int, A, -Math.PI / 6) : A
return { left, right }
}

View file

@ -10,13 +10,11 @@ export function align(data: Data, ids: string[], type: AlignType): TLDrawCommand
const initialShapes = ids.map((id) => TLDR.getShape(data, id, currentPageId))
const boundsForShapes = initialShapes.map((shape) => {
return {
id: shape.id,
point: [...shape.point],
bounds: TLDR.getShapeUtils(shape).getBounds(shape),
}
})
const boundsForShapes = initialShapes.map((shape) => ({
id: shape.id,
point: [...shape.point],
bounds: TLDR.getShapeUtils(shape).getBounds(shape),
}))
const commonBounds = Utils.getCommonBounds(boundsForShapes.map(({ bounds }) => bounds))
@ -46,10 +44,7 @@ export function align(data: Data, ids: string[], type: AlignType): TLDrawCommand
const { before, after } = TLDR.mutateShapes(
data,
ids,
(shape) => {
if (!deltaMap[shape.id]) return shape
return { point: deltaMap[shape.id].next }
},
(shape) => (deltaMap[shape.id] ? { point: deltaMap[shape.id].next } : shape),
currentPageId
)

View file

@ -197,7 +197,7 @@ export class Vec {
* @returns
*/
static tangent = (A: number[], B: number[]): number[] => {
return Vec.normalize(Vec.sub(A, B))
return Vec.uni(Vec.sub(A, B))
}
/**
@ -446,21 +446,17 @@ export class Vec {
P: number[],
clamp = true
): number[] => {
const delta = Vec.sub(B, A)
const length = Vec.len(delta)
const u = Vec.div(delta, length)
const pt = Vec.add(A, Vec.mul(u, Vec.pry(Vec.sub(P, A), u)))
const u = Vec.uni(Vec.sub(B, A))
const C = Vec.add(A, Vec.mul(u, Vec.pry(Vec.sub(P, A), u)))
if (clamp) {
const da = Vec.dist(A, pt)
const db = Vec.dist(B, pt)
if (db < da && da > length) return B
if (da < db && db > length) return A
if (C[0] < Math.min(A[0], B[0])) return A[0] < B[0] ? A : B
if (C[0] > Math.max(A[0], B[0])) return A[0] > B[0] ? A : B
if (C[1] < Math.min(A[1], B[1])) return A[1] < B[1] ? A : B
if (C[1] > Math.max(A[1], B[1])) return A[1] > B[1] ? A : B
}
return pt
return C
}
/**
@ -483,7 +479,7 @@ export class Vec {
* @returns
*/
static nudge = (A: number[], B: number[], d: number): number[] => {
return Vec.add(A, Vec.mul(Vec.uni(Vec.vec(A, B)), d))
return Vec.add(A, Vec.mul(Vec.uni(Vec.sub(B, A)), d))
}
/**