curvy 2.0.0-alpha.12 → 2.0.0-alpha.13

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 (37) hide show
  1. package/dist/characteristic/index.mjs +1 -1
  2. package/dist/curve/index.mjs +1 -1
  3. package/dist/curve/rationalCubic2d.d.ts +195 -11
  4. package/dist/interval/index.mjs +1 -1
  5. package/dist/monotonicity/index.d.ts +4 -0
  6. package/dist/monotonicity/index.mjs +2 -0
  7. package/dist/monotonicity/monotonicity.d.ts +80 -0
  8. package/dist/path/index.mjs +5 -5
  9. package/dist/path/rationalCubic2d.d.ts +27 -0
  10. package/dist/polynomial/cubic.d.ts +2 -2
  11. package/dist/polynomial/index.mjs +2 -2
  12. package/dist/polynomial/linear.d.ts +7 -7
  13. package/dist/polynomial/quadratic.d.ts +2 -2
  14. package/dist/shared/{characteristic-Hb7F8SBw.mjs → characteristic-BkEr-rr8.mjs} +2 -2
  15. package/dist/shared/{characteristic-Hb7F8SBw.mjs.map → characteristic-BkEr-rr8.mjs.map} +1 -1
  16. package/dist/shared/{cubic-DHJrzZJN.mjs → cubic-BL6dpuHh.mjs} +18 -30
  17. package/dist/shared/cubic-BL6dpuHh.mjs.map +1 -0
  18. package/dist/shared/{interval2d-DPmvk_Qe.mjs → interval2d-AtneyI45.mjs} +1 -1
  19. package/dist/shared/{interval2d-DPmvk_Qe.mjs.map → interval2d-AtneyI45.mjs.map} +1 -1
  20. package/dist/shared/monotonicity-BdebFOtv.mjs +34 -0
  21. package/dist/shared/monotonicity-BdebFOtv.mjs.map +1 -0
  22. package/dist/shared/{quadratic-BZmfZE71.mjs → quadratic-DPrUsFCp.mjs} +9 -9
  23. package/dist/shared/quadratic-DPrUsFCp.mjs.map +1 -0
  24. package/dist/shared/{rationalCubic2d-D5g3_hTV.mjs → rationalCubic2d-CeHgpNht.mjs} +373 -79
  25. package/dist/shared/rationalCubic2d-CeHgpNht.mjs.map +1 -0
  26. package/dist/shared/{rationalCubic2d-MojACId0.mjs → rationalCubic2d-H1J2Fjyy.mjs} +25 -16
  27. package/dist/shared/rationalCubic2d-H1J2Fjyy.mjs.map +1 -0
  28. package/dist/shared/{solution-B6KY1E7M.mjs → solution-B2JdOZpe.mjs} +1 -1
  29. package/dist/shared/{solution-B6KY1E7M.mjs.map → solution-B2JdOZpe.mjs.map} +1 -1
  30. package/dist/solution/index.mjs +1 -1
  31. package/dist/splines/index.mjs +4 -4
  32. package/package.json +5 -1
  33. package/dist/polynomial/monotonicity.d.ts +0 -3
  34. package/dist/shared/cubic-DHJrzZJN.mjs.map +0 -1
  35. package/dist/shared/quadratic-BZmfZE71.mjs.map +0 -1
  36. package/dist/shared/rationalCubic2d-D5g3_hTV.mjs.map +0 -1
  37. package/dist/shared/rationalCubic2d-MojACId0.mjs.map +0 -1
@@ -3,11 +3,12 @@ import { Pipeable, dual, invariant } from "../utils.mjs";
3
3
  import { a as make, i as magnitude, n as cross } from "./vector2-CSkaMXvp.mjs";
4
4
  import { n as transpose } from "./vector4-PO_7EYd-.mjs";
5
5
  import { l as scaleShift, m as unitOpen, p as unit, t as biunit, u as size } from "./interval-Dm35Xhy4.mjs";
6
- import { a as match, i as map, o as none, s as one, t as clip } from "./solution-B6KY1E7M.mjs";
7
- 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$6, 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$6, j as GL32_X10, k as GL32_X0, l as solve$8, m as GL32_W1, n as derivative$5, o as isMonotonic$6, 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-DHJrzZJN.mjs";
8
- import { _ as unitRange$1, a as make$3, c as solveInverse$2, d as isIncreasing$7, f as isMonotonic$7, g as solveInverse$1, h as solve$9, i as isMonotonic$8, l as unitRange$2, m as make$2, n as isDecreasing$8, r as isIncreasing$8, s as solve$10, t as derivative$6, u as isDecreasing$7 } from "./quadratic-BZmfZE71.mjs";
9
- import { i as maxDistance, r as make$4, t as fromVectors } from "./interval2d-DPmvk_Qe.mjs";
10
- import { i as cubicBezier, t as apply } from "./characteristic-Hb7F8SBw.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";
11
12
  //#region src/curve/linear2d.internal.ts
12
13
  const LinearCurve2dTypeId = Symbol("curvy/curve/linear2d");
13
14
  /** @internal */
@@ -54,35 +55,35 @@ const length$5 = dual(2, (c, i) => Math.sqrt(c.x.c1 ** 2 + c.y.c1 ** 2) * Math.a
54
55
  /** @internal */
55
56
  const boundingBox$7 = (c) => make$4(unitRange$1(c.x), unitRange$1(c.y));
56
57
  /** @internal */
57
- const isMonotonic$5 = (c) => isMonotonic$7(c.x) && isMonotonic$7(c.y);
58
+ const isMonotonic$7 = (c) => isMonotonic$9(c.x) && isMonotonic$9(c.y);
58
59
  /** @internal */
59
- const isIncreasing$5 = (c) => isIncreasing$7(c.x) && isIncreasing$7(c.y);
60
+ const isIncreasing$7 = (c) => isIncreasing$9(c.x) && isIncreasing$9(c.y);
60
61
  /** @internal */
61
- const isDecreasing$5 = (c) => isDecreasing$7(c.x) && isDecreasing$7(c.y);
62
- const fail$2 = (m) => {
62
+ const isDecreasing$7 = (c) => isDecreasing$9(c.x) && isDecreasing$9(c.y);
63
+ const fail$3 = (m) => {
63
64
  throw new Error(m);
64
65
  };
65
66
  /** @internal */
66
- const asMonotonic$5 = (c) => isMonotonic$5(c) ? c : fail$2("linear curve is not monotonic in both axes");
67
+ const asMonotonic$7 = (c) => isMonotonic$7(c) ? c : fail$3("linear curve is not monotonic in both axes");
67
68
  /** @internal */
68
- const asIncreasing$5 = (c) => isIncreasing$5(c) ? c : fail$2("linear curve is not increasing in both axes");
69
+ const asIncreasing$7 = (c) => isIncreasing$7(c) ? c : fail$3("linear curve is not increasing in both axes");
69
70
  /** @internal */
70
- const asDecreasing$5 = (c) => isDecreasing$5(c) ? c : fail$2("linear curve is not decreasing in both axes");
71
+ const asDecreasing$7 = (c) => isDecreasing$7(c) ? c : fail$3("linear curve is not decreasing in both axes");
71
72
  //#endregion
72
73
  //#region src/curve/linear2d.ts
73
74
  var linear2d_exports = /* @__PURE__ */ __exportAll({
74
- asDecreasing: () => asDecreasing$4,
75
- asIncreasing: () => asIncreasing$4,
76
- asMonotonic: () => asMonotonic$4,
75
+ asDecreasing: () => asDecreasing$6,
76
+ asIncreasing: () => asIncreasing$6,
77
+ asMonotonic: () => asMonotonic$6,
77
78
  boundingBox: () => boundingBox$6,
78
79
  derivative: () => derivative$3,
79
80
  fromCoefficients: () => fromCoefficients$4,
80
81
  fromEndpoints: () => fromEndpoints,
81
82
  fromPolynomials: () => fromPolynomials$6,
82
- isDecreasing: () => isDecreasing$4,
83
- isIncreasing: () => isIncreasing$4,
83
+ isDecreasing: () => isDecreasing$6,
84
+ isIncreasing: () => isIncreasing$6,
84
85
  isLinearCurve2d: () => isLinearCurve2d,
85
- isMonotonic: () => isMonotonic$4,
86
+ isMonotonic: () => isMonotonic$6,
86
87
  length: () => length$4,
87
88
  solve: () => solve$6,
88
89
  solveAtX: () => solveAtX$6,
@@ -163,37 +164,37 @@ const solveAtY$6 = solveAtY$7;
163
164
  *
164
165
  * @since 2.0.0
165
166
  */
166
- const isMonotonic$4 = isMonotonic$5;
167
+ const isMonotonic$6 = isMonotonic$7;
167
168
  /**
168
169
  * Type-narrowing predicate: refines both axes' traits to include `Increasing`.
169
170
  *
170
171
  * @since 2.0.0
171
172
  */
172
- const isIncreasing$4 = isIncreasing$5;
173
+ const isIncreasing$6 = isIncreasing$7;
173
174
  /**
174
175
  * Type-narrowing predicate: refines both axes' traits to include `Decreasing`.
175
176
  *
176
177
  * @since 2.0.0
177
178
  */
178
- const isDecreasing$4 = isDecreasing$5;
179
+ const isDecreasing$6 = isDecreasing$7;
179
180
  /**
180
181
  * Asserts monotonicity in both axes, throwing on failure.
181
182
  *
182
183
  * @since 2.0.0
183
184
  */
184
- const asMonotonic$4 = asMonotonic$5;
185
+ const asMonotonic$6 = asMonotonic$7;
185
186
  /**
186
187
  * Asserts that both axes are strictly increasing, throwing on failure.
187
188
  *
188
189
  * @since 2.0.0
189
190
  */
190
- const asIncreasing$4 = asIncreasing$5;
191
+ const asIncreasing$6 = asIncreasing$7;
191
192
  /**
192
193
  * Asserts that both axes are strictly decreasing, throwing on failure.
193
194
  *
194
195
  * @since 2.0.0
195
196
  */
196
- const asDecreasing$4 = asDecreasing$5;
197
+ const asDecreasing$6 = asDecreasing$7;
197
198
  //#endregion
198
199
  //#region src/curve/quadratic2d.internal.ts
199
200
  const QuadraticCurve2dTypeId = Symbol("curvy/curve/quadratic2d");
@@ -254,35 +255,35 @@ const curvature$3 = dual(2, (c, t) => {
254
255
  /** @internal */
255
256
  const boundingBox$5 = (c) => make$4(unitRange$2(c.x), unitRange$2(c.y));
256
257
  /** @internal */
257
- const isMonotonic$3 = (c) => isMonotonic$8(c.x, unit) && isMonotonic$8(c.y, unit);
258
+ const isMonotonic$5 = (c) => isMonotonic$10(c.x, unit) && isMonotonic$10(c.y, unit);
258
259
  /** @internal */
259
- const isIncreasing$3 = (c) => isIncreasing$8(c.x, unit) && isIncreasing$8(c.y, unit);
260
+ const isIncreasing$5 = (c) => isIncreasing$10(c.x, unit) && isIncreasing$10(c.y, unit);
260
261
  /** @internal */
261
- const isDecreasing$3 = (c) => isDecreasing$8(c.x, unit) && isDecreasing$8(c.y, unit);
262
- const fail$1 = (m) => {
262
+ const isDecreasing$5 = (c) => isDecreasing$10(c.x, unit) && isDecreasing$10(c.y, unit);
263
+ const fail$2 = (m) => {
263
264
  throw new Error(m);
264
265
  };
265
266
  /** @internal */
266
- const asMonotonic$3 = (c) => isMonotonic$3(c) ? c : fail$1("quadratic curve is not monotonic in both axes");
267
+ const asMonotonic$5 = (c) => isMonotonic$5(c) ? c : fail$2("quadratic curve is not monotonic in both axes");
267
268
  /** @internal */
268
- const asIncreasing$3 = (c) => isIncreasing$3(c) ? c : fail$1("quadratic curve is not increasing in both axes");
269
+ const asIncreasing$5 = (c) => isIncreasing$5(c) ? c : fail$2("quadratic curve is not increasing in both axes");
269
270
  /** @internal */
270
- const asDecreasing$3 = (c) => isDecreasing$3(c) ? c : fail$1("quadratic curve is not decreasing in both axes");
271
+ const asDecreasing$5 = (c) => isDecreasing$5(c) ? c : fail$2("quadratic curve is not decreasing in both axes");
271
272
  //#endregion
272
273
  //#region src/curve/quadratic2d.ts
273
274
  var quadratic2d_exports = /* @__PURE__ */ __exportAll({
274
- asDecreasing: () => asDecreasing$2,
275
- asIncreasing: () => asIncreasing$2,
276
- asMonotonic: () => asMonotonic$2,
275
+ asDecreasing: () => asDecreasing$4,
276
+ asIncreasing: () => asIncreasing$4,
277
+ asMonotonic: () => asMonotonic$4,
277
278
  boundingBox: () => boundingBox$4,
278
279
  curvature: () => curvature$2,
279
280
  derivative: () => derivative$1,
280
281
  fromBezierPoints: () => fromBezierPoints$4,
281
282
  fromCoefficients: () => fromCoefficients$2,
282
283
  fromPolynomials: () => fromPolynomials$4,
283
- isDecreasing: () => isDecreasing$2,
284
- isIncreasing: () => isIncreasing$2,
285
- isMonotonic: () => isMonotonic$2,
284
+ isDecreasing: () => isDecreasing$4,
285
+ isIncreasing: () => isIncreasing$4,
286
+ isMonotonic: () => isMonotonic$4,
286
287
  isQuadraticCurve2d: () => isQuadraticCurve2d,
287
288
  length: () => length$2,
288
289
  solve: () => solve$4,
@@ -368,17 +369,17 @@ const boundingBox$4 = boundingBox$5;
368
369
  *
369
370
  * @since 2.0.0
370
371
  */
371
- const isMonotonic$2 = isMonotonic$3;
372
+ const isMonotonic$4 = isMonotonic$5;
372
373
  /** @since 2.0.0 */
373
- const isIncreasing$2 = isIncreasing$3;
374
+ const isIncreasing$4 = isIncreasing$5;
374
375
  /** @since 2.0.0 */
375
- const isDecreasing$2 = isDecreasing$3;
376
+ const isDecreasing$4 = isDecreasing$5;
376
377
  /** @since 2.0.0 */
377
- const asMonotonic$2 = asMonotonic$3;
378
+ const asMonotonic$4 = asMonotonic$5;
378
379
  /** @since 2.0.0 */
379
- const asIncreasing$2 = asIncreasing$3;
380
+ const asIncreasing$4 = asIncreasing$5;
380
381
  /** @since 2.0.0 */
381
- const asDecreasing$2 = asDecreasing$3;
382
+ const asDecreasing$4 = asDecreasing$5;
382
383
  //#endregion
383
384
  //#region src/curve/cubic2d.internal.ts
384
385
  const CubicCurve2dTypeId = Symbol("curvy/curve/cubic2d");
@@ -446,35 +447,35 @@ const curvature$1 = dual(2, (c, t) => {
446
447
  /** @internal */
447
448
  const boundingBox$3 = (c) => make$4(unitRange(c.x), unitRange(c.y));
448
449
  /** @internal */
449
- const isMonotonic$1 = (c) => isMonotonic$6(c.x, unit) && isMonotonic$6(c.y, unit);
450
+ const isMonotonic$3 = (c) => isMonotonic$8(c.x, unit) && isMonotonic$8(c.y, unit);
450
451
  /** @internal */
451
- const isIncreasing$1 = (c) => isIncreasing$6(c.x, unit) && isIncreasing$6(c.y, unit);
452
+ const isIncreasing$3 = (c) => isIncreasing$8(c.x, unit) && isIncreasing$8(c.y, unit);
452
453
  /** @internal */
453
- const isDecreasing$1 = (c) => isDecreasing$6(c.x, unit) && isDecreasing$6(c.y, unit);
454
- const fail = (m) => {
454
+ const isDecreasing$3 = (c) => isDecreasing$8(c.x, unit) && isDecreasing$8(c.y, unit);
455
+ const fail$1 = (m) => {
455
456
  throw new Error(m);
456
457
  };
457
458
  /** @internal */
458
- const asMonotonic$1 = (c) => isMonotonic$1(c) ? c : fail("cubic curve is not monotonic in both axes");
459
+ const asMonotonic$3 = (c) => isMonotonic$3(c) ? c : fail$1("cubic curve is not monotonic in both axes");
459
460
  /** @internal */
460
- const asIncreasing$1 = (c) => isIncreasing$1(c) ? c : fail("cubic curve is not increasing in both axes");
461
+ const asIncreasing$3 = (c) => isIncreasing$3(c) ? c : fail$1("cubic curve is not increasing in both axes");
461
462
  /** @internal */
462
- const asDecreasing$1 = (c) => isDecreasing$1(c) ? c : fail("cubic curve is not decreasing in both axes");
463
+ const asDecreasing$3 = (c) => isDecreasing$3(c) ? c : fail$1("cubic curve is not decreasing in both axes");
463
464
  //#endregion
464
465
  //#region src/curve/cubic2d.ts
465
466
  var cubic2d_exports = /* @__PURE__ */ __exportAll({
466
- asDecreasing: () => asDecreasing,
467
- asIncreasing: () => asIncreasing,
468
- asMonotonic: () => asMonotonic,
467
+ asDecreasing: () => asDecreasing$2,
468
+ asIncreasing: () => asIncreasing$2,
469
+ asMonotonic: () => asMonotonic$2,
469
470
  boundingBox: () => boundingBox$2,
470
471
  curvature: () => curvature,
471
472
  fromBezierPoints: () => fromBezierPoints$2,
472
473
  fromCoefficients: () => fromCoefficients,
473
474
  fromPolynomials: () => fromPolynomials$2,
474
475
  isCubicCurve2d: () => isCubicCurve2d,
475
- isDecreasing: () => isDecreasing,
476
- isIncreasing: () => isIncreasing,
477
- isMonotonic: () => isMonotonic,
476
+ isDecreasing: () => isDecreasing$2,
477
+ isIncreasing: () => isIncreasing$2,
478
+ isMonotonic: () => isMonotonic$2,
478
479
  length: () => length,
479
480
  solve: () => solve$2,
480
481
  solveAtX: () => solveAtX$2,
@@ -552,17 +553,17 @@ const boundingBox$2 = boundingBox$3;
552
553
  *
553
554
  * @since 2.0.0
554
555
  */
555
- const isMonotonic = isMonotonic$1;
556
+ const isMonotonic$2 = isMonotonic$3;
556
557
  /** @since 2.0.0 */
557
- const isIncreasing = isIncreasing$1;
558
+ const isIncreasing$2 = isIncreasing$3;
558
559
  /** @since 2.0.0 */
559
- const isDecreasing = isDecreasing$1;
560
+ const isDecreasing$2 = isDecreasing$3;
560
561
  /** @since 2.0.0 */
561
- const asMonotonic = asMonotonic$1;
562
+ const asMonotonic$2 = asMonotonic$3;
562
563
  /** @since 2.0.0 */
563
- const asIncreasing = asIncreasing$1;
564
+ const asIncreasing$2 = asIncreasing$3;
564
565
  /** @since 2.0.0 */
565
- const asDecreasing = asDecreasing$1;
566
+ const asDecreasing$2 = asDecreasing$3;
566
567
  //#endregion
567
568
  //#region src/curve/rationalCubic2d.internal.ts
568
569
  const RationalCubicCurve2dTypeId = Symbol("curvy/curve/rationalCubic2d");
@@ -632,6 +633,128 @@ const solve$1 = dual(2, (c, t) => {
632
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))));
633
634
  /** @internal */
634
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))));
636
+ const derivativeNumeratorQuartic = (n, d) => [
637
+ n.c1 * d.c0 - n.c0 * d.c1,
638
+ 2 * (n.c2 * d.c0 - n.c0 * d.c2),
639
+ n.c2 * d.c1 - n.c1 * d.c2 + 3 * (n.c3 * d.c0 - n.c0 * d.c3),
640
+ 2 * (n.c3 * d.c1 - n.c1 * d.c3),
641
+ n.c3 * d.c2 - n.c2 * d.c3
642
+ ];
643
+ const bernsteinFromQuarticMonomial = (c0, c1, c2, c3, c4) => [
644
+ c0,
645
+ c0 + c1 / 4,
646
+ c0 + c1 / 2 + c2 / 6,
647
+ c0 + 3 * c1 / 4 + c2 / 2 + c3 / 4,
648
+ c0 + c1 + c2 + c3 + c4
649
+ ];
650
+ const BERNSTEIN_SIGN_MAX_DEPTH = 32;
651
+ const certifyBernsteinSign = (bs, depth = 0) => {
652
+ let m = 0;
653
+ for (let i = 0; i < 5; i++) {
654
+ const b = bs[i];
655
+ if (b > 0) m = m | 1;
656
+ else if (b < 0) m = m | 2;
657
+ }
658
+ if (m !== 3) return m;
659
+ if (depth >= BERNSTEIN_SIGN_MAX_DEPTH) return 3;
660
+ const [b0, b1, b2, b3, b4] = bs;
661
+ const c0 = (b0 + b1) * .5;
662
+ const c1 = (b1 + b2) * .5;
663
+ const c2 = (b2 + b3) * .5;
664
+ const c3 = (b3 + b4) * .5;
665
+ const d0 = (c0 + c1) * .5;
666
+ const d1 = (c1 + c2) * .5;
667
+ const d2 = (c2 + c3) * .5;
668
+ const e0 = (d0 + d1) * .5;
669
+ const e1 = (d1 + d2) * .5;
670
+ const f = (e0 + e1) * .5;
671
+ return certifyBernsteinSign([
672
+ b0,
673
+ c0,
674
+ d0,
675
+ e0,
676
+ f
677
+ ], depth + 1) | certifyBernsteinSign([
678
+ f,
679
+ e1,
680
+ d2,
681
+ c3,
682
+ b4
683
+ ], depth + 1);
684
+ };
685
+ const axisMonotonicity = (numerator, denominator) => {
686
+ const [q0, q1, q2, q3, q4] = derivativeNumeratorQuartic(numerator, denominator);
687
+ return certifyBernsteinSign(bernsteinFromQuarticMonomial(q0, q1, q2, q3, q4));
688
+ };
689
+ /** @internal */
690
+ const xMonotonicity$1 = (c) => axisMonotonicity(c.x, c.w);
691
+ /** @internal */
692
+ const yMonotonicity$1 = (c) => axisMonotonicity(c.y, c.w);
693
+ /** @internal */
694
+ const isMonotonicX$1 = (c) => isStrict(xMonotonicity$1(c));
695
+ /** @internal */
696
+ const isIncreasingX$1 = (c) => xMonotonicity$1(c) === 1;
697
+ /** @internal */
698
+ const isDecreasingX$1 = (c) => xMonotonicity$1(c) === 2;
699
+ /** @internal */
700
+ const isMonotonicY$1 = (c) => isStrict(yMonotonicity$1(c));
701
+ /** @internal */
702
+ const isIncreasingY$1 = (c) => yMonotonicity$1(c) === 1;
703
+ /** @internal */
704
+ const isDecreasingY$1 = (c) => yMonotonicity$1(c) === 2;
705
+ /** @internal */
706
+ const isMonotonic$1 = (c) => isMonotonicX$1(c) && isMonotonicY$1(c);
707
+ /** @internal */
708
+ const isIncreasing$1 = (c) => isIncreasingX$1(c) && isIncreasingY$1(c);
709
+ /** @internal */
710
+ const isDecreasing$1 = (c) => isDecreasingX$1(c) && isDecreasingY$1(c);
711
+ const fail = (m) => {
712
+ throw new Error(m);
713
+ };
714
+ /** @internal */
715
+ const asMonotonicX$1 = (c) => isMonotonicX$1(c) ? c : fail("rational cubic curve is not monotonic in x");
716
+ /** @internal */
717
+ const asIncreasingX$1 = (c) => isIncreasingX$1(c) ? c : fail("rational cubic curve is not increasing in x");
718
+ /** @internal */
719
+ const asDecreasingX$1 = (c) => isDecreasingX$1(c) ? c : fail("rational cubic curve is not decreasing in x");
720
+ /** @internal */
721
+ const asMonotonicY$1 = (c) => isMonotonicY$1(c) ? c : fail("rational cubic curve is not monotonic in y");
722
+ /** @internal */
723
+ const asIncreasingY$1 = (c) => isIncreasingY$1(c) ? c : fail("rational cubic curve is not increasing in y");
724
+ /** @internal */
725
+ const asDecreasingY$1 = (c) => isDecreasingY$1(c) ? c : fail("rational cubic curve is not decreasing in y");
726
+ /** @internal */
727
+ const asMonotonic$1 = (c) => isMonotonic$1(c) ? c : fail("rational cubic curve is not monotonic in both axes");
728
+ /** @internal */
729
+ const asIncreasing$1 = (c) => isIncreasing$1(c) ? c : fail("rational cubic curve is not increasing in both axes");
730
+ /** @internal */
731
+ const asDecreasing$1 = (c) => isDecreasing$1(c) ? c : fail("rational cubic curve is not decreasing in both axes");
732
+ const MAX_BBOX_DEPTH = 20;
733
+ /** @internal */
734
+ const boundingBox$1 = dual(2, (c, tolerance) => {
735
+ invariant(Number.isFinite(tolerance) && tolerance > 0, "boundingBox: tolerance must be finite and > 0");
736
+ if (c.w.c1 === 0 && c.w.c2 === 0 && c.w.c3 === 0) {
737
+ const w = c.w.c0;
738
+ return make$4(unitRange(make$1(c.x.c0 / w, c.x.c1 / w, c.x.c2 / w, c.x.c3 / w)), unitRange(make$1(c.y.c0 / w, c.y.c1 / w, c.y.c2 / w, c.y.c3 / w)));
739
+ }
740
+ const recurse = (curr, depth) => {
741
+ const hull = hullBoundingBox(curr);
742
+ const w0 = curr.w.c0;
743
+ const x0 = curr.x.c0 / w0;
744
+ const y0 = curr.y.c0 / w0;
745
+ const w1 = curr.w.c0 + curr.w.c1 + curr.w.c2 + curr.w.c3;
746
+ const x1 = (curr.x.c0 + curr.x.c1 + curr.x.c2 + curr.x.c3) / w1;
747
+ const y1 = (curr.y.c0 + curr.y.c1 + curr.y.c2 + curr.y.c3) / w1;
748
+ const lowX = Math.min(x0, x1);
749
+ const highX = Math.max(x0, x1);
750
+ const lowY = Math.min(y0, y1);
751
+ const highY = Math.max(y0, y1);
752
+ if (Math.max(lowX - hull.x.start, hull.x.end - highX, lowY - hull.y.start, hull.y.end - highY) <= tolerance || depth >= MAX_BBOX_DEPTH) return hull;
753
+ const [left, right] = subdivide$1(curr, .5);
754
+ return union(recurse(left, depth + 1), recurse(right, depth + 1));
755
+ };
756
+ return recurse(c, 0);
757
+ });
635
758
  const MAX_APPROX_DEPTH = 20;
636
759
  const buildCubicCandidate = (c) => {
637
760
  const x0 = c.x.c0;
@@ -655,8 +778,7 @@ const subdivide$1 = dual(2, (c, t) => {
655
778
  const [leftW, rightW] = subdivide$2(c.w, t);
656
779
  return [new RationalCubicCurve2dImpl(leftX, leftY, leftW), new RationalCubicCurve2dImpl(rightX, rightY, rightW)];
657
780
  });
658
- /** @internal */
659
- const boundingBox$1 = (c) => {
781
+ const hullBoundingBox = (c) => {
660
782
  const x0 = c.x.c0;
661
783
  const x1 = c.x.c0 + c.x.c1 / 3;
662
784
  const x2 = c.x.c0 + 2 * c.x.c1 / 3 + c.x.c2 / 3;
@@ -747,7 +869,7 @@ const rationalPiece = (c, depth = 0) => {
747
869
  const witnessX = solve$8(c.x, .5) / wMid;
748
870
  const witnessY = solve$8(c.y, .5) / wMid;
749
871
  return {
750
- box: boundingBox$1(c),
872
+ box: hullBoundingBox(c),
751
873
  witnessX,
752
874
  witnessY,
753
875
  depth,
@@ -791,7 +913,7 @@ const hausdorffWithinTolerance = (rational, candidate, tolerance) => {
791
913
  if (rational.w.c1 === 0 && rational.w.c2 === 0 && rational.w.c3 === 0) return true;
792
914
  const candidateBox = boundingBox$2(candidate);
793
915
  if (!oneSidedWithinTolerance(rationalPiece(rational), candidateBox, (qx, qy) => closestSquaredDistance((s) => polynomialEval(candidate, s), qx, qy), tolerance)) return false;
794
- const rationalBox = boundingBox$1(rational);
916
+ const rationalBox = hullBoundingBox(rational);
795
917
  return oneSidedWithinTolerance(polynomialPiece(candidate), rationalBox, (qx, qy) => closestSquaredDistance((s) => rationalEval(rational, s), qx, qy), tolerance);
796
918
  };
797
919
  /** @internal */
@@ -816,15 +938,35 @@ const approximateAsCubicCurves$1 = dual(2, (c, tolerance) => {
816
938
  var rationalCubic2d_exports = /* @__PURE__ */ __exportAll({
817
939
  RationalCurveTraits: () => RationalCurveTraits,
818
940
  approximateAsCubicCurves: () => approximateAsCubicCurves,
941
+ asDecreasing: () => asDecreasing,
942
+ asDecreasingX: () => asDecreasingX,
943
+ asDecreasingY: () => asDecreasingY,
944
+ asIncreasing: () => asIncreasing,
945
+ asIncreasingX: () => asIncreasingX,
946
+ asIncreasingY: () => asIncreasingY,
947
+ asMonotonic: () => asMonotonic,
948
+ asMonotonicX: () => asMonotonicX,
949
+ asMonotonicY: () => asMonotonicY,
819
950
  boundingBox: () => boundingBox,
820
951
  fromBezierPoints: () => fromBezierPoints,
821
952
  fromPolynomials: () => fromPolynomials,
953
+ isDecreasing: () => isDecreasing,
954
+ isDecreasingX: () => isDecreasingX,
955
+ isDecreasingY: () => isDecreasingY,
956
+ isIncreasing: () => isIncreasing,
957
+ isIncreasingX: () => isIncreasingX,
958
+ isIncreasingY: () => isIncreasingY,
959
+ isMonotonic: () => isMonotonic,
960
+ isMonotonicX: () => isMonotonicX,
961
+ isMonotonicY: () => isMonotonicY,
822
962
  isRationalCubicCurve2d: () => isRationalCubicCurve2d,
823
963
  makeMonotonicEasing: () => makeMonotonicEasing,
824
964
  solve: () => solve,
825
965
  solveAtX: () => solveAtX,
826
966
  solveAtY: () => solveAtY,
827
- subdivide: () => subdivide
967
+ subdivide: () => subdivide,
968
+ xMonotonicity: () => xMonotonicity,
969
+ yMonotonicity: () => yMonotonicity
828
970
  });
829
971
  /**
830
972
  * Checks if a value is a `RationalCubicCurve2d`.
@@ -886,24 +1028,176 @@ const solve = solve$1;
886
1028
  const solveAtX = solveAtX$1;
887
1029
  const solveAtY = solveAtY$1;
888
1030
  const subdivide = subdivide$1;
1031
+ const boundingBox = boundingBox$1;
889
1032
  /**
890
- * Computes a closed axis-aligned bounding box for a rational cubic curve from
891
- * its projected control polygon. Looser than the tight extrema-based box used
892
- * by `CubicCurve2d.boundingBox` — finding tight extrema of `x(t)/w(t)` and
893
- * `y(t)/w(t)` requires solving degree-5 polynomials — but always valid: a
894
- * positive-weight rational Bézier curve lies inside the convex hull of its
895
- * projected control points, so the AABB of those points contains the curve.
1033
+ * Classifies the monotonicity of the curve's `x(t) = X(t)/W(t)` projection on
1034
+ * the unit interval `[0, 1]`.
1035
+ *
1036
+ * Decided via Bernstein sign convexity on the derivative-numerator polynomial
1037
+ * `q(t) = X'·W − X·W'`. Since `W² > 0` wherever the curve is well-defined,
1038
+ * the sign of `dx/dt` equals the sign of `q`. Although `q` is a difference of
1039
+ * degree-5 products, the leading terms cancel and `q` is in fact a quartic —
1040
+ * its 5 Bernstein coefficients on `[0, 1]` are evaluated for uniform sign,
1041
+ * with de Casteljau subdivision to resolve mixed-sign cases. The procedure is
1042
+ * exact except at tangential zeros, where it conservatively reports `None`.
896
1043
  *
897
- * Suitable for subdivision-based geometric queries, where bound looseness is
898
- * compensated by recursion depth.
1044
+ * Returning `Increasing` or `Decreasing` is the trigger for
1045
+ * {@link asMonotonic} / {@link asIncreasing} / {@link asDecreasing}.
899
1046
  *
900
1047
  * @param c - The rational cubic curve.
901
- * @returns A closed `Interval2d` enclosing the curve.
1048
+ * @returns The monotonicity of the curve's x projection on `[0, 1]`.
902
1049
  * @since 2.0.0
903
1050
  */
904
- const boundingBox = boundingBox$1;
1051
+ const xMonotonicity = xMonotonicity$1;
1052
+ /**
1053
+ * Classifies the monotonicity of the curve's `y(t) = Y(t)/W(t)` projection on
1054
+ * the unit interval `[0, 1]`. See {@link xMonotonicity} for the method.
1055
+ *
1056
+ * @param c - The rational cubic curve.
1057
+ * @returns The monotonicity of the curve's y projection on `[0, 1]`.
1058
+ * @since 2.0.0
1059
+ */
1060
+ const yMonotonicity = yMonotonicity$1;
1061
+ /**
1062
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
1063
+ * `Monotonic` when `x(t)/w(t)` is strictly monotonic on `[0, 1]`. The y-axis
1064
+ * trait is unchanged.
1065
+ *
1066
+ * Use this when only x-axis monotonicity is required (e.g. to make {@link solveAtX}
1067
+ * narrow to `AtMostOne` without also asserting y-axis monotonicity).
1068
+ *
1069
+ * @param c - The rational cubic curve.
1070
+ * @returns `true` when the x projection is strictly monotonic on `[0, 1]`.
1071
+ * @since 2.0.0
1072
+ */
1073
+ const isMonotonicX = isMonotonicX$1;
1074
+ /**
1075
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
1076
+ * `Increasing`.
1077
+ *
1078
+ * @since 2.0.0
1079
+ */
1080
+ const isIncreasingX = isIncreasingX$1;
1081
+ /**
1082
+ * Type-narrowing predicate: refines the curve's x-axis trait to include
1083
+ * `Decreasing`.
1084
+ *
1085
+ * @since 2.0.0
1086
+ */
1087
+ const isDecreasingX = isDecreasingX$1;
1088
+ /**
1089
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
1090
+ * `Monotonic`. The x-axis trait is unchanged. y analog of {@link isMonotonicX}.
1091
+ *
1092
+ * @since 2.0.0
1093
+ */
1094
+ const isMonotonicY = isMonotonicY$1;
1095
+ /**
1096
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
1097
+ * `Increasing`.
1098
+ *
1099
+ * @since 2.0.0
1100
+ */
1101
+ const isIncreasingY = isIncreasingY$1;
1102
+ /**
1103
+ * Type-narrowing predicate: refines the curve's y-axis trait to include
1104
+ * `Decreasing`.
1105
+ *
1106
+ * @since 2.0.0
1107
+ */
1108
+ const isDecreasingY = isDecreasingY$1;
1109
+ /**
1110
+ * Type-narrowing predicate: refines both axes' traits to include `Monotonic`
1111
+ * when both `x(t)/w(t)` and `y(t)/w(t)` are strictly monotonic on `[0, 1]`.
1112
+ *
1113
+ * The constant case is excluded — `Monotonic` is the *strict* brand.
1114
+ *
1115
+ * @param c - The rational cubic curve.
1116
+ * @returns `true` when both axes are strictly monotonic on `[0, 1]`.
1117
+ * @since 2.0.0
1118
+ */
1119
+ const isMonotonic = isMonotonic$1;
1120
+ /**
1121
+ * Type-narrowing predicate: refines both axes' traits to include `Increasing`
1122
+ * when both `x(t)/w(t)` and `y(t)/w(t)` are strictly increasing on `[0, 1]`.
1123
+ *
1124
+ * @since 2.0.0
1125
+ */
1126
+ const isIncreasing = isIncreasing$1;
1127
+ /**
1128
+ * Type-narrowing predicate: refines both axes' traits to include `Decreasing`
1129
+ * when both `x(t)/w(t)` and `y(t)/w(t)` are strictly decreasing on `[0, 1]`.
1130
+ *
1131
+ * @since 2.0.0
1132
+ */
1133
+ const isDecreasing = isDecreasing$1;
1134
+ /**
1135
+ * Asserts that the curve is strictly monotonic in x on `[0, 1]`, returning
1136
+ * the same curve with the x-axis trait branded `Monotonic`.
1137
+ *
1138
+ * @param c - The rational cubic curve.
1139
+ * @returns The same curve, refined with the `Monotonic` brand on x.
1140
+ * @throws When the x projection is not strictly monotonic on `[0, 1]`.
1141
+ * @since 2.0.0
1142
+ */
1143
+ const asMonotonicX = asMonotonicX$1;
1144
+ /**
1145
+ * Asserts that the curve is strictly increasing in x on `[0, 1]`.
1146
+ *
1147
+ * @since 2.0.0
1148
+ */
1149
+ const asIncreasingX = asIncreasingX$1;
1150
+ /**
1151
+ * Asserts that the curve is strictly decreasing in x on `[0, 1]`.
1152
+ *
1153
+ * @since 2.0.0
1154
+ */
1155
+ const asDecreasingX = asDecreasingX$1;
1156
+ /**
1157
+ * Asserts that the curve is strictly monotonic in y on `[0, 1]`. y analog of
1158
+ * {@link asMonotonicX}.
1159
+ *
1160
+ * @since 2.0.0
1161
+ */
1162
+ const asMonotonicY = asMonotonicY$1;
1163
+ /**
1164
+ * Asserts that the curve is strictly increasing in y on `[0, 1]`.
1165
+ *
1166
+ * @since 2.0.0
1167
+ */
1168
+ const asIncreasingY = asIncreasingY$1;
1169
+ /**
1170
+ * Asserts that the curve is strictly decreasing in y on `[0, 1]`.
1171
+ *
1172
+ * @since 2.0.0
1173
+ */
1174
+ const asDecreasingY = asDecreasingY$1;
1175
+ /**
1176
+ * Asserts that the curve is strictly monotonic in both axes on `[0, 1]`,
1177
+ * returning the same curve with both axes branded `Monotonic`.
1178
+ *
1179
+ * @param c - The rational cubic curve.
1180
+ * @returns The same curve, refined with the `Monotonic` brand on both axes.
1181
+ * @throws When either axis is not strictly monotonic on `[0, 1]`.
1182
+ * @since 2.0.0
1183
+ */
1184
+ const asMonotonic = asMonotonic$1;
1185
+ /**
1186
+ * Asserts that the curve is strictly increasing in both axes on `[0, 1]`,
1187
+ * returning the same curve with both axes branded `Increasing`.
1188
+ *
1189
+ * @since 2.0.0
1190
+ */
1191
+ const asIncreasing = asIncreasing$1;
1192
+ /**
1193
+ * Asserts that the curve is strictly decreasing in both axes on `[0, 1]`,
1194
+ * returning the same curve with both axes branded `Decreasing`.
1195
+ *
1196
+ * @since 2.0.0
1197
+ */
1198
+ const asDecreasing = asDecreasing$1;
905
1199
  const approximateAsCubicCurves = approximateAsCubicCurves$1;
906
1200
  //#endregion
907
- export { linear2d_exports as C, solveAtY$6 as E, length$4 as S, solveAtX$6 as T, solve$4 as _, boundingBox$2 as a, boundingBox$6 as b, fromPolynomials$2 as c, solveAtX$2 as d, solveAtY$2 as f, quadratic2d_exports as g, length$2 as h, solve as i, length as l, boundingBox$4 as m, fromBezierPoints as n, cubic2d_exports as o, derivative as p, rationalCubic2d_exports as r, fromCoefficients as s, approximateAsCubicCurves as t, solve$2 as u, solveAtX$4 as v, solve$6 as w, fromEndpoints as x, solveAtY$4 as y };
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 };
908
1202
 
909
- //# sourceMappingURL=rationalCubic2d-D5g3_hTV.mjs.map
1203
+ //# sourceMappingURL=rationalCubic2d-CeHgpNht.mjs.map