flo-mat 4.0.2 → 4.1.0

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 (294) hide show
  1. package/__tests__/find-2-prong/get-medial/dd-get-medial-point-coeffs-same-curve.spec.ts +106 -0
  2. package/__tests__/find-2-prong/get-medial/dd-get-medial-point-coeffs.spec.ts +73 -0
  3. package/__tests__/find-2-prong/get-medial/get-closest-points.spec.ts +5 -2
  4. package/__tests__/helpers/close-to.ts +5 -5
  5. package/__tests__/specific-cases/load-svg/load-svg.ts +30 -0
  6. package/__tests__/specific-cases/specific-cases.spec.ts +170 -0
  7. package/__tests__/specific-cases/test-svgs/achispado.svg +5052 -0
  8. package/browser/index.js +5129 -8785
  9. package/browser/index.min.js +1 -1
  10. package/{jest.config.cjs → jest.config.ts} +8 -3
  11. package/node/closest-boundary-point/get-close-boundary-points-certified.js +3 -2
  12. package/node/closest-boundary-point/get-close-boundary-points-certified.js.map +1 -1
  13. package/node/corner/get-corner.js +1 -1
  14. package/node/corner/get-corner.js.map +1 -1
  15. package/node/cp-node/fs/get-all-on-loop-by-loop.d.ts +11 -0
  16. package/node/cp-node/fs/get-all-on-loop-by-loop.js +42 -0
  17. package/node/cp-node/fs/get-all-on-loop-by-loop.js.map +1 -0
  18. package/node/cp-node/fs/get-boundary-beziers-to-next.d.ts +1 -0
  19. package/node/cp-node/fs/get-boundary-beziers-to-next.js +1 -59
  20. package/node/cp-node/fs/get-boundary-beziers-to-next.js.map +1 -1
  21. package/node/cp-node/fs/get-edge-direction.d.ts +3 -1
  22. package/node/cp-node/fs/get-edge-direction.js +5 -3
  23. package/node/cp-node/fs/get-edge-direction.js.map +1 -1
  24. package/node/cp-node/fs/get-mat-curve-between.js +6 -6
  25. package/node/cp-node/fs/get-mat-curve-between.js.map +1 -1
  26. package/node/cp-node/fs/is-fully-terminating.js +12 -0
  27. package/node/cp-node/fs/is-fully-terminating.js.map +1 -1
  28. package/node/cp-node/fs/is-on-same-loop.d.ts +3 -0
  29. package/node/cp-node/fs/is-on-same-loop.js +6 -0
  30. package/node/cp-node/fs/is-on-same-loop.js.map +1 -0
  31. package/node/debug/debug.d.ts +8 -22
  32. package/node/debug/debug.js +12 -50
  33. package/node/debug/debug.js.map +1 -1
  34. package/node/find-2-prong/add-1-prong.js +1 -4
  35. package/node/find-2-prong/add-1-prong.js.map +1 -1
  36. package/node/find-2-prong/find-2-prong.js +24 -10
  37. package/node/find-2-prong/find-2-prong.js.map +1 -1
  38. package/node/find-2-prong/get-medial/get-antipodal-points.d.ts +1 -1
  39. package/node/find-2-prong/get-medial/get-antipodal-points.js +2 -2
  40. package/node/find-2-prong/get-medial/get-antipodal-points.js.map +1 -1
  41. package/node/find-2-prong/get-medial/get-closest-points.d.ts +7 -1
  42. package/node/find-2-prong/get-medial/get-closest-points.js +60 -14
  43. package/node/find-2-prong/get-medial/get-closest-points.js.map +1 -1
  44. package/node/find-2-prong/reduce-radius.d.ts +3 -1
  45. package/node/find-2-prong/reduce-radius.js +8 -6
  46. package/node/find-2-prong/reduce-radius.js.map +1 -1
  47. package/node/find-3-prong/calc-better-x.js +1 -3
  48. package/node/find-3-prong/calc-better-x.js.map +1 -1
  49. package/node/find-3-prong/calc-initial-3-prong-center.js +1 -2
  50. package/node/find-3-prong/calc-initial-3-prong-center.js.map +1 -1
  51. package/node/find-3-prong/find-3-prong-for-delta3s.js +1 -4
  52. package/node/find-3-prong/find-3-prong-for-delta3s.js.map +1 -1
  53. package/node/find-3-prong/find-3-prong.js.map +1 -1
  54. package/node/find-3-prong/find-and-add-3-prong.js +0 -14
  55. package/node/find-3-prong/find-and-add-3-prong.js.map +1 -1
  56. package/node/find-mat/find-mat.js +2 -2
  57. package/node/find-mat/find-mat.js.map +1 -1
  58. package/node/find-mat/find-mats.js.map +1 -1
  59. package/node/find-mat/get-dull-corners-on-loop.js +3 -2
  60. package/node/find-mat/get-dull-corners-on-loop.js.map +1 -1
  61. package/node/find-mat/get-for-1-prongs-on-loop.js +6 -3
  62. package/node/find-mat/get-for-1-prongs-on-loop.js.map +1 -1
  63. package/node/find-mat/get-for-2-prongs-on-loop.js +5 -1
  64. package/node/find-mat/get-for-2-prongs-on-loop.js.map +1 -1
  65. package/node/find-mat/get-meta.d.ts +4 -6
  66. package/node/find-mat/get-meta.js +12 -26
  67. package/node/find-mat/get-meta.js.map +1 -1
  68. package/node/find-mat/get-sharp-corners.js +4 -2
  69. package/node/find-mat/get-sharp-corners.js.map +1 -1
  70. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez0.d.ts +21 -0
  71. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez0.js +46 -0
  72. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez0.js.map +1 -0
  73. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez1.d.ts +28 -0
  74. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez1.js +97 -0
  75. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez1.js.map +1 -0
  76. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez2-same-curve.d.ts +28 -0
  77. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez2-same-curve.js +109 -0
  78. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez2-same-curve.js.map +1 -0
  79. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez2.d.ts +29 -0
  80. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez2.js +123 -0
  81. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez2.js.map +1 -0
  82. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3-same-curve.d.ts +30 -0
  83. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3-same-curve.js +177 -0
  84. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3-same-curve.js.map +1 -0
  85. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.d.ts +29 -0
  86. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.js +156 -0
  87. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.js.map +1 -0
  88. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs.d.ts +28 -0
  89. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs.js +40 -0
  90. package/node/get-medial-points/double-double/dd-get-medial-point-coeffs.js.map +1 -0
  91. package/node/index.d.ts +6 -10
  92. package/node/index.js +5 -6
  93. package/node/index.js.map +1 -1
  94. package/node/point-on-shape/point-on-shape.d.ts +2 -0
  95. package/node/point-on-shape/to-p.d.ts +1 -1
  96. package/node/point-on-shape/to-p.js +1 -1
  97. package/node/point-on-shape/to-p.js.map +1 -1
  98. package/node/reconstruct-from-mat/get-cp-nodess-for-sat.d.ts +4 -0
  99. package/node/reconstruct-from-mat/get-cp-nodess-for-sat.js +15 -0
  100. package/node/reconstruct-from-mat/get-cp-nodess-for-sat.js.map +1 -0
  101. package/node/reconstruct-from-mat/reconstruct-from-mat.d.ts +10 -0
  102. package/node/reconstruct-from-mat/reconstruct-from-mat.js +160 -0
  103. package/node/reconstruct-from-mat/reconstruct-from-mat.js.map +1 -0
  104. package/node/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.d.ts +12 -0
  105. package/node/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.js +46 -0
  106. package/node/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.js.map +1 -0
  107. package/node/sat/add-debug-info.js +1 -2
  108. package/node/sat/add-debug-info.js.map +1 -1
  109. package/node/svg/get-loop-bounds.js +6 -2
  110. package/node/svg/get-loop-bounds.js.map +1 -1
  111. package/node/utils/map-deep.d.ts +15 -0
  112. package/node/utils/map-deep.js +34 -0
  113. package/node/utils/map-deep.js.map +1 -0
  114. package/package.json +14 -8
  115. package/src/closest-boundary-point/get-close-boundary-points-certified.ts +3 -2
  116. package/src/corner/get-corner.ts +1 -1
  117. package/src/cp-node/fs/get-all-on-loop-by-loop.ts +56 -0
  118. package/src/cp-node/fs/get-all-on-loop.ts +1 -1
  119. package/src/cp-node/fs/get-boundary-beziers-to-next.ts +1 -72
  120. package/src/cp-node/fs/get-edge-direction.ts +8 -4
  121. package/src/cp-node/fs/get-mat-curve-between.ts +6 -6
  122. package/src/cp-node/fs/is-fully-terminating.ts +16 -0
  123. package/src/cp-node/fs/is-on-same-loop.ts +15 -0
  124. package/src/debug/debug.ts +27 -87
  125. package/src/find-2-prong/add-1-prong.ts +1 -5
  126. package/src/find-2-prong/find-2-prong.ts +37 -14
  127. package/src/find-2-prong/get-medial/get-antipodal-points.ts +3 -2
  128. package/src/find-2-prong/get-medial/get-closest-points-d.ts +213 -0
  129. package/src/find-2-prong/get-medial/get-closest-points.ts +74 -13
  130. package/src/find-2-prong/reduce-radius.ts +8 -5
  131. package/src/find-3-prong/calc-better-x.ts +1 -3
  132. package/src/find-3-prong/calc-initial-3-prong-center.ts +1 -2
  133. package/src/find-3-prong/find-3-prong-for-delta3s.ts +1 -4
  134. package/src/find-3-prong/find-3-prong.ts +0 -1
  135. package/src/find-3-prong/find-and-add-3-prong.ts +1 -15
  136. package/src/find-mat/find-mat.ts +3 -2
  137. package/src/find-mat/find-mats.ts +0 -1
  138. package/src/find-mat/get-dull-corners-on-loop.ts +4 -3
  139. package/src/find-mat/get-for-1-prongs-on-loop.ts +8 -3
  140. package/src/find-mat/get-for-2-prongs-on-loop.ts +6 -1
  141. package/src/find-mat/get-meta.ts +14 -38
  142. package/src/find-mat/get-sharp-corners.ts +5 -1
  143. package/src/get-medial-curve/__pycache__/get-cubic-self-medial-curve.cpython-313.pyc +0 -0
  144. package/src/get-medial-curve/get-cubic-self-medial-curve.py +419 -0
  145. package/src/get-medial-points/double-double/dd-get-medial-point-coeffs-bez0-with-running-err.ts +76 -0
  146. package/src/get-medial-points/double-double/dd-get-medial-point-coeffs-bez0.ts +61 -0
  147. package/src/get-medial-points/double-double/dd-get-medial-point-coeffs-bez1.ts +116 -0
  148. package/src/get-medial-points/double-double/dd-get-medial-point-coeffs-bez2-same-curve.ts +129 -0
  149. package/src/get-medial-points/double-double/dd-get-medial-point-coeffs-bez2.ts +142 -0
  150. package/src/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3-same-curve.ts +199 -0
  151. package/src/get-medial-points/double-double/dd-get-medial-point-coeffs-bez3.ts +177 -0
  152. package/src/get-medial-points/double-double/dd-get-medial-point-coeffs.ts +48 -0
  153. package/src/get-medial-points/double-double/error-bound-calc.txt +72 -0
  154. package/src/index.ts +7 -11
  155. package/src/point-on-shape/point-on-shape.ts +3 -0
  156. package/src/point-on-shape/to-p.ts +2 -2
  157. package/src/reconstruct-from-mat/get-cp-nodess-for-sat.ts +24 -0
  158. package/src/reconstruct-from-mat/reconstruct-from-mat.ts +226 -0
  159. package/src/reconstruct-from-mat/remove-sat-induced-trivial-3prongs.ts +62 -0
  160. package/src/sat/add-debug-info.ts +1 -2
  161. package/src/svg/get-loop-bounds.ts +11 -3
  162. package/src/utils/clip.ts +13 -0
  163. package/src/utils/map-deep.ts +75 -0
  164. package/src/utils/map-map.ts +33 -0
  165. package/wallaby.mjs +4 -4
  166. package/node/debug/debug-elem-types.d.ts +0 -26
  167. package/node/debug/debug-elem-types.js +0 -22
  168. package/node/debug/debug-elem-types.js.map +0 -1
  169. package/node/debug/functions/draw/draw-beziers-as-single-path.d.ts +0 -2
  170. package/node/debug/functions/draw/draw-beziers-as-single-path.js +0 -30
  171. package/node/debug/functions/draw/draw-beziers-as-single-path.js.map +0 -1
  172. package/node/debug/functions/draw/xmlns.d.ts +0 -2
  173. package/node/debug/functions/draw/xmlns.js +0 -3
  174. package/node/debug/functions/draw/xmlns.js.map +0 -1
  175. package/node/debug/functions/draw-elem/bounding-hull.d.ts +0 -3
  176. package/node/debug/functions/draw-elem/bounding-hull.js +0 -8
  177. package/node/debug/functions/draw-elem/bounding-hull.js.map +0 -1
  178. package/node/debug/functions/draw-elem/draw-branch.d.ts +0 -4
  179. package/node/debug/functions/draw-elem/draw-branch.js +0 -26
  180. package/node/debug/functions/draw-elem/draw-branch.js.map +0 -1
  181. package/node/debug/functions/draw-elem/draw-circle-percent.d.ts +0 -3
  182. package/node/debug/functions/draw-elem/draw-circle-percent.js +0 -13
  183. package/node/debug/functions/draw-elem/draw-circle-percent.js.map +0 -1
  184. package/node/debug/functions/draw-elem/draw-cp-node.d.ts +0 -4
  185. package/node/debug/functions/draw-elem/draw-cp-node.js +0 -26
  186. package/node/debug/functions/draw-elem/draw-cp-node.js.map +0 -1
  187. package/node/debug/functions/draw-elem/draw-cull.d.ts +0 -3
  188. package/node/debug/functions/draw-elem/draw-cull.js +0 -9
  189. package/node/debug/functions/draw-elem/draw-cull.js.map +0 -1
  190. package/node/debug/functions/draw-elem/draw-dull-corner.d.ts +0 -4
  191. package/node/debug/functions/draw-elem/draw-dull-corner.js +0 -10
  192. package/node/debug/functions/draw-elem/draw-dull-corner.js.map +0 -1
  193. package/node/debug/functions/draw-elem/draw-elem.d.ts +0 -10
  194. package/node/debug/functions/draw-elem/draw-elem.js +0 -39
  195. package/node/debug/functions/draw-elem/draw-elem.js.map +0 -1
  196. package/node/debug/functions/draw-elem/draw-leaves.d.ts +0 -4
  197. package/node/debug/functions/draw-elem/draw-leaves.js +0 -34
  198. package/node/debug/functions/draw-elem/draw-leaves.js.map +0 -1
  199. package/node/debug/functions/draw-elem/draw-loop.d.ts +0 -4
  200. package/node/debug/functions/draw-elem/draw-loop.js +0 -11
  201. package/node/debug/functions/draw-elem/draw-loop.js.map +0 -1
  202. package/node/debug/functions/draw-elem/draw-loops.d.ts +0 -4
  203. package/node/debug/functions/draw-elem/draw-loops.js +0 -6
  204. package/node/debug/functions/draw-elem/draw-loops.js.map +0 -1
  205. package/node/debug/functions/draw-elem/draw-loose-bounding-box.d.ts +0 -3
  206. package/node/debug/functions/draw-elem/draw-loose-bounding-box.js +0 -10
  207. package/node/debug/functions/draw-elem/draw-loose-bounding-box.js.map +0 -1
  208. package/node/debug/functions/draw-elem/draw-mat.d.ts +0 -4
  209. package/node/debug/functions/draw-elem/draw-mat.js +0 -34
  210. package/node/debug/functions/draw-elem/draw-mat.js.map +0 -1
  211. package/node/debug/functions/draw-elem/draw-max-vertex.d.ts +0 -4
  212. package/node/debug/functions/draw-elem/draw-max-vertex.js +0 -9
  213. package/node/debug/functions/draw-elem/draw-max-vertex.js.map +0 -1
  214. package/node/debug/functions/draw-elem/draw-min-y.d.ts +0 -4
  215. package/node/debug/functions/draw-elem/draw-min-y.js +0 -10
  216. package/node/debug/functions/draw-elem/draw-min-y.js.map +0 -1
  217. package/node/debug/functions/draw-elem/draw-one-prong-at-dull-corner.d.ts +0 -4
  218. package/node/debug/functions/draw-elem/draw-one-prong-at-dull-corner.js +0 -22
  219. package/node/debug/functions/draw-elem/draw-one-prong-at-dull-corner.js.map +0 -1
  220. package/node/debug/functions/draw-elem/draw-one-prong.d.ts +0 -4
  221. package/node/debug/functions/draw-elem/draw-one-prong.js +0 -13
  222. package/node/debug/functions/draw-elem/draw-one-prong.js.map +0 -1
  223. package/node/debug/functions/draw-elem/draw-sharp-corner.d.ts +0 -4
  224. package/node/debug/functions/draw-elem/draw-sharp-corner.js +0 -10
  225. package/node/debug/functions/draw-elem/draw-sharp-corner.js.map +0 -1
  226. package/node/debug/functions/draw-elem/draw-three-prong.d.ts +0 -4
  227. package/node/debug/functions/draw-elem/draw-three-prong.js +0 -26
  228. package/node/debug/functions/draw-elem/draw-three-prong.js.map +0 -1
  229. package/node/debug/functions/draw-elem/draw-tight-bounding-box.d.ts +0 -3
  230. package/node/debug/functions/draw-elem/draw-tight-bounding-box.js +0 -8
  231. package/node/debug/functions/draw-elem/draw-tight-bounding-box.js.map +0 -1
  232. package/node/debug/functions/draw-elem/draw-two-prong.d.ts +0 -4
  233. package/node/debug/functions/draw-elem/draw-two-prong.js +0 -49
  234. package/node/debug/functions/draw-elem/draw-two-prong.js.map +0 -1
  235. package/node/debug/functions/draw-elem/draw-vertex.d.ts +0 -4
  236. package/node/debug/functions/draw-elem/draw-vertex.js +0 -13
  237. package/node/debug/functions/draw-elem/draw-vertex.js.map +0 -1
  238. package/node/debug/functions/general.d.ts +0 -48
  239. package/node/debug/functions/general.js +0 -53
  240. package/node/debug/functions/general.js.map +0 -1
  241. package/node/find-3-prong/timed-cc.d.ts +0 -3
  242. package/node/find-3-prong/timed-cc.js +0 -5
  243. package/node/find-3-prong/timed-cc.js.map +0 -1
  244. package/node/point-on-shape/pos-to-human-string.d.ts +0 -8
  245. package/node/point-on-shape/pos-to-human-string.js +0 -12
  246. package/node/point-on-shape/pos-to-human-string.js.map +0 -1
  247. package/node/utils/time-function-call.d.ts +0 -14
  248. package/node/utils/time-function-call.js +0 -32
  249. package/node/utils/time-function-call.js.map +0 -1
  250. package/src/debug/debug-elem-types.ts +0 -43
  251. package/src/debug/elem-type-two-prong.ts +0 -8
  252. package/src/debug/functions/cmp-cp-on-delta.ts +0 -54
  253. package/src/debug/functions/draw-elem/bounding-hull.ts +0 -18
  254. package/src/debug/functions/draw-elem/culls.ts +0 -39
  255. package/src/debug/functions/draw-elem/draw-branch.ts +0 -37
  256. package/src/debug/functions/draw-elem/draw-circle-percent.ts +0 -23
  257. package/src/debug/functions/draw-elem/draw-cp-node.ts +0 -46
  258. package/src/debug/functions/draw-elem/draw-cull.ts +0 -21
  259. package/src/debug/functions/draw-elem/draw-dull-corner.ts +0 -21
  260. package/src/debug/functions/draw-elem/draw-elem.ts +0 -64
  261. package/src/debug/functions/draw-elem/draw-leaves.ts +0 -51
  262. package/src/debug/functions/draw-elem/draw-loop.ts +0 -16
  263. package/src/debug/functions/draw-elem/draw-loops.ts +0 -10
  264. package/src/debug/functions/draw-elem/draw-loose-bounding-box.ts +0 -21
  265. package/src/debug/functions/draw-elem/draw-mat.ts +0 -43
  266. package/src/debug/functions/draw-elem/draw-max-vertex.ts +0 -15
  267. package/src/debug/functions/draw-elem/draw-min-y.ts +0 -18
  268. package/src/debug/functions/draw-elem/draw-one-prong-at-dull-corner.ts +0 -40
  269. package/src/debug/functions/draw-elem/draw-one-prong.ts +0 -25
  270. package/src/debug/functions/draw-elem/draw-sharp-corner.ts +0 -21
  271. package/src/debug/functions/draw-elem/draw-three-prong.ts +0 -44
  272. package/src/debug/functions/draw-elem/draw-tight-bounding-box.ts +0 -18
  273. package/src/debug/functions/draw-elem/draw-two-prong.ts +0 -68
  274. package/src/debug/functions/draw-elem/draw-vertex.ts +0 -27
  275. package/src/debug/functions/draw-elem/dull-corner.ts +0 -21
  276. package/src/debug/functions/draw-elem/leaves.ts +0 -20
  277. package/src/debug/functions/draw-elem/loop.ts +0 -16
  278. package/src/debug/functions/draw-elem/loops.ts +0 -10
  279. package/src/debug/functions/draw-elem/loose-bounding-box.ts +0 -21
  280. package/src/debug/functions/draw-elem/mat.ts +0 -47
  281. package/src/debug/functions/draw-elem/max-vertex.ts +0 -15
  282. package/src/debug/functions/draw-elem/min-y.ts +0 -18
  283. package/src/debug/functions/draw-elem/one-prong-at-dull-corner.ts +0 -26
  284. package/src/debug/functions/draw-elem/one-prong.ts +0 -23
  285. package/src/debug/functions/draw-elem/sharp-corner.ts +0 -20
  286. package/src/debug/functions/draw-elem/three-prong.ts +0 -30
  287. package/src/debug/functions/draw-elem/tight-bounding-box.ts +0 -18
  288. package/src/debug/functions/draw-elem/two-prong.ts +0 -50
  289. package/src/debug/functions/draw-elem/vertex.ts +0 -51
  290. package/src/debug/functions/general.ts +0 -79
  291. package/src/debug/functions/three-prong.ts +0 -249
  292. package/src/debug/functions/two-prong.ts +0 -203
  293. package/src/find-2-prong/add-debug-info.ts +0 -45
  294. package/src/find-3-prong/timed-cc.ts +0 -9
@@ -0,0 +1,129 @@
1
+ import { toPowerBasisDd } from 'flo-bezier3';
2
+ import { ddMultDouble2, ddAddDd, ddMultDd, ddNegativeOf, ddMultBy2 } from 'double-double';
3
+
4
+ const qmd = ddMultDouble2;
5
+ const qaq = ddAddDd;
6
+ const qmq = ddMultDd;
7
+ const qno = ddNegativeOf;
8
+ const qm2 = ddMultBy2;
9
+
10
+
11
+ /**
12
+ * Returns polynomial coefficients for the same-curve quadratic medial-point
13
+ * case, where `p = b(t)` on the same quadratic bezier `ps` and `v` is normal
14
+ * to the curve at that parameter `t`.
15
+ *
16
+ * The returned coefficients encode:
17
+ * * `A`, `B`: `E2(s, τ) = (s - t)^2⋅(A(s)⋅τ + B(s))`
18
+ // * * `C`, `D`: `E1(s, τ) = C(s)⋅τ + D(s)`
19
+ * * `H`: the reduced eliminant in `s`
20
+ *
21
+ * Here `τ` is the ray parameter in `q(τ) = p + τ⋅v`.
22
+ * For a candidate root `s` of `H`, recover `τ` from
23
+ * `A(s)⋅τ + B(s) = 0`, i.e. `τ = -B(s)/A(s)` when `A(s) ≠ 0`.
24
+ *
25
+ * In this same-curve setup, the full eliminant has the form
26
+ * `H_full(s) = (s - t)^4*(l1*s + l0)`. This function returns only the reduced
27
+ * factor `H(s) = l1*s + l0` (the repeated `(s - t)^4` factor is omitted).
28
+ *
29
+ * @param t parameter on `ps` where `p = b(t)`
30
+ * @param v ray direction from `p`; assumed normal to `ps` at `t`
31
+ * @param ps order 2 bezier control points, e.g. `[[0,0],[1,1],[2,1]]`
32
+ */
33
+ function ddGetMedialPointCoeffsBez2_SameCurve(
34
+ t: number,
35
+ v: number[][],
36
+ ps: number[][]) {
37
+
38
+ // -----------------------------------------------------
39
+ // See get-medial-points.md for implementation details.
40
+ // -----------------------------------------------------
41
+ // Quadratic bezier in power basis: b(s) = a⋅s² + b⋅s + c
42
+ const [[ax,bx], [ay,by]] = toPowerBasisDd(ps);
43
+
44
+ const [vx,vy] = v;
45
+
46
+ // Same-curve assumption with explicit parameter `t`:
47
+ // p = b(t) => u0 = p - c = t*(a*t + b).
48
+ // const g0x = ax*t + bx;
49
+ // const g0y = ay*t + by;
50
+ const g0x = qaq(qmd(t,ax),bx);
51
+ const g0y = qaq(qmd(t,ay),by);
52
+
53
+ // Reuse core quadratic-form terms to reduce repeated multiplications.
54
+ // const br2 = ax*ax + ay*ay;
55
+ // const ab = ax*bx + ay*by;
56
+ // const bb = bx*bx + by*by;
57
+ // const ag = ax*g0x + ay*g0y;
58
+ const br2 = qaq(qmq(ax,ax),qmq(ay,ay));
59
+ const ab = qaq(qmq(ax,bx),qmq(ay,by));
60
+ const ag = qaq(qmq(ax,g0x),qmq(ay,g0y));
61
+
62
+ // -----------------------------------------------------
63
+ // E1(s,t): (u(s) + t⋅v) ⋅ b'(s) = 0
64
+ // => C(s)⋅t + D(s) = 0
65
+ // const c1 = 2*(vx*ax + vy*ay);
66
+ const c1 = qm2(qaq(qmq(vx,ax),qmq(vy,ay)));
67
+ // v is normal at parameter t, so C(t) = v⋅w(t) = 0.
68
+ // Since C(s) = c1*s + c0, enforce c0 = -c1*t exactly.
69
+ // const c0 = -c1*t;
70
+
71
+ // const d3 = -2*br2;
72
+ // const d2 = -3*ab;
73
+ // const d1 = 2*t*ag - bb;
74
+ // p = b(t) => D(t) = u(t)⋅w(t) = 0.
75
+ // const d0 = -t*(t*(d3*t + d2) + d1);
76
+ // -----------------------------------------------------
77
+
78
+ // -----------------------------------------------------
79
+ // E2(s,t): |t⋅v|² - |u(s) + t⋅v|² = 0
80
+ // => 2⋅(v⋅u(s))⋅t + |u(s)|² = 0
81
+ // => (s - t)^2⋅(A(s)⋅t + B(s)) = 0
82
+ // Return only the reduced constant A(s) = ar0.
83
+ // const ar0 = -c1;
84
+ const ar0 = qno(c1);
85
+
86
+ // Full B(s) factorizes as: B_full(s) = (s - t)^2*B_reduced(s).
87
+ // Return only B_reduced(s) = br2*s^2 + br1*s + br0.
88
+ // const br1 = 2*ag;
89
+ // const br0 = g0x*g0x + g0y*g0y;
90
+ const br1 = qm2(ag);
91
+ const br0 = qaq(qmq(g0x,g0x),qmq(g0y,g0y));
92
+ // -----------------------------------------------------
93
+
94
+
95
+ // Eliminate t from:
96
+ // A(s)⋅t + B(s) = 0
97
+ // C(s)⋅t + D(s) = 0
98
+ // by taking A(s)⋅D(s) - B(s)⋅C(s) = 0 (degree ≤ 5 in s)
99
+
100
+ // For this same-curve quadratic case:
101
+ // d3 = -2*b4, d2 = -(3/2)*b3, a2 = -c1, a1 = -2*c0.
102
+ // Therefore H5 and H4 reduce to:
103
+ // H5 = b4*c1
104
+ // H4 = 3*b4*c0 + (1/2)*b3*c1
105
+ // const H5 = br2*c1;
106
+ const H5 = qmq(br2,c1);
107
+
108
+ // In the same-curve quadratic case the full eliminant has the form
109
+ // H_full(s) = (s - t)^4*(l1*s + l0).
110
+ // Match the leading coefficients of H_full(s):
111
+ // H5 = l1
112
+ // H4 = l0 - 4*t*l1
113
+ // const l1 = H5;
114
+ // const l0 = H4 + 4*t*l1;
115
+ // Using c0 = -c1*t and b3 = 2*ab, this simplifies to l0 = c1*(br2*t + ab).
116
+ // const l0 = c1*(br2*t + ab);
117
+ const l0 = qmq(c1,qaq(qmd(t,br2),ab));
118
+
119
+ return {
120
+ A: [ar0],
121
+ B: [br2, br1, br0],
122
+ // C: [c1, c0],
123
+ // D: [d3, d2, d1, d0],
124
+ H: [H5, l0]
125
+ };
126
+ }
127
+
128
+
129
+ export { ddGetMedialPointCoeffsBez2_SameCurve }
@@ -0,0 +1,142 @@
1
+ import { toPowerBasisDd } from 'flo-bezier3';
2
+ import { ddMultDouble2, ddAddDd, ddMultDd, ddNegativeOf, ddMultByNeg2, ddMultBy2, ddDiffDouble } from 'double-double';
3
+
4
+ const qmd = ddMultDouble2;
5
+ const qaq = ddAddDd;
6
+ const qmq = ddMultDd;
7
+ const qno = ddNegativeOf;
8
+ const qmn2 = ddMultByNeg2;
9
+ const qm2 = ddMultBy2;
10
+ const qdd = ddDiffDouble;
11
+
12
+
13
+ /**
14
+ * Returns the polynomial coefficients for the ray parameter `t` and the
15
+ * curve parameter `s` that encode the medial condition for `q(t) = p + t⋅v`
16
+ * and a quadratic bezier curve `ps`.
17
+ *
18
+ * The returned coefficients describe the equations whose common solutions
19
+ * satisfy:
20
+ * * `q(t)` is equidistant from `p` and the nearest point on `ps`
21
+ * * that common distance is locally minimal among such candidates
22
+ *
23
+ * More specifically, this function returns:
24
+ * * `A` and `B`: the coefficients of `E2(s,t) = A(s)⋅t + B(s)`
25
+ * * `C` and `D`: the coefficients of `E1(s,t) = C(s)⋅t + D(s)`
26
+ * * `H`: the eliminated polynomial `A(s)⋅D(s) - B(s)⋅C(s)` whose roots are
27
+ * candidate `s` values for medial points
28
+ *
29
+ * @param p base point
30
+ * @param v ray direction from `p`
31
+ * @param ps quadratic bezier control points, i.e. an order 2 bezier curve
32
+ * given as an array of control points, e.g. `[[0,0],[1,1],[2,1]]`
33
+ */
34
+ function ddGetMedialPointCoeffsBez2(
35
+ p: number[][],
36
+ v: number[][],
37
+ ps: number[][]) {
38
+
39
+ // -----------------------------------------------------
40
+ // See get-medial-points.md for implementation details.
41
+ // -----------------------------------------------------
42
+ const [px, py] = p;
43
+ const [vx, vy] = v;
44
+ const [[x0, y0]] = ps;
45
+
46
+ // Quadratic bezier in power basis: b(s) = a⋅s² + b⋅s + c
47
+ const [[ax, bx], [ay, by]] = toPowerBasisDd(ps);
48
+
49
+ // u(s) = p - b(s) = u2⋅s² + u1⋅s + u0
50
+ // const u0x = px - x0;
51
+ // const u0y = py - y0;
52
+ const u0x = qdd(px,x0);
53
+ const u0y = qdd(py,y0);
54
+
55
+ // Shared dot products.
56
+ // const c1 = 2*(vx*ax + vy*ay);
57
+ // const c0 = vx*bx + vy*by;
58
+ // const vu0 = vx*u0x + vy*u0y;
59
+ // const b4 = ax*ax + ay*ay;
60
+ // const ab = ax*bx + ay*by;
61
+ // const bb = bx*bx + by*by;
62
+ // const u0a = u0x*ax + u0y*ay;
63
+ // const d0 = u0x*bx + u0y*by;
64
+ // const b0 = u0x*u0x + u0y*u0y;
65
+ const c1 = qm2(qaq(qmq(vx,ax),qmq(vy,ay)));
66
+ const c0 = qaq(qmq(vx,bx),qmq(vy,by));
67
+ const vu0 = qaq(qmq(vx,u0x),qmq(vy,u0y));
68
+ const b4 = qaq(qmq(ax,ax),qmq(ay,ay));
69
+ const ab = qaq(qmq(bx,ax),qmq(by,ay));
70
+ const bb = qaq(qmq(bx,bx),qmq(by,by));
71
+ const u0a = qaq(qmq(u0x,ax),qmq(u0y,ay));
72
+ const d0 = qaq(qmq(bx,u0x),qmq(by,u0y));
73
+ const b0 = qaq(qmq(u0x,u0x),qmq(u0y,u0y));
74
+
75
+ // -----------------------------------------------------
76
+ // E1(s,t): (u(s) + t⋅v) ⋅ b'(s) = 0
77
+ // => C(s)⋅t + D(s) = 0
78
+ // -----------------------------------------------------
79
+
80
+ // -----------------------------------------------------
81
+ // const d3 = -2*b4;
82
+ // const d2 = -3*ab;
83
+ // const d1 = 2*u0a - bb;
84
+ const d3 = qmn2(b4);
85
+ const d2 = qmd(-3,ab);
86
+ const d1 = qaq(qm2(u0a),qno(bb));
87
+ // -----------------------------------------------------
88
+
89
+ // -----------------------------------------------------
90
+ // E2(s,t): |t⋅v|² - |u(s) + t⋅v|² = 0
91
+ // => 2⋅(v⋅u(s))⋅t + |u(s)|² = 0
92
+ // => A(s)⋅t + B(s) = 0
93
+ // const a2 = -c1;
94
+ // const a1 = -2*c0;
95
+ // const a0 = 2*vu0;
96
+ const a2 = qno(c1);
97
+ const a1 = qmn2(c0);
98
+ const a0 = qm2(vu0);
99
+ // -----------------------------------------------------
100
+
101
+ // -----------------------------------------------------
102
+ // const b3 = 2*ab;
103
+ // const b2 = -d1;
104
+ // const b1 = -2*d0;
105
+ const b3 = qm2(ab);
106
+ const b2 = qno(d1);
107
+ const b1 = qmn2(d0);
108
+ // -----------------------------------------------------
109
+
110
+
111
+ // Eliminate t from:
112
+ // A(s)⋅t + B(s) = 0
113
+ // C(s)⋅t + D(s) = 0
114
+ // by taking A(s)⋅D(s) - B(s)⋅C(s) = 0 (degree ≤ 5 in s)
115
+
116
+ // Using:
117
+ // a2 = -c1, d3 = -2*b4, d1 = -b2, b1 = -2*d0
118
+ // we can compute H = A⋅D - B⋅C directly.
119
+ // const H5 = b4*c1;
120
+ // const H4 = ab*c1 + 3*b4*c0;
121
+ // const H3 = 4*(ab*c0 - vu0*b4);
122
+ // const H2 = c1*d0 + c0*b2 - 6*vu0*ab;
123
+ // const H1 = -2*vu0*b2 - c1*b0;
124
+ // const H0 = 2*vu0*d0 - c0*b0;
125
+ const H5 = qmq(b4,c1);
126
+ const H4 = qaq(qmq(ab,c1),qmd(3,qmq(b4,c0)));
127
+ const H3 = qm2(qm2(qaq(qmq(ab,c0),qno(qmq(vu0,b4)))));
128
+ const H2 = qaq(qaq(qmq(c1,d0),qmq(c0,b2)),qno(qmd(6,qmq(vu0,ab))));
129
+ const H1 = qaq(qmn2(qmq(vu0,b2)),qno(qmq(c1,b0)));
130
+ const H0 = qaq(qm2(qmq(vu0,d0)),qno(qmq(c0,b0)));
131
+
132
+ return {
133
+ A: [a2, a1, a0],
134
+ B: [b4, b3, b2, b1, b0],
135
+ C: [c1, c0],
136
+ D: [d3, d2, d1, d0],
137
+ H: [H5, H4, H3, H2, H1, H0]
138
+ };
139
+ }
140
+
141
+
142
+ export { ddGetMedialPointCoeffsBez2 }
@@ -0,0 +1,199 @@
1
+ import { toPowerBasisDd } from 'flo-bezier3';
2
+ import { ddMultDouble2, ddAddDd, ddMultDd, ddNegativeOf, ddMultByNeg2, ddMultBy2 } from 'double-double';
3
+
4
+ const qmd = ddMultDouble2;
5
+ const qaq = ddAddDd;
6
+ const qmq = ddMultDd;
7
+ const qno = ddNegativeOf;
8
+ const qmn2 = ddMultByNeg2;
9
+ const qm2 = ddMultBy2;
10
+
11
+
12
+ /**
13
+ * Returns polynomial coefficients for the same-curve cubic medial-point case,
14
+ * where `p = b(t)` on the same cubic bezier `ps` and `v` is normal to the
15
+ * curve at that parameter `t`.
16
+ *
17
+ * The returned coefficients encode:
18
+ * * `A`, `B`: `E2(s, τ) = (s - t)^2⋅(A(s)⋅τ + B(s))`
19
+ * * `C`, `D`: `E1(s, τ) = (s - t)⋅(C(s)⋅τ + D(s))`
20
+ * * `H`: the reduced eliminant in `s`
21
+ *
22
+ * Here `τ` is the ray parameter in `q(τ) = p + τ⋅v`.
23
+ * For a candidate root `s` of `H`, recover `τ` from `A(s)⋅τ + B(s) = 0`, i.e.
24
+ * `τ = -B(s)/A(s)` when `A(s) ≠ 0`.
25
+ *
26
+ * In this same-curve setup, the full eliminant has the form
27
+ * `H_full(s) = (s - t)^4*H(s)`. This function returns only the reduced factor
28
+ * `H(s)` (the repeated `(s - t)^4` factor is omitted).
29
+ *
30
+ * @param t parameter on `ps` where `p = b(t)`
31
+ * @param v ray direction from `p`; assumed normal to `ps` at `t`
32
+ * @param ps order 3 bezier control points, e.g. `[[0,0],[1,1],[2,1],[3,0]]`
33
+ */
34
+ function ddGetMedialPointCoeffsBez3_SameCurve(
35
+ t: number,
36
+ v: number[][],
37
+ ps: number[][]) {
38
+
39
+ // -----------------------------------------------------
40
+ // See get-medial-points.md for implementation details.
41
+ // -----------------------------------------------------
42
+ const [vx, vy] = v;
43
+ // Cubic bezier in power basis: b(s) = a*s^3 + b*s^2 + c*s + d
44
+ const [[ax, bx, cx], [ay, by, cy]] = toPowerBasisDd(ps);
45
+
46
+ // Shared dot products to reduce repeated multiplications.
47
+ // const va = vx*ax + vy*ay;
48
+ // const vb = vx*bx + vy*by;
49
+ // const vc = vx*cx + vy*cy;
50
+ // const aa = ax*ax + ay*ay;
51
+ // const ab = ax*bx + ay*by;
52
+ // const ac = ax*cx + ay*cy;
53
+ // const bb = bx*bx + by*by;
54
+ // const bc = bx*cx + by*cy;
55
+ // const cc = cx*cx + cy*cy;
56
+ // const vu0 = t*(t*(t*va + vb) + vc);
57
+ // const u0a = t*(t*(t*aa + ab) + ac);
58
+ // const u0b = t*(t*(t*ab + bb) + bc);
59
+ const va = qaq(qmq(vx,ax),qmq(vy,ay));
60
+ const vb = qaq(qmq(vx,bx),qmq(vy,by));
61
+ const vc = qaq(qmq(vx,cx),qmq(vy,cy));
62
+ const aa = qaq(qmq(ax,ax),qmq(ay,ay));
63
+ const ab = qaq(qmq(ax,bx),qmq(ay,by));
64
+ const ac = qaq(qmq(ax,cx),qmq(ay,cy));
65
+ const bb = qaq(qmq(bx,bx),qmq(by,by));
66
+ const bc = qaq(qmq(bx,cx),qmq(by,cy));
67
+ const cc = qaq(qmq(cx,cx),qmq(cy,cy));
68
+ const vu0 = qmd(t,qaq(qmd(t,qaq(qmd(t,va),vb)),vc));
69
+ const u0a = qmd(t,qaq(qmd(t,qaq(qmd(t,aa),ab)),ac));
70
+ const u0b = qmd(t,qaq(qmd(t,qaq(qmd(t,ab),bb)),bc));
71
+
72
+ // -----------------------------------------------------
73
+ // E1(s,t): (u(s) + t*v) * b'(s) = 0
74
+ // => C(s)*t + D(s) = 0
75
+ // const c2 = 3*va;
76
+ // const c1 = 2*vb;
77
+ const c2 = qmd(3,va);
78
+ const c1 = qm2(vb);
79
+ // v is normal at parameter t, so C(t) = 0.
80
+ // const c0 = -t*(c2*t + c1);
81
+
82
+ // Return reduced C such that C_full(s) = (s - t)*C(s).
83
+ // const cr0 = c1 + t*c2;
84
+ const cr0 = qaq(c1,qmd(t,c2));
85
+ // -----------------------------------------------------
86
+
87
+ // -----------------------------------------------------
88
+ // const d5 = -3*aa;
89
+ // const d4 = -5*ab;
90
+ // const d3 = -4*ac - 2*bb;
91
+ // const d2 = -3*bc + 3*u0a;
92
+ // const d1 = -cc + 2*u0b;
93
+ const d5 = qmd(-3,aa);
94
+ const d4 = qmd(-5,ab);
95
+ const d3 = qaq(qmd(-4,ac),qmn2(bb));
96
+ const d2 = qaq(qmd(-3,bc),qmd(3,u0a));
97
+ const d1 = qaq(qno(cc),qm2(u0b));
98
+ // p = b(t) => D(t) = u(t)⋅w(t) = 0.
99
+
100
+ // Return reduced D such that D_full(s) = (s - t)*D(s).
101
+ const dr4 = d5;
102
+ // const dr3 = d4 + t*dr4;
103
+ // const dr2 = d3 + t*dr3;
104
+ // const dr1 = d2 + t*dr2;
105
+ // const dr0 = d1 + t*dr1;
106
+ const dr3 = qaq(d4,qmd(t,dr4));
107
+ const dr2 = qaq(d3,qmd(t,dr3));
108
+ const dr1 = qaq(d2,qmd(t,dr2));
109
+ const dr0 = qaq(d1,qmd(t,dr1));
110
+ // -----------------------------------------------------
111
+
112
+ // -----------------------------------------------------
113
+ // E2(s,t): |t*v|^2 - |u(s) + t*v|^2 = 0
114
+ // => 2*(v*u(s))*t + |u(s)|^2 = 0
115
+ // => A(s)*t + B(s) = 0
116
+ // A'(s) = -2*C(s) identically for bezier curves, hence:
117
+ // const a3 = -2*va;
118
+ // const a2 = -2*vb;
119
+ const a3 = qmn2(va);
120
+ const a2 = qmn2(vb);
121
+ // const a1 = -2*vc;
122
+ // p = b(t) => A(t) = 0.
123
+ // const a0 = 2*vu0;
124
+ // -----------------------------------------------------
125
+
126
+ // -----------------------------------------------------
127
+ const b6 = aa;
128
+ // const b5 = 2*ab;
129
+ // const b4 = 2*ac + bb;
130
+ // const b3 = 2*bc - 2*u0a;
131
+ // const b2 = cc - 2*u0b;
132
+ const b5 = qm2(ab);
133
+ const b4 = qaq(qm2(ac),bb);
134
+ const b3 = qaq(qm2(bc),qmn2(u0a));
135
+ const b2 = qaq(cc,qmn2(u0b));
136
+ // -----------------------------------------------------
137
+
138
+ // -----------------------------------------------------
139
+ // Return reduced A and B such that:
140
+ // A_full(s) = (s - t)^2*A(s)
141
+ // B_full(s) = (s - t)^2*B(s)
142
+ // where A is degree 1 and B is degree 4.
143
+ const ar1 = a3;
144
+ // const ar0 = a2 + 2*t*ar1;
145
+ const ar0 = qaq(a2,qm2(qmd(t,ar1)));
146
+
147
+ const br4 = b6;
148
+ // const br3 = b5 + 2*t*br4;
149
+ // const br2 = b4 + t*(2*br3 - t*br4);
150
+ // const br1 = b3 + t*(2*br2 - t*br3);
151
+ // const br0 = b2 + t*(2*br1 - t*br2);
152
+ const br3 = qaq(b5,qm2(qmd(t,br4)));
153
+ const br2 = qaq(b4,qmd(t,qaq(qm2(br3),qno(qmd(t,br4)))));
154
+ const br1 = qaq(b3,qmd(t,qaq(qm2(br2),qno(qmd(t,br3)))));
155
+ const br0 = qaq(b2,qmd(t,qaq(qm2(br1),qno(qmd(t,br2)))));
156
+ // -----------------------------------------------------
157
+
158
+
159
+ // Eliminate t from:
160
+ // A(s)*t + B(s) = 0
161
+ // C(s)*t + D(s) = 0
162
+ // by taking A(s)*D(s) - B(s)*C(s) = 0 (degree <= 8 in s)
163
+
164
+ // H8 = a3*d5 - b6*c2 = (-2*va)*(-3*aa) - aa*(3*va) = 3*va*aa.
165
+ // const H8 = 3*va*aa;
166
+ // const H7 = 4*(va*ab + vb*aa);
167
+ // const H6 = va*b4 + 6*vb*ab + 5*vc*aa;
168
+ // const H5 = 2*vb*b4 + 8*vc*ab - 6*vu0*aa;
169
+ // const H4 = -va*b2 + vb*b3 + 3*vc*b4 - 10*vu0*ab;
170
+ const H8 = qmd(3,qmq(va,aa));
171
+ const H7 = qm2(qm2(qaq(qmq(va,ab),qmq(vb,aa))));
172
+ const H6 = qaq(qaq(qmq(va,b4),qmd(6,qmq(vb,ab))),qmd(5,qmq(vc,aa)));
173
+ const H5 = qaq(qaq(qm2(qmq(vb,b4)),qmd(8,qmq(vc,ab))),qno(qmd(6,qmq(vu0,aa))));
174
+ const H4 = qaq(qaq(qno(qmq(va,b2)),qmq(vb,b3)),qaq(qmd(3,qmq(vc,b4)),qno(qmd(10,qmq(vu0,ab)))));
175
+
176
+ // Reduce H_full(s) by its guaranteed (s - t)^4 factor:
177
+ // H_full(s) = (s - t)^4*(q4*s^4 + q3*s^3 + q2*s^2 + q1*s + q0)
178
+ // Match the high-order coefficients of H_full(s) explicitly.
179
+ const q4 = H8;
180
+ // const q3 = H7 + 4*t*q4;
181
+ // const q2 = H6 + t*(4*q3 - 6*t*q4);
182
+ // const q1 = H5 + t*(4*q2 + t*(-6*q3 + 4*t*q4));
183
+ // const q0 = H4 + t*(4*q1 + t*(-6*q2 + t*(4*q3 - t*q4)));
184
+ const q3 = qaq(H7,qm2(qm2(qmd(t,q4))));
185
+ const q2 = qaq(H6,qmd(t,qaq(qm2(qm2(q3)),qno(qmd(6,qmd(t,q4))))));
186
+ const q1 = qaq(H5,qmd(t,qaq(qm2(qm2(q2)),qmd(t,qaq(qmd(-6,q3),qm2(qm2(qmd(t,q4))))))));
187
+ const q0 = qaq(H4,qmd(t,qaq(qm2(qm2(q1)),qmd(t,qaq(qmd(-6,q2),qmd(t,qaq(qm2(qm2(q3)),qno(qmd(t,q4)))))))));
188
+
189
+ return {
190
+ A: [ar1, ar0],
191
+ B: [br4, br3, br2, br1, br0],
192
+ C: [c2, cr0],
193
+ D: [dr4, dr3, dr2, dr1, dr0],
194
+ H: [q4, q3, q2, q1, q0]
195
+ };
196
+ }
197
+
198
+
199
+ export { ddGetMedialPointCoeffsBez3_SameCurve }
@@ -0,0 +1,177 @@
1
+ import { toPowerBasisDd } from 'flo-bezier3';
2
+ import { twoDiff, ddMultDouble2, ddAddDd, ddMultDd, ddNegativeOf, ddMultByNeg2, ddMultBy2, ddDiffDouble } from 'double-double';
3
+
4
+ const td = twoDiff;
5
+ const qmd = ddMultDouble2;
6
+ const qaq = ddAddDd;
7
+ const qmq = ddMultDd;
8
+ const qno = ddNegativeOf;
9
+ const qmn2 = ddMultByNeg2;
10
+ const qm2 = ddMultBy2;
11
+ const qdd = ddDiffDouble;
12
+
13
+
14
+ /**
15
+ * Returns the polynomial coefficients for the ray parameter `t` and the
16
+ * curve parameter `s` that encode the medial condition for `q(t) = p + t⋅v`
17
+ * and a cubic bezier curve `ps`.
18
+ *
19
+ * The returned coefficients describe the equations whose common solutions
20
+ * satisfy:
21
+ * * `q(t)` is equidistant from `p` and the nearest point on `ps`
22
+ * * that common distance is locally minimal among such candidates
23
+ *
24
+ * More specifically, this function returns:
25
+ * * `A` and `B`: the coefficients of `E2(s,t) = A(s)⋅t + B(s)`
26
+ * * `C` and `D`: the coefficients of `E1(s,t) = C(s)⋅t + D(s)`
27
+ * * `H`: the eliminated polynomial `A(s)⋅D(s) - B(s)⋅C(s)` whose roots are
28
+ * candidate `s` values for medial points
29
+ *
30
+ * @param p base point
31
+ * @param v ray direction from `p`
32
+ * @param ps cubic bezier control points, i.e. an order 3 bezier curve
33
+ * given as an array of control points, e.g. `[[0,0],[1,1],[2,1],[3,0]]`
34
+ */
35
+ function ddGetMedialPointCoeffsBez3(
36
+ p: number[][],
37
+ v: number[][],
38
+ ps: number[][]) {
39
+
40
+ // -----------------------------------------------------
41
+ // See get-medial-points.md for implementation details.
42
+ // -----------------------------------------------------
43
+
44
+ const [px, py] = p;
45
+ const [vx, vy] = v;
46
+
47
+ // Cubic bezier in power basis: b(s) = a*s^3 + b*s^2 + c*s + d
48
+ const [[ax,bx,cx,[,dx]],[ay,by,cy,[,dy]]] = toPowerBasisDd(ps);
49
+
50
+ // const u0x = px - dx;
51
+ // const u0y = py - dy;
52
+ const u0x = qdd(px,dx);
53
+ const u0y = qdd(py,dy);
54
+
55
+ // Reuse dot products across A, B, C, D, and H.
56
+ // const va = vx*ax + vy*ay;
57
+ // const vb = vx*bx + vy*by;
58
+ // const vc = vx*cx + vy*cy;
59
+ // const vu0 = vx*u0x + vy*u0y;
60
+ const va = qaq(qmq(vx,ax),qmq(vy,ay));
61
+ const vb = qaq(qmq(vx,bx),qmq(vy,by));
62
+ const vc = qaq(qmq(vx,cx),qmq(vy,cy));
63
+ const vu0 = qaq(qmq(vx,u0x),qmq(vy,u0y));
64
+
65
+ // const b6 = ax*ax + ay*ay;
66
+ // const ab = ax*bx + ay*by;
67
+ // const ac = ax*cx + ay*cy;
68
+ // const bb = bx*bx + by*by;
69
+ // const bc = bx*cx + by*cy;
70
+ // const cc = cx*cx + cy*cy;
71
+ const b6 = qaq(qmq(ax,ax),qmq(ay,ay));
72
+ const ab = qaq(qmq(ax,bx),qmq(ay,by));
73
+ const ac = qaq(qmq(ax,cx),qmq(ay,cy));
74
+ const bb = qaq(qmq(bx,bx),qmq(by,by));
75
+ const bc = qaq(qmq(bx,cx),qmq(by,cy));
76
+ const cc = qaq(qmq(cx,cx),qmq(cy,cy));
77
+
78
+ // const au0 = ax*u0x + ay*u0y;
79
+ // const bu0 = bx*u0x + by*u0y;
80
+ // const d0 = cx*u0x + cy*u0y;
81
+ // const b0 = u0x*u0x + u0y*u0y;
82
+ const au0 = qaq(qmq(ax,u0x),qmq(ay,u0y));
83
+ const bu0 = qaq(qmq(bx,u0x),qmq(by,u0y));
84
+ const d0 = qaq(qmq(cx,u0x),qmq(cy,u0y));
85
+ const b0 = qaq(qmq(u0x,u0x),qmq(u0y,u0y));
86
+
87
+ // -----------------------------------------------------
88
+ // E1(s,t): (u(s) + t*v) * b'(s) = 0
89
+ // => C(s)*t + D(s) = 0
90
+ // const c2 = 3*va;
91
+ // const c1 = 2*vb;
92
+ // const c0 = vc;
93
+ const c2 = qmd(3,va);
94
+ const c1 = qm2(vb);
95
+ const c0 = vc;
96
+ // -----------------------------------------------------
97
+
98
+ // -----------------------------------------------------
99
+ // const d5 = -3*b6;
100
+ // const d4 = -5*ab;
101
+ // const d3 = -4*ac - 2*bb;
102
+ // const d2 = 3*au0 - 3*bc;
103
+ // const d1 = 2*bu0 - cc;
104
+ const d5 = qmd(-3,b6);
105
+ const d4 = qmd(-5,ab);
106
+ const d3 = qaq(qmd(-4,ac),qmn2(bb));
107
+ const d2 = qaq(qmd(3,au0),qmd(-3,bc));
108
+ const d1 = qaq(qm2(bu0),qno(cc));
109
+ // -----------------------------------------------------
110
+
111
+ // -----------------------------------------------------
112
+ // E2(s,t): |t*v|^2 - |u(s) + t*v|^2 = 0
113
+ // => 2*(v*u(s))*t + |u(s)|^2 = 0
114
+ // => A(s)*t + B(s) = 0
115
+ // const a3 = -2*va;
116
+ // const a2 = -2*vb;
117
+ // const a1 = -2*vc;
118
+ // const a0 = 2*vu0;
119
+ const a3 = qmn2(va);
120
+ const a2 = qmn2(vb);
121
+ const a1 = qmn2(vc);
122
+ const a0 = qm2(vu0);
123
+ // -----------------------------------------------------
124
+
125
+ // -----------------------------------------------------
126
+ // const b5 = 2*ab;
127
+ // const b4 = 2*ac + bb;
128
+ // const b3 = 2*bc - 2*au0;
129
+ // const b2 = cc - 2*bu0;
130
+ // const b1 = -2*d0;
131
+ const b5 = qm2(ab);
132
+ const b4 = qaq(qm2(ac),bb);
133
+ const b3 = qaq(qm2(bc),qmn2(au0));
134
+ const b2 = qaq(cc,qmn2(bu0));
135
+ const b1 = qmn2(d0);
136
+ // -----------------------------------------------------
137
+
138
+
139
+ // Eliminate t from:
140
+ // A(s)*t + B(s) = 0
141
+ // C(s)*t + D(s) = 0
142
+ // by taking H(s) = A(s)*D(s) - B(s)*C(s) = 0 (degree <= 8 in s).
143
+ // Using:
144
+ // a2 = -c1, a1 = -2*c0,
145
+ // d5 = -3*b6, d4 = -(5/2)*b5, d3 = -2*b4, d2 = -(3/2)*b3,
146
+ // d1 = -b2, d0 = -(1/2)*b1,
147
+ // we can compute H directly with fewer operations.
148
+ // const H8 = 3*va*b6;
149
+ // const H7 = 4*(va*ab + vb*b6);
150
+ // const H6 = va*b4 + 6*vb*ab + 5*vc*b6;
151
+ // const H5 = 2*vb*b4 + 8*vc*ab - 6*vu0*b6;
152
+ // const H4 = -va*b2 + vb*b3 + 3*vc*b4 - 10*vu0*ab;
153
+ // const H3 = -2*va*b1 + 2*vc*b3 - 4*vu0*b4;
154
+ // const H2 = vc*b2 - vb*b1 - 3*vu0*b3 - 3*va*b0;
155
+ // const H1 = -2*vu0*b2 - 2*vb*b0;
156
+ // const H0 = -vu0*b1 - vc*b0;
157
+ const H8 = qmd(3,qmq(va,b6));
158
+ const H7 = qm2(qm2(qaq(qmq(va,ab),qmq(vb,b6))));
159
+ const H6 = qaq(qaq(qmq(va,b4),qmd(6,qmq(vb,ab))),qmd(5,qmq(vc,b6)));
160
+ const H5 = qaq(qaq(qm2(qmq(vb,b4)),qmd(8,qmq(vc,ab))),qno(qmd(6,qmq(vu0,b6))));
161
+ const H4 = qaq(qaq(qno(qmq(va,b2)),qmq(vb,b3)),qaq(qmd(3,qmq(vc,b4)),qno(qmd(10,qmq(vu0,ab)))));
162
+ const H3 = qaq(qaq(qmn2(qmq(va,b1)),qm2(qmq(vc,b3))),qno(qm2(qm2(qmq(vu0,b4)))));
163
+ const H2 = qaq(qaq(qaq(qmq(vc,b2),qno(qmq(vb,b1))),qno(qmd(3,qmq(vu0,b3)))),qno(qmd(3,qmq(va,b0))));
164
+ const H1 = qaq(qmn2(qmq(vu0,b2)),qmn2(qmq(vb,b0)));
165
+ const H0 = qaq(qno(qmq(vu0,b1)),qno(qmq(vc,b0)));
166
+
167
+ return {
168
+ A: [a3, a2, a1, a0],
169
+ B: [b6, b5, b4, b3, b2, b1, b0],
170
+ C: [c2, c1, c0],
171
+ D: [d5, d4, d3, d2, d1, d0],
172
+ H: [H8, H7, H6, H5, H4, H3, H2, H1, H0]
173
+ };
174
+ }
175
+
176
+
177
+ export { ddGetMedialPointCoeffsBez3 }
@@ -0,0 +1,48 @@
1
+ import { ddGetMedialPointCoeffsBez2 } from './dd-get-medial-point-coeffs-bez2.js';
2
+ import { ddGetMedialPointCoeffsBez1 } from './dd-get-medial-point-coeffs-bez1.js';
3
+ import { ddGetMedialPointCoeffsBez3 } from './dd-get-medial-point-coeffs-bez3.js';
4
+ import { ddGetMedialPointCoeffsBez0 } from './dd-get-medial-point-coeffs-bez0.js';
5
+
6
+
7
+ const getMedialPointCoeffss = [
8
+ ,,
9
+ ddGetMedialPointCoeffsBez1,
10
+ ddGetMedialPointCoeffsBez2,
11
+ ddGetMedialPointCoeffsBez3
12
+ ];
13
+
14
+
15
+ /**
16
+ * Returns polynomial coefficients for ray parameter values `t`, bezier
17
+ * parameter values `s` and medial points for points `q(t)` and b(s) (an order
18
+ * 0, 1, 2 or 3 bezier curve) that satisfy the medial condition with respect to `p` and `ps`:
19
+ *
20
+ * Let `p` be a fixed point in the plane.
21
+ * Let `v` be a direction vector defining the ray `q(t) = p + t⋅v`.
22
+ * Let `ps` be a cubic bezier curve.
23
+ *
24
+ * * `q(t)` is equidistant from `p` and the nearest point on `ps`
25
+ * * that common distance is locally minimal among such candidates
26
+ *
27
+ * In other words, this function returns candidate ray parameters for the
28
+ * sought medial point(s). Selecting physically valid solutions (if needed)
29
+ * is done by the caller or by a later stage of this routine.
30
+ *
31
+ * @param p base point
32
+ * @param v ray direction from `p`
33
+ * @param ps bezier control points, e.g. `[[0,0],[1,1],[2,1],[3,0]]`
34
+ */
35
+ function ddGetMedialPointCoeffs(
36
+ p: number[][],
37
+ v: number[][],
38
+ ps: number[][]) {
39
+
40
+ if (ps.length === 1) {
41
+ const { a0, b0 } = ddGetMedialPointCoeffsBez0(p,v,ps[0]);
42
+ return { A: [a0], B: [b0], C: [], D: [], H: [] };
43
+ }
44
+ return getMedialPointCoeffss[ps.length]!(p,v,ps);
45
+ }
46
+
47
+
48
+ export { ddGetMedialPointCoeffs }