curvy 2.0.0-alpha.13 → 2.0.0-alpha.15

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 (93) hide show
  1. package/dist/characteristic/index.mjs +1 -1
  2. package/dist/curve/cubic2d.d.ts +92 -3
  3. package/dist/curve/curve2d.d.ts +81 -0
  4. package/dist/curve/index.mjs +1 -1
  5. package/dist/curve/linear2d.d.ts +113 -3
  6. package/dist/curve/quadratic2d.d.ts +92 -3
  7. package/dist/curve/rationalCubic2d.d.ts +100 -38
  8. package/dist/interval/index.mjs +2 -2
  9. package/dist/matrix/index.mjs +47 -1
  10. package/dist/matrix/index.mjs.map +1 -1
  11. package/dist/matrix/matrix3x3.d.ts +87 -1
  12. package/dist/matrix/matrix4x4.d.ts +57 -6
  13. package/dist/matrix/traits.d.ts +34 -0
  14. package/dist/monotonicity/index.mjs +1 -1
  15. package/dist/monotonicity/monotonicity.d.ts +25 -0
  16. package/dist/number.d.ts +53 -0
  17. package/dist/number.mjs +56 -1
  18. package/dist/number.mjs.map +1 -1
  19. package/dist/path/cubic2d.d.ts +22 -0
  20. package/dist/path/index.mjs +25 -149
  21. package/dist/path/index.mjs.map +1 -1
  22. package/dist/path/linear2d.d.ts +24 -0
  23. package/dist/path/path2d.d.ts +54 -0
  24. package/dist/path/quadratic2d.d.ts +22 -0
  25. package/dist/path/rationalCubic2d.d.ts +21 -0
  26. package/dist/polynomial/index.mjs +2 -2
  27. package/dist/shared/affine2d-Dvna84gc.mjs +332 -0
  28. package/dist/shared/affine2d-Dvna84gc.mjs.map +1 -0
  29. package/dist/shared/{characteristic-BkEr-rr8.mjs → characteristic--7nC4Q_a.mjs} +4 -5
  30. package/dist/shared/characteristic--7nC4Q_a.mjs.map +1 -0
  31. package/dist/shared/{cubic-BL6dpuHh.mjs → cubic-BiGuAnZ0.mjs} +56 -27
  32. package/dist/shared/cubic-BiGuAnZ0.mjs.map +1 -0
  33. package/dist/shared/{interval-Dm35Xhy4.mjs → interval-Dcqpo73t.mjs} +5 -5
  34. package/dist/shared/interval-Dcqpo73t.mjs.map +1 -0
  35. package/dist/shared/{interval2d-AtneyI45.mjs → interval2d-C2Pk66-2.mjs} +3 -3
  36. package/dist/shared/{interval2d-AtneyI45.mjs.map → interval2d-C2Pk66-2.mjs.map} +1 -1
  37. package/dist/shared/matrix3x3.internal-Cod-r7H3.mjs +233 -0
  38. package/dist/shared/matrix3x3.internal-Cod-r7H3.mjs.map +1 -0
  39. package/dist/shared/{matrix4x4-BWmf4lZM.mjs → matrix4x4-BrqgYZCD.mjs} +72 -223
  40. package/dist/shared/matrix4x4-BrqgYZCD.mjs.map +1 -0
  41. package/dist/shared/monotonicity-DNxBoC7F.mjs +64 -0
  42. package/dist/shared/monotonicity-DNxBoC7F.mjs.map +1 -0
  43. package/dist/shared/{quadratic-DPrUsFCp.mjs → quadratic-BmMqkvxx.mjs} +2 -2
  44. package/dist/shared/{quadratic-DPrUsFCp.mjs.map → quadratic-BmMqkvxx.mjs.map} +1 -1
  45. package/dist/shared/{rationalCubic2d-H1J2Fjyy.mjs → rationalCubic2d-CZiP8nIq.mjs} +282 -326
  46. package/dist/shared/rationalCubic2d-CZiP8nIq.mjs.map +1 -0
  47. package/dist/shared/{rationalCubic2d-CeHgpNht.mjs → rationalCubic2d-gM7VeiiT.mjs} +585 -125
  48. package/dist/shared/rationalCubic2d-gM7VeiiT.mjs.map +1 -0
  49. package/dist/shared/{solution-B2JdOZpe.mjs → solution-BW0BBMXI.mjs} +22 -6
  50. package/dist/shared/solution-BW0BBMXI.mjs.map +1 -0
  51. package/dist/shared/{vector2-CSkaMXvp.mjs → vector2-DuA3EmfL.mjs} +5 -3
  52. package/dist/shared/vector2-DuA3EmfL.mjs.map +1 -0
  53. package/dist/shared/{vector2.internal-DP1nTBdS.mjs → vector2.internal-rPnW0RCx.mjs} +10 -5
  54. package/dist/shared/vector2.internal-rPnW0RCx.mjs.map +1 -0
  55. package/dist/shared/{vector3-CR2LPV03.mjs → vector3-oxtggkDp.mjs} +2 -2
  56. package/dist/shared/{vector3-CR2LPV03.mjs.map → vector3-oxtggkDp.mjs.map} +1 -1
  57. package/dist/shared/vector3.internal-CfWHl9SG.mjs +135 -0
  58. package/dist/shared/vector3.internal-CfWHl9SG.mjs.map +1 -0
  59. package/dist/shared/{vector4-PO_7EYd-.mjs → vector4-DGHuCvTV.mjs} +2 -2
  60. package/dist/shared/{vector4-PO_7EYd-.mjs.map → vector4-DGHuCvTV.mjs.map} +1 -1
  61. package/dist/shared/vector4.internal-DH5DzNYO.mjs +116 -0
  62. package/dist/shared/vector4.internal-DH5DzNYO.mjs.map +1 -0
  63. package/dist/solution/index.mjs +1 -1
  64. package/dist/solution/solution.d.ts +16 -0
  65. package/dist/splines/basis2d.d.ts +64 -0
  66. package/dist/splines/bezier2d.d.ts +72 -0
  67. package/dist/splines/cardinal2d.d.ts +78 -0
  68. package/dist/splines/hermite2d.d.ts +76 -0
  69. package/dist/splines/index.mjs +109 -15
  70. package/dist/splines/index.mjs.map +1 -1
  71. package/dist/splines/linear2d.d.ts +65 -0
  72. package/dist/splines/rationalBezier2d.d.ts +76 -0
  73. package/dist/transform/affine2d.d.ts +339 -0
  74. package/dist/transform/affine2d.internal.d.ts +2 -0
  75. package/dist/transform/index.d.ts +3 -0
  76. package/dist/transform/index.mjs +2 -0
  77. package/dist/transform/traits.d.ts +19 -0
  78. package/dist/vector/index.mjs +3 -3
  79. package/dist/vector/vector2.d.ts +49 -0
  80. package/package.json +5 -1
  81. package/dist/shared/characteristic-BkEr-rr8.mjs.map +0 -1
  82. package/dist/shared/cubic-BL6dpuHh.mjs.map +0 -1
  83. package/dist/shared/interval-Dm35Xhy4.mjs.map +0 -1
  84. package/dist/shared/matrix4x4-BWmf4lZM.mjs.map +0 -1
  85. package/dist/shared/monotonicity-BdebFOtv.mjs +0 -34
  86. package/dist/shared/monotonicity-BdebFOtv.mjs.map +0 -1
  87. package/dist/shared/rationalCubic2d-CeHgpNht.mjs.map +0 -1
  88. package/dist/shared/rationalCubic2d-H1J2Fjyy.mjs.map +0 -1
  89. package/dist/shared/solution-B2JdOZpe.mjs.map +0 -1
  90. package/dist/shared/vector2-CSkaMXvp.mjs.map +0 -1
  91. package/dist/shared/vector2.internal-DP1nTBdS.mjs.map +0 -1
  92. package/dist/shared/vector4.internal-BJ1QN2Ck.mjs +0 -246
  93. package/dist/shared/vector4.internal-BJ1QN2Ck.mjs.map +0 -1
@@ -1,14 +1,14 @@
1
1
  import { t as __exportAll } from "./chunk-25Hzd3z8.mjs";
2
2
  import { Pipeable, dual, invariant } from "../utils.mjs";
3
- import { a as make, i as magnitude, n as cross } from "./vector2-CSkaMXvp.mjs";
4
- import { n as transpose } from "./vector4-PO_7EYd-.mjs";
5
- import { l as scaleShift, m as unitOpen, p as unit, t as biunit, u as size } from "./interval-Dm35Xhy4.mjs";
6
- import { n as isStrict } from "./monotonicity-BdebFOtv.mjs";
7
- import { a as match, i as map, o as none, s as one, t as clip } from "./solution-B2JdOZpe.mjs";
8
- import { A as GL32_X1, B as GL32_X5, C as GL32_W4, D as GL32_W8, E as GL32_W7, F as GL32_X14, H as GL32_X7, I as GL32_X15, L as GL32_X2, M as GL32_X11, N as GL32_X12, O as GL32_W9, P as GL32_X13, R as GL32_X3, S as GL32_W3, T as GL32_W6, U as GL32_X8, V as GL32_X6, W as GL32_X9, _ as GL32_W12, a as isIncreasing$8, b as GL32_W15, c as roots, d as subdivide$2, f as unitRange, g as GL32_W11, h as GL32_W10, i as isDecreasing$8, j as GL32_X10, k as GL32_X0, l as solve$8, m as GL32_W1, n as derivative$5, o as isMonotonic$8, p as GL32_W0, s as make$1, u as solveInverse, v as GL32_W13, w as GL32_W5, x as GL32_W2, y as GL32_W14, z as GL32_X4 } from "./cubic-BL6dpuHh.mjs";
9
- import { _ as unitRange$1, a as make$3, c as solveInverse$2, d as isIncreasing$9, f as isMonotonic$9, g as solveInverse$1, h as solve$9, i as isMonotonic$10, l as unitRange$2, m as make$2, n as isDecreasing$10, r as isIncreasing$10, s as solve$10, t as derivative$6, u as isDecreasing$9 } from "./quadratic-DPrUsFCp.mjs";
10
- import { a as union, i as maxDistance, r as make$4, t as fromVectors } from "./interval2d-AtneyI45.mjs";
11
- import { i as cubicBezier, t as apply } from "./characteristic-BkEr-rr8.mjs";
3
+ import { a as magnitude, n as cross, o as make, s as makeWeighted } from "./vector2-DuA3EmfL.mjs";
4
+ import { n as transpose } from "./vector4-DGHuCvTV.mjs";
5
+ import { d as size, p as unit, t as biunit, u as scaleShift } from "./interval-Dcqpo73t.mjs";
6
+ import { a as map, n as clipApprox, t as clip } from "./solution-BW0BBMXI.mjs";
7
+ import { n as isStrict } from "./monotonicity-DNxBoC7F.mjs";
8
+ import { A as GL32_X0, B as GL32_X4, C as GL32_W3, D as GL32_W7, E as GL32_W6, F as GL32_X13, G as GL32_X9, H as GL32_X6, I as GL32_X14, L as GL32_X15, M as GL32_X10, N as GL32_X11, O as GL32_W8, P as GL32_X12, R as GL32_X2, S as GL32_W2, T as GL32_W5, U as GL32_X7, V as GL32_X5, W as GL32_X8, _ as GL32_W11, a as isIncreasing$8, b as GL32_W14, c as roots, d as subdivide$2, f as toSolver, g as GL32_W10, h as GL32_W1, i as isDecreasing$8, j as GL32_X1, k as GL32_W9, l as solve$8, m as GL32_W0, n as derivative$5, o as isMonotonic$8, p as unitRange, s as make$1, u as solveInverse, v as GL32_W12, w as GL32_W4, x as GL32_W15, y as GL32_W13, z as GL32_X3 } from "./cubic-BiGuAnZ0.mjs";
9
+ import { _ as unitRange$1, a as make$3, c as solveInverse$2, d as isIncreasing$9, f as isMonotonic$9, g as solveInverse$1, h as solve$9, i as isMonotonic$10, l as unitRange$2, m as make$2, n as isDecreasing$10, r as isIncreasing$10, s as solve$10, t as derivative$6, u as isDecreasing$9 } from "./quadratic-BmMqkvxx.mjs";
10
+ import { a as union, i as maxDistance, r as make$4, t as fromVectors } from "./interval2d-C2Pk66-2.mjs";
11
+ import { i as cubicBezier, t as apply } from "./characteristic--7nC4Q_a.mjs";
12
12
  //#region src/curve/linear2d.internal.ts
13
13
  const LinearCurve2dTypeId = Symbol("curvy/curve/linear2d");
14
14
  /** @internal */
@@ -41,25 +41,43 @@ const derivative$4 = (c) => make(c.x.c1, c.y.c1);
41
41
  /** @internal */
42
42
  const solve$7 = dual(2, (c, t) => make(solve$9(c.x, t), solve$9(c.y, t)));
43
43
  /** @internal */
44
- const solveAtX$7 = dual(2, (c, x) => match(solveInverse$1(c.x, x), {
45
- onNone: () => none,
46
- onSome: ({ value: t }) => t < 0 || t > 1 ? none : one(solve$9(c.y, t))
47
- }));
44
+ const solveAtX$7 = dual(2, (c, x) => solveInverse$1(c.x, x).pipe(clip(unit), map((t) => solve$9(c.y, t))));
48
45
  /** @internal */
49
- const solveAtY$7 = dual(2, (c, y) => match(solveInverse$1(c.y, y), {
50
- onNone: () => none,
51
- onSome: ({ value: t }) => t < 0 || t > 1 ? none : one(solve$9(c.x, t))
52
- }));
46
+ const solveAtY$7 = dual(2, (c, y) => solveInverse$1(c.y, y).pipe(clip(unit), map((t) => solve$9(c.x, t))));
53
47
  /** @internal */
54
48
  const length$5 = dual(2, (c, i) => Math.sqrt(c.x.c1 ** 2 + c.y.c1 ** 2) * Math.abs(i.end - i.start));
55
49
  /** @internal */
56
50
  const boundingBox$7 = (c) => make$4(unitRange$1(c.x), unitRange$1(c.y));
57
51
  /** @internal */
58
- const isMonotonic$7 = (c) => isMonotonic$9(c.x) && isMonotonic$9(c.y);
52
+ const startPoint$7 = (c) => make(c.x.c0, c.y.c0);
59
53
  /** @internal */
60
- const isIncreasing$7 = (c) => isIncreasing$9(c.x) && isIncreasing$9(c.y);
54
+ const endPoint$7 = (c) => make(c.x.c0 + c.x.c1, c.y.c0 + c.y.c1);
61
55
  /** @internal */
62
- const isDecreasing$7 = (c) => isDecreasing$9(c.x) && isDecreasing$9(c.y);
56
+ const xRange$5 = (c) => unitRange$1(c.x);
57
+ /** @internal */
58
+ const yRange$5 = (c) => unitRange$1(c.y);
59
+ /** @internal */
60
+ const toPathDataSegment$5 = (c) => {
61
+ return `L ${c.x.c0 + c.x.c1},${c.y.c0 + c.y.c1}`;
62
+ };
63
+ /** @internal */
64
+ const isMonotonicX$7 = (c) => isMonotonic$9(c.x);
65
+ /** @internal */
66
+ const isIncreasingX$7 = (c) => isIncreasing$9(c.x);
67
+ /** @internal */
68
+ const isDecreasingX$7 = (c) => isDecreasing$9(c.x);
69
+ /** @internal */
70
+ const isMonotonicY$7 = (c) => isMonotonic$9(c.y);
71
+ /** @internal */
72
+ const isIncreasingY$7 = (c) => isIncreasing$9(c.y);
73
+ /** @internal */
74
+ const isDecreasingY$7 = (c) => isDecreasing$9(c.y);
75
+ /** @internal */
76
+ const isMonotonic$7 = (c) => isMonotonicX$7(c) && isMonotonicY$7(c);
77
+ /** @internal */
78
+ const isIncreasing$7 = (c) => isIncreasingX$7(c) && isIncreasingY$7(c);
79
+ /** @internal */
80
+ const isDecreasing$7 = (c) => isDecreasingX$7(c) && isDecreasingY$7(c);
63
81
  const fail$3 = (m) => {
64
82
  throw new Error(m);
65
83
  };
@@ -69,6 +87,31 @@ const asMonotonic$7 = (c) => isMonotonic$7(c) ? c : fail$3("linear curve is not
69
87
  const asIncreasing$7 = (c) => isIncreasing$7(c) ? c : fail$3("linear curve is not increasing in both axes");
70
88
  /** @internal */
71
89
  const asDecreasing$7 = (c) => isDecreasing$7(c) ? c : fail$3("linear curve is not decreasing in both axes");
90
+ /** @internal */
91
+ const transform$7 = dual(2, (c, a) => {
92
+ const m = a.matrix;
93
+ return new LinearCurve2dImpl(make$2(m.m00 * c.x.c0 + m.m01 * c.y.c0 + m.m02, m.m00 * c.x.c1 + m.m01 * c.y.c1), make$2(m.m10 * c.x.c0 + m.m11 * c.y.c0 + m.m12, m.m10 * c.x.c1 + m.m11 * c.y.c1));
94
+ });
95
+ /**
96
+ * The `Curve2dOps` bundle consumed by the generic `Path2d` implementation.
97
+ *
98
+ * @internal
99
+ */
100
+ const Ops$2 = {
101
+ solve: solve$7,
102
+ startPoint: startPoint$7,
103
+ endPoint: endPoint$7,
104
+ length: length$5,
105
+ boundingBox: boundingBox$7,
106
+ solveAtX: solveAtX$7,
107
+ solveAtY: solveAtY$7,
108
+ toPathDataSegment: toPathDataSegment$5,
109
+ isIncreasingX: isIncreasingX$7,
110
+ isDecreasingX: isDecreasingX$7,
111
+ isIncreasingY: isIncreasingY$7,
112
+ isDecreasingY: isDecreasingY$7,
113
+ transform: transform$7
114
+ };
72
115
  //#endregion
73
116
  //#region src/curve/linear2d.ts
74
117
  var linear2d_exports = /* @__PURE__ */ __exportAll({
@@ -77,17 +120,29 @@ var linear2d_exports = /* @__PURE__ */ __exportAll({
77
120
  asMonotonic: () => asMonotonic$6,
78
121
  boundingBox: () => boundingBox$6,
79
122
  derivative: () => derivative$3,
123
+ endPoint: () => endPoint$6,
80
124
  fromCoefficients: () => fromCoefficients$4,
81
125
  fromEndpoints: () => fromEndpoints,
82
126
  fromPolynomials: () => fromPolynomials$6,
83
127
  isDecreasing: () => isDecreasing$6,
128
+ isDecreasingX: () => isDecreasingX$6,
129
+ isDecreasingY: () => isDecreasingY$6,
84
130
  isIncreasing: () => isIncreasing$6,
131
+ isIncreasingX: () => isIncreasingX$6,
132
+ isIncreasingY: () => isIncreasingY$6,
85
133
  isLinearCurve2d: () => isLinearCurve2d,
86
134
  isMonotonic: () => isMonotonic$6,
135
+ isMonotonicX: () => isMonotonicX$6,
136
+ isMonotonicY: () => isMonotonicY$6,
87
137
  length: () => length$4,
88
138
  solve: () => solve$6,
89
139
  solveAtX: () => solveAtX$6,
90
- solveAtY: () => solveAtY$6
140
+ solveAtY: () => solveAtY$6,
141
+ startPoint: () => startPoint$6,
142
+ toPathDataSegment: () => toPathDataSegment$4,
143
+ transform: () => transform$6,
144
+ xRange: () => xRange$4,
145
+ yRange: () => yRange$4
91
146
  });
92
147
  /**
93
148
  * Creates a new `LinearCurve2d` instance from polynomial parameters.
@@ -152,16 +207,103 @@ const length$4 = length$5;
152
207
  * @since 2.0.0
153
208
  */
154
209
  const boundingBox$6 = boundingBox$7;
210
+ /**
211
+ * Evaluates the curve at `t = 0` in closed form — `(c.x.c0, c.y.c0)`.
212
+ *
213
+ * @param c - The linear curve.
214
+ * @returns The point at the start of the curve's parameter domain.
215
+ * @since 2.0.0
216
+ */
217
+ const startPoint$6 = startPoint$7;
218
+ /**
219
+ * Evaluates the curve at `t = 1` in closed form — `(c.x.c0 + c.x.c1, c.y.c0 + c.y.c1)`.
220
+ *
221
+ * @param c - The linear curve.
222
+ * @returns The point at the end of the curve's parameter domain.
223
+ * @since 2.0.0
224
+ */
225
+ const endPoint$6 = endPoint$7;
226
+ /**
227
+ * The tight `[min, max]` range of x over the curve's parameter domain `[0, 1]`.
228
+ * For a linear curve this is the closed interval bounded by the two endpoints'
229
+ * x coordinates.
230
+ *
231
+ * @param c - The linear curve.
232
+ * @returns The closed range of x over `[0, 1]`.
233
+ * @since 2.0.0
234
+ */
235
+ const xRange$4 = xRange$5;
236
+ /**
237
+ * The tight `[min, max]` range of y over the curve's parameter domain `[0, 1]`.
238
+ * For a linear curve this is the closed interval bounded by the two endpoints'
239
+ * y coordinates.
240
+ *
241
+ * @param c - The linear curve.
242
+ * @returns The closed range of y over `[0, 1]`.
243
+ * @since 2.0.0
244
+ */
245
+ const yRange$4 = yRange$5;
246
+ /**
247
+ * Renders the curve as a single SVG path-data drawing command — for a linear
248
+ * curve, `L endX,endY`. Does not include a leading `M`; callers (typically a
249
+ * path-level `toPathData`) decide whether to emit a move based on continuity
250
+ * with the previous segment.
251
+ *
252
+ * @param c - The linear curve.
253
+ * @returns The SVG drawing command for this segment, without a leading `M`.
254
+ * @since 2.0.0
255
+ */
256
+ const toPathDataSegment$4 = toPathDataSegment$5;
155
257
  const solveAtX$6 = solveAtX$7;
156
258
  const solveAtY$6 = solveAtY$7;
157
259
  /**
260
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
261
+ * `Monotonic` when the x polynomial is strictly monotonic. The y-axis trait
262
+ * is unchanged.
263
+ *
264
+ * @since 2.0.0
265
+ */
266
+ const isMonotonicX$6 = isMonotonicX$7;
267
+ /**
268
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
269
+ * `Increasing`.
270
+ *
271
+ * @since 2.0.0
272
+ */
273
+ const isIncreasingX$6 = isIncreasingX$7;
274
+ /**
275
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
276
+ * `Decreasing`.
277
+ *
278
+ * @since 2.0.0
279
+ */
280
+ const isDecreasingX$6 = isDecreasingX$7;
281
+ /**
282
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
283
+ * `Monotonic`. The x-axis trait is unchanged.
284
+ *
285
+ * @since 2.0.0
286
+ */
287
+ const isMonotonicY$6 = isMonotonicY$7;
288
+ /**
289
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
290
+ * `Increasing`.
291
+ *
292
+ * @since 2.0.0
293
+ */
294
+ const isIncreasingY$6 = isIncreasingY$7;
295
+ /**
296
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
297
+ * `Decreasing`.
298
+ *
299
+ * @since 2.0.0
300
+ */
301
+ const isDecreasingY$6 = isDecreasingY$7;
302
+ /**
158
303
  * Type-narrowing predicate: refines both axes' traits to include `Monotonic`
159
304
  * when both the x and y polynomials are strictly monotonic. When both axes
160
305
  * are monotonic, the curve is invertible in either direction.
161
306
  *
162
- * For checking only one axis, call the polynomial-level refiner directly:
163
- * `LinearPolynomial.isMonotonic(curve.x)`.
164
- *
165
307
  * @since 2.0.0
166
308
  */
167
309
  const isMonotonic$6 = isMonotonic$7;
@@ -195,6 +337,7 @@ const asIncreasing$6 = asIncreasing$7;
195
337
  * @since 2.0.0
196
338
  */
197
339
  const asDecreasing$6 = asDecreasing$7;
340
+ const transform$6 = transform$7;
198
341
  //#endregion
199
342
  //#region src/curve/quadratic2d.internal.ts
200
343
  const QuadraticCurve2dTypeId = Symbol("curvy/curve/quadratic2d");
@@ -226,13 +369,9 @@ const isQuadraticCurve2d$1 = (c) => typeof c === "object" && c !== null && Quadr
226
369
  /** @internal */
227
370
  const solve$5 = dual(2, (c, t) => make(solve$10(c.x, t), solve$10(c.y, t)));
228
371
  /** @internal */
229
- const solveAtX$5 = dual(2, (c, x) => {
230
- return map(clip(solveInverse$2(c.x, x), unit), (t) => solve$10(c.y, t));
231
- });
372
+ const solveAtX$5 = dual(2, (c, x) => solveInverse$2(c.x, x).pipe(clipApprox(unit), map((t) => solve$10(c.y, t))));
232
373
  /** @internal */
233
- const solveAtY$5 = dual(2, (c, y) => {
234
- return map(clip(solveInverse$2(c.y, y), unit), (t) => solve$10(c.x, t));
235
- });
374
+ const solveAtY$5 = dual(2, (c, y) => solveInverse$2(c.y, y).pipe(clipApprox(unit), map((t) => solve$10(c.x, t))));
236
375
  /** @internal */
237
376
  const derivative$2 = (c) => fromPolynomials$6(derivative$6(c.x), derivative$6(c.y));
238
377
  /** @internal */
@@ -255,11 +394,35 @@ const curvature$3 = dual(2, (c, t) => {
255
394
  /** @internal */
256
395
  const boundingBox$5 = (c) => make$4(unitRange$2(c.x), unitRange$2(c.y));
257
396
  /** @internal */
258
- const isMonotonic$5 = (c) => isMonotonic$10(c.x, unit) && isMonotonic$10(c.y, unit);
397
+ const startPoint$5 = (c) => make(c.x.c0, c.y.c0);
398
+ /** @internal */
399
+ const endPoint$5 = (c) => make(c.x.c0 + c.x.c1 + c.x.c2, c.y.c0 + c.y.c1 + c.y.c2);
400
+ /** @internal */
401
+ const xRange$3 = (c) => unitRange$2(c.x);
402
+ /** @internal */
403
+ const yRange$3 = (c) => unitRange$2(c.y);
404
+ /** @internal */
405
+ const toPathDataSegment$3 = (c) => {
406
+ return `Q ${c.x.c0 + c.x.c1 / 2},${c.y.c0 + c.y.c1 / 2} ${c.x.c0 + c.x.c1 + c.x.c2},${c.y.c0 + c.y.c1 + c.y.c2}`;
407
+ };
408
+ /** @internal */
409
+ const isMonotonicX$5 = (c) => isMonotonic$10(c.x, unit);
410
+ /** @internal */
411
+ const isIncreasingX$5 = (c) => isIncreasing$10(c.x, unit);
412
+ /** @internal */
413
+ const isDecreasingX$5 = (c) => isDecreasing$10(c.x, unit);
259
414
  /** @internal */
260
- const isIncreasing$5 = (c) => isIncreasing$10(c.x, unit) && isIncreasing$10(c.y, unit);
415
+ const isMonotonicY$5 = (c) => isMonotonic$10(c.y, unit);
261
416
  /** @internal */
262
- const isDecreasing$5 = (c) => isDecreasing$10(c.x, unit) && isDecreasing$10(c.y, unit);
417
+ const isIncreasingY$5 = (c) => isIncreasing$10(c.y, unit);
418
+ /** @internal */
419
+ const isDecreasingY$5 = (c) => isDecreasing$10(c.y, unit);
420
+ /** @internal */
421
+ const isMonotonic$5 = (c) => isMonotonicX$5(c) && isMonotonicY$5(c);
422
+ /** @internal */
423
+ const isIncreasing$5 = (c) => isIncreasingX$5(c) && isIncreasingY$5(c);
424
+ /** @internal */
425
+ const isDecreasing$5 = (c) => isDecreasingX$5(c) && isDecreasingY$5(c);
263
426
  const fail$2 = (m) => {
264
427
  throw new Error(m);
265
428
  };
@@ -269,6 +432,34 @@ const asMonotonic$5 = (c) => isMonotonic$5(c) ? c : fail$2("quadratic curve is n
269
432
  const asIncreasing$5 = (c) => isIncreasing$5(c) ? c : fail$2("quadratic curve is not increasing in both axes");
270
433
  /** @internal */
271
434
  const asDecreasing$5 = (c) => isDecreasing$5(c) ? c : fail$2("quadratic curve is not decreasing in both axes");
435
+ /** @internal */
436
+ const transform$5 = dual(2, (c, a) => {
437
+ const m = a.matrix;
438
+ return new QuadraticCurve2dImpl(make$3(m.m00 * c.x.c0 + m.m01 * c.y.c0 + m.m02, m.m00 * c.x.c1 + m.m01 * c.y.c1, m.m00 * c.x.c2 + m.m01 * c.y.c2), make$3(m.m10 * c.x.c0 + m.m11 * c.y.c0 + m.m12, m.m10 * c.x.c1 + m.m11 * c.y.c1, m.m10 * c.x.c2 + m.m11 * c.y.c2));
439
+ });
440
+ /**
441
+ * The `Curve2dOps` bundle consumed by the generic `Path2d` implementation.
442
+ * `solveAtX` / `solveAtY` narrow the curve's potentially-2-element result to
443
+ * `AtMostOne` — path callers guarantee that via the path's
444
+ * `MonotonicX`/`MonotonicY` brand.
445
+ *
446
+ * @internal
447
+ */
448
+ const Ops$1 = {
449
+ solve: solve$5,
450
+ startPoint: startPoint$5,
451
+ endPoint: endPoint$5,
452
+ length: length$3,
453
+ boundingBox: boundingBox$5,
454
+ solveAtX: (c, x) => solveAtX$5(c, x),
455
+ solveAtY: (c, y) => solveAtY$5(c, y),
456
+ toPathDataSegment: toPathDataSegment$3,
457
+ isIncreasingX: isIncreasingX$5,
458
+ isDecreasingX: isDecreasingX$5,
459
+ isIncreasingY: isIncreasingY$5,
460
+ isDecreasingY: isDecreasingY$5,
461
+ transform: transform$5
462
+ };
272
463
  //#endregion
273
464
  //#region src/curve/quadratic2d.ts
274
465
  var quadratic2d_exports = /* @__PURE__ */ __exportAll({
@@ -278,17 +469,29 @@ var quadratic2d_exports = /* @__PURE__ */ __exportAll({
278
469
  boundingBox: () => boundingBox$4,
279
470
  curvature: () => curvature$2,
280
471
  derivative: () => derivative$1,
472
+ endPoint: () => endPoint$4,
281
473
  fromBezierPoints: () => fromBezierPoints$4,
282
474
  fromCoefficients: () => fromCoefficients$2,
283
475
  fromPolynomials: () => fromPolynomials$4,
284
476
  isDecreasing: () => isDecreasing$4,
477
+ isDecreasingX: () => isDecreasingX$4,
478
+ isDecreasingY: () => isDecreasingY$4,
285
479
  isIncreasing: () => isIncreasing$4,
480
+ isIncreasingX: () => isIncreasingX$4,
481
+ isIncreasingY: () => isIncreasingY$4,
286
482
  isMonotonic: () => isMonotonic$4,
483
+ isMonotonicX: () => isMonotonicX$4,
484
+ isMonotonicY: () => isMonotonicY$4,
287
485
  isQuadraticCurve2d: () => isQuadraticCurve2d,
288
486
  length: () => length$2,
289
487
  solve: () => solve$4,
290
488
  solveAtX: () => solveAtX$4,
291
- solveAtY: () => solveAtY$4
489
+ solveAtY: () => solveAtY$4,
490
+ startPoint: () => startPoint$4,
491
+ toPathDataSegment: () => toPathDataSegment$2,
492
+ transform: () => transform$4,
493
+ xRange: () => xRange$2,
494
+ yRange: () => yRange$2
292
495
  });
293
496
  /**
294
497
  * Creates a new `QuadraticCurve2d` instance from polynomial parameters.
@@ -361,12 +564,78 @@ const curvature$2 = curvature$3;
361
564
  */
362
565
  const boundingBox$4 = boundingBox$5;
363
566
  /**
567
+ * Evaluates the curve at `t = 0` in closed form — `(c.x.c0, c.y.c0)`.
568
+ *
569
+ * @param c - The quadratic curve.
570
+ * @returns The point at the start of the curve's parameter domain.
571
+ * @since 2.0.0
572
+ */
573
+ const startPoint$4 = startPoint$5;
574
+ /**
575
+ * Evaluates the curve at `t = 1` in closed form — the sum of the per-axis
576
+ * monomial coefficients.
577
+ *
578
+ * @param c - The quadratic curve.
579
+ * @returns The point at the end of the curve's parameter domain.
580
+ * @since 2.0.0
581
+ */
582
+ const endPoint$4 = endPoint$5;
583
+ /**
584
+ * The tight `[min, max]` range of x over the curve's parameter domain `[0, 1]`,
585
+ * accounting for an interior extremum if one exists.
586
+ *
587
+ * @param c - The quadratic curve.
588
+ * @returns The closed range of x over `[0, 1]`.
589
+ * @since 2.0.0
590
+ */
591
+ const xRange$2 = xRange$3;
592
+ /**
593
+ * The tight `[min, max]` range of y over the curve's parameter domain `[0, 1]`,
594
+ * accounting for an interior extremum if one exists.
595
+ *
596
+ * @param c - The quadratic curve.
597
+ * @returns The closed range of y over `[0, 1]`.
598
+ * @since 2.0.0
599
+ */
600
+ const yRange$2 = yRange$3;
601
+ /**
602
+ * Renders the curve as a single SVG path-data drawing command — for a
603
+ * quadratic curve, `Q ctrlX,ctrlY endX,endY`, where the control point is
604
+ * recovered from the monomial coefficients via the inverse Bernstein
605
+ * expansion. Does not include a leading `M`.
606
+ *
607
+ * @param c - The quadratic curve.
608
+ * @returns The SVG drawing command for this segment, without a leading `M`.
609
+ * @since 2.0.0
610
+ */
611
+ const toPathDataSegment$2 = toPathDataSegment$3;
612
+ /**
613
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
614
+ * `Monotonic` when the x polynomial is strictly monotonic on the unit
615
+ * interval `[0, 1]`. The y-axis trait is unchanged.
616
+ *
617
+ * @since 2.0.0
618
+ */
619
+ const isMonotonicX$4 = isMonotonicX$5;
620
+ /** @since 2.0.0 */
621
+ const isIncreasingX$4 = isIncreasingX$5;
622
+ /** @since 2.0.0 */
623
+ const isDecreasingX$4 = isDecreasingX$5;
624
+ /**
625
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
626
+ * `Monotonic`. The x-axis trait is unchanged.
627
+ *
628
+ * @since 2.0.0
629
+ */
630
+ const isMonotonicY$4 = isMonotonicY$5;
631
+ /** @since 2.0.0 */
632
+ const isIncreasingY$4 = isIncreasingY$5;
633
+ /** @since 2.0.0 */
634
+ const isDecreasingY$4 = isDecreasingY$5;
635
+ /**
364
636
  * Type-narrowing predicate: refines both axes' traits to include `Monotonic`
365
637
  * when both x and y polynomials are monotonic over the unit interval `[0, 1]`.
366
638
  *
367
- * For checking only one axis, call the polynomial-level refiner directly:
368
- * `QuadraticPolynomial.isMonotonic(curve.x, Interval.unit)`.
369
- *
370
639
  * @since 2.0.0
371
640
  */
372
641
  const isMonotonic$4 = isMonotonic$5;
@@ -380,6 +649,7 @@ const asMonotonic$4 = asMonotonic$5;
380
649
  const asIncreasing$4 = asIncreasing$5;
381
650
  /** @since 2.0.0 */
382
651
  const asDecreasing$4 = asDecreasing$5;
652
+ const transform$4 = transform$5;
383
653
  //#endregion
384
654
  //#region src/curve/cubic2d.internal.ts
385
655
  const CubicCurve2dTypeId = Symbol("curvy/curve/cubic2d");
@@ -405,26 +675,20 @@ const fromPolynomials$3 = (c0, c1) => new CubicCurve2dImpl(c0, c1);
405
675
  /** @internal */
406
676
  const fromCoefficients$1 = (c0, c1, c2, c3) => new CubicCurve2dImpl(make$1(c0.x, c1.x, c2.x, c3.x), make$1(c0.y, c1.y, c2.y, c3.y));
407
677
  /** @internal */
408
- const fromBezierPoints$3 = (p0, p1, p2, p3) => {
409
- return new CubicCurve2dImpl(...apply(cubicBezier, ...transpose([
410
- p0,
411
- p1,
412
- p2,
413
- p3
414
- ], (p) => [p.x, p.y])));
415
- };
678
+ const fromBezierPoints$3 = (p0, p1, p2, p3) => new CubicCurve2dImpl(...apply(cubicBezier, ...transpose([
679
+ p0,
680
+ p1,
681
+ p2,
682
+ p3
683
+ ], (p) => [p.x, p.y])));
416
684
  /** @internal */
417
685
  const isCubicCurve2d$1 = (c) => typeof c === "object" && c !== null && CubicCurve2dTypeId in c;
418
686
  /** @internal */
419
687
  const solve$3 = dual(2, (c, t) => make(solve$8(c.x, t), solve$8(c.y, t)));
420
688
  /** @internal */
421
- const solveAtX$3 = dual(2, (c, x) => {
422
- return map(clip(solveInverse(c.x, x), unit), (t) => solve$8(c.y, t));
423
- });
689
+ const solveAtX$3 = dual(2, (c, x) => solveInverse(c.x, x).pipe(clipApprox(unit), map(toSolver(c.y))));
424
690
  /** @internal */
425
- const solveAtY$3 = dual(2, (c, y) => {
426
- return map(clip(solveInverse(c.y, y), unit), (t) => solve$8(c.x, t));
427
- });
691
+ const solveAtY$3 = dual(2, (c, y) => solveInverse(c.y, y).pipe(clipApprox(unit), map(toSolver(c.x))));
428
692
  /** @internal */
429
693
  const derivative = (c) => fromPolynomials$4(derivative$5(c.x), derivative$5(c.y));
430
694
  /** @internal */
@@ -447,11 +711,43 @@ const curvature$1 = dual(2, (c, t) => {
447
711
  /** @internal */
448
712
  const boundingBox$3 = (c) => make$4(unitRange(c.x), unitRange(c.y));
449
713
  /** @internal */
450
- const isMonotonic$3 = (c) => isMonotonic$8(c.x, unit) && isMonotonic$8(c.y, unit);
714
+ const startPoint$3 = (c) => make(c.x.c0, c.y.c0);
715
+ /** @internal */
716
+ const endPoint$3 = (c) => make(c.x.c0 + c.x.c1 + c.x.c2 + c.x.c3, c.y.c0 + c.y.c1 + c.y.c2 + c.y.c3);
717
+ /** @internal */
718
+ const xRange$1 = (c) => unitRange(c.x);
719
+ /** @internal */
720
+ const yRange$1 = (c) => unitRange(c.y);
721
+ /** @internal */
722
+ const toPathDataSegment$1 = (c) => {
723
+ const c0x = c.x.c0;
724
+ const c0y = c.y.c0;
725
+ const c1x = c.x.c1;
726
+ const c1y = c.y.c1;
727
+ const c2x = c.x.c2;
728
+ const c2y = c.y.c2;
729
+ const c3x = c.x.c3;
730
+ const c3y = c.y.c3;
731
+ return `C ${c0x + c1x / 3},${c0y + c1y / 3} ${c0x + 2 * c1x / 3 + c2x / 3},${c0y + 2 * c1y / 3 + c2y / 3} ${c0x + c1x + c2x + c3x},${c0y + c1y + c2y + c3y}`;
732
+ };
733
+ /** @internal */
734
+ const isMonotonicX$3 = (c) => isMonotonic$8(c.x, unit);
451
735
  /** @internal */
452
- const isIncreasing$3 = (c) => isIncreasing$8(c.x, unit) && isIncreasing$8(c.y, unit);
736
+ const isIncreasingX$3 = (c) => isIncreasing$8(c.x, unit);
453
737
  /** @internal */
454
- const isDecreasing$3 = (c) => isDecreasing$8(c.x, unit) && isDecreasing$8(c.y, unit);
738
+ const isDecreasingX$3 = (c) => isDecreasing$8(c.x, unit);
739
+ /** @internal */
740
+ const isMonotonicY$3 = (c) => isMonotonic$8(c.y, unit);
741
+ /** @internal */
742
+ const isIncreasingY$3 = (c) => isIncreasing$8(c.y, unit);
743
+ /** @internal */
744
+ const isDecreasingY$3 = (c) => isDecreasing$8(c.y, unit);
745
+ /** @internal */
746
+ const isMonotonic$3 = (c) => isMonotonicX$3(c) && isMonotonicY$3(c);
747
+ /** @internal */
748
+ const isIncreasing$3 = (c) => isIncreasingX$3(c) && isIncreasingY$3(c);
749
+ /** @internal */
750
+ const isDecreasing$3 = (c) => isDecreasingX$3(c) && isDecreasingY$3(c);
455
751
  const fail$1 = (m) => {
456
752
  throw new Error(m);
457
753
  };
@@ -461,6 +757,34 @@ const asMonotonic$3 = (c) => isMonotonic$3(c) ? c : fail$1("cubic curve is not m
461
757
  const asIncreasing$3 = (c) => isIncreasing$3(c) ? c : fail$1("cubic curve is not increasing in both axes");
462
758
  /** @internal */
463
759
  const asDecreasing$3 = (c) => isDecreasing$3(c) ? c : fail$1("cubic curve is not decreasing in both axes");
760
+ /** @internal */
761
+ const transform$3 = dual(2, (c, a) => {
762
+ const m = a.matrix;
763
+ return new CubicCurve2dImpl(make$1(m.m00 * c.x.c0 + m.m01 * c.y.c0 + m.m02, m.m00 * c.x.c1 + m.m01 * c.y.c1, m.m00 * c.x.c2 + m.m01 * c.y.c2, m.m00 * c.x.c3 + m.m01 * c.y.c3), make$1(m.m10 * c.x.c0 + m.m11 * c.y.c0 + m.m12, m.m10 * c.x.c1 + m.m11 * c.y.c1, m.m10 * c.x.c2 + m.m11 * c.y.c2, m.m10 * c.x.c3 + m.m11 * c.y.c3));
764
+ });
765
+ /**
766
+ * The `Curve2dOps` bundle consumed by the generic `Path2d` implementation.
767
+ * `solveAtX` / `solveAtY` narrow the curve's potentially-3-element result to
768
+ * `AtMostOne` — path callers guarantee that via the path's
769
+ * `MonotonicX`/`MonotonicY` brand.
770
+ *
771
+ * @internal
772
+ */
773
+ const Ops = {
774
+ solve: solve$3,
775
+ startPoint: startPoint$3,
776
+ endPoint: endPoint$3,
777
+ length: length$1,
778
+ boundingBox: boundingBox$3,
779
+ solveAtX: (c, x) => solveAtX$3(c, x),
780
+ solveAtY: (c, y) => solveAtY$3(c, y),
781
+ toPathDataSegment: toPathDataSegment$1,
782
+ isIncreasingX: isIncreasingX$3,
783
+ isDecreasingX: isDecreasingX$3,
784
+ isIncreasingY: isIncreasingY$3,
785
+ isDecreasingY: isDecreasingY$3,
786
+ transform: transform$3
787
+ };
464
788
  //#endregion
465
789
  //#region src/curve/cubic2d.ts
466
790
  var cubic2d_exports = /* @__PURE__ */ __exportAll({
@@ -469,17 +793,29 @@ var cubic2d_exports = /* @__PURE__ */ __exportAll({
469
793
  asMonotonic: () => asMonotonic$2,
470
794
  boundingBox: () => boundingBox$2,
471
795
  curvature: () => curvature,
796
+ endPoint: () => endPoint$2,
472
797
  fromBezierPoints: () => fromBezierPoints$2,
473
798
  fromCoefficients: () => fromCoefficients,
474
799
  fromPolynomials: () => fromPolynomials$2,
475
800
  isCubicCurve2d: () => isCubicCurve2d,
476
801
  isDecreasing: () => isDecreasing$2,
802
+ isDecreasingX: () => isDecreasingX$2,
803
+ isDecreasingY: () => isDecreasingY$2,
477
804
  isIncreasing: () => isIncreasing$2,
805
+ isIncreasingX: () => isIncreasingX$2,
806
+ isIncreasingY: () => isIncreasingY$2,
478
807
  isMonotonic: () => isMonotonic$2,
808
+ isMonotonicX: () => isMonotonicX$2,
809
+ isMonotonicY: () => isMonotonicY$2,
479
810
  length: () => length,
480
811
  solve: () => solve$2,
481
812
  solveAtX: () => solveAtX$2,
482
- solveAtY: () => solveAtY$2
813
+ solveAtY: () => solveAtY$2,
814
+ startPoint: () => startPoint$2,
815
+ toPathDataSegment: () => toPathDataSegment,
816
+ transform: () => transform$2,
817
+ xRange: () => xRange,
818
+ yRange: () => yRange
483
819
  });
484
820
  /**
485
821
  * Creates a new `CubicCurve2d` instance from polynomial parameters.
@@ -545,12 +881,78 @@ const curvature = curvature$1;
545
881
  */
546
882
  const boundingBox$2 = boundingBox$3;
547
883
  /**
884
+ * Evaluates the curve at `t = 0` in closed form — `(c.x.c0, c.y.c0)`.
885
+ *
886
+ * @param c - The cubic curve.
887
+ * @returns The point at the start of the curve's parameter domain.
888
+ * @since 2.0.0
889
+ */
890
+ const startPoint$2 = startPoint$3;
891
+ /**
892
+ * Evaluates the curve at `t = 1` in closed form — the sum of the per-axis
893
+ * monomial coefficients.
894
+ *
895
+ * @param c - The cubic curve.
896
+ * @returns The point at the end of the curve's parameter domain.
897
+ * @since 2.0.0
898
+ */
899
+ const endPoint$2 = endPoint$3;
900
+ /**
901
+ * The tight `[min, max]` range of x over the curve's parameter domain `[0, 1]`,
902
+ * accounting for up to two interior extrema.
903
+ *
904
+ * @param c - The cubic curve.
905
+ * @returns The closed range of x over `[0, 1]`.
906
+ * @since 2.0.0
907
+ */
908
+ const xRange = xRange$1;
909
+ /**
910
+ * The tight `[min, max]` range of y over the curve's parameter domain `[0, 1]`,
911
+ * accounting for up to two interior extrema.
912
+ *
913
+ * @param c - The cubic curve.
914
+ * @returns The closed range of y over `[0, 1]`.
915
+ * @since 2.0.0
916
+ */
917
+ const yRange = yRange$1;
918
+ /**
919
+ * Renders the curve as a single SVG path-data drawing command — for a cubic
920
+ * curve, `C ctrl1X,ctrl1Y ctrl2X,ctrl2Y endX,endY`. Bernstein control points
921
+ * are recovered from the monomial coefficients in closed form. Does not
922
+ * include a leading `M`.
923
+ *
924
+ * @param c - The cubic curve.
925
+ * @returns The SVG drawing command for this segment, without a leading `M`.
926
+ * @since 2.0.0
927
+ */
928
+ const toPathDataSegment = toPathDataSegment$1;
929
+ /**
930
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
931
+ * `Monotonic` when the x polynomial is strictly monotonic on the unit
932
+ * interval `[0, 1]`. The y-axis trait is unchanged.
933
+ *
934
+ * @since 2.0.0
935
+ */
936
+ const isMonotonicX$2 = isMonotonicX$3;
937
+ /** @since 2.0.0 */
938
+ const isIncreasingX$2 = isIncreasingX$3;
939
+ /** @since 2.0.0 */
940
+ const isDecreasingX$2 = isDecreasingX$3;
941
+ /**
942
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
943
+ * `Monotonic`. The x-axis trait is unchanged.
944
+ *
945
+ * @since 2.0.0
946
+ */
947
+ const isMonotonicY$2 = isMonotonicY$3;
948
+ /** @since 2.0.0 */
949
+ const isIncreasingY$2 = isIncreasingY$3;
950
+ /** @since 2.0.0 */
951
+ const isDecreasingY$2 = isDecreasingY$3;
952
+ /**
548
953
  * Type-narrowing predicate: refines both axes' traits to include `Monotonic`
549
954
  * when both x and y polynomials are monotonic over the unit interval `[0, 1]`.
550
955
  *
551
- * For checking only one axis, call the polynomial-level refiner directly:
552
- * `CubicPolynomial.isMonotonic(curve.x, Interval.unit)`.
553
- *
554
956
  * @since 2.0.0
555
957
  */
556
958
  const isMonotonic$2 = isMonotonic$3;
@@ -564,6 +966,7 @@ const asMonotonic$2 = asMonotonic$3;
564
966
  const asIncreasing$2 = asIncreasing$3;
565
967
  /** @since 2.0.0 */
566
968
  const asDecreasing$2 = asDecreasing$3;
969
+ const transform$2 = transform$3;
567
970
  //#endregion
568
971
  //#region src/curve/rationalCubic2d.internal.ts
569
972
  const RationalCubicCurve2dTypeId = Symbol("curvy/curve/rationalCubic2d");
@@ -586,43 +989,76 @@ var RationalCubicCurve2dImpl = class extends Pipeable {
586
989
  const isRationalCubicCurve2d$1 = (c) => typeof c === "object" && c !== null && RationalCubicCurve2dTypeId in c;
587
990
  /** @internal */
588
991
  const fromPolynomials$1 = (x, y, w) => new RationalCubicCurve2dImpl(x, y, w);
992
+ const EASING_P0 = makeWeighted(0, 0, 1);
993
+ const EASING_P3 = makeWeighted(1, 1, 1);
994
+ /** @internal */
995
+ const fromBezierPoints$1 = (...args) => {
996
+ const [p0, p1, p2, p3] = args.length === 2 ? [
997
+ EASING_P0,
998
+ args[0],
999
+ args[1],
1000
+ EASING_P3
1001
+ ] : args;
1002
+ return new RationalCubicCurve2dImpl(...apply(cubicBezier, ...transpose([
1003
+ p0,
1004
+ p1,
1005
+ p2,
1006
+ p3
1007
+ ], (p) => [
1008
+ p.x * p.weight,
1009
+ p.y * p.weight,
1010
+ p.weight
1011
+ ])));
1012
+ };
589
1013
  /** @internal */
590
- const fromBezierPoints$1 = (p0, p1, p2, p3) => new RationalCubicCurve2dImpl(...apply(cubicBezier, ...transpose([
591
- p0,
592
- p1,
593
- p2,
594
- p3
595
- ], (p) => [
596
- p.x * p.weight,
597
- p.y * p.weight,
598
- p.weight
599
- ])));
600
- /** @internal */
601
- const makeMonotonicEasing$1 = (startSlope, endSlope) => {
602
- invariant(Number.isFinite(startSlope) && startSlope >= 0, "makeMonotonicEasing: startSlope must be finite and ≥ 0");
603
- invariant(Number.isFinite(endSlope) && endSlope >= 0, "makeMonotonicEasing: endSlope must be finite and ≥ 0");
1014
+ const fromSlopesAndCurvatures$1 = (startSlope, endSlope, startCurvature, endCurvature) => {
1015
+ invariant(Number.isFinite(startSlope), "fromSlopesAndCurvatures: startSlope must be finite");
1016
+ invariant(Number.isFinite(endSlope), "fromSlopesAndCurvatures: endSlope must be finite");
1017
+ invariant(Number.isFinite(startCurvature), "fromSlopesAndCurvatures: startCurvature must be finite");
1018
+ invariant(Number.isFinite(endCurvature), "fromSlopesAndCurvatures: endCurvature must be finite");
604
1019
  const m0 = startSlope;
605
1020
  const m1 = endSlope;
606
- const alpha = m0 + 1;
607
- const beta = m1 + 1;
608
- const pC0 = 0;
609
- const pC1 = m0 * alpha;
610
- const pC2 = beta * (2 - m1) + alpha * (1 - 2 * m0);
611
- const pC3 = beta * (m1 - 1) + alpha * (m0 - 1);
612
- const qC0 = alpha;
613
- const qC1 = beta - alpha;
614
- const xPoly = make$1(0, alpha, beta - alpha, 0);
615
- const yPoly = make$1(pC0, pC1, pC2, pC3);
616
- const wPoly = make$1(qC0, qC1, 0, 0);
617
- const monoQ = make$1(m0 * alpha * alpha, 2 * alpha * pC2, 3 * alpha * pC3 + pC2 * (beta - alpha), 2 * pC3 * (beta - alpha));
618
- const interiorRoots = monoQ.pipe(roots, clip(unitOpen));
619
- for (const t of interiorRoots) {
620
- const epsilon = 1e-6;
621
- const lo = Math.max(0, t - epsilon);
622
- const hi = Math.min(1, t + epsilon);
623
- invariant(Math.sign(solve$8(monoQ, lo)) * Math.sign(solve$8(monoQ, hi)) >= 0, `makeMonotonicEasing: slopes (${m0}, ${m1}) produce a non-monotonic curve with the default Gregory-Delbourgo construction. Try smaller slopes or use a different easing form.`);
1021
+ const d0 = startCurvature * Math.pow(1 + m0 * m0, 1.5);
1022
+ const d1 = endCurvature * Math.pow(1 + m1 * m1, 1.5);
1023
+ const u = 1 - m0;
1024
+ const v = 1 - m1;
1025
+ const det = 4 * u * d1 - 8 * v * v;
1026
+ const detScale = Math.max(Math.abs(4 * u * d1), Math.abs(8 * v * v), 1);
1027
+ const SINGULAR_TOLERANCE = 1e-12;
1028
+ let w0;
1029
+ let w1;
1030
+ let w2;
1031
+ if (Math.abs(det) > SINGULAR_TOLERANCE * detScale) {
1032
+ w0 = 1;
1033
+ w1 = (d0 * d1 + 4 * u * v) / det;
1034
+ w2 = (-8 * u * u - 4 * d0 * v) / det;
1035
+ } else if (u === 0 && v === 0) {
1036
+ invariant(d0 === 0 && d1 === 0, `fromSlopesAndCurvatures: inputs (m₀=${m0}, m₁=${m1}, κ₀=${startCurvature}, κ₁=${endCurvature}) yield an inconsistent constraint system`);
1037
+ return new RationalCubicCurve2dImpl(make$1(0, 1, 0, 0), make$1(0, 1, 0, 0), make$1(1, 0, 0, 0));
1038
+ } else {
1039
+ const residual = -8 * u * u - 4 * v * d0;
1040
+ invariant(Math.abs(residual) <= SINGULAR_TOLERANCE * detScale, `fromSlopesAndCurvatures: inputs (m₀=${m0}, m₁=${m1}, κ₀=${startCurvature}, κ₁=${endCurvature}) yield an inconsistent constraint system`);
1041
+ w0 = 1;
1042
+ w2 = 1;
1043
+ w1 = u !== 0 ? (d0 - 2 * v) / (4 * u) : -(2 * u + d1) / (4 * v);
1044
+ }
1045
+ invariant(w2 > 0, `fromSlopesAndCurvatures: inputs (m₀=${m0}, m₁=${m1}, κ₀=${startCurvature}, κ₁=${endCurvature}) yield denominator ≤ 0 at t = 1`);
1046
+ const a = w0 - 2 * w1 + w2;
1047
+ const b = 2 * (w1 - w0);
1048
+ if (a > 0) {
1049
+ const tStar = -b / (2 * a);
1050
+ if (tStar > 0 && tStar < 1) invariant(w0 + tStar * (b + a * tStar) > 0, `fromSlopesAndCurvatures: inputs (m₀=${m0}, m₁=${m1}, κ₀=${startCurvature}, κ₁=${endCurvature}) yield denominator ≤ 0 in (0, 1)`);
624
1051
  }
625
- return new RationalCubicCurve2dImpl(xPoly, yPoly, wPoly);
1052
+ const p1 = m0 * w0 / 3;
1053
+ const p2 = (v * w2 + 2 * w1) / 3;
1054
+ const p3 = w2;
1055
+ const yC1 = 3 * p1;
1056
+ const yC2 = 3 * (p2 - 2 * p1);
1057
+ const yC3 = p3 - 3 * p2 + 3 * p1;
1058
+ const wC0 = w0;
1059
+ const wC1 = b;
1060
+ const wC2 = a;
1061
+ return new RationalCubicCurve2dImpl(make$1(0, wC0, wC1, wC2), make$1(0, yC1, yC2, yC3), make$1(wC0, wC1, wC2, 0));
626
1062
  };
627
1063
  /** @internal */
628
1064
  const solve$1 = dual(2, (c, t) => {
@@ -630,9 +1066,16 @@ const solve$1 = dual(2, (c, t) => {
630
1066
  return make(solve$8(c.x, t) / w, solve$8(c.y, t) / w);
631
1067
  });
632
1068
  /** @internal */
633
- const solveAtX$1 = dual(2, (c, x) => make$1(c.x.c0 - x * c.w.c0, c.x.c1 - x * c.w.c1, c.x.c2 - x * c.w.c2, c.x.c3 - x * c.w.c3).pipe(roots, clip(unit), map((t) => solve$8(c.y, t) / solve$8(c.w, t))));
1069
+ const startPoint$1 = (c) => make(c.x.c0 / c.w.c0, c.y.c0 / c.w.c0);
1070
+ /** @internal */
1071
+ const endPoint$1 = (c) => {
1072
+ const w = c.w.c0 + c.w.c1 + c.w.c2 + c.w.c3;
1073
+ return make((c.x.c0 + c.x.c1 + c.x.c2 + c.x.c3) / w, (c.y.c0 + c.y.c1 + c.y.c2 + c.y.c3) / w);
1074
+ };
1075
+ /** @internal */
1076
+ const solveAtX$1 = dual(2, (c, x) => make$1(c.x.c0 - x * c.w.c0, c.x.c1 - x * c.w.c1, c.x.c2 - x * c.w.c2, c.x.c3 - x * c.w.c3).pipe(roots, clipApprox(unit), map((t) => solve$8(c.y, t) / solve$8(c.w, t))));
634
1077
  /** @internal */
635
- const solveAtY$1 = dual(2, (c, y) => make$1(c.y.c0 - y * c.w.c0, c.y.c1 - y * c.w.c1, c.y.c2 - y * c.w.c2, c.y.c3 - y * c.w.c3).pipe(roots, clip(unit), map((t) => solve$8(c.x, t) / solve$8(c.w, t))));
1078
+ const solveAtY$1 = dual(2, (c, y) => make$1(c.y.c0 - y * c.w.c0, c.y.c1 - y * c.w.c1, c.y.c2 - y * c.w.c2, c.y.c3 - y * c.w.c3).pipe(roots, clipApprox(unit), map((t) => solve$8(c.x, t) / solve$8(c.w, t))));
636
1079
  const derivativeNumeratorQuartic = (n, d) => [
637
1080
  n.c1 * d.c0 - n.c0 * d.c1,
638
1081
  2 * (n.c2 * d.c0 - n.c0 * d.c2),
@@ -729,6 +1172,11 @@ const asMonotonic$1 = (c) => isMonotonic$1(c) ? c : fail("rational cubic curve i
729
1172
  const asIncreasing$1 = (c) => isIncreasing$1(c) ? c : fail("rational cubic curve is not increasing in both axes");
730
1173
  /** @internal */
731
1174
  const asDecreasing$1 = (c) => isDecreasing$1(c) ? c : fail("rational cubic curve is not decreasing in both axes");
1175
+ /** @internal */
1176
+ const transform$1 = dual(2, (c, a) => {
1177
+ const m = a.matrix;
1178
+ return new RationalCubicCurve2dImpl(make$1(m.m00 * c.x.c0 + m.m01 * c.y.c0 + m.m02 * c.w.c0, m.m00 * c.x.c1 + m.m01 * c.y.c1 + m.m02 * c.w.c1, m.m00 * c.x.c2 + m.m01 * c.y.c2 + m.m02 * c.w.c2, m.m00 * c.x.c3 + m.m01 * c.y.c3 + m.m02 * c.w.c3), make$1(m.m10 * c.x.c0 + m.m11 * c.y.c0 + m.m12 * c.w.c0, m.m10 * c.x.c1 + m.m11 * c.y.c1 + m.m12 * c.w.c1, m.m10 * c.x.c2 + m.m11 * c.y.c2 + m.m12 * c.w.c2, m.m10 * c.x.c3 + m.m11 * c.y.c3 + m.m12 * c.w.c3), c.w);
1179
+ });
732
1180
  const MAX_BBOX_DEPTH = 20;
733
1181
  /** @internal */
734
1182
  const boundingBox$1 = dual(2, (c, tolerance) => {
@@ -948,8 +1396,10 @@ var rationalCubic2d_exports = /* @__PURE__ */ __exportAll({
948
1396
  asMonotonicX: () => asMonotonicX,
949
1397
  asMonotonicY: () => asMonotonicY,
950
1398
  boundingBox: () => boundingBox,
1399
+ endPoint: () => endPoint,
951
1400
  fromBezierPoints: () => fromBezierPoints,
952
1401
  fromPolynomials: () => fromPolynomials,
1402
+ fromSlopesAndCurvatures: () => fromSlopesAndCurvatures,
953
1403
  isDecreasing: () => isDecreasing,
954
1404
  isDecreasingX: () => isDecreasingX,
955
1405
  isDecreasingY: () => isDecreasingY,
@@ -960,11 +1410,12 @@ var rationalCubic2d_exports = /* @__PURE__ */ __exportAll({
960
1410
  isMonotonicX: () => isMonotonicX,
961
1411
  isMonotonicY: () => isMonotonicY,
962
1412
  isRationalCubicCurve2d: () => isRationalCubicCurve2d,
963
- makeMonotonicEasing: () => makeMonotonicEasing,
964
1413
  solve: () => solve,
965
1414
  solveAtX: () => solveAtX,
966
1415
  solveAtY: () => solveAtY,
1416
+ startPoint: () => startPoint,
967
1417
  subdivide: () => subdivide,
1418
+ transform: () => transform,
968
1419
  xMonotonicity: () => xMonotonicity,
969
1420
  yMonotonicity: () => yMonotonicity
970
1421
  });
@@ -987,44 +1438,52 @@ const isRationalCubicCurve2d = isRationalCubicCurve2d$1;
987
1438
  * @since 2.0.0
988
1439
  */
989
1440
  const fromPolynomials = fromPolynomials$1;
1441
+ const fromBezierPoints = fromBezierPoints$1;
990
1442
  /**
991
- * Creates a new `RationalCubicCurve2d` from four weighted cubic Bézier
992
- * control points. The four control points are lifted to homogeneous form
993
- * `(w·x, w·y, w)` and the cubic Bernstein basis is expanded into per-channel
994
- * monomial coefficients, yielding the curve's `x`, `y`, and `w` polynomials.
1443
+ * Creates a rational cubic easing curve from endpoint slopes and signed
1444
+ * curvatures. The result interpolates `(0, 0)` and `(1, 1)` with `x(t) = t`
1445
+ * pinned linearly; the y-axis projection `y(t) = Y(t)/W(t)` uses a cubic
1446
+ * numerator over a quadratic denominator, giving six free parameters that
1447
+ * exactly match the six endpoint constraints (two values, two slopes, two
1448
+ * curvatures).
995
1449
  *
996
- * @param p0 - The first weighted control point (curve start).
997
- * @param p1 - The second weighted control point (start handle).
998
- * @param p2 - The third weighted control point (end handle).
999
- * @param p3 - The fourth weighted control point (curve end).
1000
- * @returns A new `RationalCubicCurve2d` instance.
1450
+ * Curvatures are the signed differential-geometric curvatures `κ = y''(x) /
1451
+ * (1 + y'(x)²)^(3/2)` — the parameterization-invariant "bend" of the easing
1452
+ * graph. Positive κ is concave-up. Smoothstep is `(0, 0, 6, -6)`; linear is
1453
+ * `(1, 1, 0, 0)` (taken as a redundant-system special case).
1454
+ *
1455
+ * Monotonicity is not enforced. Callers needing the `Increasing` brand for
1456
+ * narrowed inverse-solve returns should follow construction with
1457
+ * {@link asIncreasing}, which verifies monotonicity rigorously.
1458
+ *
1459
+ * @param startSlope - The easing function's slope at the start (`dy/dx` at `x = 0`).
1460
+ * @param endSlope - The easing function's slope at the end (`dy/dx` at `x = 1`).
1461
+ * @param startCurvature - The signed differential curvature at the start.
1462
+ * @param endCurvature - The signed differential curvature at the end.
1463
+ * @returns A rational cubic easing curve.
1464
+ * @throws When inputs are non-finite, the constraint system is singular, or the resulting denominator vanishes on `[0, 1]`.
1001
1465
  * @since 2.0.0
1002
1466
  */
1003
- const fromBezierPoints = fromBezierPoints$1;
1467
+ const fromSlopesAndCurvatures = fromSlopesAndCurvatures$1;
1468
+ const solve = solve$1;
1004
1469
  /**
1005
- * Creates a guaranteed-monotonic rational cubic easing curve via Gregory-
1006
- * Delbourgo style construction. The result interpolates `(0, 0)` and
1007
- * `(1, 1)` with the given endpoint slopes, with `x(t) = t` pinned linearly
1008
- * and a rational cubic numerator for `y(t)`. Monotonicity of `y(t)` is
1009
- * verified rigorously at construction (degree-3 polynomial sign analysis);
1010
- * the returned curve is branded `<Increasing, Increasing>` so that
1011
- * {@link solveAtX} returns `Solution.AtMostOne<number>` without further
1012
- * trait refinement.
1470
+ * Evaluates the curve at `t = 0` in closed form — `(c.x.c0 / c.w.c0, c.y.c0 / c.w.c0)`.
1013
1471
  *
1014
- * For input slope combinations that the default Gregory-Delbourgo
1015
- * construction cannot accommodate (typically when one slope is large while
1016
- * the other is small), construction throws. Useful operating range is
1017
- * roughly `m₀, m₁ ∈ [0, 2]` with `m₀ + m₁ ≲ 3`; smoothstep (`0, 0`) and
1018
- * linear (`1, 1`) fall out as special cases.
1472
+ * @param c - The rational cubic curve.
1473
+ * @returns The point at the start of the curve's parameter domain.
1474
+ * @since 2.0.0
1475
+ */
1476
+ const startPoint = startPoint$1;
1477
+ /**
1478
+ * Evaluates the curve at `t = 1` in closed form. Both numerator and denominator
1479
+ * Horner evaluations at `t = 1` collapse to the sum of their monomial
1480
+ * coefficients, so the projection is `(Σxᵢ / Σwᵢ, Σyᵢ / Σwᵢ)`.
1019
1481
  *
1020
- * @param startSlope - The easing function's slope at the start (`dy/dx` at `x = 0`); must be finite and non-negative.
1021
- * @param endSlope - The easing function's slope at the end (`dy/dx` at `x = 1`); must be finite and non-negative.
1022
- * @returns A monotone-by-construction rational cubic easing curve.
1023
- * @throws When slopes are negative, non-finite, or produce a non-monotonic curve under the default construction.
1482
+ * @param c - The rational cubic curve.
1483
+ * @returns The point at the end of the curve's parameter domain.
1024
1484
  * @since 2.0.0
1025
1485
  */
1026
- const makeMonotonicEasing = makeMonotonicEasing$1;
1027
- const solve = solve$1;
1486
+ const endPoint = endPoint$1;
1028
1487
  const solveAtX = solveAtX$1;
1029
1488
  const solveAtY = solveAtY$1;
1030
1489
  const subdivide = subdivide$1;
@@ -1196,8 +1655,9 @@ const asIncreasing = asIncreasing$1;
1196
1655
  * @since 2.0.0
1197
1656
  */
1198
1657
  const asDecreasing = asDecreasing$1;
1658
+ const transform = transform$1;
1199
1659
  const approximateAsCubicCurves = approximateAsCubicCurves$1;
1200
1660
  //#endregion
1201
- export { length$4 as C, solveAtY$6 as D, solveAtX$6 as E, fromEndpoints as S, solve$6 as T, quadratic2d_exports as _, solve as a, solveAtY$4 as b, fromCoefficients as c, solve$2 as d, solveAtX$2 as f, length$2 as g, boundingBox$4 as h, rationalCubic2d_exports as i, fromPolynomials$2 as l, derivative as m, boundingBox as n, boundingBox$2 as o, solveAtY$2 as p, fromBezierPoints as r, cubic2d_exports as s, approximateAsCubicCurves as t, length as u, solve$4 as v, linear2d_exports as w, boundingBox$6 as x, solveAtX$4 as y };
1661
+ export { fromEndpoints as _, solve as a, fromCoefficients as c, solve$2 as d, Ops as f, Ops$1 as g, solve$4 as h, rationalCubic2d_exports as i, fromPolynomials$2 as l, quadratic2d_exports as m, boundingBox as n, transform as o, derivative as p, fromBezierPoints as r, cubic2d_exports as s, approximateAsCubicCurves as t, length as u, linear2d_exports as v, Ops$2 as y };
1202
1662
 
1203
- //# sourceMappingURL=rationalCubic2d-CeHgpNht.mjs.map
1663
+ //# sourceMappingURL=rationalCubic2d-gM7VeiiT.mjs.map