@sarmal/core 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/auto-init.cjs +113 -44
  2. package/dist/auto-init.cjs.map +1 -1
  3. package/dist/auto-init.js +113 -44
  4. package/dist/auto-init.js.map +1 -1
  5. package/dist/curves/artemis2.cjs +79 -11
  6. package/dist/curves/artemis2.cjs.map +1 -1
  7. package/dist/curves/artemis2.d.cts +1 -5
  8. package/dist/curves/artemis2.d.ts +1 -5
  9. package/dist/curves/artemis2.js +79 -11
  10. package/dist/curves/artemis2.js.map +1 -1
  11. package/dist/curves/astroid.d.cts +1 -1
  12. package/dist/curves/astroid.d.ts +1 -1
  13. package/dist/curves/deltoid.d.cts +1 -1
  14. package/dist/curves/deltoid.d.ts +1 -1
  15. package/dist/curves/epicycloid3.d.cts +1 -1
  16. package/dist/curves/epicycloid3.d.ts +1 -1
  17. package/dist/curves/epitrochoid7.d.cts +1 -1
  18. package/dist/curves/epitrochoid7.d.ts +1 -1
  19. package/dist/curves/index.cjs +103 -35
  20. package/dist/curves/index.cjs.map +1 -1
  21. package/dist/curves/index.d.cts +1 -1
  22. package/dist/curves/index.d.ts +1 -1
  23. package/dist/curves/index.js +103 -35
  24. package/dist/curves/index.js.map +1 -1
  25. package/dist/curves/lame.d.cts +1 -1
  26. package/dist/curves/lame.d.ts +1 -1
  27. package/dist/curves/lissajous32.d.cts +1 -1
  28. package/dist/curves/lissajous32.d.ts +1 -1
  29. package/dist/curves/lissajous43.d.cts +1 -1
  30. package/dist/curves/lissajous43.d.ts +1 -1
  31. package/dist/curves/rose3.d.cts +1 -1
  32. package/dist/curves/rose3.d.ts +1 -1
  33. package/dist/curves/rose5.d.cts +1 -1
  34. package/dist/curves/rose5.d.ts +1 -1
  35. package/dist/curves/rose52.d.cts +1 -1
  36. package/dist/curves/rose52.d.ts +1 -1
  37. package/dist/curves/star.d.cts +1 -1
  38. package/dist/curves/star.d.ts +1 -1
  39. package/dist/curves/star4.d.cts +1 -1
  40. package/dist/curves/star4.d.ts +1 -1
  41. package/dist/curves/star7.d.cts +1 -1
  42. package/dist/curves/star7.d.ts +1 -1
  43. package/dist/index.cjs +114 -87
  44. package/dist/index.cjs.map +1 -1
  45. package/dist/index.d.cts +25 -7
  46. package/dist/index.d.ts +25 -7
  47. package/dist/index.js +114 -88
  48. package/dist/index.js.map +1 -1
  49. package/dist/{types-CknrlCAf.d.cts → types-BZpzgNau.d.cts} +19 -1
  50. package/dist/{types-CknrlCAf.d.ts → types-BZpzgNau.d.ts} +19 -1
  51. package/package.json +1 -1
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as BaseRendererOptions, E as Engine, S as SarmalInstance, C as CurveDef, R as RendererOptions, P as Point, a as SarmalOptions } from './types-CknrlCAf.cjs';
2
- export { J as JumpOptions, b as RuntimeRenderOptions, c as SeekOptions, T as TrailColor, d as TrailStyle } from './types-CknrlCAf.cjs';
1
+ import { B as BaseRendererOptions, E as Engine, S as SarmalInstance, C as CurveDef, P as Point, R as RendererOptions, a as ControlPoint, b as SarmalOptions } from './types-BZpzgNau.cjs';
2
+ export { J as JumpOptions, c as RuntimeRenderOptions, d as SeekOptions, T as TrailColor, e as TrailStyle } from './types-BZpzgNau.cjs';
3
3
  export { CurveName, curves } from './curves/index.cjs';
4
4
  export { artemis2 } from './curves/artemis2.cjs';
5
5
  export { astroid } from './curves/astroid.cjs';
@@ -52,6 +52,21 @@ declare function createSVGRenderer(options: SVGRendererOptions): SarmalInstance;
52
52
  */
53
53
  declare function createSarmalSVG(container: SVGSVGElement, curveDef: CurveDef, options?: SVGSarmalOptions): SarmalInstance;
54
54
 
55
+ interface BoundaryResult {
56
+ scale: number;
57
+ offsetX: number;
58
+ offsetY: number;
59
+ }
60
+ /**
61
+ * Computes how to map engine coordinates into a viewport of the given logical size.
62
+ * ! Returns `null` if `pts` is empty
63
+ * ! Throws if all points are identical
64
+ *
65
+ * Padding per side is `max(FIT_PADDING * dim, minPaddingPx)`, so the stricter constraint wins.
66
+ * `minPaddingPx` defaults to `FIT_PADDING_MIN` (4px) for pixel-space callers.
67
+ * Pass `0` when the logical space is itself a normalized viewBox (e.g. SVG export).
68
+ */
69
+ declare function computeBoundaries(pts: Point[], logicalWidth: number, logicalHeight: number, minPaddingPx?: number): BoundaryResult | null;
55
70
  /**
56
71
  * Can be passed directly to `trailColor`,
57
72
  * or can be mixed/sliced before passing as a prop.
@@ -86,7 +101,7 @@ declare function createRenderer(options: RendererOptions): SarmalInstance;
86
101
  * @param t Parametric position along the closed loop. Wraps into `[0, 2π)` automatically, so values outside that range are remapped rather than rejected
87
102
  * @returns The `(x, y)` position on the spline at time `t`
88
103
  */
89
- declare function evaluateCatmullRom(points: Array<[number, number]>, t: number): Point;
104
+ declare function evaluateCatmullRom(points: Array<ControlPoint>, t: number): Point;
90
105
  /**
91
106
  * The returned curve definition produces a closed Catmull-Rom spline that
92
107
  * passes through every point in order, looping back from the last point to the first.
@@ -94,8 +109,9 @@ declare function evaluateCatmullRom(points: Array<[number, number]>, t: number):
94
109
  * @param points Array of control points in **normalized `[−1, 1]` space**,
95
110
  * matching the playground's draw-mode coordinate system.
96
111
  * ! Must contain at least 3 points.
97
- * @returns A `CurveDef` with `period: 2π` and the spline evaluator as its `fn`.
98
- * `name` is set to `"custom"`.
112
+ * @param opts Optional overrides for the returned `CurveDef`.
113
+ * @param opts.name Display name for the curve. Defaults to `"drawn"`.
114
+ * @returns A `CurveDef` with `period: 2π`, `kind: "drawn"`, and the spline evaluator as its `fn`.
99
115
  * @throws If `points` has fewer than 3 entries.
100
116
  *
101
117
  * @example
@@ -111,7 +127,9 @@ declare function evaluateCatmullRom(points: Array<[number, number]>, t: number):
111
127
  * createSarmal(canvas, curve)
112
128
  * ```
113
129
  */
114
- declare function drawCurve(points: Array<[number, number]>): CurveDef;
130
+ declare function drawCurve(points: Array<ControlPoint>, opts?: {
131
+ name?: string;
132
+ }): CurveDef;
115
133
 
116
134
  /**
117
135
  * Creates a sarmal animation on a canvas element
@@ -129,4 +147,4 @@ declare function drawCurve(points: Array<[number, number]>): CurveDef;
129
147
  */
130
148
  declare function createSarmal(canvas: HTMLCanvasElement, curveDef: CurveDef, options?: SarmalOptions): SarmalInstance;
131
149
 
132
- export { BaseRendererOptions, CurveDef, Engine, Point, RendererOptions, type SVGRendererOptions, type SVGSarmalOptions, SarmalInstance, SarmalOptions, type SarmalPalette, createEngine, createRenderer, createSVGRenderer, createSarmal, createSarmalSVG, drawCurve, evaluateCatmullRom, palettes };
150
+ export { BaseRendererOptions, type BoundaryResult, CurveDef, Engine, Point, RendererOptions, type SVGRendererOptions, type SVGSarmalOptions, SarmalInstance, SarmalOptions, type SarmalPalette, computeBoundaries, createEngine, createRenderer, createSVGRenderer, createSarmal, createSarmalSVG, drawCurve, evaluateCatmullRom, palettes };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as BaseRendererOptions, E as Engine, S as SarmalInstance, C as CurveDef, R as RendererOptions, P as Point, a as SarmalOptions } from './types-CknrlCAf.js';
2
- export { J as JumpOptions, b as RuntimeRenderOptions, c as SeekOptions, T as TrailColor, d as TrailStyle } from './types-CknrlCAf.js';
1
+ import { B as BaseRendererOptions, E as Engine, S as SarmalInstance, C as CurveDef, P as Point, R as RendererOptions, a as ControlPoint, b as SarmalOptions } from './types-BZpzgNau.js';
2
+ export { J as JumpOptions, c as RuntimeRenderOptions, d as SeekOptions, T as TrailColor, e as TrailStyle } from './types-BZpzgNau.js';
3
3
  export { CurveName, curves } from './curves/index.js';
4
4
  export { artemis2 } from './curves/artemis2.js';
5
5
  export { astroid } from './curves/astroid.js';
@@ -52,6 +52,21 @@ declare function createSVGRenderer(options: SVGRendererOptions): SarmalInstance;
52
52
  */
53
53
  declare function createSarmalSVG(container: SVGSVGElement, curveDef: CurveDef, options?: SVGSarmalOptions): SarmalInstance;
54
54
 
55
+ interface BoundaryResult {
56
+ scale: number;
57
+ offsetX: number;
58
+ offsetY: number;
59
+ }
60
+ /**
61
+ * Computes how to map engine coordinates into a viewport of the given logical size.
62
+ * ! Returns `null` if `pts` is empty
63
+ * ! Throws if all points are identical
64
+ *
65
+ * Padding per side is `max(FIT_PADDING * dim, minPaddingPx)`, so the stricter constraint wins.
66
+ * `minPaddingPx` defaults to `FIT_PADDING_MIN` (4px) for pixel-space callers.
67
+ * Pass `0` when the logical space is itself a normalized viewBox (e.g. SVG export).
68
+ */
69
+ declare function computeBoundaries(pts: Point[], logicalWidth: number, logicalHeight: number, minPaddingPx?: number): BoundaryResult | null;
55
70
  /**
56
71
  * Can be passed directly to `trailColor`,
57
72
  * or can be mixed/sliced before passing as a prop.
@@ -86,7 +101,7 @@ declare function createRenderer(options: RendererOptions): SarmalInstance;
86
101
  * @param t Parametric position along the closed loop. Wraps into `[0, 2π)` automatically, so values outside that range are remapped rather than rejected
87
102
  * @returns The `(x, y)` position on the spline at time `t`
88
103
  */
89
- declare function evaluateCatmullRom(points: Array<[number, number]>, t: number): Point;
104
+ declare function evaluateCatmullRom(points: Array<ControlPoint>, t: number): Point;
90
105
  /**
91
106
  * The returned curve definition produces a closed Catmull-Rom spline that
92
107
  * passes through every point in order, looping back from the last point to the first.
@@ -94,8 +109,9 @@ declare function evaluateCatmullRom(points: Array<[number, number]>, t: number):
94
109
  * @param points Array of control points in **normalized `[−1, 1]` space**,
95
110
  * matching the playground's draw-mode coordinate system.
96
111
  * ! Must contain at least 3 points.
97
- * @returns A `CurveDef` with `period: 2π` and the spline evaluator as its `fn`.
98
- * `name` is set to `"custom"`.
112
+ * @param opts Optional overrides for the returned `CurveDef`.
113
+ * @param opts.name Display name for the curve. Defaults to `"drawn"`.
114
+ * @returns A `CurveDef` with `period: 2π`, `kind: "drawn"`, and the spline evaluator as its `fn`.
99
115
  * @throws If `points` has fewer than 3 entries.
100
116
  *
101
117
  * @example
@@ -111,7 +127,9 @@ declare function evaluateCatmullRom(points: Array<[number, number]>, t: number):
111
127
  * createSarmal(canvas, curve)
112
128
  * ```
113
129
  */
114
- declare function drawCurve(points: Array<[number, number]>): CurveDef;
130
+ declare function drawCurve(points: Array<ControlPoint>, opts?: {
131
+ name?: string;
132
+ }): CurveDef;
115
133
 
116
134
  /**
117
135
  * Creates a sarmal animation on a canvas element
@@ -129,4 +147,4 @@ declare function drawCurve(points: Array<[number, number]>): CurveDef;
129
147
  */
130
148
  declare function createSarmal(canvas: HTMLCanvasElement, curveDef: CurveDef, options?: SarmalOptions): SarmalInstance;
131
149
 
132
- export { BaseRendererOptions, CurveDef, Engine, Point, RendererOptions, type SVGRendererOptions, type SVGSarmalOptions, SarmalInstance, SarmalOptions, type SarmalPalette, createEngine, createRenderer, createSVGRenderer, createSarmal, createSarmalSVG, drawCurve, evaluateCatmullRom, palettes };
150
+ export { BaseRendererOptions, type BoundaryResult, CurveDef, Engine, Point, RendererOptions, type SVGRendererOptions, type SVGSarmalOptions, SarmalInstance, SarmalOptions, type SarmalPalette, computeBoundaries, createEngine, createRenderer, createSVGRenderer, createSarmal, createSarmalSVG, drawCurve, evaluateCatmullRom, palettes };
package/dist/index.js CHANGED
@@ -196,25 +196,25 @@ function createEngine(curveDef, trailLength = 120) {
196
196
  },
197
197
  getSarmalSkeleton() {
198
198
  const steps = Math.ceil(curve.period * POINTS_PER_PERIOD_UNIT);
199
- const points = new Array(steps);
199
+ const points2 = new Array(steps);
200
200
  if (morphCurveB !== null && _morphAlpha !== null) {
201
201
  for (let i = 0; i < steps; i++) {
202
202
  const sampleT = i / (steps - 1) * curve.period;
203
203
  const a = sampleSkeleton(curve, sampleT);
204
204
  const tB = _morphStrategy === "normalized" ? sampleT / curve.period * morphCurveB.period : sampleT;
205
205
  const b = sampleSkeleton(morphCurveB, tB);
206
- points[i] = {
206
+ points2[i] = {
207
207
  x: a.x + (b.x - a.x) * _morphAlpha,
208
208
  y: a.y + (b.y - a.y) * _morphAlpha
209
209
  };
210
210
  }
211
- return points;
211
+ return points2;
212
212
  }
213
213
  for (let i = 0; i < steps; i++) {
214
214
  const sampleT = i / (steps - 1) * curve.period;
215
- points[i] = sampleSkeleton(curve, sampleT);
215
+ points2[i] = sampleSkeleton(curve, sampleT);
216
216
  }
217
- return points;
217
+ return points2;
218
218
  },
219
219
  setSpeed(speed) {
220
220
  if (!Number.isFinite(speed)) {
@@ -319,7 +319,7 @@ function computeTrailQuad(trail, i, trailCount, toX, toY, minWidth = TRAIL_MIN_W
319
319
  progress
320
320
  };
321
321
  }
322
- function computeBoundaries(pts, logicalWidth, logicalHeight) {
322
+ function computeBoundaries(pts, logicalWidth, logicalHeight, minPaddingPx = FIT_PADDING_MIN) {
323
323
  if (pts.length === 0) return null;
324
324
  const first = pts[0];
325
325
  let minX = first.x, maxX = first.x, minY = first.y, maxY = first.y;
@@ -346,8 +346,8 @@ function computeBoundaries(pts, logicalWidth, logicalHeight) {
346
346
  }
347
347
  const scaleXProportional = logicalWidth / (w * (1 + FIT_PADDING * 2));
348
348
  const scaleYProportional = logicalHeight / (h * (1 + FIT_PADDING * 2));
349
- const scaleXMinPadding = (logicalWidth - FIT_PADDING_MIN * 2) / w;
350
- const scaleYMinPadding = (logicalHeight - FIT_PADDING_MIN * 2) / h;
349
+ const scaleXMinPadding = (logicalWidth - minPaddingPx * 2) / w;
350
+ const scaleYMinPadding = (logicalHeight - minPaddingPx * 2) / h;
351
351
  const scale = Math.min(
352
352
  scaleXProportional,
353
353
  scaleYProportional,
@@ -367,7 +367,8 @@ function enginePassthroughs(engine) {
367
367
  setSpeed: engine.setSpeed,
368
368
  getSpeed: engine.getSpeed,
369
369
  resetSpeed: engine.resetSpeed,
370
- setSpeedOver: engine.setSpeedOver
370
+ setSpeedOver: engine.setSpeedOver,
371
+ getSarmalSkeleton: engine.getSarmalSkeleton
371
372
  };
372
373
  }
373
374
  var palettes = {
@@ -1232,26 +1233,94 @@ function createSarmalSVG(container, curveDef, options) {
1232
1233
  return createSVGRenderer({ container, engine, ...rendererOpts });
1233
1234
  }
1234
1235
 
1235
- // src/curves/artemis2.ts
1236
- var TWO_PI2 = Math.PI * 2;
1237
- function artemis2Fn(t, _time, _params) {
1238
- const a = 0.35, b = 0.15, ox = 0.175;
1239
- const s = Math.sin(t), c = Math.cos(t);
1240
- const denom = 1 + s * s;
1236
+ // src/catmull-rom.ts
1237
+ var PERIOD = 2 * Math.PI;
1238
+ function catmullRom1D(p0, p1, p2, p3, u) {
1239
+ const u2 = u * u;
1240
+ const u3 = u2 * u;
1241
+ return 0.5 * (2 * p1 + (-p0 + p2) * u + (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 + (-p0 + 3 * p1 - 3 * p2 + p3) * u3);
1242
+ }
1243
+ function evaluateCatmullRom(points2, t) {
1244
+ const N = points2.length;
1245
+ if (N === 0) {
1246
+ return { x: 0, y: 0 };
1247
+ }
1248
+ if (N === 1) {
1249
+ return { x: points2[0][0], y: points2[0][1] };
1250
+ }
1251
+ t = (t % PERIOD + PERIOD) % PERIOD;
1252
+ const segmentSize = PERIOD / N;
1253
+ let i = Math.floor(t / segmentSize);
1254
+ if (i >= N) {
1255
+ i = N - 1;
1256
+ }
1257
+ let u = (t - i * segmentSize) / segmentSize;
1258
+ u = Math.max(0, Math.min(1, u));
1259
+ const p0 = points2[(i - 1 + N) % N];
1260
+ const p1 = points2[i];
1261
+ const p2 = points2[(i + 1) % N];
1262
+ const p3 = points2[(i + 2) % N];
1241
1263
  return {
1242
- x: c * (1 + a * c) / denom - ox,
1243
- y: s * c * (1 + b * c) / denom
1264
+ x: catmullRom1D(p0[0], p1[0], p2[0], p3[0], u),
1265
+ y: catmullRom1D(p0[1], p1[1], p2[1], p3[1], u)
1244
1266
  };
1245
1267
  }
1268
+ function drawCurve(points2, opts) {
1269
+ if (points2.length < 3) {
1270
+ throw new Error(`drawCurve requires at least 3 points, received ${points2.length}.`);
1271
+ }
1272
+ const first = points2[0];
1273
+ if (points2.every((p) => p[0] === first[0] && p[1] === first[1])) {
1274
+ console.warn(
1275
+ "[sarmal].drawCurve: all control points are identical. The curve will be a single point."
1276
+ );
1277
+ }
1278
+ const maxAbs = points2.reduce((m, p) => Math.max(m, Math.abs(p[0]), Math.abs(p[1])), 0);
1279
+ if (maxAbs > 2) {
1280
+ console.warn(
1281
+ `[sarmal].drawCurve: control points extend to \xB1${maxAbs.toFixed(1)}, which may render off-screen. Coordinates should be in [-1, 1].`
1282
+ );
1283
+ }
1284
+ const pts = points2.map(([x, y]) => [x, y]);
1285
+ return {
1286
+ name: opts?.name ?? "drawn",
1287
+ fn: (t) => evaluateCatmullRom(pts, t),
1288
+ period: PERIOD,
1289
+ kind: "drawn"
1290
+ };
1291
+ }
1292
+
1293
+ // src/curves/artemis2.ts
1294
+ var points = [
1295
+ [-0.44, -0.45],
1296
+ [-0.53, -0.77],
1297
+ [-0.82, -0.66],
1298
+ [-0.82, -0.18],
1299
+ [-0.25, -0.04],
1300
+ [0.16, -0.49],
1301
+ [-0.03, -0.87],
1302
+ [-0.68, -0.94],
1303
+ [-0.95, -0.61],
1304
+ [-0.87, -0],
1305
+ [-0.34, 0.21],
1306
+ [0.27, -0.04],
1307
+ [0.87, 0.06],
1308
+ [0.87, 0.57],
1309
+ [0.32, 0.66],
1310
+ [-0.21, -0.43],
1311
+ [-0.43, -0.81],
1312
+ [-0.69, -0.84],
1313
+ [-0.87, -0.66],
1314
+ [-0.9, -0.47],
1315
+ [-0.76, -0.35]
1316
+ ];
1246
1317
  var artemis2 = {
1247
- name: "Artemis II",
1248
- fn: artemis2Fn,
1249
- period: TWO_PI2,
1318
+ ...drawCurve(points, { name: "Artemis II" }),
1250
1319
  speed: 0.7
1251
1320
  };
1252
1321
 
1253
1322
  // src/curves/astroid.ts
1254
- var TWO_PI3 = Math.PI * 2;
1323
+ var TWO_PI2 = Math.PI * 2;
1255
1324
  function astroidFn(t, _time, _params) {
1256
1325
  const c = Math.cos(t);
1257
1326
  const s = Math.sin(t);
@@ -1263,12 +1332,12 @@ function astroidFn(t, _time, _params) {
1263
1332
  var astroid = {
1264
1333
  name: "Astroid",
1265
1334
  fn: astroidFn,
1266
- period: TWO_PI3,
1335
+ period: TWO_PI2,
1267
1336
  speed: 1.1
1268
1337
  };
1269
1338
 
1270
1339
  // src/curves/deltoid.ts
1271
- var TWO_PI4 = Math.PI * 2;
1340
+ var TWO_PI3 = Math.PI * 2;
1272
1341
  function deltoidFn(t, _time, _params) {
1273
1342
  return {
1274
1343
  x: 2 * Math.cos(t) + Math.cos(2 * t),
@@ -1278,12 +1347,12 @@ function deltoidFn(t, _time, _params) {
1278
1347
  var deltoid = {
1279
1348
  name: "Deltoid",
1280
1349
  fn: deltoidFn,
1281
- period: TWO_PI4,
1350
+ period: TWO_PI3,
1282
1351
  speed: 0.9
1283
1352
  };
1284
1353
 
1285
1354
  // src/curves/epicycloid3.ts
1286
- var TWO_PI5 = Math.PI * 2;
1355
+ var TWO_PI4 = Math.PI * 2;
1287
1356
  function epicycloid3Fn(t, _time, _params) {
1288
1357
  return {
1289
1358
  x: 4 * Math.cos(t) - Math.cos(4 * t),
@@ -1293,12 +1362,12 @@ function epicycloid3Fn(t, _time, _params) {
1293
1362
  var epicycloid3 = {
1294
1363
  name: "Epicycloid (n=3)",
1295
1364
  fn: epicycloid3Fn,
1296
- period: TWO_PI5,
1365
+ period: TWO_PI4,
1297
1366
  speed: 0.75
1298
1367
  };
1299
1368
 
1300
1369
  // src/curves/epitrochoid7.ts
1301
- var TWO_PI6 = Math.PI * 2;
1370
+ var TWO_PI5 = Math.PI * 2;
1302
1371
  function epitrochoid7Fn(t, _time, _params) {
1303
1372
  const d = 1 + 0.55 * Math.sin(t * 0.5);
1304
1373
  return {
@@ -1316,13 +1385,13 @@ function epitrochoid7SkeletonFn(t) {
1316
1385
  var epitrochoid7 = {
1317
1386
  name: "Epitrochoid",
1318
1387
  fn: epitrochoid7Fn,
1319
- period: TWO_PI6,
1388
+ period: TWO_PI5,
1320
1389
  speed: 1.4,
1321
1390
  skeletonFn: epitrochoid7SkeletonFn
1322
1391
  };
1323
1392
 
1324
1393
  // src/curves/lissajous32.ts
1325
- var TWO_PI7 = Math.PI * 2;
1394
+ var TWO_PI6 = Math.PI * 2;
1326
1395
  function lissajous32Fn(t, time, _params) {
1327
1396
  const phi = time * 0.45;
1328
1397
  return {
@@ -1333,13 +1402,13 @@ function lissajous32Fn(t, time, _params) {
1333
1402
  var lissajous32 = {
1334
1403
  name: "Lissajous 3:2",
1335
1404
  fn: lissajous32Fn,
1336
- period: TWO_PI7,
1405
+ period: TWO_PI6,
1337
1406
  speed: 2,
1338
1407
  skeleton: "live"
1339
1408
  };
1340
1409
 
1341
1410
  // src/curves/lissajous43.ts
1342
- var TWO_PI8 = Math.PI * 2;
1411
+ var TWO_PI7 = Math.PI * 2;
1343
1412
  function lissajous43Fn(t, time, _params) {
1344
1413
  const phi = time * 0.38;
1345
1414
  return {
@@ -1350,13 +1419,13 @@ function lissajous43Fn(t, time, _params) {
1350
1419
  var lissajous43 = {
1351
1420
  name: "Lissajous 4:3",
1352
1421
  fn: lissajous43Fn,
1353
- period: TWO_PI8,
1422
+ period: TWO_PI7,
1354
1423
  speed: 1.8,
1355
1424
  skeleton: "live"
1356
1425
  };
1357
1426
 
1358
1427
  // src/curves/lame.ts
1359
- var TWO_PI9 = Math.PI * 2;
1428
+ var TWO_PI8 = Math.PI * 2;
1360
1429
  function lameFn(t, time, _params) {
1361
1430
  const p = 1.75 + 1.25 * Math.sin(time * 0.48);
1362
1431
  const c = Math.cos(t), s = Math.sin(t);
@@ -1368,13 +1437,13 @@ function lameFn(t, time, _params) {
1368
1437
  var lame = {
1369
1438
  name: "Lam\xE9 Curve",
1370
1439
  fn: lameFn,
1371
- period: TWO_PI9,
1440
+ period: TWO_PI8,
1372
1441
  speed: 1,
1373
1442
  skeleton: "live"
1374
1443
  };
1375
1444
 
1376
1445
  // src/curves/rose3.ts
1377
- var TWO_PI10 = Math.PI * 2;
1446
+ var TWO_PI9 = Math.PI * 2;
1378
1447
  function rose3Fn(t, _time, _params) {
1379
1448
  const r = Math.cos(3 * t);
1380
1449
  return {
@@ -1385,12 +1454,12 @@ function rose3Fn(t, _time, _params) {
1385
1454
  var rose3 = {
1386
1455
  name: "Rose (n=3)",
1387
1456
  fn: rose3Fn,
1388
- period: TWO_PI10,
1457
+ period: TWO_PI9,
1389
1458
  speed: 1.15
1390
1459
  };
1391
1460
 
1392
1461
  // src/curves/rose5.ts
1393
- var TWO_PI11 = Math.PI * 2;
1462
+ var TWO_PI10 = Math.PI * 2;
1394
1463
  function rose5Fn(t, _time, _params) {
1395
1464
  const r = Math.cos(5 * t);
1396
1465
  return {
@@ -1401,7 +1470,7 @@ function rose5Fn(t, _time, _params) {
1401
1470
  var rose5 = {
1402
1471
  name: "Rose (n=5)",
1403
1472
  fn: rose5Fn,
1404
- period: TWO_PI11,
1473
+ period: TWO_PI10,
1405
1474
  speed: 1
1406
1475
  };
1407
1476
 
@@ -1422,7 +1491,7 @@ var rose52 = {
1422
1491
  };
1423
1492
 
1424
1493
  // src/curves/star.ts
1425
- var TWO_PI12 = Math.PI * 2;
1494
+ var TWO_PI11 = Math.PI * 2;
1426
1495
  function starFn(t, _time, _params) {
1427
1496
  const r = Math.abs(Math.cos(5 / 2 * t)) + 0.35 * Math.abs(Math.cos(15 / 2 * t)) + 0.15 * Math.abs(Math.cos(25 / 2 * t));
1428
1497
  return {
@@ -1433,12 +1502,12 @@ function starFn(t, _time, _params) {
1433
1502
  var star = {
1434
1503
  name: "Star",
1435
1504
  fn: starFn,
1436
- period: TWO_PI12,
1505
+ period: TWO_PI11,
1437
1506
  speed: 1
1438
1507
  };
1439
1508
 
1440
1509
  // src/curves/star4.ts
1441
- var TWO_PI13 = Math.PI * 2;
1510
+ var TWO_PI12 = Math.PI * 2;
1442
1511
  function star4Fn(t, _time, _params) {
1443
1512
  const r = Math.abs(Math.cos(2 * t)) + 0.35 * Math.abs(Math.cos(6 * t)) + 0.15 * Math.abs(Math.cos(10 * t));
1444
1513
  return {
@@ -1449,12 +1518,12 @@ function star4Fn(t, _time, _params) {
1449
1518
  var star4 = {
1450
1519
  name: "Star (4-arm)",
1451
1520
  fn: star4Fn,
1452
- period: TWO_PI13,
1521
+ period: TWO_PI12,
1453
1522
  speed: 1
1454
1523
  };
1455
1524
 
1456
1525
  // src/curves/star7.ts
1457
- var TWO_PI14 = Math.PI * 2;
1526
+ var TWO_PI13 = Math.PI * 2;
1458
1527
  function star7Fn(t, _time, _params) {
1459
1528
  const r = Math.abs(Math.cos(7 / 2 * t)) + 0.35 * Math.abs(Math.cos(21 / 2 * t)) + 0.15 * Math.abs(Math.cos(35 / 2 * t));
1460
1529
  return {
@@ -1465,7 +1534,7 @@ function star7Fn(t, _time, _params) {
1465
1534
  var star7 = {
1466
1535
  name: "Star (7-arm)",
1467
1536
  fn: star7Fn,
1468
- period: TWO_PI14,
1537
+ period: TWO_PI13,
1469
1538
  speed: 1
1470
1539
  };
1471
1540
 
@@ -1487,49 +1556,6 @@ var curves = {
1487
1556
  lame
1488
1557
  };
1489
1558
 
1490
- // src/catmull-rom.ts
1491
- var PERIOD = 2 * Math.PI;
1492
- function catmullRom1D(p0, p1, p2, p3, u) {
1493
- const u2 = u * u;
1494
- const u3 = u2 * u;
1495
- return 0.5 * (2 * p1 + (-p0 + p2) * u + (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 + (-p0 + 3 * p1 - 3 * p2 + p3) * u3);
1496
- }
1497
- function evaluateCatmullRom(points, t) {
1498
- const N = points.length;
1499
- if (N === 0) {
1500
- return { x: 0, y: 0 };
1501
- }
1502
- if (N === 1) {
1503
- return { x: points[0][0], y: points[0][1] };
1504
- }
1505
- t = (t % PERIOD + PERIOD) % PERIOD;
1506
- const segmentSize = PERIOD / N;
1507
- let i = Math.floor(t / segmentSize);
1508
- if (i >= N) {
1509
- i = N - 1;
1510
- }
1511
- let u = (t - i * segmentSize) / segmentSize;
1512
- u = Math.max(0, Math.min(1, u));
1513
- const p0 = points[(i - 1 + N) % N];
1514
- const p1 = points[i];
1515
- const p2 = points[(i + 1) % N];
1516
- const p3 = points[(i + 2) % N];
1517
- return {
1518
- x: catmullRom1D(p0[0], p1[0], p2[0], p3[0], u),
1519
- y: catmullRom1D(p0[1], p1[1], p2[1], p3[1], u)
1520
- };
1521
- }
1522
- function drawCurve(points) {
1523
- if (points.length < 3) {
1524
- throw new Error(`drawCurve requires at least 3 points, received ${points.length}.`);
1525
- }
1526
- return {
1527
- name: "custom",
1528
- fn: (t) => evaluateCatmullRom(points, t),
1529
- period: PERIOD
1530
- };
1531
- }
1532
-
1533
1559
  // src/index.ts
1534
1560
  function createSarmal(canvas, curveDef, options) {
1535
1561
  const { trailLength, ...rendererOpts } = options ?? {};
@@ -1537,6 +1563,6 @@ function createSarmal(canvas, curveDef, options) {
1537
1563
  return createRenderer({ canvas, engine, ...rendererOpts });
1538
1564
  }
1539
1565
 
1540
- export { artemis2, astroid, createEngine, createRenderer, createSVGRenderer, createSarmal, createSarmalSVG, curves, deltoid, drawCurve, epicycloid3, epitrochoid7, evaluateCatmullRom, lame, lissajous32, lissajous43, palettes, rose3, rose5 };
1566
+ export { artemis2, astroid, computeBoundaries, createEngine, createRenderer, createSVGRenderer, createSarmal, createSarmalSVG, curves, deltoid, drawCurve, epicycloid3, epitrochoid7, evaluateCatmullRom, lame, lissajous32, lissajous43, palettes, rose3, rose5 };
1541
1567
  //# sourceMappingURL=index.js.map
1542
1568
  //# sourceMappingURL=index.js.map