UNPKG

@davepagurek/flo-mat

Version:

Medial / Scale Axis Transform (MAT/SAT) Library.

95 lines (79 loc) 2.36 kB
import { cross, dot, toUnitVector } from "flo-vector2d"; import { Corner } from "./corner"; import { getInterfaceCcw } from './get-interface-ccw.js'; /** * @internal * Angle in degrees to radians. */ const DEGREES = { //'0' : 0.0000, 0.25 : 0.0050, 1 : 0.0167, 4 : 0.0698, 16 : 0.2756, }; /** @internal */ //const DEGREE_LIMIT = DEGREES[1]; const DEGREE_LIMIT = DEGREES[4]; //const DEGREE_LIMIT = DEGREES[16]; /** * @internal * Returns a new corner with properties. * * PRECONDITION: The beziers has control points with max bit-length of 26 and * aligned to a 'grid' to have the same exponent. This is so the vectors between * control points can be calculated exactly without resorting to adaptive * infinite precision floating point operations. * * @param psI The incoming bezier that ends in the corner * @param psO The outgoing bezier that starts at the corner */ function getCorner( psI: number[][], psO: number[][]): Corner { // getInterfaceCcw must return a number !== 0 if psI and psO are not the // same as seen as a curve extension with t ∈ [-∞,+∞] const ccw = getInterfaceCcw(psI, psO); const isSharp = ccw < 0; const isDull = ccw > 0; // Find (non-normalized) tangent of curve.ps at t === 1 const p0E = psI[psI.length-2]; const p1E = psI[psI.length-1]; const xE = p1E[0] - p0E[0]; const yE = p1E[1] - p0E[1]; const tangentAtEnd = [xE,yE]; // Find (non-normalized) tangent of curve.next.ps at t === 0 const p0S = psO[0]; const p1S = psO[1]; const xS = p1S[0] - p0S[0]; const yS = p1S[1] - p0S[1]; const tangentAtStart = [xS,yS]; // These use square root and are thus not exact const tangents_ = [ toUnitVector(tangentAtEnd), toUnitVector(tangentAtStart), ]; // The cross calculated below should be exact due to beziers having been // normalized! const crossTangents = cross(tangents_[0], tangents_[1]); let isQuiteSharp: boolean; let isQuiteDull: boolean; const dotTangents = dot(tangentAtEnd, tangentAtStart); if (dotTangents > 0) { // Curves go in same direction isQuiteSharp = crossTangents < -DEGREE_LIMIT; isQuiteDull = crossTangents > +DEGREE_LIMIT; } else { isQuiteSharp = isSharp; isQuiteDull = isDull; } return { tangents: tangents_, crossTangents, isSharp, isDull, isQuiteSharp, isQuiteDull }; } export { getCorner }