@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.
- package/dist/dev/index.js +311 -114
- package/dist/dev/index.js.map +4 -4
- package/dist/prod/index.js +1 -1
- package/dist/types/common/src/colors.d.ts +20 -1
- package/dist/types/common/src/constants.d.ts +12 -7
- package/dist/types/common/src/keys.d.ts +2 -0
- package/dist/types/common/src/points.d.ts +1 -1
- package/dist/types/common/src/utils.d.ts +1 -43
- package/dist/types/element/src/Scene.d.ts +6 -4
- package/dist/types/element/src/align.d.ts +2 -2
- package/dist/types/element/src/arrowEndpointText.d.ts +49 -0
- package/dist/types/element/src/arrows/focus.d.ts +5 -2
- package/dist/types/element/src/binding.d.ts +17 -8
- package/dist/types/element/src/bounds.d.ts +22 -7
- package/dist/types/element/src/bucketFill.d.ts +110 -0
- package/dist/types/element/src/collision.d.ts +1 -1
- package/dist/types/element/src/comparisons.d.ts +5 -4
- package/dist/types/element/src/convertToShape.d.ts +23 -0
- package/dist/types/element/src/distribute.d.ts +2 -2
- package/dist/types/element/src/dragElements.d.ts +27 -0
- package/dist/types/element/src/duplicate.d.ts +4 -3
- package/dist/types/element/src/embeddable.d.ts +2 -2
- package/dist/types/element/src/flowchart.d.ts +7 -7
- package/dist/types/element/src/fractionalIndex.d.ts +2 -2
- package/dist/types/element/src/frame.d.ts +9 -8
- package/dist/types/element/src/groups.d.ts +9 -9
- package/dist/types/element/src/index.d.ts +4 -1
- package/dist/types/element/src/linearElementEditor.d.ts +27 -10
- package/dist/types/element/src/newElement.d.ts +15 -0
- package/dist/types/element/src/renderElement.d.ts +0 -3
- package/dist/types/element/src/resizeElements.d.ts +2 -2
- package/dist/types/element/src/selection.d.ts +11 -7
- package/dist/types/element/src/shape.d.ts +13 -1
- package/dist/types/element/src/sortElements.d.ts +10 -0
- package/dist/types/element/src/textElement.d.ts +14 -10
- package/dist/types/element/src/textWrapping.d.ts +26 -0
- package/dist/types/element/src/transform.d.ts +2 -2
- package/dist/types/element/src/typeChecks.d.ts +26 -25
- package/dist/types/element/src/types.d.ts +15 -1
- package/dist/types/element/src/utils.d.ts +7 -3
- package/dist/types/element/src/zindex.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionAddToLibrary.d.ts +48 -21
- package/dist/types/excalidraw/actions/actionAlign.d.ts +6 -6
- package/dist/types/excalidraw/actions/actionBoundText.d.ts +33 -15
- package/dist/types/excalidraw/actions/actionCanvas.d.ts +174 -947
- package/dist/types/excalidraw/actions/actionClipboard.d.ts +32 -14
- package/dist/types/excalidraw/actions/actionCropEditor.d.ts +16 -7
- package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +50 -22
- package/dist/types/excalidraw/actions/{actionEmbeddable.d.ts → actionDeselect.d.ts} +30 -36
- package/dist/types/excalidraw/actions/actionDistribute.d.ts +2 -3
- package/dist/types/excalidraw/actions/actionElementLink.d.ts +16 -7
- package/dist/types/excalidraw/actions/actionElementLock.d.ts +33 -15
- package/dist/types/excalidraw/actions/actionExport.d.ts +34 -16
- package/dist/types/excalidraw/actions/actionFinalize.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionFrame.d.ts +61 -205
- package/dist/types/excalidraw/actions/actionGroup.d.ts +48 -30
- package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +21 -9
- package/dist/types/excalidraw/actions/actionLink.d.ts +17 -8
- package/dist/types/excalidraw/actions/actionMenu.d.ts +16 -7
- package/dist/types/excalidraw/actions/actionProperties.d.ts +62 -32
- package/dist/types/excalidraw/actions/actionSelectAll.d.ts +21 -12
- package/dist/types/excalidraw/actions/actionStyles.d.ts +17 -7
- package/dist/types/excalidraw/actions/actionTextAutoResize.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionToggleArrowBinding.d.ts +17 -8
- package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +20 -12
- package/dist/types/excalidraw/actions/actionToggleMidpointSnapping.d.ts +17 -8
- package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +17 -8
- package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +20 -12
- package/dist/types/excalidraw/actions/actionToggleShapeSwitch.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleStats.d.ts +17 -8
- package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +18 -9
- package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +17 -8
- package/dist/types/excalidraw/actions/index.d.ts +2 -2
- package/dist/types/excalidraw/actions/manager.d.ts +1 -0
- package/dist/types/excalidraw/actions/shortcuts.d.ts +1 -1
- package/dist/types/excalidraw/actions/types.d.ts +8 -4
- package/dist/types/excalidraw/{animated-trail.d.ts → animatedTrail.d.ts} +4 -3
- package/dist/types/excalidraw/appState.d.ts +12 -5
- package/dist/types/excalidraw/components/Actions.d.ts +17 -12
- package/dist/types/excalidraw/components/ActiveConfirmDialog.d.ts +1 -1
- package/dist/types/excalidraw/components/App.arrowText.d.ts +104 -0
- package/dist/types/excalidraw/components/App.bucketFill.d.ts +48 -0
- package/dist/types/excalidraw/components/App.cursor.d.ts +38 -0
- package/dist/types/excalidraw/components/App.d.ts +391 -68
- package/dist/types/excalidraw/components/App.drawshape.d.ts +55 -0
- package/dist/types/excalidraw/components/App.flowchart.d.ts +21 -0
- package/dist/types/excalidraw/components/App.viewport.d.ts +73 -0
- package/dist/types/excalidraw/components/ColorPicker/ColorPicker.d.ts +9 -3
- package/dist/types/excalidraw/components/ColorPicker/CustomColorList.d.ts +3 -1
- package/dist/types/excalidraw/components/ColorPicker/Picker.d.ts +3 -1
- package/dist/types/excalidraw/components/ColorPicker/PickerColorList.d.ts +9 -2
- package/dist/types/excalidraw/components/ColorPicker/ShadeList.d.ts +4 -2
- package/dist/types/excalidraw/components/ColorPicker/TopPicks.d.ts +8 -1
- package/dist/types/excalidraw/components/ColorPicker/colorPickerUtils.d.ts +1 -1
- package/dist/types/excalidraw/components/ColorPicker/keyboardNavHandlers.d.ts +2 -1
- package/dist/types/excalidraw/components/ColorPicker/topPicksDnD.d.ts +31 -0
- package/dist/types/excalidraw/components/CommandPalette/defaultCommandPaletteItems.d.ts +1 -2
- package/dist/types/excalidraw/components/ConvertElementTypePopup.d.ts +2 -2
- package/dist/types/excalidraw/components/CursorHint.d.ts +46 -0
- package/dist/types/excalidraw/components/EyeDropper.d.ts +1 -1
- package/dist/types/excalidraw/components/{ToolButton.d.ts → IconButton.d.ts} +16 -19
- package/dist/types/excalidraw/components/Island.d.ts +7 -0
- package/dist/types/excalidraw/components/LaserPointerButton.d.ts +2 -4
- package/dist/types/excalidraw/components/LayerUI.d.ts +5 -2
- package/dist/types/excalidraw/components/LibraryMenu.d.ts +1 -1
- package/dist/types/excalidraw/components/LockButton.d.ts +3 -4
- package/dist/types/excalidraw/components/MagicButton.d.ts +0 -2
- package/dist/types/excalidraw/components/MobileMenu.d.ts +4 -4
- package/dist/types/excalidraw/components/MobileToolbar.d.ts +9 -0
- package/dist/types/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.d.ts +1 -1
- package/dist/types/excalidraw/components/PenModeButton.d.ts +2 -5
- package/dist/types/excalidraw/components/Popover.d.ts +1 -3
- package/dist/types/excalidraw/components/{ButtonIcon.d.ts → RadioButton.d.ts} +2 -5
- package/dist/types/excalidraw/components/Range.d.ts +10 -4
- package/dist/types/excalidraw/components/SVGLayer.d.ts +1 -1
- package/dist/types/excalidraw/components/SearchMenu.d.ts +1 -1
- package/dist/types/excalidraw/components/Sidebar/Sidebar.d.ts +1 -1
- package/dist/types/excalidraw/components/Stats/Angle.d.ts +2 -2
- package/dist/types/excalidraw/components/Stats/Dimension.d.ts +2 -2
- package/dist/types/excalidraw/components/Stats/DragInput.d.ts +2 -2
- package/dist/types/excalidraw/components/Stats/MultiAngle.d.ts +2 -2
- package/dist/types/excalidraw/components/Stats/MultiDimension.d.ts +2 -2
- package/dist/types/excalidraw/components/Stats/MultiPosition.d.ts +2 -2
- package/dist/types/excalidraw/components/Stats/Position.d.ts +3 -3
- package/dist/types/excalidraw/components/Stats/utils.d.ts +1 -1
- package/dist/types/excalidraw/components/TTDDialog/TTDContext.d.ts +4 -4
- package/dist/types/excalidraw/components/TTDDialog/useTTDChatStorage.d.ts +3 -3
- package/dist/types/excalidraw/components/ToolPopover.d.ts +3 -6
- package/dist/types/excalidraw/components/Toolbar.d.ts +11 -0
- package/dist/types/excalidraw/components/Tools.d.ts +146 -0
- package/dist/types/excalidraw/components/UserList.d.ts +3 -2
- package/dist/types/excalidraw/components/ViewportStatusFrame/ViewportStatusFrame.d.ts +11 -0
- package/dist/types/excalidraw/components/canvases/InteractiveCanvas.d.ts +4 -1
- package/dist/types/excalidraw/components/canvases/NewElementCanvas.d.ts +1 -0
- package/dist/types/excalidraw/components/canvases/StaticCanvas.d.ts +1 -1
- package/dist/types/excalidraw/components/dropdownMenu/DropdownMenuItemContentRadio.d.ts +2 -1
- package/dist/types/excalidraw/components/footer/Footer.d.ts +3 -1
- package/dist/types/excalidraw/components/hyperlink/helpers.d.ts +2 -2
- package/dist/types/excalidraw/components/icons.d.ts +6 -1
- package/dist/types/excalidraw/components/main-menu/DefaultItems.d.ts +8 -4
- package/dist/types/excalidraw/components/positionElementBesideCursor.d.ts +26 -0
- package/dist/types/excalidraw/components/shapeActionPredicates.d.ts +39 -0
- package/dist/types/excalidraw/data/blob.d.ts +36 -18
- package/dist/types/excalidraw/data/index.d.ts +4 -4
- package/dist/types/excalidraw/data/json.d.ts +24 -15
- package/dist/types/excalidraw/data/library.d.ts +1 -1
- package/dist/types/excalidraw/drawShapeTrail.d.ts +16 -0
- package/dist/types/excalidraw/eraser/index.d.ts +2 -3
- package/dist/types/excalidraw/fonts/Fonts.d.ts +3 -2
- package/dist/types/excalidraw/hooks/useAppStateValue.d.ts +29 -0
- package/dist/types/excalidraw/hooks/useLibraryItemSvg.d.ts +1 -1
- package/dist/types/excalidraw/hooks/useTextEditorFocus.d.ts +5 -5
- package/dist/types/excalidraw/{laser-trails.d.ts → laserTrails.d.ts} +5 -7
- package/dist/types/excalidraw/lasso/index.d.ts +2 -3
- package/dist/types/excalidraw/lasso/utils.d.ts +2 -0
- package/dist/types/excalidraw/renderer/animation.d.ts +5 -1
- package/dist/types/excalidraw/renderer/helpers.d.ts +7 -0
- package/dist/types/excalidraw/renderer/interactiveScene.d.ts +1 -3
- package/dist/types/excalidraw/scene/Renderer.d.ts +427 -19
- package/dist/types/excalidraw/scene/export.d.ts +3 -3
- package/dist/types/excalidraw/scene/index.d.ts +2 -2
- package/dist/types/excalidraw/scene/types.d.ts +4 -3
- package/dist/types/excalidraw/snapping.d.ts +7 -7
- package/dist/types/excalidraw/textAutoResizeHandle.d.ts +15 -0
- package/dist/types/excalidraw/types.d.ts +436 -24
- package/dist/types/excalidraw/viewport.d.ts +275 -0
- package/dist/types/excalidraw/wysiwyg/textWysiwyg.d.ts +6 -3
- package/dist/types/fractional-indexing/src/index.d.ts +29 -0
- package/dist/types/laser-pointer/src/index.d.ts +2 -0
- package/dist/types/laser-pointer/src/math.d.ts +16 -0
- package/dist/types/laser-pointer/src/simplify.d.ts +2 -0
- package/dist/types/laser-pointer/src/state.d.ts +36 -0
- package/dist/types/math/src/constants.d.ts +0 -1
- package/dist/types/math/src/curve.d.ts +23 -13
- package/dist/types/math/src/index.d.ts +1 -0
- package/dist/types/math/src/pca.d.ts +79 -0
- package/dist/types/math/src/point.d.ts +2 -1
- package/dist/types/math/src/polygon.d.ts +25 -1
- package/dist/types/math/src/segment.d.ts +6 -0
- package/dist/types/utils/src/export.d.ts +3 -3
- package/dist/types/utils/src/index.d.ts +1 -2
- package/package.json +2 -2
- package/dist/types/excalidraw/animation-frame-handler.d.ts +0 -16
- package/dist/types/excalidraw/components/FollowMode/FollowMode.d.ts +0 -10
- package/dist/types/excalidraw/components/HandButton.d.ts +0 -10
- package/dist/types/excalidraw/components/MobileToolBar.d.ts +0 -10
- package/dist/types/excalidraw/components/shapes.d.ts +0 -263
- package/dist/types/excalidraw/cursor.d.ts +0 -5
- package/dist/types/excalidraw/scene/scroll.d.ts +0 -18
- package/dist/types/excalidraw/scene/zoom.d.ts +0 -12
- package/dist/types/utils/src/bbox.d.ts +0 -9
- 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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
342
|
+
const param = localMinimum(
|
|
310
343
|
t0,
|
|
311
344
|
t1,
|
|
312
345
|
(t) => pointDistance(p, bezierEquation(c, t))
|
|
313
346
|
);
|
|
314
|
-
|
|
315
|
-
return null;
|
|
316
|
-
}
|
|
317
|
-
return bezierEquation(c, solution);
|
|
347
|
+
return param ?? closestStep / maxSteps;
|
|
318
348
|
}
|
|
319
|
-
function
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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/
|
|
609
|
-
function
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
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
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
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
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
const [
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
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
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
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
|
-
|
|
672
|
-
yy = y1 + param * D;
|
|
672
|
+
major = m20 >= m02 ? vector(1, 0) : vector(0, 1);
|
|
673
673
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
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
|
-
|
|
698
|
+
const major = vectorScale(axes.major, -1);
|
|
699
|
+
return { ...axes, major, minor: vectorNormal(major) };
|
|
684
700
|
}
|
|
685
|
-
function
|
|
686
|
-
|
|
687
|
-
|
|
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
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
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,
|