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.
Files changed (356) hide show
  1. package/__tests__/closest-boundary-point/get-endpoint-info.spec.ts +140 -0
  2. package/__tests__/closest-boundary-point/root-interval-to-distance-squared-interval.spec.ts +87 -0
  3. package/__tests__/cp-node/fs/get-all-on-loop-by-loop.spec.ts +55 -0
  4. package/__tests__/cp-node/fs/get-angle-between-mat-curves.spec.ts +39 -3
  5. package/__tests__/cp-node/fs/get-boundary-bezier-parts-to-next.spec.ts +87 -3
  6. package/__tests__/cp-node/fs/get-boundary-beziers-between.spec.ts +68 -3
  7. package/__tests__/cp-node/fs/get-boundary-beziers-to-next.spec.ts +41 -3
  8. package/__tests__/cp-node/fs/get-boundary-distance-to-next.spec.ts +20 -3
  9. package/__tests__/cp-node/fs/get-branch-beziers.spec.ts +42 -3
  10. package/__tests__/cp-node/fs/get-branch.spec.ts +60 -3
  11. package/__tests__/cp-node/fs/get-cp-node-ordering.spec.ts +19 -3
  12. package/__tests__/cp-node/fs/get-distance-to-next.spec.ts +37 -4
  13. package/__tests__/cp-node/fs/get-edge-direction.spec.ts +50 -3
  14. package/__tests__/cp-node/fs/get-first-exit.spec.ts +78 -3
  15. package/__tests__/cp-node/fs/get-hole-closers.spec.ts +32 -3
  16. package/__tests__/cp-node/fs/get-implied-boundary-bezier-between.spec.ts +48 -3
  17. package/__tests__/cp-node/fs/get-mat-curve-between.spec.ts +77 -3
  18. package/__tests__/cp-node/fs/get-mat-curve-to-next.spec.ts +17 -4
  19. package/__tests__/cp-node/fs/get-mat-curves-between.spec.ts +38 -3
  20. package/__tests__/cp-node/fs/get-salience.spec.ts +68 -3
  21. package/__tests__/cp-node/fs/get-vertex-forward-children.spec.ts +40 -3
  22. package/__tests__/cp-node/fs/insert-cp-node.spec.ts +87 -3
  23. package/__tests__/cp-node/fs/is-special.spec.ts +1 -1
  24. package/__tests__/cp-node/fs/remove-cp-node.spec.ts +42 -3
  25. package/__tests__/find-2-prong/calc-seperation-tolerance.spec.ts +46 -0
  26. package/__tests__/find-2-prong/get-medial/get-closest-points.spec.ts +1 -1
  27. package/__tests__/floyd-warshall/get-graph.spec.ts +100 -0
  28. package/__tests__/get-mats-with-hole.ts +28 -0
  29. package/__tests__/get-mats1.spec.ts +61 -0
  30. package/__tests__/get-mats1.ts +75 -67
  31. package/__tests__/helpers/cp-node-by-id.ts +27 -0
  32. package/__tests__/helpers/expect-point-close.ts +42 -0
  33. package/__tests__/mat/hausdorff-distance-one-sided-exceeds.spec.ts +129 -0
  34. package/__tests__/mat/simplify-mat.spec.ts +85 -0
  35. package/__tests__/reconstruct-from-mat/reconstruct-from-mat.spec.ts +39 -0
  36. package/__tests__/specific-cases/test-svgs/achispado.svg +14 -0
  37. package/__tests__/utils/get-beziers-from-tangents.spec.ts +142 -0
  38. package/browser/index.js +12985 -9965
  39. package/browser/index.min.js +1 -1
  40. package/node/closest-boundary-point/cull-curve-pieces.d.ts +21 -0
  41. package/node/closest-boundary-point/cull-curve-pieces.js +40 -0
  42. package/node/closest-boundary-point/cull-curve-pieces.js.map +1 -0
  43. package/node/closest-boundary-point/get-close-boundary-points-certified.js +5 -2
  44. package/node/closest-boundary-point/get-close-boundary-points-certified.js.map +1 -1
  45. package/node/closest-boundary-point/get-endpoint-info.d.ts +39 -0
  46. package/node/closest-boundary-point/get-endpoint-info.js +78 -0
  47. package/node/closest-boundary-point/get-endpoint-info.js.map +1 -0
  48. package/node/closest-boundary-point/get-potential-closest-points-on-curve-certified.js +5 -19
  49. package/node/closest-boundary-point/get-potential-closest-points-on-curve-certified.js.map +1 -1
  50. package/node/closest-boundary-point/root-interval-to-distance-squared-interval.d.ts +17 -5
  51. package/node/closest-boundary-point/root-interval-to-distance-squared-interval.js +37 -50
  52. package/node/closest-boundary-point/root-interval-to-distance-squared-interval.js.map +1 -1
  53. package/node/corner/get-corner.d.ts +18 -1
  54. package/node/corner/get-corner.js +8 -1
  55. package/node/corner/get-corner.js.map +1 -1
  56. package/node/corner/get-interface-ccw.js.map +1 -1
  57. package/node/cp-node/cp-node.d.ts +4 -3
  58. package/node/cp-node/fs/get-all-on-loop-by-loop.js +0 -4
  59. package/node/cp-node/fs/get-all-on-loop-by-loop.js.map +1 -1
  60. package/node/cp-node/fs/get-angle-between-mat-curves.js +6 -4
  61. package/node/cp-node/fs/get-angle-between-mat-curves.js.map +1 -1
  62. package/node/cp-node/fs/get-boundary-beziers-between.d.ts +6 -4
  63. package/node/cp-node/fs/get-boundary-beziers-between.js +6 -4
  64. package/node/cp-node/fs/get-boundary-beziers-between.js.map +1 -1
  65. package/node/cp-node/fs/get-branch-beziers.d.ts +2 -1
  66. package/node/cp-node/fs/get-branch-beziers.js +3 -2
  67. package/node/cp-node/fs/get-branch-beziers.js.map +1 -1
  68. package/node/cp-node/fs/get-branch.js +1 -2
  69. package/node/cp-node/fs/get-branch.js.map +1 -1
  70. package/node/cp-node/fs/get-distance-to-next.js +4 -2
  71. package/node/cp-node/fs/get-distance-to-next.js.map +1 -1
  72. package/node/cp-node/fs/get-first-exit.d.ts +7 -3
  73. package/node/cp-node/fs/get-first-exit.js +13 -11
  74. package/node/cp-node/fs/get-first-exit.js.map +1 -1
  75. package/node/cp-node/fs/get-implied-boundary-bezier-between.d.ts +9 -1
  76. package/node/cp-node/fs/get-implied-boundary-bezier-between.js +11 -55
  77. package/node/cp-node/fs/get-implied-boundary-bezier-between.js.map +1 -1
  78. package/node/cp-node/fs/get-mat-curve-between.d.ts +4 -3
  79. package/node/cp-node/fs/get-mat-curve-between.js +5 -49
  80. package/node/cp-node/fs/get-mat-curve-between.js.map +1 -1
  81. package/node/cp-node/fs/get-mat-curve-to-next.d.ts +1 -1
  82. package/node/cp-node/fs/get-mat-curves-between.d.ts +8 -0
  83. package/node/cp-node/fs/get-mat-curves-between.js +9 -2
  84. package/node/cp-node/fs/get-mat-curves-between.js.map +1 -1
  85. package/node/cp-node/fs/get-real-prong-count.d.ts +2 -1
  86. package/node/cp-node/fs/get-real-prong-count.js +11 -5
  87. package/node/cp-node/fs/get-real-prong-count.js.map +1 -1
  88. package/node/cp-node/fs/get-salience.d.ts +10 -0
  89. package/node/cp-node/fs/get-salience.js +17 -1
  90. package/node/cp-node/fs/get-salience.js.map +1 -1
  91. package/node/cp-node/fs/is-fully-terminating.d.ts +4 -2
  92. package/node/cp-node/fs/is-fully-terminating.js +6 -15
  93. package/node/cp-node/fs/is-fully-terminating.js.map +1 -1
  94. package/node/cp-node/fs/is-on-same-loop.d.ts +1 -1
  95. package/node/cp-node/fs/is-special.d.ts +7 -0
  96. package/node/cp-node/fs/is-special.js +9 -2
  97. package/node/cp-node/fs/is-special.js.map +1 -1
  98. package/node/cp-node/fs/is-vertex.d.ts +1 -1
  99. package/node/cp-node/fs/traverse-edges.d.ts +7 -3
  100. package/node/cp-node/fs/traverse-edges.js +7 -3
  101. package/node/cp-node/fs/traverse-edges.js.map +1 -1
  102. package/node/cp-node/stringification/from-stringifyable.d.ts +2 -2
  103. package/node/cp-node/stringification/from-stringifyable.js +1 -1
  104. package/node/cp-node/stringification/from-stringifyable.js.map +1 -1
  105. package/node/cp-node/stringification/to-stringifyable.d.ts +3 -3
  106. package/node/cp-node/stringification/to-stringifyable.js +3 -3
  107. package/node/debug/debug.d.ts +26 -3
  108. package/node/debug/debug.js +16 -5
  109. package/node/debug/debug.js.map +1 -1
  110. package/node/find-2-prong/add-2-prong.js +1 -7
  111. package/node/find-2-prong/add-2-prong.js.map +1 -1
  112. package/node/find-2-prong/calc-seperation-tolerance.d.ts +28 -5
  113. package/node/find-2-prong/calc-seperation-tolerance.js +32 -89
  114. package/node/find-2-prong/calc-seperation-tolerance.js.map +1 -1
  115. package/node/find-2-prong/find-2-prong.js +8 -10
  116. package/node/find-2-prong/find-2-prong.js.map +1 -1
  117. package/node/find-2-prong/find-and-add-2-prongs.js +2 -2
  118. package/node/find-2-prong/find-and-add-2-prongs.js.map +1 -1
  119. package/node/find-2-prong/get-medial/get-antipodal-points.d.ts +1 -2
  120. package/node/find-2-prong/get-medial/get-antipodal-points.js +2 -3
  121. package/node/find-2-prong/get-medial/get-antipodal-points.js.map +1 -1
  122. package/node/find-2-prong/get-medial/get-closest-points.d.ts +1 -8
  123. package/node/find-2-prong/get-medial/get-closest-points.js +4 -40
  124. package/node/find-2-prong/get-medial/get-closest-points.js.map +1 -1
  125. package/node/find-2-prong/reduce-radius.d.ts +1 -1
  126. package/node/find-2-prong/reduce-radius.js +6 -3
  127. package/node/find-2-prong/reduce-radius.js.map +1 -1
  128. package/node/find-3-prong/calc-better-x.js +1 -1
  129. package/node/find-3-prong/calc-better-x.js.map +1 -1
  130. package/node/find-3-prong/find-3-prong-for-delta3s.d.ts +3 -2
  131. package/node/find-3-prong/find-3-prong-for-delta3s.js +35 -41
  132. package/node/find-3-prong/find-3-prong-for-delta3s.js.map +1 -1
  133. package/node/find-3-prong/find-3-prong.js +3 -1
  134. package/node/find-3-prong/find-3-prong.js.map +1 -1
  135. package/node/find-3-prong/find-and-add-3-prongs.js +16 -0
  136. package/node/find-3-prong/find-and-add-3-prongs.js.map +1 -1
  137. package/node/find-mat/create-initial-cp-tree.js +2 -2
  138. package/node/find-mat/create-initial-cp-tree.js.map +1 -1
  139. package/node/find-mat/find-mat.js +3 -4
  140. package/node/find-mat/find-mat.js.map +1 -1
  141. package/node/find-mat/find-mats.d.ts +6 -12
  142. package/node/find-mat/find-mats.js +10 -27
  143. package/node/find-mat/find-mats.js.map +1 -1
  144. package/node/find-mat/get-dull-corners-on-loop.js +2 -2
  145. package/node/find-mat/get-dull-corners-on-loop.js.map +1 -1
  146. package/node/find-mat/get-for-1-prongs-on-loop.js +36 -8
  147. package/node/find-mat/get-for-1-prongs-on-loop.js.map +1 -1
  148. package/node/find-mat/get-meta.d.ts +14 -4
  149. package/node/find-mat/get-meta.js +30 -24
  150. package/node/find-mat/get-meta.js.map +1 -1
  151. package/node/find-mat/get-sharp-corners.js +2 -2
  152. package/node/find-mat/get-sharp-corners.js.map +1 -1
  153. package/node/find-mat/mat-options.d.ts +2 -2
  154. package/node/floyd-warshall/get-graph.d.ts +12 -1
  155. package/node/floyd-warshall/get-graph.js +41 -38
  156. package/node/floyd-warshall/get-graph.js.map +1 -1
  157. package/node/geometry/get-bounding-box-.d.ts +16 -2
  158. package/node/geometry/get-bounding-box-.js +5 -2
  159. package/node/geometry/get-bounding-box-.js.map +1 -1
  160. package/node/geometry/get-closest-square-distance-to-rect.d.ts +3 -0
  161. package/node/geometry/get-closest-square-distance-to-rect.js +7 -5
  162. package/node/geometry/get-closest-square-distance-to-rect.js.map +1 -1
  163. package/node/geometry/get-closest-squared-distance-to-rotated-rect.d.ts +4 -0
  164. package/node/geometry/get-closest-squared-distance-to-rotated-rect.js +11 -5
  165. package/node/geometry/get-closest-squared-distance-to-rotated-rect.js.map +1 -1
  166. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.js +1 -2
  167. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.js.map +1 -1
  168. package/node/index.d.ts +3 -2
  169. package/node/index.js +2 -1
  170. package/node/index.js.map +1 -1
  171. package/node/mat/clone-mat.d.ts +9 -0
  172. package/node/mat/clone-mat.js +17 -0
  173. package/node/mat/clone-mat.js.map +1 -0
  174. package/node/mat/clone-meta.d.ts +12 -0
  175. package/node/mat/clone-meta.js +24 -0
  176. package/node/mat/clone-meta.js.map +1 -0
  177. package/node/mat/get-boundary-piece-beziers.d.ts +5 -0
  178. package/node/mat/get-boundary-piece-beziers.js +7 -93
  179. package/node/mat/get-boundary-piece-beziers.js.map +1 -1
  180. package/node/mat/get-largest-3-prong.d.ts +6 -0
  181. package/node/mat/get-largest-3-prong.js +8 -5
  182. package/node/mat/get-largest-3-prong.js.map +1 -1
  183. package/node/mat/get-largest-vertex.d.ts +15 -1
  184. package/node/mat/get-largest-vertex.js +20 -7
  185. package/node/mat/get-largest-vertex.js.map +1 -1
  186. package/node/mat/hausdorff-distance-one-sided-exceeds.d.ts +79 -0
  187. package/node/mat/hausdorff-distance-one-sided-exceeds.js +251 -0
  188. package/node/mat/hausdorff-distance-one-sided-exceeds.js.map +1 -0
  189. package/node/mat/mat-meta.d.ts +0 -6
  190. package/node/mat/simplify-mat.d.ts +25 -8
  191. package/node/mat/simplify-mat.js +182 -53
  192. package/node/mat/simplify-mat.js.map +1 -1
  193. package/node/mat/trim-mat.d.ts +4 -2
  194. package/node/mat/trim-mat.js +3 -1
  195. package/node/mat/trim-mat.js.map +1 -1
  196. package/node/point-on-shape/get-boundary-tangent-line.d.ts +19 -0
  197. package/node/point-on-shape/get-boundary-tangent-line.js +33 -0
  198. package/node/point-on-shape/get-boundary-tangent-line.js.map +1 -0
  199. package/node/point-on-shape/get-osculating-circle.d.ts +6 -4
  200. package/node/point-on-shape/get-osculating-circle.js +6 -4
  201. package/node/point-on-shape/get-osculating-circle.js.map +1 -1
  202. package/node/point-on-shape/get-pos-corner.js +2 -2
  203. package/node/point-on-shape/get-pos-corner.js.map +1 -1
  204. package/node/reconstruct-from-mat/reconstruct-from-mat.js +20 -80
  205. package/node/reconstruct-from-mat/reconstruct-from-mat.js.map +1 -1
  206. package/node/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.d.ts +4 -0
  207. package/node/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.js +4 -0
  208. package/node/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.js.map +1 -1
  209. package/node/sat/cull.d.ts +7 -6
  210. package/node/sat/cull.js +13 -16
  211. package/node/sat/cull.js.map +1 -1
  212. package/node/sat/get-sat-culls.d.ts +12 -2
  213. package/node/sat/get-sat-culls.js +21 -16
  214. package/node/sat/get-sat-culls.js.map +1 -1
  215. package/node/svg/get-shape-bounds.d.ts +1 -12
  216. package/node/svg/get-shape-bounds.js +2 -3
  217. package/node/svg/get-shape-bounds.js.map +1 -1
  218. package/node/sweep-line/sweep-line.js.map +1 -1
  219. package/node/utils/get-beziers-from-tangents.d.ts +28 -0
  220. package/node/utils/get-beziers-from-tangents.js +92 -0
  221. package/node/utils/get-beziers-from-tangents.js.map +1 -0
  222. package/node/vertex/remove-vertex.d.ts +5 -3
  223. package/node/vertex/remove-vertex.js +5 -3
  224. package/node/vertex/remove-vertex.js.map +1 -1
  225. package/package.json +9 -9
  226. package/qv-infinite-loop.md +120 -0
  227. package/src/closest-boundary-point/cull-curve-pieces.ts +49 -0
  228. package/src/closest-boundary-point/get-close-boundary-points-certified.ts +5 -2
  229. package/src/closest-boundary-point/get-endpoint-info.ts +96 -0
  230. package/src/closest-boundary-point/get-potential-closest-points-on-curve-certified.ts +5 -23
  231. package/src/closest-boundary-point/root-interval-to-distance-squared-interval.ts +42 -60
  232. package/src/corner/get-corner.ts +10 -1
  233. package/src/corner/get-interface-ccw.ts +2 -2
  234. package/src/cp-node/cp-node.ts +4 -3
  235. package/src/cp-node/fs/get-all-on-loop-by-loop.ts +0 -4
  236. package/src/cp-node/fs/get-angle-between-mat-curves.ts +6 -4
  237. package/src/cp-node/fs/get-boundary-beziers-between.ts +10 -8
  238. package/src/cp-node/fs/get-branch-beziers.ts +3 -2
  239. package/src/cp-node/fs/get-branch.ts +1 -2
  240. package/src/cp-node/fs/get-distance-to-next.ts +4 -2
  241. package/src/cp-node/fs/get-first-exit.ts +15 -14
  242. package/src/cp-node/fs/get-implied-boundary-bezier-between.ts +17 -69
  243. package/src/cp-node/fs/get-mat-curve-between.ts +9 -67
  244. package/src/cp-node/fs/get-mat-curves-between.ts +9 -2
  245. package/src/cp-node/fs/get-real-prong-count.ts +11 -7
  246. package/src/cp-node/fs/get-salience.ts +15 -2
  247. package/src/cp-node/fs/is-fully-terminating.ts +6 -18
  248. package/src/cp-node/fs/is-on-same-loop.ts +2 -2
  249. package/src/cp-node/fs/is-special.ts +11 -6
  250. package/src/cp-node/fs/is-vertex.ts +1 -1
  251. package/src/cp-node/fs/traverse-edges.ts +8 -4
  252. package/src/cp-node/stringification/from-stringifyable.ts +75 -75
  253. package/src/cp-node/stringification/to-stringifyable.ts +3 -3
  254. package/src/debug/debug.ts +44 -8
  255. package/src/find-2-prong/add-2-prong.ts +2 -9
  256. package/src/find-2-prong/calc-seperation-tolerance.ts +34 -115
  257. package/src/find-2-prong/find-2-prong.ts +9 -11
  258. package/src/find-2-prong/find-and-add-2-prongs.ts +2 -2
  259. package/src/find-2-prong/get-medial/get-antipodal-points.ts +1 -3
  260. package/src/find-2-prong/get-medial/get-closest-points.ts +6 -51
  261. package/src/find-2-prong/reduce-radius.ts +6 -4
  262. package/src/find-3-prong/calc-better-x.ts +2 -2
  263. package/src/find-3-prong/find-3-prong-for-delta3s.ts +197 -214
  264. package/src/find-3-prong/find-3-prong.ts +54 -51
  265. package/src/find-3-prong/find-and-add-3-prongs.ts +20 -1
  266. package/src/find-mat/create-initial-cp-tree.ts +2 -2
  267. package/src/find-mat/find-mat.ts +4 -6
  268. package/src/find-mat/find-mats.ts +83 -105
  269. package/src/find-mat/get-dull-corners-on-loop.ts +2 -2
  270. package/src/find-mat/get-for-1-prongs-on-loop.ts +40 -8
  271. package/src/find-mat/get-meta.ts +34 -39
  272. package/src/find-mat/get-sharp-corners.ts +2 -2
  273. package/src/find-mat/mat-options.ts +2 -2
  274. package/src/floyd-warshall/get-graph.ts +46 -47
  275. package/src/geometry/get-bounding-box-.ts +5 -2
  276. package/src/geometry/get-closest-square-distance-to-rect.ts +7 -7
  277. package/src/geometry/get-closest-squared-distance-to-rotated-rect.ts +12 -10
  278. package/src/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.ts +1 -2
  279. package/src/index.ts +3 -2
  280. package/src/mat/clone-mat.ts +9 -3
  281. package/src/mat/clone-meta.ts +8 -0
  282. package/src/mat/get-boundary-piece-beziers.ts +16 -117
  283. package/src/mat/get-largest-3-prong.ts +9 -6
  284. package/src/mat/get-largest-vertex.ts +25 -9
  285. package/src/mat/hausdorff-distance-one-sided-exceeds.ts +314 -0
  286. package/src/mat/mat-meta.ts +0 -9
  287. package/src/mat/simplify-mat.ts +254 -116
  288. package/src/mat/trim-mat.ts +6 -4
  289. package/src/point-on-shape/get-boundary-tangent-line.ts +36 -0
  290. package/src/point-on-shape/get-osculating-circle.ts +7 -5
  291. package/src/point-on-shape/get-pos-corner.ts +2 -2
  292. package/src/reconstruct-from-mat/reconstruct-from-mat.ts +22 -111
  293. package/src/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.ts +4 -0
  294. package/src/sat/cull.ts +16 -20
  295. package/src/sat/get-sat-culls.ts +28 -23
  296. package/src/svg/get-shape-bounds.ts +2 -3
  297. package/src/sweep-line/sweep-line.ts +1 -1
  298. package/src/utils/get-beziers-from-tangents.ts +110 -0
  299. package/src/utils/map-map.ts +1 -1
  300. package/src/vertex/remove-vertex.ts +5 -3
  301. package/__tests__/cp-node/fs/get-distance-between.spec.ts +0 -7
  302. package/__tests__/cp-node/fs/get-terminating-on-circle.spec.ts +0 -24
  303. package/__tests__/cp-node/fs/is-single-3-prong.spec.ts +0 -17
  304. package/__tests__/cp-node/fs/iterate-all-on-loop.spec.ts +0 -17
  305. package/__tests__/cp-node/fs/traverse-all-forward.spec.ts +0 -14
  306. package/node/closest-boundary-point/cull-bezier-pieces-1.d.ts +0 -9
  307. package/node/closest-boundary-point/cull-bezier-pieces-1.js +0 -17
  308. package/node/closest-boundary-point/cull-bezier-pieces-1.js.map +0 -1
  309. package/node/closest-boundary-point/cull-by-loose-bounding-box.d.ts +0 -13
  310. package/node/closest-boundary-point/cull-by-loose-bounding-box.js +0 -27
  311. package/node/closest-boundary-point/cull-by-loose-bounding-box.js.map +0 -1
  312. package/node/closest-boundary-point/cull-by-tight-boundary-box.d.ts +0 -11
  313. package/node/closest-boundary-point/cull-by-tight-boundary-box.js +0 -27
  314. package/node/closest-boundary-point/cull-by-tight-boundary-box.js.map +0 -1
  315. package/node/cp-node/fs/find-first.d.ts +0 -10
  316. package/node/cp-node/fs/find-first.js +0 -19
  317. package/node/cp-node/fs/find-first.js.map +0 -1
  318. package/node/debug/functions/check-ordering.d.ts +0 -4
  319. package/node/debug/functions/check-ordering.js +0 -43
  320. package/node/debug/functions/check-ordering.js.map +0 -1
  321. package/node/find-2-prong/cull-bezier-pieces.d.ts +0 -13
  322. package/node/find-2-prong/cull-bezier-pieces.js +0 -43
  323. package/node/find-2-prong/cull-bezier-pieces.js.map +0 -1
  324. package/node/floyd-warshall/get-hole-closer-pairs.d.ts +0 -8
  325. package/node/floyd-warshall/get-hole-closer-pairs.js +0 -27
  326. package/node/floyd-warshall/get-hole-closer-pairs.js.map +0 -1
  327. package/node/utils/dual-set.d.ts +0 -27
  328. package/node/utils/dual-set.js +0 -55
  329. package/node/utils/dual-set.js.map +0 -1
  330. package/node/utils/tri-map.d.ts +0 -27
  331. package/node/utils/tri-map.js +0 -49
  332. package/node/utils/tri-map.js.map +0 -1
  333. package/src/closest-boundary-point/cull-bezier-pieces-1.ts +0 -36
  334. package/src/closest-boundary-point/cull-by-loose-bounding-box.ts +0 -42
  335. package/src/closest-boundary-point/cull-by-tight-boundary-box.ts +0 -43
  336. package/src/closest-boundary-point/get-p-from-box.ts +0 -14
  337. package/src/cp-node/fs/add-distance-from.ts +0 -49
  338. package/src/cp-node/fs/get-distance-between.ts +0 -16
  339. package/src/cp-node/fs/get-terminating-on-circle.ts +0 -24
  340. package/src/cp-node/fs/is-single-3-prong.ts +0 -15
  341. package/src/cp-node/fs/iterate-all-on-loop.ts +0 -15
  342. package/src/cp-node/fs/traverse-all-forward.ts +0 -24
  343. package/src/debug/functions/draw/draw-beziers-as-single-path.ts +0 -40
  344. package/src/debug/functions/draw/draw-disk.ts +0 -34
  345. package/src/debug/functions/draw/xmlns.ts +0 -5
  346. package/src/find-2-prong/cull-bezier-pieces.ts +0 -61
  347. package/src/find-2-prong/find-and-add-2-prong.ts +0 -30
  348. package/src/find-2-prong/get-medial/get-closest-points-d.ts +0 -213
  349. package/src/find-2-prong/x-for-debugging.ts +0 -13
  350. package/src/floyd-warshall/get-hole-closer-pairs.ts +0 -35
  351. package/src/mat/get-two-prong-type.ts +0 -13
  352. package/src/point-on-shape/is-pos-dull-corner.ts +0 -18
  353. package/src/point-on-shape/is-pos-quite-dull-corner.ts +0 -18
  354. package/src/point-on-shape/is-pos-quite-sharp-corner.ts +0 -18
  355. package/src/point-on-shape/pos-to-human-string.ts +0 -18
  356. package/src/sweep-line/are-boxes-intersecting.ts +0 -37
@@ -1,116 +1,254 @@
1
- import type { Mat } from './mat.js';
2
- import type { CpNode } from '../cp-node/cp-node.js';
3
- import { hausdorffDistanceOneSided } from 'flo-bezier3';
4
- import { removeVertex } from '../vertex/remove-vertex.js';
5
- import { getBranches } from './get-branches.js';
6
- import { getMatCurveToNext } from '../cp-node/fs/get-mat-curve-to-next.js';
7
- import { getMatCurveBetween } from '../cp-node/fs/get-mat-curve-between.js';
8
- import { createNewCpTrees } from './create-new-cp-trees.js';
9
- import { clone } from '../cp-node/fs/clone.js';
10
- import { findFirst } from '../cp-node/fs/find-first.js';
11
- import { isTerminating } from '../cp-node/fs/is-terminating.js';
12
- import { isVertex } from '../cp-node/fs/is-vertex.js';
13
- import { getProngCount } from '../cp-node/fs/get-prong-count.js';
14
-
15
- const { max } = Math;
16
-
17
-
18
- // FUTURE could be made faster by binary "search" on hausdorff curves?
19
- /**
20
- * Returns a new simplified MAT of the given one by replacing the piecewise
21
- * quad beziers composing the MAT with fewer ones to within a given tolerance.
22
- *
23
- * @param cpNode a representation of the MAT
24
- * @param anlgeTolerance tolerance given as the degrees difference of the unit
25
- * direction vectors at the interface between curves. A tolerance of zero means
26
- * perfect smoothness is required - defaults to 15
27
- * @param hausdorffTolerance the approximate maximum Hausdorff Distance tolerance -
28
- * defaults to `2**-3`
29
- * @param maxIterations the max iterations of the Hausdorff Distance calculation,
30
- * defaults to `50`
31
- */
32
- function simplifyMat(
33
- mat: Mat,
34
- hausdorffTolerance = 2**-3,
35
- maxIterations = 50): Mat {
36
-
37
- let cpNode = clone(mat.cpNode);
38
-
39
- // Start from a leaf
40
- while (!isTerminating(cpNode)) { cpNode = cpNode.next; }
41
-
42
- const branches = getBranches(cpNode);
43
-
44
- const canDeletes: Set<CpNode> = new Set();
45
- for (let k=0; k<branches.length; k++) {
46
- const branch = branches[k];
47
-
48
- // Try to remove some
49
- let j = 0;
50
- while (j < branch.length) {
51
- const i = j;
52
- while (true) {
53
- j++;
54
-
55
- if (j === branch.length) { break; }
56
-
57
- const hd = getTotalHausdorffDistance(i, j, branch, maxIterations);
58
-
59
- if (hd > hausdorffTolerance) {
60
- break;
61
- } else {
62
- canDeletes.add(branch[j]);
63
- }
64
- }
65
-
66
- if (i+1 === j) {
67
- continue; // no simplification occured
68
- }
69
- }
70
- }
71
-
72
- // cpNode = findFirst(cpNode_ => isTerminating(cpNode_) ? cpNode_ : undefined, cpNode)!;
73
- cpNode = findFirst(isTerminating, cpNode)!;
74
-
75
- for (const cpNode of canDeletes) {
76
- if (!isVertex(cpNode =>
77
- (getProngCount(cpNode) !== 2) &&
78
- !cpNode.isHoleClosing
79
- )(cpNode)) {
80
-
81
- removeVertex(cpNode, mat.meta);
82
- }
83
- }
84
-
85
-
86
- return {
87
- cpNode,
88
- meta: {
89
- ...mat.meta,
90
- cpTrees: createNewCpTrees(cpNode)
91
- }
92
- }
93
- }
94
-
95
-
96
- function getTotalHausdorffDistance(
97
- i: number,
98
- j: number,
99
- branch: CpNode[],
100
- hausdorffSpacing: number) {
101
-
102
- const hds: number[] = [];
103
- const longCurve = getMatCurveBetween(branch[i], branch[j].next);
104
- for (; i<j+1; i++) {
105
- hds.push(hausdorffDistanceOneSided(
106
- getMatCurveToNext(branch[i]),
107
- longCurve,
108
- hausdorffSpacing
109
- ));
110
- }
111
-
112
- return max(...hds);
113
- }
114
-
115
-
116
- export { simplifyMat }
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 }
@@ -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
- * @param mat The MAT to trim.
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
- * @param minCurvature if not `Infinity` then the circle radius will be limited
11
- * to this value
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 useMaxRadius
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 { getRealProngCount } from '../cp-node/fs/get-real-prong-count.js';
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
- const maxPO2 = max(...mats.map(mat => mat.meta.maxCoordPowerOf2));
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
- return r;
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 a line segment of unit length starting at the given point and
195
- * being tangent to the shape boundary.
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 getEdgeDirection(
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 [p,v];
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
  *