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
|
@@ -1,7 +1,72 @@
|
|
|
1
1
|
import { expect, test } from '@jest/globals';
|
|
2
|
+
import { distanceBetween } from 'flo-vector2d';
|
|
2
3
|
import { getSalience } from '../../../src/cp-node/fs/get-salience.js';
|
|
4
|
+
import { getBoundaryBeziersBetween } from '../../../src/cp-node/fs/get-boundary-beziers-between.js';
|
|
5
|
+
import { getAllOnLoop } from '../../../src/cp-node/fs/get-all-on-loop.js';
|
|
6
|
+
import { getAllOnLoop_ByLoop } from '../../../src/cp-node/fs/get-all-on-loop-by-loop.js';
|
|
7
|
+
import { getRealProngCount } from '../../../src/cp-node/fs/get-real-prong-count.js';
|
|
8
|
+
import { getMats1 } from '../../get-mats1.js';
|
|
9
|
+
import { getMatsWithHole } from '../../get-mats-with-hole.js';
|
|
10
|
+
import { cpNodesByIdOn } from '../../helpers/cp-node-by-id.js';
|
|
3
11
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
12
|
+
|
|
13
|
+
test('getSalience', function() {
|
|
14
|
+
const { cpNode } = getMats1()[0];
|
|
15
|
+
const byId = cpNodesByIdOn(cpNode);
|
|
16
|
+
|
|
17
|
+
// Salience = (boundary length from this contact point forward to the next
|
|
18
|
+
// contact point on the circle) / (straight distance between them).
|
|
19
|
+
|
|
20
|
+
{
|
|
21
|
+
// 2-prong {10,11} touching [46,8] and a point on the other edge of the
|
|
22
|
+
// corner [24,8]: from id 11 the boundary runs to the corner and on to
|
|
23
|
+
// [46,8] - two equal tangent lengths of 22.
|
|
24
|
+
const cp = byId(11);
|
|
25
|
+
const d = distanceBetween(cp.pointOnShape.p, cp.nextOnCircle.pointOnShape.p);
|
|
26
|
+
expect(getSalience(cp)).toBeCloseTo(44/d, 9);
|
|
27
|
+
}
|
|
28
|
+
{
|
|
29
|
+
// 3-prong {142,143,144}: from [46,8] (id 144) forward to [117,8]
|
|
30
|
+
// (id 142) the boundary goes round the top of the rectangle:
|
|
31
|
+
// 46 + 71 + 46 = 163, against a chord of 71.
|
|
32
|
+
expect(getSalience(byId(144))).toBeCloseTo(163/71, 9);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// the boundary is never shorter than the chord
|
|
36
|
+
for (const cp of getAllOnLoop(cpNode)) {
|
|
37
|
+
if (getRealProngCount(cp) < 2) { continue; } // 1-prongs: see below
|
|
38
|
+
const s = getSalience(cp);
|
|
39
|
+
expect(Number.isFinite(s)).toBe(true);
|
|
40
|
+
expect(s).toBeGreaterThanOrEqual(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 1-prongs (two nodes at the same point): the terminating node has no
|
|
44
|
+
// boundary between itself and its twin - salience 0 - while the twin has
|
|
45
|
+
// the entire boundary - salience Infinity. Ids 0 and 1 at the corner
|
|
46
|
+
// [24,8] are such a pair.
|
|
47
|
+
expect(getSalience(byId(0))).toBe(0);
|
|
48
|
+
expect(getSalience(byId(1))).toBe(Infinity);
|
|
49
|
+
for (const cp of getAllOnLoop(cpNode)) {
|
|
50
|
+
if (getRealProngCount(cp) >= 2) { continue; }
|
|
51
|
+
const s = getSalience(cp);
|
|
52
|
+
expect(Number.isNaN(s)).toBe(false);
|
|
53
|
+
expect(s === 0 || s === Infinity).toBe(true);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
test('getSalience - hole closers', function() {
|
|
59
|
+
const { cpNode } = getMatsWithHole()[0];
|
|
60
|
+
|
|
61
|
+
// a stretch of boundary passing a hole closer has infinite salience
|
|
62
|
+
const cpNodes = getAllOnLoop_ByLoop(cpNode).flat();
|
|
63
|
+
let infinite = 0;
|
|
64
|
+
for (const cp of cpNodes) {
|
|
65
|
+
const { hasHoleCloser } = getBoundaryBeziersBetween(cp, cp.nextOnCircle);
|
|
66
|
+
if (hasHoleCloser) {
|
|
67
|
+
infinite++;
|
|
68
|
+
expect(getSalience(cp)).toBe(Infinity);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
expect(infinite).toBeGreaterThan(0);
|
|
7
72
|
});
|
|
@@ -1,7 +1,44 @@
|
|
|
1
1
|
import { expect, test } from '@jest/globals';
|
|
2
2
|
import { getVertexForwardChildren } from '../../../src/cp-node/fs/get-vertex-forward-children.js';
|
|
3
|
+
import { getAllOnLoop } from '../../../src/cp-node/fs/get-all-on-loop.js';
|
|
4
|
+
import { getAllOnCircle } from '../../../src/cp-node/fs/get-all-on-circle.js';
|
|
5
|
+
import { isTerminating } from '../../../src/cp-node/fs/is-terminating.js';
|
|
6
|
+
import { getMats1 } from '../../get-mats1.js';
|
|
7
|
+
import { cpNodesByIdOn } from '../../helpers/cp-node-by-id.js';
|
|
3
8
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
9
|
+
|
|
10
|
+
test('getVertexForwardChildren', function() {
|
|
11
|
+
const { cpNode } = getMats1()[0];
|
|
12
|
+
const byId = cpNodesByIdOn(cpNode);
|
|
13
|
+
const childIds = (id: number) => getVertexForwardChildren(byId(id)).map(cp => cp.id);
|
|
14
|
+
|
|
15
|
+
// Seen as a vertex entered via the given node (its `prevOnCircle` being
|
|
16
|
+
// the edge back to the parent), the forward children are the far ends of
|
|
17
|
+
// the other edges, in on-circle order.
|
|
18
|
+
expect(childIds(144)).toEqual([147, 148]); // 3-prong: two children
|
|
19
|
+
expect(childIds(142)).toEqual([148, 11]); // same 3-prong, entered differently
|
|
20
|
+
expect(childIds(147)).toEqual([2, 4]); // 3-prong towards two leaves
|
|
21
|
+
expect(childIds(10)).toEqual([144]); // 2-prong: one child
|
|
22
|
+
expect(childIds(1)).toEqual([10]); // leaf, leaving
|
|
23
|
+
expect(childIds(0)).toEqual([]); // leaf, entered - no children
|
|
24
|
+
|
|
25
|
+
for (const cp of getAllOnLoop(cpNode)) {
|
|
26
|
+
const children = getVertexForwardChildren(cp);
|
|
27
|
+
|
|
28
|
+
// one child per non-terminating node on the circle other than the one
|
|
29
|
+
// leading back
|
|
30
|
+
const ring = getAllOnCircle(cp);
|
|
31
|
+
const expected = ring
|
|
32
|
+
.filter(c => c !== cp.prevOnCircle && !isTerminating(c))
|
|
33
|
+
.map(c => c.next);
|
|
34
|
+
expect(children.length).toBe(expected.length);
|
|
35
|
+
expect(children.every((c, i) => c === expected[i])).toBe(true);
|
|
36
|
+
|
|
37
|
+
for (const child of children) {
|
|
38
|
+
// a child is reached by an edge from this vertex...
|
|
39
|
+
expect(child.prev.pointOnShape.circle).toBe(cp.pointOnShape.circle);
|
|
40
|
+
// ...to a different vertex
|
|
41
|
+
expect(child.pointOnShape.circle).not.toBe(cp.pointOnShape.circle);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
7
44
|
});
|
|
@@ -1,7 +1,91 @@
|
|
|
1
1
|
import { expect, test } from '@jest/globals';
|
|
2
|
+
import { RbTree } from 'flo-ll-rb-tree';
|
|
3
|
+
import type { CpNode } from '../../../src/cp-node/cp-node.js';
|
|
4
|
+
import type { PointOnShape } from '../../../src/point-on-shape/point-on-shape.js';
|
|
2
5
|
import { insertCpNode } from '../../../src/cp-node/fs/insert-cp-node.js';
|
|
6
|
+
import { cpNodeComparator } from '../../../src/cp-node/fs/cp-node-comparator.js';
|
|
7
|
+
import { getAllOnLoop } from '../../../src/cp-node/fs/get-all-on-loop.js';
|
|
8
|
+
import { getMats1 } from '../../get-mats1.js';
|
|
9
|
+
import { cpNodesByIdOn } from '../../helpers/cp-node-by-id.js';
|
|
3
10
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
11
|
+
|
|
12
|
+
/** A point on the shape (on the curve of the given node at `t`) with a zero disk. */
|
|
13
|
+
function posOnCurveOf(cpNode: CpNode, t: number, p: number[]): PointOnShape {
|
|
14
|
+
return {
|
|
15
|
+
curve: cpNode.pointOnShape.curve, t, p,
|
|
16
|
+
pDd: [[0,p[0]],[0,p[1]]], isSource: true,
|
|
17
|
+
circle: { center: p, radius: 0 }, order: 0, order2: 0
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
test('insertCpNode', function() {
|
|
23
|
+
const { cpNode } = getMats1()[0];
|
|
24
|
+
const byId = cpNodesByIdOn(cpNode);
|
|
25
|
+
const all = getAllOnLoop(cpNode);
|
|
26
|
+
const cpTree = new RbTree<CpNode>(cpNodeComparator);
|
|
27
|
+
for (const cp of all) { cpTree.insert(cp); }
|
|
28
|
+
const lastInsertId = { id: 1000 };
|
|
29
|
+
|
|
30
|
+
// insert between [24,8] (id 1, end of curve 0) and [46,8] (id 10, end of
|
|
31
|
+
// curve 1) a point halfway along curve 1
|
|
32
|
+
const pred = byId(1);
|
|
33
|
+
const succ = byId(10);
|
|
34
|
+
const pos = posOnCurveOf(succ, 0.5, [35, 8]);
|
|
35
|
+
const inserted = insertCpNode(false, false, false, cpTree, pos, pred, succ, lastInsertId)!;
|
|
36
|
+
|
|
37
|
+
expect(inserted).toBeDefined();
|
|
38
|
+
expect(inserted.id).toBe(1000);
|
|
39
|
+
expect(lastInsertId.id).toBe(1001);
|
|
40
|
+
expect(inserted.pointOnShape).toBe(pos);
|
|
41
|
+
expect(inserted.isHoleClosing).toBe(false);
|
|
42
|
+
expect(inserted.isIntersection).toBe(false);
|
|
43
|
+
// linked into the loop...
|
|
44
|
+
expect(inserted.prev).toBe(pred);
|
|
45
|
+
expect(inserted.next).toBe(succ);
|
|
46
|
+
expect(pred.next).toBe(inserted);
|
|
47
|
+
expect(succ.prev).toBe(inserted);
|
|
48
|
+
expect(getAllOnLoop(cpNode).length).toBe(all.length + 1);
|
|
49
|
+
// ...and into the tree, in order
|
|
50
|
+
expect(cpTree.find(inserted)?.datum).toBe(inserted);
|
|
51
|
+
expect(cpTree.size).toBe(all.length + 1);
|
|
52
|
+
const inOrder = cpTree.toArr();
|
|
53
|
+
expect(inOrder.length).toBe(all.length + 1);
|
|
54
|
+
expect(inOrder[inOrder.indexOf(pred) + 1]).toBe(inserted);
|
|
55
|
+
expect(inOrder[inOrder.indexOf(inserted) + 1]).toBe(succ);
|
|
56
|
+
// the on-circle edges are left for the caller to set
|
|
57
|
+
expect(inserted.nextOnCircle).toBeUndefined();
|
|
58
|
+
expect(inserted.prevOnCircle).toBeUndefined();
|
|
59
|
+
|
|
60
|
+
{
|
|
61
|
+
// A point on curve 3 does not belong between ids 1 and 10 - refused
|
|
62
|
+
// unless told to insert regardless. (At t=0.25 - not t=0.5 where id
|
|
63
|
+
// 145 already sits, which the tree would treat as a duplicate.)
|
|
64
|
+
const wrongPos = posOnCurveOf(byId(145), 0.25, [63.75, 54]);
|
|
65
|
+
const r = insertCpNode(false, false, false, cpTree, wrongPos, pred, inserted, lastInsertId);
|
|
66
|
+
expect(r).toBeUndefined();
|
|
67
|
+
expect(pred.next).toBe(inserted);
|
|
68
|
+
expect(cpTree.size).toBe(all.length + 1);
|
|
69
|
+
expect(lastInsertId.id).toBe(1001);
|
|
70
|
+
|
|
71
|
+
const forced = insertCpNode(true, true, true, cpTree, wrongPos, pred, inserted, lastInsertId)!;
|
|
72
|
+
expect(forced).toBeDefined();
|
|
73
|
+
expect(forced.id).toBe(1001);
|
|
74
|
+
expect(forced.isHoleClosing).toBe(true);
|
|
75
|
+
expect(forced.isIntersection).toBe(true);
|
|
76
|
+
expect(pred.next).toBe(forced);
|
|
77
|
+
expect(forced.next).toBe(inserted);
|
|
78
|
+
expect(inserted.prev).toBe(forced);
|
|
79
|
+
expect(cpTree.size).toBe(all.length + 2);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
{
|
|
83
|
+
// without a predecessor the node starts a loop of its own
|
|
84
|
+
const emptyTree = new RbTree<CpNode>(cpNodeComparator);
|
|
85
|
+
const lone = insertCpNode(false, false, false, emptyTree, pos, undefined, undefined, lastInsertId)!;
|
|
86
|
+
expect(lone.next).toBe(lone);
|
|
87
|
+
expect(lone.prev).toBe(lone);
|
|
88
|
+
expect(emptyTree.size).toBe(1);
|
|
89
|
+
expect(emptyTree.toArr()[0]).toBe(lone);
|
|
90
|
+
}
|
|
7
91
|
});
|
|
@@ -10,7 +10,7 @@ test('isSpecial', function() {
|
|
|
10
10
|
const allOnLoop = getAllOnLoop(cpNode);
|
|
11
11
|
|
|
12
12
|
for (const n of allOnLoop) {
|
|
13
|
-
const expected = getRealProngCount(n) !== 2
|
|
13
|
+
const expected = getRealProngCount(n) !== 2 || n.isHoleClosing;
|
|
14
14
|
expect(isSpecial(n)).toBe(expected);
|
|
15
15
|
}
|
|
16
16
|
});
|
|
@@ -1,7 +1,46 @@
|
|
|
1
1
|
import { expect, test } from '@jest/globals';
|
|
2
|
+
import { RbTree } from 'flo-ll-rb-tree';
|
|
3
|
+
import type { CpNode } from '../../../src/cp-node/cp-node.js';
|
|
4
|
+
import type { MatMeta } from '../../../src/mat/mat-meta.js';
|
|
2
5
|
import { removeCpNode } from '../../../src/cp-node/fs/remove-cp-node.js';
|
|
6
|
+
import { cpNodeComparator } from '../../../src/cp-node/fs/cp-node-comparator.js';
|
|
7
|
+
import { getAllOnLoop } from '../../../src/cp-node/fs/get-all-on-loop.js';
|
|
8
|
+
import { getMats1 } from '../../get-mats1.js';
|
|
9
|
+
import { cpNodesByIdOn } from '../../helpers/cp-node-by-id.js';
|
|
3
10
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
11
|
+
|
|
12
|
+
test('removeCpNode', function() {
|
|
13
|
+
const { cpNode } = getMats1()[0];
|
|
14
|
+
const byId = cpNodesByIdOn(cpNode);
|
|
15
|
+
const all = getAllOnLoop(cpNode);
|
|
16
|
+
|
|
17
|
+
const loop = cpNode.pointOnShape.curve.loop;
|
|
18
|
+
const cpTree = new RbTree<CpNode>(cpNodeComparator);
|
|
19
|
+
for (const cp of all) { cpTree.insert(cp); }
|
|
20
|
+
const meta = { cpTrees: new Map([[loop, cpTree]]) } as unknown as MatMeta;
|
|
21
|
+
|
|
22
|
+
const cp = byId(10);
|
|
23
|
+
const prev = cp.prev; // id 1
|
|
24
|
+
const next = cp.next; // id 144
|
|
25
|
+
expect(cpTree.find(cp)?.datum).toBe(cp);
|
|
26
|
+
|
|
27
|
+
removeCpNode(cp, meta);
|
|
28
|
+
|
|
29
|
+
// (compare `CpNode`s by identity / id only - they are circular structures
|
|
30
|
+
// that must not be deep-compared)
|
|
31
|
+
|
|
32
|
+
// unlinked from the loop...
|
|
33
|
+
expect(prev.next).toBe(next);
|
|
34
|
+
expect(next.prev).toBe(prev);
|
|
35
|
+
const remaining = getAllOnLoop(cpNode);
|
|
36
|
+
expect(remaining.length).toBe(all.length - 1);
|
|
37
|
+
expect(remaining.includes(cp)).toBe(false);
|
|
38
|
+
// ...and from the tree, with everything else still there
|
|
39
|
+
expect(cpTree.find(cp)).toBeUndefined();
|
|
40
|
+
expect(cpTree.size).toBe(all.length - 1);
|
|
41
|
+
const expectedIds = all.filter(c => c !== cp).sort(cpNodeComparator).map(c => c.id);
|
|
42
|
+
expect(cpTree.toArr().map(c => c.id)).toEqual(expectedIds);
|
|
43
|
+
// the removed node itself is left untouched
|
|
44
|
+
expect(cp.prev).toBe(prev);
|
|
45
|
+
expect(cp.next).toBe(next);
|
|
7
46
|
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { expect, test } from '@jest/globals';
|
|
2
|
+
import { calcSquaredSeperationTolerance } from '../../src/find-2-prong/calc-seperation-tolerance.js';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Reference: the squared chord `(2r·sin(θ/2))²` with `θ` from the law of
|
|
7
|
+
* cosines formulation, computed via `1 - cos θ` to avoid cancellation.
|
|
8
|
+
*/
|
|
9
|
+
function refSquaredChord(R: number, r: number, δ: number) {
|
|
10
|
+
const oneMinusCos = (R*δ + δ*δ/2) / ((R - r)*(r + δ));
|
|
11
|
+
const θ = 2*Math.asin(Math.sqrt(oneMinusCos/2));
|
|
12
|
+
return (2*r*Math.sin(θ/2))**2;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
test('calcSquaredSeperationTolerance', function() {
|
|
17
|
+
// a spread of osculating radii, MAT radii and (tiny) distance tolerances
|
|
18
|
+
const cases: [number, number, number][] = [
|
|
19
|
+
[100, 50, 2**-34], [100, 99, 2**-34], [1000, 0.5, 2**-30],
|
|
20
|
+
[100, 99.999, 2**-34], [37.3, 12.1, 2**-40], [2**20, 1000, 2**-24],
|
|
21
|
+
];
|
|
22
|
+
for (const [R, r, δ] of cases) {
|
|
23
|
+
const d2 = calcSquaredSeperationTolerance(R, r, δ);
|
|
24
|
+
expect(Number.isFinite(d2)).toBe(true);
|
|
25
|
+
expect(d2).toBeGreaterThan(0);
|
|
26
|
+
// agrees with the trigonometric reference
|
|
27
|
+
expect(d2 / refSquaredChord(R, r, δ)).toBeCloseTo(1, 12);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// the closer the MAT radius gets to the osculating radius (a near
|
|
31
|
+
// 1-prong) the larger the separation required
|
|
32
|
+
const grow = [10, 50, 90, 99, 99.9].map(r => calcSquaredSeperationTolerance(100, r, 2**-34));
|
|
33
|
+
for (let i=1; i<grow.length; i++) { expect(grow[i]).toBeGreaterThan(grow[i-1]); }
|
|
34
|
+
|
|
35
|
+
// ...and a larger error tolerance requires more separation too
|
|
36
|
+
expect(calcSquaredSeperationTolerance(100, 50, 2**-30))
|
|
37
|
+
.toBeGreaterThan(calcSquaredSeperationTolerance(100, 50, 2**-34));
|
|
38
|
+
|
|
39
|
+
// the enlarged MAT circle reaching the osculating circle: reject everything
|
|
40
|
+
expect(calcSquaredSeperationTolerance(100, 100, 2**-34)).toBe(Infinity);
|
|
41
|
+
expect(calcSquaredSeperationTolerance(100, 100 - 2**-40, 2**-34)).toBe(Infinity);
|
|
42
|
+
expect(calcSquaredSeperationTolerance(100, 120, 2**-34)).toBe(Infinity);
|
|
43
|
+
|
|
44
|
+
// sanity: a concrete value (R=100, r=50, δ=2**-34), chord ~ 1.079e-4
|
|
45
|
+
expect(Math.sqrt(calcSquaredSeperationTolerance(100, 50, 2**-34))).toBeCloseTo(1.078959e-4, 9);
|
|
46
|
+
});
|
|
@@ -5,6 +5,8 @@ import { ddGetMedialPointCoeffsBez2_SameCurve } from '../../../src/get-medial-po
|
|
|
5
5
|
import { ddGetMedialPointCoeffsBez3_SameCurve } from '../../../src/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3-same-curve.js';
|
|
6
6
|
import { ddNormal } from 'flo-bezier3';
|
|
7
7
|
|
|
8
|
+
const { abs, floor } = Math;
|
|
9
|
+
|
|
8
10
|
|
|
9
11
|
function toDdVec(v: number[]): number[][] {
|
|
10
12
|
return v.map(x => [0, x]);
|
|
@@ -17,7 +19,7 @@ function ddPolyToDouble(poly: number[][]): number[] {
|
|
|
17
19
|
function normalizedPoly(poly: number[]): number[] {
|
|
18
20
|
let m = 0;
|
|
19
21
|
for (const x of poly) {
|
|
20
|
-
const ax =
|
|
22
|
+
const ax = abs(x);
|
|
21
23
|
if (ax > m) { m = ax; }
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -34,8 +36,8 @@ function randomNumberIn01(seed: number): number {
|
|
|
34
36
|
|
|
35
37
|
function randomSignedValue(seed: number): number {
|
|
36
38
|
const sign = randomNumberIn01(seed) < 0.5 ? -1 : 1;
|
|
37
|
-
const exponent =
|
|
38
|
-
const mantissa = 1 +
|
|
39
|
+
const exponent = floor(randomNumberIn01(seed + 1) * 61) - 30;
|
|
40
|
+
const mantissa = 1 + floor(randomNumberIn01(seed + 2) * 2**20);
|
|
39
41
|
|
|
40
42
|
return sign * mantissa * 2**exponent;
|
|
41
43
|
}
|
|
@@ -67,7 +69,7 @@ test.skip('dd same-curve coefficients match flo-bezier3 double coefficients', fu
|
|
|
67
69
|
|
|
68
70
|
const n2Dd = ddNormal(ps2, t);
|
|
69
71
|
let v2 = [n2Dd[0][1], n2Dd[1][1]];
|
|
70
|
-
if (
|
|
72
|
+
if (abs(v2[0]) + abs(v2[1]) < 2**-20) {
|
|
71
73
|
v2 = [v2[0] + 1, v2[1] - 1];
|
|
72
74
|
}
|
|
73
75
|
const v2Dd = toDdVec(v2);
|
|
@@ -89,7 +91,7 @@ test.skip('dd same-curve coefficients match flo-bezier3 double coefficients', fu
|
|
|
89
91
|
|
|
90
92
|
const n3Dd = ddNormal(ps3, t);
|
|
91
93
|
let v3 = [n3Dd[0][1], n3Dd[1][1]];
|
|
92
|
-
if (
|
|
94
|
+
if (abs(v3[0]) + abs(v3[1]) < 2**-20) {
|
|
93
95
|
v3 = [v3[0] + 1, v3[1] - 1];
|
|
94
96
|
}
|
|
95
97
|
const v3Dd = toDdVec(v3);
|
|
@@ -3,6 +3,8 @@ import { getMedialPointCoeffs } from 'flo-bezier3';
|
|
|
3
3
|
import { ddGetMedialPointCoeffs } from '../../../src/get-medial-points/double-double/dd-get-medial-point-coeffs.js';
|
|
4
4
|
import { squares } from 'squares-rng';
|
|
5
5
|
|
|
6
|
+
const { floor, abs } = Math;
|
|
7
|
+
|
|
6
8
|
|
|
7
9
|
function toDdVec(v: number[]): number[][] {
|
|
8
10
|
return v.map(x => [0, x]);
|
|
@@ -19,7 +21,7 @@ function randomNumberIn01(seed: number): number {
|
|
|
19
21
|
|
|
20
22
|
function randomSignedValue(seed: number): number {
|
|
21
23
|
const sign = randomNumberIn01(seed) < 0.5 ? -1 : 1;
|
|
22
|
-
const exponent =
|
|
24
|
+
const exponent = floor(randomNumberIn01(seed + 1) * 81) - 40;
|
|
23
25
|
const mantissa = 1 + randomNumberIn01(seed + 2);
|
|
24
26
|
|
|
25
27
|
return sign * mantissa * 2**exponent;
|
|
@@ -46,7 +48,7 @@ test('ddGetMedialPointCoeffs matches flo-bezier3 double coefficients', function(
|
|
|
46
48
|
let v = randomPoint(seed); seed += 11;
|
|
47
49
|
|
|
48
50
|
// Keep the direction away from near-zero vectors.
|
|
49
|
-
if (
|
|
51
|
+
if (abs(v[0]) + abs(v[1]) < 2**-20) {
|
|
50
52
|
v = [v[0] + 1, v[1] - 1];
|
|
51
53
|
}
|
|
52
54
|
|
|
@@ -44,7 +44,7 @@ test('getClosestPoints', function() {
|
|
|
44
44
|
const def = deflate(H,t);//?
|
|
45
45
|
// def = [47279295, -157379071.5, 100304568, -23598664.03125, 1904993.75390625]
|
|
46
46
|
|
|
47
|
-
const r = getClosestPoint(maxPowerOf2,
|
|
47
|
+
const r = getClosestPoint(maxPowerOf2, nnormDd, yPos, for1Prong, angle, curvePiece);
|
|
48
48
|
|
|
49
49
|
r;//?
|
|
50
50
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { expect, test } from '@jest/globals';
|
|
2
|
+
import type { CpNode } from '../../src/cp-node/cp-node.js';
|
|
3
|
+
import { getGraph } from '../../src/floyd-warshall/get-graph.js';
|
|
4
|
+
import { getAllOnLoop } from '../../src/cp-node/fs/get-all-on-loop.js';
|
|
5
|
+
import { getAllOnCircle } from '../../src/cp-node/fs/get-all-on-circle.js';
|
|
6
|
+
import { isVertexSpecial } from '../../src/cp-node/fs/is-vertex-special.js';
|
|
7
|
+
import { getPathsFromStr } from 'flo-boolean';
|
|
8
|
+
import { findMats } from '../../src/find-mat/find-mats.js';
|
|
9
|
+
import { getMats1 } from '../get-mats1.js';
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/** One `CpNode` per special vertex (leaves, 3-prongs, hole closers). */
|
|
13
|
+
function getSpecialVertices(cpNode: CpNode): CpNode[] {
|
|
14
|
+
const seen = new Set<CpNode>();
|
|
15
|
+
const vertices: CpNode[] = [];
|
|
16
|
+
for (const cp of getAllOnLoop(cpNode)) {
|
|
17
|
+
if (seen.has(cp)) { continue; }
|
|
18
|
+
for (const c of getAllOnCircle(cp)) { seen.add(c); }
|
|
19
|
+
if (isVertexSpecial(cp)) { vertices.push(cp); }
|
|
20
|
+
}
|
|
21
|
+
return vertices;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
function checkGraph(graph: number[][], V: number, symmetricLengths: boolean) {
|
|
26
|
+
expect(graph.length).toBe(V);
|
|
27
|
+
for (let i=0; i<V; i++) {
|
|
28
|
+
expect(graph[i].length).toBe(V);
|
|
29
|
+
expect(graph[i][i]).toBe(0);
|
|
30
|
+
let adjacent = 0;
|
|
31
|
+
for (let j=0; j<V; j++) {
|
|
32
|
+
const d = graph[i][j];
|
|
33
|
+
// symmetric adjacency...
|
|
34
|
+
expect(Number.isFinite(graph[j][i])).toBe(Number.isFinite(d));
|
|
35
|
+
// ...and symmetric lengths (up to the summation order of the edge
|
|
36
|
+
// lengths) - except across hole closers, where the two directions
|
|
37
|
+
// currently accumulate slightly different lengths (pre-existing)
|
|
38
|
+
if (symmetricLengths && Number.isFinite(d)) {
|
|
39
|
+
expect(d).toBeCloseTo(graph[j][i], 9);
|
|
40
|
+
}
|
|
41
|
+
expect(d >= 0).toBe(true);
|
|
42
|
+
if (i !== j && Number.isFinite(d)) { adjacent++; }
|
|
43
|
+
}
|
|
44
|
+
// the MAT is connected: every special vertex has a neighbour
|
|
45
|
+
expect(adjacent).toBeGreaterThan(0);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
test('getGraph - single loop fixture', function() {
|
|
51
|
+
const { cpNode } = getMats1()[0];
|
|
52
|
+
const vertices = getSpecialVertices(cpNode);
|
|
53
|
+
// 5 leaves + 3 3-prongs
|
|
54
|
+
expect(vertices.length).toBe(8);
|
|
55
|
+
|
|
56
|
+
const graph = getGraph(vertices);
|
|
57
|
+
checkGraph(graph, vertices.length, true);
|
|
58
|
+
|
|
59
|
+
// the 3-prong {142,143,144} (center [81.5,-12.64]) is adjacent to the
|
|
60
|
+
// 3-prong at [81.5,18.5] by a straight vertical edge of length 31.14...
|
|
61
|
+
const i = vertices.findIndex(v => v.pointOnShape.circle.center[1] === 18.5);
|
|
62
|
+
const j = vertices.findIndex(v => v.pointOnShape.circle.center[1] === -12.641417453935567);
|
|
63
|
+
expect(i).toBeGreaterThanOrEqual(0);
|
|
64
|
+
expect(j).toBeGreaterThanOrEqual(0);
|
|
65
|
+
expect(graph[i][j]).toBeCloseTo(18.5 + 12.641417453935567, 9);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
test('getGraph - shape with a hole (hole closers are skipped via their twins)', function() {
|
|
70
|
+
// (not the SAT-processed fixture: the SAT culls all the spurs of a square
|
|
71
|
+
// frame, leaving only a cycle of 2-prongs and thus no special vertices)
|
|
72
|
+
const loops = getPathsFromStr(
|
|
73
|
+
'M0 0 L100 0 L100 100 L0 100 Z ' +
|
|
74
|
+
'M30 30 L30 70 L70 70 L70 30 Z'
|
|
75
|
+
);
|
|
76
|
+
const { cpNode } = findMats(loops, { applySat: false, simplify: false })[0];
|
|
77
|
+
const vertices = getSpecialVertices(cpNode).filter(v => !v.isHoleClosing);
|
|
78
|
+
// 4 outer-corner leaves + 4 3-prongs where the spurs meet the ring
|
|
79
|
+
expect(vertices.length).toBe(8);
|
|
80
|
+
|
|
81
|
+
// must terminate (the walk over a hole closer continues on the other loop)
|
|
82
|
+
const graph = getGraph(vertices);
|
|
83
|
+
checkGraph(graph, vertices.length, false);
|
|
84
|
+
|
|
85
|
+
// the 4 leaves are each adjacent to exactly one 3-prong (their spur)...
|
|
86
|
+
const leaves = vertices.filter(v => v.pointOnShape.circle.radius === 0);
|
|
87
|
+
expect(leaves.length).toBe(4);
|
|
88
|
+
for (const leaf of leaves) {
|
|
89
|
+
const i = vertices.indexOf(leaf);
|
|
90
|
+
const finite = graph[i].filter((d, j) => j !== i && Number.isFinite(d));
|
|
91
|
+
expect(finite.length).toBe(1);
|
|
92
|
+
}
|
|
93
|
+
// ...and each 3-prong to its spur leaf and its two ring neighbours
|
|
94
|
+
for (const v of vertices) {
|
|
95
|
+
if (v.pointOnShape.circle.radius === 0) { continue; }
|
|
96
|
+
const i = vertices.indexOf(v);
|
|
97
|
+
const finite = graph[i].filter((d, j) => j !== i && Number.isFinite(d));
|
|
98
|
+
expect(finite.length).toBe(3);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Mat } from "../src/mat/mat.js";
|
|
2
|
+
import { getPathsFromStr } from 'flo-boolean';
|
|
3
|
+
import { findMats } from "../src/find-mat/find-mats.js";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// Cache - the tests using this fixture must not mutate it.
|
|
7
|
+
let mats: Mat[] | undefined = undefined;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A square with a square hole - forces hole-closing 2-prongs (which `getMats1`
|
|
11
|
+
* does not have). Unlike `getMats1` this is calculated and thus susceptible to
|
|
12
|
+
* small perturbations in the algorithm, so only test *structural* properties
|
|
13
|
+
* against it.
|
|
14
|
+
*/
|
|
15
|
+
function getMatsWithHole(): Mat[] {
|
|
16
|
+
if (mats) { return mats; }
|
|
17
|
+
|
|
18
|
+
const loops = getPathsFromStr(
|
|
19
|
+
'M0 0 L100 0 L100 100 L0 100 Z ' +
|
|
20
|
+
'M30 30 L30 70 L70 70 L70 30 Z'
|
|
21
|
+
);
|
|
22
|
+
mats = findMats(loops, {});
|
|
23
|
+
|
|
24
|
+
return mats;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
export { getMatsWithHole }
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { expect, test } from '@jest/globals';
|
|
2
|
+
import type { Circle } from '../src/geometry/circle.js';
|
|
3
|
+
import { getMats1, cpNodeStringifyable1 } from './get-mats1.js';
|
|
4
|
+
import { getAllOnCircle } from '../src/cp-node/fs/get-all-on-circle.js';
|
|
5
|
+
import { getAllOnLoop_ByLoop } from '../src/cp-node/fs/get-all-on-loop-by-loop.js';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
test('`getMats1` fixture: one `Circle` object per on-circle ring', function() {
|
|
9
|
+
{
|
|
10
|
+
// The stringifyable literal itself (before `fromStringifyable`
|
|
11
|
+
// normalizes anything) must already share one `Circle` object per
|
|
12
|
+
// on-circle ring and no `Circle` object across rings.
|
|
13
|
+
const { cpNodes } = cpNodeStringifyable1;
|
|
14
|
+
const byId = new Map(cpNodes.map(cp => [cp.id, cp]));
|
|
15
|
+
|
|
16
|
+
const seen = new Set<number>();
|
|
17
|
+
const ringOfCircle = new Map<Circle, number[]>();
|
|
18
|
+
for (const cpNode of cpNodes) {
|
|
19
|
+
if (seen.has(cpNode.id)) { continue; }
|
|
20
|
+
|
|
21
|
+
// walk the ring via the `nextOnCircle` ids
|
|
22
|
+
const ring: number[] = [];
|
|
23
|
+
let cp = cpNode;
|
|
24
|
+
do {
|
|
25
|
+
ring.push(cp.id);
|
|
26
|
+
seen.add(cp.id);
|
|
27
|
+
cp = byId.get(cp.nextOnCircle as number)!;
|
|
28
|
+
} while (cp !== cpNode);
|
|
29
|
+
|
|
30
|
+
const { circle } = cpNode.pointOnShape;
|
|
31
|
+
for (const id of ring) {
|
|
32
|
+
expect(byId.get(id)!.pointOnShape.circle).toBe(circle);
|
|
33
|
+
}
|
|
34
|
+
expect(ringOfCircle.has(circle)).toBe(false);
|
|
35
|
+
ringOfCircle.set(circle, ring);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
expect(ringOfCircle.size).toBe(10);
|
|
39
|
+
}
|
|
40
|
+
{
|
|
41
|
+
// ...and so does the `CpNode` graph built from it
|
|
42
|
+
const { cpNode } = getMats1()[0];
|
|
43
|
+
const cpNodes = getAllOnLoop_ByLoop(cpNode).flat();
|
|
44
|
+
|
|
45
|
+
const seen = new Set<typeof cpNode>();
|
|
46
|
+
const circles = new Set<Circle>();
|
|
47
|
+
for (const cp of cpNodes) {
|
|
48
|
+
if (seen.has(cp)) { continue; }
|
|
49
|
+
|
|
50
|
+
const { circle } = cp.pointOnShape;
|
|
51
|
+
for (const cp_ of getAllOnCircle(cp)) {
|
|
52
|
+
seen.add(cp_);
|
|
53
|
+
expect(cp_.pointOnShape.circle).toBe(circle);
|
|
54
|
+
}
|
|
55
|
+
expect(circles.has(circle)).toBe(false);
|
|
56
|
+
circles.add(circle);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
expect(circles.size).toBe(10);
|
|
60
|
+
}
|
|
61
|
+
});
|