@weasel-js/geom 1.15.0 → 1.15.2

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 (47) hide show
  1. package/dist/3d/index.d.ts +3 -1
  2. package/dist/3d/index.js +7 -10
  3. package/dist/3d/index.js.map +1 -1
  4. package/dist/booleans/index.js +4 -5
  5. package/dist/booleans/index.js.map +1 -1
  6. package/dist/{chunk-B3D6KWW3.js → chunk-346XYYMX.js} +154 -3
  7. package/dist/chunk-346XYYMX.js.map +1 -0
  8. package/dist/chunk-DNX24KBT.js +82 -0
  9. package/dist/chunk-DNX24KBT.js.map +1 -0
  10. package/dist/{chunk-EURWZUNY.js → chunk-GA5R5KWD.js} +59 -65
  11. package/dist/chunk-GA5R5KWD.js.map +1 -0
  12. package/dist/{chunk-3HQJGI63.js → chunk-HTT5AQIU.js} +3 -4
  13. package/dist/chunk-HTT5AQIU.js.map +1 -0
  14. package/dist/{chunk-FROQPADA.js → chunk-IDSKOHA4.js} +4 -4
  15. package/dist/{chunk-FROQPADA.js.map → chunk-IDSKOHA4.js.map} +1 -1
  16. package/dist/{chunk-HMGGJZTM.js → chunk-MIKP4V2C.js} +7 -21
  17. package/dist/chunk-MIKP4V2C.js.map +1 -0
  18. package/dist/{chunk-HNLJO3E7.js → chunk-MOCSUHEI.js} +22 -8
  19. package/dist/chunk-MOCSUHEI.js.map +1 -0
  20. package/dist/{chunk-3YH5XU3H.js → chunk-OQP5M5VD.js} +14 -23
  21. package/dist/chunk-OQP5M5VD.js.map +1 -0
  22. package/dist/{chunk-ZOMUTU7J.js → chunk-STYO7J4Y.js} +5 -11
  23. package/dist/chunk-STYO7J4Y.js.map +1 -0
  24. package/dist/{curvature-CDOI32hv.d.ts → curvature-DKPO4Qeh.d.ts} +0 -27
  25. package/dist/curves/index.d.ts +1 -1
  26. package/dist/curves/index.js +4 -4
  27. package/dist/index.d.ts +108 -3
  28. package/dist/index.js +159 -162
  29. package/dist/index.js.map +1 -1
  30. package/dist/nd/index.d.ts +28 -1
  31. package/dist/nd/index.js +2 -5
  32. package/dist/nd/index.js.map +1 -1
  33. package/dist/tessellate/index.js +5 -5
  34. package/dist/warp/index.js +8 -15
  35. package/dist/warp/index.js.map +1 -1
  36. package/package.json +3 -3
  37. package/dist/chunk-2N6OWA7E.js +0 -104
  38. package/dist/chunk-2N6OWA7E.js.map +0 -1
  39. package/dist/chunk-3HQJGI63.js.map +0 -1
  40. package/dist/chunk-3YH5XU3H.js.map +0 -1
  41. package/dist/chunk-755Y4YZS.js +0 -32
  42. package/dist/chunk-755Y4YZS.js.map +0 -1
  43. package/dist/chunk-B3D6KWW3.js.map +0 -1
  44. package/dist/chunk-EURWZUNY.js.map +0 -1
  45. package/dist/chunk-HMGGJZTM.js.map +0 -1
  46. package/dist/chunk-HNLJO3E7.js.map +0 -1
  47. package/dist/chunk-ZOMUTU7J.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,29 +1,45 @@
1
- import { carryCorners, parseSubpaths, intersectSegments, evalSeg, keepCorners, anchorRange, subSeg, writePath, derivSeg } from './chunk-3YH5XU3H.js';
2
- export { CORNER_RESTORE_TOLERANCE, cornerTraces, intersectSegments, keepCorners, restoreCorners } from './chunk-3YH5XU3H.js';
1
+ import { carryCorners, parseSubpaths, intersectSegments, evalSeg, keepCorners, anchorRange, subSeg, writePath, derivSeg } from './chunk-OQP5M5VD.js';
2
+ export { CORNER_RESTORE_TOLERANCE, cornerTraces, intersectSegments, keepCorners, restoreCorners } from './chunk-OQP5M5VD.js';
3
3
  import { createBvh } from './chunk-XXNK4N7Z.js';
4
4
  import { PORT_REACH, portControls, portCurvePoints } from './chunk-YQADYJJ7.js';
5
5
  export { PORT_REACH } from './chunk-YQADYJJ7.js';
6
- import { eulerAngleAt, eulerSegmentCubic, eulerCubicError, integrateEuler, eulerPointAt, eulerCurvatureAt, cubicDerivativeAt, cubicCurvatureAt } from './chunk-HNLJO3E7.js';
7
- export { SPIRO_KINDS, combTeeth, cubicCurvatureAt, cubicCurvatureSource, cubicDerivativeAt, curvatureComb, eulerAngleAt, eulerCurvatureAt, eulerCurvatureDerivativesAt, eulerPointAt, fitEulerSegment, isSpiroKind, placeEulerSegment, solveSpiro, spiroContoursFromControl, spiroContoursOf, spiroControlPath, spiroToPath } from './chunk-HNLJO3E7.js';
8
- import { extractPolylines } from './chunk-FROQPADA.js';
9
- import { boundsOfPath, fitPointRun, keepCorner } from './chunk-ZOMUTU7J.js';
10
- export { boundsOfPath } from './chunk-ZOMUTU7J.js';
11
- import { countPathAnchors, pathToAnchors, anchorsToPath, isAnchorSmooth, segmentEnds, isStraightSegment, nearestSegmentT } from './chunk-3HQJGI63.js';
12
- export { anchorsToPath, countPathAnchors, isAnchorSmooth, isStraightSegment, nearestSegmentT, pathToAnchors, segmentEnds } from './chunk-3HQJGI63.js';
13
- import { nearestOnLine, nearestOnPath, nearestOnCubic, nearestOnQuadratic } from './chunk-2N6OWA7E.js';
14
- export { nearestOnCubic, nearestOnLine, nearestOnPath, nearestOnQuadratic } from './chunk-2N6OWA7E.js';
15
- import { resolveCorners, pointInPolygon, cornerCuts, fillsOpenSubpaths, schneiderFit, fitCubicWithTangents, flattenCubic, pointSegmentDist2, flattenQuadratic, DEFAULT_FLATTEN_TOLERANCE, segmentsCross, tangentAt } from './chunk-EURWZUNY.js';
16
- export { CORNER_FIT_TOLERANCE, CORNER_KEYWORDS, DEFAULT_FLATTEN_TOLERANCE, cornerCenter, cornerCuts, cornerFrameAt, cornerFrames, cornerKeywordOf, cornerShapeK, cornerShapePieces, cornerShapePoint, defaultOpenFill, fillsOpenSubpaths, fitCubicWithTangents, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, isCornerShape, nextCornerShape, pointInPolygon, pointSegmentDist2, remapPerAnchor, resolveCorners, resolveCornersWithSources, schneiderFit, segmentsCross, setDefaultOpenFill } from './chunk-EURWZUNY.js';
17
- import { SINGULAR_RATIO, clamp } from './chunk-755Y4YZS.js';
18
- export { EPS, approxEq, clamp, cross, dot, len2, sign, sub } from './chunk-755Y4YZS.js';
19
- import { worldCoords, PATH_M, PATH_L, PATH_C, PATH_Q, PATH_Z, PathBuilder, withCorner, scaleCorners, originFor, coordsFrom, forEachSegment, pathCommandCoordCount, withoutCorners, elevateQuadraticToCubic, cubicEvalAt, cubicPointAt, splitCubicAtT, cubicAxisExtremaTs, rectToContour, splitCubicAt } from './chunk-B3D6KWW3.js';
20
- export { ORIGIN_THRESHOLD, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, PathBuilder, addOrigin, asPolygonPath, boundsOfCoords, boxContainsBox, boxContainsPoint, compactCorners, coordsFrom, cornerAt, cornerSpecAt, cubicAxisExtremaTs, cubicBounds, cubicEvalAt, cubicPointAt, elevateQuadraticToCubic, ellipsePath, forEachSegment, hasCorners, joinPaths, lerpCorners, linePath, originFor, originOf, pathCommandCoordCount, pathPoint, polygonFromPoints, polylineFromPoints, quadraticEvalAt, rectPath, rectToContour, regularPolygonPath, scaleCorners, splitCubicAt, splitCubicAtT, splitLineAt, splitQuadraticAt, starPath, unionBox, withCorner, withoutCorners, worldCoords } from './chunk-B3D6KWW3.js';
6
+ import { wrapPositive, eulerAngleAt, eulerSegmentCubic, eulerCubicError, integrateEuler, eulerPointAt, eulerCurvatureAt, DEG_TO_RAD, cubicDerivativeAt, cubicCurvatureAt } from './chunk-MOCSUHEI.js';
7
+ export { DEG_TO_RAD, RAD_TO_DEG, SPIRO_KINDS, combTeeth, cubicCurvatureAt, cubicCurvatureSource, cubicDerivativeAt, curvatureComb, eulerAngleAt, eulerCurvatureAt, eulerCurvatureDerivativesAt, eulerPointAt, fitEulerSegment, isSpiroKind, placeEulerSegment, solveSpiro, spiroContoursFromControl, spiroContoursOf, spiroControlPath, spiroToPath, wrapAngle, wrapPositive } from './chunk-MOCSUHEI.js';
8
+ import { extractPolylines } from './chunk-IDSKOHA4.js';
9
+ import { boundsOfPath, fitPointRun, keepCorner } from './chunk-STYO7J4Y.js';
10
+ export { boundsOfPath } from './chunk-STYO7J4Y.js';
11
+ import { countPathAnchors, pathToAnchors, anchorsToPath, isAnchorSmooth, segmentEnds, isStraightSegment, nearestSegmentT } from './chunk-HTT5AQIU.js';
12
+ export { anchorsToPath, countPathAnchors, isAnchorSmooth, isStraightSegment, nearestSegmentT, pathToAnchors, segmentEnds } from './chunk-HTT5AQIU.js';
13
+ import { resolveCorners, pointInPolygon, cornerCuts, fillsOpenSubpaths, schneiderFit, fitCubicWithTangents, flattenCubic, flattenQuadratic, DEFAULT_FLATTEN_TOLERANCE, segmentsCross, tangentAt } from './chunk-GA5R5KWD.js';
14
+ export { CORNER_FIT_TOLERANCE, CORNER_KEYWORDS, DEFAULT_FLATTEN_TOLERANCE, cornerCenter, cornerCuts, cornerFrameAt, cornerFrames, cornerKeywordOf, cornerShapeK, cornerShapePieces, cornerShapePoint, defaultOpenFill, fillsOpenSubpaths, fitCubicWithTangents, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, isCornerShape, nextCornerShape, pointInPolygon, remapPerAnchor, resolveCorners, resolveCornersWithSources, ringSignedArea, schneiderFit, segmentsCross, setDefaultOpenFill } from './chunk-GA5R5KWD.js';
15
+ import { nearestOnLine, worldCoords, PATH_M, PATH_L, PATH_C, PATH_Q, PATH_Z, PathBuilder, withCorner, scaleCorners, originFor, coordsFrom, forEachSegment, pathCommandCoordCount, withoutCorners, elevateQuadraticToCubic, cubicEvalAt, nearestOnPath, cubicPointAt, splitCubicAtT, nearestOnCubic, cubicAxisExtremaTs, rectToContour, pointSegmentDist2, lerpPoint, distance, splitCubicAt, nearestOnQuadratic, boxesIntersect } from './chunk-346XYYMX.js';
16
+ export { ORIGIN_THRESHOLD, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, PathBuilder, addOrigin, asPolygonPath, boundsOfCoords, boxContainsBox, boxContainsPoint, boxesIntersect, compactCorners, coordsFrom, cornerAt, cornerSpecAt, cubicAxisExtremaTs, cubicBounds, cubicEvalAt, cubicPointAt, distance, distance2, elevateQuadraticToCubic, ellipsePath, forEachSegment, hasCorners, joinPaths, lerpCorners, lerpPoint, linePath, nearestOnCubic, nearestOnLine, nearestOnPath, nearestOnQuadratic, originFor, originOf, pathCommandCoordCount, pathPoint, pointSegmentDist, pointSegmentDist2, polygonFromPoints, polylineFromPoints, quadraticEvalAt, rectContainsPoint, rectContainsPointHalfOpen, rectPath, rectToContour, rectsIntersect, rectsOverlap, regularPolygonPath, scaleCorners, segmentT, splitCubicAt, splitCubicAtT, splitLineAt, splitQuadraticAt, starPath, unionBox, unionRects, withCorner, withoutCorners, worldCoords } from './chunk-346XYYMX.js';
17
+ import { SINGULAR_RATIO, clamp } from './chunk-DNX24KBT.js';
18
+ export { EPS, approxEq, clamp, clamp01, cross, dot, len2, lerp, sign, sub } from './chunk-DNX24KBT.js';
21
19
 
22
20
  // src/view.ts
23
21
  var ZOOM_FLOOR = 1e-9;
24
22
  function normalizeZoom(zoom) {
25
23
  return zoom >= ZOOM_FLOOR && zoom < Infinity ? zoom : ZOOM_FLOOR;
26
24
  }
25
+ function viewWorldToScreen(view, p) {
26
+ return { x: (p.x - view.x) * view.scale.x, y: (p.y - view.y) * view.scale.y };
27
+ }
28
+ function viewScreenToWorld(view, p) {
29
+ return { x: p.x / view.scale.x + view.x, y: p.y / view.scale.y + view.y };
30
+ }
31
+ function viewRectToScreen(view, r) {
32
+ const x0 = (r.x - view.x) * view.scale.x;
33
+ const y0 = (r.y - view.y) * view.scale.y;
34
+ const w = r.width * view.scale.x;
35
+ const h = r.height * view.scale.y;
36
+ return {
37
+ x: w < 0 ? x0 + w : x0,
38
+ y: h < 0 ? y0 + h : y0,
39
+ width: Math.abs(w),
40
+ height: Math.abs(h)
41
+ };
42
+ }
27
43
 
28
44
  // src/affine.ts
29
45
  function identity() {
@@ -87,12 +103,12 @@ function transformCoords(coords, m) {
87
103
  function lineShape(from, to) {
88
104
  const dx2 = to.x - from.x;
89
105
  const dy2 = to.y - from.y;
90
- const length2 = Math.hypot(dx2, dy2);
91
- const tangent = length2 === 0 ? { x: 1, y: 0 } : { x: dx2 / length2, y: dy2 / length2 };
106
+ const length = Math.hypot(dx2, dy2);
107
+ const tangent = length === 0 ? { x: 1, y: 0 } : { x: dx2 / length, y: dy2 / length };
92
108
  const normal2 = { x: tangent.y, y: -tangent.x };
93
109
  return {
94
110
  kind: "line",
95
- length: length2,
111
+ length,
96
112
  closed: false,
97
113
  at(f, options) {
98
114
  const t = options?.open ? f : clamp(f, 0, 1);
@@ -104,25 +120,23 @@ function lineShape(from, to) {
104
120
  },
105
121
  nearest(p, options) {
106
122
  const n = nearestOnLine(p.x, p.y, from.x, from.y, to.x, to.y);
107
- if (!options?.open || length2 === 0) return { f: n.t, dist: n.dist };
108
- const f = ((p.x - from.x) * dx2 + (p.y - from.y) * dy2) / (length2 * length2);
123
+ if (!options?.open || length === 0) return { f: n.t, dist: n.dist };
124
+ const f = ((p.x - from.x) * dx2 + (p.y - from.y) * dy2) / (length * length);
109
125
  return { f, dist: n.dist };
110
126
  }
111
127
  };
112
128
  }
113
129
 
114
130
  // src/track/arc.ts
115
- var RAD = Math.PI / 180;
116
- var mod360 = (a) => (a % 360 + 360) % 360;
117
131
  function arcShape(spec) {
118
132
  const { center, radius, start } = spec;
119
133
  const sign2 = spec.direction === "ccw" ? -1 : 1;
120
- const raw = mod360(sign2 * (spec.end - start));
134
+ const raw = wrapPositive(sign2 * (spec.end - start), 360);
121
135
  const sweep = raw === 0 ? 360 : raw;
122
- const length2 = radius * sweep * RAD;
136
+ const length = radius * sweep * DEG_TO_RAD;
123
137
  const at2 = (f, options) => {
124
138
  const t = options?.open ? f : clamp(f, 0, 1);
125
- const theta = (start + sign2 * t * sweep) * RAD;
139
+ const theta = (start + sign2 * t * sweep) * DEG_TO_RAD;
126
140
  const s = Math.sin(theta);
127
141
  const c = Math.cos(theta);
128
142
  return {
@@ -133,14 +147,14 @@ function arcShape(spec) {
133
147
  };
134
148
  const shape = {
135
149
  kind: "arc",
136
- length: length2,
150
+ length,
137
151
  closed: raw === 0,
138
152
  at: at2,
139
153
  nearest(p, options) {
140
154
  const dx2 = p.x - center.x;
141
155
  const dy2 = p.y - center.y;
142
- const angle = dx2 === 0 && dy2 === 0 ? 0 : Math.atan2(dx2, -dy2) / RAD;
143
- const offset2 = mod360(sign2 * (angle - start));
156
+ const angle = dx2 === 0 && dy2 === 0 ? 0 : Math.atan2(dx2, -dy2) / DEG_TO_RAD;
157
+ const offset2 = wrapPositive(sign2 * (angle - start), 360);
144
158
  let f;
145
159
  if (offset2 <= sweep) f = offset2 / sweep;
146
160
  else f = 360 - offset2 < offset2 - sweep ? 0 : 1;
@@ -148,7 +162,7 @@ function arcShape(spec) {
148
162
  const dist = Math.hypot(p.x - q.x, p.y - q.y);
149
163
  if (!options?.open) return { f, dist };
150
164
  const mid = (options.about ?? 0.5) * sweep;
151
- const unwrapped = mid + mod360(offset2 - mid + 180) - 180;
165
+ const unwrapped = mid + wrapPositive(offset2 - mid + 180, 360) - 180;
152
166
  return { f: unwrapped / sweep, dist };
153
167
  }
154
168
  };
@@ -157,18 +171,16 @@ function arcShape(spec) {
157
171
  }
158
172
 
159
173
  // src/track/ellipse.ts
160
- var RAD2 = Math.PI / 180;
161
- var mod3602 = (a) => (a % 360 + 360) % 360;
162
174
  var PIECES = 128;
163
175
  var PANELS = 4;
164
176
  var RING = 256;
165
177
  var pointAt = ({ center, a, b, t0, sign: sign2 }, u) => {
166
- const t = (t0 + sign2 * u) * RAD2;
178
+ const t = (t0 + sign2 * u) * DEG_TO_RAD;
167
179
  return { x: center.x + a * Math.sin(t), y: center.y - b * Math.cos(t) };
168
180
  };
169
181
  var speed = ({ a, b, t0, sign: sign2 }, u) => {
170
- const t = (t0 + sign2 * u) * RAD2;
171
- return Math.hypot(a * Math.cos(t), b * Math.sin(t)) * RAD2;
182
+ const t = (t0 + sign2 * u) * DEG_TO_RAD;
183
+ return Math.hypot(a * Math.cos(t), b * Math.sin(t)) * DEG_TO_RAD;
172
184
  };
173
185
  function lengthTable(e, sweep) {
174
186
  const simpson = (u0, u1) => {
@@ -180,7 +192,7 @@ function lengthTable(e, sweep) {
180
192
  const du = sweep / PIECES;
181
193
  const table = [0];
182
194
  for (let i = 0; i < PIECES; i++) table.push(table[i] + simpson(i * du, (i + 1) * du));
183
- const length2 = table[PIECES];
195
+ const length = table[PIECES];
184
196
  const lengthTo = (u) => {
185
197
  if (u >= 0 && u <= sweep) {
186
198
  const i = Math.min(PIECES - 1, Math.floor(u / du));
@@ -192,8 +204,8 @@ function lengthTable(e, sweep) {
192
204
  return s;
193
205
  };
194
206
  const offsetAt = (f) => {
195
- if (length2 === 0) return f * sweep;
196
- const s = f * length2;
207
+ if (length === 0) return f * sweep;
208
+ const s = f * length;
197
209
  let lo = 0;
198
210
  let hi = PIECES;
199
211
  while (hi - lo > 1) {
@@ -210,7 +222,7 @@ function lengthTable(e, sweep) {
210
222
  }
211
223
  return u;
212
224
  };
213
- return { length: length2, lengthTo, offsetAt };
225
+ return { length, lengthTo, offsetAt };
214
226
  }
215
227
  var dist2 = (e, p, u) => {
216
228
  const q = pointAt(e, u);
@@ -230,13 +242,13 @@ function footBetween(e, p, lo, hi, n, late) {
230
242
  const dy2 = p.y - e.center.y;
231
243
  let u = best;
232
244
  for (let i = 0; i < 12; i++) {
233
- const t = (t0 + sign2 * u) * RAD2;
245
+ const t = (t0 + sign2 * u) * DEG_TO_RAD;
234
246
  const s = Math.sin(t);
235
247
  const c = Math.cos(t);
236
248
  const g = (a * a - b * b) * s * c - dx2 * a * c - dy2 * b * s;
237
249
  const g1 = (a * a - b * b) * (c * c - s * s) + dx2 * a * s - dy2 * b * c;
238
250
  if (!(g1 > 0)) break;
239
- const next = clamp(u - sign2 * g / g1 / RAD2, Math.max(lo, best - step), Math.min(hi, best + step));
251
+ const next = clamp(u - sign2 * g / g1 / DEG_TO_RAD, Math.max(lo, best - step), Math.min(hi, best + step));
240
252
  if (Math.abs(next - u) < 1e-12) break;
241
253
  u = next;
242
254
  }
@@ -245,24 +257,24 @@ function footBetween(e, p, lo, hi, n, late) {
245
257
  function ellipseShape(spec) {
246
258
  const { center, radiusX: a, radiusY: b } = spec;
247
259
  const sign2 = spec.direction === "ccw" ? -1 : 1;
248
- const param = (seenDeg) => Math.atan2(b * Math.sin(seenDeg * RAD2), a * Math.cos(seenDeg * RAD2)) / RAD2;
260
+ const param = (seenDeg) => Math.atan2(b * Math.sin(seenDeg * DEG_TO_RAD), a * Math.cos(seenDeg * DEG_TO_RAD)) / DEG_TO_RAD;
249
261
  const e = { center, a, b, t0: param(spec.start), sign: sign2 };
250
- const raw = mod3602(sign2 * (param(spec.end) - e.t0));
262
+ const raw = wrapPositive(sign2 * (param(spec.end) - e.t0), 360);
251
263
  const sweep = raw === 0 ? 360 : raw;
252
- const { length: length2, lengthTo, offsetAt } = lengthTable(e, sweep);
264
+ const { length, lengthTo, offsetAt } = lengthTable(e, sweep);
253
265
  const offsetPast = (f) => {
254
266
  if (raw === 0) return offsetAt((f % 1 + 1) % 1);
255
267
  let u = f * sweep;
256
268
  for (let i = 0; i < 8; i++) {
257
269
  const v = speed(e, u);
258
270
  if (!(v > 0)) break;
259
- u -= (lengthTo(u) - f * length2) / v;
271
+ u -= (lengthTo(u) - f * length) / v;
260
272
  }
261
273
  return u;
262
274
  };
263
275
  const at2 = (f, options) => {
264
276
  const u = options?.open && (f < 0 || f > 1) ? offsetPast(f) : offsetAt(clamp(f, 0, 1));
265
- const t = (e.t0 + sign2 * u) * RAD2;
277
+ const t = (e.t0 + sign2 * u) * DEG_TO_RAD;
266
278
  const s = Math.sin(t);
267
279
  const c = Math.cos(t);
268
280
  const k = Math.hypot(a * c, b * s);
@@ -272,16 +284,16 @@ function ellipseShape(spec) {
272
284
  };
273
285
  const shape = {
274
286
  kind: "ellipse",
275
- length: length2,
287
+ length,
276
288
  closed: raw === 0,
277
289
  at: at2,
278
290
  nearest(p, options) {
279
291
  const u = footBetween(e, p, 0, sweep, PIECES, true);
280
- const f = length2 === 0 ? 0 : clamp(lengthTo(u) / length2, 0, 1);
292
+ const f = length === 0 ? 0 : clamp(lengthTo(u) / length, 0, 1);
281
293
  const dist = Math.sqrt(dist2(e, p, u));
282
- if (!options?.open || length2 === 0) return { f, dist };
294
+ if (!options?.open || length === 0) return { f, dist };
283
295
  const mid = offsetAt(options.about ?? 0.5);
284
- return { f: lengthTo(footBetween(e, p, mid - 180, mid + 180, RING, false)) / length2, dist };
296
+ return { f: lengthTo(footBetween(e, p, mid - 180, mid + 180, RING, false)) / length, dist };
285
297
  }
286
298
  };
287
299
  Object.defineProperty(shape, "ellipse", { value: spec, enumerable: false });
@@ -413,22 +425,22 @@ function segmentAt(segments, s) {
413
425
  function pathShape(path, options = {}) {
414
426
  const measure2 = measurePath(path, { ...options, keepCorners: true });
415
427
  if (!measure2) return null;
416
- const { length: length2, closed } = measure2;
428
+ const { length, closed } = measure2;
417
429
  const shape = {
418
430
  kind: "path",
419
- length: length2,
431
+ length,
420
432
  closed,
421
433
  at(f, options2) {
422
434
  const open = options2?.open === true && (f < 0 || f > 1);
423
435
  const g = open && closed ? (f % 1 + 1) % 1 : clamp(f, 0, 1);
424
- const { point, tangent } = measure2.at(g * length2, true);
425
- const past = open && !closed ? (f - g) * length2 : 0;
436
+ const { point, tangent } = measure2.at(g * length, true);
437
+ const past = open && !closed ? (f - g) * length : 0;
426
438
  return { point: { x: point.x + past * tangent.x, y: point.y + past * tangent.y }, tangent, normal: { x: tangent.y, y: -tangent.x } };
427
439
  },
428
440
  nearest(p, opts) {
429
441
  const n = measure2.nearest(p);
430
- const f = length2 === 0 ? 0 : n.s / length2;
431
- if (!opts?.open || !closed || length2 === 0) return { f, dist: n.dist };
442
+ const f = length === 0 ? 0 : n.s / length;
443
+ if (!opts?.open || !closed || length === 0) return { f, dist: n.dist };
432
444
  const about = opts.about ?? 0.5;
433
445
  const unwrapped = [f - 1, f + 1].reduce((best, g) => Math.abs(g - about) < Math.abs(best - about) ? g : best, f);
434
446
  return { f: unwrapped, dist: n.dist };
@@ -556,7 +568,7 @@ function trackShapeD(shape, from = 0, to = 1) {
556
568
  const param = (p) => Math.atan2((p.x - center.x) / radiusX, (center.y - p.y) / radiusY);
557
569
  const sign2 = direction === "ccw" ? -1 : 1;
558
570
  const whole = (shape.ellipse.start - shape.ellipse.end) % 360 === 0 && Math.abs(to - from) >= 1 - 1e-12;
559
- const raw = (sign2 * Math.sign(to - from) * (param(b) - param(a)) + 4 * Math.PI) % (2 * Math.PI);
571
+ const raw = wrapPositive(sign2 * Math.sign(to - from) * (param(b) - param(a)));
560
572
  return arcsD(a, b, m, radiusX, radiusY, whole ? 2 * Math.PI : raw, direction === "ccw" === to < from ? 1 : 0);
561
573
  }
562
574
  let d = `M ${pt(a)}`;
@@ -591,15 +603,15 @@ function shiftTrack(shape, shift) {
591
603
  table[i] = table[i - 1] + Math.hypot(step.x, step.y);
592
604
  prev = next;
593
605
  }
594
- const length2 = table[SAMPLES2];
606
+ const length = table[SAMPLES2];
595
607
  const per = shape.length / SAMPLES2;
596
608
  const startRatio = table[1] > 0 ? per / table[1] : 1;
597
609
  const endRatio = table[SAMPLES2] - table[SAMPLES2 - 1] > 0 ? per / (table[SAMPLES2] - table[SAMPLES2 - 1]) : 1;
598
610
  const toBase = (f) => {
599
- const d = f * length2;
600
- if (length2 <= 0 || shape.length <= 0) return f;
611
+ const d = f * length;
612
+ if (length <= 0 || shape.length <= 0) return f;
601
613
  if (d < 0) return d * startRatio / shape.length;
602
- if (d > length2) return 1 + (d - length2) * endRatio / shape.length;
614
+ if (d > length) return 1 + (d - length) * endRatio / shape.length;
603
615
  let lo = 0;
604
616
  let hi = SAMPLES2;
605
617
  while (hi - lo > 1) {
@@ -611,17 +623,17 @@ function shiftTrack(shape, shift) {
611
623
  return (lo + (span > 0 ? (d - table[lo]) / span : 0)) / SAMPLES2;
612
624
  };
613
625
  const fromBase = (g) => {
614
- if (length2 <= 0 || shape.length <= 0) return g;
615
- if (g < 0) return g * shape.length / startRatio / length2;
616
- if (g > 1) return (length2 + (g - 1) * shape.length / endRatio) / length2;
626
+ if (length <= 0 || shape.length <= 0) return g;
627
+ if (g < 0) return g * shape.length / startRatio / length;
628
+ if (g > 1) return (length + (g - 1) * shape.length / endRatio) / length;
617
629
  const x = g * SAMPLES2;
618
630
  const i = Math.min(SAMPLES2 - 1, Math.floor(x));
619
- return (table[i] + (x - i) * (table[i + 1] - table[i])) / length2;
631
+ return (table[i] + (x - i) * (table[i + 1] - table[i])) / length;
620
632
  };
621
633
  const at2 = (f, options) => moved2(shape.at(toBase(options?.open ? f : clamp(f, 0, 1)), options));
622
634
  return {
623
635
  kind: shape.kind,
624
- length: length2,
636
+ length,
625
637
  closed: shape.closed,
626
638
  at: at2,
627
639
  nearest(p, options) {
@@ -634,8 +646,7 @@ function shiftTrack(shape, shift) {
634
646
  }
635
647
 
636
648
  // src/track/slice.ts
637
- var RAD3 = Math.PI / 180;
638
- var seen = (c, p) => Math.atan2(p.x - c.x, c.y - p.y) / RAD3;
649
+ var seen = (c, p) => Math.atan2(p.x - c.x, c.y - p.y) / DEG_TO_RAD;
639
650
  function trackSlice(shape, from, to) {
640
651
  const lo = clamp(Math.min(from, to), 0, 1);
641
652
  const hi = clamp(Math.max(from, to), 0, 1);
@@ -675,25 +686,25 @@ function runPlaces(lengths, gap, room, align, offset2, at2) {
675
686
  const fits = at2 === void 0 && total <= room;
676
687
  const lead = align === "start" ? 0 : align === "end" ? total : total / 2;
677
688
  let lo = at2 !== void 0 ? at2 - offset2 - lead : !fits ? -offset2 : align === "start" ? 0 : align === "end" ? room - total : (room - total) / 2;
678
- return lengths.map((length2) => {
689
+ return lengths.map((length) => {
679
690
  const start = lo;
680
- const hi = start + length2;
691
+ const hi = start + length;
681
692
  lo = hi + gap;
682
- return { center: start + length2 / 2, clipped: fits ? "none" : clipOf(start, hi, 0, room) };
693
+ return { center: start + length / 2, clipped: fits ? "none" : clipOf(start, hi, 0, room) };
683
694
  });
684
695
  }
685
696
  function runLength(lengths, gap) {
686
- return lengths.reduce((sum, length2, i) => sum + length2 + (i > 0 ? gap : 0), 0);
697
+ return lengths.reduce((sum, length, i) => sum + length + (i > 0 ? gap : 0), 0);
687
698
  }
688
- function runStationAt(run2, distance, shift = 0, past = "extend") {
689
- const { length: length2 } = run2;
690
- if (past === "follow" && length2 > 0) {
691
- const place2 = run2.at(distance / length2, { open: true });
699
+ function runStationAt(run2, distance3, shift = 0, past = "extend") {
700
+ const { length } = run2;
701
+ if (past === "follow" && length > 0) {
702
+ const place2 = run2.at(distance3 / length, { open: true });
692
703
  const { point: point2, normal: normal3 } = place2;
693
704
  return { ...place2, point: { x: point2.x + shift * normal3.x, y: point2.y + shift * normal3.y } };
694
705
  }
695
- const place = run2.at(length2 === 0 ? 0 : distance / length2);
696
- const beyond = distance < 0 ? distance : distance > length2 ? distance - length2 : 0;
706
+ const place = run2.at(length === 0 ? 0 : distance3 / length);
707
+ const beyond = distance3 < 0 ? distance3 : distance3 > length ? distance3 - length : 0;
697
708
  const { point, tangent, normal: normal2 } = place;
698
709
  return {
699
710
  ...place,
@@ -702,22 +713,22 @@ function runStationAt(run2, distance, shift = 0, past = "extend") {
702
713
  }
703
714
  function placeAlongRun(run2, lengths, options = {}) {
704
715
  const { gap = 0, align = "center", offset: offset2 = 0, at: at2, shift = 0, wrap = false, past = "extend", order = "reading" } = options;
705
- const { length: length2 } = run2;
716
+ const { length } = run2;
706
717
  const mirror = order === "track" && run2.reversed;
707
- const spots = runPlaces(lengths, gap, length2, align, offset2, at2);
708
- const lap = wrap && run2.closed && spots.length > 0 ? wrapWindow(spots[0], lengths[0], length2) : null;
718
+ const spots = runPlaces(lengths, gap, length, align, offset2, at2);
719
+ const lap = wrap && run2.closed && spots.length > 0 ? wrapWindow(spots[0], lengths[0], length) : null;
709
720
  return spots.map((spot, i) => {
710
721
  const half = lengths[i] / 2;
711
722
  const clipped = lap ? clipOf(spot.center - half, spot.center + half, lap.start, lap.end, lap.hair) : spot.clipped;
712
- let distance = spot.center;
713
- if (past === "hold" && clipped === "past") distance = clamp(distance, lap?.start ?? 0, lap?.end ?? length2);
714
- if (lap && length2 > 0) distance = (distance % length2 + length2) % length2;
715
- return { ...runStationAt(run2, mirror ? length2 - distance : distance, shift, past === "extend" ? "extend" : "follow"), center: spot.center, clipped };
723
+ let distance3 = spot.center;
724
+ if (past === "hold" && clipped === "past") distance3 = clamp(distance3, lap?.start ?? 0, lap?.end ?? length);
725
+ if (lap && length > 0) distance3 = (distance3 % length + length) % length;
726
+ return { ...runStationAt(run2, mirror ? length - distance3 : distance3, shift, past === "extend" ? "extend" : "follow"), center: spot.center, clipped };
716
727
  });
717
728
  }
718
- function wrapWindow(first, firstLength, length2) {
729
+ function wrapWindow(first, firstLength, length) {
719
730
  const start = first.center - firstLength / 2;
720
- return { start, end: start + length2, hair: 1e-9 * Math.max(1, length2) };
731
+ return { start, end: start + length, hair: 1e-9 * Math.max(1, length) };
721
732
  }
722
733
 
723
734
  // src/portCurve2.ts
@@ -1128,8 +1139,8 @@ function polygonIntersectsPath(polygon, path, opts = {}) {
1128
1139
  }
1129
1140
 
1130
1141
  // src/paths/cornerOffset.ts
1131
- function offsetCornerTraces(path, distance) {
1132
- if (path.kind !== "polygon" || distance === 0) return [];
1142
+ function offsetCornerTraces(path, distance3) {
1143
+ if (path.kind !== "polygon" || distance3 === 0) return [];
1133
1144
  const drawn = resolveCorners(path);
1134
1145
  const out = [];
1135
1146
  for (const cut of cornerCuts(path)) {
@@ -1146,9 +1157,9 @@ function offsetCornerTraces(path, distance) {
1146
1157
  const half = Math.acos(Math.max(-1, Math.min(1, din.x * b.x + din.y * b.y)));
1147
1158
  const probe = Math.min(inLen, outLen) * 0.01;
1148
1159
  const sign2 = pointInPath(drawn, v.x + b.x * probe, v.y + b.y * probe) ? -1 : 1;
1149
- const radius = spec.radius + sign2 * distance / Math.tan(half);
1160
+ const radius = spec.radius + sign2 * distance3 / Math.tan(half);
1150
1161
  if (!(radius > 0)) continue;
1151
- const at2 = { x: v.x - b.x * sign2 * distance / Math.sin(half), y: v.y - b.y * sign2 * distance / Math.sin(half) };
1162
+ const at2 = { x: v.x - b.x * sign2 * distance3 / Math.sin(half), y: v.y - b.y * sign2 * distance3 / Math.sin(half) };
1152
1163
  const reach = radius * 2 + 1;
1153
1164
  const wedge = new PathBuilder().moveTo(at2.x + din.x * reach, at2.y + din.y * reach).lineTo(at2.x, at2.y).lineTo(at2.x + dout.x * reach, at2.y + dout.y * reach).build();
1154
1165
  const [moved2] = cornerCuts(withCorner(wedge, 1, { shape: spec.shape, radius }));
@@ -2341,14 +2352,14 @@ function segmentLength(s, a = 0, b = 1) {
2341
2352
  }
2342
2353
  return sum * h / 2;
2343
2354
  }
2344
- function segmentTAtLength(s, length2) {
2355
+ function segmentTAtLength(s, length) {
2345
2356
  const total = segmentLength(s);
2346
- if (length2 <= 0 || !(total > 0)) return 0;
2347
- if (length2 >= total) return 1;
2348
- if (s.length === 2) return length2 / total;
2349
- let lo = 0, hi = 1, t = length2 / total;
2357
+ if (length <= 0 || !(total > 0)) return 0;
2358
+ if (length >= total) return 1;
2359
+ if (s.length === 2) return length / total;
2360
+ let lo = 0, hi = 1, t = length / total;
2350
2361
  for (let i = 0; i < 30; i++) {
2351
- const err = segmentLength(s, 0, t) - length2;
2362
+ const err = segmentLength(s, 0, t) - length;
2352
2363
  if (Math.abs(err) < 1e-10 * Math.max(1, total)) break;
2353
2364
  if (err > 0) hi = t;
2354
2365
  else lo = t;
@@ -2559,8 +2570,8 @@ function findPathSnaps(index, probe, query) {
2559
2570
  const skip = query.skip ?? (() => false);
2560
2571
  const hits = [];
2561
2572
  const offer = (kind, x, y, paths) => {
2562
- const distance = metric(x - probe.x, y - probe.y);
2563
- if (distance <= r) hits.push({ kind, x, y, distance, paths });
2573
+ const distance3 = metric(x - probe.x, y - probe.y);
2574
+ if (distance3 <= r) hits.push({ kind, x, y, distance: distance3, paths });
2564
2575
  };
2565
2576
  const rx = sx > 0 ? r / sx : Infinity, ry = sy > 0 ? r / sy : Infinity;
2566
2577
  const box = [probe.x - rx, probe.y - ry, probe.x + rx, probe.y + ry];
@@ -3142,12 +3153,12 @@ var FULL = 2 * Math.PI;
3142
3153
  var FIT_SHARE = 1e-4;
3143
3154
  var FIT_FLOOR = 1e-3;
3144
3155
  var MAX_SPLITS = 6;
3145
- function extensionPieces(frame, distance, mode, opts = {}) {
3146
- if (!(distance > 0)) return [];
3147
- const bends = Math.abs(frame.curvature) * distance > STRAIGHT_TURN;
3148
- if (mode === "curvature" && bends) return arcPieces(frame, distance);
3149
- if (mode === "eased" && bends) return easedPieces(frame, distance, easeTurnOf(opts));
3150
- return [line(frame.point, frame.tangent, distance)];
3156
+ function extensionPieces(frame, distance3, mode, opts = {}) {
3157
+ if (!(distance3 > 0)) return [];
3158
+ const bends = Math.abs(frame.curvature) * distance3 > STRAIGHT_TURN;
3159
+ if (mode === "curvature" && bends) return arcPieces(frame, distance3);
3160
+ if (mode === "eased" && bends) return easedPieces(frame, distance3, easeTurnOf(opts));
3161
+ return [line(frame.point, frame.tangent, distance3)];
3151
3162
  }
3152
3163
  function easeLength(frame, opts = {}) {
3153
3164
  const k = Math.abs(frame.curvature);
@@ -3157,16 +3168,16 @@ function easeTurnOf(opts) {
3157
3168
  const turn = opts.easeTurn;
3158
3169
  return turn !== void 0 && Number.isFinite(turn) && turn > 0 ? Math.min(turn, QUARTER) : DEFAULT_EASE_TURN;
3159
3170
  }
3160
- function line(from, dir, length2) {
3161
- return { pts: [from, { x: from.x + dir.x * length2, y: from.y + dir.y * length2 }], length: length2 };
3171
+ function line(from, dir, length) {
3172
+ return { pts: [from, { x: from.x + dir.x * length, y: from.y + dir.y * length }], length };
3162
3173
  }
3163
3174
  function arcCenter({ point, tangent, curvature }) {
3164
3175
  return { x: point.x - tangent.y / curvature, y: point.y + tangent.x / curvature };
3165
3176
  }
3166
- function arcPieces(frame, distance) {
3177
+ function arcPieces(frame, distance3) {
3167
3178
  const s = Math.sign(frame.curvature);
3168
3179
  const r = 1 / Math.abs(frame.curvature);
3169
- const sweep = Math.min(distance / r, FULL);
3180
+ const sweep = Math.min(distance3 / r, FULL);
3170
3181
  const count = Math.max(1, Math.ceil(sweep / QUARTER - 1e-9));
3171
3182
  const step = sweep / count;
3172
3183
  const reach = 4 / 3 * Math.tan(step / 4) * r;
@@ -3197,7 +3208,7 @@ function arcPieces(frame, distance) {
3197
3208
  }
3198
3209
  return out;
3199
3210
  }
3200
- function easeSpiral(frame, length2, turn) {
3211
+ function easeSpiral(frame, length, turn) {
3201
3212
  const sign2 = Math.sign(frame.curvature);
3202
3213
  const k0 = sign2 * turn;
3203
3214
  const k1 = -2 * sign2 * turn;
@@ -3212,19 +3223,19 @@ function easeSpiral(frame, length2, turn) {
3212
3223
  chordAngle: Math.atan2(c.y, c.x),
3213
3224
  p0: frame.point,
3214
3225
  p1: frame.point,
3215
- length: length2,
3226
+ length,
3216
3227
  rotation
3217
3228
  };
3218
3229
  return { ...seg, p1: eulerPointAt(seg, 1) };
3219
3230
  }
3220
- function easedPieces(frame, distance, turn) {
3231
+ function easedPieces(frame, distance3, turn) {
3221
3232
  const ease = 2 * turn / Math.abs(frame.curvature);
3222
3233
  const spiral = easeSpiral(frame, ease, turn);
3223
- const drawn = distance < ease ? spiralPiece(spiral, 0, distance / ease) : spiral;
3234
+ const drawn = distance3 < ease ? spiralPiece(spiral, 0, distance3 / ease) : spiral;
3224
3235
  const out = fitSpiral(drawn, Math.max(FIT_FLOOR, FIT_SHARE * ease), 0);
3225
- if (distance > ease) {
3236
+ if (distance3 > ease) {
3226
3237
  const a = eulerAngleAt(spiral, 1);
3227
- out.push(line(spiral.p1, { x: Math.cos(a), y: Math.sin(a) }, distance - ease));
3238
+ out.push(line(spiral.p1, { x: Math.cos(a), y: Math.sin(a) }, distance3 - ease));
3228
3239
  }
3229
3240
  return out;
3230
3241
  }
@@ -3315,9 +3326,9 @@ function pathEndAnchorIndex(set, end) {
3315
3326
  function pathEndFrame(set, end) {
3316
3327
  return atTail(set, end, tailFrame) ?? null;
3317
3328
  }
3318
- function lengthenPathEnd(set, end, distance, mode, opts = {}) {
3319
- if (!(distance !== 0 && Number.isFinite(distance))) return false;
3320
- return atTail(set, end, (sub3) => distance < 0 ? trimTail(sub3, -distance) : growTail(sub3, distance, mode, opts)) ?? false;
3329
+ function lengthenPathEnd(set, end, distance3, mode, opts = {}) {
3330
+ if (!(distance3 !== 0 && Number.isFinite(distance3))) return false;
3331
+ return atTail(set, end, (sub3) => distance3 < 0 ? trimTail(sub3, -distance3) : growTail(sub3, distance3, mode, opts)) ?? false;
3321
3332
  }
3322
3333
  function lengthToward(set, end, mode, point, near2 = 0, opts = {}) {
3323
3334
  const frame = pathEndFrame(set, end);
@@ -3393,10 +3404,10 @@ function lengthAlongEased(frame, point, opts) {
3393
3404
  }
3394
3405
  return best.length;
3395
3406
  }
3396
- function growTail(sub3, distance, mode, opts) {
3407
+ function growTail(sub3, distance3, mode, opts) {
3397
3408
  const frame = tailFrame(sub3);
3398
3409
  if (!frame) return false;
3399
- const pieces = extensionPieces(frame, distance, mode, opts);
3410
+ const pieces = extensionPieces(frame, distance3, mode, opts);
3400
3411
  const end = sub3[sub3.length - 1];
3401
3412
  const first = pieces[0];
3402
3413
  if (pieces.length === 1 && first.pts.length === 2 && isStraightSegment(sub3[sub3.length - 2], end)) {
@@ -3479,9 +3490,9 @@ function segmentsBesideEnd(path, end) {
3479
3490
  return s === end.sub ? segs.filter((g) => g.index !== (end.end === "last" ? g.count - 1 : 0)) : segs;
3480
3491
  });
3481
3492
  }
3482
- function lengthenOpenEnd(path, end, distance, mode = "tangent", opts = {}) {
3483
- if (!(distance > 0) || path.kind !== "polygon") return null;
3484
- return editAnchorSetTracked(path, (set) => lengthenPathEnd(set, end, distance, mode, opts))?.path ?? null;
3493
+ function lengthenOpenEnd(path, end, distance3, mode = "tangent", opts = {}) {
3494
+ if (!(distance3 > 0) || path.kind !== "polygon") return null;
3495
+ return editAnchorSetTracked(path, (set) => lengthenPathEnd(set, end, distance3, mode, opts))?.path ?? null;
3485
3496
  }
3486
3497
  function extendToMeet(path, boundaries, end, opts = {}) {
3487
3498
  if (path.kind !== "polygon") return null;
@@ -3649,12 +3660,12 @@ function unit(p) {
3649
3660
  // src/paths/growRegion.ts
3650
3661
  var MAX_DEPTH = 6;
3651
3662
  var SAMPLES3 = [0.2, 0.35, 0.5, 0.65, 0.8];
3652
- function growRegion(path, distance, opts = {}) {
3663
+ function growRegion(path, distance3, opts = {}) {
3653
3664
  const b = new PathBuilder();
3654
- if (!(distance > 0)) return b.build();
3665
+ if (!(distance3 > 0)) return b.build();
3655
3666
  const sigma = pathSignedArea(path) < 0 ? -1 : 1;
3656
3667
  const ctx = {
3657
- d: distance,
3668
+ d: distance3,
3658
3669
  sigma,
3659
3670
  tol: opts.tolerance ?? 0.1,
3660
3671
  join: opts.join ?? "miter",
@@ -3887,7 +3898,7 @@ function segmentCrossings(segs) {
3887
3898
  const out = [];
3888
3899
  for (let a = 0; a < segs.length; a++) {
3889
3900
  for (let b = a + 1; b < segs.length; b++) {
3890
- if (!overlaps(boxes[a], boxes[b])) continue;
3901
+ if (!boxesIntersect(boxes[a], boxes[b])) continue;
3891
3902
  const pa = flat[a], pb = flat[b];
3892
3903
  for (let i = 0; i + 1 < pa.length; i++) {
3893
3904
  for (let j = 0; j + 1 < pb.length; j++) {
@@ -3921,7 +3932,6 @@ function boxOf(pts) {
3921
3932
  }
3922
3933
  return b;
3923
3934
  }
3924
- var overlaps = (p, q) => p[0] <= q[2] && q[0] <= p[2] && p[1] <= q[3] && q[1] <= p[3];
3925
3935
  function linesCross(a, b, c, d) {
3926
3936
  const rx = b[0] - a[0], ry = b[1] - a[1], sx = d[0] - c[0], sy = d[1] - c[1];
3927
3937
  const den = rx * sy - ry * sx;
@@ -4221,21 +4231,21 @@ function paramAt(seg, d) {
4221
4231
  function arcRun(sub3, from, to) {
4222
4232
  const n = sub3.length;
4223
4233
  const segs = [];
4224
- let length2 = 0;
4234
+ let length = 0;
4225
4235
  for (let i = from; i < to; i++) {
4226
- const seg = measure(sub3[i % n], sub3[(i + 1) % n], length2);
4236
+ const seg = measure(sub3[i % n], sub3[(i + 1) % n], length);
4227
4237
  segs.push(seg);
4228
- length2 += seg.len;
4238
+ length += seg.len;
4229
4239
  }
4230
4240
  const locate = (s, arriving) => {
4231
- const d = Math.min(Math.max(s, 0), length2);
4241
+ const d = Math.min(Math.max(s, 0), length);
4232
4242
  let k = 0;
4233
4243
  while (k < segs.length - 1 && (arriving ? segs[k].from + segs[k].len < d : segs[k].from + segs[k].len <= d)) k++;
4234
4244
  return { seg: segs[k], t: paramAt(segs[k], d - segs[k].from) };
4235
4245
  };
4236
4246
  const start = { x: sub3[from % n].x, y: sub3[from % n].y };
4237
4247
  return {
4238
- length: length2,
4248
+ length,
4239
4249
  pointAt(s) {
4240
4250
  if (segs.length === 0) return start;
4241
4251
  const { seg, t } = locate(s, false);
@@ -5189,17 +5199,13 @@ function pathThroughPoseFrame(path, pose) {
5189
5199
  function anchorsUnderBrush(set, from, to, opts) {
5190
5200
  const scale3 = opts.scale ?? { x: 1, y: 1 };
5191
5201
  const ax = from.x * scale3.x, ay = from.y * scale3.y;
5192
- const dx2 = to.x * scale3.x - ax, dy2 = to.y * scale3.y - ay;
5193
- const len22 = dx2 * dx2 + dy2 * dy2;
5202
+ const bx = to.x * scale3.x, by = to.y * scale3.y;
5194
5203
  const r2 = opts.radiusPx * opts.radiusPx;
5195
5204
  const hits = [];
5196
5205
  let flat = 0;
5197
5206
  for (const sub3 of set.anchors) {
5198
5207
  for (const a of sub3) {
5199
- const px = a.x * scale3.x - ax, py = a.y * scale3.y - ay;
5200
- const t = len22 === 0 ? 0 : Math.max(0, Math.min(1, (px * dx2 + py * dy2) / len22));
5201
- const ex = px - t * dx2, ey = py - t * dy2;
5202
- if (ex * ex + ey * ey <= r2) hits.push(flat);
5208
+ if (pointSegmentDist2(a.x * scale3.x, a.y * scale3.y, ax, ay, bx, by) <= r2) hits.push(flat);
5203
5209
  flat++;
5204
5210
  }
5205
5211
  }
@@ -5321,8 +5327,8 @@ function bendSegment(set, grip, dx2, dy2) {
5321
5327
  const aSmooth = isAnchorSmooth(a);
5322
5328
  const bSmooth = isAnchorSmooth(b);
5323
5329
  const straight = isStraightSegment(a, b);
5324
- const p1 = a.outHandle ?? (straight ? lerp(a, b, 1 / 3) : { x: a.x, y: a.y });
5325
- const p2 = b.inHandle ?? (straight ? lerp(a, b, 2 / 3) : { x: b.x, y: b.y });
5330
+ const p1 = a.outHandle ?? (straight ? lerpPoint(a, b, 1 / 3) : { x: a.x, y: a.y });
5331
+ const p2 = b.inHandle ?? (straight ? lerpPoint(a, b, 2 / 3) : { x: b.x, y: b.y });
5326
5332
  const t = Math.min(1 - T_MARGIN, Math.max(T_MARGIN, grip.t));
5327
5333
  const u = 1 - t;
5328
5334
  const k = 1 / (3 * t * u * (u * u + t * t));
@@ -5332,9 +5338,6 @@ function bendSegment(set, grip, dx2, dy2) {
5332
5338
  if (bSmooth) b.outHandle = alignedOpposite(b, b.inHandle, b.outHandle);
5333
5339
  return true;
5334
5340
  }
5335
- function lerp(a, b, f) {
5336
- return { x: a.x + (b.x - a.x) * f, y: a.y + (b.y - a.y) * f };
5337
- }
5338
5341
  function alignedOpposite(anchor, moved2, other2) {
5339
5342
  const mx = moved2.x - anchor.x;
5340
5343
  const my = moved2.y - anchor.y;
@@ -5483,10 +5486,10 @@ function same2(p, q) {
5483
5486
  }
5484
5487
 
5485
5488
  // src/paths/softSelection.ts
5486
- function softFalloff(falloff, distance, radius) {
5487
- if (!(radius > 0) || distance >= radius) return 0;
5488
- if (distance <= 0) return 1;
5489
- const u = distance / radius;
5489
+ function softFalloff(falloff, distance3, radius) {
5490
+ if (!(radius > 0) || distance3 >= radius) return 0;
5491
+ if (distance3 <= 0) return 1;
5492
+ const u = distance3 / radius;
5490
5493
  switch (falloff) {
5491
5494
  case "linear":
5492
5495
  return 1 - u;
@@ -5581,7 +5584,7 @@ function softSelectionBand(measure2, set, selected, radius) {
5581
5584
  sub3.segments.forEach((seg, i) => {
5582
5585
  const c = segmentControls2(anchors, sub3.closed, i);
5583
5586
  if (!c) return;
5584
- const at2 = (t) => isStraight(c) ? lerp2(c[0], c[3], t) : cubicPointAt(c[0], c[1], c[2], c[3], t);
5587
+ const at2 = (t) => isStraight(c) ? lerpPoint(c[0], c[3], t) : cubicPointAt(c[0], c[1], c[2], c[3], t);
5585
5588
  const steps = seg.lengths.length - 1;
5586
5589
  for (let k = 0; k <= steps; k++) {
5587
5590
  const len = seg.lengths[k];
@@ -5631,9 +5634,6 @@ function crossing2(a, b, aIn, inside) {
5631
5634
  }
5632
5635
  return (lo + hi) / 2;
5633
5636
  }
5634
- function lerp2(a, b, t) {
5635
- return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
5636
- }
5637
5637
 
5638
5638
  // src/paths/balanceHandles.ts
5639
5639
  function handleBalances(set) {
@@ -5661,7 +5661,7 @@ function segmentHandles(set, sub3, segIdx) {
5661
5661
  if (!ends || isStraightSegment(ends.a, ends.b)) return null;
5662
5662
  const { a, b } = ends;
5663
5663
  if (!a.outHandle || !b.inHandle) return null;
5664
- if (length(a, a.outHandle) === 0 || length(b, b.inHandle) === 0) return null;
5664
+ if (distance(a, a.outHandle) === 0 || distance(b, b.inHandle) === 0) return null;
5665
5665
  return { a, b, from: a.outHandle, to: b.inHandle };
5666
5666
  }
5667
5667
  function scaleSegmentHandles(set, sub3, segIdx, factor, syms = []) {
@@ -5691,8 +5691,8 @@ function equalizeSegmentHandles(set, sub3, segIdx) {
5691
5691
  const handles = segmentHandles(set, sub3, segIdx);
5692
5692
  if (!handles) return false;
5693
5693
  const { a, b, from, to } = handles;
5694
- const lenA = length(a, from);
5695
- const lenB = length(b, to);
5694
+ const lenA = distance(a, from);
5695
+ const lenB = distance(b, to);
5696
5696
  const ua = { x: (from.x - a.x) / lenA, y: (from.y - a.y) / lenA };
5697
5697
  const ub = { x: (to.x - b.x) / lenB, y: (to.y - b.y) / lenB };
5698
5698
  const corner = rayCrossing(a, ua, b, ub);
@@ -5719,9 +5719,6 @@ function rayCrossing(p, u, q, v) {
5719
5719
  const tb = (dx2 * u.y - dy2 * u.x) / den;
5720
5720
  return ta > 0 && tb > 0 ? { ta, tb } : null;
5721
5721
  }
5722
- function length(a, b) {
5723
- return Math.hypot(b.x - a.x, b.y - a.y);
5724
- }
5725
5722
  function scaledFrom(anchor, handle, k) {
5726
5723
  return { x: anchor.x + (handle.x - anchor.x) * k, y: anchor.y + (handle.y - anchor.y) * k };
5727
5724
  }
@@ -6917,10 +6914,10 @@ function handleOf(a, side) {
6917
6914
  function handleTarget(a, h, part, entry) {
6918
6915
  if (part === "X") return { x: apply2(h.x, entry), y: h.y };
6919
6916
  if (part === "Y") return { x: h.x, y: apply2(h.y, entry) };
6920
- const length2 = Math.hypot(h.x - a.x, h.y - a.y);
6917
+ const length = Math.hypot(h.x - a.x, h.y - a.y);
6921
6918
  const angle = angleOf(a, h);
6922
6919
  const nextAngle = part === "Angle" ? apply2(angle, entry) : angle;
6923
- const nextLength = part === "Length" ? Math.max(0, apply2(length2, entry)) : length2;
6920
+ const nextLength = part === "Length" ? Math.max(0, apply2(length, entry)) : length;
6924
6921
  const rad = nextAngle * Math.PI / 180;
6925
6922
  return { x: a.x + Math.cos(rad) * nextLength, y: a.y - Math.sin(rad) * nextLength };
6926
6923
  }
@@ -7020,6 +7017,6 @@ function typedArrayReplacer(_key, value) {
7020
7017
  return tagTypedArray(value) ?? value;
7021
7018
  }
7022
7019
 
7023
- export { ANCHOR_FIELDS, CONSTRAINT_TOLERANCE, EASINGS, PATH_SNAP_KINDS, SPRING_PRESETS, TYPED_ARRAY_CONSTRUCTORS, ZOOM_FLOOR, addExtremaAnchors, anchorAt, anchorCount, anchorOriginsOf, anchorSymmetries, anchorSymmetry, anchorsBefore, anchorsInRect, anchorsUnderBrush, anchorsWhere, applyToPoint, arcShape, averageAnchorsAt, balanceFactorToward, bendAlongPath, bendSegment, bendSide, blendPaths, boxFrameOf, boxToBox, circlePath, clampRectWithin, closestOpenEnds, composePath, conflictingConstraints, constrainPathEdit, constrainPathsEdit, constraintAnchors, constraintApplies, constraintFits, convertSegments, cornerAnchors, createPathSnapIndex, cubicBezierEasing, cubicContoursToPath, decomposePath, deleteAnchorsAt, directionMarks, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeLength, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorSet, editAnchorSetTracked, ellipseShape, equalizeSegmentHandles, everyNthAnchor, extendToMeet, extensionPieces, findPathSnap, findPathSnaps, fitAffine, fitCubicThroughDeletion, flatAnchorIndex, flatIndexesAfterReverse, growAnchorSelection, growRegion, handleAlongItsAngle, handleAtItsLength, handleBalances, harmonizeAnchors, hasOpenSubpath, identity, insertAnchorOnSegment, invert, invertAnchorSelection, isSegmentStraight, joinAnchorsAt, joinSubpathEnds, lengthToward, lengthenOpenEnd, lengthenPathEnd, lineShape, linear, locateAnchor, makeHandlesSymmetric, mapConstraintAnchors, mat3, meanScale, measureAnchorPath, measurePath, mergeRegion, moveHandleSymmetric, moveHandleTo, multiply, nearestPathAnchor, normalizeZoom, offsetCornerTraces, openEndAt, openEndRay, openPathEnds, openSubpathAt, pathAnchorPoints, pathAwayFromAnchors, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathCrossings, pathDistanceToPoint, pathEndAnchorIndex, pathEndFrame, pathFromD, pathInPoseFrame, pathInWorld, pathIntersectsPolygon, pathIntersectsRect, pathSegments, pathShape, pathSignedArea, pathThroughPoseFrame, pathToCubicContours, pathToD, placeAlongRun, placeRect, pointAlongPath, pointInPath, polygonContainsPath, polygonIntersectsPath, portControls2 as portControls, portCurvePoints2 as portCurvePoints, poseFrameInverseOf, poseFrameOf, poseLinearOf, poseRotationOf, prepareBlend, puckerBloatPath, pxExtent, pxExtentInFrame, readAnchorFields, rectMarkerPath, remapAnchorValues, remapConstraints, remapPointValues, repeatAlongPath, resamplePath, resolveEasing, retractHandles, reverseAnchors, reversePath, reverseSubpaths, reviveTypedArrays, rotate, rotateAboutPoint, rotatePathAround, roughenPath, roundRectPath, runLength, runPlaces, runStationAt, scale, scaleDelta, scalePathToBounds, scaleSegmentHandles, screenAngleOf, segmentAt2 as segmentAt, segmentBetween, segmentExtremaTs, segmentsBetweenAnchors, setSubpathStart, shiftTrack, shrinkAnchorSelection, simplifyAnchorsAt, simplifyPath, simplifySpan, simplifySubpath, smoothAnchors, smudgePath, softFalloff, softSelectionBand, softSelectionWeights, solveConstraints, solvePathConstraints, splitByClosure, splitSubpaths, squarePath, standoff, stationsAlongPath, strokeHitTest, subpathEndAt, subpathsOfAnchors, tagTypedArray, tagTypedArrays, trackRun, trackShapeD, trackSlice, transformCoords, transformPath, translate, translateAnchorBy, translateAnchorsSymmetric, translatePath, trimPathAt, typedArrayReplacer, unionBoundsPath, unsatisfiedConstraints, untagTypedArray, viewToMat3, withAnchorPoints, withinPxBox, withinPxRadius, worldEditToStorage, writeAnchorField, zigzagPath };
7020
+ export { ANCHOR_FIELDS, CONSTRAINT_TOLERANCE, EASINGS, PATH_SNAP_KINDS, SPRING_PRESETS, TYPED_ARRAY_CONSTRUCTORS, ZOOM_FLOOR, addExtremaAnchors, anchorAt, anchorCount, anchorOriginsOf, anchorSymmetries, anchorSymmetry, anchorsBefore, anchorsInRect, anchorsUnderBrush, anchorsWhere, applyToPoint, arcShape, averageAnchorsAt, balanceFactorToward, bendAlongPath, bendSegment, bendSide, blendPaths, boxFrameOf, boxToBox, circlePath, clampRectWithin, closestOpenEnds, composePath, conflictingConstraints, constrainPathEdit, constrainPathsEdit, constraintAnchors, constraintApplies, constraintFits, convertSegments, cornerAnchors, createPathSnapIndex, cubicBezierEasing, cubicContoursToPath, decomposePath, deleteAnchorsAt, directionMarks, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeLength, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorSet, editAnchorSetTracked, ellipseShape, equalizeSegmentHandles, everyNthAnchor, extendToMeet, extensionPieces, findPathSnap, findPathSnaps, fitAffine, fitCubicThroughDeletion, flatAnchorIndex, flatIndexesAfterReverse, growAnchorSelection, growRegion, handleAlongItsAngle, handleAtItsLength, handleBalances, harmonizeAnchors, hasOpenSubpath, identity, insertAnchorOnSegment, invert, invertAnchorSelection, isSegmentStraight, joinAnchorsAt, joinSubpathEnds, lengthToward, lengthenOpenEnd, lengthenPathEnd, lineShape, linear, locateAnchor, makeHandlesSymmetric, mapConstraintAnchors, mat3, meanScale, measureAnchorPath, measurePath, mergeRegion, moveHandleSymmetric, moveHandleTo, multiply, nearestPathAnchor, normalizeZoom, offsetCornerTraces, openEndAt, openEndRay, openPathEnds, openSubpathAt, pathAnchorPoints, pathAwayFromAnchors, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathCrossings, pathDistanceToPoint, pathEndAnchorIndex, pathEndFrame, pathFromD, pathInPoseFrame, pathInWorld, pathIntersectsPolygon, pathIntersectsRect, pathSegments, pathShape, pathSignedArea, pathThroughPoseFrame, pathToCubicContours, pathToD, placeAlongRun, placeRect, pointAlongPath, pointInPath, polygonContainsPath, polygonIntersectsPath, portControls2 as portControls, portCurvePoints2 as portCurvePoints, poseFrameInverseOf, poseFrameOf, poseLinearOf, poseRotationOf, prepareBlend, puckerBloatPath, pxExtent, pxExtentInFrame, readAnchorFields, rectMarkerPath, remapAnchorValues, remapConstraints, remapPointValues, repeatAlongPath, resamplePath, resolveEasing, retractHandles, reverseAnchors, reversePath, reverseSubpaths, reviveTypedArrays, rotate, rotateAboutPoint, rotatePathAround, roughenPath, roundRectPath, runLength, runPlaces, runStationAt, scale, scaleDelta, scalePathToBounds, scaleSegmentHandles, screenAngleOf, segmentAt2 as segmentAt, segmentBetween, segmentExtremaTs, segmentsBetweenAnchors, setSubpathStart, shiftTrack, shrinkAnchorSelection, simplifyAnchorsAt, simplifyPath, simplifySpan, simplifySubpath, smoothAnchors, smudgePath, softFalloff, softSelectionBand, softSelectionWeights, solveConstraints, solvePathConstraints, splitByClosure, splitSubpaths, squarePath, standoff, stationsAlongPath, strokeHitTest, subpathEndAt, subpathsOfAnchors, tagTypedArray, tagTypedArrays, trackRun, trackShapeD, trackSlice, transformCoords, transformPath, translate, translateAnchorBy, translateAnchorsSymmetric, translatePath, trimPathAt, typedArrayReplacer, unionBoundsPath, unsatisfiedConstraints, untagTypedArray, viewRectToScreen, viewScreenToWorld, viewToMat3, viewWorldToScreen, withAnchorPoints, withinPxBox, withinPxRadius, worldEditToStorage, writeAnchorField, zigzagPath };
7024
7021
  //# sourceMappingURL=index.js.map
7025
7022
  //# sourceMappingURL=index.js.map