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.
Files changed (379) 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/circle-identity.spec.ts +56 -0
  4. package/__tests__/cp-node/fs/get-all-on-loop-by-loop.spec.ts +55 -0
  5. package/__tests__/cp-node/fs/get-angle-between-mat-curves.spec.ts +39 -3
  6. package/__tests__/cp-node/fs/get-boundary-bezier-parts-to-next.spec.ts +87 -3
  7. package/__tests__/cp-node/fs/get-boundary-beziers-between.spec.ts +68 -3
  8. package/__tests__/cp-node/fs/get-boundary-beziers-to-next.spec.ts +41 -3
  9. package/__tests__/cp-node/fs/get-boundary-distance-to-next.spec.ts +20 -3
  10. package/__tests__/cp-node/fs/get-branch-beziers.spec.ts +42 -3
  11. package/__tests__/cp-node/fs/get-branch.spec.ts +60 -3
  12. package/__tests__/cp-node/fs/get-cp-node-ordering.spec.ts +19 -3
  13. package/__tests__/cp-node/fs/get-distance-to-next.spec.ts +37 -4
  14. package/__tests__/cp-node/fs/get-edge-direction.spec.ts +50 -3
  15. package/__tests__/cp-node/fs/get-first-exit.spec.ts +78 -3
  16. package/__tests__/cp-node/fs/get-hole-closers.spec.ts +32 -3
  17. package/__tests__/cp-node/fs/get-implied-boundary-bezier-between.spec.ts +48 -3
  18. package/__tests__/cp-node/fs/get-mat-curve-between.spec.ts +77 -3
  19. package/__tests__/cp-node/fs/get-mat-curve-to-next.spec.ts +17 -4
  20. package/__tests__/cp-node/fs/get-mat-curves-between.spec.ts +38 -3
  21. package/__tests__/cp-node/fs/get-salience.spec.ts +68 -3
  22. package/__tests__/cp-node/fs/get-vertex-forward-children.spec.ts +40 -3
  23. package/__tests__/cp-node/fs/insert-cp-node.spec.ts +87 -3
  24. package/__tests__/cp-node/fs/is-special.spec.ts +1 -1
  25. package/__tests__/cp-node/fs/remove-cp-node.spec.ts +42 -3
  26. package/__tests__/find-2-prong/calc-seperation-tolerance.spec.ts +46 -0
  27. package/__tests__/find-2-prong/get-medial/dd-get-medial-point-coeffs-same-curve.spec.ts +7 -5
  28. package/__tests__/find-2-prong/get-medial/dd-get-medial-point-coeffs.spec.ts +4 -2
  29. package/__tests__/find-2-prong/get-medial/get-closest-points.spec.ts +1 -1
  30. package/__tests__/floyd-warshall/get-graph.spec.ts +100 -0
  31. package/__tests__/get-mats-with-hole.ts +28 -0
  32. package/__tests__/get-mats1.spec.ts +61 -0
  33. package/__tests__/get-mats1.ts +75 -67
  34. package/__tests__/helpers/cp-node-by-id.ts +27 -0
  35. package/__tests__/helpers/expect-point-close.ts +42 -0
  36. package/__tests__/mat/hausdorff-distance-one-sided-exceeds.spec.ts +129 -0
  37. package/__tests__/mat/simplify-mat.spec.ts +85 -0
  38. package/__tests__/reconstruct-from-mat/reconstruct-from-mat.spec.ts +39 -0
  39. package/__tests__/specific-cases/test-svgs/achispado.svg +14 -0
  40. package/__tests__/utils/get-beziers-from-tangents.spec.ts +142 -0
  41. package/browser/index.js +17882 -13800
  42. package/browser/index.min.js +1 -1
  43. package/node/add-n-prong.ts/join-spokes.js +3 -2
  44. package/node/add-n-prong.ts/join-spokes.js.map +1 -1
  45. package/node/closest-boundary-point/cull-curve-pieces.d.ts +21 -0
  46. package/node/closest-boundary-point/cull-curve-pieces.js +40 -0
  47. package/node/closest-boundary-point/cull-curve-pieces.js.map +1 -0
  48. package/node/closest-boundary-point/get-close-boundary-points-certified.js +5 -2
  49. package/node/closest-boundary-point/get-close-boundary-points-certified.js.map +1 -1
  50. package/node/closest-boundary-point/get-endpoint-info.d.ts +39 -0
  51. package/node/closest-boundary-point/get-endpoint-info.js +78 -0
  52. package/node/closest-boundary-point/get-endpoint-info.js.map +1 -0
  53. package/node/closest-boundary-point/get-potential-closest-points-on-curve-certified.js +5 -19
  54. package/node/closest-boundary-point/get-potential-closest-points-on-curve-certified.js.map +1 -1
  55. package/node/closest-boundary-point/root-interval-to-distance-squared-interval.d.ts +17 -5
  56. package/node/closest-boundary-point/root-interval-to-distance-squared-interval.js +37 -50
  57. package/node/closest-boundary-point/root-interval-to-distance-squared-interval.js.map +1 -1
  58. package/node/corner/get-corner.d.ts +18 -1
  59. package/node/corner/get-corner.js +8 -1
  60. package/node/corner/get-corner.js.map +1 -1
  61. package/node/corner/get-interface-ccw.js.map +1 -1
  62. package/node/cp-node/cp-node.d.ts +4 -3
  63. package/node/cp-node/fs/enhance-cp-node.d.ts +9 -9
  64. package/node/cp-node/fs/get-all-on-loop-by-loop.js +0 -4
  65. package/node/cp-node/fs/get-all-on-loop-by-loop.js.map +1 -1
  66. package/node/cp-node/fs/get-angle-between-mat-curves.d.ts +1 -1
  67. package/node/cp-node/fs/get-angle-between-mat-curves.js +7 -4
  68. package/node/cp-node/fs/get-angle-between-mat-curves.js.map +1 -1
  69. package/node/cp-node/fs/get-boundary-beziers-between.d.ts +6 -4
  70. package/node/cp-node/fs/get-boundary-beziers-between.js +6 -4
  71. package/node/cp-node/fs/get-boundary-beziers-between.js.map +1 -1
  72. package/node/cp-node/fs/get-branch-beziers.d.ts +2 -1
  73. package/node/cp-node/fs/get-branch-beziers.js +3 -2
  74. package/node/cp-node/fs/get-branch-beziers.js.map +1 -1
  75. package/node/cp-node/fs/get-branch.js +1 -2
  76. package/node/cp-node/fs/get-branch.js.map +1 -1
  77. package/node/cp-node/fs/get-distance-to-next.js +4 -2
  78. package/node/cp-node/fs/get-distance-to-next.js.map +1 -1
  79. package/node/cp-node/fs/get-edge-direction.js +3 -2
  80. package/node/cp-node/fs/get-edge-direction.js.map +1 -1
  81. package/node/cp-node/fs/get-first-exit.d.ts +7 -3
  82. package/node/cp-node/fs/get-first-exit.js +13 -11
  83. package/node/cp-node/fs/get-first-exit.js.map +1 -1
  84. package/node/cp-node/fs/get-implied-boundary-bezier-between.d.ts +10 -2
  85. package/node/cp-node/fs/get-implied-boundary-bezier-between.js +11 -54
  86. package/node/cp-node/fs/get-implied-boundary-bezier-between.js.map +1 -1
  87. package/node/cp-node/fs/get-mat-curve-between.d.ts +5 -3
  88. package/node/cp-node/fs/get-mat-curve-between.js +6 -49
  89. package/node/cp-node/fs/get-mat-curve-between.js.map +1 -1
  90. package/node/cp-node/fs/get-mat-curve-to-next.d.ts +1 -1
  91. package/node/cp-node/fs/get-mat-curves-between.d.ts +8 -0
  92. package/node/cp-node/fs/get-mat-curves-between.js +9 -2
  93. package/node/cp-node/fs/get-mat-curves-between.js.map +1 -1
  94. package/node/cp-node/fs/get-real-prong-count.d.ts +2 -1
  95. package/node/cp-node/fs/get-real-prong-count.js +11 -5
  96. package/node/cp-node/fs/get-real-prong-count.js.map +1 -1
  97. package/node/cp-node/fs/get-salience.d.ts +10 -0
  98. package/node/cp-node/fs/get-salience.js +17 -1
  99. package/node/cp-node/fs/get-salience.js.map +1 -1
  100. package/node/cp-node/fs/is-fully-terminating.d.ts +4 -2
  101. package/node/cp-node/fs/is-fully-terminating.js +6 -17
  102. package/node/cp-node/fs/is-fully-terminating.js.map +1 -1
  103. package/node/cp-node/fs/is-on-same-circle.d.ts +3 -0
  104. package/node/cp-node/fs/is-on-same-circle.js +4 -4
  105. package/node/cp-node/fs/is-on-same-circle.js.map +1 -1
  106. package/node/cp-node/fs/is-on-same-loop.d.ts +1 -1
  107. package/node/cp-node/fs/is-special.d.ts +7 -0
  108. package/node/cp-node/fs/is-special.js +9 -2
  109. package/node/cp-node/fs/is-special.js.map +1 -1
  110. package/node/cp-node/fs/is-vertex.d.ts +1 -1
  111. package/node/cp-node/fs/traverse-edges.d.ts +7 -3
  112. package/node/cp-node/fs/traverse-edges.js +7 -3
  113. package/node/cp-node/fs/traverse-edges.js.map +1 -1
  114. package/node/cp-node/stringification/from-stringifyable.d.ts +2 -2
  115. package/node/cp-node/stringification/from-stringifyable.js +17 -1
  116. package/node/cp-node/stringification/from-stringifyable.js.map +1 -1
  117. package/node/cp-node/stringification/to-stringifyable.d.ts +3 -3
  118. package/node/cp-node/stringification/to-stringifyable.js +3 -3
  119. package/node/debug/debug.d.ts +26 -3
  120. package/node/debug/debug.js +16 -5
  121. package/node/debug/debug.js.map +1 -1
  122. package/node/find-2-prong/add-2-prong.js +7 -9
  123. package/node/find-2-prong/add-2-prong.js.map +1 -1
  124. package/node/find-2-prong/calc-seperation-tolerance.d.ts +28 -5
  125. package/node/find-2-prong/calc-seperation-tolerance.js +32 -89
  126. package/node/find-2-prong/calc-seperation-tolerance.js.map +1 -1
  127. package/node/find-2-prong/find-2-prong.js +8 -10
  128. package/node/find-2-prong/find-2-prong.js.map +1 -1
  129. package/node/find-2-prong/find-and-add-2-prongs.js +2 -2
  130. package/node/find-2-prong/find-and-add-2-prongs.js.map +1 -1
  131. package/node/find-2-prong/get-medial/get-antipodal-points.d.ts +1 -2
  132. package/node/find-2-prong/get-medial/get-antipodal-points.js +2 -3
  133. package/node/find-2-prong/get-medial/get-antipodal-points.js.map +1 -1
  134. package/node/find-2-prong/get-medial/get-closest-points.d.ts +1 -8
  135. package/node/find-2-prong/get-medial/get-closest-points.js +4 -40
  136. package/node/find-2-prong/get-medial/get-closest-points.js.map +1 -1
  137. package/node/find-2-prong/reduce-radius.d.ts +1 -1
  138. package/node/find-2-prong/reduce-radius.js +6 -3
  139. package/node/find-2-prong/reduce-radius.js.map +1 -1
  140. package/node/find-3-prong/calc-better-x.js +1 -1
  141. package/node/find-3-prong/calc-better-x.js.map +1 -1
  142. package/node/find-3-prong/find-3-prong-for-delta3s.d.ts +3 -2
  143. package/node/find-3-prong/find-3-prong-for-delta3s.js +36 -42
  144. package/node/find-3-prong/find-3-prong-for-delta3s.js.map +1 -1
  145. package/node/find-3-prong/find-3-prong.js +3 -1
  146. package/node/find-3-prong/find-3-prong.js.map +1 -1
  147. package/node/find-3-prong/find-and-add-3-prongs.js +16 -0
  148. package/node/find-3-prong/find-and-add-3-prongs.js.map +1 -1
  149. package/node/find-mat/create-initial-cp-tree.js +2 -2
  150. package/node/find-mat/create-initial-cp-tree.js.map +1 -1
  151. package/node/find-mat/find-mat.js +3 -4
  152. package/node/find-mat/find-mat.js.map +1 -1
  153. package/node/find-mat/find-mats.d.ts +6 -12
  154. package/node/find-mat/find-mats.js +10 -27
  155. package/node/find-mat/find-mats.js.map +1 -1
  156. package/node/find-mat/get-dull-corners-on-loop.js +2 -2
  157. package/node/find-mat/get-dull-corners-on-loop.js.map +1 -1
  158. package/node/find-mat/get-for-1-prongs-on-loop.js +36 -8
  159. package/node/find-mat/get-for-1-prongs-on-loop.js.map +1 -1
  160. package/node/find-mat/get-meta.d.ts +14 -4
  161. package/node/find-mat/get-meta.js +30 -24
  162. package/node/find-mat/get-meta.js.map +1 -1
  163. package/node/find-mat/get-sharp-corners.js +2 -2
  164. package/node/find-mat/get-sharp-corners.js.map +1 -1
  165. package/node/find-mat/mat-options.d.ts +2 -2
  166. package/node/floyd-warshall/get-graph.d.ts +12 -1
  167. package/node/floyd-warshall/get-graph.js +41 -38
  168. package/node/floyd-warshall/get-graph.js.map +1 -1
  169. package/node/geometry/get-bounding-box-.d.ts +16 -2
  170. package/node/geometry/get-bounding-box-.js +5 -2
  171. package/node/geometry/get-bounding-box-.js.map +1 -1
  172. package/node/geometry/get-closest-square-distance-to-rect.d.ts +3 -0
  173. package/node/geometry/get-closest-square-distance-to-rect.js +7 -5
  174. package/node/geometry/get-closest-square-distance-to-rect.js.map +1 -1
  175. package/node/geometry/get-closest-squared-distance-to-rotated-rect.d.ts +4 -0
  176. package/node/geometry/get-closest-squared-distance-to-rotated-rect.js +12 -5
  177. package/node/geometry/get-closest-squared-distance-to-rotated-rect.js.map +1 -1
  178. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.js +1 -2
  179. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.js.map +1 -1
  180. package/node/index.d.ts +3 -2
  181. package/node/index.js +2 -1
  182. package/node/index.js.map +1 -1
  183. package/node/mat/clone-mat.d.ts +9 -0
  184. package/node/mat/clone-mat.js +17 -0
  185. package/node/mat/clone-mat.js.map +1 -0
  186. package/node/mat/clone-meta.d.ts +12 -0
  187. package/node/mat/clone-meta.js +24 -0
  188. package/node/mat/clone-meta.js.map +1 -0
  189. package/node/mat/get-boundary-piece-beziers.d.ts +5 -0
  190. package/node/mat/get-boundary-piece-beziers.js +7 -93
  191. package/node/mat/get-boundary-piece-beziers.js.map +1 -1
  192. package/node/mat/get-closeby-cp-if-exist.js +2 -1
  193. package/node/mat/get-closeby-cp-if-exist.js.map +1 -1
  194. package/node/mat/get-largest-3-prong.d.ts +6 -0
  195. package/node/mat/get-largest-3-prong.js +8 -5
  196. package/node/mat/get-largest-3-prong.js.map +1 -1
  197. package/node/mat/get-largest-vertex.d.ts +15 -1
  198. package/node/mat/get-largest-vertex.js +20 -7
  199. package/node/mat/get-largest-vertex.js.map +1 -1
  200. package/node/mat/hausdorff-distance-one-sided-exceeds.d.ts +79 -0
  201. package/node/mat/hausdorff-distance-one-sided-exceeds.js +251 -0
  202. package/node/mat/hausdorff-distance-one-sided-exceeds.js.map +1 -0
  203. package/node/mat/mat-meta.d.ts +0 -6
  204. package/node/mat/simplify-mat.d.ts +25 -8
  205. package/node/mat/simplify-mat.js +182 -53
  206. package/node/mat/simplify-mat.js.map +1 -1
  207. package/node/mat/trim-mat.d.ts +4 -2
  208. package/node/mat/trim-mat.js +3 -1
  209. package/node/mat/trim-mat.js.map +1 -1
  210. package/node/point-on-shape/get-boundary-tangent-line.d.ts +19 -0
  211. package/node/point-on-shape/get-boundary-tangent-line.js +33 -0
  212. package/node/point-on-shape/get-boundary-tangent-line.js.map +1 -0
  213. package/node/point-on-shape/get-osculating-circle.d.ts +6 -4
  214. package/node/point-on-shape/get-osculating-circle.js +6 -4
  215. package/node/point-on-shape/get-osculating-circle.js.map +1 -1
  216. package/node/point-on-shape/get-pos-corner.js +2 -2
  217. package/node/point-on-shape/get-pos-corner.js.map +1 -1
  218. package/node/point-on-shape/point-on-shape.d.ts +5 -0
  219. package/node/reconstruct-from-mat/reconstruct-from-mat.js +20 -80
  220. package/node/reconstruct-from-mat/reconstruct-from-mat.js.map +1 -1
  221. package/node/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.d.ts +4 -0
  222. package/node/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.js +4 -0
  223. package/node/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.js.map +1 -1
  224. package/node/sat/cull.d.ts +7 -6
  225. package/node/sat/cull.js +13 -16
  226. package/node/sat/cull.js.map +1 -1
  227. package/node/sat/get-sat-culls.d.ts +12 -2
  228. package/node/sat/get-sat-culls.js +21 -16
  229. package/node/sat/get-sat-culls.js.map +1 -1
  230. package/node/svg/get-shape-bounds.d.ts +1 -12
  231. package/node/svg/get-shape-bounds.js +2 -3
  232. package/node/svg/get-shape-bounds.js.map +1 -1
  233. package/node/sweep-line/sweep-line.js.map +1 -1
  234. package/node/utils/get-beziers-from-tangents.d.ts +28 -0
  235. package/node/utils/get-beziers-from-tangents.js +92 -0
  236. package/node/utils/get-beziers-from-tangents.js.map +1 -0
  237. package/node/vertex/remove-vertex.d.ts +5 -3
  238. package/node/vertex/remove-vertex.js +5 -3
  239. package/node/vertex/remove-vertex.js.map +1 -1
  240. package/package.json +16 -16
  241. package/qv-infinite-loop.md +120 -0
  242. package/src/add-n-prong.ts/join-spokes.ts +4 -2
  243. package/src/closest-boundary-point/cull-curve-pieces.ts +49 -0
  244. package/src/closest-boundary-point/get-close-boundary-points-certified.ts +5 -2
  245. package/src/closest-boundary-point/get-endpoint-info.ts +96 -0
  246. package/src/closest-boundary-point/get-potential-closest-points-on-curve-certified.ts +5 -23
  247. package/src/closest-boundary-point/root-interval-to-distance-squared-interval.ts +42 -60
  248. package/src/corner/get-corner.ts +10 -1
  249. package/src/corner/get-interface-ccw.ts +2 -2
  250. package/src/cp-node/cp-node.ts +4 -3
  251. package/src/cp-node/fs/get-all-on-loop-by-loop.ts +0 -4
  252. package/src/cp-node/fs/get-angle-between-mat-curves.ts +9 -5
  253. package/src/cp-node/fs/get-boundary-beziers-between.ts +10 -8
  254. package/src/cp-node/fs/get-branch-beziers.ts +3 -2
  255. package/src/cp-node/fs/get-branch.ts +1 -2
  256. package/src/cp-node/fs/get-distance-to-next.ts +4 -2
  257. package/src/cp-node/fs/get-edge-direction.ts +4 -2
  258. package/src/cp-node/fs/get-first-exit.ts +15 -14
  259. package/src/cp-node/fs/get-implied-boundary-bezier-between.ts +18 -70
  260. package/src/cp-node/fs/get-mat-curve-between.ts +10 -67
  261. package/src/cp-node/fs/get-mat-curves-between.ts +9 -2
  262. package/src/cp-node/fs/get-real-prong-count.ts +11 -7
  263. package/src/cp-node/fs/get-salience.ts +15 -2
  264. package/src/cp-node/fs/is-fully-terminating.ts +6 -22
  265. package/src/cp-node/fs/is-on-same-circle.ts +6 -7
  266. package/src/cp-node/fs/is-on-same-loop.ts +2 -2
  267. package/src/cp-node/fs/is-special.ts +11 -6
  268. package/src/cp-node/fs/is-vertex.ts +1 -1
  269. package/src/cp-node/fs/traverse-edges.ts +8 -4
  270. package/src/cp-node/stringification/from-stringifyable.ts +75 -58
  271. package/src/cp-node/stringification/to-stringifyable.ts +3 -3
  272. package/src/debug/debug.ts +44 -8
  273. package/src/find-2-prong/add-2-prong.ts +9 -11
  274. package/src/find-2-prong/calc-seperation-tolerance.ts +34 -115
  275. package/src/find-2-prong/find-2-prong.ts +9 -11
  276. package/src/find-2-prong/find-and-add-2-prongs.ts +2 -2
  277. package/src/find-2-prong/get-medial/get-antipodal-points.ts +1 -3
  278. package/src/find-2-prong/get-medial/get-closest-points.ts +6 -51
  279. package/src/find-2-prong/reduce-radius.ts +6 -4
  280. package/src/find-3-prong/calc-better-x.ts +2 -2
  281. package/src/find-3-prong/find-3-prong-for-delta3s.ts +197 -214
  282. package/src/find-3-prong/find-3-prong.ts +54 -51
  283. package/src/find-3-prong/find-and-add-3-prongs.ts +20 -1
  284. package/src/find-mat/create-initial-cp-tree.ts +2 -2
  285. package/src/find-mat/find-mat.ts +4 -6
  286. package/src/find-mat/find-mats.ts +83 -105
  287. package/src/find-mat/get-dull-corners-on-loop.ts +2 -2
  288. package/src/find-mat/get-for-1-prongs-on-loop.ts +40 -8
  289. package/src/find-mat/get-meta.ts +34 -39
  290. package/src/find-mat/get-sharp-corners.ts +2 -2
  291. package/src/find-mat/mat-options.ts +2 -2
  292. package/src/floyd-warshall/get-graph.ts +46 -47
  293. package/src/geometry/get-bounding-box-.ts +5 -2
  294. package/src/geometry/get-closest-square-distance-to-rect.ts +7 -7
  295. package/src/geometry/get-closest-squared-distance-to-rotated-rect.ts +15 -13
  296. package/src/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.ts +1 -2
  297. package/src/index.ts +3 -2
  298. package/src/mat/clone-mat.ts +9 -3
  299. package/src/mat/clone-meta.ts +8 -0
  300. package/src/mat/get-boundary-piece-beziers.ts +16 -117
  301. package/src/mat/get-closeby-cp-if-exist.ts +3 -1
  302. package/src/mat/get-largest-3-prong.ts +9 -6
  303. package/src/mat/get-largest-vertex.ts +25 -9
  304. package/src/mat/hausdorff-distance-one-sided-exceeds.ts +314 -0
  305. package/src/mat/mat-meta.ts +0 -9
  306. package/src/mat/simplify-mat.ts +254 -116
  307. package/src/mat/trim-mat.ts +6 -4
  308. package/src/point-on-shape/get-boundary-tangent-line.ts +36 -0
  309. package/src/point-on-shape/get-osculating-circle.ts +7 -5
  310. package/src/point-on-shape/get-pos-corner.ts +2 -2
  311. package/src/point-on-shape/point-on-shape.ts +5 -0
  312. package/src/reconstruct-from-mat/reconstruct-from-mat.ts +22 -111
  313. package/src/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.ts +4 -0
  314. package/src/sat/cull.ts +16 -20
  315. package/src/sat/get-sat-culls.ts +28 -23
  316. package/src/svg/get-shape-bounds.ts +2 -3
  317. package/src/sweep-line/sweep-line.ts +1 -1
  318. package/src/utils/deg-to-rad.ts +4 -2
  319. package/src/utils/get-beziers-from-tangents.ts +110 -0
  320. package/src/utils/map-map.ts +1 -1
  321. package/src/utils/rad-to-deg.ts +4 -1
  322. package/src/vertex/remove-vertex.ts +5 -3
  323. package/webpack.config.cjs +7 -2
  324. package/__tests__/cp-node/fs/get-distance-between.spec.ts +0 -7
  325. package/__tests__/cp-node/fs/get-terminating-on-circle.spec.ts +0 -24
  326. package/__tests__/cp-node/fs/is-single-3-prong.spec.ts +0 -17
  327. package/__tests__/cp-node/fs/iterate-all-on-loop.spec.ts +0 -17
  328. package/__tests__/cp-node/fs/traverse-all-forward.spec.ts +0 -14
  329. package/node/closest-boundary-point/cull-bezier-pieces-1.d.ts +0 -9
  330. package/node/closest-boundary-point/cull-bezier-pieces-1.js +0 -17
  331. package/node/closest-boundary-point/cull-bezier-pieces-1.js.map +0 -1
  332. package/node/closest-boundary-point/cull-by-loose-bounding-box.d.ts +0 -13
  333. package/node/closest-boundary-point/cull-by-loose-bounding-box.js +0 -27
  334. package/node/closest-boundary-point/cull-by-loose-bounding-box.js.map +0 -1
  335. package/node/closest-boundary-point/cull-by-tight-boundary-box.d.ts +0 -11
  336. package/node/closest-boundary-point/cull-by-tight-boundary-box.js +0 -27
  337. package/node/closest-boundary-point/cull-by-tight-boundary-box.js.map +0 -1
  338. package/node/cp-node/fs/find-first.d.ts +0 -10
  339. package/node/cp-node/fs/find-first.js +0 -19
  340. package/node/cp-node/fs/find-first.js.map +0 -1
  341. package/node/debug/functions/check-ordering.d.ts +0 -4
  342. package/node/debug/functions/check-ordering.js +0 -43
  343. package/node/debug/functions/check-ordering.js.map +0 -1
  344. package/node/find-2-prong/cull-bezier-pieces.d.ts +0 -13
  345. package/node/find-2-prong/cull-bezier-pieces.js +0 -43
  346. package/node/find-2-prong/cull-bezier-pieces.js.map +0 -1
  347. package/node/floyd-warshall/get-hole-closer-pairs.d.ts +0 -8
  348. package/node/floyd-warshall/get-hole-closer-pairs.js +0 -27
  349. package/node/floyd-warshall/get-hole-closer-pairs.js.map +0 -1
  350. package/node/utils/dual-set.d.ts +0 -27
  351. package/node/utils/dual-set.js +0 -55
  352. package/node/utils/dual-set.js.map +0 -1
  353. package/node/utils/tri-map.d.ts +0 -27
  354. package/node/utils/tri-map.js +0 -49
  355. package/node/utils/tri-map.js.map +0 -1
  356. package/src/closest-boundary-point/cull-bezier-pieces-1.ts +0 -36
  357. package/src/closest-boundary-point/cull-by-loose-bounding-box.ts +0 -42
  358. package/src/closest-boundary-point/cull-by-tight-boundary-box.ts +0 -43
  359. package/src/closest-boundary-point/get-p-from-box.ts +0 -14
  360. package/src/cp-node/fs/add-distance-from.ts +0 -49
  361. package/src/cp-node/fs/get-distance-between.ts +0 -16
  362. package/src/cp-node/fs/get-terminating-on-circle.ts +0 -24
  363. package/src/cp-node/fs/is-single-3-prong.ts +0 -15
  364. package/src/cp-node/fs/iterate-all-on-loop.ts +0 -15
  365. package/src/cp-node/fs/traverse-all-forward.ts +0 -24
  366. package/src/debug/functions/draw/draw-beziers-as-single-path.ts +0 -40
  367. package/src/debug/functions/draw/draw-disk.ts +0 -34
  368. package/src/debug/functions/draw/xmlns.ts +0 -5
  369. package/src/find-2-prong/cull-bezier-pieces.ts +0 -61
  370. package/src/find-2-prong/find-and-add-2-prong.ts +0 -30
  371. package/src/find-2-prong/get-medial/get-closest-points-d.ts +0 -213
  372. package/src/find-2-prong/x-for-debugging.ts +0 -13
  373. package/src/floyd-warshall/get-hole-closer-pairs.ts +0 -35
  374. package/src/mat/get-two-prong-type.ts +0 -13
  375. package/src/point-on-shape/is-pos-dull-corner.ts +0 -18
  376. package/src/point-on-shape/is-pos-quite-dull-corner.ts +0 -18
  377. package/src/point-on-shape/is-pos-quite-sharp-corner.ts +0 -18
  378. package/src/point-on-shape/pos-to-human-string.ts +0 -18
  379. package/src/sweep-line/are-boxes-intersecting.ts +0 -37
@@ -1,75 +1,57 @@
1
- import { twoDiff, ddMultDd, ddAddDd } from 'double-double';
1
+ import { eps } from '../error-analysis/gamma.js';
2
2
 
3
- const td = twoDiff;
4
- const qmq = ddMultDd;
5
- const qaq = ddAddDd;
3
+ const { max } = Math;
6
4
 
7
- const eps = Number.EPSILON;
5
+ /**
6
+ * Relative widening of the interval bounds - see the error analysis in
7
+ * `rootIntervalToDistanceSquaredInterval`: the exact first order requirement
8
+ * is `4u = 2eps` (`u = eps/2` the unit roundoff); `4eps = 2**-50` (exactly
9
+ * representable) leaves room for the `O(u²)` terms.
10
+ */
11
+ const WIDEN = 4*eps;
8
12
 
9
13
 
10
14
  /**
11
- * Returns the distance interval squared given the root interval (currently
12
- * ignoring multiplicity).
13
- *
14
- * * the result is returned as `[minPossibleSquared, maxPossibleSquared]` distance.
15
- *
16
- * @param box
17
- * @param p
18
- *
15
+ * Returns an interval `[min, max]` guaranteed to contain the squared distance
16
+ * from the point `p` to *any* point of a curve piece, given an axis-aligned
17
+ * box that is guaranteed to engulf that piece (see `getIntervalBox`).
18
+ *
19
+ * * the minimum squared distance to the box is attained on its boundary (or
20
+ * is `0` if `p` is inside): per axis the distance is the gap between `p` and
21
+ * the box's range on that axis (`0` if `p` is within the range)
22
+ * * the maximum squared distance to the box is attained at a corner: per axis
23
+ * it is the larger of the distances to the two range ends
24
+ *
25
+ * Error analysis (`u = eps/2` the unit roundoff, `fl(a∘b) = (a∘b)(1+δ)`,
26
+ * `|δ| <= u`): all inputs are doubles and each bound is computed with 3
27
+ * roundings per term path (subtraction, square, sum - `max` is exact) and
28
+ * widened with 1 more, so the computed bound is within a factor `(1±u)⁴` of
29
+ * the exact one before widening and `WIDEN >= 4u + O(u²)` makes the interval
30
+ * rigorous. (A gap of `0` is exact: `fl(a-b)` has the sign of `a-b`.)
31
+ *
32
+ * @param box the engulfing box given as `[[minX, minY], [maxX, maxY]]`
33
+ * @param p the point
34
+ *
19
35
  * @internal
20
36
  */
21
37
  function rootIntervalToDistanceSquaredInterval(
22
- box: number[][],
23
- p: number[]) {
24
-
25
- const bl = box[0];
26
- const tr = box[1];
27
- const minX = bl[0];
28
- const minY = bl[1];
29
- const maxX = tr[0];
30
- const maxY = tr[1];
31
-
32
- const x = p[0]; // <0>
33
- const y = p[1]; // <0>
34
-
35
- let minDSquared = +Infinity;
36
- let maxDSquared = -Infinity;
37
-
38
- // for each corner of the interval box
39
- for (const [a,b] of [[minX,minY],[minX,maxY],[maxX,minY],[maxX,maxY]]) {
40
- /*
41
- // distance to 1st corner of interval box - `distance² = x² + y²`
42
- const dc1 = (a - x)**2 + (b - y)**2;
43
- // max absolute roundoff error of `dc1`
44
- // <4>dc1 <-- <4>(<3>(<1>(a - x)**2) + <3>(<1>((b - y)**2))
45
- const dc1E = 4*γ1*((a + x)**2 + (b + y)**2);
46
- const dc1Min = dc1 - dc1E; // distance minus max error
47
- const dc1Max = dc1 + dc1E; // distance plus max error
48
- */
38
+ box: number[][],
39
+ p: number[]): number[] {
49
40
 
50
- /** distance to 1st corner of interval box - `distance² = x² + y²` */
51
- const ax = td(a,x); // a - x
52
- const by = td(b,y); // b - y
53
- // const dc1Exact = eadd(emult(ax,ax),emult(by,by)); // ax**2 + bx**2
54
- // const dc1 = estimate(dc1Exact);
55
- const dc1Dd = qaq(qmq(ax,ax),qmq(by,by)); // ax**2 + bx**2
56
- const dc1 = dc1Dd[1];
41
+ const [[minX, minY], [maxX, maxY]] = box;
42
+ const [x, y] = p;
57
43
 
58
- // const dc1Min = dc1*(1 - 2**maxCoordPowerOf2*eps); // distance minus max error
59
- // const dc1Max = dc1*(1 + 2**maxCoordPowerOf2*eps); // distance plus max error
60
- const dc1Min = dc1*(1 - eps); // distance minus max error
61
- const dc1Max = dc1*(1 + eps); // distance plus max error
62
-
63
- if (dc1Min <= minDSquared) {
64
- minDSquared = dc1Min;
65
- }
44
+ // per axis gap between `p` and the box (`0` if `p` is within range)
45
+ const dxMin = max(minX - x, 0, x - maxX);
46
+ const dyMin = max(minY - y, 0, y - maxY);
47
+ // per axis distance from `p` to the furthest end of the box's range
48
+ const dxMax = max(x - minX, maxX - x);
49
+ const dyMax = max(y - minY, maxY - y);
66
50
 
67
- if (dc1Max >= maxDSquared) {
68
- maxDSquared = dc1Max;
69
- }
70
- }
51
+ const minDSquared = dxMin*dxMin + dyMin*dyMin;
52
+ const maxDSquared = dxMax*dxMax + dyMax*dyMax;
71
53
 
72
- return [minDSquared,maxDSquared];
54
+ return [minDSquared*(1 - WIDEN), maxDSquared*(1 + WIDEN)];
73
55
  }
74
56
 
75
57
 
@@ -1,4 +1,5 @@
1
1
  import type { Corner } from "./corner.js";
2
+ import { memoize } from 'flo-memoize';
2
3
  import { cross, toUnitVector } from "flo-vector2d";
3
4
  import { getInterfaceCcw } from './get-interface-ccw.js';
4
5
 
@@ -70,4 +71,12 @@ function getCorner(
70
71
  }
71
72
 
72
73
 
73
- export { getCorner }
74
+ /**
75
+ * Memoized version of `getCorner` (keyed on the two control point arrays).
76
+ *
77
+ * @internal
78
+ */
79
+ const getCorner$ = memoize(getCorner);
80
+
81
+
82
+ export { getCorner, getCorner$ }
@@ -1,4 +1,4 @@
1
- import { eAdd, eCompress, eEstimate, eMult, eNegativeOf, eProduct, orient2d, twoDiff } from 'big-float-ts';
1
+ import { eAdd, eEstimate, eMult, eNegativeOf, twoDiff } from 'big-float-ts';
2
2
  import { compareCurvaturesAtInterface } from "./compare-curvatures-at-interface.js";
3
3
 
4
4
 
@@ -137,4 +137,4 @@ function crossPrecise(
137
137
  }
138
138
 
139
139
 
140
- export { getInterfaceCcw }
140
+ export { getInterfaceCcw }
@@ -26,9 +26,10 @@ import { PointOnShape } from '../point-on-shape/point-on-shape.js';
26
26
  * following other branches on the MAT.
27
27
  *
28
28
  * Call `getMatCurveBetween(cpNodeFrom, cpNodeTo)` or `getMatCurveToNext(cpNode)`
29
- * (replacing the older CpNode.`matCurveToNextVertex`) to get a bezier curve
30
- * from the maximal disk of this `CpNode` to the next `CpNode`'s
31
- * maximal disk and thus directly representing a piece of the medial axis.
29
+ * (replacing the older CpNode.`matCurveToNextVertex`) to get the bezier curves
30
+ * (1 or 2 lines or quadratics joined smoothly) from the maximal disk of this
31
+ * `CpNode` to the next `CpNode`'s maximal disk and thus directly representing
32
+ * a piece of the medial axis.
32
33
  *
33
34
  * The function, `getChildren`, returns the children of this `CpNode` when
34
35
  * seen as a MAT edge. Only children in a 'forward' direction are returned. These
@@ -16,10 +16,6 @@ function getAllOnLoop_ByLoop(
16
16
 
17
17
  const cpStarts: CpNode[] = [cpNode];
18
18
  const cpStartSet = new Set(cpStarts);
19
- if (cpNode.isHoleClosing) {
20
- cpStartSet.add(cpNode.prevOnCircle.holeCloserTwin!);
21
- }
22
- cpStartSet.add(cpNode);
23
19
 
24
20
  while (cpStarts.length > 0) {
25
21
  const cpNodes: CpNode[] = [];
@@ -1,8 +1,10 @@
1
+ import type { CpNode } from "../cp-node.js";
1
2
  import { tangent } from "flo-bezier3";
2
3
  import { cross, toUnitVector } from "flo-vector2d";
3
- import { CpNode } from "../cp-node.js";
4
4
  import { getMatCurveToNext } from "./get-mat-curve-to-next.js";
5
5
 
6
+ const { abs, asin, min, max, PI: π } = Math;
7
+
6
8
 
7
9
  /**
8
10
  *
@@ -15,16 +17,18 @@ function getInitialDegAngleBetweenMatCurves(
15
17
  cpNode2: CpNode) {
16
18
 
17
19
  const tan1 = toUnitVector(tangent(
18
- getMatCurveToNext(cpNode1),
20
+ getMatCurveToNext(cpNode1)[0],
19
21
  0
20
22
  ));
21
23
  const tan2 = toUnitVector(tangent(
22
- getMatCurveToNext(cpNode2),
24
+ getMatCurveToNext(cpNode2)[0],
23
25
  0
24
26
  ));
25
27
 
26
- const cross_ = cross(tan1, tan2);
27
- const angle = Math.abs(Math.asin( cross_ ) * (180/Math.PI));
28
+ // clamp: rounding can push the cross product of two unit vectors just
29
+ // outside [-1,1], which would make `asin` return `NaN`
30
+ const cross_ = max(-1, min(1, cross(tan1, tan2)));
31
+ const angle = abs(asin( cross_ ) * (180/π));
28
32
 
29
33
  return angle;
30
34
  }
@@ -4,15 +4,17 @@ import { getBoundaryBeziersToNext } from "./get-boundary-beziers-to-next.js";
4
4
 
5
5
 
6
6
  /**
7
- * Returns all `CpNode`s between the two given ones (inclusive).
8
- *
9
- * * If the second `CpNode` is never encountered all on the loop will be
7
+ * Returns the bezier curves of the shape boundary from the contact point of
8
+ * the first given `CpNode` to that of the second (following `next`), together
9
+ * with whether a hole closer was passed on the way.
10
+ *
11
+ * * If the second `CpNode` is never encountered the entire boundary is
10
12
  * returned.
11
- *
12
- * @param cpNode1
13
- * @param cpNode2
14
- * @param inclAllIfEqual if `true` and first and last `CpNode`s are equal then
15
- * include all `CpNode`s around the loop, otherwise include none.
13
+ *
14
+ * @param cpNode1
15
+ * @param cpNode2
16
+ * @param inclAllIfEqual if `true` and the two `CpNode`s are equal then return
17
+ * the entire boundary, otherwise return nothing.
16
18
  */
17
19
  function getBoundaryBeziersBetween(
18
20
  cpNode1: CpNode,
@@ -4,14 +4,15 @@ import { getMatCurveToNext } from './get-mat-curve-to-next.js';
4
4
 
5
5
 
6
6
  /**
7
- * Returns the branch associated with the give cpNode
7
+ * Returns the (flattened) array of bezier curves (lines or quadratics)
8
+ * representing the branch associated with the given cpNode
8
9
  *
9
10
  * @param cpNode `CpNode` representing the start vertex.
10
11
  */
11
12
  function getBranchBeziers(
12
13
  cpNode: CpNode): number[][][] {
13
14
 
14
- return getBranch(cpNode).map(b => getMatCurveToNext(b));
15
+ return getBranch(cpNode).flatMap(getMatCurveToNext);
15
16
  }
16
17
 
17
18
 
@@ -1,6 +1,5 @@
1
1
  import { CpNode } from '../cp-node.js';
2
2
  import { getRealProngCount } from './get-real-prong-count.js';
3
- import { isFullyTerminating } from './is-fully-terminating.js';
4
3
  import { isTerminating } from './is-terminating.js';
5
4
  import { isTrivial } from './is-trivial.js';
6
5
 
@@ -34,7 +33,7 @@ function getBranch(
34
33
  do {
35
34
  branch.push(cpNode);
36
35
  cpNode = cpNode.next;
37
- } while (!isFullyTerminating(cpNode) && getRealProngCount(cpNode) === 2)
36
+ } while (getRealProngCount(cpNode) === 2)
38
37
 
39
38
  return branch;
40
39
  }
@@ -7,8 +7,10 @@ import { getMatCurveToNext } from "./get-mat-curve-to-next.js";
7
7
  function getMatDistanceToNext(
8
8
  cpNode: CpNode) {
9
9
 
10
- const ps = getMatCurveToNext(cpNode);
11
- const l = totalLength(ps);
10
+ let l = 0;
11
+ for (const ps of getMatCurveToNext(cpNode)) {
12
+ l += totalLength(ps);
13
+ }
12
14
 
13
15
  return l;
14
16
  }
@@ -4,6 +4,8 @@ import { toUnitVector, fromTo, rotate, translate, rotate90Degrees, reverse as re
4
4
  import { tangent } from 'flo-bezier3';
5
5
  import { isPosSharpCorner } from '../../point-on-shape/is-pos-sharp-corner.js';
6
6
 
7
+ const { sqrt } = Math;
8
+
7
9
 
8
10
  /**
9
11
  * Returns a line segment of unit length starting in the given Vertex center and
@@ -54,8 +56,8 @@ function getEdgeDirection(
54
56
  // Recall the identities sin(acos(x)) = sqrt(1-x^2), etc. Also
55
57
  // recall the half angle formulas. Then the rotation matrix, R, can
56
58
  // be calculated.
57
- const cosθ = Math.sqrt((1 + x)/2);
58
- const sinθ = Math.sqrt((1 - x)/2);
59
+ const cosθ = sqrt((1 + x)/2);
60
+ const sinθ = sqrt((1 - x)/2);
59
61
 
60
62
  vDir = rotate(sinθ, cosθ, tan2);
61
63
  }
@@ -1,25 +1,26 @@
1
- import { CpNode } from "../cp-node.js";
1
+ import type { CpNode } from "../cp-node.js";
2
+ import { isTerminating } from "./is-terminating.js";
2
3
 
3
4
 
4
5
  /**
5
- * Returns the first `CpNode` (from this one by successively applying
6
- * .nextOnCircle) that exits the circle.
6
+ * Returns the first `CpNode` *after* the given one (by successively applying
7
+ * `.nextOnCircle`) that exits the circle, i.e. the first one that is not
8
+ * terminating - the given `CpNode` itself is never returned.
9
+ *
10
+ * * returns `undefined` if no other `CpNode` on the circle exits (e.g. the
11
+ * other `CpNode` of a 1-prong, or the MAT is a single point)
7
12
  */
8
- function getFirstExit(cpNode: CpNode) {
9
- // const startNode = this as CpNode;
10
- const startNode = cpNode;
11
- let cpNode_ = startNode;
13
+ function getFirstExit(cpNode: CpNode): CpNode | undefined {
14
+ let cpNode_ = cpNode.nextOnCircle;
12
15
 
13
- while (cpNode_.next === cpNode_.prevOnCircle) {
14
- cpNode_ = cpNode_.next;
15
-
16
- if (cpNode_ === startNode) {
17
- // The very special case the MAT is a single point.
18
- return undefined;
16
+ while (cpNode_ !== cpNode) {
17
+ if (!isTerminating(cpNode_)) {
18
+ return cpNode_;
19
19
  }
20
+ cpNode_ = cpNode_.nextOnCircle;
20
21
  }
21
22
 
22
- return cpNode_;
23
+ return undefined;
23
24
  }
24
25
 
25
26
 
@@ -1,76 +1,24 @@
1
- import { tangent } from 'flo-bezier3';
2
- import {
3
- fromTo, dot, cross, translate, lineLineIntersection, toUnitVector
4
- } from 'flo-vector2d';
5
- import { CpNode } from '../cp-node.js';
6
-
7
-
8
- /** @internal */
9
- const TOLERANCE_ADD_2PRONG = 0.01;
10
- /** @internal */
11
- const TOLERANCE_USE_LINE = 0.0001; // else cubic
12
-
13
-
1
+ import type { CpNode } from '../cp-node.js';
2
+ import { getBoundaryTangentLine } from '../../point-on-shape/get-boundary-tangent-line.js';
3
+ import { getBeziersFromTangents } from '../../utils/get-beziers-from-tangents.js';
4
+
5
+
6
+ /**
7
+ * Returns the bezier curves (an array of 1 or 2 lines or quadratics joined
8
+ * smoothly) approximating the shape boundary between the contact points of
9
+ * two `CpNode`s.
10
+ *
11
+ * @param cpNodeA
12
+ * @param cpNodeB
13
+ */
14
14
  function getImpliedBoundaryBezierBetween(
15
15
  cpNodeA: CpNode,
16
- cpNodeB: CpNode): number[][] | undefined {
17
-
18
- const posA = cpNodeA.pointOnShape;
19
- const posB = cpNodeB.pointOnShape;
20
-
21
- let { curve: curveA, p: pA, t: tA } = posA;
22
- let { curve: curveB, p: pB, t: tB } = posB;
23
-
24
- if (pA[0] === pB[0] && pA[1] === pB[1]) {
25
- return [pA];
26
- }
27
-
28
- if (tA === 1) { tA = 0; curveA = curveA.next; }
29
- if (tB === 0) { tB = 1; curveB = curveB.prev; }
30
-
31
- const { ps: psA } = curveA;
32
- const { ps: psB } = curveB;
33
-
34
- const lA = [pA,translate(pA)(toUnitVector(tangent(psA, tA)))];
35
- const lB = [pB,translate(pB)(toUnitVector(tangent(psB, tB)))];
36
-
37
- const mid = lineLineIntersection(lA, lB);
38
-
39
- const c = fromTo(pA,pB);
40
-
41
- let twisted: boolean;
42
- if (!mid) {
43
- twisted = true;
44
- } else {
45
- const a = fromTo(pA, mid);
46
- const b = fromTo(pB, mid);
47
-
48
- twisted = dot(a,c) < 0 || dot(b,c) > 0;
49
- }
50
-
51
- if (!twisted) {
52
- // drawFs.bezier(g, [pA, mid!, pB], 'thin10 pink nofill', 0)
53
- return [pA, mid!, pB];
54
- }
55
-
56
- const w1 = fromTo(lA[0], lA[1]); // This is a unit vector
57
- const w2 = fromTo(lB[0], lB[1]); // This is a unit vector
58
-
59
- const d1 = Math.abs(cross(c, w1)) / (3*3);
60
- const d2 = Math.abs(cross(c, w2)) / (3*3);
61
-
62
- if (d1 > TOLERANCE_ADD_2PRONG || d2 > TOLERANCE_ADD_2PRONG) {
63
- // not within tolerance
64
- return undefined;
65
- }
66
-
67
- if (d1 > TOLERANCE_USE_LINE || d2 > TOLERANCE_USE_LINE) {
68
- // approximate with cubic bezier?
69
- return undefined; // add 2-prong
70
- }
16
+ cpNodeB: CpNode): number[][][] {
71
17
 
72
- // Within tolerance - approximate with a straight line.
73
- return [pA, pB];
18
+ return getBeziersFromTangents(
19
+ getBoundaryTangentLine(cpNodeA.pointOnShape, true),
20
+ getBoundaryTangentLine(cpNodeB.pointOnShape, false)
21
+ );
74
22
  }
75
23
 
76
24
 
@@ -1,81 +1,24 @@
1
1
  import type { CpNode } from '../cp-node.js';
2
- import {
3
- fromTo as fromToVec, dot, cross, rotate90Degrees, interpolate, translate,
4
- lineLineIntersection
5
- } from 'flo-vector2d';
6
2
  import { getEdgeDirection } from './get-edge-direction.js';
7
-
8
- const { abs } = Math;
9
-
10
-
11
- /** @internal */
12
- const TOLERANCE_ADD_2PRONG = 0.01;
13
- /** @internal */
14
- const TOLERANCE_USE_LINE = 0.0001; // else cubic
3
+ import { getBeziersFromTangents } from '../../utils/get-beziers-from-tangents.js';
15
4
 
16
5
 
17
6
  /**
18
- * Returns the bezier curve from the maximal disk of one `CpNode` to another
19
- * `CpNode`'s maximal disk.
7
+ * Returns the bezier curves (an array of 1 or 2 lines or quadratics joined
8
+ * smoothly) from the maximal disk of one `CpNode` to another `CpNode`'s
9
+ * maximal disk.
10
+ *
20
11
  * @param cpNodeFrom
21
12
  * @param cpNodeTo
22
13
  */
23
14
  function getMatCurveBetween(
24
15
  cpNodeFrom: CpNode,
25
- cpNodeTo: CpNode): number[][] {
26
-
27
- const fromCc = cpNodeFrom.pointOnShape.circle.center;
28
- const fromL = getEdgeDirection(cpNodeFrom);
29
-
30
- const toCc = cpNodeTo.pointOnShape.circle.center;
31
- const toL = getEdgeDirection(cpNodeTo.prevOnCircle);
32
-
33
- const mid = lineLineIntersection(fromL, toL);
34
-
35
- const c = fromToVec(fromCc,toCc);
36
-
37
- let twisted: boolean;
38
- if (!mid) {
39
- twisted = true;
40
- } else {
41
- const a = fromToVec(fromCc, mid);
42
- const b = fromToVec(toCc, mid);
43
-
44
- twisted = dot(a,c) < 0 || dot(b,c) > 0;
45
- }
46
-
47
- if (!twisted) {
48
- return [fromCc, mid!, toCc];
49
- }
50
-
51
- const r = rotate90Degrees(c);
52
- const w1 = fromToVec(fromL[0], fromL[1]); // This is a unit vector
53
- const w2 = fromToVec(toL[0], toL[1]); // This is a unit vector
54
-
55
- const d1 = abs(cross(c, w1)) / (3*3);
56
- const d2 = abs(cross(c, w2)) / (3*3);
57
-
58
- if (d1 > TOLERANCE_ADD_2PRONG || d2 > TOLERANCE_ADD_2PRONG) {
59
- // FUTURE - not within tolerance - must add additional 2-prong
60
- return [fromCc, toCc];
61
- }
62
-
63
- if (d1 > TOLERANCE_USE_LINE || d2 > TOLERANCE_USE_LINE) {
64
- // approximate with cubic bezier
65
- const m1 = interpolate(fromCc,toCc,1/3);
66
- const m2 = interpolate(fromCc,toCc,2/3);
67
- const v1 = translate(r, m1);
68
- const v2 = translate(r, m2);
69
- const l1 = [m1,v1];
70
- const l2 = [m2,v2];
71
- const mid1 = lineLineIntersection(fromL, l1)!;
72
- const mid2 = lineLineIntersection(toL, l2)!;
73
-
74
- return [fromCc, mid1, mid2, toCc];
75
- }
16
+ cpNodeTo: CpNode): number[][][] {
76
17
 
77
- // Within tolerance - approximate with a straight line.
78
- return [fromCc, toCc];
18
+ return getBeziersFromTangents(
19
+ getEdgeDirection(cpNodeFrom),
20
+ getEdgeDirection(cpNodeTo.prevOnCircle)
21
+ );
79
22
  }
80
23
 
81
24
 
@@ -2,6 +2,14 @@ import { CpNode } from '../cp-node.js';
2
2
  import { getMatCurveBetween } from './get-mat-curve-between.js';
3
3
 
4
4
 
5
+ /**
6
+ * Returns the (flattened) array of bezier curves (lines or quadratics)
7
+ * representing the medial axis from one `CpNode` to another by following
8
+ * `next` repeatedly.
9
+ *
10
+ * @param cpNodeS
11
+ * @param cpNodeE
12
+ */
5
13
  function getMatCurvesBetween(
6
14
  cpNodeS: CpNode,
7
15
  cpNodeE: CpNode) {
@@ -9,8 +17,7 @@ function getMatCurvesBetween(
9
17
  let cpNode = cpNodeS;
10
18
  const pss: number[][][] = [];
11
19
  while (cpNode !== cpNodeE) {
12
- const ps = getMatCurveBetween(cpNode, cpNode.next);
13
- pss.push(ps);
20
+ pss.push(...getMatCurveBetween(cpNode, cpNode.next));
14
21
 
15
22
  cpNode = cpNode.next;
16
23
  }
@@ -1,19 +1,23 @@
1
1
  import { CpNode } from "../cp-node.js";
2
- import { getAllOnCircle } from "./get-all-on-circle.js";
3
2
  import { isTerminating } from "./is-terminating.js";
4
3
 
5
4
 
6
5
  /**
7
- * Returns the number of contact points (up to planar coordinates) on the
8
- * maximal disk circle implied by this `CpNode`.
9
- *
6
+ * Returns the number of contact points (up to planar coordinates) on the
7
+ * maximal disk circle implied by this `CpNode`, i.e. the number of
8
+ * non-terminating `CpNode`s on its circle.
9
+ *
10
10
  * See also `getProngCount`.
11
11
  */
12
12
  function getRealProngCount(cpNode: CpNode) {
13
- const nonTerminatingCpNodes = getAllOnCircle(cpNode)
14
- .filter(cpNode => !isTerminating(cpNode));
13
+ let count = 0;
14
+ let cpNode_ = cpNode;
15
+ do {
16
+ if (!isTerminating(cpNode_)) { count++; }
17
+ cpNode_ = cpNode_.nextOnCircle;
18
+ } while (cpNode_ !== cpNode);
15
19
 
16
- return nonTerminatingCpNodes.length;
20
+ return count;
17
21
  }
18
22
 
19
23
 
@@ -6,8 +6,18 @@ import { sum } from '../../utils/sum.js';
6
6
 
7
7
 
8
8
  /**
9
+ * Returns the salience of the given `CpNode`: the ratio of the boundary length
10
+ * from its contact point forward to the next contact point on its circle to
11
+ * the straight distance between those two points.
12
+ *
13
+ * * `Infinity` if that stretch of boundary passes a hole closer
14
+ * * `0` if the two contact points coincide with no boundary in between (the
15
+ * terminating `CpNode` of a 1-prong) - the other `CpNode` of a 1-prong,
16
+ * whose stretch is the entire boundary, gives `Infinity`
17
+ *
9
18
  * See https://research.gold.ac.uk/id/eprint/31944/
10
- * @param cpNode
19
+ *
20
+ * @param cpNode
11
21
  */
12
22
  function getSalience(cpNode: CpNode) {
13
23
  const cpNode1 = cpNode;
@@ -21,7 +31,10 @@ function getSalience(cpNode: CpNode) {
21
31
 
22
32
  const s = sum(pss.map(ps => totalLength(ps)));
23
33
 
24
- return hasHoleCloser ? Infinity : s/d;
34
+ if (hasHoleCloser) { return Infinity; }
35
+ if (s === 0) { return 0; } // (avoids `0/0` for the 1-prong case)
36
+
37
+ return s/d;
25
38
  }
26
39
 
27
40