flo-mat 4.1.4 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/closest-boundary-point/get-endpoint-info.spec.ts +140 -0
- package/__tests__/closest-boundary-point/root-interval-to-distance-squared-interval.spec.ts +87 -0
- package/__tests__/cp-node/circle-identity.spec.ts +56 -0
- package/__tests__/cp-node/fs/get-all-on-loop-by-loop.spec.ts +55 -0
- package/__tests__/cp-node/fs/get-angle-between-mat-curves.spec.ts +39 -3
- package/__tests__/cp-node/fs/get-boundary-bezier-parts-to-next.spec.ts +87 -3
- package/__tests__/cp-node/fs/get-boundary-beziers-between.spec.ts +68 -3
- package/__tests__/cp-node/fs/get-boundary-beziers-to-next.spec.ts +41 -3
- package/__tests__/cp-node/fs/get-boundary-distance-to-next.spec.ts +20 -3
- package/__tests__/cp-node/fs/get-branch-beziers.spec.ts +42 -3
- package/__tests__/cp-node/fs/get-branch.spec.ts +60 -3
- package/__tests__/cp-node/fs/get-cp-node-ordering.spec.ts +19 -3
- package/__tests__/cp-node/fs/get-distance-to-next.spec.ts +37 -4
- package/__tests__/cp-node/fs/get-edge-direction.spec.ts +50 -3
- package/__tests__/cp-node/fs/get-first-exit.spec.ts +78 -3
- package/__tests__/cp-node/fs/get-hole-closers.spec.ts +32 -3
- package/__tests__/cp-node/fs/get-implied-boundary-bezier-between.spec.ts +48 -3
- package/__tests__/cp-node/fs/get-mat-curve-between.spec.ts +77 -3
- package/__tests__/cp-node/fs/get-mat-curve-to-next.spec.ts +17 -4
- package/__tests__/cp-node/fs/get-mat-curves-between.spec.ts +38 -3
- package/__tests__/cp-node/fs/get-salience.spec.ts +68 -3
- package/__tests__/cp-node/fs/get-vertex-forward-children.spec.ts +40 -3
- package/__tests__/cp-node/fs/insert-cp-node.spec.ts +87 -3
- package/__tests__/cp-node/fs/is-special.spec.ts +1 -1
- package/__tests__/cp-node/fs/remove-cp-node.spec.ts +42 -3
- package/__tests__/find-2-prong/calc-seperation-tolerance.spec.ts +46 -0
- package/__tests__/find-2-prong/get-medial/dd-get-medial-point-coeffs-same-curve.spec.ts +7 -5
- package/__tests__/find-2-prong/get-medial/dd-get-medial-point-coeffs.spec.ts +4 -2
- package/__tests__/find-2-prong/get-medial/get-closest-points.spec.ts +1 -1
- package/__tests__/floyd-warshall/get-graph.spec.ts +100 -0
- package/__tests__/get-mats-with-hole.ts +28 -0
- package/__tests__/get-mats1.spec.ts +61 -0
- package/__tests__/get-mats1.ts +75 -67
- package/__tests__/helpers/cp-node-by-id.ts +27 -0
- package/__tests__/helpers/expect-point-close.ts +42 -0
- package/__tests__/mat/hausdorff-distance-one-sided-exceeds.spec.ts +129 -0
- package/__tests__/mat/simplify-mat.spec.ts +85 -0
- package/__tests__/reconstruct-from-mat/reconstruct-from-mat.spec.ts +39 -0
- package/__tests__/specific-cases/test-svgs/achispado.svg +14 -0
- package/__tests__/utils/get-beziers-from-tangents.spec.ts +142 -0
- package/browser/index.js +17882 -13800
- package/browser/index.min.js +1 -1
- package/node/add-n-prong.ts/join-spokes.js +3 -2
- package/node/add-n-prong.ts/join-spokes.js.map +1 -1
- package/node/closest-boundary-point/cull-curve-pieces.d.ts +21 -0
- package/node/closest-boundary-point/cull-curve-pieces.js +40 -0
- package/node/closest-boundary-point/cull-curve-pieces.js.map +1 -0
- package/node/closest-boundary-point/get-close-boundary-points-certified.js +5 -2
- package/node/closest-boundary-point/get-close-boundary-points-certified.js.map +1 -1
- package/node/closest-boundary-point/get-endpoint-info.d.ts +39 -0
- package/node/closest-boundary-point/get-endpoint-info.js +78 -0
- package/node/closest-boundary-point/get-endpoint-info.js.map +1 -0
- package/node/closest-boundary-point/get-potential-closest-points-on-curve-certified.js +5 -19
- package/node/closest-boundary-point/get-potential-closest-points-on-curve-certified.js.map +1 -1
- package/node/closest-boundary-point/root-interval-to-distance-squared-interval.d.ts +17 -5
- package/node/closest-boundary-point/root-interval-to-distance-squared-interval.js +37 -50
- package/node/closest-boundary-point/root-interval-to-distance-squared-interval.js.map +1 -1
- package/node/corner/get-corner.d.ts +18 -1
- package/node/corner/get-corner.js +8 -1
- package/node/corner/get-corner.js.map +1 -1
- package/node/corner/get-interface-ccw.js.map +1 -1
- package/node/cp-node/cp-node.d.ts +4 -3
- package/node/cp-node/fs/enhance-cp-node.d.ts +9 -9
- package/node/cp-node/fs/get-all-on-loop-by-loop.js +0 -4
- package/node/cp-node/fs/get-all-on-loop-by-loop.js.map +1 -1
- package/node/cp-node/fs/get-angle-between-mat-curves.d.ts +1 -1
- package/node/cp-node/fs/get-angle-between-mat-curves.js +7 -4
- package/node/cp-node/fs/get-angle-between-mat-curves.js.map +1 -1
- package/node/cp-node/fs/get-boundary-beziers-between.d.ts +6 -4
- package/node/cp-node/fs/get-boundary-beziers-between.js +6 -4
- package/node/cp-node/fs/get-boundary-beziers-between.js.map +1 -1
- package/node/cp-node/fs/get-branch-beziers.d.ts +2 -1
- package/node/cp-node/fs/get-branch-beziers.js +3 -2
- package/node/cp-node/fs/get-branch-beziers.js.map +1 -1
- package/node/cp-node/fs/get-branch.js +1 -2
- package/node/cp-node/fs/get-branch.js.map +1 -1
- package/node/cp-node/fs/get-distance-to-next.js +4 -2
- package/node/cp-node/fs/get-distance-to-next.js.map +1 -1
- package/node/cp-node/fs/get-edge-direction.js +3 -2
- package/node/cp-node/fs/get-edge-direction.js.map +1 -1
- package/node/cp-node/fs/get-first-exit.d.ts +7 -3
- package/node/cp-node/fs/get-first-exit.js +13 -11
- package/node/cp-node/fs/get-first-exit.js.map +1 -1
- package/node/cp-node/fs/get-implied-boundary-bezier-between.d.ts +10 -2
- package/node/cp-node/fs/get-implied-boundary-bezier-between.js +11 -54
- package/node/cp-node/fs/get-implied-boundary-bezier-between.js.map +1 -1
- package/node/cp-node/fs/get-mat-curve-between.d.ts +5 -3
- package/node/cp-node/fs/get-mat-curve-between.js +6 -49
- package/node/cp-node/fs/get-mat-curve-between.js.map +1 -1
- package/node/cp-node/fs/get-mat-curve-to-next.d.ts +1 -1
- package/node/cp-node/fs/get-mat-curves-between.d.ts +8 -0
- package/node/cp-node/fs/get-mat-curves-between.js +9 -2
- package/node/cp-node/fs/get-mat-curves-between.js.map +1 -1
- package/node/cp-node/fs/get-real-prong-count.d.ts +2 -1
- package/node/cp-node/fs/get-real-prong-count.js +11 -5
- package/node/cp-node/fs/get-real-prong-count.js.map +1 -1
- package/node/cp-node/fs/get-salience.d.ts +10 -0
- package/node/cp-node/fs/get-salience.js +17 -1
- package/node/cp-node/fs/get-salience.js.map +1 -1
- package/node/cp-node/fs/is-fully-terminating.d.ts +4 -2
- package/node/cp-node/fs/is-fully-terminating.js +6 -17
- package/node/cp-node/fs/is-fully-terminating.js.map +1 -1
- package/node/cp-node/fs/is-on-same-circle.d.ts +3 -0
- package/node/cp-node/fs/is-on-same-circle.js +4 -4
- package/node/cp-node/fs/is-on-same-circle.js.map +1 -1
- package/node/cp-node/fs/is-on-same-loop.d.ts +1 -1
- package/node/cp-node/fs/is-special.d.ts +7 -0
- package/node/cp-node/fs/is-special.js +9 -2
- package/node/cp-node/fs/is-special.js.map +1 -1
- package/node/cp-node/fs/is-vertex.d.ts +1 -1
- package/node/cp-node/fs/traverse-edges.d.ts +7 -3
- package/node/cp-node/fs/traverse-edges.js +7 -3
- package/node/cp-node/fs/traverse-edges.js.map +1 -1
- package/node/cp-node/stringification/from-stringifyable.d.ts +2 -2
- package/node/cp-node/stringification/from-stringifyable.js +17 -1
- package/node/cp-node/stringification/from-stringifyable.js.map +1 -1
- package/node/cp-node/stringification/to-stringifyable.d.ts +3 -3
- package/node/cp-node/stringification/to-stringifyable.js +3 -3
- package/node/debug/debug.d.ts +26 -3
- package/node/debug/debug.js +16 -5
- package/node/debug/debug.js.map +1 -1
- package/node/find-2-prong/add-2-prong.js +7 -9
- package/node/find-2-prong/add-2-prong.js.map +1 -1
- package/node/find-2-prong/calc-seperation-tolerance.d.ts +28 -5
- package/node/find-2-prong/calc-seperation-tolerance.js +32 -89
- package/node/find-2-prong/calc-seperation-tolerance.js.map +1 -1
- package/node/find-2-prong/find-2-prong.js +8 -10
- package/node/find-2-prong/find-2-prong.js.map +1 -1
- package/node/find-2-prong/find-and-add-2-prongs.js +2 -2
- package/node/find-2-prong/find-and-add-2-prongs.js.map +1 -1
- package/node/find-2-prong/get-medial/get-antipodal-points.d.ts +1 -2
- package/node/find-2-prong/get-medial/get-antipodal-points.js +2 -3
- package/node/find-2-prong/get-medial/get-antipodal-points.js.map +1 -1
- package/node/find-2-prong/get-medial/get-closest-points.d.ts +1 -8
- package/node/find-2-prong/get-medial/get-closest-points.js +4 -40
- package/node/find-2-prong/get-medial/get-closest-points.js.map +1 -1
- package/node/find-2-prong/reduce-radius.d.ts +1 -1
- package/node/find-2-prong/reduce-radius.js +6 -3
- package/node/find-2-prong/reduce-radius.js.map +1 -1
- package/node/find-3-prong/calc-better-x.js +1 -1
- package/node/find-3-prong/calc-better-x.js.map +1 -1
- package/node/find-3-prong/find-3-prong-for-delta3s.d.ts +3 -2
- package/node/find-3-prong/find-3-prong-for-delta3s.js +36 -42
- package/node/find-3-prong/find-3-prong-for-delta3s.js.map +1 -1
- package/node/find-3-prong/find-3-prong.js +3 -1
- package/node/find-3-prong/find-3-prong.js.map +1 -1
- package/node/find-3-prong/find-and-add-3-prongs.js +16 -0
- package/node/find-3-prong/find-and-add-3-prongs.js.map +1 -1
- package/node/find-mat/create-initial-cp-tree.js +2 -2
- package/node/find-mat/create-initial-cp-tree.js.map +1 -1
- package/node/find-mat/find-mat.js +3 -4
- package/node/find-mat/find-mat.js.map +1 -1
- package/node/find-mat/find-mats.d.ts +6 -12
- package/node/find-mat/find-mats.js +10 -27
- package/node/find-mat/find-mats.js.map +1 -1
- package/node/find-mat/get-dull-corners-on-loop.js +2 -2
- package/node/find-mat/get-dull-corners-on-loop.js.map +1 -1
- package/node/find-mat/get-for-1-prongs-on-loop.js +36 -8
- package/node/find-mat/get-for-1-prongs-on-loop.js.map +1 -1
- package/node/find-mat/get-meta.d.ts +14 -4
- package/node/find-mat/get-meta.js +30 -24
- package/node/find-mat/get-meta.js.map +1 -1
- package/node/find-mat/get-sharp-corners.js +2 -2
- package/node/find-mat/get-sharp-corners.js.map +1 -1
- package/node/find-mat/mat-options.d.ts +2 -2
- package/node/floyd-warshall/get-graph.d.ts +12 -1
- package/node/floyd-warshall/get-graph.js +41 -38
- package/node/floyd-warshall/get-graph.js.map +1 -1
- package/node/geometry/get-bounding-box-.d.ts +16 -2
- package/node/geometry/get-bounding-box-.js +5 -2
- package/node/geometry/get-bounding-box-.js.map +1 -1
- package/node/geometry/get-closest-square-distance-to-rect.d.ts +3 -0
- package/node/geometry/get-closest-square-distance-to-rect.js +7 -5
- package/node/geometry/get-closest-square-distance-to-rect.js.map +1 -1
- package/node/geometry/get-closest-squared-distance-to-rotated-rect.d.ts +4 -0
- package/node/geometry/get-closest-squared-distance-to-rotated-rect.js +12 -5
- package/node/geometry/get-closest-squared-distance-to-rotated-rect.js.map +1 -1
- package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.js +1 -2
- package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.js.map +1 -1
- package/node/index.d.ts +3 -2
- package/node/index.js +2 -1
- package/node/index.js.map +1 -1
- package/node/mat/clone-mat.d.ts +9 -0
- package/node/mat/clone-mat.js +17 -0
- package/node/mat/clone-mat.js.map +1 -0
- package/node/mat/clone-meta.d.ts +12 -0
- package/node/mat/clone-meta.js +24 -0
- package/node/mat/clone-meta.js.map +1 -0
- package/node/mat/get-boundary-piece-beziers.d.ts +5 -0
- package/node/mat/get-boundary-piece-beziers.js +7 -93
- package/node/mat/get-boundary-piece-beziers.js.map +1 -1
- package/node/mat/get-closeby-cp-if-exist.js +2 -1
- package/node/mat/get-closeby-cp-if-exist.js.map +1 -1
- package/node/mat/get-largest-3-prong.d.ts +6 -0
- package/node/mat/get-largest-3-prong.js +8 -5
- package/node/mat/get-largest-3-prong.js.map +1 -1
- package/node/mat/get-largest-vertex.d.ts +15 -1
- package/node/mat/get-largest-vertex.js +20 -7
- package/node/mat/get-largest-vertex.js.map +1 -1
- package/node/mat/hausdorff-distance-one-sided-exceeds.d.ts +79 -0
- package/node/mat/hausdorff-distance-one-sided-exceeds.js +251 -0
- package/node/mat/hausdorff-distance-one-sided-exceeds.js.map +1 -0
- package/node/mat/mat-meta.d.ts +0 -6
- package/node/mat/simplify-mat.d.ts +25 -8
- package/node/mat/simplify-mat.js +182 -53
- package/node/mat/simplify-mat.js.map +1 -1
- package/node/mat/trim-mat.d.ts +4 -2
- package/node/mat/trim-mat.js +3 -1
- package/node/mat/trim-mat.js.map +1 -1
- package/node/point-on-shape/get-boundary-tangent-line.d.ts +19 -0
- package/node/point-on-shape/get-boundary-tangent-line.js +33 -0
- package/node/point-on-shape/get-boundary-tangent-line.js.map +1 -0
- package/node/point-on-shape/get-osculating-circle.d.ts +6 -4
- package/node/point-on-shape/get-osculating-circle.js +6 -4
- package/node/point-on-shape/get-osculating-circle.js.map +1 -1
- package/node/point-on-shape/get-pos-corner.js +2 -2
- package/node/point-on-shape/get-pos-corner.js.map +1 -1
- package/node/point-on-shape/point-on-shape.d.ts +5 -0
- package/node/reconstruct-from-mat/reconstruct-from-mat.js +20 -80
- package/node/reconstruct-from-mat/reconstruct-from-mat.js.map +1 -1
- package/node/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.d.ts +4 -0
- package/node/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.js +4 -0
- package/node/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.js.map +1 -1
- package/node/sat/cull.d.ts +7 -6
- package/node/sat/cull.js +13 -16
- package/node/sat/cull.js.map +1 -1
- package/node/sat/get-sat-culls.d.ts +12 -2
- package/node/sat/get-sat-culls.js +21 -16
- package/node/sat/get-sat-culls.js.map +1 -1
- package/node/svg/get-shape-bounds.d.ts +1 -12
- package/node/svg/get-shape-bounds.js +2 -3
- package/node/svg/get-shape-bounds.js.map +1 -1
- package/node/sweep-line/sweep-line.js.map +1 -1
- package/node/utils/get-beziers-from-tangents.d.ts +28 -0
- package/node/utils/get-beziers-from-tangents.js +92 -0
- package/node/utils/get-beziers-from-tangents.js.map +1 -0
- package/node/vertex/remove-vertex.d.ts +5 -3
- package/node/vertex/remove-vertex.js +5 -3
- package/node/vertex/remove-vertex.js.map +1 -1
- package/package.json +16 -16
- package/qv-infinite-loop.md +120 -0
- package/src/add-n-prong.ts/join-spokes.ts +4 -2
- package/src/closest-boundary-point/cull-curve-pieces.ts +49 -0
- package/src/closest-boundary-point/get-close-boundary-points-certified.ts +5 -2
- package/src/closest-boundary-point/get-endpoint-info.ts +96 -0
- package/src/closest-boundary-point/get-potential-closest-points-on-curve-certified.ts +5 -23
- package/src/closest-boundary-point/root-interval-to-distance-squared-interval.ts +42 -60
- package/src/corner/get-corner.ts +10 -1
- package/src/corner/get-interface-ccw.ts +2 -2
- package/src/cp-node/cp-node.ts +4 -3
- package/src/cp-node/fs/get-all-on-loop-by-loop.ts +0 -4
- package/src/cp-node/fs/get-angle-between-mat-curves.ts +9 -5
- package/src/cp-node/fs/get-boundary-beziers-between.ts +10 -8
- package/src/cp-node/fs/get-branch-beziers.ts +3 -2
- package/src/cp-node/fs/get-branch.ts +1 -2
- package/src/cp-node/fs/get-distance-to-next.ts +4 -2
- package/src/cp-node/fs/get-edge-direction.ts +4 -2
- package/src/cp-node/fs/get-first-exit.ts +15 -14
- package/src/cp-node/fs/get-implied-boundary-bezier-between.ts +18 -70
- package/src/cp-node/fs/get-mat-curve-between.ts +10 -67
- package/src/cp-node/fs/get-mat-curves-between.ts +9 -2
- package/src/cp-node/fs/get-real-prong-count.ts +11 -7
- package/src/cp-node/fs/get-salience.ts +15 -2
- package/src/cp-node/fs/is-fully-terminating.ts +6 -22
- package/src/cp-node/fs/is-on-same-circle.ts +6 -7
- package/src/cp-node/fs/is-on-same-loop.ts +2 -2
- package/src/cp-node/fs/is-special.ts +11 -6
- package/src/cp-node/fs/is-vertex.ts +1 -1
- package/src/cp-node/fs/traverse-edges.ts +8 -4
- package/src/cp-node/stringification/from-stringifyable.ts +75 -58
- package/src/cp-node/stringification/to-stringifyable.ts +3 -3
- package/src/debug/debug.ts +44 -8
- package/src/find-2-prong/add-2-prong.ts +9 -11
- package/src/find-2-prong/calc-seperation-tolerance.ts +34 -115
- package/src/find-2-prong/find-2-prong.ts +9 -11
- package/src/find-2-prong/find-and-add-2-prongs.ts +2 -2
- package/src/find-2-prong/get-medial/get-antipodal-points.ts +1 -3
- package/src/find-2-prong/get-medial/get-closest-points.ts +6 -51
- package/src/find-2-prong/reduce-radius.ts +6 -4
- package/src/find-3-prong/calc-better-x.ts +2 -2
- package/src/find-3-prong/find-3-prong-for-delta3s.ts +197 -214
- package/src/find-3-prong/find-3-prong.ts +54 -51
- package/src/find-3-prong/find-and-add-3-prongs.ts +20 -1
- package/src/find-mat/create-initial-cp-tree.ts +2 -2
- package/src/find-mat/find-mat.ts +4 -6
- package/src/find-mat/find-mats.ts +83 -105
- package/src/find-mat/get-dull-corners-on-loop.ts +2 -2
- package/src/find-mat/get-for-1-prongs-on-loop.ts +40 -8
- package/src/find-mat/get-meta.ts +34 -39
- package/src/find-mat/get-sharp-corners.ts +2 -2
- package/src/find-mat/mat-options.ts +2 -2
- package/src/floyd-warshall/get-graph.ts +46 -47
- package/src/geometry/get-bounding-box-.ts +5 -2
- package/src/geometry/get-closest-square-distance-to-rect.ts +7 -7
- package/src/geometry/get-closest-squared-distance-to-rotated-rect.ts +15 -13
- package/src/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.ts +1 -2
- package/src/index.ts +3 -2
- package/src/mat/clone-mat.ts +9 -3
- package/src/mat/clone-meta.ts +8 -0
- package/src/mat/get-boundary-piece-beziers.ts +16 -117
- package/src/mat/get-closeby-cp-if-exist.ts +3 -1
- package/src/mat/get-largest-3-prong.ts +9 -6
- package/src/mat/get-largest-vertex.ts +25 -9
- package/src/mat/hausdorff-distance-one-sided-exceeds.ts +314 -0
- package/src/mat/mat-meta.ts +0 -9
- package/src/mat/simplify-mat.ts +254 -116
- package/src/mat/trim-mat.ts +6 -4
- package/src/point-on-shape/get-boundary-tangent-line.ts +36 -0
- package/src/point-on-shape/get-osculating-circle.ts +7 -5
- package/src/point-on-shape/get-pos-corner.ts +2 -2
- package/src/point-on-shape/point-on-shape.ts +5 -0
- package/src/reconstruct-from-mat/reconstruct-from-mat.ts +22 -111
- package/src/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.ts +4 -0
- package/src/sat/cull.ts +16 -20
- package/src/sat/get-sat-culls.ts +28 -23
- package/src/svg/get-shape-bounds.ts +2 -3
- package/src/sweep-line/sweep-line.ts +1 -1
- package/src/utils/deg-to-rad.ts +4 -2
- package/src/utils/get-beziers-from-tangents.ts +110 -0
- package/src/utils/map-map.ts +1 -1
- package/src/utils/rad-to-deg.ts +4 -1
- package/src/vertex/remove-vertex.ts +5 -3
- package/webpack.config.cjs +7 -2
- package/__tests__/cp-node/fs/get-distance-between.spec.ts +0 -7
- package/__tests__/cp-node/fs/get-terminating-on-circle.spec.ts +0 -24
- package/__tests__/cp-node/fs/is-single-3-prong.spec.ts +0 -17
- package/__tests__/cp-node/fs/iterate-all-on-loop.spec.ts +0 -17
- package/__tests__/cp-node/fs/traverse-all-forward.spec.ts +0 -14
- package/node/closest-boundary-point/cull-bezier-pieces-1.d.ts +0 -9
- package/node/closest-boundary-point/cull-bezier-pieces-1.js +0 -17
- package/node/closest-boundary-point/cull-bezier-pieces-1.js.map +0 -1
- package/node/closest-boundary-point/cull-by-loose-bounding-box.d.ts +0 -13
- package/node/closest-boundary-point/cull-by-loose-bounding-box.js +0 -27
- package/node/closest-boundary-point/cull-by-loose-bounding-box.js.map +0 -1
- package/node/closest-boundary-point/cull-by-tight-boundary-box.d.ts +0 -11
- package/node/closest-boundary-point/cull-by-tight-boundary-box.js +0 -27
- package/node/closest-boundary-point/cull-by-tight-boundary-box.js.map +0 -1
- package/node/cp-node/fs/find-first.d.ts +0 -10
- package/node/cp-node/fs/find-first.js +0 -19
- package/node/cp-node/fs/find-first.js.map +0 -1
- package/node/debug/functions/check-ordering.d.ts +0 -4
- package/node/debug/functions/check-ordering.js +0 -43
- package/node/debug/functions/check-ordering.js.map +0 -1
- package/node/find-2-prong/cull-bezier-pieces.d.ts +0 -13
- package/node/find-2-prong/cull-bezier-pieces.js +0 -43
- package/node/find-2-prong/cull-bezier-pieces.js.map +0 -1
- package/node/floyd-warshall/get-hole-closer-pairs.d.ts +0 -8
- package/node/floyd-warshall/get-hole-closer-pairs.js +0 -27
- package/node/floyd-warshall/get-hole-closer-pairs.js.map +0 -1
- package/node/utils/dual-set.d.ts +0 -27
- package/node/utils/dual-set.js +0 -55
- package/node/utils/dual-set.js.map +0 -1
- package/node/utils/tri-map.d.ts +0 -27
- package/node/utils/tri-map.js +0 -49
- package/node/utils/tri-map.js.map +0 -1
- package/src/closest-boundary-point/cull-bezier-pieces-1.ts +0 -36
- package/src/closest-boundary-point/cull-by-loose-bounding-box.ts +0 -42
- package/src/closest-boundary-point/cull-by-tight-boundary-box.ts +0 -43
- package/src/closest-boundary-point/get-p-from-box.ts +0 -14
- package/src/cp-node/fs/add-distance-from.ts +0 -49
- package/src/cp-node/fs/get-distance-between.ts +0 -16
- package/src/cp-node/fs/get-terminating-on-circle.ts +0 -24
- package/src/cp-node/fs/is-single-3-prong.ts +0 -15
- package/src/cp-node/fs/iterate-all-on-loop.ts +0 -15
- package/src/cp-node/fs/traverse-all-forward.ts +0 -24
- package/src/debug/functions/draw/draw-beziers-as-single-path.ts +0 -40
- package/src/debug/functions/draw/draw-disk.ts +0 -34
- package/src/debug/functions/draw/xmlns.ts +0 -5
- package/src/find-2-prong/cull-bezier-pieces.ts +0 -61
- package/src/find-2-prong/find-and-add-2-prong.ts +0 -30
- package/src/find-2-prong/get-medial/get-closest-points-d.ts +0 -213
- package/src/find-2-prong/x-for-debugging.ts +0 -13
- package/src/floyd-warshall/get-hole-closer-pairs.ts +0 -35
- package/src/mat/get-two-prong-type.ts +0 -13
- package/src/point-on-shape/is-pos-dull-corner.ts +0 -18
- package/src/point-on-shape/is-pos-quite-dull-corner.ts +0 -18
- package/src/point-on-shape/is-pos-quite-sharp-corner.ts +0 -18
- package/src/point-on-shape/pos-to-human-string.ts +0 -18
- package/src/sweep-line/are-boxes-intersecting.ts +0 -37
package/__tests__/get-mats1.ts
CHANGED
|
@@ -1,83 +1,90 @@
|
|
|
1
1
|
import type { Mat } from "../src/mat/mat.js";
|
|
2
2
|
import type { CpNodeStringifyable } from "../src/cp-node/stringification/cp-node-stringifyable.js";
|
|
3
|
+
import type { Circle } from "../src/geometry/circle.js";
|
|
3
4
|
import { findMats } from "../src/find-mat/find-mats.js";
|
|
4
5
|
import { fromStringifyable } from "../src/cp-node/stringification/from-stringifyable.js";
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
9
|
+
// One `Circle` object per on-circle ring (shared by all the ring's `CpNode`s
|
|
10
|
+
// and by no other ring) - see `PointOnShape.circle`. The fixture has no hole
|
|
11
|
+
// closers, so there are no twin rings with equal-but-distinct circles.
|
|
12
|
+
const circle_0_1: Circle = { center: [24, 8], radius: 0 };
|
|
13
|
+
const circle_10_11: Circle = { center: [46, -5.21425847941623], radius: 13.21425847941623 };
|
|
14
|
+
const circle_142_143_144: Circle = { center: [81.5, -12.641417453935567], radius: 41.064803841095305 };
|
|
15
|
+
const circle_145_146_147: Circle = { center: [81.5, 18.5], radius: 35.5 };
|
|
16
|
+
const circle_2_3: Circle = { center: [46, 54], radius: 0 };
|
|
17
|
+
const circle_4_5: Circle = { center: [117, 54], radius: 0 };
|
|
18
|
+
const circle_6_7: Circle = { center: [139, 8], radius: 0 };
|
|
19
|
+
const circle_8_9: Circle = { center: [82, -101], radius: 0 };
|
|
20
|
+
const circle_148_149_150: Circle = { center: [81.68410160768288, -12.970446490933696], radius: 41.07276841516263 };
|
|
21
|
+
const circle_118_119: Circle = { center: [115.9110440340909, -5.952334953607174], radius: 13.994766012811272 };
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
/** mat-demo: "achispado" font, "comma" glyph - fixed MAT fixture */
|
|
25
|
+
const cpNodeStringifyable1: CpNodeStringifyable = {
|
|
26
|
+
cpNodes: [
|
|
27
|
+
{
|
|
28
|
+
id: 0,
|
|
29
|
+
isHoleClosing: false,
|
|
30
|
+
isIntersection: false,
|
|
31
|
+
pointOnShape: {
|
|
32
|
+
circle: circle_0_1,
|
|
33
|
+
curveIdx: 0,
|
|
34
|
+
loopIdx: 0,
|
|
35
|
+
p: [24, 8],
|
|
36
|
+
pDd: [[0,24],[0,8]],
|
|
37
|
+
t: 1,
|
|
38
|
+
isSource: true,
|
|
39
|
+
order: -1,
|
|
40
|
+
order2: 0
|
|
36
41
|
},
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
],
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
]
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
42
|
+
prev: 11,
|
|
43
|
+
next: 1,
|
|
44
|
+
prevOnCircle: 1,
|
|
45
|
+
nextOnCircle: 1
|
|
46
|
+
},
|
|
47
|
+
{ id: 1, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_0_1, curveIdx: 0, loopIdx: 0, p: [24, 8], t: 1, isSource: true , order: 1, order2: 0, pDd: [[0,24],[0,8]] }, prev: 0, next: 10, prevOnCircle: 0, nextOnCircle: 0 },
|
|
48
|
+
{ id: 10, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_10_11, curveIdx: 1, loopIdx: 0, p: [46, 8], t: 1, isSource: true , order: -1, order2: 0, pDd: [[0,46],[0,8]] }, prev: 1, next: 144, prevOnCircle: 11, nextOnCircle: 11 },
|
|
49
|
+
{ id: 144, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_142_143_144, curveIdx: 1, loopIdx: 0, p: [46, 8], t: 1, isSource: false , order: -0.5026547194480646, order2: 0, pDd: [[0,46],[0,8]] }, prev: 10, next: 147, prevOnCircle: 143, nextOnCircle: 142 },
|
|
50
|
+
{ id: 147, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_145_146_147, curveIdx: 2, loopIdx: 0, p: [46, 18.499999999999996], t: 0.2282608695652173, isSource: false , order: 0, order2: 0, pDd: [[0,46],[0,18.499999999999996]] }, prev: 144, next: 2, prevOnCircle: 146, nextOnCircle: 145 },
|
|
51
|
+
{ id: 2, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_2_3, curveIdx: 2, loopIdx: 0, p: [46, 54], t: 1, isSource: true , order: -1, order2: 0, pDd: [[0,46],[0,54]] }, prev: 147, next: 3, prevOnCircle: 3, nextOnCircle: 3 },
|
|
52
|
+
{ id: 3, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_2_3, curveIdx: 2, loopIdx: 0, p: [46, 54], t: 1, isSource: true , order: 1, order2: 0, pDd: [[0,46],[0,54]] }, prev: 2, next: 145, prevOnCircle: 2, nextOnCircle: 2 },
|
|
53
|
+
{ id: 145, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_145_146_147, curveIdx: 3, loopIdx: 0, p: [81.5, 54], t: 0.5, isSource: false , order: 0, order2: 0, pDd: [[0,81.5],[0,54]] }, prev: 3, next: 4, prevOnCircle: 147, nextOnCircle: 146 },
|
|
54
|
+
{ id: 4, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_4_5, curveIdx: 3, loopIdx: 0, p: [117, 54], t: 1, isSource: true , order: -1, order2: 0, pDd: [[0,117],[0,54]] }, prev: 145, next: 5, prevOnCircle: 5, nextOnCircle: 5 },
|
|
55
|
+
{ id: 5, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_4_5, curveIdx: 3, loopIdx: 0, p: [117, 54], t: 1, isSource: true , order: 1, order2: 0, pDd: [[0,117],[0,54]] }, prev: 4, next: 146, prevOnCircle: 4, nextOnCircle: 4 },
|
|
56
|
+
{ id: 146, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_145_146_147, curveIdx: 4, loopIdx: 0, p: [117, 18.499999999999996], t: 0.7717391304347827, isSource: false , order: 0, order2: 0, pDd: [[0,117],[0,18.499999999999996]] }, prev: 5, next: 142, prevOnCircle: 145, nextOnCircle: 147 },
|
|
57
|
+
{ id: 142, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_142_143_144, curveIdx: 4, loopIdx: 0, p: [117, 8], t: 1, isSource: false , order: -0.8644872659655476, order2: 0, pDd: [[0,117],[0,8]] }, prev: 146, next: 148, prevOnCircle: 144, nextOnCircle: 143 },
|
|
58
|
+
{ id: 148, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_148_149_150, curveIdx: 4, loopIdx: 0, p: [117, 8], t: 1, isSource: false , order: -0.8598373023056252, order2: 0, pDd: [[0,117],[0,8]] }, prev: 142, next: 119, prevOnCircle: 150, nextOnCircle: 149 },
|
|
59
|
+
{ id: 119, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_118_119, curveIdx: 4, loopIdx: 0, p: [117, 8], t: 1, isSource: false , order: -0.07781165936695383, order2: 0, pDd: [[0,117],[0,8]] }, prev: 148, next: 6, prevOnCircle: 118, nextOnCircle: 118 },
|
|
60
|
+
{ id: 6, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_6_7, curveIdx: 5, loopIdx: 0, p: [139, 8], t: 1, isSource: true , order: -1, order2: 0, pDd: [[0,139],[0,8]] }, prev: 119, next: 7, prevOnCircle: 7, nextOnCircle: 7 },
|
|
61
|
+
{ id: 7, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_6_7, curveIdx: 5, loopIdx: 0, p: [139, 8], t: 1, isSource: true , order: 1, order2: 0, pDd: [[0,139],[0,8]] }, prev: 6, next: 118, prevOnCircle: 6, nextOnCircle: 6 },
|
|
62
|
+
{ id: 118, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_118_119, curveIdx: 6, loopIdx: 0, p: [128.3125, -12.4375], t: 0.1875, isSource: true , order: 0, order2: 0, pDd: [[0,128.3125],[0,-12.4375]] }, prev: 7, next: 149, prevOnCircle: 119, nextOnCircle: 119 },
|
|
63
|
+
{ id: 149, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_148_149_150, curveIdx: 6, loopIdx: 0, p: [118.08071791640388, -32.003539423017145], t: 0.36700494883501966, isSource: false , order: 0, order2: 0, pDd: [[0,118.08071791640388],[0,-32.003539423017145]] }, prev: 118, next: 8, prevOnCircle: 148, nextOnCircle: 150 },
|
|
64
|
+
{ id: 8, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_8_9, curveIdx: 6, loopIdx: 0, p: [82, -101], t: 1, isSource: true , order: -1, order2: 0, pDd: [[0,82],[0,-101]] }, prev: 149, next: 9, prevOnCircle: 9, nextOnCircle: 9 },
|
|
65
|
+
{ id: 9, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_8_9, curveIdx: 6, loopIdx: 0, p: [82, -101], t: 1, isSource: true , order: 1, order2: 0, pDd: [[0,82],[0,-101]] }, prev: 8, next: 150, prevOnCircle: 8, nextOnCircle: 8 },
|
|
66
|
+
{ id: 150, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_148_149_150, curveIdx: 0, loopIdx: 0, p: [45.425023320690585, -32.264267964746104], t: 0.6306030461949899, isSource: false , order: 0, order2: 0, pDd: [[0,45.425023320690585],[0,-32.264267964746104]] }, prev: 9, next: 143, prevOnCircle: 149, nextOnCircle: 148 },
|
|
67
|
+
{ id: 143, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_142_143_144, curveIdx: 0, loopIdx: 0, p: [45.24795284642707, -31.931497590699145], t: 0.6336559854064299, isSource: false , order: 0, order2: 0, pDd: [[0,45.24795284642707],[0,-31.931497590699145]] }, prev: 150, next: 11, prevOnCircle: 142, nextOnCircle: 144 },
|
|
68
|
+
{ id: 11, isHoleClosing: false, isIntersection: false, pointOnShape: { circle: circle_10_11, curveIdx: 0, loopIdx: 0, p: [34.33444028251029, -11.421620530924521], t: 0.8218199951291328, isSource: false , order: 0, order2: 0, pDd: [[0,34.33444028251029],[0,-11.421620530924521]] }, prev: 143, next: 0, prevOnCircle: 10, nextOnCircle: 10 }
|
|
69
|
+
],
|
|
70
|
+
loops: [
|
|
71
|
+
{ idx: 0, beziers: [[[82, -101], [24, 8]], [[24, 8], [46, 8]], [[46, 8], [46, 54]], [[46, 54], [117, 54]], [[117, 54], [117, 8]], [[117, 8], [139, 8]], [[139, 8], [82, -101]]] }
|
|
72
|
+
]
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
// We use this one in tests since it is fixed and not susceptible to
|
|
77
|
+
// small perturbations in the algorithm.
|
|
78
|
+
function getMats1(): Mat[] {
|
|
79
|
+
const cpNode = fromStringifyable(cpNodeStringifyable1);
|
|
80
|
+
|
|
81
|
+
return [{ cpNode, meta: {
|
|
69
82
|
cpTrees: undefined!,
|
|
70
83
|
loops: undefined!,
|
|
71
|
-
dullCorners: undefined!,
|
|
72
84
|
lastInsertId: undefined!,
|
|
73
|
-
looseBoundingBoxes: undefined!,
|
|
74
85
|
maxCoordPowerOf2: undefined!,
|
|
75
|
-
|
|
76
|
-
squaredDiagonalLength: undefined!,
|
|
77
|
-
tightBoundingBoxes: undefined!
|
|
86
|
+
squaredDiagonalLength: undefined!
|
|
78
87
|
} }];
|
|
79
|
-
|
|
80
|
-
return mats1;
|
|
81
88
|
}
|
|
82
89
|
|
|
83
90
|
|
|
@@ -119,5 +126,6 @@ function _getMats1() {
|
|
|
119
126
|
|
|
120
127
|
export {
|
|
121
128
|
getMats1,
|
|
129
|
+
cpNodeStringifyable1,
|
|
122
130
|
// _getMats1
|
|
123
131
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { CpNode } from "../../src/cp-node/cp-node.js";
|
|
2
|
+
import { getAllOnLoop } from "../../src/cp-node/fs/get-all-on-loop.js";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns the `CpNode` with the given `id` on the same loop as the given
|
|
7
|
+
* `CpNode` (throws if not found) - for picking out specific nodes of the
|
|
8
|
+
* `getMats1` fixture.
|
|
9
|
+
*/
|
|
10
|
+
function cpNodeById(
|
|
11
|
+
cpNode: CpNode,
|
|
12
|
+
id: number): CpNode {
|
|
13
|
+
|
|
14
|
+
const found = getAllOnLoop(cpNode).find(cp => cp.id === id);
|
|
15
|
+
if (!found) { throw new Error(`no CpNode with id ${id}`); }
|
|
16
|
+
|
|
17
|
+
return found;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
/** Returns a function mapping ids to `CpNode`s on the given loop. */
|
|
22
|
+
function cpNodesByIdOn(cpNode: CpNode) {
|
|
23
|
+
return (id: number) => cpNodeById(cpNode, id);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
export { cpNodeById, cpNodesByIdOn }
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { expect } from '@jest/globals';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
/** Asserts two points (or any equal-length number arrays) are nearly equal. */
|
|
5
|
+
function expectPointClose(
|
|
6
|
+
actual: number[],
|
|
7
|
+
expected: number[],
|
|
8
|
+
digits = 9): void {
|
|
9
|
+
|
|
10
|
+
expect(actual.length).toBe(expected.length);
|
|
11
|
+
for (let i=0; i<actual.length; i++) {
|
|
12
|
+
expect(actual[i]).toBeCloseTo(expected[i], digits);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/** Asserts two bezier curves are nearly equal (same order and control points). */
|
|
18
|
+
function expectBezierClose(
|
|
19
|
+
actual: number[][],
|
|
20
|
+
expected: number[][],
|
|
21
|
+
digits = 9): void {
|
|
22
|
+
|
|
23
|
+
expect(actual.length).toBe(expected.length);
|
|
24
|
+
for (let i=0; i<actual.length; i++) {
|
|
25
|
+
expectPointClose(actual[i], expected[i], digits);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/** Asserts consecutive beziers in the array join up end-to-start. */
|
|
31
|
+
function expectBeziersConnected(
|
|
32
|
+
pss: number[][][],
|
|
33
|
+
digits = 9): void {
|
|
34
|
+
|
|
35
|
+
for (let i=1; i<pss.length; i++) {
|
|
36
|
+
const prev = pss[i-1];
|
|
37
|
+
expectPointClose(pss[i][0], prev[prev.length-1], digits);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
export { expectPointClose, expectBezierClose, expectBeziersConnected }
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { describe, expect, test } from '@jest/globals';
|
|
2
|
+
import { hausdorffDistanceOneSided, closestPointOnBezier, evalDeCasteljau } from 'flo-bezier3';
|
|
3
|
+
import { hausdorffDistanceOneSidedExceeds, distanceToCurves } from '../../src/mat/hausdorff-distance-one-sided-exceeds.js';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The one-sided Hausdorff distance from `A` to the piecewise curve `B`
|
|
8
|
+
* approximated by dense sampling of `A` (a lower bound, accurate to within
|
|
9
|
+
* the sample spacing times the speed of `A`).
|
|
10
|
+
*/
|
|
11
|
+
function sampledHausdorffDistanceOneSided(
|
|
12
|
+
A: number[][],
|
|
13
|
+
B: number[][][],
|
|
14
|
+
samples = 4096): number {
|
|
15
|
+
|
|
16
|
+
let worst = 0;
|
|
17
|
+
for (let i=0; i<=samples; i++) {
|
|
18
|
+
const p = evalDeCasteljau(A, i/samples);
|
|
19
|
+
let best = Infinity;
|
|
20
|
+
for (const qs of B) {
|
|
21
|
+
best = Math.min(best, closestPointOnBezier(qs, p).d);
|
|
22
|
+
}
|
|
23
|
+
worst = Math.max(worst, best);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return worst;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
// a handful of 'from' curves of all orders
|
|
31
|
+
const As: number[][][] = [
|
|
32
|
+
[[0,0], [100,0]], // a line
|
|
33
|
+
[[0,0], [50,30], [100,0]], // a quadratic
|
|
34
|
+
[[0,0], [30,40], [70,-40], [100,0]], // a cubic with an inflection
|
|
35
|
+
[[0,0], [10,80], [90,80], [100,0]], // a 'tall' cubic
|
|
36
|
+
[[0,0], [100,0], [0,0]], // a degenerate (folded) quadratic
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
// a handful of 'to' curves
|
|
40
|
+
const Bs: number[][][] = [
|
|
41
|
+
[[0,1], [100,1]], // a line (offset by 1)
|
|
42
|
+
[[0,0], [50,10], [100,0]], // a quadratic
|
|
43
|
+
[[0,0], [50,-10], [100,0]], // a quadratic bending the other way
|
|
44
|
+
[[-10,5], [40,60], [110,-20]], // a quadratic not sharing endpoints
|
|
45
|
+
[[0,0], [30,10], [70,10], [100,0]], // a cubic
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
// relative margin beyond which the answers must certainly agree
|
|
49
|
+
const MARGIN = 2**-10;
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
describe('hausdorffDistanceOneSidedExceeds', function() {
|
|
53
|
+
test('agrees with the computed one-sided Hausdorff distance (single curve B)', function() {
|
|
54
|
+
let checks = 0;
|
|
55
|
+
for (const A of As) {
|
|
56
|
+
for (const B of Bs) {
|
|
57
|
+
// a very accurate reference value
|
|
58
|
+
const hd = hausdorffDistanceOneSided(A, B, 2**-30, 10_000);
|
|
59
|
+
expect(hd).toBeGreaterThan(0);
|
|
60
|
+
|
|
61
|
+
// tolerances on both sides of the reference value (a large
|
|
62
|
+
// iteration budget is given since certifying a distance that
|
|
63
|
+
// is *just* within tolerance requires resolving the curve to
|
|
64
|
+
// within the margin - e.g. the folded quadratic is at a
|
|
65
|
+
// uniform distance of 1 from the first line)
|
|
66
|
+
for (const f of [1/4, 1/2, 1 - 2*MARGIN, 1 + 2*MARGIN, 2, 4]) {
|
|
67
|
+
const tolerance = f*hd;
|
|
68
|
+
const exceeds = hausdorffDistanceOneSidedExceeds(A, [B], tolerance, 1_000_000);
|
|
69
|
+
expect(exceeds).toBe(hd > tolerance);
|
|
70
|
+
checks++;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
expect(checks).toBe(As.length*Bs.length*6);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('agrees with a densely sampled one-sided Hausdorff distance (piecewise B)', function() {
|
|
78
|
+
// piecewise 'to' curves - two quads joined at a point, and two
|
|
79
|
+
// disconnected pieces
|
|
80
|
+
const Bss: number[][][][] = [
|
|
81
|
+
[[[0,0], [25,20], [50,10]], [[50,10], [75,0], [100,0]]],
|
|
82
|
+
[[[0,2], [40,2]], [[60,-2], [100,-2]]],
|
|
83
|
+
[[[0,0], [30,10], [50,0]], [[50,0], [70,-10], [100,0]]],
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
for (const A of As) {
|
|
87
|
+
for (const Bs of Bss) {
|
|
88
|
+
const hd = sampledHausdorffDistanceOneSided(A, Bs);
|
|
89
|
+
expect(hd).toBeGreaterThan(0);
|
|
90
|
+
|
|
91
|
+
// the sampled value is a lower bound accurate to about
|
|
92
|
+
// `speed/4096` which is ~0.05 here, so stay well clear of it
|
|
93
|
+
expect(hausdorffDistanceOneSidedExceeds(A, Bs, hd*(1 - 2**-3), 1000)).toBe(true);
|
|
94
|
+
expect(hausdorffDistanceOneSidedExceeds(A, Bs, hd*(1 + 2**-3), 1000)).toBe(false);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('decides trivially for a point or line to a line', function() {
|
|
100
|
+
const B = [[[0,1], [100,1]]];
|
|
101
|
+
expect(hausdorffDistanceOneSidedExceeds([[50,0]], B, 0.5)).toBe(true);
|
|
102
|
+
expect(hausdorffDistanceOneSidedExceeds([[50,0]], B, 1.5)).toBe(false);
|
|
103
|
+
expect(hausdorffDistanceOneSidedExceeds([[0,0], [100,0]], B, 0.5)).toBe(true);
|
|
104
|
+
expect(hausdorffDistanceOneSidedExceeds([[0,0], [100,0]], B, 1.5)).toBe(false);
|
|
105
|
+
// a line to a line not parallel to it - the max is at an endpoint
|
|
106
|
+
expect(hausdorffDistanceOneSidedExceeds([[0,0], [100,0]], [[[0,0], [100,10]]], 9.9)).toBe(true);
|
|
107
|
+
expect(hausdorffDistanceOneSidedExceeds([[0,0], [100,0]], [[[0,0], [100,10]]], 10.1)).toBe(false);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test('is conservative when the iteration budget is exhausted', function() {
|
|
111
|
+
// the endpoints of `A` lie on `B` but the middle is 10 away; the
|
|
112
|
+
// initial upper bound is half the control polygon length (~54) so
|
|
113
|
+
// with no bisections allowed a tolerance of 30 cannot be certified
|
|
114
|
+
// either way and the check must fail
|
|
115
|
+
const A = [[0,0], [50,20], [100,0]];
|
|
116
|
+
const B = [[[0,0], [100,0]]];
|
|
117
|
+
expect(hausdorffDistanceOneSidedExceeds(A, B, 30, 0)).toBe(true);
|
|
118
|
+
// with a budget it decides correctly
|
|
119
|
+
expect(hausdorffDistanceOneSidedExceeds(A, B, 30, 50)).toBe(false);
|
|
120
|
+
expect(hausdorffDistanceOneSidedExceeds(A, B, 9.9, 50)).toBe(true);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test('distanceToCurves is the minimum over the pieces', function() {
|
|
124
|
+
const Bs = [[[0,0], [100,0]], [[0,10], [100,10]]];
|
|
125
|
+
expect(distanceToCurves([50,2], Bs)).toBeCloseTo(2, 12);
|
|
126
|
+
expect(distanceToCurves([50,8], Bs)).toBeCloseTo(2, 12);
|
|
127
|
+
expect(distanceToCurves([150,0], Bs)).toBeCloseTo(50, 12);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { expect, test } from '@jest/globals';
|
|
2
|
+
import { getPathsFromStr } from 'flo-boolean';
|
|
3
|
+
import { closestPointOnBezier, evalDeCasteljau } from 'flo-bezier3';
|
|
4
|
+
import { distanceBetween } from 'flo-vector2d';
|
|
5
|
+
import { findMats } from '../../src/find-mat/find-mats.js';
|
|
6
|
+
import { simplifyMat } from '../../src/mat/simplify-mat.js';
|
|
7
|
+
import { getAllOnLoop } from '../../src/cp-node/fs/get-all-on-loop.js';
|
|
8
|
+
import { getMatCurveToNext } from '../../src/cp-node/fs/get-mat-curve-to-next.js';
|
|
9
|
+
import { isTerminating } from '../../src/cp-node/fs/is-terminating.js';
|
|
10
|
+
import type { CpNode } from '../../src/cp-node/cp-node.js';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/** All the bezier pieces making up the MAT. */
|
|
14
|
+
function getMatBeziers(cpNode: CpNode): number[][][] {
|
|
15
|
+
return getAllOnLoop(cpNode)
|
|
16
|
+
.filter(cp => !isTerminating(cp))
|
|
17
|
+
.flatMap(getMatCurveToNext);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The one-sided Hausdorff distance from the curves `A` to the curves `B`,
|
|
23
|
+
* approximated by sampling points on `A`.
|
|
24
|
+
*/
|
|
25
|
+
function sampledHausdorffDistanceOneSided(
|
|
26
|
+
A: number[][][],
|
|
27
|
+
B: number[][][],
|
|
28
|
+
samplesPerCurve = 16): number {
|
|
29
|
+
|
|
30
|
+
let worst = 0;
|
|
31
|
+
for (const ps of A) {
|
|
32
|
+
for (let i=0; i<=samplesPerCurve; i++) {
|
|
33
|
+
const p = evalDeCasteljau(ps, i/samplesPerCurve);
|
|
34
|
+
let best = Infinity;
|
|
35
|
+
for (const qs of B) {
|
|
36
|
+
const { p: q } = closestPointOnBezier(qs, p);
|
|
37
|
+
best = Math.min(best, distanceBetween(p, q));
|
|
38
|
+
}
|
|
39
|
+
worst = Math.max(worst, best);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return worst;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
test('simplifyMat', function() {
|
|
48
|
+
// A smooth blob: its MAT is a single long branch made up of very many
|
|
49
|
+
// 2-prongs, so there is a lot to simplify.
|
|
50
|
+
const loops = getPathsFromStr(
|
|
51
|
+
'M0 0 C 50 -40 150 -40 200 0 C 250 40 250 80 200 120 ' +
|
|
52
|
+
'C 150 160 50 160 0 120 C -50 80 -50 40 0 0 Z'
|
|
53
|
+
);
|
|
54
|
+
const [mat] = findMats(loops, { simplify: false, applySat: false });
|
|
55
|
+
const original = getMatBeziers(mat.cpNode);
|
|
56
|
+
const originalCount = getAllOnLoop(mat.cpNode).length;
|
|
57
|
+
const originalTreeSizes = [...mat.meta.cpTrees.values()].map(t => t.size);
|
|
58
|
+
|
|
59
|
+
const hausdorffTolerance = 2**-3;
|
|
60
|
+
const simplified = simplifyMat(mat, hausdorffTolerance);
|
|
61
|
+
const simplifiedBeziers = getMatBeziers(simplified.cpNode);
|
|
62
|
+
|
|
63
|
+
// it did simplify...
|
|
64
|
+
expect(getAllOnLoop(simplified.cpNode).length).toBeLessThan(originalCount);
|
|
65
|
+
expect(simplifiedBeziers.length).toBeLessThan(original.length);
|
|
66
|
+
|
|
67
|
+
// ...but stayed within the tolerance: no point of the original MAT is
|
|
68
|
+
// further than `hausdorffTolerance` from the simplified MAT (the tolerance
|
|
69
|
+
// is a certified bound, up to floating point roundoff)
|
|
70
|
+
const hd = sampledHausdorffDistanceOneSided(original, simplifiedBeziers);
|
|
71
|
+
expect(hd).toBeLessThanOrEqual(hausdorffTolerance * (1 + 2**-20));
|
|
72
|
+
|
|
73
|
+
// the input MAT is left intact - its linked list *and* its `cpTrees`
|
|
74
|
+
expect(getAllOnLoop(mat.cpNode).length).toBe(originalCount);
|
|
75
|
+
expect([...mat.meta.cpTrees.values()].map(t => t.size)).toEqual(originalTreeSizes);
|
|
76
|
+
|
|
77
|
+
// the simplified MAT has its own `cpTrees`, consistent with its nodes
|
|
78
|
+
expect(simplified.meta.cpTrees).not.toBe(mat.meta.cpTrees);
|
|
79
|
+
const simplifiedNodes = getAllOnLoop(simplified.cpNode);
|
|
80
|
+
for (const [loop, tree] of simplified.meta.cpTrees) {
|
|
81
|
+
const onLoop = simplifiedNodes.filter(cp => cp.pointOnShape.curve.loop === loop);
|
|
82
|
+
expect(tree.size).toBe(onLoop.length);
|
|
83
|
+
for (const cp of onLoop) { expect(tree.find(cp)?.datum).toBe(cp); }
|
|
84
|
+
}
|
|
85
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { expect, test } from '@jest/globals';
|
|
2
|
+
import { reconstructFromMats } from '../../src/reconstruct-from-mat/reconstruct-from-mat.js';
|
|
3
|
+
import { getAllOnLoop } from '../../src/cp-node/fs/get-all-on-loop.js';
|
|
4
|
+
import { getMatsWithHole } from '../get-mats-with-hole.js';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
test('reconstructFromMats - does not modify the given MATs', function() {
|
|
8
|
+
// (the fixture is SAT-processed, so SAT-induced trivial 3-prongs - which
|
|
9
|
+
// `reconstructFromMats` removes before reconstructing - may be present)
|
|
10
|
+
const mats = getMatsWithHole();
|
|
11
|
+
const before = mats.map(mat => ({
|
|
12
|
+
cpNode: mat.cpNode,
|
|
13
|
+
nodes: getAllOnLoop(mat.cpNode),
|
|
14
|
+
links: getAllOnLoop(mat.cpNode).map(cp =>
|
|
15
|
+
[cp.prev, cp.next, cp.prevOnCircle, cp.nextOnCircle]
|
|
16
|
+
)
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
const piecesss = reconstructFromMats(mats);
|
|
20
|
+
expect(piecesss.length).toBe(mats.length);
|
|
21
|
+
for (const piecess of piecesss) {
|
|
22
|
+
for (const pieces of piecess) { expect(pieces.length).toBeGreaterThan(0); }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// same start node, same nodes, same links
|
|
26
|
+
mats.forEach((mat, i) => {
|
|
27
|
+
expect(mat.cpNode).toBe(before[i].cpNode);
|
|
28
|
+
const nodes = getAllOnLoop(mat.cpNode);
|
|
29
|
+
expect(nodes.length).toBe(before[i].nodes.length);
|
|
30
|
+
expect(nodes.every((cp, k) => cp === before[i].nodes[k])).toBe(true);
|
|
31
|
+
nodes.forEach((cp, k) => {
|
|
32
|
+
const [prev, next, prevOnCircle, nextOnCircle] = before[i].links[k];
|
|
33
|
+
expect(cp.prev).toBe(prev);
|
|
34
|
+
expect(cp.next).toBe(next);
|
|
35
|
+
expect(cp.prevOnCircle).toBe(prevOnCircle);
|
|
36
|
+
expect(cp.nextOnCircle).toBe(nextOnCircle);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -7,6 +7,20 @@
|
|
|
7
7
|
<glyph glyph-name=".notdef" horiz-adv-x="500"
|
|
8
8
|
d="M15 609v-593h469v593h-469zM500 0h-500v625h500v-625z" />
|
|
9
9
|
|
|
10
|
+
<glyph glyph-name="Q_V2"
|
|
11
|
+
d="
|
|
12
|
+
M 600 700
|
|
13
|
+
L 570 670
|
|
14
|
+
L 551.4300900092946 724.4845356715714
|
|
15
|
+
C 550.4300900092946 726.2165864791402 550.2961154130791 728.4486372867091 550.6621408168635 729.8146626904936
|
|
16
|
+
C 550.0281662206479 732.9127389018469 550.7602170282167 735.6447897094158 551.4922678357857 738.3768405169847
|
|
17
|
+
C 552.3582932395701 738.8768405169847 552.7243186433545 740.2428659207691 552.7243186433545 740.2428659207691
|
|
18
|
+
C 554.6884202584923 744.8409421321223 558.5185472774145 748.2069675359069 562.8486742963368 750.7069675359069
|
|
19
|
+
C 568.0448267190433 753.7069675359069 573.3749537379655 754.474916728338 578.3390553531033 753.8768405169847
|
|
20
|
+
z
|
|
21
|
+
"
|
|
22
|
+
/>
|
|
23
|
+
|
|
10
24
|
<glyph glyph-name="Q_V" unicode="" horiz-adv-x="750"
|
|
11
25
|
d="
|
|
12
26
|
M 1154.0678381635485 290.68533730950645
|