@excalidraw/math 0.18.0-2b0e4c9 → 0.18.0-2b1c2a9

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 (192) hide show
  1. package/dist/dev/index.js +311 -114
  2. package/dist/dev/index.js.map +4 -4
  3. package/dist/prod/index.js +1 -1
  4. package/dist/types/common/src/colors.d.ts +20 -1
  5. package/dist/types/common/src/constants.d.ts +12 -7
  6. package/dist/types/common/src/keys.d.ts +2 -0
  7. package/dist/types/common/src/points.d.ts +1 -1
  8. package/dist/types/common/src/utils.d.ts +1 -43
  9. package/dist/types/element/src/Scene.d.ts +6 -4
  10. package/dist/types/element/src/align.d.ts +2 -2
  11. package/dist/types/element/src/arrowEndpointText.d.ts +49 -0
  12. package/dist/types/element/src/arrows/focus.d.ts +5 -2
  13. package/dist/types/element/src/binding.d.ts +17 -8
  14. package/dist/types/element/src/bounds.d.ts +22 -7
  15. package/dist/types/element/src/bucketFill.d.ts +110 -0
  16. package/dist/types/element/src/collision.d.ts +1 -1
  17. package/dist/types/element/src/comparisons.d.ts +5 -4
  18. package/dist/types/element/src/convertToShape.d.ts +23 -0
  19. package/dist/types/element/src/distribute.d.ts +2 -2
  20. package/dist/types/element/src/dragElements.d.ts +27 -0
  21. package/dist/types/element/src/duplicate.d.ts +4 -3
  22. package/dist/types/element/src/embeddable.d.ts +2 -2
  23. package/dist/types/element/src/flowchart.d.ts +7 -7
  24. package/dist/types/element/src/fractionalIndex.d.ts +2 -2
  25. package/dist/types/element/src/frame.d.ts +9 -8
  26. package/dist/types/element/src/groups.d.ts +9 -9
  27. package/dist/types/element/src/index.d.ts +4 -1
  28. package/dist/types/element/src/linearElementEditor.d.ts +27 -10
  29. package/dist/types/element/src/newElement.d.ts +15 -0
  30. package/dist/types/element/src/renderElement.d.ts +0 -3
  31. package/dist/types/element/src/resizeElements.d.ts +2 -2
  32. package/dist/types/element/src/selection.d.ts +11 -7
  33. package/dist/types/element/src/shape.d.ts +13 -1
  34. package/dist/types/element/src/sortElements.d.ts +10 -0
  35. package/dist/types/element/src/textElement.d.ts +14 -10
  36. package/dist/types/element/src/textWrapping.d.ts +26 -0
  37. package/dist/types/element/src/transform.d.ts +2 -2
  38. package/dist/types/element/src/typeChecks.d.ts +26 -25
  39. package/dist/types/element/src/types.d.ts +15 -1
  40. package/dist/types/element/src/utils.d.ts +7 -3
  41. package/dist/types/element/src/zindex.d.ts +2 -2
  42. package/dist/types/excalidraw/actions/actionAddToLibrary.d.ts +48 -21
  43. package/dist/types/excalidraw/actions/actionAlign.d.ts +6 -6
  44. package/dist/types/excalidraw/actions/actionBoundText.d.ts +33 -15
  45. package/dist/types/excalidraw/actions/actionCanvas.d.ts +174 -947
  46. package/dist/types/excalidraw/actions/actionClipboard.d.ts +32 -14
  47. package/dist/types/excalidraw/actions/actionCropEditor.d.ts +16 -7
  48. package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +50 -22
  49. package/dist/types/excalidraw/actions/{actionEmbeddable.d.ts → actionDeselect.d.ts} +30 -36
  50. package/dist/types/excalidraw/actions/actionDistribute.d.ts +2 -3
  51. package/dist/types/excalidraw/actions/actionElementLink.d.ts +16 -7
  52. package/dist/types/excalidraw/actions/actionElementLock.d.ts +33 -15
  53. package/dist/types/excalidraw/actions/actionExport.d.ts +34 -16
  54. package/dist/types/excalidraw/actions/actionFinalize.d.ts +1 -0
  55. package/dist/types/excalidraw/actions/actionFrame.d.ts +61 -205
  56. package/dist/types/excalidraw/actions/actionGroup.d.ts +48 -30
  57. package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +21 -9
  58. package/dist/types/excalidraw/actions/actionLink.d.ts +17 -8
  59. package/dist/types/excalidraw/actions/actionMenu.d.ts +16 -7
  60. package/dist/types/excalidraw/actions/actionProperties.d.ts +62 -32
  61. package/dist/types/excalidraw/actions/actionSelectAll.d.ts +21 -12
  62. package/dist/types/excalidraw/actions/actionStyles.d.ts +17 -7
  63. package/dist/types/excalidraw/actions/actionTextAutoResize.d.ts +3 -3
  64. package/dist/types/excalidraw/actions/actionToggleArrowBinding.d.ts +17 -8
  65. package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +20 -12
  66. package/dist/types/excalidraw/actions/actionToggleMidpointSnapping.d.ts +17 -8
  67. package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +17 -8
  68. package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +20 -12
  69. package/dist/types/excalidraw/actions/actionToggleShapeSwitch.d.ts +1 -1
  70. package/dist/types/excalidraw/actions/actionToggleStats.d.ts +17 -8
  71. package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +18 -9
  72. package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +17 -8
  73. package/dist/types/excalidraw/actions/index.d.ts +2 -2
  74. package/dist/types/excalidraw/actions/manager.d.ts +1 -0
  75. package/dist/types/excalidraw/actions/shortcuts.d.ts +1 -1
  76. package/dist/types/excalidraw/actions/types.d.ts +8 -4
  77. package/dist/types/excalidraw/{animated-trail.d.ts → animatedTrail.d.ts} +4 -3
  78. package/dist/types/excalidraw/appState.d.ts +12 -5
  79. package/dist/types/excalidraw/components/Actions.d.ts +17 -12
  80. package/dist/types/excalidraw/components/ActiveConfirmDialog.d.ts +1 -1
  81. package/dist/types/excalidraw/components/App.arrowText.d.ts +104 -0
  82. package/dist/types/excalidraw/components/App.bucketFill.d.ts +48 -0
  83. package/dist/types/excalidraw/components/App.cursor.d.ts +38 -0
  84. package/dist/types/excalidraw/components/App.d.ts +391 -68
  85. package/dist/types/excalidraw/components/App.drawshape.d.ts +55 -0
  86. package/dist/types/excalidraw/components/App.flowchart.d.ts +21 -0
  87. package/dist/types/excalidraw/components/App.viewport.d.ts +73 -0
  88. package/dist/types/excalidraw/components/ColorPicker/ColorPicker.d.ts +9 -3
  89. package/dist/types/excalidraw/components/ColorPicker/CustomColorList.d.ts +3 -1
  90. package/dist/types/excalidraw/components/ColorPicker/Picker.d.ts +3 -1
  91. package/dist/types/excalidraw/components/ColorPicker/PickerColorList.d.ts +9 -2
  92. package/dist/types/excalidraw/components/ColorPicker/ShadeList.d.ts +4 -2
  93. package/dist/types/excalidraw/components/ColorPicker/TopPicks.d.ts +8 -1
  94. package/dist/types/excalidraw/components/ColorPicker/colorPickerUtils.d.ts +1 -1
  95. package/dist/types/excalidraw/components/ColorPicker/keyboardNavHandlers.d.ts +2 -1
  96. package/dist/types/excalidraw/components/ColorPicker/topPicksDnD.d.ts +31 -0
  97. package/dist/types/excalidraw/components/CommandPalette/defaultCommandPaletteItems.d.ts +1 -2
  98. package/dist/types/excalidraw/components/ConvertElementTypePopup.d.ts +2 -2
  99. package/dist/types/excalidraw/components/CursorHint.d.ts +46 -0
  100. package/dist/types/excalidraw/components/EyeDropper.d.ts +1 -1
  101. package/dist/types/excalidraw/components/{ToolButton.d.ts → IconButton.d.ts} +16 -19
  102. package/dist/types/excalidraw/components/Island.d.ts +7 -0
  103. package/dist/types/excalidraw/components/LaserPointerButton.d.ts +2 -4
  104. package/dist/types/excalidraw/components/LayerUI.d.ts +5 -2
  105. package/dist/types/excalidraw/components/LibraryMenu.d.ts +1 -1
  106. package/dist/types/excalidraw/components/LockButton.d.ts +3 -4
  107. package/dist/types/excalidraw/components/MagicButton.d.ts +0 -2
  108. package/dist/types/excalidraw/components/MobileMenu.d.ts +4 -4
  109. package/dist/types/excalidraw/components/MobileToolbar.d.ts +9 -0
  110. package/dist/types/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.d.ts +1 -1
  111. package/dist/types/excalidraw/components/PenModeButton.d.ts +2 -5
  112. package/dist/types/excalidraw/components/Popover.d.ts +1 -3
  113. package/dist/types/excalidraw/components/{ButtonIcon.d.ts → RadioButton.d.ts} +2 -5
  114. package/dist/types/excalidraw/components/Range.d.ts +10 -4
  115. package/dist/types/excalidraw/components/SVGLayer.d.ts +1 -1
  116. package/dist/types/excalidraw/components/SearchMenu.d.ts +1 -1
  117. package/dist/types/excalidraw/components/Sidebar/Sidebar.d.ts +1 -1
  118. package/dist/types/excalidraw/components/Stats/Angle.d.ts +2 -2
  119. package/dist/types/excalidraw/components/Stats/Dimension.d.ts +2 -2
  120. package/dist/types/excalidraw/components/Stats/DragInput.d.ts +2 -2
  121. package/dist/types/excalidraw/components/Stats/MultiAngle.d.ts +2 -2
  122. package/dist/types/excalidraw/components/Stats/MultiDimension.d.ts +2 -2
  123. package/dist/types/excalidraw/components/Stats/MultiPosition.d.ts +2 -2
  124. package/dist/types/excalidraw/components/Stats/Position.d.ts +3 -3
  125. package/dist/types/excalidraw/components/Stats/utils.d.ts +1 -1
  126. package/dist/types/excalidraw/components/TTDDialog/TTDContext.d.ts +4 -4
  127. package/dist/types/excalidraw/components/TTDDialog/useTTDChatStorage.d.ts +3 -3
  128. package/dist/types/excalidraw/components/ToolPopover.d.ts +3 -6
  129. package/dist/types/excalidraw/components/Toolbar.d.ts +11 -0
  130. package/dist/types/excalidraw/components/Tools.d.ts +146 -0
  131. package/dist/types/excalidraw/components/UserList.d.ts +3 -2
  132. package/dist/types/excalidraw/components/ViewportStatusFrame/ViewportStatusFrame.d.ts +11 -0
  133. package/dist/types/excalidraw/components/canvases/InteractiveCanvas.d.ts +4 -1
  134. package/dist/types/excalidraw/components/canvases/NewElementCanvas.d.ts +1 -0
  135. package/dist/types/excalidraw/components/canvases/StaticCanvas.d.ts +1 -1
  136. package/dist/types/excalidraw/components/dropdownMenu/DropdownMenuItemContentRadio.d.ts +2 -1
  137. package/dist/types/excalidraw/components/footer/Footer.d.ts +3 -1
  138. package/dist/types/excalidraw/components/hyperlink/helpers.d.ts +2 -2
  139. package/dist/types/excalidraw/components/icons.d.ts +6 -1
  140. package/dist/types/excalidraw/components/main-menu/DefaultItems.d.ts +8 -4
  141. package/dist/types/excalidraw/components/positionElementBesideCursor.d.ts +26 -0
  142. package/dist/types/excalidraw/components/shapeActionPredicates.d.ts +39 -0
  143. package/dist/types/excalidraw/data/blob.d.ts +36 -18
  144. package/dist/types/excalidraw/data/index.d.ts +4 -4
  145. package/dist/types/excalidraw/data/json.d.ts +24 -15
  146. package/dist/types/excalidraw/data/library.d.ts +1 -1
  147. package/dist/types/excalidraw/drawShapeTrail.d.ts +16 -0
  148. package/dist/types/excalidraw/eraser/index.d.ts +2 -3
  149. package/dist/types/excalidraw/fonts/Fonts.d.ts +3 -2
  150. package/dist/types/excalidraw/hooks/useAppStateValue.d.ts +29 -0
  151. package/dist/types/excalidraw/hooks/useLibraryItemSvg.d.ts +1 -1
  152. package/dist/types/excalidraw/hooks/useTextEditorFocus.d.ts +5 -5
  153. package/dist/types/excalidraw/{laser-trails.d.ts → laserTrails.d.ts} +5 -7
  154. package/dist/types/excalidraw/lasso/index.d.ts +2 -3
  155. package/dist/types/excalidraw/lasso/utils.d.ts +2 -0
  156. package/dist/types/excalidraw/renderer/animation.d.ts +5 -1
  157. package/dist/types/excalidraw/renderer/helpers.d.ts +7 -0
  158. package/dist/types/excalidraw/renderer/interactiveScene.d.ts +1 -3
  159. package/dist/types/excalidraw/scene/Renderer.d.ts +427 -19
  160. package/dist/types/excalidraw/scene/export.d.ts +3 -3
  161. package/dist/types/excalidraw/scene/index.d.ts +2 -2
  162. package/dist/types/excalidraw/scene/types.d.ts +4 -3
  163. package/dist/types/excalidraw/snapping.d.ts +7 -7
  164. package/dist/types/excalidraw/textAutoResizeHandle.d.ts +15 -0
  165. package/dist/types/excalidraw/types.d.ts +436 -24
  166. package/dist/types/excalidraw/viewport.d.ts +275 -0
  167. package/dist/types/excalidraw/wysiwyg/textWysiwyg.d.ts +6 -3
  168. package/dist/types/fractional-indexing/src/index.d.ts +29 -0
  169. package/dist/types/laser-pointer/src/index.d.ts +2 -0
  170. package/dist/types/laser-pointer/src/math.d.ts +16 -0
  171. package/dist/types/laser-pointer/src/simplify.d.ts +2 -0
  172. package/dist/types/laser-pointer/src/state.d.ts +36 -0
  173. package/dist/types/math/src/constants.d.ts +0 -1
  174. package/dist/types/math/src/curve.d.ts +23 -13
  175. package/dist/types/math/src/index.d.ts +1 -0
  176. package/dist/types/math/src/pca.d.ts +79 -0
  177. package/dist/types/math/src/point.d.ts +2 -1
  178. package/dist/types/math/src/polygon.d.ts +25 -1
  179. package/dist/types/math/src/segment.d.ts +6 -0
  180. package/dist/types/utils/src/export.d.ts +3 -3
  181. package/dist/types/utils/src/index.d.ts +1 -2
  182. package/package.json +2 -2
  183. package/dist/types/excalidraw/animation-frame-handler.d.ts +0 -16
  184. package/dist/types/excalidraw/components/FollowMode/FollowMode.d.ts +0 -10
  185. package/dist/types/excalidraw/components/HandButton.d.ts +0 -10
  186. package/dist/types/excalidraw/components/MobileToolBar.d.ts +0 -10
  187. package/dist/types/excalidraw/components/shapes.d.ts +0 -263
  188. package/dist/types/excalidraw/cursor.d.ts +0 -5
  189. package/dist/types/excalidraw/scene/scroll.d.ts +0 -18
  190. package/dist/types/excalidraw/scene/zoom.d.ts +0 -12
  191. package/dist/types/utils/src/bbox.d.ts +0 -9
  192. package/dist/types/utils/src/withinBounds.d.ts +0 -19
package/dist/dev/index.js CHANGED
@@ -120,7 +120,12 @@ function pointsEqual(a, b, tolerance = PRECISION) {
120
120
  const abs = Math.abs;
121
121
  return abs(a[0] - b[0]) < tolerance && abs(a[1] - b[1]) < tolerance;
122
122
  }
123
- function pointRotateRads([x, y], [cx, cy], angle) {
123
+ function pointRotateRads(point, center, angle) {
124
+ if (!angle) {
125
+ return point;
126
+ }
127
+ const [x, y] = point;
128
+ const [cx, cy] = center;
124
129
  return pointFrom(
125
130
  (x - cx) * Math.cos(angle) - (y - cy) * Math.sin(angle) + cx,
126
131
  (x - cx) * Math.sin(angle) + (y - cy) * Math.cos(angle) + cy
@@ -147,6 +152,9 @@ var pointScaleFromOrigin = (p, mid, multiplier) => pointTranslate(mid, vectorSca
147
152
  var isPointWithinBounds = (p, q, r) => {
148
153
  return q[0] <= Math.max(p[0], r[0]) && q[0] >= Math.min(p[0], r[0]) && q[1] <= Math.max(p[1], r[1]) && q[1] >= Math.min(p[1], r[1]);
149
154
  };
155
+ var isValidPoint = (point) => {
156
+ return Array.isArray(point) && point.length === 2 && isFiniteNumber(point[0]) && isFiniteNumber(point[1]);
157
+ };
150
158
 
151
159
  // src/constants.ts
152
160
  var LegendreGaussN24TValues = [
@@ -254,8 +262,15 @@ var initial_guesses = [
254
262
  [0.2, 0],
255
263
  [0.8, 0]
256
264
  ];
257
- var calculate = ([t0, s0], l, c) => {
258
- const solution = solveWithAnalyticalJacobian(c, l, t0, s0, 0.01, 4);
265
+ var calculate = ([t0, s0], l, c, tolerance = 0.01, iterLimit = 4) => {
266
+ const solution = solveWithAnalyticalJacobian(
267
+ c,
268
+ l,
269
+ t0,
270
+ s0,
271
+ tolerance,
272
+ iterLimit
273
+ );
259
274
  if (!solution) {
260
275
  return null;
261
276
  }
@@ -265,22 +280,40 @@ var calculate = ([t0, s0], l, c) => {
265
280
  }
266
281
  return bezierEquation(c, t);
267
282
  };
268
- function curveIntersectLineSegment(c, l) {
269
- let solution = calculate(initial_guesses[0], l, c);
283
+ function curveIntersectLineSegment(c, l, opts) {
284
+ let solution = calculate(
285
+ initial_guesses[0],
286
+ l,
287
+ c,
288
+ opts?.tolerance,
289
+ opts?.iterLimit
290
+ );
270
291
  if (solution) {
271
292
  return [solution];
272
293
  }
273
- solution = calculate(initial_guesses[1], l, c);
294
+ solution = calculate(
295
+ initial_guesses[1],
296
+ l,
297
+ c,
298
+ opts?.tolerance,
299
+ opts?.iterLimit
300
+ );
274
301
  if (solution) {
275
302
  return [solution];
276
303
  }
277
- solution = calculate(initial_guesses[2], l, c);
304
+ solution = calculate(
305
+ initial_guesses[2],
306
+ l,
307
+ c,
308
+ opts?.tolerance,
309
+ opts?.iterLimit
310
+ );
278
311
  if (solution) {
279
312
  return [solution];
280
313
  }
281
314
  return [];
282
315
  }
283
- function curveClosestPoint(c, p, tolerance = 1e-3) {
316
+ function curveClosestParameter(c, p, tolerance = 1e-3) {
284
317
  const localMinimum = (min, max, f, e = tolerance) => {
285
318
  let m = min;
286
319
  let n = max;
@@ -297,7 +330,7 @@ function curveClosestPoint(c, p, tolerance = 1e-3) {
297
330
  };
298
331
  const maxSteps = 30;
299
332
  let closestStep = 0;
300
- for (let min = Infinity, step = 0; step < maxSteps; step++) {
333
+ for (let min = Infinity, step = 0; step <= maxSteps; step++) {
301
334
  const d = pointDistance(p, bezierEquation(c, step / maxSteps));
302
335
  if (d < min) {
303
336
  min = d;
@@ -306,22 +339,18 @@ function curveClosestPoint(c, p, tolerance = 1e-3) {
306
339
  }
307
340
  const t0 = Math.max((closestStep - 1) / maxSteps, 0);
308
341
  const t1 = Math.min((closestStep + 1) / maxSteps, 1);
309
- const solution = localMinimum(
342
+ const param = localMinimum(
310
343
  t0,
311
344
  t1,
312
345
  (t) => pointDistance(p, bezierEquation(c, t))
313
346
  );
314
- if (!solution) {
315
- return null;
316
- }
317
- return bezierEquation(c, solution);
347
+ return param ?? closestStep / maxSteps;
318
348
  }
319
- function curvePointDistance(c, p) {
320
- const closest = curveClosestPoint(c, p);
321
- if (!closest) {
322
- return 0;
323
- }
324
- return pointDistance(p, closest);
349
+ function curveClosestPoint(c, p, tolerance = 1e-3) {
350
+ return bezierEquation(c, curveClosestParameter(c, p, tolerance));
351
+ }
352
+ function curvePointDistance(c, p, tolerance = 1e-3) {
353
+ return pointDistance(p, curveClosestPoint(c, p, tolerance));
325
354
  }
326
355
  function isCurve(v) {
327
356
  return Array.isArray(v) && v.length === 4 && isPoint(v[0]) && isPoint(v[1]) && isPoint(v[2]) && isPoint(v[3]);
@@ -439,14 +468,13 @@ function curveLengthAtParameter(c, t) {
439
468
  }
440
469
  return z1 * sum;
441
470
  }
442
- function curvePointAtLength(c, percent) {
471
+ function curvePointAtLength(c, percent, totalLength = curveLength(c)) {
443
472
  if (percent <= 0) {
444
473
  return bezierEquation(c, 0);
445
474
  }
446
475
  if (percent >= 1) {
447
476
  return bezierEquation(c, 1);
448
477
  }
449
- const totalLength = curveLength(c);
450
478
  const targetLength = totalLength * percent;
451
479
  let tMin = 0;
452
480
  let tMax = 1;
@@ -605,93 +633,98 @@ function linesIntersectAt(a, b) {
605
633
  return null;
606
634
  }
607
635
 
608
- // src/segment.ts
609
- function lineSegment(a, b) {
610
- return [a, b];
611
- }
612
- var isLineSegment = (segment) => Array.isArray(segment) && segment.length === 2 && isPoint(segment[0]) && isPoint(segment[0]);
613
- var lineSegmentRotate = (l, angle, origin) => {
614
- return lineSegment(
615
- pointRotateRads(l[0], origin || pointCenter(l[0], l[1]), angle),
616
- pointRotateRads(l[1], origin || pointCenter(l[0], l[1]), angle)
617
- );
618
- };
619
- var segmentsIntersectAt = (a, b) => {
620
- const a0 = vectorFromPoint(a[0]);
621
- const a1 = vectorFromPoint(a[1]);
622
- const b0 = vectorFromPoint(b[0]);
623
- const b1 = vectorFromPoint(b[1]);
624
- const r = vectorSubtract(a1, a0);
625
- const s = vectorSubtract(b1, b0);
626
- const denominator = vectorCross(r, s);
627
- if (denominator === 0) {
628
- return null;
629
- }
630
- const i = vectorSubtract(vectorFromPoint(b[0]), vectorFromPoint(a[0]));
631
- const u = vectorCross(i, r) / denominator;
632
- const t = vectorCross(i, s) / denominator;
633
- if (u === 0) {
634
- return null;
635
- }
636
- const p = vectorAdd(a0, vectorScale(r, t));
637
- if (t >= 0 && t < 1 && u >= 0 && u < 1) {
638
- return pointFromVector(p);
636
+ // src/pca.ts
637
+ function centroid(points) {
638
+ let cx = 0;
639
+ let cy = 0;
640
+ for (const [x, y] of points) {
641
+ cx += x;
642
+ cy += y;
639
643
  }
640
- return null;
641
- };
642
- var pointOnLineSegment = (point, line2, threshold = PRECISION) => {
643
- const distance = distanceToLineSegment(point, line2);
644
- if (distance === 0) {
645
- return true;
644
+ return pointFrom(cx / points.length, cy / points.length);
645
+ }
646
+ function principalAxes(points) {
647
+ if (points.length < 2) {
648
+ console.error("Degenerate point set: at least two points are required");
646
649
  }
647
- return distance < threshold;
648
- };
649
- var distanceToLineSegment = (point, line2) => {
650
- const [x, y] = point;
651
- const [[x1, y1], [x2, y2]] = line2;
652
- const A = x - x1;
653
- const B = y - y1;
654
- const C = x2 - x1;
655
- const D = y2 - y1;
656
- const dot = A * C + B * D;
657
- const len_sq = C * C + D * D;
658
- let param = -1;
659
- if (len_sq !== 0) {
660
- param = dot / len_sq;
650
+ const c = centroid(points);
651
+ let m20 = 0;
652
+ let m02 = 0;
653
+ let m11 = 0;
654
+ for (const [x, y] of points) {
655
+ const dx = x - c[0];
656
+ const dy = y - c[1];
657
+ m20 += dx * dx;
658
+ m02 += dy * dy;
659
+ m11 += dx * dy;
661
660
  }
662
- let xx;
663
- let yy;
664
- if (param < 0) {
665
- xx = x1;
666
- yy = y1;
667
- } else if (param > 1) {
668
- xx = x2;
669
- yy = y2;
661
+ m20 /= points.length;
662
+ m02 /= points.length;
663
+ m11 /= points.length;
664
+ const trace = m20 + m02;
665
+ const diff = Math.hypot(m20 - m02, 2 * m11);
666
+ const majorVariance = (trace + diff) / 2;
667
+ const minorVariance = (trace - diff) / 2;
668
+ let major;
669
+ if (Math.abs(m11) > Number.EPSILON) {
670
+ major = vectorNormalize(vector(majorVariance - m02, m11));
670
671
  } else {
671
- xx = x1 + param * C;
672
- yy = y1 + param * D;
672
+ major = m20 >= m02 ? vector(1, 0) : vector(0, 1);
673
673
  }
674
- const dx = x - xx;
675
- const dy = y - yy;
676
- return Math.sqrt(dx * dx + dy * dy);
677
- };
678
- function lineSegmentIntersectionPoints(l, s, threshold) {
679
- const candidate = linesIntersectAt(line(l[0], l[1]), line(s[0], s[1]));
680
- if (!candidate || !pointOnLineSegment(candidate, s, threshold) || !pointOnLineSegment(candidate, l, threshold)) {
681
- return null;
674
+ return {
675
+ centroid: c,
676
+ major,
677
+ minor: vectorNormal(major),
678
+ majorVariance,
679
+ minorVariance
680
+ };
681
+ }
682
+ function principalCoords(points, axes, scale = 1) {
683
+ const { centroid: c, major, minor } = axes;
684
+ return points.map(([x, y]) => {
685
+ const dx = x - c[0];
686
+ const dy = y - c[1];
687
+ return [
688
+ (dx * major[0] + dy * major[1]) * scale,
689
+ (dx * minor[0] + dy * minor[1]) * scale
690
+ ];
691
+ });
692
+ }
693
+ function orientPrincipalAxes(points, axes) {
694
+ const u = principalCoords(points, axes).map(([uu]) => uu);
695
+ if (skewness(u) <= 0) {
696
+ return axes;
682
697
  }
683
- return candidate;
698
+ const major = vectorScale(axes.major, -1);
699
+ return { ...axes, major, minor: vectorNormal(major) };
684
700
  }
685
- function lineSegmentsDistance(s1, s2) {
686
- if (lineSegmentIntersectionPoints(s1, s2)) {
687
- return 0;
701
+ function elongation(axes) {
702
+ return axes.majorVariance > 0 ? axes.minorVariance / axes.majorVariance : 1;
703
+ }
704
+ function standardizedMoment(values, order) {
705
+ const n = values.length;
706
+ let mean = 0;
707
+ for (const v of values) {
708
+ mean += v;
688
709
  }
689
- return Math.min(
690
- distanceToLineSegment(s1[0], s2),
691
- distanceToLineSegment(s1[1], s2),
692
- distanceToLineSegment(s2[0], s1),
693
- distanceToLineSegment(s2[1], s1)
694
- );
710
+ mean /= n;
711
+ let variance = 0;
712
+ let moment = 0;
713
+ for (const v of values) {
714
+ const d = v - mean;
715
+ variance += d * d;
716
+ moment += d ** order;
717
+ }
718
+ variance /= n;
719
+ moment /= n;
720
+ const sigma = Math.sqrt(variance);
721
+ return sigma > Number.EPSILON ? moment / sigma ** order : 0;
722
+ }
723
+ function skewness(values) {
724
+ return standardizedMoment(values, 3);
725
+ }
726
+ function kurtosis(values) {
727
+ return standardizedMoment(values, 4);
695
728
  }
696
729
 
697
730
  // src/polygon.ts
@@ -737,21 +770,84 @@ var polygonIncludesPointNonZero = (point, polygon2) => {
737
770
  }
738
771
  return windingNumber !== 0;
739
772
  };
740
- var pointOnPolygon = (p, poly, threshold = PRECISION) => {
741
- let on = false;
742
- for (let i = 0, l = poly.length - 1; i < l; i++) {
743
- if (pointOnLineSegment(p, lineSegment(poly[i], poly[i + 1]), threshold)) {
744
- on = true;
745
- break;
746
- }
747
- }
748
- return on;
749
- };
750
773
  function polygonClose(polygon2) {
751
774
  return polygonIsClosed(polygon2) ? polygon2 : [...polygon2, polygon2[0]];
752
775
  }
753
- function polygonIsClosed(polygon2) {
754
- return pointsEqual(polygon2[0], polygon2[polygon2.length - 1]);
776
+ function polygonIsClosed(polygon2, tolerance = PRECISION) {
777
+ return pointsEqual(polygon2[0], polygon2[polygon2.length - 1], tolerance);
778
+ }
779
+ function polygonSignedArea(polygon2, tolerance = PRECISION) {
780
+ const pts = polygonIsClosed(polygon2, tolerance) ? polygon2.slice(0, -1) : polygon2;
781
+ let sum = 0;
782
+ for (let i = 0, j = pts.length - 1; i < pts.length; j = i++) {
783
+ sum += pts[j][0] * pts[i][1] - pts[i][0] * pts[j][1];
784
+ }
785
+ return sum / 2;
786
+ }
787
+ function polygonArea(polygon2, tolerance = PRECISION) {
788
+ return Math.abs(polygonSignedArea(polygon2, tolerance));
789
+ }
790
+ function convexHull(points) {
791
+ if (points.length < 3) {
792
+ return [...points];
793
+ }
794
+ const sorted = [...points].sort(
795
+ (a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]
796
+ );
797
+ const cross = (o, a, b) => (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
798
+ const half = (pts) => {
799
+ const chain = [];
800
+ for (const p of pts) {
801
+ while (chain.length >= 2 && cross(chain[chain.length - 2], chain[chain.length - 1], p) <= 0) {
802
+ chain.pop();
803
+ }
804
+ chain.push(p);
805
+ }
806
+ chain.pop();
807
+ return chain;
808
+ };
809
+ const hull = [...half(sorted), ...half([...sorted].reverse())];
810
+ return hull.length >= 3 ? hull : [...points];
811
+ }
812
+ function simplifyConvexPolygon(polygon2, angleThreshold) {
813
+ if (polygon2.length < 3) {
814
+ return [...polygon2];
815
+ }
816
+ const turnAt = (i) => {
817
+ const prev = polygon2[(i - 1 + polygon2.length) % polygon2.length];
818
+ const curr = polygon2[i];
819
+ const next = polygon2[(i + 1) % polygon2.length];
820
+ const inAngle = Math.atan2(curr[1] - prev[1], curr[0] - prev[0]);
821
+ const outAngle = Math.atan2(next[1] - curr[1], next[0] - curr[0]);
822
+ return Math.abs(normalizeTurn(outAngle - inAngle));
823
+ };
824
+ let start = 0;
825
+ for (let i = 1; i < polygon2.length; i++) {
826
+ if (turnAt(i) > turnAt(start)) {
827
+ start = i;
828
+ }
829
+ }
830
+ const simplified = [];
831
+ let accumulated = 0;
832
+ for (let k = 0; k < polygon2.length; k++) {
833
+ const i = (start + k) % polygon2.length;
834
+ accumulated += turnAt(i);
835
+ if (accumulated >= angleThreshold) {
836
+ simplified.push(polygon2[i]);
837
+ accumulated = 0;
838
+ }
839
+ }
840
+ return simplified.length >= 3 ? simplified : [...polygon2];
841
+ }
842
+ function normalizeTurn(angle) {
843
+ let a = angle;
844
+ while (a > Math.PI) {
845
+ a -= 2 * Math.PI;
846
+ }
847
+ while (a < -Math.PI) {
848
+ a += 2 * Math.PI;
849
+ }
850
+ return a;
755
851
  }
756
852
 
757
853
  // src/range.ts
@@ -783,6 +879,91 @@ var rangeIncludesValue = (value, [min, max]) => {
783
879
  return value >= min && value <= max;
784
880
  };
785
881
 
882
+ // src/segment.ts
883
+ function lineSegment(a, b) {
884
+ return [a, b];
885
+ }
886
+ var isLineSegment = (segment) => Array.isArray(segment) && segment.length === 2 && isPoint(segment[0]) && isPoint(segment[1]);
887
+ var lineSegmentRotate = (l, angle, origin) => {
888
+ return lineSegment(
889
+ pointRotateRads(l[0], origin || pointCenter(l[0], l[1]), angle),
890
+ pointRotateRads(l[1], origin || pointCenter(l[0], l[1]), angle)
891
+ );
892
+ };
893
+ var segmentsIntersectAt = (a, b) => {
894
+ const a0 = vectorFromPoint(a[0]);
895
+ const a1 = vectorFromPoint(a[1]);
896
+ const b0 = vectorFromPoint(b[0]);
897
+ const b1 = vectorFromPoint(b[1]);
898
+ const r = vectorSubtract(a1, a0);
899
+ const s = vectorSubtract(b1, b0);
900
+ const denominator = vectorCross(r, s);
901
+ if (denominator === 0) {
902
+ return null;
903
+ }
904
+ const i = vectorSubtract(vectorFromPoint(b[0]), vectorFromPoint(a[0]));
905
+ const u = vectorCross(i, r) / denominator;
906
+ const t = vectorCross(i, s) / denominator;
907
+ if (u === 0) {
908
+ return null;
909
+ }
910
+ const p = vectorAdd(a0, vectorScale(r, t));
911
+ if (t >= 0 && t < 1 && u >= 0 && u < 1) {
912
+ return pointFromVector(p);
913
+ }
914
+ return null;
915
+ };
916
+ var pointOnLineSegment = (point, line2, threshold = PRECISION) => {
917
+ const distance = distanceToLineSegment(point, line2);
918
+ if (distance === 0) {
919
+ return true;
920
+ }
921
+ return distance < threshold;
922
+ };
923
+ var distanceToLineSegment = (point, line2) => {
924
+ return pointDistance(
925
+ point,
926
+ lineSegmentPointAt(line2, lineSegmentClosestParameter(point, line2))
927
+ );
928
+ };
929
+ function lineSegmentPointAt(line2, t) {
930
+ const [[x1, y1], [x2, y2]] = line2;
931
+ return pointFrom(x1 + t * (x2 - x1), y1 + t * (y2 - y1));
932
+ }
933
+ function lineSegmentIntersectionPoints(l, s, threshold) {
934
+ const candidate = linesIntersectAt(line(l[0], l[1]), line(s[0], s[1]));
935
+ if (!candidate || !pointOnLineSegment(candidate, s, threshold) || !pointOnLineSegment(candidate, l, threshold)) {
936
+ return null;
937
+ }
938
+ return candidate;
939
+ }
940
+ function lineSegmentsDistance(s1, s2) {
941
+ if (lineSegmentIntersectionPoints(s1, s2)) {
942
+ return 0;
943
+ }
944
+ return Math.min(
945
+ distanceToLineSegment(s1[0], s2),
946
+ distanceToLineSegment(s1[1], s2),
947
+ distanceToLineSegment(s2[0], s1),
948
+ distanceToLineSegment(s2[1], s1)
949
+ );
950
+ }
951
+ function lineSegmentClosestParameter(point, line2) {
952
+ const [x, y] = point;
953
+ const [[x1, y1], [x2, y2]] = line2;
954
+ const A = x - x1;
955
+ const B = y - y1;
956
+ const C = x2 - x1;
957
+ const D = y2 - y1;
958
+ const dot = A * C + B * D;
959
+ const len_sq = C * C + D * D;
960
+ let param = 0;
961
+ if (len_sq !== 0) {
962
+ param = dot / len_sq;
963
+ }
964
+ return Math.max(0, Math.min(1, param));
965
+ }
966
+
786
967
  // src/rectangle.ts
787
968
  function rectangle(topLeft, bottomRight) {
788
969
  return [topLeft, bottomRight];
@@ -819,10 +1000,13 @@ export {
819
1000
  average,
820
1001
  bezierEquation,
821
1002
  cartesian2Polar,
1003
+ centroid,
822
1004
  clamp,
1005
+ convexHull,
823
1006
  curve,
824
1007
  curveCatmullRomCubicApproxPoints,
825
1008
  curveCatmullRomQuadraticApproxPoints,
1009
+ curveClosestParameter,
826
1010
  curveClosestPoint,
827
1011
  curveIntersectLineSegment,
828
1012
  curveLength,
@@ -839,6 +1023,7 @@ export {
839
1023
  ellipseLineIntersectionPoints,
840
1024
  ellipseSegmentInterceptPoints,
841
1025
  ellipseTouchesPoint,
1026
+ elongation,
842
1027
  isCloseTo,
843
1028
  isCurve,
844
1029
  isFiniteNumber,
@@ -846,15 +1031,20 @@ export {
846
1031
  isPoint,
847
1032
  isPointWithinBounds,
848
1033
  isRightAngleRads,
1034
+ isValidPoint,
849
1035
  isVector,
1036
+ kurtosis,
850
1037
  line,
851
1038
  lineSegment,
1039
+ lineSegmentClosestParameter,
852
1040
  lineSegmentIntersectionPoints,
1041
+ lineSegmentPointAt,
853
1042
  lineSegmentRotate,
854
1043
  lineSegmentsDistance,
855
1044
  linesIntersectAt,
856
1045
  normalizeRadians,
857
1046
  offsetPointsForQuadraticBezier,
1047
+ orientPrincipalAxes,
858
1048
  pointCenter,
859
1049
  pointDistance,
860
1050
  pointDistanceSq,
@@ -863,16 +1053,20 @@ export {
863
1053
  pointFromPair,
864
1054
  pointFromVector,
865
1055
  pointOnLineSegment,
866
- pointOnPolygon,
867
1056
  pointRotateDegs,
868
1057
  pointRotateRads,
869
1058
  pointScaleFromOrigin,
870
1059
  pointTranslate,
871
1060
  pointsEqual,
872
1061
  polygon,
1062
+ polygonArea,
873
1063
  polygonFromPoints,
874
1064
  polygonIncludesPoint,
875
1065
  polygonIncludesPointNonZero,
1066
+ polygonIsClosed,
1067
+ polygonSignedArea,
1068
+ principalAxes,
1069
+ principalCoords,
876
1070
  radiansBetweenAngles,
877
1071
  radiansDifference,
878
1072
  radiansToDegrees,
@@ -888,6 +1082,9 @@ export {
888
1082
  round,
889
1083
  roundToStep,
890
1084
  segmentsIntersectAt,
1085
+ simplifyConvexPolygon,
1086
+ skewness,
1087
+ standardizedMoment,
891
1088
  triangleIncludesPoint,
892
1089
  vector,
893
1090
  vectorAdd,