@cornerstonejs/tools 1.34.0 → 1.35.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 (284) hide show
  1. package/dist/cjs/eventDispatchers/mouseEventHandlers/mouseDown.js +4 -4
  2. package/dist/cjs/eventDispatchers/mouseEventHandlers/mouseDown.js.map +1 -1
  3. package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js +3 -2
  4. package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js.map +1 -1
  5. package/dist/cjs/index.d.ts +2 -2
  6. package/dist/cjs/index.js +3 -2
  7. package/dist/cjs/index.js.map +1 -1
  8. package/dist/cjs/tools/AdvancedMagnifyTool.d.ts +4 -0
  9. package/dist/cjs/tools/AdvancedMagnifyTool.js +8 -3
  10. package/dist/cjs/tools/AdvancedMagnifyTool.js.map +1 -1
  11. package/dist/cjs/tools/annotation/SplineROITool.d.ts +59 -0
  12. package/dist/cjs/tools/annotation/SplineROITool.js +709 -0
  13. package/dist/cjs/tools/annotation/SplineROITool.js.map +1 -0
  14. package/dist/cjs/tools/annotation/splines/BSpline.d.ts +5 -0
  15. package/dist/cjs/tools/annotation/splines/BSpline.js +14 -0
  16. package/dist/cjs/tools/annotation/splines/BSpline.js.map +1 -0
  17. package/dist/cjs/tools/annotation/splines/CardinalSpline.d.ts +12 -0
  18. package/dist/cjs/tools/annotation/splines/CardinalSpline.js +38 -0
  19. package/dist/cjs/tools/annotation/splines/CardinalSpline.js.map +1 -0
  20. package/dist/cjs/tools/annotation/splines/CatmullRomSpline.d.ts +5 -0
  21. package/dist/cjs/tools/annotation/splines/CatmullRomSpline.js +12 -0
  22. package/dist/cjs/tools/annotation/splines/CatmullRomSpline.js.map +1 -0
  23. package/dist/cjs/tools/annotation/splines/CubicSpline.d.ts +13 -0
  24. package/dist/cjs/tools/annotation/splines/CubicSpline.js +192 -0
  25. package/dist/cjs/tools/annotation/splines/CubicSpline.js.map +1 -0
  26. package/dist/cjs/tools/annotation/splines/LinearSpline.d.ts +5 -0
  27. package/dist/cjs/tools/annotation/splines/LinearSpline.js +12 -0
  28. package/dist/cjs/tools/annotation/splines/LinearSpline.js.map +1 -0
  29. package/dist/cjs/tools/annotation/splines/QuadraticBezier.d.ts +6 -0
  30. package/dist/cjs/tools/annotation/splines/QuadraticBezier.js +20 -0
  31. package/dist/cjs/tools/annotation/splines/QuadraticBezier.js.map +1 -0
  32. package/dist/cjs/tools/annotation/splines/QuadraticSpline.d.ts +9 -0
  33. package/dist/cjs/tools/annotation/splines/QuadraticSpline.js +18 -0
  34. package/dist/cjs/tools/annotation/splines/QuadraticSpline.js.map +1 -0
  35. package/dist/cjs/tools/annotation/splines/Spline.d.ts +49 -0
  36. package/dist/cjs/tools/annotation/splines/Spline.js +420 -0
  37. package/dist/cjs/tools/annotation/splines/Spline.js.map +1 -0
  38. package/dist/cjs/tools/index.d.ts +2 -1
  39. package/dist/cjs/tools/index.js +3 -1
  40. package/dist/cjs/tools/index.js.map +1 -1
  41. package/dist/cjs/types/CardinalSplineProps.d.ts +5 -0
  42. package/dist/cjs/types/CardinalSplineProps.js +3 -0
  43. package/dist/cjs/types/CardinalSplineProps.js.map +1 -0
  44. package/dist/cjs/types/ClosestControlPoint.d.ts +4 -0
  45. package/dist/cjs/types/ClosestControlPoint.js +3 -0
  46. package/dist/cjs/types/ClosestControlPoint.js.map +1 -0
  47. package/dist/cjs/types/ClosestPoint.d.ts +5 -0
  48. package/dist/cjs/types/ClosestPoint.js +3 -0
  49. package/dist/cjs/types/ClosestPoint.js.map +1 -0
  50. package/dist/cjs/types/ClosestSplinePoint.d.ts +4 -0
  51. package/dist/cjs/types/ClosestSplinePoint.js +3 -0
  52. package/dist/cjs/types/ClosestSplinePoint.js.map +1 -0
  53. package/dist/cjs/types/ControlPointInfo.d.ts +5 -0
  54. package/dist/cjs/types/ControlPointInfo.js +3 -0
  55. package/dist/cjs/types/ControlPointInfo.js.map +1 -0
  56. package/dist/cjs/types/ISpline.d.ts +29 -0
  57. package/dist/cjs/types/ISpline.js +3 -0
  58. package/dist/cjs/types/ISpline.js.map +1 -0
  59. package/dist/cjs/types/SplineCurveSegment.d.ts +14 -0
  60. package/dist/cjs/types/SplineCurveSegment.js +3 -0
  61. package/dist/cjs/types/SplineCurveSegment.js.map +1 -0
  62. package/dist/cjs/types/SplineLineSegment.d.ts +10 -0
  63. package/dist/cjs/types/SplineLineSegment.js +3 -0
  64. package/dist/cjs/types/SplineLineSegment.js.map +1 -0
  65. package/dist/cjs/types/SplineProps.d.ts +4 -0
  66. package/dist/cjs/types/SplineProps.js +3 -0
  67. package/dist/cjs/types/SplineProps.js.map +1 -0
  68. package/dist/cjs/types/ToolSpecificAnnotationTypes.d.ts +34 -0
  69. package/dist/cjs/types/index.d.ts +10 -1
  70. package/dist/cjs/utilities/index.d.ts +2 -3
  71. package/dist/cjs/utilities/index.js +5 -5
  72. package/dist/cjs/utilities/index.js.map +1 -1
  73. package/dist/cjs/utilities/math/aabb/distanceToPoint.d.ts +2 -0
  74. package/dist/cjs/utilities/math/aabb/distanceToPoint.js +11 -0
  75. package/dist/cjs/utilities/math/aabb/distanceToPoint.js.map +1 -0
  76. package/dist/cjs/utilities/math/aabb/distanceToPointSquared.d.ts +2 -0
  77. package/dist/cjs/utilities/math/aabb/distanceToPointSquared.js +24 -0
  78. package/dist/cjs/utilities/math/aabb/distanceToPointSquared.js.map +1 -0
  79. package/dist/cjs/utilities/math/aabb/index.d.ts +2 -0
  80. package/dist/cjs/utilities/math/aabb/index.js +11 -0
  81. package/dist/cjs/utilities/math/aabb/index.js.map +1 -0
  82. package/dist/cjs/utilities/math/index.d.ts +6 -5
  83. package/dist/cjs/utilities/math/index.js +11 -9
  84. package/dist/cjs/utilities/math/index.js.map +1 -1
  85. package/dist/cjs/utilities/math/line/distanceToPointSquared.js +5 -21
  86. package/dist/cjs/utilities/math/line/distanceToPointSquared.js.map +1 -1
  87. package/dist/cjs/utilities/math/line/distanceToPointSquaredInfo.d.ts +5 -0
  88. package/dist/cjs/utilities/math/line/distanceToPointSquaredInfo.js +56 -0
  89. package/dist/cjs/utilities/math/line/distanceToPointSquaredInfo.js.map +1 -0
  90. package/dist/cjs/utilities/math/line/index.d.ts +2 -1
  91. package/dist/cjs/utilities/math/line/index.js +3 -1
  92. package/dist/cjs/utilities/math/line/index.js.map +1 -1
  93. package/dist/cjs/utilities/math/point/distanceToPoint.js +5 -6
  94. package/dist/cjs/utilities/math/point/distanceToPoint.js.map +1 -1
  95. package/dist/cjs/utilities/math/point/distanceToPointSquared.d.ts +4 -0
  96. package/dist/cjs/utilities/math/point/distanceToPointSquared.js +12 -0
  97. package/dist/cjs/utilities/math/point/distanceToPointSquared.js.map +1 -0
  98. package/dist/cjs/utilities/math/point/index.d.ts +3 -2
  99. package/dist/cjs/utilities/math/point/index.js +7 -3
  100. package/dist/cjs/utilities/math/point/index.js.map +1 -1
  101. package/dist/cjs/utilities/math/point/mirror.d.ts +2 -0
  102. package/dist/cjs/utilities/math/point/mirror.js +11 -0
  103. package/dist/cjs/utilities/math/point/mirror.js.map +1 -0
  104. package/dist/esm/eventDispatchers/mouseEventHandlers/mouseDown.js +4 -4
  105. package/dist/esm/eventDispatchers/mouseEventHandlers/mouseDown.js.map +1 -1
  106. package/dist/esm/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js +2 -1
  107. package/dist/esm/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js.map +1 -1
  108. package/dist/esm/index.js +2 -2
  109. package/dist/esm/index.js.map +1 -1
  110. package/dist/esm/tools/AdvancedMagnifyTool.js +8 -3
  111. package/dist/esm/tools/AdvancedMagnifyTool.js.map +1 -1
  112. package/dist/esm/tools/annotation/SplineROITool.js +703 -0
  113. package/dist/esm/tools/annotation/SplineROITool.js.map +1 -0
  114. package/dist/esm/tools/annotation/splines/BSpline.js +10 -0
  115. package/dist/esm/tools/annotation/splines/BSpline.js.map +1 -0
  116. package/dist/esm/tools/annotation/splines/CardinalSpline.js +33 -0
  117. package/dist/esm/tools/annotation/splines/CardinalSpline.js.map +1 -0
  118. package/dist/esm/tools/annotation/splines/CatmullRomSpline.js +8 -0
  119. package/dist/esm/tools/annotation/splines/CatmullRomSpline.js.map +1 -0
  120. package/dist/esm/tools/annotation/splines/CubicSpline.js +165 -0
  121. package/dist/esm/tools/annotation/splines/CubicSpline.js.map +1 -0
  122. package/dist/esm/tools/annotation/splines/LinearSpline.js +8 -0
  123. package/dist/esm/tools/annotation/splines/LinearSpline.js.map +1 -0
  124. package/dist/esm/tools/annotation/splines/QuadraticBezier.js +16 -0
  125. package/dist/esm/tools/annotation/splines/QuadraticBezier.js.map +1 -0
  126. package/dist/esm/tools/annotation/splines/QuadraticSpline.js +14 -0
  127. package/dist/esm/tools/annotation/splines/QuadraticSpline.js.map +1 -0
  128. package/dist/esm/tools/annotation/splines/Spline.js +392 -0
  129. package/dist/esm/tools/annotation/splines/Spline.js.map +1 -0
  130. package/dist/esm/tools/index.js +2 -1
  131. package/dist/esm/tools/index.js.map +1 -1
  132. package/dist/esm/types/CardinalSplineProps.js +2 -0
  133. package/dist/esm/types/CardinalSplineProps.js.map +1 -0
  134. package/dist/esm/types/ClosestControlPoint.js +2 -0
  135. package/dist/esm/types/ClosestControlPoint.js.map +1 -0
  136. package/dist/esm/types/ClosestPoint.js +2 -0
  137. package/dist/esm/types/ClosestPoint.js.map +1 -0
  138. package/dist/esm/types/ClosestSplinePoint.js +2 -0
  139. package/dist/esm/types/ClosestSplinePoint.js.map +1 -0
  140. package/dist/esm/types/ControlPointInfo.js +2 -0
  141. package/dist/esm/types/ControlPointInfo.js.map +1 -0
  142. package/dist/esm/types/ISpline.js +2 -0
  143. package/dist/esm/types/ISpline.js.map +1 -0
  144. package/dist/esm/types/SplineCurveSegment.js +2 -0
  145. package/dist/esm/types/SplineCurveSegment.js.map +1 -0
  146. package/dist/esm/types/SplineLineSegment.js +2 -0
  147. package/dist/esm/types/SplineLineSegment.js.map +1 -0
  148. package/dist/esm/types/SplineProps.js +2 -0
  149. package/dist/esm/types/SplineProps.js.map +1 -0
  150. package/dist/esm/utilities/index.js +2 -3
  151. package/dist/esm/utilities/index.js.map +1 -1
  152. package/dist/esm/utilities/math/aabb/distanceToPoint.js +5 -0
  153. package/dist/esm/utilities/math/aabb/distanceToPoint.js.map +1 -0
  154. package/dist/esm/utilities/math/aabb/distanceToPointSquared.js +21 -0
  155. package/dist/esm/utilities/math/aabb/distanceToPointSquared.js.map +1 -0
  156. package/dist/esm/utilities/math/aabb/index.js +3 -0
  157. package/dist/esm/utilities/math/aabb/index.js.map +1 -0
  158. package/dist/esm/utilities/math/index.js +6 -5
  159. package/dist/esm/utilities/math/index.js.map +1 -1
  160. package/dist/esm/utilities/math/line/distanceToPointSquared.js +2 -21
  161. package/dist/esm/utilities/math/line/distanceToPointSquared.js.map +1 -1
  162. package/dist/esm/utilities/math/line/distanceToPointSquaredInfo.js +30 -0
  163. package/dist/esm/utilities/math/line/distanceToPointSquaredInfo.js.map +1 -0
  164. package/dist/esm/utilities/math/line/index.js +2 -1
  165. package/dist/esm/utilities/math/line/index.js.map +1 -1
  166. package/dist/esm/utilities/math/point/distanceToPoint.js +2 -6
  167. package/dist/esm/utilities/math/point/distanceToPoint.js.map +1 -1
  168. package/dist/esm/utilities/math/point/distanceToPointSquared.js +9 -0
  169. package/dist/esm/utilities/math/point/distanceToPointSquared.js.map +1 -0
  170. package/dist/esm/utilities/math/point/index.js +3 -2
  171. package/dist/esm/utilities/math/point/index.js.map +1 -1
  172. package/dist/esm/utilities/math/point/mirror.js +8 -0
  173. package/dist/esm/utilities/math/point/mirror.js.map +1 -0
  174. package/dist/types/eventDispatchers/mouseEventHandlers/mouseDown.d.ts.map +1 -1
  175. package/dist/types/eventDispatchers/shared/getToolsWithActionsForMouseEvent.d.ts.map +1 -1
  176. package/dist/types/index.d.ts +2 -2
  177. package/dist/types/index.d.ts.map +1 -1
  178. package/dist/types/tools/AdvancedMagnifyTool.d.ts +4 -0
  179. package/dist/types/tools/AdvancedMagnifyTool.d.ts.map +1 -1
  180. package/dist/types/tools/annotation/SplineROITool.d.ts +60 -0
  181. package/dist/types/tools/annotation/SplineROITool.d.ts.map +1 -0
  182. package/dist/types/tools/annotation/splines/BSpline.d.ts +6 -0
  183. package/dist/types/tools/annotation/splines/BSpline.d.ts.map +1 -0
  184. package/dist/types/tools/annotation/splines/CardinalSpline.d.ts +13 -0
  185. package/dist/types/tools/annotation/splines/CardinalSpline.d.ts.map +1 -0
  186. package/dist/types/tools/annotation/splines/CatmullRomSpline.d.ts +6 -0
  187. package/dist/types/tools/annotation/splines/CatmullRomSpline.d.ts.map +1 -0
  188. package/dist/types/tools/annotation/splines/CubicSpline.d.ts +14 -0
  189. package/dist/types/tools/annotation/splines/CubicSpline.d.ts.map +1 -0
  190. package/dist/types/tools/annotation/splines/LinearSpline.d.ts +6 -0
  191. package/dist/types/tools/annotation/splines/LinearSpline.d.ts.map +1 -0
  192. package/dist/types/tools/annotation/splines/QuadraticBezier.d.ts +7 -0
  193. package/dist/types/tools/annotation/splines/QuadraticBezier.d.ts.map +1 -0
  194. package/dist/types/tools/annotation/splines/QuadraticSpline.d.ts +10 -0
  195. package/dist/types/tools/annotation/splines/QuadraticSpline.d.ts.map +1 -0
  196. package/dist/types/tools/annotation/splines/Spline.d.ts +50 -0
  197. package/dist/types/tools/annotation/splines/Spline.d.ts.map +1 -0
  198. package/dist/types/tools/index.d.ts +2 -1
  199. package/dist/types/tools/index.d.ts.map +1 -1
  200. package/dist/types/types/CardinalSplineProps.d.ts +6 -0
  201. package/dist/types/types/CardinalSplineProps.d.ts.map +1 -0
  202. package/dist/types/types/ClosestControlPoint.d.ts +5 -0
  203. package/dist/types/types/ClosestControlPoint.d.ts.map +1 -0
  204. package/dist/types/types/ClosestPoint.d.ts +6 -0
  205. package/dist/types/types/ClosestPoint.d.ts.map +1 -0
  206. package/dist/types/types/ClosestSplinePoint.d.ts +5 -0
  207. package/dist/types/types/ClosestSplinePoint.d.ts.map +1 -0
  208. package/dist/types/types/ControlPointInfo.d.ts +6 -0
  209. package/dist/types/types/ControlPointInfo.d.ts.map +1 -0
  210. package/dist/types/types/ISpline.d.ts +30 -0
  211. package/dist/types/types/ISpline.d.ts.map +1 -0
  212. package/dist/types/types/SplineCurveSegment.d.ts +15 -0
  213. package/dist/types/types/SplineCurveSegment.d.ts.map +1 -0
  214. package/dist/types/types/SplineLineSegment.d.ts +11 -0
  215. package/dist/types/types/SplineLineSegment.d.ts.map +1 -0
  216. package/dist/types/types/SplineProps.d.ts +5 -0
  217. package/dist/types/types/SplineProps.d.ts.map +1 -0
  218. package/dist/types/types/ToolSpecificAnnotationTypes.d.ts +34 -0
  219. package/dist/types/types/ToolSpecificAnnotationTypes.d.ts.map +1 -1
  220. package/dist/types/types/index.d.ts +10 -1
  221. package/dist/types/types/index.d.ts.map +1 -1
  222. package/dist/types/utilities/index.d.ts +2 -3
  223. package/dist/types/utilities/index.d.ts.map +1 -1
  224. package/dist/types/utilities/math/aabb/distanceToPoint.d.ts +3 -0
  225. package/dist/types/utilities/math/aabb/distanceToPoint.d.ts.map +1 -0
  226. package/dist/types/utilities/math/aabb/distanceToPointSquared.d.ts +3 -0
  227. package/dist/types/utilities/math/aabb/distanceToPointSquared.d.ts.map +1 -0
  228. package/dist/types/utilities/math/aabb/index.d.ts +3 -0
  229. package/dist/types/utilities/math/aabb/index.d.ts.map +1 -0
  230. package/dist/types/utilities/math/index.d.ts +6 -5
  231. package/dist/types/utilities/math/index.d.ts.map +1 -1
  232. package/dist/types/utilities/math/line/distanceToPointSquared.d.ts.map +1 -1
  233. package/dist/types/utilities/math/line/distanceToPointSquaredInfo.d.ts +6 -0
  234. package/dist/types/utilities/math/line/distanceToPointSquaredInfo.d.ts.map +1 -0
  235. package/dist/types/utilities/math/line/index.d.ts +2 -1
  236. package/dist/types/utilities/math/line/index.d.ts.map +1 -1
  237. package/dist/types/utilities/math/point/distanceToPoint.d.ts.map +1 -1
  238. package/dist/types/utilities/math/point/distanceToPointSquared.d.ts +5 -0
  239. package/dist/types/utilities/math/point/distanceToPointSquared.d.ts.map +1 -0
  240. package/dist/types/utilities/math/point/index.d.ts +3 -2
  241. package/dist/types/utilities/math/point/index.d.ts.map +1 -1
  242. package/dist/types/utilities/math/point/mirror.d.ts +3 -0
  243. package/dist/types/utilities/math/point/mirror.d.ts.map +1 -0
  244. package/dist/umd/index.js +2 -1
  245. package/dist/umd/index.js.LICENSE.txt +6 -0
  246. package/dist/umd/index.js.map +1 -1
  247. package/package.json +3 -3
  248. package/src/eventDispatchers/mouseEventHandlers/mouseDown.ts +8 -6
  249. package/src/eventDispatchers/shared/getToolsWithActionsForMouseEvent.ts +3 -2
  250. package/src/index.ts +2 -0
  251. package/src/tools/AdvancedMagnifyTool.ts +8 -3
  252. package/src/tools/annotation/SplineROITool.ts +1151 -0
  253. package/src/tools/annotation/splines/BSpline.ts +22 -0
  254. package/src/tools/annotation/splines/CardinalSpline.ts +45 -0
  255. package/src/tools/annotation/splines/CatmullRomSpline.ts +19 -0
  256. package/src/tools/annotation/splines/CubicSpline.ts +288 -0
  257. package/src/tools/annotation/splines/LinearSpline.ts +20 -0
  258. package/src/tools/annotation/splines/QuadraticBezier.ts +20 -0
  259. package/src/tools/annotation/splines/QuadraticSpline.ts +25 -0
  260. package/src/tools/annotation/splines/Spline.ts +729 -0
  261. package/src/tools/index.ts +2 -0
  262. package/src/types/CardinalSplineProps.ts +11 -0
  263. package/src/types/ClosestControlPoint.ts +6 -0
  264. package/src/types/ClosestPoint.ts +8 -0
  265. package/src/types/ClosestSplinePoint.ts +6 -0
  266. package/src/types/ControlPointInfo.ts +8 -0
  267. package/src/types/ISpline.ts +164 -0
  268. package/src/types/SplineCurveSegment.ts +28 -0
  269. package/src/types/SplineLineSegment.ts +20 -0
  270. package/src/types/SplineProps.ts +15 -0
  271. package/src/types/ToolSpecificAnnotationTypes.ts +35 -0
  272. package/src/types/index.ts +21 -0
  273. package/src/utilities/index.ts +6 -2
  274. package/src/utilities/math/aabb/distanceToPoint.ts +20 -0
  275. package/src/utilities/math/aabb/distanceToPointSquared.ts +47 -0
  276. package/src/utilities/math/aabb/index.ts +2 -0
  277. package/src/utilities/math/index.ts +10 -8
  278. package/src/utilities/math/line/distanceToPointSquared.ts +3 -29
  279. package/src/utilities/math/line/distanceToPointSquaredInfo.ts +54 -0
  280. package/src/utilities/math/line/index.ts +7 -1
  281. package/src/utilities/math/point/distanceToPoint.ts +2 -10
  282. package/src/utilities/math/point/distanceToPointSquared.ts +21 -0
  283. package/src/utilities/math/point/index.ts +3 -3
  284. package/src/utilities/math/point/mirror.ts +21 -0
@@ -0,0 +1,729 @@
1
+ import { Types } from '@cornerstonejs/core';
2
+ import * as math from '../../../utilities/math';
3
+ import type {
4
+ ISpline,
5
+ SplineProps,
6
+ SplineLineSegment,
7
+ ClosestControlPoint,
8
+ ClosestSplinePoint,
9
+ ClosestPoint,
10
+ ControlPointInfo,
11
+ SplineCurveSegment,
12
+ } from '../../../types';
13
+
14
+ type CurveSegmentDistanceSquared = {
15
+ curveSegmentIndex: number;
16
+ curveSegment: SplineCurveSegment;
17
+ distanceSquared: number;
18
+ };
19
+
20
+ /**
21
+ * Spline curve representation
22
+ *
23
+ * You can find more about splines in this video
24
+ * https://www.youtube.com/watch?v=jvPPXbo87ds&t=11m20s
25
+ */
26
+ abstract class Spline implements ISpline {
27
+ private _controlPoints: Types.Point2[] = [];
28
+ private _resolution: number;
29
+ private _closed: boolean;
30
+ private _invalidated = false;
31
+ private _curveSegments: SplineCurveSegment[];
32
+ private _aabb: Types.AABB2;
33
+ private _length = 0;
34
+
35
+ constructor(props?: SplineProps) {
36
+ this._controlPoints = [];
37
+ this._resolution = props?.resolution ?? 20;
38
+ this._closed = props?.closed ?? false;
39
+ this._invalidated = true;
40
+ }
41
+
42
+ /**
43
+ * Return the control points array
44
+ *
45
+ * Any external access should be done through getControlPoints because it
46
+ * clones the points to make sure the data will not get changed by the caller
47
+ */
48
+ protected get controlPoints(): Types.Point2[] {
49
+ return this._controlPoints;
50
+ }
51
+
52
+ /** Number of control points */
53
+ public get numControlPoints(): number {
54
+ return this._controlPoints.length;
55
+ }
56
+
57
+ /** Resolution of the spline curve (greater than or equal to 0) */
58
+ public get resolution(): number {
59
+ return this._resolution;
60
+ }
61
+
62
+ /** Set the resolution of the spline curve */
63
+ public set resolution(resolution: number) {
64
+ if (this._resolution === resolution) {
65
+ return;
66
+ }
67
+
68
+ this._resolution = resolution;
69
+ this.invalidated = true;
70
+ }
71
+
72
+ /** Flag that is set to true when the curve is already closed */
73
+ public get closed(): boolean {
74
+ return this._closed;
75
+ }
76
+
77
+ /** Set the curve as closed which connects the last to the first point */
78
+ public set closed(closed: boolean) {
79
+ if (this._closed === closed) {
80
+ return;
81
+ }
82
+
83
+ this._closed = closed;
84
+ this.invalidated = true;
85
+ }
86
+
87
+ /** Axis-aligned bounding box (minX, minY, maxX, maxY) */
88
+ public get aabb(): Types.AABB2 {
89
+ this._update();
90
+ return this._aabb;
91
+ }
92
+
93
+ /** Length of the spline curve in pixels */
94
+ public get length(): number {
95
+ this._update();
96
+ return this._length;
97
+ }
98
+
99
+ /**
100
+ * Flag that is set to true when the spline needs to be updated. The update
101
+ * runs automaticaly when needed (eg: getPolylinePoints).
102
+ */
103
+ public get invalidated(): boolean {
104
+ return this._invalidated;
105
+ }
106
+
107
+ /**
108
+ * Sets the spline as invalid when curve segments need to be recalculated
109
+ * or as valid after recomputing the curves
110
+ */
111
+ protected set invalidated(invalidated: boolean) {
112
+ this._invalidated = invalidated;
113
+ }
114
+
115
+ /**
116
+ * Bézier curves have tangent points connected to control points
117
+ * @returns True if the spline has tangent point or false otherwise
118
+ */
119
+ public hasTangentPoints() {
120
+ return false;
121
+ }
122
+
123
+ /**
124
+ * Add a control point to the end of the array
125
+ * @param point - Control point (2D)
126
+ */
127
+ public addControlPoint(point: Types.Point2): void {
128
+ this._controlPoints.push([point[0], point[1]]);
129
+ this.invalidated = true;
130
+ }
131
+
132
+ /**
133
+ * Add a list of control poits to the end of the array
134
+ * @param points - Control points to be added
135
+ */
136
+ public addControlPoints(points: Types.Point2[]): void {
137
+ points.forEach((point) => this.addControlPoint(point));
138
+ }
139
+
140
+ /**
141
+ * Add a control point specifying its `u` value in Parameter Space which is a number from 0 to N
142
+ * where N is the number of curve segments. The integer part is the curve segment index and the
143
+ * decimal part is the `t` value on that curve segment.
144
+ * @param u - `u` value in Parameter Space
145
+ */
146
+ public addControlPointAtU(u: number): ControlPointInfo {
147
+ const lineSegment = this._getLineSegmentAt(u);
148
+ const { start: startPoint, end: endPoint } = lineSegment.points;
149
+ const curveSegmentIndex = Math.floor(u);
150
+ const curveSegment = this._curveSegments[curveSegmentIndex];
151
+ const t = u - Math.floor(curveSegmentIndex);
152
+ const controlPointPos: Types.Point2 = [
153
+ startPoint[0] + t * (endPoint[0] - startPoint[0]),
154
+ startPoint[1] + t * (endPoint[1] - startPoint[1]),
155
+ ];
156
+
157
+ const insertIndex =
158
+ this._controlPoints.indexOf(curveSegment.controlPoints.p1) + 1;
159
+
160
+ this._controlPoints.splice(insertIndex, 0, controlPointPos);
161
+ this.invalidated = true;
162
+
163
+ return {
164
+ index: insertIndex,
165
+ point: controlPointPos,
166
+ };
167
+ }
168
+
169
+ /**
170
+ * Delete a control point given its index
171
+ * @param index - Control point index to be removed
172
+ * @returns True if the control point is removed or false otherwise
173
+ */
174
+ public deleteControlPointByIndex(index: number): boolean {
175
+ const minControlPoints = this._closed ? 3 : 1;
176
+ const canDelete =
177
+ index >= 0 &&
178
+ index < this._controlPoints.length &&
179
+ this._controlPoints.length > minControlPoints;
180
+
181
+ if (!canDelete) {
182
+ return false;
183
+ }
184
+
185
+ this._controlPoints.splice(index, 1);
186
+ this.invalidated = true;
187
+
188
+ return true;
189
+ }
190
+
191
+ /**
192
+ * Remove all control points
193
+ */
194
+ public clearControlPoints(): void {
195
+ this._controlPoints = [];
196
+ this.invalidated = true;
197
+ }
198
+
199
+ /**
200
+ * Replace all control points by some new ones
201
+ * @param points - Control points to be added to the array
202
+ */
203
+ public setControlPoints(points: Types.Point2[]): void {
204
+ this.clearControlPoints();
205
+ this.addControlPoints(points);
206
+ }
207
+
208
+ /**
209
+ * Update the coordinate of a control point given its index
210
+ * @param index - Control point index
211
+ * @param newControlPoint - New control point
212
+ */
213
+ public updateControlPoint(
214
+ index: number,
215
+ newControlPoint: Types.Point2
216
+ ): void {
217
+ if (index < 0 || index >= this._controlPoints.length) {
218
+ throw new Error('Index out of bounds');
219
+ }
220
+
221
+ this._controlPoints[index] = [...newControlPoint];
222
+ this.invalidated = true;
223
+ }
224
+
225
+ /**
226
+ * Get a list with all control points. The control points are cloned to prevent
227
+ * any caller from changing them resulting in unexpected behaviors
228
+ * @returns - List of all control points
229
+ */
230
+ public getControlPoints(): Types.Point2[] {
231
+ return this._controlPoints.map((controlPoint) => [
232
+ controlPoint[0],
233
+ controlPoint[1],
234
+ ]);
235
+ }
236
+
237
+ /**
238
+ * Finds the closest control point given a 2D point
239
+ * @param point - Reference point
240
+ * @returns Closest control point
241
+ */
242
+ public getClosestControlPoint(point: Types.Point2): ClosestControlPoint {
243
+ const controlPoints = this._controlPoints;
244
+ let minSquaredDist = Infinity;
245
+ let closestPointIndex = -1;
246
+
247
+ for (let i = 0, len = controlPoints.length; i < len; i++) {
248
+ const controlPoint = controlPoints[i];
249
+ const dx = point[0] - controlPoint[0];
250
+ const dy = point[1] - controlPoint[1];
251
+ const squaredDist = dx * dx + dy * dy;
252
+
253
+ if (squaredDist < minSquaredDist) {
254
+ minSquaredDist = squaredDist;
255
+ closestPointIndex = i;
256
+ }
257
+ }
258
+
259
+ return {
260
+ index: closestPointIndex,
261
+ point:
262
+ closestPointIndex === -1
263
+ ? undefined
264
+ : [...controlPoints[closestPointIndex]],
265
+ distance: Math.sqrt(minSquaredDist),
266
+ };
267
+ }
268
+
269
+ /**
270
+ * Finds the closest control point given a 2D point and a maximum distance
271
+ * @param point - Reference 2D point
272
+ * @param maxDist - Maximum distance
273
+ * @returns Closest control point that is within the given range or undefined otherwise
274
+ */
275
+ public getClosestControlPointWithinDistance(
276
+ point: Types.Point2,
277
+ maxDist: number
278
+ ): ClosestControlPoint {
279
+ const closestControlPoint = this.getClosestControlPoint(point);
280
+
281
+ return closestControlPoint.distance <= maxDist
282
+ ? closestControlPoint
283
+ : undefined;
284
+ }
285
+
286
+ /**
287
+ * Finds the closest point on the spline curve given 2D point
288
+ * @param point - Reference 2D point
289
+ * @returns Closest point on the spline curve
290
+ */
291
+ public getClosestPoint(point: Types.Point2): ClosestSplinePoint {
292
+ this._update();
293
+
294
+ const curveSegmentsDistInfo =
295
+ this._getCurveSegmmentsDistanceSquaredInfo(point);
296
+
297
+ if (!curveSegmentsDistInfo.length) {
298
+ return;
299
+ }
300
+
301
+ // Sort the curves by distance because in most cases the closest point may be in the first
302
+ // curve segment and there is no need to check all next line segments if theirs curve segments'
303
+ // AABB is not closest compared to the minDist found saving a lot of cpu time.
304
+ curveSegmentsDistInfo.sort(
305
+ (csA, csB) => csA.distanceSquared - csB.distanceSquared
306
+ );
307
+
308
+ let closestPoint: Types.Point2;
309
+ let closestPointCurveSegmentIndex = -1;
310
+ let minDistSquared = Infinity;
311
+ let minDistCurveSegment: SplineCurveSegment;
312
+ let minDistLineSegment: SplineLineSegment;
313
+
314
+ for (let i = 0; i < curveSegmentsDistInfo.length; i++) {
315
+ const curveSegmentDistInfo = curveSegmentsDistInfo[i];
316
+
317
+ // If the distance to curve segments' AABB is greater than the minDist
318
+ // it does not need to waste time verifying each line segment
319
+ if (curveSegmentDistInfo.distanceSquared > minDistSquared) {
320
+ continue;
321
+ }
322
+
323
+ const { curveSegmentIndex, curveSegment } = curveSegmentDistInfo;
324
+ const { lineSegments } = curveSegment;
325
+
326
+ for (let j = 0; j < lineSegments.length; j++) {
327
+ const lineSegment = lineSegments[j];
328
+ const { point: lineSegPoint, distanceSquared: lineSegDistSquared } =
329
+ math.lineSegment.distanceToPointSquaredInfo(
330
+ lineSegment.points.start,
331
+ lineSegment.points.end,
332
+ point
333
+ );
334
+
335
+ if (lineSegDistSquared < minDistSquared) {
336
+ minDistLineSegment = lineSegment;
337
+ closestPointCurveSegmentIndex = curveSegmentIndex;
338
+ minDistCurveSegment = curveSegmentDistInfo.curveSegment;
339
+ closestPoint = lineSegPoint;
340
+ minDistSquared = lineSegDistSquared;
341
+ }
342
+ }
343
+ }
344
+
345
+ const curveSegmentLengthToPoint =
346
+ minDistLineSegment.previousLineSegmentsLength +
347
+ math.point.distanceToPoint(minDistLineSegment.points.start, closestPoint);
348
+
349
+ const t = curveSegmentLengthToPoint / minDistCurveSegment.length;
350
+ const u = closestPointCurveSegmentIndex + t;
351
+
352
+ return {
353
+ point: closestPoint,
354
+ uValue: u,
355
+ distance: Math.sqrt(minDistSquared),
356
+ };
357
+ }
358
+
359
+ /**
360
+ * Finds the closest point on the straight line that connects all control points given a 2D point
361
+ * @param point - Reference point
362
+ * @returns Closest point on the straight line that connects all control points
363
+ */
364
+ public getClosestPointOnControlPointLines(point: Types.Point2): ClosestPoint {
365
+ const linePoints = [...this._controlPoints];
366
+
367
+ if (this._closed) {
368
+ linePoints.push(this._controlPoints[0]);
369
+ }
370
+
371
+ if (!linePoints.length) {
372
+ return;
373
+ }
374
+
375
+ let closestPoint: Types.Point2;
376
+ let minDistSquared = Infinity;
377
+ let startPoint = linePoints[0];
378
+
379
+ for (let i = 1, len = linePoints.length; i < len; i++) {
380
+ const endPoint = linePoints[i];
381
+ const { point: lineSegPoint, distanceSquared: lineSegDistSquared } =
382
+ math.lineSegment.distanceToPointSquaredInfo(
383
+ startPoint,
384
+ endPoint,
385
+ point
386
+ );
387
+
388
+ if (lineSegDistSquared < minDistSquared) {
389
+ closestPoint = lineSegPoint;
390
+ minDistSquared = lineSegDistSquared;
391
+ }
392
+
393
+ startPoint = endPoint;
394
+ }
395
+
396
+ return {
397
+ point: closestPoint,
398
+ distance: Math.sqrt(minDistSquared),
399
+ };
400
+ }
401
+
402
+ /**
403
+ * Get all points necessary to draw a spline curve
404
+ * @returns Array with all points necessary to draw a spline curve
405
+ */
406
+ public getPolylinePoints(): Types.Point2[] {
407
+ this._update();
408
+
409
+ return this._convertCurveSegmentsToPolyline(this._curveSegments);
410
+ }
411
+
412
+ /**
413
+ * Get all points necessary to draw the preview of the changes that shall be
414
+ * made to the spline if a new control point is added to it
415
+ * @param controlPointPreview - New control point preview
416
+ * @param closeDistance - Distance to the first control point to consider it a closed spline
417
+ * @returns Array with all points necessary to draw a spline curve preview
418
+ */
419
+ public getPreviewPolylinePoints(
420
+ controlPointPreview: Types.Point2,
421
+ closeDistance: number
422
+ ): Types.Point2[] {
423
+ if (this._closed) {
424
+ return [];
425
+ }
426
+
427
+ this._update();
428
+
429
+ // Check if the new control point would be close to the first one
430
+ // in order to create a preview of a closed spline
431
+ const closestControlPoint = this.getClosestControlPointWithinDistance(
432
+ controlPointPreview,
433
+ closeDistance
434
+ );
435
+
436
+ const closeSpline = closestControlPoint?.index === 0;
437
+ const previewCurveSegments = this.getPreviewCurveSegments(
438
+ controlPointPreview,
439
+ closeSpline
440
+ );
441
+
442
+ return previewCurveSegments?.length
443
+ ? this._convertCurveSegmentsToPolyline(previewCurveSegments)
444
+ : [];
445
+ }
446
+
447
+ /**
448
+ * Checks if a point is near to the spline curve
449
+ * @param point - Reference point
450
+ * @param maxDist - Maximum allowed distance
451
+ * @returns True if the point is close to the spline curve or false otherwise
452
+ */
453
+ public isPointNearCurve(point: Types.Point2, maxDist: number): boolean {
454
+ this._update();
455
+
456
+ const curveSegments = this._getCurveSegmmentsWithinDistance(point, maxDist);
457
+ const maxDistSquared = maxDist * maxDist;
458
+
459
+ // Check if the point is close to the spline and doest waste time checking each curve/line
460
+ for (let i = 0; i < curveSegments.length; i++) {
461
+ const { lineSegments } = curveSegments[i];
462
+
463
+ for (let j = 0; j < lineSegments.length; j++) {
464
+ const lineSegment = lineSegments[j];
465
+ const lineDistSquared = math.lineSegment.distanceToPointSquared(
466
+ lineSegment.points.start,
467
+ lineSegment.points.end,
468
+ point
469
+ );
470
+
471
+ if (lineDistSquared <= maxDistSquared) {
472
+ return true;
473
+ }
474
+ }
475
+ }
476
+
477
+ return false;
478
+ }
479
+
480
+ /**
481
+ * Checks if a 2D point is inside the spline curve.
482
+ *
483
+ * A point is inside a curve/polygon if the number of intersections between the horizontal
484
+ * ray emanating from the given point and to the right and the line segments is odd.
485
+ * https://www.eecs.umich.edu/courses/eecs380/HANDOUTS/PROJ2/InsidePoly.html
486
+ *
487
+ * @param point - 2D Point
488
+ * @returns True is the point is inside the spline curve or false otherwise
489
+ */
490
+ public containsPoint(point: Types.Point2): boolean {
491
+ this._update();
492
+
493
+ const controlPoints = this._controlPoints;
494
+
495
+ if (controlPoints.length < 3) {
496
+ return false;
497
+ }
498
+
499
+ const curveSegments = [...this._curveSegments];
500
+ const closingCurveSegment =
501
+ this._getClosingCurveSegmentWithStraightLineSegment();
502
+
503
+ if (closingCurveSegment) {
504
+ curveSegments.push(closingCurveSegment);
505
+ }
506
+
507
+ let numIntersections = 0;
508
+
509
+ for (let i = 0; i < curveSegments.length; i++) {
510
+ const curveSegment = curveSegments[i];
511
+ const { aabb: curveSegAABB } = curveSegment;
512
+ const mayIntersectCurveSegment =
513
+ point[0] <= curveSegAABB.maxX &&
514
+ point[1] >= curveSegAABB.minY &&
515
+ point[1] < curveSegAABB.maxY;
516
+
517
+ // Skip all line segments if it is not possible to intersect the curve segment
518
+ if (!mayIntersectCurveSegment) {
519
+ continue;
520
+ }
521
+
522
+ const { lineSegments } = curveSegment;
523
+
524
+ for (let i = 0; i < lineSegments.length; i++) {
525
+ const lineSegment = lineSegments[i];
526
+ const { aabb: lineSegmentAABB } = lineSegment;
527
+ const mayIntersectLineSegment =
528
+ point[0] <= lineSegmentAABB.maxX &&
529
+ point[1] >= lineSegmentAABB.minY &&
530
+ point[1] < lineSegmentAABB.maxY;
531
+
532
+ if (mayIntersectLineSegment) {
533
+ const { start: p1, end: p2 } = lineSegment.points;
534
+ const isVerticalLine = p1[0] === p2[0];
535
+ const xIntersection =
536
+ ((point[1] - p1[1]) * (p2[0] - p1[0])) / (p2[1] - p1[1]) + p1[0];
537
+
538
+ numIntersections +=
539
+ isVerticalLine || point[0] <= xIntersection ? 1 : 0;
540
+ }
541
+ }
542
+ }
543
+
544
+ return numIntersections % 2 === 1;
545
+ }
546
+
547
+ protected abstract getTransformMatrix(): number[];
548
+
549
+ protected abstract getSplineCurves(): SplineCurveSegment[];
550
+
551
+ protected abstract getPreviewCurveSegments(
552
+ controlPointPreview: Types.Point2,
553
+ closeSpline: boolean
554
+ ): SplineCurveSegment[];
555
+
556
+ private _update() {
557
+ if (!this._invalidated) {
558
+ return;
559
+ }
560
+
561
+ const curveSegments = this.getSplineCurves();
562
+ let length = 0;
563
+ let minX = Infinity;
564
+ let minY = Infinity;
565
+ let maxX = -Infinity;
566
+ let maxY = -Infinity;
567
+
568
+ for (let i = 0, len = curveSegments.length; i < len; i++) {
569
+ const { aabb: curveSegAABB, length: curveSegLength } = curveSegments[i];
570
+
571
+ minX = minX <= curveSegAABB.minX ? minX : curveSegAABB.minX;
572
+ minY = minY <= curveSegAABB.minY ? minY : curveSegAABB.minY;
573
+ maxX = maxX >= curveSegAABB.maxX ? maxX : curveSegAABB.maxX;
574
+ maxY = maxY >= curveSegAABB.maxY ? maxY : curveSegAABB.maxY;
575
+ length += curveSegLength;
576
+ }
577
+
578
+ this._curveSegments = curveSegments;
579
+ this._aabb = { minX, minY, maxX, maxY };
580
+ this._length = length;
581
+ this._invalidated = false;
582
+ }
583
+
584
+ private _convertCurveSegmentsToPolyline(
585
+ curveSegments: SplineCurveSegment[]
586
+ ): Types.Point2[] {
587
+ this._update();
588
+
589
+ const polylinePoints: Types.Point2[] = [];
590
+
591
+ curveSegments.forEach(({ lineSegments }, curveSegIndex) => {
592
+ lineSegments.forEach((lineSegment, lineSegIndex) => {
593
+ // Add the start point before adding all end points
594
+ if (curveSegIndex === 0 && lineSegIndex === 0) {
595
+ polylinePoints.push([...lineSegment.points.start]);
596
+ }
597
+
598
+ // Always add 1 because the first segment stored its start point at the first position
599
+ polylinePoints.push([...lineSegment.points.end]);
600
+ });
601
+ });
602
+
603
+ return polylinePoints;
604
+ }
605
+
606
+ /**
607
+ * Returns all curve segments and theirs respective squared distance to a given point
608
+ * @param point - Reference point
609
+ * @returns Curve segments and theirs respective squared distance to a given point
610
+ */
611
+ private _getCurveSegmmentsDistanceSquaredInfo(
612
+ point: Types.Point2
613
+ ): CurveSegmentDistanceSquared[] {
614
+ this._update();
615
+
616
+ const curveSegmentsDistanceSquared: CurveSegmentDistanceSquared[] = [];
617
+ const { _curveSegments: curveSegments } = this;
618
+
619
+ for (let i = 0; i < curveSegments.length; i++) {
620
+ const curveSegment = curveSegments[i];
621
+ const distanceSquared = math.aabb.distanceToPointSquared(
622
+ curveSegment.aabb,
623
+ point
624
+ );
625
+
626
+ curveSegmentsDistanceSquared.push({
627
+ curveSegmentIndex: i,
628
+ curveSegment,
629
+ distanceSquared,
630
+ });
631
+ }
632
+
633
+ return curveSegmentsDistanceSquared;
634
+ }
635
+
636
+ private _getCurveSegmmentsWithinDistance(
637
+ point: Types.Point2,
638
+ maxDist: number
639
+ ): SplineCurveSegment[] {
640
+ this._update();
641
+
642
+ const maxDistSquared = maxDist * maxDist;
643
+
644
+ // Does not waste time checking each curve segment if the point is not event
645
+ // close to the spline's AABB
646
+ if (math.aabb.distanceToPointSquared(this.aabb, point) > maxDistSquared) {
647
+ return [];
648
+ }
649
+
650
+ const curveSegmentsDistance =
651
+ this._getCurveSegmmentsDistanceSquaredInfo(point);
652
+ const curveSegmentsWithinRange: SplineCurveSegment[] = [];
653
+
654
+ for (let i = 0, len = curveSegmentsDistance.length; i < len; i++) {
655
+ const { curveSegment, distanceSquared: curveSegmentDistSquared } =
656
+ curveSegmentsDistance[i];
657
+
658
+ if (curveSegmentDistSquared <= maxDistSquared) {
659
+ curveSegmentsWithinRange.push(curveSegment);
660
+ }
661
+ }
662
+
663
+ return curveSegmentsWithinRange;
664
+ }
665
+
666
+ private _getLineSegmentAt(u: number): SplineLineSegment {
667
+ this._update();
668
+
669
+ const curveSegmentIndex = Math.floor(u);
670
+ const t = u - curveSegmentIndex;
671
+ const curveSegment = this._curveSegments[curveSegmentIndex];
672
+ const { lineSegments } = curveSegment;
673
+ const pointLength = curveSegment.length * t;
674
+
675
+ for (let i = 0; i < lineSegments.length; i++) {
676
+ const lineSegment = lineSegments[i];
677
+ const lengthEnd =
678
+ lineSegment.previousLineSegmentsLength + lineSegment.length;
679
+
680
+ if (
681
+ pointLength >= lineSegment.previousLineSegmentsLength &&
682
+ pointLength <= lengthEnd
683
+ ) {
684
+ return lineSegment;
685
+ }
686
+ }
687
+ }
688
+
689
+ /**
690
+ * Creates a curve segment with a single line segment connecting the start and end control points
691
+ * @returns A curve segment that closes the spline
692
+ */
693
+ private _getClosingCurveSegmentWithStraightLineSegment(): SplineCurveSegment {
694
+ if (this.closed) {
695
+ return;
696
+ }
697
+
698
+ const controlPoints = this._controlPoints;
699
+ const startControlPoint = controlPoints[0];
700
+ const endControlPoint = controlPoints[controlPoints.length - 1];
701
+
702
+ // The only properties needed are `points` and `aabb`. All the other ones may undefined
703
+ const closingLineSegment: SplineLineSegment = {
704
+ points: {
705
+ start: [...startControlPoint],
706
+ end: [...endControlPoint],
707
+ },
708
+ aabb: {
709
+ minX: Math.min(startControlPoint[0], endControlPoint[0]),
710
+ minY: Math.min(startControlPoint[1], endControlPoint[1]),
711
+ maxX: Math.max(startControlPoint[0], endControlPoint[0]),
712
+ maxY: Math.max(startControlPoint[1], endControlPoint[1]),
713
+ },
714
+ } as SplineLineSegment;
715
+
716
+ // The only properties needed are `lineSegments` and `aabb`. All the other ones may undefined
717
+ return {
718
+ aabb: {
719
+ minX: closingLineSegment.aabb.minX,
720
+ minY: closingLineSegment.aabb.minY,
721
+ maxX: closingLineSegment.aabb.maxX,
722
+ maxY: closingLineSegment.aabb.maxY,
723
+ },
724
+ lineSegments: [closingLineSegment],
725
+ } as SplineCurveSegment;
726
+ }
727
+ }
728
+
729
+ export { Spline as default, Spline };