UNPKG

@davepagurek/flo-mat

Version:

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

70 lines (56 loc) 2.03 kB
import { LlRbTree } from 'flo-ll-rb-tree'; import { distanceBetween, toUnitVector, fromTo, dot } from 'flo-vector2d'; import { Loop } from 'flo-boolean'; import { CpNode } from '../cp-node/cp-node.js'; import { PointOnShape } from '../point-on-shape/point-on-shape.js'; import { Circle } from '../geometry/circle.js'; import { getNeighbouringPoints } from './get-neighboring-cps.js'; /** @internal */ const DEGREES = 3; const ANGLE_THRESHOLD = Math.cos(DEGREES * (Math.PI / 180)); /** * @internal * If another `CpNode` is close by (to the given implied (via `pos`, `order` and * `order2`) then return it, else return `undefined`. * * @param cpTrees * @param pos * @param circle * @param order * @param order2 * @param extreme The maximum coordinate value used to calculate floating point * tolerances. * @param color Used for debugging only */ function isAnotherCpCloseby( cpTrees: Map<Loop,LlRbTree<CpNode>>, pos: PointOnShape, circle: Circle, order: number, order2: number, extreme: number): CpNode | undefined { const DISTANCE_THRESHOLD = extreme * 2e-14; const DISTANCE_THRESHOLD_2 = DISTANCE_THRESHOLD * 2e-2; const cpTree = cpTrees.get(pos.curve.loop)!; const cpNodes = getNeighbouringPoints(cpTree, pos, order, order2); if (!cpNodes[0]) { return undefined; } const { p, t } = pos; for (const cpNode of cpNodes) { const pos2 = cpNode.cp.pointOnShape; const p2 = pos2.p; const d = distanceBetween(p,p2); if (d > DISTANCE_THRESHOLD) { continue; } const v1 = toUnitVector(fromTo(p2, cpNode.cp.circle.center)); const v2 = toUnitVector(fromTo(p, circle.center)); const cosTheta = dot(v1,v2); if (cosTheta > ANGLE_THRESHOLD || (d < DISTANCE_THRESHOLD_2 && t !== 0 && t !== 1)) { // console.log(d, DISTANCE_THRESHOLD2) return cpNode; } } return undefined; } export { isAnotherCpCloseby }