import type { Mat } from './mat.js'; import type { CpNode } from '../cp-node/cp-node.js'; import { hausdorffDistanceOneSided } from 'flo-bezier3'; import { removeVertex } from '../vertex/remove-vertex.js'; import { getBranches } from './get-branches.js'; import { getMatCurveToNext } from '../cp-node/fs/get-mat-curve-to-next.js'; import { getMatCurveBetween } from '../cp-node/fs/get-mat-curve-between.js'; import { createNewCpTrees } from './create-new-cp-trees.js'; import { clone } from '../cp-node/fs/clone.js'; import { findFirst } from '../cp-node/fs/find-first.js'; import { isTerminating } from '../cp-node/fs/is-terminating.js'; import { isVertex } from '../cp-node/fs/is-vertex.js'; import { getProngCount } from '../cp-node/fs/get-prong-count.js'; const { max } = Math; // FUTURE could be made faster by binary "search" on hausdorff curves? /** * Returns a new simplified MAT of the given one by replacing the piecewise * quad beziers composing the MAT with fewer ones to within a given tolerance. * * @param cpNode a representation of the MAT * @param anlgeTolerance tolerance given as the degrees difference of the unit * direction vectors at the interface between curves. A tolerance of zero means * perfect smoothness is required - defaults to 15 * @param hausdorffTolerance the approximate maximum Hausdorff Distance tolerance - * defaults to `2**-3` * @param maxIterations the max iterations of the Hausdorff Distance calculation, * defaults to `50` */ function simplifyMat( mat: Mat, hausdorffTolerance = 2**-3, maxIterations = 50): Mat { let cpNode = clone(mat.cpNode); // Start from a leaf while (!isTerminating(cpNode)) { cpNode = cpNode.next; } const branches = getBranches(cpNode); const canDeletes: Set = new Set(); for (let k=0; k hausdorffTolerance) { break; } else { canDeletes.add(branch[j]); } } if (i+1 === j) { continue; // no simplification occured } } } // cpNode = findFirst(cpNode_ => isTerminating(cpNode_) ? cpNode_ : undefined, cpNode)!; cpNode = findFirst(isTerminating, cpNode)!; for (const cpNode of canDeletes) { if (!isVertex(cpNode => (getProngCount(cpNode) !== 2) && !cpNode.isHoleClosing )(cpNode)) { removeVertex(cpNode, mat.meta); } } return { cpNode, meta: { ...mat.meta, cpTrees: createNewCpTrees(cpNode) } } } function getTotalHausdorffDistance( i: number, j: number, branch: CpNode[], hausdorffSpacing: number) { const hds: number[] = []; const longCurve = getMatCurveBetween(branch[i], branch[j].next); for (; i