danceflow-geometry 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,985 @@
1
+ function M(t) {
2
+ if (t.length === 0)
3
+ return { x: 0, y: 0 };
4
+ const n = t.reduce(
5
+ (r, e) => ({
6
+ x: r.x + e.x,
7
+ y: r.y + e.y
8
+ }),
9
+ { x: 0, y: 0 }
10
+ );
11
+ return {
12
+ x: n.x / t.length,
13
+ y: n.y / t.length
14
+ };
15
+ }
16
+ function rt(t, n, r) {
17
+ const e = r || M(t);
18
+ return t.map((c) => ({
19
+ x: e.x + (c.x - e.x) * n,
20
+ y: e.y + (c.y - e.y) * n,
21
+ facing: c.facing
22
+ // Facing doesn't change
23
+ }));
24
+ }
25
+ function ct(t, n) {
26
+ let r = !1;
27
+ for (let e = 0, c = n.length - 1; e < n.length; c = e++) {
28
+ const a = n[e].x, i = n[e].y, s = n[c].x, o = n[c].y;
29
+ i > t.y != o > t.y && t.x < (s - a) * (t.y - i) / (o - i) + a && (r = !r);
30
+ }
31
+ return r;
32
+ }
33
+ function at(t, n) {
34
+ const r = n.x - t.x, e = n.y - t.y;
35
+ return Math.sqrt(r * r + e * e);
36
+ }
37
+ function $(t, n, r, e, c = 0) {
38
+ if (t.length === 0) return [];
39
+ const a = e || M(t), i = c * Math.PI / 180, s = Math.cos(i), o = Math.sin(i);
40
+ return t.map((l) => {
41
+ let u = l.x - a.x, x = l.y - a.y;
42
+ if (c !== 0) {
43
+ const h = u * s - x * o, f = u * o + x * s;
44
+ u = h, x = f;
45
+ }
46
+ if (u *= n, x *= r, c !== 0) {
47
+ const h = u * s + x * o, f = -u * o + x * s;
48
+ u = h, x = f;
49
+ }
50
+ return {
51
+ x: u + a.x,
52
+ y: x + a.y,
53
+ facing: l.facing
54
+ };
55
+ });
56
+ }
57
+ function it(t, n) {
58
+ const { direction: r, scaleFactor: e, center: c, aspectRatio: a = 1, angle: i = 0 } = n;
59
+ let s, o, l;
60
+ switch (r) {
61
+ case "radial":
62
+ s = e, o = e, l = 0;
63
+ break;
64
+ case "horizontal":
65
+ s = e, o = 1, l = 0;
66
+ break;
67
+ case "vertical":
68
+ s = 1, o = e, l = 0;
69
+ break;
70
+ case "diagonal":
71
+ s = e, o = e, l = i || 45;
72
+ break;
73
+ default:
74
+ throw new Error(`Unknown spread direction: ${r}`);
75
+ }
76
+ return a !== 1 && (s *= a), $(t, s, o, c, l);
77
+ }
78
+ function st(t, n, r) {
79
+ if (t.length === 0) return 1;
80
+ const e = r || M(t), a = t.reduce((i, s) => {
81
+ const o = s.x - e.x, l = s.y - e.y;
82
+ return i + Math.sqrt(o * o + l * l);
83
+ }, 0) / t.length;
84
+ return a === 0 ? 1 : n / a;
85
+ }
86
+ function ot(t) {
87
+ if (t.length === 0)
88
+ return { minX: 0, maxX: 0, minY: 0, maxY: 0, width: 0, height: 0 };
89
+ let n = 1 / 0, r = -1 / 0, e = 1 / 0, c = -1 / 0;
90
+ return t.forEach((a) => {
91
+ n = Math.min(n, a.x), r = Math.max(r, a.x), e = Math.min(e, a.y), c = Math.max(c, a.y);
92
+ }), {
93
+ minX: n,
94
+ maxX: r,
95
+ minY: e,
96
+ maxY: c,
97
+ width: r - n,
98
+ height: c - e
99
+ };
100
+ }
101
+ function lt(t, n, r, e, c) {
102
+ if (t.length === 0) return !0;
103
+ const a = c || M(t);
104
+ return t.every((i) => {
105
+ const s = i.x - a.x, o = i.y - a.y, l = a.x + s * n, u = a.y + o * n, x = 20;
106
+ return l >= x && l <= r - x && u >= x && u <= e - x;
107
+ });
108
+ }
109
+ function E(t, n, r) {
110
+ if (t.length === 0)
111
+ throw new Error("Cannot arrange line with 0 dancers");
112
+ const e = M(t), a = (r || Math.max(400, t.length * 50)) / 2;
113
+ switch (n) {
114
+ case "horizontal":
115
+ return {
116
+ start: { x: e.x - a, y: e.y },
117
+ end: { x: e.x + a, y: e.y }
118
+ };
119
+ case "vertical":
120
+ return {
121
+ start: { x: e.x, y: e.y - a },
122
+ end: { x: e.x, y: e.y + a }
123
+ };
124
+ case "diagonal-45":
125
+ return {
126
+ start: {
127
+ x: e.x - a * Math.cos(Math.PI / 4),
128
+ y: e.y - a * Math.sin(Math.PI / 4)
129
+ },
130
+ end: {
131
+ x: e.x + a * Math.cos(Math.PI / 4),
132
+ y: e.y + a * Math.sin(Math.PI / 4)
133
+ }
134
+ };
135
+ case "diagonal-135":
136
+ return {
137
+ start: {
138
+ x: e.x - a * Math.cos(3 * Math.PI / 4),
139
+ y: e.y - a * Math.sin(3 * Math.PI / 4)
140
+ },
141
+ end: {
142
+ x: e.x + a * Math.cos(3 * Math.PI / 4),
143
+ y: e.y + a * Math.sin(3 * Math.PI / 4)
144
+ }
145
+ };
146
+ default:
147
+ throw new Error(`Unknown line orientation: ${n}`);
148
+ }
149
+ }
150
+ function T(t, n, r, e) {
151
+ if (typeof e == "number")
152
+ return e;
153
+ const c = Math.atan2(r.y, r.x) * (180 / Math.PI);
154
+ switch (e) {
155
+ case "auto":
156
+ case "forward":
157
+ return (c + 90) % 360;
158
+ case "backward":
159
+ return (c + 270) % 360;
160
+ case "center":
161
+ return t < n / 2 ? (c + 90) % 360 : (c + 270) % 360;
162
+ default:
163
+ return 0;
164
+ }
165
+ }
166
+ function N(t, n) {
167
+ const r = t.length;
168
+ if (r === 0)
169
+ return [];
170
+ const { orientation: e, spacing: c, startPoint: a, endPoint: i, faceDirection: s = "auto", lineLength: o } = n;
171
+ let l, u;
172
+ if (a && i)
173
+ l = a, u = i;
174
+ else if (c && r > 1) {
175
+ const h = c * (r - 1), f = M(t), g = h / 2, d = E(t, e, h), y = d.end.x - d.start.x, A = d.end.y - d.start.y, m = Math.sqrt(y * y + A * A);
176
+ if (m === 0)
177
+ throw new Error("Invalid line orientation");
178
+ const I = y / m * g, S = A / m * g;
179
+ l = { x: f.x - I, y: f.y - S }, u = { x: f.x + I, y: f.y + S };
180
+ } else {
181
+ const h = E(t, e, o);
182
+ l = h.start, u = h.end;
183
+ }
184
+ const x = {
185
+ x: u.x - l.x,
186
+ y: u.y - l.y
187
+ };
188
+ return r === 1 ? [
189
+ {
190
+ x: (l.x + u.x) / 2,
191
+ y: (l.y + u.y) / 2,
192
+ facing: T(0, 1, x, s)
193
+ }
194
+ ] : t.map((h, f) => {
195
+ const g = f / (r - 1), d = l.x + g * (u.x - l.x), y = l.y + g * (u.y - l.y);
196
+ return {
197
+ x: d,
198
+ y,
199
+ facing: T(f, r, x, s)
200
+ };
201
+ });
202
+ }
203
+ function ut(t, n, r = !1) {
204
+ const e = n.x - t.x, c = n.y - t.y, i = (Math.atan2(c, e) * (180 / Math.PI) % 360 + 360) % 360;
205
+ let s, o = t, l = n;
206
+ if (r)
207
+ if (i >= 337.5 || i < 22.5) {
208
+ s = "horizontal";
209
+ const u = (t.y + n.y) / 2;
210
+ o = { x: t.x, y: u }, l = { x: n.x, y: u };
211
+ } else if (i >= 22.5 && i < 67.5)
212
+ s = "diagonal-45";
213
+ else if (i >= 67.5 && i < 112.5) {
214
+ s = "vertical";
215
+ const u = (t.x + n.x) / 2;
216
+ o = { x: u, y: t.y }, l = { x: u, y: n.y };
217
+ } else if (i >= 112.5 && i < 157.5)
218
+ s = "diagonal-135";
219
+ else if (i >= 157.5 && i < 202.5) {
220
+ s = "horizontal";
221
+ const u = (t.y + n.y) / 2;
222
+ o = { x: t.x, y: u }, l = { x: n.x, y: u };
223
+ } else if (i >= 202.5 && i < 247.5)
224
+ s = "diagonal-45";
225
+ else if (i >= 247.5 && i < 292.5) {
226
+ s = "vertical";
227
+ const u = (t.x + n.x) / 2;
228
+ o = { x: u, y: t.y }, l = { x: u, y: n.y };
229
+ } else
230
+ s = "diagonal-135";
231
+ else
232
+ Math.abs(e) > Math.abs(c) * 2 ? s = "horizontal" : Math.abs(c) > Math.abs(e) * 2 ? s = "vertical" : e * c > 0 ? s = "diagonal-45" : s = "diagonal-135";
233
+ return {
234
+ orientation: s,
235
+ start: o,
236
+ end: l
237
+ };
238
+ }
239
+ function xt(t, n, r = 1e3, e = 1e3, c = 20) {
240
+ return t.length === 0 ? !0 : N(t, n).every(
241
+ (i) => i.x >= c && i.x <= r - c && i.y >= c && i.y <= e - c
242
+ );
243
+ }
244
+ function C(t) {
245
+ return t * Math.PI / 180;
246
+ }
247
+ function w(t) {
248
+ return t * 180 / Math.PI;
249
+ }
250
+ function _(t) {
251
+ switch (t) {
252
+ case "full":
253
+ return 360;
254
+ case "half":
255
+ return 180;
256
+ case "quarter":
257
+ return 90;
258
+ case "three-quarter":
259
+ return 270;
260
+ case "custom":
261
+ return 180;
262
+ // Default for custom
263
+ default:
264
+ return 360;
265
+ }
266
+ }
267
+ function O(t, n, r, e) {
268
+ if (typeof e == "number")
269
+ return e;
270
+ switch (e) {
271
+ case "center": {
272
+ const c = n.x - t.x, a = n.y - t.y, i = Math.atan2(-a, c);
273
+ return ((w(i) + 90) % 360 + 360) % 360;
274
+ }
275
+ case "outward": {
276
+ const c = t.x - n.x, a = t.y - n.y, i = Math.atan2(-a, c);
277
+ return ((w(i) + 90) % 360 + 360) % 360;
278
+ }
279
+ case "tangent": {
280
+ const c = r + Math.PI / 2;
281
+ return ((w(c) + 90) % 360 + 360) % 360;
282
+ }
283
+ case "counter-tangent": {
284
+ const c = r - Math.PI / 2;
285
+ return ((w(c) + 90) % 360 + 360) % 360;
286
+ }
287
+ default:
288
+ return 0;
289
+ }
290
+ }
291
+ function U(t, n, r = 1e3, e = 1e3, c = 50) {
292
+ const a = Math.min(t.x - c, r - t.x - c), i = Math.min(t.y - c, e - t.y - c), s = Math.min(a, i), l = n * 40 / (2 * Math.PI);
293
+ return Math.min(s, l, 400);
294
+ }
295
+ function P(t, n = {}) {
296
+ const r = t.length;
297
+ if (r === 0)
298
+ return [];
299
+ const {
300
+ preset: e = "full",
301
+ arcAngle: c,
302
+ startAngle: a = 0,
303
+ radius: i,
304
+ center: s,
305
+ faceDirection: o = "center",
306
+ distributeEvenly: l = !0
307
+ } = n, u = s || M(t), x = c !== void 0 ? c : _(e), h = i !== void 0 ? i : U(u, r);
308
+ if (h <= 0)
309
+ throw new Error("Circle radius must be positive");
310
+ const f = C(a - 90), g = Math.abs(x % 360) < 1e-3;
311
+ let d;
312
+ if (r === 1)
313
+ d = [f];
314
+ else if (g) {
315
+ const y = 2 * Math.PI / r;
316
+ d = Array.from({ length: r }, (A, m) => f + m * y);
317
+ } else if (l) {
318
+ const y = C(x);
319
+ d = Array.from({ length: r }, (A, m) => {
320
+ const I = m / (r - 1);
321
+ return f + I * y;
322
+ });
323
+ } else {
324
+ const A = C(x) / r;
325
+ d = Array.from({ length: r }, (m, I) => f + I * A);
326
+ }
327
+ return d.map((y) => {
328
+ const A = u.x + h * Math.cos(y), m = u.y + h * Math.sin(y);
329
+ return {
330
+ x: A,
331
+ y: m,
332
+ facing: O({ x: A, y: m }, u, y, o)
333
+ };
334
+ });
335
+ }
336
+ function ht(t, n) {
337
+ const r = t.length;
338
+ if (r === 0)
339
+ return [];
340
+ const {
341
+ rings: e,
342
+ radiusStep: c = 100,
343
+ innerRadius: a = 150,
344
+ center: i,
345
+ faceDirection: s = "center"
346
+ } = n;
347
+ if (e < 1)
348
+ throw new Error("Must have at least 1 ring");
349
+ const o = i || M(t), l = Math.ceil(r / e), u = [];
350
+ let x = 0;
351
+ for (let h = 0; h < e && x < r; h++) {
352
+ const f = a + h * c, g = Math.min(l, r - x), d = Array.from({ length: g }, () => ({
353
+ x: 0,
354
+ y: 0,
355
+ facing: 0
356
+ })), y = P(d, {
357
+ preset: "full",
358
+ radius: f,
359
+ center: o,
360
+ faceDirection: s
361
+ });
362
+ u.push(...y), x += g;
363
+ }
364
+ return u;
365
+ }
366
+ function ft(t, n, r = 1e3, e = 1e3, c = 20) {
367
+ return t.length === 0 ? !0 : P(t, n).every(
368
+ (i) => i.x >= c && i.x <= r - c && i.y >= c && i.y <= e - c
369
+ );
370
+ }
371
+ function yt(t, n, r) {
372
+ const e = t.x, c = t.y, a = n.x, i = n.y, s = r.x, o = r.y, l = 2 * (e * (i - o) + a * (o - c) + s * (c - i));
373
+ if (Math.abs(l) < 1e-3)
374
+ return null;
375
+ const u = ((e * e + c * c) * (i - o) + (a * a + i * i) * (o - c) + (s * s + o * o) * (c - i)) / l, x = ((e * e + c * c) * (s - a) + (a * a + i * i) * (e - s) + (s * s + o * o) * (a - e)) / l, h = { x: u, y: x }, f = t.x - h.x, g = t.y - h.y, d = Math.sqrt(f * f + g * g), y = Math.atan2(-(t.y - h.y), t.x - h.x);
376
+ let m = Math.atan2(-(r.y - h.y), r.x - h.x) - y;
377
+ m < 0 && (m += 2 * Math.PI);
378
+ const I = (w(y) + 90 + 360) % 360, S = w(m);
379
+ return {
380
+ center: h,
381
+ radius: d,
382
+ startAngle: I,
383
+ arcAngle: S
384
+ };
385
+ }
386
+ function H(t) {
387
+ return (360 - t) % 360;
388
+ }
389
+ function K(t) {
390
+ return (180 - t + 360) % 360;
391
+ }
392
+ function b(t, n) {
393
+ if (t.length === 0)
394
+ return [];
395
+ const { axis: e, axisPosition: c, center: a, mirrorFacing: i = !0 } = n;
396
+ let s;
397
+ if (c !== void 0)
398
+ s = c;
399
+ else if (a)
400
+ s = e === "horizontal" ? a.x : a.y;
401
+ else {
402
+ const o = M(t);
403
+ s = e === "horizontal" ? o.x : o.y;
404
+ }
405
+ return t.map((o) => {
406
+ let l = o.x, u = o.y, x = o.facing;
407
+ return e === "horizontal" ? (l = 2 * s - o.x, i && (x = H(o.facing))) : (u = 2 * s - o.y, i && (x = K(o.facing))), {
408
+ x: l,
409
+ y: u,
410
+ facing: x
411
+ };
412
+ });
413
+ }
414
+ function dt(t, n) {
415
+ const r = b(t, n);
416
+ return [...t, ...r];
417
+ }
418
+ function V(t, n, r = !0) {
419
+ if (t.length === 0)
420
+ return [];
421
+ const c = n || M(t);
422
+ return t.map((a) => {
423
+ const i = 2 * c.x - a.x, s = 2 * c.y - a.y, o = r ? (a.facing + 180) % 360 : a.facing;
424
+ return {
425
+ x: i,
426
+ y: s,
427
+ facing: o
428
+ };
429
+ });
430
+ }
431
+ function gt(t, n) {
432
+ const r = n || M(t), e = t, c = b(t, {
433
+ axis: "horizontal",
434
+ center: r
435
+ }), a = b(t, {
436
+ axis: "vertical",
437
+ center: r
438
+ }), i = V(t, r);
439
+ return [...e, ...c, ...a, ...i];
440
+ }
441
+ function mt(t, n, r = 1e3, e = 1e3, c = 20) {
442
+ return t.length === 0 ? !0 : b(t, n).every(
443
+ (i) => i.x >= c && i.x <= r - c && i.y >= c && i.y <= e - c
444
+ );
445
+ }
446
+ function Mt(t, n) {
447
+ const r = Math.abs(n.x - t.x), e = Math.abs(n.y - t.y);
448
+ return r < e ? {
449
+ axis: "horizontal",
450
+ axisPosition: (t.x + n.x) / 2
451
+ } : {
452
+ axis: "vertical",
453
+ axisPosition: (t.y + n.y) / 2
454
+ };
455
+ }
456
+ function At(t, n, r = 10) {
457
+ const e = [], c = /* @__PURE__ */ new Set();
458
+ for (let a = 0; a < t.length; a++) {
459
+ if (c.has(a)) continue;
460
+ const i = b([t[a]], n)[0];
461
+ for (let s = a + 1; s < t.length; s++) {
462
+ if (c.has(s)) continue;
463
+ const o = t[s].x - i.x, l = t[s].y - i.y;
464
+ if (Math.sqrt(o * o + l * l) < r) {
465
+ e.push([a, s]), c.add(a), c.add(s);
466
+ break;
467
+ }
468
+ }
469
+ }
470
+ return e;
471
+ }
472
+ function G(t) {
473
+ return t * Math.PI / 180;
474
+ }
475
+ function J(t) {
476
+ return (t % 360 + 360) % 360;
477
+ }
478
+ function Q(t, n, r) {
479
+ const e = Math.cos(r), c = Math.sin(r), a = t.x - n.x, i = t.y - n.y;
480
+ return {
481
+ x: n.x + a * e - i * c,
482
+ // Negate the Y rotation to account for Y-down coordinate system
483
+ y: n.y - (a * c - i * e)
484
+ };
485
+ }
486
+ function Y(t, n) {
487
+ if (t.length === 0)
488
+ return [];
489
+ const { angle: e, center: c, rotateFacing: a = !0 } = n, i = c || M(t), s = G(e);
490
+ return t.map((o) => {
491
+ const l = Q({ x: o.x, y: o.y }, i, s);
492
+ return {
493
+ x: l.x,
494
+ y: l.y,
495
+ facing: a ? J(o.facing + e) : o.facing
496
+ };
497
+ });
498
+ }
499
+ function It(t, n, r) {
500
+ return Y(t, {
501
+ angle: n,
502
+ center: r
503
+ });
504
+ }
505
+ function wt(t, n, r) {
506
+ if (n < 1)
507
+ throw new Error("Number of copies must be at least 1");
508
+ if (t.length === 0)
509
+ return [];
510
+ const e = r || M(t), c = 360 / n, a = [];
511
+ for (let i = 0; i < n; i++) {
512
+ const s = i * c, o = Y(t, {
513
+ angle: s,
514
+ center: e
515
+ });
516
+ a.push(...o);
517
+ }
518
+ return a;
519
+ }
520
+ function Rt(t, n, r, e, c) {
521
+ if (e < 2)
522
+ throw new Error("Animation requires at least 2 steps");
523
+ const a = c || M(t), i = [];
524
+ for (let s = 0; s < e; s++) {
525
+ const o = s / (e - 1), l = n + o * (r - n), u = Y(t, {
526
+ angle: l,
527
+ center: a
528
+ });
529
+ i.push(u);
530
+ }
531
+ return i;
532
+ }
533
+ function bt(t, n, r) {
534
+ const e = Math.atan2(-(n.y - t.y), n.x - t.x);
535
+ let a = Math.atan2(-(r.y - t.y), r.x - t.x) - e;
536
+ return a > Math.PI ? a -= 2 * Math.PI : a < -Math.PI && (a += 2 * Math.PI), a * 180 / Math.PI;
537
+ }
538
+ function St(t, n = 45) {
539
+ return Math.round(t / n) * n;
540
+ }
541
+ function Xt(t, n, r = 1e3, e = 1e3, c = 20) {
542
+ return t.length === 0 ? !0 : Y(t, n).every(
543
+ (i) => i.x >= c && i.x <= r - c && i.y >= c && i.y <= e - c
544
+ );
545
+ }
546
+ function Yt(t) {
547
+ if (t.length === 0) return 0;
548
+ let n = 1 / 0, r = -1 / 0, e = 1 / 0, c = -1 / 0;
549
+ t.forEach((s) => {
550
+ n = Math.min(n, s.x), r = Math.max(r, s.x), e = Math.min(e, s.y), c = Math.max(c, s.y);
551
+ });
552
+ const a = r - n, i = c - e;
553
+ return Math.sqrt(a * a + i * i);
554
+ }
555
+ function Ct(t, n = 1e3, r = 1e3, e = 20) {
556
+ const c = t.x - e, a = n - t.x - e, i = t.y - e, s = r - t.y - e;
557
+ return Math.min(c, a, i, s);
558
+ }
559
+ function j(t) {
560
+ if (t.length < 2)
561
+ return { minX: 0, maxX: 0, minY: 0, maxY: 0 };
562
+ let n = 1 / 0, r = -1 / 0, e = 1 / 0, c = -1 / 0;
563
+ for (let a = 0; a < t.length; a += 2) {
564
+ const i = t[a], s = t[a + 1];
565
+ n = Math.min(n, i), r = Math.max(r, i), e = Math.min(e, s), c = Math.max(c, s);
566
+ }
567
+ return { minX: n, maxX: r, minY: e, maxY: c };
568
+ }
569
+ function vt(t, n) {
570
+ if (n.length < 6) return !1;
571
+ let r = !1;
572
+ const e = n.length / 2;
573
+ for (let c = 0, a = e - 1; c < e; a = c++) {
574
+ const i = n[c * 2], s = n[c * 2 + 1], o = n[a * 2], l = n[a * 2 + 1];
575
+ s > t.y != l > t.y && t.x < (o - i) * (t.y - s) / (l - s) + i && (r = !r);
576
+ }
577
+ return r;
578
+ }
579
+ function W(t, n, r) {
580
+ if (n.length < 6) return !1;
581
+ const e = r || j(n);
582
+ if (t.x < e.minX || t.x > e.maxX || t.y < e.minY || t.y > e.maxY)
583
+ return !1;
584
+ let c = !1;
585
+ const a = n.length / 2;
586
+ for (let i = 0, s = a - 1; i < a; s = i++) {
587
+ const o = n[i * 2], l = n[i * 2 + 1], u = n[s * 2], x = n[s * 2 + 1];
588
+ if (l === x) continue;
589
+ l > t.y != x > t.y && t.x < (u - o) * (t.y - l) / (x - l) + o && (c = !c);
590
+ }
591
+ return c;
592
+ }
593
+ function zt(t, n) {
594
+ if (n.length < 6)
595
+ return t.map(() => !1);
596
+ const r = j(n);
597
+ return t.map((e) => W(e, n, r));
598
+ }
599
+ function Et(t) {
600
+ if (t.length < 6) return 0;
601
+ let n = 0;
602
+ const r = t.length / 2;
603
+ for (let e = 0; e < r; e++) {
604
+ const c = (e + 1) % r, a = t[e * 2], i = t[e * 2 + 1], s = t[c * 2], o = t[c * 2 + 1];
605
+ n += a * o - s * i;
606
+ }
607
+ return n / 2;
608
+ }
609
+ function Tt(t) {
610
+ if (t.length < 6)
611
+ return { x: 0, y: 0 };
612
+ let n = 0, r = 0, e = 0;
613
+ const c = t.length / 2;
614
+ for (let a = 0; a < c; a++) {
615
+ const i = (a + 1) % c, s = t[a * 2], o = t[a * 2 + 1], l = t[i * 2], u = t[i * 2 + 1], x = s * u - l * o;
616
+ n += (s + l) * x, r += (o + u) * x, e += x;
617
+ }
618
+ if (e /= 2, Math.abs(e) < 1e-4) {
619
+ let a = 0, i = 0;
620
+ for (let s = 0; s < t.length; s += 2)
621
+ a += t[s], i += t[s + 1];
622
+ return { x: a / c, y: i / c };
623
+ }
624
+ return {
625
+ x: n / (6 * e),
626
+ y: r / (6 * e)
627
+ };
628
+ }
629
+ function Pt(t, n) {
630
+ if (t.length < 6) return [...t];
631
+ const r = [];
632
+ r.push(t[0], t[1]);
633
+ for (let e = 2; e < t.length; e += 2) {
634
+ const c = r[r.length - 2], a = r[r.length - 1], i = t[e], s = t[e + 1], o = i - c, l = s - a;
635
+ Math.sqrt(o * o + l * l) >= n && r.push(i, s);
636
+ }
637
+ return r;
638
+ }
639
+ const v = 80, F = 20;
640
+ function L(t, n, r, e, c) {
641
+ const a = t * t, i = a * t, s = 1 - t, o = s * s, u = o * s, x = 3 * o * t, h = 3 * s * a, f = i;
642
+ return {
643
+ x: u * n.x + x * r.x + h * e.x + f * c.x,
644
+ y: u * n.y + x * r.y + h * e.y + f * c.y
645
+ };
646
+ }
647
+ function D(t, n, r) {
648
+ const e = (t.x + n.x) / 2, c = (t.y + n.y) / 2, a = n.x - t.x, s = -(n.y - t.y), o = a, l = Math.sqrt(s * s + o * o);
649
+ if (l < 1e-4) {
650
+ const y = { x: e, y: c };
651
+ return [y, y];
652
+ }
653
+ const u = s / l, x = o / l, h = -u * r, f = -x * r, g = {
654
+ x: e + h,
655
+ y: c + f
656
+ }, d = {
657
+ x: e + h,
658
+ y: c + f
659
+ };
660
+ return [g, d];
661
+ }
662
+ function Z(t, n, r = v, e = F) {
663
+ if (e < 2)
664
+ throw new Error("Number of interpolation points must be at least 2");
665
+ const [c, a] = D(t, n, r), i = [];
666
+ for (let s = 0; s < e; s++) {
667
+ const o = s / (e - 1), l = L(
668
+ o,
669
+ { x: t.x, y: t.y },
670
+ // P0 - start
671
+ c,
672
+ // P1 - first control point
673
+ a,
674
+ // P2 - second control point
675
+ { x: n.x, y: n.y }
676
+ // P3 - end
677
+ );
678
+ i.push(l);
679
+ }
680
+ return i;
681
+ }
682
+ function jt(t, n, r = 150) {
683
+ const e = n.x - t.x, c = n.y - t.y, i = Math.sqrt(e * e + c * c) * 0.15;
684
+ return Math.min(i, r);
685
+ }
686
+ function Ft(t, n, r = v, e = F) {
687
+ const c = Z(t, n, r, e);
688
+ let a = 0;
689
+ for (let i = 1; i < c.length; i++) {
690
+ const s = c[i].x - c[i - 1].x, o = c[i].y - c[i - 1].y;
691
+ a += Math.sqrt(s * s + o * o);
692
+ }
693
+ return a;
694
+ }
695
+ function Lt(t, n, r, e = v) {
696
+ const c = Math.max(0, Math.min(1, r)), [a, i] = D(t, n, e);
697
+ return L(
698
+ c,
699
+ { x: t.x, y: t.y },
700
+ a,
701
+ i,
702
+ { x: n.x, y: n.y }
703
+ );
704
+ }
705
+ function z(t, n, r, e, c) {
706
+ const a = c * c, i = a * c, s = 0.5 * (2 * n.x + (-t.x + r.x) * c + (2 * t.x - 5 * n.x + 4 * r.x - e.x) * a + (-t.x + 3 * n.x - 3 * r.x + e.x) * i), o = 0.5 * (2 * n.y + (-t.y + r.y) * c + (2 * t.y - 5 * n.y + 4 * r.y - e.y) * a + (-t.y + 3 * n.y - 3 * r.y + e.y) * i);
707
+ return { x: s, y: o };
708
+ }
709
+ function Dt(t, n = 20) {
710
+ if (t.length < 2)
711
+ return [...t];
712
+ if (t.length === 2)
713
+ return [t[0], t[1]];
714
+ const r = [];
715
+ for (let e = 0; e < t.length - 1; e++) {
716
+ const c = e === 0 ? t[0] : t[e - 1], a = t[e], i = t[e + 1], s = e === t.length - 2 ? t[e + 1] : t[e + 2];
717
+ for (let o = 0; o < n; o++) {
718
+ const l = o / n, u = z(c, a, i, s, l);
719
+ r.push(u);
720
+ }
721
+ }
722
+ return r.push(t[t.length - 1]), r;
723
+ }
724
+ function p(t, n, r, e) {
725
+ const c = {
726
+ x: n.x + (r.x - t.x) / 6,
727
+ y: n.y + (r.y - t.y) / 6
728
+ }, a = {
729
+ x: r.x - (e.x - n.x) / 6,
730
+ y: r.y - (e.y - n.y) / 6
731
+ };
732
+ return {
733
+ start: n,
734
+ control1: c,
735
+ control2: a,
736
+ end: r
737
+ };
738
+ }
739
+ function qt(t) {
740
+ if (t.length < 2)
741
+ return [];
742
+ const n = [];
743
+ for (let r = 0; r < t.length - 1; r++) {
744
+ const e = r === 0 ? t[0] : t[r - 1], c = t[r], a = t[r + 1], i = r === t.length - 2 ? t[r + 1] : t[r + 2];
745
+ n.push(p(e, c, a, i));
746
+ }
747
+ return n;
748
+ }
749
+ function tt(t, n, r, e, c) {
750
+ const a = c * c, i = 0.5 * (-t.x + r.x + 2 * (2 * t.x - 5 * n.x + 4 * r.x - e.x) * c + 3 * (-t.x + 3 * n.x - 3 * r.x + e.x) * a), s = 0.5 * (-t.y + r.y + 2 * (2 * t.y - 5 * n.y + 4 * r.y - e.y) * c + 3 * (-t.y + 3 * n.y - 3 * r.y + e.y) * a);
751
+ return { x: i, y: s };
752
+ }
753
+ function Bt(t, n, r, e, c) {
754
+ const a = tt(t, n, r, e, c);
755
+ return Math.atan2(a.y, a.x) * 180 / Math.PI;
756
+ }
757
+ function kt(t, n, r, e, c = 100) {
758
+ let a = 0, i = n;
759
+ for (let s = 1; s <= c; s++) {
760
+ const o = s / c, l = z(t, n, r, e, o), u = l.x - i.x, x = l.y - i.y;
761
+ a += Math.sqrt(u * u + x * x), i = l;
762
+ }
763
+ return a;
764
+ }
765
+ function $t(t, n) {
766
+ if (t.length < 2)
767
+ return [...t];
768
+ const r = [t[0]];
769
+ let e = 0, c = n;
770
+ for (let a = 0; a < t.length - 1; a++) {
771
+ const i = a === 0 ? t[0] : t[a - 1], s = t[a], o = t[a + 1], l = a === t.length - 2 ? t[a + 1] : t[a + 2];
772
+ let u = s;
773
+ const x = 100;
774
+ for (let h = 1; h <= x; h++) {
775
+ const f = h / x, g = z(i, s, o, l, f), d = g.x - u.x, y = g.y - u.y, A = Math.sqrt(d * d + y * y);
776
+ e += A, e >= c && (r.push(g), c += n), u = g;
777
+ }
778
+ }
779
+ return r;
780
+ }
781
+ const R = 20;
782
+ function X(t, n = R) {
783
+ return {
784
+ minX: t.x - n,
785
+ maxX: t.x + n,
786
+ minY: t.y - n,
787
+ maxY: t.y + n
788
+ };
789
+ }
790
+ function q(t, n) {
791
+ return t.maxX >= n.minX && t.minX <= n.maxX && t.maxY >= n.minY && t.minY <= n.maxY;
792
+ }
793
+ function B(t, n, r = R, e = R) {
794
+ const c = n.x - t.x, a = n.y - t.y, i = c * c + a * a, s = r + e;
795
+ return i < s * s;
796
+ }
797
+ function k(t, n) {
798
+ const r = n.x - t.x, e = n.y - t.y;
799
+ return Math.sqrt(r * r + e * e);
800
+ }
801
+ function nt(t, n = R) {
802
+ const r = [];
803
+ for (let e = 0; e < t.length; e++)
804
+ for (let c = e + 1; c < t.length; c++) {
805
+ const a = t[e], i = t[c], s = X(a.position, n), o = X(i.position, n);
806
+ if (q(s, o) && B(a.position, i.position, n, n)) {
807
+ const l = k(a.position, i.position), u = n * 2 - l;
808
+ r.push({
809
+ id1: a.id,
810
+ id2: i.id,
811
+ distance: l,
812
+ penetration: u
813
+ });
814
+ }
815
+ }
816
+ return r;
817
+ }
818
+ class et {
819
+ /**
820
+ * Create a new spatial hash grid
821
+ *
822
+ * @param radius - Dancer radius (default: 20)
823
+ * @param cellSize - Grid cell size (default: 2 * radius = 40)
824
+ */
825
+ constructor(n = R, r) {
826
+ this.radius = n, this.cellSize = r || n * 2, this.grid = /* @__PURE__ */ new Map();
827
+ }
828
+ /**
829
+ * Compute hash key for a position
830
+ *
831
+ * @param x - X coordinate
832
+ * @param y - Y coordinate
833
+ * @returns Grid cell key
834
+ */
835
+ hashKey(n, r) {
836
+ const e = Math.floor(n / this.cellSize), c = Math.floor(r / this.cellSize);
837
+ return `${e},${c}`;
838
+ }
839
+ /**
840
+ * Insert a dancer into the spatial grid
841
+ *
842
+ * @param id - Dancer ID
843
+ * @param position - Dancer position
844
+ */
845
+ insert(n, r) {
846
+ const e = this.hashKey(r.x, r.y);
847
+ this.grid.has(e) || this.grid.set(e, []), this.grid.get(e).push({ id: n, position: r });
848
+ }
849
+ /**
850
+ * Get all dancers in the same or adjacent cells
851
+ *
852
+ * @param position - Query position
853
+ * @returns Array of nearby dancers
854
+ */
855
+ getNearby(n) {
856
+ const r = [], e = Math.floor(n.x / this.cellSize), c = Math.floor(n.y / this.cellSize);
857
+ for (let a = -1; a <= 1; a++)
858
+ for (let i = -1; i <= 1; i++) {
859
+ const s = `${e + a},${c + i}`, o = this.grid.get(s);
860
+ o && r.push(...o);
861
+ }
862
+ return r;
863
+ }
864
+ /**
865
+ * Clear all entries from the grid
866
+ */
867
+ clear() {
868
+ this.grid.clear();
869
+ }
870
+ /**
871
+ * Detect all collisions using spatial hashing
872
+ *
873
+ * @param dancers - Array of dancer IDs and positions
874
+ * @returns Array of collision pairs
875
+ */
876
+ detectCollisions(n) {
877
+ this.clear(), n.forEach((c) => this.insert(c.id, c.position));
878
+ const r = [], e = /* @__PURE__ */ new Set();
879
+ return n.forEach((c) => {
880
+ this.getNearby(c.position).forEach((i) => {
881
+ if (c.id === i.id) return;
882
+ const s = c.id < i.id ? `${c.id}:${i.id}` : `${i.id}:${c.id}`;
883
+ if (e.has(s)) return;
884
+ e.add(s);
885
+ const o = X(c.position, this.radius), l = X(i.position, this.radius);
886
+ if (q(o, l) && B(c.position, i.position, this.radius, this.radius)) {
887
+ const u = k(c.position, i.position), x = this.radius * 2 - u;
888
+ r.push({
889
+ id1: c.id,
890
+ id2: i.id,
891
+ distance: u,
892
+ penetration: x
893
+ });
894
+ }
895
+ });
896
+ }), r;
897
+ }
898
+ /**
899
+ * Get statistics about the grid (for debugging/optimization)
900
+ *
901
+ * @returns Grid statistics
902
+ */
903
+ getStats() {
904
+ const n = this.grid.size;
905
+ let r = 0, e = 0;
906
+ return this.grid.forEach((c) => {
907
+ r += c.length, e = Math.max(e, c.length);
908
+ }), {
909
+ totalCells: this.grid.size * 9,
910
+ // Account for neighbor checks
911
+ occupiedCells: n,
912
+ totalDancers: r,
913
+ avgDancersPerCell: n > 0 ? r / n : 0,
914
+ maxDancersInCell: e
915
+ };
916
+ }
917
+ }
918
+ function Nt(t, n = R) {
919
+ return t.length < 50 ? nt(t, n) : new et(n).detectCollisions(t);
920
+ }
921
+ const _t = "1.0.0";
922
+ export {
923
+ R as DANCER_RADIUS,
924
+ et as SpatialHashGrid,
925
+ _t as VERSION,
926
+ Rt as animateRotation,
927
+ P as arrangeInCircle,
928
+ ht as arrangeInConcentricCircles,
929
+ N as arrangeInLine,
930
+ zt as batchPointInPolygon,
931
+ D as calculateArcControlPoints,
932
+ yt as calculateArcFromThreePoints,
933
+ Ft as calculateArcLength,
934
+ M as calculateCentroid,
935
+ k as calculateDistance,
936
+ ut as calculateLineFromDrag,
937
+ Mt as calculateMirrorAxisFromDrag,
938
+ jt as calculateOptimalArcHeight,
939
+ bt as calculateRotationFromDrag,
940
+ st as calculateSpreadFactorForDistance,
941
+ Z as calculateSwapArcPath,
942
+ Bt as catmullRomAngle,
943
+ kt as catmullRomArcLength,
944
+ z as catmullRomPoint,
945
+ Dt as catmullRomSpline,
946
+ qt as catmullRomSplineToBezier,
947
+ tt as catmullRomTangent,
948
+ p as catmullRomToBezier,
949
+ $t as catmullRomUniformSample,
950
+ q as checkAABBOverlap,
951
+ B as checkCircleCollision,
952
+ j as computeBoundingBox,
953
+ X as createAABB,
954
+ gt as createKaleidoscope,
955
+ wt as createRotationalCopies,
956
+ L as cubicBezier,
957
+ nt as detectCollisions,
958
+ Nt as detectCollisionsAuto,
959
+ it as directionalSpread,
960
+ at as distance,
961
+ $ as ellipticalScale,
962
+ At as findSymmetricPairs,
963
+ Lt as getArcPositionAtTime,
964
+ ot as getBoundingBox,
965
+ Yt as getBoundingBoxDiagonal,
966
+ Ct as getMaxRotationRadius,
967
+ ft as isCircleArrangementSafe,
968
+ xt as isLineArrangementSafe,
969
+ mt as isMirrorSafe,
970
+ vt as isPointInPolygon,
971
+ W as isPointInPolygonOptimized,
972
+ Xt as isRotationSafe,
973
+ lt as isSpreadSafe,
974
+ dt as mirrorAndDuplicate,
975
+ V as mirrorBothAxes,
976
+ b as mirrorFormation,
977
+ ct as pointInPolygon,
978
+ Et as polygonArea,
979
+ Tt as polygonCentroid,
980
+ Y as rotateFormation,
981
+ It as rotateFormationPreset,
982
+ rt as scaleAroundCenter,
983
+ Pt as simplifyPolygon,
984
+ St as snapRotationAngle
985
+ };