UNPKG

@davepagurek/flo-mat

Version:

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

84 lines (69 loc) 2.84 kB
/** @internal */ declare const _debug_: Debug; import { beziersToSvgPathStr, simplifyPaths } from 'flo-boolean'; import { Debug } from '../debug/debug.js'; import { Mat } from '../mat/mat.js'; import { findMat } from './find-mat.js'; import { getSizeParams } from './get-size-params.js'; /** * Finds and returns the Medial Axis Transforms (MATs) from the given array of * bezier loops representing shape boundaries. * * @param bezierLoops An array of (possibly intersecting) loops with each loop * representing one or more piecewise smooth closed curves (i.e. shapes). Each * loop consists of an array of beziers represented by an array of control * points with 2,3 or 4 elements corresponding to linear, quadratic and cubic * beziers respectively. Each point is a two-element array (ordered pair), the * first of which is the x-coordinate and the second the y-coordinate. * * @param maxCurviness The maximum value the 'curviness' of a curve can have * before an additional MAT point is inserted in between. Defaults to 0.4. * (Curviness is measured as the total angle in radians between the consecutive * vectors formed by the ordered control points of th bezier curve). The value * is clipped in the range `[0.05,3]`. * @param maxLength The maximum length a curve can have before an additional MAT * point is inserted. This value is scaled to a reference 1024 x 1024 * grid (e.g. if the shape fits in a 512 x 512 axis-aligned box the value will be * halved, e.g. from 10 to 5). Together with maxCurviness it represents a * tolerance for the accuracy of the MAT. Defaults to 4. The value is clipped * in [1,100]. */ function findMats( bezierLoops: number[][][][], maxCurviness = 0.4, maxLength = 4): Mat[] { // if (typeof _debug_ !== 'undefined') { var timingStart = performance.now(); } let maxCoordinate: number; let minBezLength: number; ({ maxCurviness, maxLength, maxCoordinate, minBezLength } = getSizeParams(bezierLoops, maxCurviness, maxLength)); const loopss = simplifyPaths(bezierLoops); // console.log(loopsToSvgPathStr(bezierLoops.map(v => v.map(v => v.map(v => v.map(v => v*2**4)))))); // console.log(loopsToSvgPathStr(loopss[0].map(loop => loop.beziers))); const mats: Mat[] = []; for (const loops of loopss) { const mat = findMat( loops, minBezLength, maxCurviness, maxLength, maxCoordinate ); if (mat) { mats.push(mat); } } return mats; } /** * Returns an SVG path string representation of the given bezier loops. * @param loops An array of loops having an array of bezier curves each given as * an array of control points. */ function loopsToSvgPathStr( loops: number[][][][]) { let str = ''; for (const loop of loops) { str = str + beziersToSvgPathStr(loop) + '\n'; } return str; } export { findMats }