curvy 2.0.0-alpha.13 → 2.0.0-alpha.14

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 +102 -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 +122 -3
  6. package/dist/curve/quadratic2d.d.ts +103 -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-CeHgpNht.mjs → rationalCubic2d-CZSwwKtS.mjs} +591 -125
  46. package/dist/shared/rationalCubic2d-CZSwwKtS.mjs.map +1 -0
  47. package/dist/shared/{rationalCubic2d-H1J2Fjyy.mjs → rationalCubic2d-bveuGqBZ.mjs} +282 -326
  48. package/dist/shared/rationalCubic2d-bveuGqBZ.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,25 +87,43 @@ 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
+ });
72
95
  //#endregion
73
96
  //#region src/curve/linear2d.ts
74
97
  var linear2d_exports = /* @__PURE__ */ __exportAll({
98
+ Ops: () => Ops$2,
75
99
  asDecreasing: () => asDecreasing$6,
76
100
  asIncreasing: () => asIncreasing$6,
77
101
  asMonotonic: () => asMonotonic$6,
78
102
  boundingBox: () => boundingBox$6,
79
103
  derivative: () => derivative$3,
104
+ endPoint: () => endPoint$6,
80
105
  fromCoefficients: () => fromCoefficients$4,
81
106
  fromEndpoints: () => fromEndpoints,
82
107
  fromPolynomials: () => fromPolynomials$6,
83
108
  isDecreasing: () => isDecreasing$6,
109
+ isDecreasingX: () => isDecreasingX$6,
110
+ isDecreasingY: () => isDecreasingY$6,
84
111
  isIncreasing: () => isIncreasing$6,
112
+ isIncreasingX: () => isIncreasingX$6,
113
+ isIncreasingY: () => isIncreasingY$6,
85
114
  isLinearCurve2d: () => isLinearCurve2d,
86
115
  isMonotonic: () => isMonotonic$6,
116
+ isMonotonicX: () => isMonotonicX$6,
117
+ isMonotonicY: () => isMonotonicY$6,
87
118
  length: () => length$4,
88
119
  solve: () => solve$6,
89
120
  solveAtX: () => solveAtX$6,
90
- solveAtY: () => solveAtY$6
121
+ solveAtY: () => solveAtY$6,
122
+ startPoint: () => startPoint$6,
123
+ toPathDataSegment: () => toPathDataSegment$4,
124
+ transform: () => transform$6,
125
+ xRange: () => xRange$4,
126
+ yRange: () => yRange$4
91
127
  });
92
128
  /**
93
129
  * Creates a new `LinearCurve2d` instance from polynomial parameters.
@@ -152,16 +188,103 @@ const length$4 = length$5;
152
188
  * @since 2.0.0
153
189
  */
154
190
  const boundingBox$6 = boundingBox$7;
191
+ /**
192
+ * Evaluates the curve at `t = 0` in closed form — `(c.x.c0, c.y.c0)`.
193
+ *
194
+ * @param c - The linear curve.
195
+ * @returns The point at the start of the curve's parameter domain.
196
+ * @since 2.0.0
197
+ */
198
+ const startPoint$6 = startPoint$7;
199
+ /**
200
+ * Evaluates the curve at `t = 1` in closed form — `(c.x.c0 + c.x.c1, c.y.c0 + c.y.c1)`.
201
+ *
202
+ * @param c - The linear curve.
203
+ * @returns The point at the end of the curve's parameter domain.
204
+ * @since 2.0.0
205
+ */
206
+ const endPoint$6 = endPoint$7;
207
+ /**
208
+ * The tight `[min, max]` range of x over the curve's parameter domain `[0, 1]`.
209
+ * For a linear curve this is the closed interval bounded by the two endpoints'
210
+ * x coordinates.
211
+ *
212
+ * @param c - The linear curve.
213
+ * @returns The closed range of x over `[0, 1]`.
214
+ * @since 2.0.0
215
+ */
216
+ const xRange$4 = xRange$5;
217
+ /**
218
+ * The tight `[min, max]` range of y over the curve's parameter domain `[0, 1]`.
219
+ * For a linear curve this is the closed interval bounded by the two endpoints'
220
+ * y coordinates.
221
+ *
222
+ * @param c - The linear curve.
223
+ * @returns The closed range of y over `[0, 1]`.
224
+ * @since 2.0.0
225
+ */
226
+ const yRange$4 = yRange$5;
227
+ /**
228
+ * Renders the curve as a single SVG path-data drawing command — for a linear
229
+ * curve, `L endX,endY`. Does not include a leading `M`; callers (typically a
230
+ * path-level `toPathData`) decide whether to emit a move based on continuity
231
+ * with the previous segment.
232
+ *
233
+ * @param c - The linear curve.
234
+ * @returns The SVG drawing command for this segment, without a leading `M`.
235
+ * @since 2.0.0
236
+ */
237
+ const toPathDataSegment$4 = toPathDataSegment$5;
155
238
  const solveAtX$6 = solveAtX$7;
156
239
  const solveAtY$6 = solveAtY$7;
157
240
  /**
241
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
242
+ * `Monotonic` when the x polynomial is strictly monotonic. The y-axis trait
243
+ * is unchanged.
244
+ *
245
+ * @since 2.0.0
246
+ */
247
+ const isMonotonicX$6 = isMonotonicX$7;
248
+ /**
249
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
250
+ * `Increasing`.
251
+ *
252
+ * @since 2.0.0
253
+ */
254
+ const isIncreasingX$6 = isIncreasingX$7;
255
+ /**
256
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
257
+ * `Decreasing`.
258
+ *
259
+ * @since 2.0.0
260
+ */
261
+ const isDecreasingX$6 = isDecreasingX$7;
262
+ /**
263
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
264
+ * `Monotonic`. The x-axis trait is unchanged.
265
+ *
266
+ * @since 2.0.0
267
+ */
268
+ const isMonotonicY$6 = isMonotonicY$7;
269
+ /**
270
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
271
+ * `Increasing`.
272
+ *
273
+ * @since 2.0.0
274
+ */
275
+ const isIncreasingY$6 = isIncreasingY$7;
276
+ /**
277
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
278
+ * `Decreasing`.
279
+ *
280
+ * @since 2.0.0
281
+ */
282
+ const isDecreasingY$6 = isDecreasingY$7;
283
+ /**
158
284
  * Type-narrowing predicate: refines both axes' traits to include `Monotonic`
159
285
  * when both the x and y polynomials are strictly monotonic. When both axes
160
286
  * are monotonic, the curve is invertible in either direction.
161
287
  *
162
- * For checking only one axis, call the polynomial-level refiner directly:
163
- * `LinearPolynomial.isMonotonic(curve.x)`.
164
- *
165
288
  * @since 2.0.0
166
289
  */
167
290
  const isMonotonic$6 = isMonotonic$7;
@@ -195,6 +318,29 @@ const asIncreasing$6 = asIncreasing$7;
195
318
  * @since 2.0.0
196
319
  */
197
320
  const asDecreasing$6 = asDecreasing$7;
321
+ const transform$6 = transform$7;
322
+ /**
323
+ * The {@link Curve2dOps} bundle for `LinearCurve2d`. Used by
324
+ * `LinearPath2d` (and any user code building a generic `Path2d` over linear
325
+ * curves) to wire up the path-level operation surface.
326
+ *
327
+ * @since 2.0.0
328
+ */
329
+ const Ops$2 = {
330
+ solve: solve$6,
331
+ startPoint: startPoint$6,
332
+ endPoint: endPoint$6,
333
+ length: length$4,
334
+ boundingBox: boundingBox$6,
335
+ solveAtX: solveAtX$6,
336
+ solveAtY: solveAtY$6,
337
+ toPathDataSegment: toPathDataSegment$4,
338
+ isIncreasingX: isIncreasingX$6,
339
+ isDecreasingX: isDecreasingX$6,
340
+ isIncreasingY: isIncreasingY$6,
341
+ isDecreasingY: isDecreasingY$6,
342
+ transform: transform$6
343
+ };
198
344
  //#endregion
199
345
  //#region src/curve/quadratic2d.internal.ts
200
346
  const QuadraticCurve2dTypeId = Symbol("curvy/curve/quadratic2d");
@@ -226,13 +372,9 @@ const isQuadraticCurve2d$1 = (c) => typeof c === "object" && c !== null && Quadr
226
372
  /** @internal */
227
373
  const solve$5 = dual(2, (c, t) => make(solve$10(c.x, t), solve$10(c.y, t)));
228
374
  /** @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
- });
375
+ const solveAtX$5 = dual(2, (c, x) => solveInverse$2(c.x, x).pipe(clipApprox(unit), map((t) => solve$10(c.y, t))));
232
376
  /** @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
- });
377
+ const solveAtY$5 = dual(2, (c, y) => solveInverse$2(c.y, y).pipe(clipApprox(unit), map((t) => solve$10(c.x, t))));
236
378
  /** @internal */
237
379
  const derivative$2 = (c) => fromPolynomials$6(derivative$6(c.x), derivative$6(c.y));
238
380
  /** @internal */
@@ -255,11 +397,35 @@ const curvature$3 = dual(2, (c, t) => {
255
397
  /** @internal */
256
398
  const boundingBox$5 = (c) => make$4(unitRange$2(c.x), unitRange$2(c.y));
257
399
  /** @internal */
258
- const isMonotonic$5 = (c) => isMonotonic$10(c.x, unit) && isMonotonic$10(c.y, unit);
400
+ const startPoint$5 = (c) => make(c.x.c0, c.y.c0);
401
+ /** @internal */
402
+ const endPoint$5 = (c) => make(c.x.c0 + c.x.c1 + c.x.c2, c.y.c0 + c.y.c1 + c.y.c2);
403
+ /** @internal */
404
+ const xRange$3 = (c) => unitRange$2(c.x);
405
+ /** @internal */
406
+ const yRange$3 = (c) => unitRange$2(c.y);
407
+ /** @internal */
408
+ const toPathDataSegment$3 = (c) => {
409
+ 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}`;
410
+ };
411
+ /** @internal */
412
+ const isMonotonicX$5 = (c) => isMonotonic$10(c.x, unit);
413
+ /** @internal */
414
+ const isIncreasingX$5 = (c) => isIncreasing$10(c.x, unit);
415
+ /** @internal */
416
+ const isDecreasingX$5 = (c) => isDecreasing$10(c.x, unit);
417
+ /** @internal */
418
+ const isMonotonicY$5 = (c) => isMonotonic$10(c.y, unit);
259
419
  /** @internal */
260
- const isIncreasing$5 = (c) => isIncreasing$10(c.x, unit) && isIncreasing$10(c.y, unit);
420
+ const isIncreasingY$5 = (c) => isIncreasing$10(c.y, unit);
261
421
  /** @internal */
262
- const isDecreasing$5 = (c) => isDecreasing$10(c.x, unit) && isDecreasing$10(c.y, unit);
422
+ const isDecreasingY$5 = (c) => isDecreasing$10(c.y, unit);
423
+ /** @internal */
424
+ const isMonotonic$5 = (c) => isMonotonicX$5(c) && isMonotonicY$5(c);
425
+ /** @internal */
426
+ const isIncreasing$5 = (c) => isIncreasingX$5(c) && isIncreasingY$5(c);
427
+ /** @internal */
428
+ const isDecreasing$5 = (c) => isDecreasingX$5(c) && isDecreasingY$5(c);
263
429
  const fail$2 = (m) => {
264
430
  throw new Error(m);
265
431
  };
@@ -269,26 +435,44 @@ const asMonotonic$5 = (c) => isMonotonic$5(c) ? c : fail$2("quadratic curve is n
269
435
  const asIncreasing$5 = (c) => isIncreasing$5(c) ? c : fail$2("quadratic curve is not increasing in both axes");
270
436
  /** @internal */
271
437
  const asDecreasing$5 = (c) => isDecreasing$5(c) ? c : fail$2("quadratic curve is not decreasing in both axes");
438
+ /** @internal */
439
+ const transform$5 = dual(2, (c, a) => {
440
+ const m = a.matrix;
441
+ 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));
442
+ });
272
443
  //#endregion
273
444
  //#region src/curve/quadratic2d.ts
274
445
  var quadratic2d_exports = /* @__PURE__ */ __exportAll({
446
+ Ops: () => Ops$1,
275
447
  asDecreasing: () => asDecreasing$4,
276
448
  asIncreasing: () => asIncreasing$4,
277
449
  asMonotonic: () => asMonotonic$4,
278
450
  boundingBox: () => boundingBox$4,
279
451
  curvature: () => curvature$2,
280
452
  derivative: () => derivative$1,
453
+ endPoint: () => endPoint$4,
281
454
  fromBezierPoints: () => fromBezierPoints$4,
282
455
  fromCoefficients: () => fromCoefficients$2,
283
456
  fromPolynomials: () => fromPolynomials$4,
284
457
  isDecreasing: () => isDecreasing$4,
458
+ isDecreasingX: () => isDecreasingX$4,
459
+ isDecreasingY: () => isDecreasingY$4,
285
460
  isIncreasing: () => isIncreasing$4,
461
+ isIncreasingX: () => isIncreasingX$4,
462
+ isIncreasingY: () => isIncreasingY$4,
286
463
  isMonotonic: () => isMonotonic$4,
464
+ isMonotonicX: () => isMonotonicX$4,
465
+ isMonotonicY: () => isMonotonicY$4,
287
466
  isQuadraticCurve2d: () => isQuadraticCurve2d,
288
467
  length: () => length$2,
289
468
  solve: () => solve$4,
290
469
  solveAtX: () => solveAtX$4,
291
- solveAtY: () => solveAtY$4
470
+ solveAtY: () => solveAtY$4,
471
+ startPoint: () => startPoint$4,
472
+ toPathDataSegment: () => toPathDataSegment$2,
473
+ transform: () => transform$4,
474
+ xRange: () => xRange$2,
475
+ yRange: () => yRange$2
292
476
  });
293
477
  /**
294
478
  * Creates a new `QuadraticCurve2d` instance from polynomial parameters.
@@ -361,12 +545,78 @@ const curvature$2 = curvature$3;
361
545
  */
362
546
  const boundingBox$4 = boundingBox$5;
363
547
  /**
548
+ * Evaluates the curve at `t = 0` in closed form — `(c.x.c0, c.y.c0)`.
549
+ *
550
+ * @param c - The quadratic curve.
551
+ * @returns The point at the start of the curve's parameter domain.
552
+ * @since 2.0.0
553
+ */
554
+ const startPoint$4 = startPoint$5;
555
+ /**
556
+ * Evaluates the curve at `t = 1` in closed form — the sum of the per-axis
557
+ * monomial coefficients.
558
+ *
559
+ * @param c - The quadratic curve.
560
+ * @returns The point at the end of the curve's parameter domain.
561
+ * @since 2.0.0
562
+ */
563
+ const endPoint$4 = endPoint$5;
564
+ /**
565
+ * The tight `[min, max]` range of x over the curve's parameter domain `[0, 1]`,
566
+ * accounting for an interior extremum if one exists.
567
+ *
568
+ * @param c - The quadratic curve.
569
+ * @returns The closed range of x over `[0, 1]`.
570
+ * @since 2.0.0
571
+ */
572
+ const xRange$2 = xRange$3;
573
+ /**
574
+ * The tight `[min, max]` range of y over the curve's parameter domain `[0, 1]`,
575
+ * accounting for an interior extremum if one exists.
576
+ *
577
+ * @param c - The quadratic curve.
578
+ * @returns The closed range of y over `[0, 1]`.
579
+ * @since 2.0.0
580
+ */
581
+ const yRange$2 = yRange$3;
582
+ /**
583
+ * Renders the curve as a single SVG path-data drawing command — for a
584
+ * quadratic curve, `Q ctrlX,ctrlY endX,endY`, where the control point is
585
+ * recovered from the monomial coefficients via the inverse Bernstein
586
+ * expansion. Does not include a leading `M`.
587
+ *
588
+ * @param c - The quadratic curve.
589
+ * @returns The SVG drawing command for this segment, without a leading `M`.
590
+ * @since 2.0.0
591
+ */
592
+ const toPathDataSegment$2 = toPathDataSegment$3;
593
+ /**
594
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
595
+ * `Monotonic` when the x polynomial is strictly monotonic on the unit
596
+ * interval `[0, 1]`. The y-axis trait is unchanged.
597
+ *
598
+ * @since 2.0.0
599
+ */
600
+ const isMonotonicX$4 = isMonotonicX$5;
601
+ /** @since 2.0.0 */
602
+ const isIncreasingX$4 = isIncreasingX$5;
603
+ /** @since 2.0.0 */
604
+ const isDecreasingX$4 = isDecreasingX$5;
605
+ /**
606
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
607
+ * `Monotonic`. The x-axis trait is unchanged.
608
+ *
609
+ * @since 2.0.0
610
+ */
611
+ const isMonotonicY$4 = isMonotonicY$5;
612
+ /** @since 2.0.0 */
613
+ const isIncreasingY$4 = isIncreasingY$5;
614
+ /** @since 2.0.0 */
615
+ const isDecreasingY$4 = isDecreasingY$5;
616
+ /**
364
617
  * Type-narrowing predicate: refines both axes' traits to include `Monotonic`
365
618
  * when both x and y polynomials are monotonic over the unit interval `[0, 1]`.
366
619
  *
367
- * For checking only one axis, call the polynomial-level refiner directly:
368
- * `QuadraticPolynomial.isMonotonic(curve.x, Interval.unit)`.
369
- *
370
620
  * @since 2.0.0
371
621
  */
372
622
  const isMonotonic$4 = isMonotonic$5;
@@ -380,6 +630,31 @@ const asMonotonic$4 = asMonotonic$5;
380
630
  const asIncreasing$4 = asIncreasing$5;
381
631
  /** @since 2.0.0 */
382
632
  const asDecreasing$4 = asDecreasing$5;
633
+ const transform$4 = transform$5;
634
+ /**
635
+ * The {@link Curve2dOps} bundle for `QuadraticCurve2d`. Used by
636
+ * `QuadraticPath2d` to wire up the path-level operation surface. The
637
+ * `solveAtX` / `solveAtY` entries narrow the curve's potentially-2-element
638
+ * result to `AtMostOne` — path callers enforce that via the path's
639
+ * `MonotonicX`/`MonotonicY` brand.
640
+ *
641
+ * @since 2.0.0
642
+ */
643
+ const Ops$1 = {
644
+ solve: solve$4,
645
+ startPoint: startPoint$4,
646
+ endPoint: endPoint$4,
647
+ length: length$2,
648
+ boundingBox: boundingBox$4,
649
+ solveAtX: (c, x) => solveAtX$5(c, x),
650
+ solveAtY: (c, y) => solveAtY$5(c, y),
651
+ toPathDataSegment: toPathDataSegment$2,
652
+ isIncreasingX: isIncreasingX$4,
653
+ isDecreasingX: isDecreasingX$4,
654
+ isIncreasingY: isIncreasingY$4,
655
+ isDecreasingY: isDecreasingY$4,
656
+ transform: transform$4
657
+ };
383
658
  //#endregion
384
659
  //#region src/curve/cubic2d.internal.ts
385
660
  const CubicCurve2dTypeId = Symbol("curvy/curve/cubic2d");
@@ -405,26 +680,20 @@ const fromPolynomials$3 = (c0, c1) => new CubicCurve2dImpl(c0, c1);
405
680
  /** @internal */
406
681
  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
682
  /** @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
- };
683
+ const fromBezierPoints$3 = (p0, p1, p2, p3) => new CubicCurve2dImpl(...apply(cubicBezier, ...transpose([
684
+ p0,
685
+ p1,
686
+ p2,
687
+ p3
688
+ ], (p) => [p.x, p.y])));
416
689
  /** @internal */
417
690
  const isCubicCurve2d$1 = (c) => typeof c === "object" && c !== null && CubicCurve2dTypeId in c;
418
691
  /** @internal */
419
692
  const solve$3 = dual(2, (c, t) => make(solve$8(c.x, t), solve$8(c.y, t)));
420
693
  /** @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
- });
694
+ const solveAtX$3 = dual(2, (c, x) => solveInverse(c.x, x).pipe(clipApprox(unit), map(toSolver(c.y))));
424
695
  /** @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
- });
696
+ const solveAtY$3 = dual(2, (c, y) => solveInverse(c.y, y).pipe(clipApprox(unit), map(toSolver(c.x))));
428
697
  /** @internal */
429
698
  const derivative = (c) => fromPolynomials$4(derivative$5(c.x), derivative$5(c.y));
430
699
  /** @internal */
@@ -447,11 +716,43 @@ const curvature$1 = dual(2, (c, t) => {
447
716
  /** @internal */
448
717
  const boundingBox$3 = (c) => make$4(unitRange(c.x), unitRange(c.y));
449
718
  /** @internal */
450
- const isMonotonic$3 = (c) => isMonotonic$8(c.x, unit) && isMonotonic$8(c.y, unit);
719
+ const startPoint$3 = (c) => make(c.x.c0, c.y.c0);
720
+ /** @internal */
721
+ 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);
722
+ /** @internal */
723
+ const xRange$1 = (c) => unitRange(c.x);
724
+ /** @internal */
725
+ const yRange$1 = (c) => unitRange(c.y);
726
+ /** @internal */
727
+ const toPathDataSegment$1 = (c) => {
728
+ const c0x = c.x.c0;
729
+ const c0y = c.y.c0;
730
+ const c1x = c.x.c1;
731
+ const c1y = c.y.c1;
732
+ const c2x = c.x.c2;
733
+ const c2y = c.y.c2;
734
+ const c3x = c.x.c3;
735
+ const c3y = c.y.c3;
736
+ 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}`;
737
+ };
738
+ /** @internal */
739
+ const isMonotonicX$3 = (c) => isMonotonic$8(c.x, unit);
451
740
  /** @internal */
452
- const isIncreasing$3 = (c) => isIncreasing$8(c.x, unit) && isIncreasing$8(c.y, unit);
741
+ const isIncreasingX$3 = (c) => isIncreasing$8(c.x, unit);
453
742
  /** @internal */
454
- const isDecreasing$3 = (c) => isDecreasing$8(c.x, unit) && isDecreasing$8(c.y, unit);
743
+ const isDecreasingX$3 = (c) => isDecreasing$8(c.x, unit);
744
+ /** @internal */
745
+ const isMonotonicY$3 = (c) => isMonotonic$8(c.y, unit);
746
+ /** @internal */
747
+ const isIncreasingY$3 = (c) => isIncreasing$8(c.y, unit);
748
+ /** @internal */
749
+ const isDecreasingY$3 = (c) => isDecreasing$8(c.y, unit);
750
+ /** @internal */
751
+ const isMonotonic$3 = (c) => isMonotonicX$3(c) && isMonotonicY$3(c);
752
+ /** @internal */
753
+ const isIncreasing$3 = (c) => isIncreasingX$3(c) && isIncreasingY$3(c);
754
+ /** @internal */
755
+ const isDecreasing$3 = (c) => isDecreasingX$3(c) && isDecreasingY$3(c);
455
756
  const fail$1 = (m) => {
456
757
  throw new Error(m);
457
758
  };
@@ -461,25 +762,43 @@ const asMonotonic$3 = (c) => isMonotonic$3(c) ? c : fail$1("cubic curve is not m
461
762
  const asIncreasing$3 = (c) => isIncreasing$3(c) ? c : fail$1("cubic curve is not increasing in both axes");
462
763
  /** @internal */
463
764
  const asDecreasing$3 = (c) => isDecreasing$3(c) ? c : fail$1("cubic curve is not decreasing in both axes");
765
+ /** @internal */
766
+ const transform$3 = dual(2, (c, a) => {
767
+ const m = a.matrix;
768
+ 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));
769
+ });
464
770
  //#endregion
465
771
  //#region src/curve/cubic2d.ts
466
772
  var cubic2d_exports = /* @__PURE__ */ __exportAll({
773
+ Ops: () => Ops,
467
774
  asDecreasing: () => asDecreasing$2,
468
775
  asIncreasing: () => asIncreasing$2,
469
776
  asMonotonic: () => asMonotonic$2,
470
777
  boundingBox: () => boundingBox$2,
471
778
  curvature: () => curvature,
779
+ endPoint: () => endPoint$2,
472
780
  fromBezierPoints: () => fromBezierPoints$2,
473
781
  fromCoefficients: () => fromCoefficients,
474
782
  fromPolynomials: () => fromPolynomials$2,
475
783
  isCubicCurve2d: () => isCubicCurve2d,
476
784
  isDecreasing: () => isDecreasing$2,
785
+ isDecreasingX: () => isDecreasingX$2,
786
+ isDecreasingY: () => isDecreasingY$2,
477
787
  isIncreasing: () => isIncreasing$2,
788
+ isIncreasingX: () => isIncreasingX$2,
789
+ isIncreasingY: () => isIncreasingY$2,
478
790
  isMonotonic: () => isMonotonic$2,
791
+ isMonotonicX: () => isMonotonicX$2,
792
+ isMonotonicY: () => isMonotonicY$2,
479
793
  length: () => length,
480
794
  solve: () => solve$2,
481
795
  solveAtX: () => solveAtX$2,
482
- solveAtY: () => solveAtY$2
796
+ solveAtY: () => solveAtY$2,
797
+ startPoint: () => startPoint$2,
798
+ toPathDataSegment: () => toPathDataSegment,
799
+ transform: () => transform$2,
800
+ xRange: () => xRange,
801
+ yRange: () => yRange
483
802
  });
484
803
  /**
485
804
  * Creates a new `CubicCurve2d` instance from polynomial parameters.
@@ -545,12 +864,78 @@ const curvature = curvature$1;
545
864
  */
546
865
  const boundingBox$2 = boundingBox$3;
547
866
  /**
867
+ * Evaluates the curve at `t = 0` in closed form — `(c.x.c0, c.y.c0)`.
868
+ *
869
+ * @param c - The cubic curve.
870
+ * @returns The point at the start of the curve's parameter domain.
871
+ * @since 2.0.0
872
+ */
873
+ const startPoint$2 = startPoint$3;
874
+ /**
875
+ * Evaluates the curve at `t = 1` in closed form — the sum of the per-axis
876
+ * monomial coefficients.
877
+ *
878
+ * @param c - The cubic curve.
879
+ * @returns The point at the end of the curve's parameter domain.
880
+ * @since 2.0.0
881
+ */
882
+ const endPoint$2 = endPoint$3;
883
+ /**
884
+ * The tight `[min, max]` range of x over the curve's parameter domain `[0, 1]`,
885
+ * accounting for up to two interior extrema.
886
+ *
887
+ * @param c - The cubic curve.
888
+ * @returns The closed range of x over `[0, 1]`.
889
+ * @since 2.0.0
890
+ */
891
+ const xRange = xRange$1;
892
+ /**
893
+ * The tight `[min, max]` range of y over the curve's parameter domain `[0, 1]`,
894
+ * accounting for up to two interior extrema.
895
+ *
896
+ * @param c - The cubic curve.
897
+ * @returns The closed range of y over `[0, 1]`.
898
+ * @since 2.0.0
899
+ */
900
+ const yRange = yRange$1;
901
+ /**
902
+ * Renders the curve as a single SVG path-data drawing command — for a cubic
903
+ * curve, `C ctrl1X,ctrl1Y ctrl2X,ctrl2Y endX,endY`. Bernstein control points
904
+ * are recovered from the monomial coefficients in closed form. Does not
905
+ * include a leading `M`.
906
+ *
907
+ * @param c - The cubic curve.
908
+ * @returns The SVG drawing command for this segment, without a leading `M`.
909
+ * @since 2.0.0
910
+ */
911
+ const toPathDataSegment = toPathDataSegment$1;
912
+ /**
913
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
914
+ * `Monotonic` when the x polynomial is strictly monotonic on the unit
915
+ * interval `[0, 1]`. The y-axis trait is unchanged.
916
+ *
917
+ * @since 2.0.0
918
+ */
919
+ const isMonotonicX$2 = isMonotonicX$3;
920
+ /** @since 2.0.0 */
921
+ const isIncreasingX$2 = isIncreasingX$3;
922
+ /** @since 2.0.0 */
923
+ const isDecreasingX$2 = isDecreasingX$3;
924
+ /**
925
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
926
+ * `Monotonic`. The x-axis trait is unchanged.
927
+ *
928
+ * @since 2.0.0
929
+ */
930
+ const isMonotonicY$2 = isMonotonicY$3;
931
+ /** @since 2.0.0 */
932
+ const isIncreasingY$2 = isIncreasingY$3;
933
+ /** @since 2.0.0 */
934
+ const isDecreasingY$2 = isDecreasingY$3;
935
+ /**
548
936
  * Type-narrowing predicate: refines both axes' traits to include `Monotonic`
549
937
  * when both x and y polynomials are monotonic over the unit interval `[0, 1]`.
550
938
  *
551
- * For checking only one axis, call the polynomial-level refiner directly:
552
- * `CubicPolynomial.isMonotonic(curve.x, Interval.unit)`.
553
- *
554
939
  * @since 2.0.0
555
940
  */
556
941
  const isMonotonic$2 = isMonotonic$3;
@@ -564,6 +949,30 @@ const asMonotonic$2 = asMonotonic$3;
564
949
  const asIncreasing$2 = asIncreasing$3;
565
950
  /** @since 2.0.0 */
566
951
  const asDecreasing$2 = asDecreasing$3;
952
+ const transform$2 = transform$3;
953
+ /**
954
+ * The {@link Curve2dOps} bundle for `CubicCurve2d`. Used by `CubicPath2d`
955
+ * to wire up the path-level operation surface. The `solveAtX` / `solveAtY`
956
+ * entries narrow the curve's potentially-3-element result to `AtMostOne` —
957
+ * path callers enforce that via the path's `MonotonicX`/`MonotonicY` brand.
958
+ *
959
+ * @since 2.0.0
960
+ */
961
+ const Ops = {
962
+ solve: solve$2,
963
+ startPoint: startPoint$2,
964
+ endPoint: endPoint$2,
965
+ length,
966
+ boundingBox: boundingBox$2,
967
+ solveAtX: (c, x) => solveAtX$3(c, x),
968
+ solveAtY: (c, y) => solveAtY$3(c, y),
969
+ toPathDataSegment,
970
+ isIncreasingX: isIncreasingX$2,
971
+ isDecreasingX: isDecreasingX$2,
972
+ isIncreasingY: isIncreasingY$2,
973
+ isDecreasingY: isDecreasingY$2,
974
+ transform: transform$2
975
+ };
567
976
  //#endregion
568
977
  //#region src/curve/rationalCubic2d.internal.ts
569
978
  const RationalCubicCurve2dTypeId = Symbol("curvy/curve/rationalCubic2d");
@@ -586,43 +995,76 @@ var RationalCubicCurve2dImpl = class extends Pipeable {
586
995
  const isRationalCubicCurve2d$1 = (c) => typeof c === "object" && c !== null && RationalCubicCurve2dTypeId in c;
587
996
  /** @internal */
588
997
  const fromPolynomials$1 = (x, y, w) => new RationalCubicCurve2dImpl(x, y, w);
998
+ const EASING_P0 = makeWeighted(0, 0, 1);
999
+ const EASING_P3 = makeWeighted(1, 1, 1);
1000
+ /** @internal */
1001
+ const fromBezierPoints$1 = (...args) => {
1002
+ const [p0, p1, p2, p3] = args.length === 2 ? [
1003
+ EASING_P0,
1004
+ args[0],
1005
+ args[1],
1006
+ EASING_P3
1007
+ ] : args;
1008
+ return new RationalCubicCurve2dImpl(...apply(cubicBezier, ...transpose([
1009
+ p0,
1010
+ p1,
1011
+ p2,
1012
+ p3
1013
+ ], (p) => [
1014
+ p.x * p.weight,
1015
+ p.y * p.weight,
1016
+ p.weight
1017
+ ])));
1018
+ };
589
1019
  /** @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");
1020
+ const fromSlopesAndCurvatures$1 = (startSlope, endSlope, startCurvature, endCurvature) => {
1021
+ invariant(Number.isFinite(startSlope), "fromSlopesAndCurvatures: startSlope must be finite");
1022
+ invariant(Number.isFinite(endSlope), "fromSlopesAndCurvatures: endSlope must be finite");
1023
+ invariant(Number.isFinite(startCurvature), "fromSlopesAndCurvatures: startCurvature must be finite");
1024
+ invariant(Number.isFinite(endCurvature), "fromSlopesAndCurvatures: endCurvature must be finite");
604
1025
  const m0 = startSlope;
605
1026
  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.`);
1027
+ const d0 = startCurvature * Math.pow(1 + m0 * m0, 1.5);
1028
+ const d1 = endCurvature * Math.pow(1 + m1 * m1, 1.5);
1029
+ const u = 1 - m0;
1030
+ const v = 1 - m1;
1031
+ const det = 4 * u * d1 - 8 * v * v;
1032
+ const detScale = Math.max(Math.abs(4 * u * d1), Math.abs(8 * v * v), 1);
1033
+ const SINGULAR_TOLERANCE = 1e-12;
1034
+ let w0;
1035
+ let w1;
1036
+ let w2;
1037
+ if (Math.abs(det) > SINGULAR_TOLERANCE * detScale) {
1038
+ w0 = 1;
1039
+ w1 = (d0 * d1 + 4 * u * v) / det;
1040
+ w2 = (-8 * u * u - 4 * d0 * v) / det;
1041
+ } else if (u === 0 && v === 0) {
1042
+ invariant(d0 === 0 && d1 === 0, `fromSlopesAndCurvatures: inputs (m₀=${m0}, m₁=${m1}, κ₀=${startCurvature}, κ₁=${endCurvature}) yield an inconsistent constraint system`);
1043
+ return new RationalCubicCurve2dImpl(make$1(0, 1, 0, 0), make$1(0, 1, 0, 0), make$1(1, 0, 0, 0));
1044
+ } else {
1045
+ const residual = -8 * u * u - 4 * v * d0;
1046
+ invariant(Math.abs(residual) <= SINGULAR_TOLERANCE * detScale, `fromSlopesAndCurvatures: inputs (m₀=${m0}, m₁=${m1}, κ₀=${startCurvature}, κ₁=${endCurvature}) yield an inconsistent constraint system`);
1047
+ w0 = 1;
1048
+ w2 = 1;
1049
+ w1 = u !== 0 ? (d0 - 2 * v) / (4 * u) : -(2 * u + d1) / (4 * v);
1050
+ }
1051
+ invariant(w2 > 0, `fromSlopesAndCurvatures: inputs (m₀=${m0}, m₁=${m1}, κ₀=${startCurvature}, κ₁=${endCurvature}) yield denominator ≤ 0 at t = 1`);
1052
+ const a = w0 - 2 * w1 + w2;
1053
+ const b = 2 * (w1 - w0);
1054
+ if (a > 0) {
1055
+ const tStar = -b / (2 * a);
1056
+ 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
1057
  }
625
- return new RationalCubicCurve2dImpl(xPoly, yPoly, wPoly);
1058
+ const p1 = m0 * w0 / 3;
1059
+ const p2 = (v * w2 + 2 * w1) / 3;
1060
+ const p3 = w2;
1061
+ const yC1 = 3 * p1;
1062
+ const yC2 = 3 * (p2 - 2 * p1);
1063
+ const yC3 = p3 - 3 * p2 + 3 * p1;
1064
+ const wC0 = w0;
1065
+ const wC1 = b;
1066
+ const wC2 = a;
1067
+ return new RationalCubicCurve2dImpl(make$1(0, wC0, wC1, wC2), make$1(0, yC1, yC2, yC3), make$1(wC0, wC1, wC2, 0));
626
1068
  };
627
1069
  /** @internal */
628
1070
  const solve$1 = dual(2, (c, t) => {
@@ -630,9 +1072,16 @@ const solve$1 = dual(2, (c, t) => {
630
1072
  return make(solve$8(c.x, t) / w, solve$8(c.y, t) / w);
631
1073
  });
632
1074
  /** @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))));
1075
+ const startPoint$1 = (c) => make(c.x.c0 / c.w.c0, c.y.c0 / c.w.c0);
1076
+ /** @internal */
1077
+ const endPoint$1 = (c) => {
1078
+ const w = c.w.c0 + c.w.c1 + c.w.c2 + c.w.c3;
1079
+ 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);
1080
+ };
1081
+ /** @internal */
1082
+ 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
1083
  /** @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))));
1084
+ 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
1085
  const derivativeNumeratorQuartic = (n, d) => [
637
1086
  n.c1 * d.c0 - n.c0 * d.c1,
638
1087
  2 * (n.c2 * d.c0 - n.c0 * d.c2),
@@ -729,6 +1178,11 @@ const asMonotonic$1 = (c) => isMonotonic$1(c) ? c : fail("rational cubic curve i
729
1178
  const asIncreasing$1 = (c) => isIncreasing$1(c) ? c : fail("rational cubic curve is not increasing in both axes");
730
1179
  /** @internal */
731
1180
  const asDecreasing$1 = (c) => isDecreasing$1(c) ? c : fail("rational cubic curve is not decreasing in both axes");
1181
+ /** @internal */
1182
+ const transform$1 = dual(2, (c, a) => {
1183
+ const m = a.matrix;
1184
+ 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);
1185
+ });
732
1186
  const MAX_BBOX_DEPTH = 20;
733
1187
  /** @internal */
734
1188
  const boundingBox$1 = dual(2, (c, tolerance) => {
@@ -948,8 +1402,10 @@ var rationalCubic2d_exports = /* @__PURE__ */ __exportAll({
948
1402
  asMonotonicX: () => asMonotonicX,
949
1403
  asMonotonicY: () => asMonotonicY,
950
1404
  boundingBox: () => boundingBox,
1405
+ endPoint: () => endPoint,
951
1406
  fromBezierPoints: () => fromBezierPoints,
952
1407
  fromPolynomials: () => fromPolynomials,
1408
+ fromSlopesAndCurvatures: () => fromSlopesAndCurvatures,
953
1409
  isDecreasing: () => isDecreasing,
954
1410
  isDecreasingX: () => isDecreasingX,
955
1411
  isDecreasingY: () => isDecreasingY,
@@ -960,11 +1416,12 @@ var rationalCubic2d_exports = /* @__PURE__ */ __exportAll({
960
1416
  isMonotonicX: () => isMonotonicX,
961
1417
  isMonotonicY: () => isMonotonicY,
962
1418
  isRationalCubicCurve2d: () => isRationalCubicCurve2d,
963
- makeMonotonicEasing: () => makeMonotonicEasing,
964
1419
  solve: () => solve,
965
1420
  solveAtX: () => solveAtX,
966
1421
  solveAtY: () => solveAtY,
1422
+ startPoint: () => startPoint,
967
1423
  subdivide: () => subdivide,
1424
+ transform: () => transform,
968
1425
  xMonotonicity: () => xMonotonicity,
969
1426
  yMonotonicity: () => yMonotonicity
970
1427
  });
@@ -987,44 +1444,52 @@ const isRationalCubicCurve2d = isRationalCubicCurve2d$1;
987
1444
  * @since 2.0.0
988
1445
  */
989
1446
  const fromPolynomials = fromPolynomials$1;
1447
+ const fromBezierPoints = fromBezierPoints$1;
990
1448
  /**
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.
1449
+ * Creates a rational cubic easing curve from endpoint slopes and signed
1450
+ * curvatures. The result interpolates `(0, 0)` and `(1, 1)` with `x(t) = t`
1451
+ * pinned linearly; the y-axis projection `y(t) = Y(t)/W(t)` uses a cubic
1452
+ * numerator over a quadratic denominator, giving six free parameters that
1453
+ * exactly match the six endpoint constraints (two values, two slopes, two
1454
+ * curvatures).
995
1455
  *
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.
1456
+ * Curvatures are the signed differential-geometric curvatures `κ = y''(x) /
1457
+ * (1 + y'(x)²)^(3/2)` — the parameterization-invariant "bend" of the easing
1458
+ * graph. Positive κ is concave-up. Smoothstep is `(0, 0, 6, -6)`; linear is
1459
+ * `(1, 1, 0, 0)` (taken as a redundant-system special case).
1460
+ *
1461
+ * Monotonicity is not enforced. Callers needing the `Increasing` brand for
1462
+ * narrowed inverse-solve returns should follow construction with
1463
+ * {@link asIncreasing}, which verifies monotonicity rigorously.
1464
+ *
1465
+ * @param startSlope - The easing function's slope at the start (`dy/dx` at `x = 0`).
1466
+ * @param endSlope - The easing function's slope at the end (`dy/dx` at `x = 1`).
1467
+ * @param startCurvature - The signed differential curvature at the start.
1468
+ * @param endCurvature - The signed differential curvature at the end.
1469
+ * @returns A rational cubic easing curve.
1470
+ * @throws When inputs are non-finite, the constraint system is singular, or the resulting denominator vanishes on `[0, 1]`.
1001
1471
  * @since 2.0.0
1002
1472
  */
1003
- const fromBezierPoints = fromBezierPoints$1;
1473
+ const fromSlopesAndCurvatures = fromSlopesAndCurvatures$1;
1474
+ const solve = solve$1;
1004
1475
  /**
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.
1476
+ * Evaluates the curve at `t = 0` in closed form — `(c.x.c0 / c.w.c0, c.y.c0 / c.w.c0)`.
1013
1477
  *
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.
1478
+ * @param c - The rational cubic curve.
1479
+ * @returns The point at the start of the curve's parameter domain.
1480
+ * @since 2.0.0
1481
+ */
1482
+ const startPoint = startPoint$1;
1483
+ /**
1484
+ * Evaluates the curve at `t = 1` in closed form. Both numerator and denominator
1485
+ * Horner evaluations at `t = 1` collapse to the sum of their monomial
1486
+ * coefficients, so the projection is `(Σxᵢ / Σwᵢ, Σyᵢ / Σwᵢ)`.
1019
1487
  *
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.
1488
+ * @param c - The rational cubic curve.
1489
+ * @returns The point at the end of the curve's parameter domain.
1024
1490
  * @since 2.0.0
1025
1491
  */
1026
- const makeMonotonicEasing = makeMonotonicEasing$1;
1027
- const solve = solve$1;
1492
+ const endPoint = endPoint$1;
1028
1493
  const solveAtX = solveAtX$1;
1029
1494
  const solveAtY = solveAtY$1;
1030
1495
  const subdivide = subdivide$1;
@@ -1196,8 +1661,9 @@ const asIncreasing = asIncreasing$1;
1196
1661
  * @since 2.0.0
1197
1662
  */
1198
1663
  const asDecreasing = asDecreasing$1;
1664
+ const transform = transform$1;
1199
1665
  const approximateAsCubicCurves = approximateAsCubicCurves$1;
1200
1666
  //#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 };
1667
+ export { Ops$2 as _, solve as a, cubic2d_exports as c, length as d, solve$2 as f, solve$4 as g, quadratic2d_exports as h, rationalCubic2d_exports as i, fromCoefficients as l, Ops$1 as m, boundingBox as n, transform as o, derivative as p, fromBezierPoints as r, Ops as s, approximateAsCubicCurves as t, fromPolynomials$2 as u, fromEndpoints as v, linear2d_exports as y };
1202
1668
 
1203
- //# sourceMappingURL=rationalCubic2d-CeHgpNht.mjs.map
1669
+ //# sourceMappingURL=rationalCubic2d-CZSwwKtS.mjs.map