flo-mat 4.1.5 → 5.0.2
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/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/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 +12985 -9965
- package/browser/index.min.js +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/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.js +6 -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-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 +9 -1
- package/node/cp-node/fs/get-implied-boundary-bezier-between.js +11 -55
- 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 +4 -3
- package/node/cp-node/fs/get-mat-curve-between.js +5 -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 -15
- package/node/cp-node/fs/is-fully-terminating.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 +1 -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 +1 -7
- 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 +35 -41
- 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 +11 -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-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/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 +9 -9
- package/qv-infinite-loop.md +120 -0
- 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 +6 -4
- 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-first-exit.ts +15 -14
- package/src/cp-node/fs/get-implied-boundary-bezier-between.ts +17 -69
- package/src/cp-node/fs/get-mat-curve-between.ts +9 -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 -18
- 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 -75
- 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 +2 -9
- 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 +12 -10
- 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-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/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/get-beziers-from-tangents.ts +110 -0
- package/src/utils/map-map.ts +1 -1
- package/src/vertex/remove-vertex.ts +5 -3
- 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/src/mat/simplify-mat.ts
CHANGED
|
@@ -1,116 +1,254 @@
|
|
|
1
|
-
import type { Mat } from './mat.js';
|
|
2
|
-
import type {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { isTerminating } from '../cp-node/fs/is-terminating.js';
|
|
12
|
-
import {
|
|
13
|
-
import { getProngCount } from '../cp-node/fs/get-prong-count.js';
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
1
|
+
import type { Mat } from './mat.js';
|
|
2
|
+
import type { MatMeta } from './mat-meta.js';
|
|
3
|
+
import type { CpNode } from '../cp-node/cp-node.js';
|
|
4
|
+
import { evalDeCasteljau } from 'flo-bezier3';
|
|
5
|
+
import { removeVertex } from '../vertex/remove-vertex.js';
|
|
6
|
+
import { getBranches } from './get-branches.js';
|
|
7
|
+
import { getMatCurveToNext } from '../cp-node/fs/get-mat-curve-to-next.js';
|
|
8
|
+
import { getMatCurveBetween } from '../cp-node/fs/get-mat-curve-between.js';
|
|
9
|
+
import { createNewCpTrees } from './create-new-cp-trees.js';
|
|
10
|
+
import { clone } from '../cp-node/fs/clone.js';
|
|
11
|
+
import { isTerminating } from '../cp-node/fs/is-terminating.js';
|
|
12
|
+
import { isSpecial } from '../cp-node/fs/is-special.js';
|
|
13
|
+
import { getProngCount } from '../cp-node/fs/get-prong-count.js';
|
|
14
|
+
import { distanceToCurves, hausdorffDistanceOneSidedExceeds } from './hausdorff-distance-one-sided-exceeds.js';
|
|
15
|
+
|
|
16
|
+
const { abs } = Math;
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Spans of at least this many edges whose worst vertex lies within
|
|
21
|
+
* `END_FRACTION` of either end are additionally split at their middle - this
|
|
22
|
+
* guards against the degenerate case where each split peels off only a few
|
|
23
|
+
* edges at an end (making the recursion depth, and the total work, quadratic
|
|
24
|
+
* in the branch length) at the cost of at most one extra curve per occurrence.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
const MIN_EDGES_FOR_BALANCED_SPLIT = 32;
|
|
29
|
+
/** @internal */
|
|
30
|
+
const END_FRACTION = 1/8;
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Returns a new simplified MAT of the given one by replacing the piecewise
|
|
35
|
+
* quad beziers composing the MAT with fewer ones to within a given tolerance.
|
|
36
|
+
*
|
|
37
|
+
* * the vertices of the simplified MAT are a subset of those of the given one
|
|
38
|
+
* (so the endpoints of each new curve are endpoints of existing ones) and all
|
|
39
|
+
* 'special' vertices (leaves, 3-prongs and higher, hole-closers) are kept
|
|
40
|
+
* * each branch is simplified Douglas-Peucker style: the single curve from the
|
|
41
|
+
* start to the end of a span of edges is tried and, if some edge deviates from
|
|
42
|
+
* it by more than the tolerance, the span is split at the vertex of worst
|
|
43
|
+
* deviation and both halves are tried in turn; this is `O(n log n)` (in the
|
|
44
|
+
* number of edges `n` of a branch) Hausdorff distance checks as opposed to the
|
|
45
|
+
* `O(n²)` of greedily extending spans one vertex at a time
|
|
46
|
+
* * the deviation of an edge from the single curve is checked first by cheap
|
|
47
|
+
* sampled *lower* bounds (which already find most splits) and only then by
|
|
48
|
+
* the certified `hausdorffDistanceOneSidedExceeds`
|
|
49
|
+
* * the tolerance is a certified upper bound on the one-sided Hausdorff
|
|
50
|
+
* distance from the original MAT curves to the simplified ones (up to
|
|
51
|
+
* floating point roundoff)
|
|
52
|
+
*
|
|
53
|
+
* @param mat the MAT to simplify (it is not modified)
|
|
54
|
+
* @param hausdorffTolerance the maximum one-sided Hausdorff distance (in
|
|
55
|
+
* coordinate units) from the original to the simplified MAT - defaults to
|
|
56
|
+
* `2**-3`
|
|
57
|
+
* @param maxIterations the max bisections of each Hausdorff distance check
|
|
58
|
+
* (see `hausdorffDistanceOneSidedExceeds`) after which the check conservatively
|
|
59
|
+
* fails (so that the span is split rather than accepted) - defaults to `1000`;
|
|
60
|
+
* lower values trade simplification quality for a bound on the time spent on
|
|
61
|
+
* curves that are only just within tolerance
|
|
62
|
+
*/
|
|
63
|
+
function simplifyMat(
|
|
64
|
+
mat: Mat,
|
|
65
|
+
hausdorffTolerance = 2**-3,
|
|
66
|
+
maxIterations = 1000): Mat {
|
|
67
|
+
|
|
68
|
+
let cpNode = clone(mat.cpNode);
|
|
69
|
+
// The clone gets its own `cpTrees` (removing vertices below must not
|
|
70
|
+
// touch the trees of the given `mat`) - they are kept up to date by
|
|
71
|
+
// `removeVertex`.
|
|
72
|
+
const meta: MatMeta = { ...mat.meta, cpTrees: createNewCpTrees(cpNode) };
|
|
73
|
+
|
|
74
|
+
// Start from a leaf (which is never removed so it can be returned)
|
|
75
|
+
while (!isTerminating(cpNode)) { cpNode = cpNode.next; }
|
|
76
|
+
|
|
77
|
+
const branches = getBranches(cpNode);
|
|
78
|
+
|
|
79
|
+
const toRemove: CpNode[] = [];
|
|
80
|
+
for (let k=0; k<branches.length; k++) {
|
|
81
|
+
simplifyBranch(branches[k], hausdorffTolerance, maxIterations, toRemove);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
for (const cpNode of toRemove) {
|
|
85
|
+
removeVertex(cpNode, meta);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return { cpNode, meta };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Simplifies the given branch by adding the `CpNode`s of the vertices that
|
|
94
|
+
* can be removed to `toRemove`.
|
|
95
|
+
*
|
|
96
|
+
* * edge `k` of the branch runs from `branch[k]` to `branch[k].next`; vertex
|
|
97
|
+
* `k` (for `0 < k < branch.length`) is the interior vertex `branch[k]` between
|
|
98
|
+
* edges `k-1` and `k`
|
|
99
|
+
* * a span of edges `i..j` is simplified to the single curve from the start
|
|
100
|
+
* of edge `i` to the end of edge `j`, removing the interior vertices `i+1..j`
|
|
101
|
+
*
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
104
|
+
function simplifyBranch(
|
|
105
|
+
branch: CpNode[],
|
|
106
|
+
tolerance: number,
|
|
107
|
+
maxIterations: number,
|
|
108
|
+
toRemove: CpNode[]): void {
|
|
109
|
+
|
|
110
|
+
const n = branch.length; // the number of edges
|
|
111
|
+
if (n < 2) { return; }
|
|
112
|
+
|
|
113
|
+
// the MAT curves of the edges of the branch - computed once per branch
|
|
114
|
+
const curves = branch.map(getMatCurveToNext);
|
|
115
|
+
const vertexPoints = branch.map(cpNode => cpNode.pointOnShape.circle.center);
|
|
116
|
+
|
|
117
|
+
// The spans still to be processed; interior vertices that cannot be
|
|
118
|
+
// removed must be kept so the branch is pre-split there: the 'special'
|
|
119
|
+
// ones (e.g. hole-closers) and those whose circle carries more than 2
|
|
120
|
+
// `CpNode`s (e.g. a 2-prong having a terminating sharp corner contact,
|
|
121
|
+
// which `getBranch` passes through but `removeVertex` cannot remove).
|
|
122
|
+
const spans: [number,number][] = [];
|
|
123
|
+
let a = 0;
|
|
124
|
+
for (let k=1; k<n; k++) {
|
|
125
|
+
if (isSpecial(branch[k]) || getProngCount(branch[k]) !== 2) {
|
|
126
|
+
spans.push([a, k-1]);
|
|
127
|
+
a = k;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
spans.push([a, n-1]);
|
|
131
|
+
|
|
132
|
+
while (spans.length > 0) {
|
|
133
|
+
const [i, j] = spans.pop()!;
|
|
134
|
+
if (j <= i) { continue; } // a single edge - nothing to remove
|
|
135
|
+
|
|
136
|
+
const longCurves = getMatCurveBetween(branch[i], branch[j].next);
|
|
137
|
+
|
|
138
|
+
//------------------------------------------------------------------
|
|
139
|
+
// 1. Cheap pass: sampled lower bounds on the deviation of each edge -
|
|
140
|
+
// the interior vertices and the piece midpoints.
|
|
141
|
+
//------------------------------------------------------------------
|
|
142
|
+
let worstD = 0;
|
|
143
|
+
let worstV = -1;
|
|
144
|
+
for (let k=i; k<=j; k++) {
|
|
145
|
+
if (k > i) {
|
|
146
|
+
const d = distanceToCurves(vertexPoints[k], longCurves);
|
|
147
|
+
if (d > worstD) { worstD = d; worstV = k; }
|
|
148
|
+
}
|
|
149
|
+
const pieces = curves[k];
|
|
150
|
+
for (let m=0; m<pieces.length; m++) {
|
|
151
|
+
const d = distanceToCurves(evalDeCasteljau(pieces[m], 0.5), longCurves);
|
|
152
|
+
if (d > worstD) {
|
|
153
|
+
worstD = d;
|
|
154
|
+
worstV = getSplitVertexForEdge(i, j, k, m, pieces.length);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (worstD > tolerance) {
|
|
160
|
+
split(spans, i, j, worstV);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
//------------------------------------------------------------------
|
|
165
|
+
// 2. Certified pass - split at the first edge found to exceed the
|
|
166
|
+
// tolerance.
|
|
167
|
+
//------------------------------------------------------------------
|
|
168
|
+
let splitV = -1;
|
|
169
|
+
outer: for (let k=i; k<=j; k++) {
|
|
170
|
+
const pieces = curves[k];
|
|
171
|
+
for (let m=0; m<pieces.length; m++) {
|
|
172
|
+
if (hausdorffDistanceOneSidedExceeds(pieces[m], longCurves, tolerance, maxIterations)) {
|
|
173
|
+
splitV = getSplitVertexForEdge(i, j, k, m, pieces.length);
|
|
174
|
+
break outer;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (splitV !== -1) {
|
|
180
|
+
split(spans, i, j, splitV);
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
//------------------------------------------------------------------
|
|
185
|
+
// 3. Accept the span.
|
|
186
|
+
//------------------------------------------------------------------
|
|
187
|
+
for (let k=i+1; k<=j; k++) {
|
|
188
|
+
toRemove.push(branch[k]);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Returns the vertex (in `(i,j]`) at which to split the span of edges `i..j`
|
|
196
|
+
* given that piece `m` (of `numPieces`) of edge `k` deviates too much: one of
|
|
197
|
+
* the edge's two endpoint vertices - the one on the side of the piece if the
|
|
198
|
+
* edge has 2 pieces, else the one nearer the middle of the span (for a more
|
|
199
|
+
* balanced recursion).
|
|
200
|
+
*
|
|
201
|
+
* @internal
|
|
202
|
+
*/
|
|
203
|
+
function getSplitVertexForEdge(
|
|
204
|
+
i: number,
|
|
205
|
+
j: number,
|
|
206
|
+
k: number,
|
|
207
|
+
m: number,
|
|
208
|
+
numPieces: number): number {
|
|
209
|
+
|
|
210
|
+
const canUseStart = k > i;
|
|
211
|
+
const canUseEnd = k + 1 <= j;
|
|
212
|
+
|
|
213
|
+
if (!canUseStart) { return k + 1; }
|
|
214
|
+
if (!canUseEnd) { return k; }
|
|
215
|
+
|
|
216
|
+
if (numPieces === 2) {
|
|
217
|
+
return m === 0 ? k : k + 1;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const mid = (i + 1 + j)/2; // middle of the interior vertices `i+1..j`
|
|
221
|
+
|
|
222
|
+
return abs(k - mid) <= abs(k + 1 - mid) ? k : k + 1;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Splits the span of edges `i..j` at the vertex `v` (in `(i,j]`) and pushes
|
|
228
|
+
* the resulting spans (for very long spans with `v` near an end also split at
|
|
229
|
+
* the middle - see `MIN_EDGES_FOR_BALANCED_SPLIT`).
|
|
230
|
+
*
|
|
231
|
+
* @internal
|
|
232
|
+
*/
|
|
233
|
+
function split(
|
|
234
|
+
spans: [number,number][],
|
|
235
|
+
i: number,
|
|
236
|
+
j: number,
|
|
237
|
+
v: number): void {
|
|
238
|
+
|
|
239
|
+
const numEdges = j - i + 1;
|
|
240
|
+
if (numEdges >= MIN_EDGES_FOR_BALANCED_SPLIT) {
|
|
241
|
+
const margin = numEdges*END_FRACTION;
|
|
242
|
+
if (v - i < margin || j + 1 - v < margin) {
|
|
243
|
+
const vMid = (i + j + 1) >>> 1; // an interior vertex near the middle
|
|
244
|
+
const [v1, v2] = v < vMid ? [v, vMid] : [vMid, v];
|
|
245
|
+
spans.push([v2, j], [v1, v2-1], [i, v1-1]);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
spans.push([v, j], [i, v-1]);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
export { simplifyMat }
|
package/src/mat/trim-mat.ts
CHANGED
|
@@ -7,14 +7,16 @@ import { clone } from '../cp-node/fs/clone.js';
|
|
|
7
7
|
/**
|
|
8
8
|
* Trims the given Medial Axis Transform so that only cycles remain. Similar to
|
|
9
9
|
* toScaleAxis(mat, Infinity).
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
*
|
|
11
|
+
* * returns `undefined` if the MAT has no cycles (i.e. the shape has no holes)
|
|
12
|
+
*
|
|
13
|
+
* @param mat The MAT to trim (it is not modified).
|
|
12
14
|
*/
|
|
13
|
-
function trimMat(mat: Mat): Mat {
|
|
15
|
+
function trimMat(mat: Mat): Mat | undefined {
|
|
14
16
|
// FUTURE - clone entire `Mat` instead (the function already exists)
|
|
15
17
|
const cpNode = cullNonCycles(clone(mat.cpNode));
|
|
16
18
|
|
|
17
|
-
if (!cpNode) { return undefined
|
|
19
|
+
if (!cpNode) { return undefined; }
|
|
18
20
|
|
|
19
21
|
return {
|
|
20
22
|
cpNode,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { PointOnShape } from './point-on-shape.js';
|
|
2
|
+
import { tangent } from 'flo-bezier3';
|
|
3
|
+
import { translate } from 'flo-vector2d';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Returns a line segment starting at the given point on the shape boundary and
|
|
8
|
+
* being tangent to the boundary at that point.
|
|
9
|
+
*
|
|
10
|
+
* * the returned line is of the form `[p, p + tangent]` where `p` is the
|
|
11
|
+
* point on the shape (the tangent is not normalized)
|
|
12
|
+
* * if the point falls on the boundary between two curves then the curve
|
|
13
|
+
* the point starts (if `fromElseTo` is `true`) or ends (if `fromElseTo` is
|
|
14
|
+
* `false`) is used
|
|
15
|
+
*
|
|
16
|
+
* @param pos the point on the shape
|
|
17
|
+
* @param fromElseTo `true` if the tangent is to be taken as leaving the point,
|
|
18
|
+
* `false` if it is to be taken as arriving at the point
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
function getBoundaryTangentLine(
|
|
23
|
+
pos: PointOnShape,
|
|
24
|
+
fromElseTo: boolean): number[][] {
|
|
25
|
+
|
|
26
|
+
let { curve, t } = pos;
|
|
27
|
+
const { p } = pos;
|
|
28
|
+
|
|
29
|
+
if (fromElseTo && t === 1) { t = 0; curve = curve.next; }
|
|
30
|
+
if (!fromElseTo && t === 0) { t = 1; curve = curve.prev; }
|
|
31
|
+
|
|
32
|
+
return [p, translate(p, tangent(curve.ps, t))];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
export { getBoundaryTangentLine }
|
|
@@ -5,12 +5,14 @@ const { sqrt } = Math;
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Returns the osculating circle at this point of the curve
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* to this
|
|
8
|
+
* Returns the osculating circle at this point of the curve as
|
|
9
|
+
* `[center, radius]`.
|
|
10
|
+
*
|
|
11
|
+
* @param maxOsculatingCircleRadius the circle radius will be limited to this
|
|
12
|
+
* value (i.e. the curvature is taken to be at least its reciprocal)
|
|
12
13
|
* @param pos the `PointOnShape` identifying the point
|
|
13
|
-
* @param
|
|
14
|
+
* @param norm the (not necessarily unit) normal at the point pointing towards
|
|
15
|
+
* the center of the circle
|
|
14
16
|
*/
|
|
15
17
|
function getOsculatingCircle(
|
|
16
18
|
maxOsculatingCircleRadius: number,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Corner } from "../corner/corner.js";
|
|
2
2
|
import type { Curve } from "flo-boolean";
|
|
3
3
|
import { memoize } from 'flo-memoize';
|
|
4
|
-
import { getCorner } from "../corner/get-corner.js";
|
|
4
|
+
import { getCorner$ } from "../corner/get-corner.js";
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -12,7 +12,7 @@ const getPosCorner$ = memoize(function(
|
|
|
12
12
|
|
|
13
13
|
const { t, curve } = pos;
|
|
14
14
|
|
|
15
|
-
return getCorner(
|
|
15
|
+
return getCorner$(
|
|
16
16
|
t === 1 ? curve.ps : curve.prev.ps,
|
|
17
17
|
t === 1 ? curve.next.ps : curve.ps,
|
|
18
18
|
);
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import type { BezierPiece } from 'flo-bezier3';
|
|
2
2
|
import type { Mat } from '../mat/mat.js';
|
|
3
3
|
import type { CpNode } from '../cp-node/cp-node.js';
|
|
4
|
-
import {
|
|
5
|
-
toUnitVector, distanceBetween, fromTo as fromToVec, dot, rotate90Degrees,
|
|
6
|
-
cross, interpolate, translate, lineLineIntersection
|
|
7
|
-
} from 'flo-vector2d';
|
|
8
|
-
import { tangent as getTangent } from 'flo-bezier3';
|
|
4
|
+
import { distanceBetween } from 'flo-vector2d';
|
|
9
5
|
import { mapDeep } from '../utils/map-deep.js';
|
|
10
6
|
import { removeSatInducedTrivial3Prongs } from './remove-sat-induced-trivial-3prongs.js';
|
|
11
7
|
import { getCpNodessForSat } from './get-cp-nodess-for-sat.js';
|
|
12
|
-
import {
|
|
8
|
+
import { clone } from '../cp-node/fs/clone.js';
|
|
9
|
+
import { getBoundaryTangentLine } from '../point-on-shape/get-boundary-tangent-line.js';
|
|
10
|
+
import { getBeziersFromTangents } from '../utils/get-beziers-from-tangents.js';
|
|
13
11
|
|
|
14
12
|
|
|
15
13
|
const { max, abs, round, log2 } = Math;
|
|
@@ -29,24 +27,28 @@ function reconstructFromMats(
|
|
|
29
27
|
mats: Mat[],
|
|
30
28
|
minNumAccurateBits: number | undefined = undefined) {
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
let maxPO2 = -Infinity;
|
|
31
|
+
for (const mat of mats) { maxPO2 = max(maxPO2, mat.meta.maxCoordPowerOf2); }
|
|
33
32
|
const recoverBoundary_ = recoverBoundary(maxPO2, minNumAccurateBits);
|
|
34
33
|
|
|
34
|
+
// `removeSatInducedTrivial3Prongs` relinks nodes in place so work on
|
|
35
|
+
// clones - the given `Mat`s must not be modified. (Only
|
|
36
|
+
// `meta.maxCoordPowerOf2` is used from the metas so they can be shared.)
|
|
35
37
|
// Really only required if getSats was called on the `Mat`s
|
|
36
38
|
const cpNodessPerSat = mats
|
|
39
|
+
.map(mat => ({ cpNode: clone(mat.cpNode), meta: mat.meta }))
|
|
37
40
|
.map(removeSatInducedTrivial3Prongs)
|
|
38
41
|
.map(getCpNodessForSat);
|
|
39
42
|
|
|
40
43
|
const r = mapDeep(3, cpNodessPerSat, recoverBoundary_, true);
|
|
41
44
|
// ii;//?
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
// Flatten the (1 or 2) beziers per boundary piece into a single array of
|
|
47
|
+
// beziers per loop.
|
|
48
|
+
return r.map(loops => loops.map(pieces => pieces.flat()));
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
|
|
47
|
-
const FROM = 0;
|
|
48
|
-
const TO = 1;
|
|
49
|
-
|
|
50
52
|
/**
|
|
51
53
|
*
|
|
52
54
|
* @param cpNode
|
|
@@ -78,9 +80,6 @@ function recoverBoundary(
|
|
|
78
80
|
|
|
79
81
|
const d = distanceBetween(circle.center, p);
|
|
80
82
|
|
|
81
|
-
if (getRealProngCount(cpNode)) {
|
|
82
|
-
|
|
83
|
-
}
|
|
84
83
|
|
|
85
84
|
// DON'T remove these - they tell us the accuracy of the algorithm
|
|
86
85
|
// if (!closeTo(2**34)(circle.radius, d) && getRealProngCount(cpNode) === 3) {
|
|
@@ -118,108 +117,20 @@ function recoverBoundary(
|
|
|
118
117
|
}
|
|
119
118
|
|
|
120
119
|
|
|
121
|
-
/** @internal */
|
|
122
|
-
const TOLERANCE_ADD_2PRONG = 0.01;
|
|
123
|
-
/** @internal */
|
|
124
|
-
const TOLERANCE_USE_LINE = 0.0001; // else cubic
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
function getBoundaryPiece(
|
|
128
|
-
cpNode: CpNode) {
|
|
129
|
-
|
|
130
|
-
const cpNode_ = cpNode.next;
|
|
131
|
-
|
|
132
|
-
const pos = cpNode.pointOnShape;
|
|
133
|
-
const pos_ = cpNode_.pointOnShape;
|
|
134
|
-
|
|
135
|
-
const { p } = pos;
|
|
136
|
-
const { p: p_ } = pos_;
|
|
137
|
-
|
|
138
|
-
const fromCc = p;
|
|
139
|
-
const fromL = getEdgeDirection(cpNode, FROM);
|
|
140
|
-
|
|
141
|
-
const toCc = p_;
|
|
142
|
-
const toL = getEdgeDirection(cpNode_, TO);
|
|
143
|
-
|
|
144
|
-
const mid = lineLineIntersection(fromL, toL);
|
|
145
|
-
|
|
146
|
-
const c = fromToVec(fromCc,toCc);
|
|
147
|
-
|
|
148
|
-
let twisted: boolean;
|
|
149
|
-
if (!mid) {
|
|
150
|
-
twisted = true;
|
|
151
|
-
} else {
|
|
152
|
-
const a = fromToVec(fromCc, mid);
|
|
153
|
-
const b = fromToVec(toCc, mid);
|
|
154
|
-
|
|
155
|
-
twisted = dot(a,c) < 0 || dot(b,c) > 0;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (!twisted) {
|
|
159
|
-
return [fromCc, mid!, toCc];
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const r = rotate90Degrees(c);
|
|
163
|
-
const w1 = fromToVec(fromL[0], fromL[1]); // This is a unit vector
|
|
164
|
-
const w2 = fromToVec(toL[0], toL[1]); // This is a unit vector
|
|
165
|
-
|
|
166
|
-
const d1 = abs(cross(c, w1)) / (3*3);
|
|
167
|
-
const d2 = abs(cross(c, w2)) / (3*3);
|
|
168
|
-
|
|
169
|
-
if (d1 > TOLERANCE_ADD_2PRONG || d2 > TOLERANCE_ADD_2PRONG) {
|
|
170
|
-
// FUTURE - not within tolerance - must add additional 2-prong
|
|
171
|
-
return [fromCc, toCc];
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (d1 > TOLERANCE_USE_LINE || d2 > TOLERANCE_USE_LINE) {
|
|
175
|
-
// approximate with cubic bezier
|
|
176
|
-
const m1 = interpolate(fromCc,toCc,1/3);
|
|
177
|
-
const m2 = interpolate(fromCc,toCc,2/3);
|
|
178
|
-
const v1 = translate(r, m1);
|
|
179
|
-
const v2 = translate(r, m2);
|
|
180
|
-
const l1 = [m1,v1];
|
|
181
|
-
const l2 = [m2,v2];
|
|
182
|
-
const mid1 = lineLineIntersection(fromL, l1)!;
|
|
183
|
-
const mid2 = lineLineIntersection(toL, l2)!;
|
|
184
|
-
|
|
185
|
-
return [fromCc, mid1, mid2, toCc];
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Within tolerance - approximate with a straight line.
|
|
189
|
-
return [fromCc, toCc];
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
|
|
193
120
|
/**
|
|
194
|
-
* Returns
|
|
195
|
-
*
|
|
121
|
+
* Returns the bezier curves (1 or 2 lines or quadratics) approximating the
|
|
122
|
+
* shape boundary from the contact point of the given `CpNode` to that of the
|
|
123
|
+
* next `CpNode`.
|
|
196
124
|
*
|
|
197
125
|
* @internal
|
|
198
126
|
*/
|
|
199
|
-
function
|
|
200
|
-
cpNode: CpNode
|
|
201
|
-
fromOrTo: typeof FROM | typeof TO) {
|
|
202
|
-
|
|
203
|
-
let { pointOnShape } = cpNode;
|
|
204
|
-
let { curve, t, p } = pointOnShape;
|
|
205
|
-
let { ps } = curve;
|
|
206
|
-
|
|
207
|
-
if (fromOrTo === FROM && t === 1) {
|
|
208
|
-
t = 0;
|
|
209
|
-
curve = curve.next;
|
|
210
|
-
ps = curve.ps;
|
|
211
|
-
}
|
|
212
|
-
if (fromOrTo === TO && t === 0 ) {
|
|
213
|
-
t = 1;
|
|
214
|
-
curve = curve.prev;
|
|
215
|
-
ps = curve.ps;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const tangent = getTangent(ps, t);
|
|
219
|
-
|
|
220
|
-
const v = translate(p, tangent);
|
|
127
|
+
function getBoundaryPiece(
|
|
128
|
+
cpNode: CpNode) {
|
|
221
129
|
|
|
222
|
-
return
|
|
130
|
+
return getBeziersFromTangents(
|
|
131
|
+
getBoundaryTangentLine(cpNode.pointOnShape, true),
|
|
132
|
+
getBoundaryTangentLine(cpNode.next.pointOnShape, false)
|
|
133
|
+
);
|
|
223
134
|
}
|
|
224
135
|
|
|
225
136
|
|
|
@@ -7,6 +7,10 @@ import { isFullyTerminating } from '../cp-node/fs/is-fully-terminating.js';
|
|
|
7
7
|
* In-place removes trivial 3-prongs from the SAT graph; just to simplify
|
|
8
8
|
* subsequent processing.
|
|
9
9
|
*
|
|
10
|
+
* * **mutates** the given `Mat` (its `CpNode`s are relinked and `cpNode` is
|
|
11
|
+
* reassigned; `meta.cpTrees` is left stale) - pass a clone if the original
|
|
12
|
+
* must be kept
|
|
13
|
+
*
|
|
10
14
|
* These are 3-prongs that are induced by the SAT construction, and do
|
|
11
15
|
* not correspond to actual 3-prongs in the shape.
|
|
12
16
|
*
|