curvy 2.0.0-alpha.0 → 2.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/characteristic/index.d.mts +3 -3
  2. package/dist/characteristic/index.mjs +1 -1
  3. package/dist/curve/index.d.mts +1 -1
  4. package/dist/curve/index.mjs +1 -1
  5. package/dist/interval/index.d.mts +3 -2
  6. package/dist/interval/index.mjs +3 -2
  7. package/dist/matrix/index.d.mts +1 -1
  8. package/dist/number.mjs.map +1 -1
  9. package/dist/path/index.d.mts +26 -6
  10. package/dist/path/index.mjs +36 -3
  11. package/dist/path/index.mjs.map +1 -1
  12. package/dist/polynomial/index.d.mts +1 -1
  13. package/dist/polynomial/index.mjs +2 -2
  14. package/dist/shared/{characteristic-BGRxcxUH.mjs → characteristic-B9nCh_cx.mjs} +2 -2
  15. package/dist/shared/{characteristic-BGRxcxUH.mjs.map → characteristic-B9nCh_cx.mjs.map} +1 -1
  16. package/dist/shared/{cubic-Dfn6DB02.d.mts → cubic-BajUY0JT.d.mts} +12 -11
  17. package/dist/shared/{cubic-CYYEUHNm.mjs → cubic-CpHAx8cC.mjs} +5 -5
  18. package/dist/shared/cubic-CpHAx8cC.mjs.map +1 -0
  19. package/dist/shared/{interval-CCEqzPgA.mjs → interval-05CR6eBf.mjs} +47 -2
  20. package/dist/shared/interval-05CR6eBf.mjs.map +1 -0
  21. package/dist/shared/{interval-hQDiKqj0.d.mts → interval-Dy-RMEE3.d.mts} +43 -4
  22. package/dist/shared/interval2d-8IBZnUOq.mjs +108 -0
  23. package/dist/shared/interval2d-8IBZnUOq.mjs.map +1 -0
  24. package/dist/shared/interval2d-C2id9u31.d.mts +172 -0
  25. package/dist/shared/{matrix4x4-Bt_DBlP0.d.mts → matrix4x4-Dm_tSiH1.d.mts} +4 -3
  26. package/dist/shared/{quadratic-DEhuAKuE.mjs → quadratic-CamozcFc.mjs} +3 -3
  27. package/dist/shared/quadratic-CamozcFc.mjs.map +1 -0
  28. package/dist/shared/{rationalCubic2d-D_-XWxcm.d.mts → rationalCubic2d-B6g97ryJ.d.mts} +16 -5
  29. package/dist/shared/{rationalCubic2d-CXa7Yren.mjs → rationalCubic2d-BEgUGSFf.mjs} +20 -3
  30. package/dist/shared/rationalCubic2d-BEgUGSFf.mjs.map +1 -0
  31. package/dist/shared/{rationalCubic2d-CP4oGpnk.mjs → rationalCubic2d-Bys2Uory.mjs} +44 -7
  32. package/dist/shared/rationalCubic2d-Bys2Uory.mjs.map +1 -0
  33. package/dist/shared/{rationalCubic2d-BPLohNuI.d.mts → rationalCubic2d-DlQfBURs.d.mts} +40 -9
  34. package/dist/shared/{solution-CbSWzXCn.mjs → solution-CrtLfqEq.mjs} +2 -2
  35. package/dist/shared/{solution-CbSWzXCn.mjs.map → solution-CrtLfqEq.mjs.map} +1 -1
  36. package/dist/shared/{solution-BjoW7ov4.d.mts → solution-sNQ-ZVhN.d.mts} +3 -3
  37. package/dist/shared/{utils-DqTGyXrP.d.mts → utils-MCckigYk.d.mts} +1 -1
  38. package/dist/shared/vector2-DPUY3_eA.d.mts +470 -0
  39. package/dist/shared/{vector2-TV0UnlxY.d.mts → vector3-DqeOZtOB.d.mts} +43 -508
  40. package/dist/solution/index.d.mts +1 -1
  41. package/dist/solution/index.mjs +1 -1
  42. package/dist/splines/index.d.mts +4 -4
  43. package/dist/splines/index.mjs +4 -4
  44. package/dist/utils.d.mts +1 -1
  45. package/dist/vector/index.d.mts +2 -1
  46. package/package.json +1 -1
  47. package/dist/shared/cubic-CYYEUHNm.mjs.map +0 -1
  48. package/dist/shared/interval-CCEqzPgA.mjs.map +0 -1
  49. package/dist/shared/quadratic-DEhuAKuE.mjs.map +0 -1
  50. package/dist/shared/rationalCubic2d-CP4oGpnk.mjs.map +0 -1
  51. package/dist/shared/rationalCubic2d-CXa7Yren.mjs.map +0 -1
@@ -0,0 +1,172 @@
1
+ import { t as Vector2 } from "./vector2-DPUY3_eA.mjs";
2
+ import { t as Pipeable } from "./utils-MCckigYk.mjs";
3
+ import { n as Closed, r as Interval, t as Bounds } from "./interval-Dy-RMEE3.mjs";
4
+
5
+ //#region src/interval/interval2d.internal.d.ts
6
+ declare const Interval2dTypeId: unique symbol;
7
+ type Interval2dTypeId = typeof Interval2dTypeId;
8
+ declare namespace interval2d_d_exports {
9
+ export { Bounds2d, Interval2d, containsInterval2d, containsVector, equals, fromCorners, fromVectors, isInterval2d, make, size, union };
10
+ }
11
+ /**
12
+ * An axis-aligned 2D interval — the Cartesian product of two 1D intervals.
13
+ * Used as a bounding box for curves and paths, and as a region for
14
+ * containment tests.
15
+ *
16
+ * The two type parameters carry the per-axis interval subtype so that a value
17
+ * built from closed intervals stays `Interval2d<Closed, Closed>` and a value
18
+ * with mixed openness preserves that information at the type level.
19
+ *
20
+ * All fields are readonly and immutable, and all operations create new instances.
21
+ *
22
+ * @since 2.1.0
23
+ */
24
+ interface Interval2d<X extends Interval = Interval, Y extends Interval = Interval> extends Pipeable {
25
+ readonly [Interval2dTypeId]: Interval2dTypeId;
26
+ readonly x: X;
27
+ readonly y: Y;
28
+ }
29
+ /**
30
+ * The structural minimum: any value with `x` and `y` fields shaped like
31
+ * {@link Bounds}. Operations that don't read endpoint inclusivity (e.g.
32
+ * {@link size}) accept `Bounds2d` so the signature itself documents what the
33
+ * operation depends on. Mirrors the {@link Bounds}/{@link Interval} split in 1D.
34
+ *
35
+ * @since 2.1.0
36
+ */
37
+ interface Bounds2d {
38
+ readonly x: Bounds;
39
+ readonly y: Bounds;
40
+ }
41
+ /**
42
+ * Checks if a value is an `Interval2d`.
43
+ *
44
+ * @param v - The value to check.
45
+ * @returns `true` if the value is an `Interval2d`, `false` otherwise.
46
+ * @since 2.1.0
47
+ */
48
+ declare const isInterval2d: (v: unknown) => v is Interval2d;
49
+ /**
50
+ * Creates a new `Interval2d` from two intervals — one for the x axis, one
51
+ * for the y axis. Preserves both interval subtypes at the type level.
52
+ *
53
+ * @param x - The x-axis interval.
54
+ * @param y - The y-axis interval.
55
+ * @returns A new `Interval2d` instance.
56
+ * @since 2.1.0
57
+ */
58
+ declare const make: <X extends Interval, Y extends Interval>(x: X, y: Y) => Interval2d<X, Y>;
59
+ /**
60
+ * Creates a closed `Interval2d` from two corner points. The corners can be in
61
+ * any order — each axis is built from the min and max of the coordinate.
62
+ *
63
+ * @param p0 - The first corner.
64
+ * @param p1 - The second corner.
65
+ * @returns A new `Interval2d<Closed, Closed>` enclosing both corners.
66
+ * @since 2.1.0
67
+ */
68
+ declare const fromCorners: (p0: Vector2, p1: Vector2) => Interval2d<Closed, Closed>;
69
+ /**
70
+ * Creates the smallest closed `Interval2d` enclosing the given points. Useful
71
+ * for computing a bounding box from sampled points.
72
+ *
73
+ * @param points - One or more points to enclose.
74
+ * @returns A new `Interval2d<Closed, Closed>` enclosing all input points.
75
+ * @throws When called with zero points.
76
+ * @since 2.1.0
77
+ */
78
+ declare const fromVectors: (...points: ReadonlyArray<Vector2>) => Interval2d<Closed, Closed>;
79
+ declare const containsVector: {
80
+ /**
81
+ * Checks if a vector lies within the 2D interval. Per-axis endpoint
82
+ * inclusivity follows each axis interval's `kind`.
83
+ *
84
+ * @param box - The 2D interval to test against.
85
+ * @param v - The vector to test.
86
+ * @returns `true` when the vector lies within the box on both axes.
87
+ * @since 2.1.0
88
+ */
89
+ (box: Interval2d, v: Vector2): boolean;
90
+ /**
91
+ * @param v - The vector to test.
92
+ * @returns A function that takes a 2D interval and returns the containment result.
93
+ * @since 2.1.0
94
+ */
95
+ (v: Vector2): (box: Interval2d) => boolean;
96
+ };
97
+ declare const containsInterval2d: {
98
+ /**
99
+ * Checks if `inner` is a subset of `outer`. The check is per-axis interval
100
+ * containment — for each axis, every point of the inner interval must also
101
+ * be in the outer interval, respecting endpoint inclusivity on both sides.
102
+ *
103
+ * @param outer - The enclosing 2D interval.
104
+ * @param inner - The candidate inner 2D interval.
105
+ * @returns `true` when every point of `inner` is also in `outer`.
106
+ * @since 2.1.0
107
+ */
108
+ (outer: Interval2d, inner: Interval2d): boolean;
109
+ /**
110
+ * @param inner - The candidate inner 2D interval.
111
+ * @returns A function that takes the outer 2D interval and returns the containment result.
112
+ * @since 2.1.0
113
+ */
114
+ (inner: Interval2d): (outer: Interval2d) => boolean;
115
+ };
116
+ /**
117
+ * Returns the size as a vector `(width, height)`. Accepts the broader
118
+ * {@link Bounds2d} type because size does not depend on endpoint inclusivity.
119
+ *
120
+ * @param box - The 2D interval (or bounds-shaped value) to measure.
121
+ * @returns The size as a `Vector2`.
122
+ * @since 2.1.0
123
+ */
124
+ declare const size: (box: Bounds2d) => Vector2;
125
+ declare const union: {
126
+ /**
127
+ * Returns the smallest 2D interval enclosing both inputs.
128
+ *
129
+ * The per-axis return kind is determined by which input's endpoint wins on
130
+ * each side, with the contributor's openness preserved (or unioned to
131
+ * "closed" when endpoints are numerically equal and either is closed at
132
+ * that point).
133
+ *
134
+ * When both inputs share the same kind on an axis, the result collapses
135
+ * back to that kind. Otherwise the axis falls back to the open
136
+ * {@link Interval} type since the runtime kind depends on the values.
137
+ *
138
+ * @param a - The first 2D interval.
139
+ * @param b - The second 2D interval.
140
+ * @returns A new `Interval2d` enclosing both inputs.
141
+ * @since 2.1.0
142
+ */
143
+ <AX extends Interval, AY extends Interval, BX extends Interval, BY extends Interval>(a: Interval2d<AX, AY>, b: Interval2d<BX, BY>): Interval2d<AX extends BX ? (BX extends AX ? AX : Interval) : Interval, AY extends BY ? (BY extends AY ? AY : Interval) : Interval>;
144
+ /**
145
+ * @param b - The second 2D interval.
146
+ * @returns A function that takes the first 2D interval and returns the union.
147
+ * @since 2.1.0
148
+ */
149
+ <BX extends Interval, BY extends Interval>(b: Interval2d<BX, BY>): <AX extends Interval, AY extends Interval>(a: Interval2d<AX, AY>) => Interval2d<AX extends BX ? (BX extends AX ? AX : Interval) : Interval, AY extends BY ? (BY extends AY ? AY : Interval) : Interval>;
150
+ };
151
+ declare const equals: {
152
+ /**
153
+ * Checks if two `Interval2d` values are approximately equal within the
154
+ * default absolute tolerance ({@link EPSILON}). Both the numeric endpoints
155
+ * AND the per-axis kinds must match.
156
+ *
157
+ * @param a - The first 2D interval.
158
+ * @param b - The second 2D interval.
159
+ * @returns `true` when both axes are equal.
160
+ * @since 2.1.0
161
+ */
162
+ (a: Interval2d, b: Interval2d): boolean;
163
+ /**
164
+ * @param b - The second 2D interval.
165
+ * @returns A function that takes the first 2D interval and returns the comparison result.
166
+ * @since 2.1.0
167
+ */
168
+ (b: Interval2d): (a: Interval2d) => boolean;
169
+ };
170
+ //#endregion
171
+ export { interval2d_d_exports as n, Interval2d as t };
172
+ //# sourceMappingURL=interval2d-C2id9u31.d.mts.map
@@ -1,5 +1,6 @@
1
- import { c as FourDimensionalComponent, d as ThreeDimensionalIndex, i as Vector3, l as FourDimensionalIndex, m as TwoDimensionalIndex, o as Vector4, p as TwoDimensionalComponent, t as Vector2, u as ThreeDimensionalComponent } from "./vector2-TV0UnlxY.mjs";
2
- import { t as Pipeable } from "./utils-DqTGyXrP.mjs";
1
+ import { a as FourDimensionalComponent, c as ThreeDimensionalComponent, d as TwoDimensionalComponent, f as TwoDimensionalIndex, l as ThreeDimensionalIndex, o as FourDimensionalIndex, t as Vector2 } from "./vector2-DPUY3_eA.mjs";
2
+ import { t as Pipeable } from "./utils-MCckigYk.mjs";
3
+ import { r as Vector4, t as Vector3 } from "./vector3-DqeOZtOB.mjs";
3
4
 
4
5
  //#region src/matrix/matrix2x2.internal.d.ts
5
6
  declare const Matrix2x2TypeId: unique symbol;
@@ -1179,4 +1180,4 @@ declare const reverseRows: (m: Matrix4x4) => Matrix4x4;
1179
1180
  declare const reverseColumns: (m: Matrix4x4) => Matrix4x4;
1180
1181
  //#endregion
1181
1182
  export { matrix2x2_d_exports as i, matrix4x4_d_exports as n, matrix3x3_d_exports as r, Matrix4x4 as t };
1182
- //# sourceMappingURL=matrix4x4-Bt_DBlP0.d.mts.map
1183
+ //# sourceMappingURL=matrix4x4-Dm_tSiH1.d.mts.map
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./chunk-25Hzd3z8.mjs";
2
- import { $ as fromPoints$3, At as monotonicity$2, Ct as fromVector$2, Dt as isMonotonic$2, Et as isLinearPolynomial$1, Ft as toSolver$2, G as asDecreasing$3, J as curvature$1, K as asIncreasing$3, Mt as solve$2, Nt as solveInverse$2, Ot as length$2, Pt as toInverseSolver$2, Q as extreme$1, St as fromPoints$2, Tt as isIncreasing$2, W as antiderivative$3, X as domain$3, Y as derivative$3, Z as equals$3, _t as asMonotonic$2, at as length$3, bt as equals$2, ct as range$3, dt as solveInverse$3, et as fromVector$3, ft as toInverseSolver$3, gt as asIncreasing$2, ht as asDecreasing$2, it as isQuadraticPolynomial$1, jt as range$2, kt as make$2, lt as roots$1, mt as antiderivative$2, nt as isIncreasing$3, ot as make$3, pt as toSolver$3, q as asMonotonic$3, rt as isMonotonic$3, st as monotonicity$3, tt as isDecreasing$3, ut as solve$3, vt as derivative$2, wt as isDecreasing$2, xt as fromPointSlope$1, yt as domain$2 } from "./cubic-CYYEUHNm.mjs";
2
+ import { $ as extreme$1, At as make$2, Ct as fromPoints$2, Dt as isLinearPolynomial$1, Et as isIncreasing$2, Ft as toInverseSolver$2, G as antiderivative$3, It as toSolver$2, J as asMonotonic$3, K as asDecreasing$3, Mt as range$2, Nt as solve$2, Ot as isMonotonic$2, Pt as solveInverse$2, Q as equals$3, St as fromPointSlope$1, Tt as isDecreasing$2, X as derivative$3, Y as curvature$1, Z as domain$3, _t as asIncreasing$2, at as isQuadraticPolynomial$1, bt as domain$2, ct as monotonicity$3, dt as solve$3, et as fromPoints$3, ft as solveInverse$3, gt as asDecreasing$2, ht as antiderivative$2, it as isMonotonic$3, jt as monotonicity$2, kt as length$2, lt as range$3, mt as toSolver$3, nt as isDecreasing$3, ot as length$3, pt as toInverseSolver$3, q as asIncreasing$3, rt as isIncreasing$3, st as make$3, tt as fromVector$3, ut as roots$1, vt as asMonotonic$2, wt as fromVector$2, xt as equals$2, yt as derivative$2 } from "./cubic-CpHAx8cC.mjs";
3
3
  //#region src/polynomial/linear.ts
4
4
  var linear_exports = /* @__PURE__ */ __exportAll({
5
5
  antiderivative: () => antiderivative$1,
@@ -325,6 +325,6 @@ const range = range$3;
325
325
  const length = length$3;
326
326
  const curvature = curvature$1;
327
327
  //#endregion
328
- export { make as a, solveInverse as c, isMonotonic$1 as d, linear_exports as f, solveInverse$1 as h, isMonotonic as i, isDecreasing$1 as l, solve$1 as m, isDecreasing as n, quadratic_exports as o, make$1 as p, isIncreasing as r, solve as s, derivative as t, isIncreasing$1 as u };
328
+ export { solveInverse$1 as _, make as a, solve as c, isIncreasing$1 as d, isMonotonic$1 as f, solve$1 as g, range$1 as h, isMonotonic as i, solveInverse as l, make$1 as m, isDecreasing as n, quadratic_exports as o, linear_exports as p, isIncreasing as r, range as s, derivative as t, isDecreasing$1 as u };
329
329
 
330
- //# sourceMappingURL=quadratic-DEhuAKuE.mjs.map
330
+ //# sourceMappingURL=quadratic-CamozcFc.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quadratic-CamozcFc.mjs","names":["internal.isLinearPolynomial","equals","internal.equals","make","internal.make","fromVector","internal.fromVector","internal.fromPointSlope","fromPoints","internal.fromPoints","solve","internal.solve","toSolver","internal.toSolver","solveInverse","internal.solveInverse","toInverseSolver","internal.toInverseSolver","monotonicity","internal.monotonicity","isMonotonic","internal.isMonotonic","isIncreasing","internal.isIncreasing","isDecreasing","internal.isDecreasing","asMonotonic","internal.asMonotonic","asIncreasing","internal.asIncreasing","asDecreasing","internal.asDecreasing","derivative","internal.derivative","antiderivative","internal.antiderivative","domain","internal.domain","range","internal.range","length","internal.length","internal.isQuadraticPolynomial","internal.equals","internal.make","internal.fromVector","internal.fromPoints","internal.solve","internal.toSolver","internal.solveInverse","internal.toInverseSolver","internal.derivative","internal.roots","internal.extreme","internal.monotonicity","internal.isMonotonic","internal.isIncreasing","internal.isDecreasing","internal.asMonotonic","internal.asIncreasing","internal.asDecreasing","internal.antiderivative","internal.domain","internal.range","internal.length","internal.curvature"],"sources":["../../src/polynomial/linear.ts","../../src/polynomial/quadratic.ts"],"sourcesContent":["import type { Closed, Interval } from '../interval/interval'\nimport type { Pipeable } from '../utils'\nimport type * as Solution from '../solution/solution'\nimport type { Vector2 } from '../vector/vector2'\nimport type { LinearPolynomialTypeId } from './linear.internal'\nimport * as internal from './linear.internal'\nimport type { GuaranteedMonotonicity } from './monotonicity'\nimport type { QuadraticPolynomial } from './quadratic'\nimport type { Decreasing, Increasing, Monotonic, PolynomialTraits } from './traits'\n\nexport type { Monotonic, Increasing, Decreasing } from './traits'\n\n/**\n * A linear polynomial.\n *\n * All fields are readonly and immutable, and all operations create new instances.\n *\n * The `Traits` type parameter is a phantom marker that accumulates trait\n * brands as the polynomial is refined via `isMonotonic` / `asMonotonic` and\n * friends. The runtime value carries no trait data — `Traits` only flows\n * through the type system to enable tighter return types on operations like\n * `solveInverse`.\n *\n * @since 1.0.0\n */\nexport interface LinearPolynomial<out Traits = unknown> extends Pipeable {\n readonly [LinearPolynomialTypeId]: LinearPolynomialTypeId\n readonly [PolynomialTraits]: Traits\n\n /**\n * The coefficient of the x^0 term.\n */\n readonly c0: number\n\n /**\n * The coefficient of the x^1 term.\n */\n readonly c1: number\n}\n\n/**\n * Checks if a value is a `LinearPolynomial`.\n *\n * @param v - The value to check.\n * @returns `true` if the value is a `LinearPolynomial`, `false` otherwise.\n * @since 1.0.0\n */\nexport const isLinearPolynomial: (v: unknown) => v is LinearPolynomial = internal.isLinearPolynomial\n\nexport const equals: {\n /**\n * Checks if two `LinearPolynomial` instances are approximately equal within\n * the default absolute tolerance ({@link EPSILON}).\n *\n * @param a - The first polynomial.\n * @param b - The second polynomial.\n * @returns `true` when each pair of coefficients is within tolerance.\n * @since 1.1.0\n */\n (a: LinearPolynomial, b: LinearPolynomial): boolean\n /**\n * Checks if two `LinearPolynomial` instances are approximately equal within\n * the default absolute tolerance ({@link EPSILON}).\n *\n * @param b - The second polynomial.\n * @returns A function that takes the first polynomial and returns the comparison result.\n * @since 1.1.0\n */\n (b: LinearPolynomial): (a: LinearPolynomial) => boolean\n} = internal.equals\n\n/**\n * Creates a new `LinearPolynomial` instance.\n *\n * @param c0 - The coefficient of the x^0 term. Defaults to 0.\n * @param c1 - The coefficient of the x^1 term. Defaults to 0.\n * @returns A new `LinearPolynomial` instance.\n * @since 1.0.0\n */\nexport const make: (c0?: number, c1?: number) => LinearPolynomial = internal.make\n\n/**\n * Creates a new `LinearPolynomial` instance from a vector.\n *\n * @param v - The vector to create the polynomial from.\n * @returns A new `LinearPolynomial` instance.\n * @since 1.0.0\n */\nexport const fromVector: (v: Vector2) => LinearPolynomial = internal.fromVector\n\n/**\n * Creates a new `LinearPolynomial` instance from a point and slope.\n *\n * @param p - The point on the line.\n * @param slope - The slope of the line.\n * @returns A new `LinearPolynomial` instance.\n * @since 1.0.0\n */\nexport const fromPointSlope: (p: Vector2, slope: number) => LinearPolynomial =\n internal.fromPointSlope\n\n/**\n * Creates a new `LinearPolynomial` instance from two points.\n *\n * @param p1 - The first point.\n * @param p2 - The second point.\n * @returns A new `LinearPolynomial` instance.\n * @since 1.0.0\n */\nexport const fromPoints: (p1: Vector2, p2: Vector2) => LinearPolynomial = internal.fromPoints\n\nexport const solve: {\n /**\n * Solves a linear polynomial for a given value of x.\n *\n * @param p - The linear polynomial to solve.\n * @param x - The value of x to solve for.\n * @returns The result of the polynomial evaluated at x.\n * @since 1.0.0\n */\n (p: LinearPolynomial, x: number): number\n /**\n * Solves a linear polynomial for a given value of x.\n *\n * @param x - The value of x to solve for.\n * @returns A function that takes a `LinearPolynomial` and returns the result of the polynomial evaluated at x.\n * @since 1.0.0\n */\n (x: number): (p: LinearPolynomial) => number\n} = internal.solve\n\n/**\n * Converts a linear polynomial to a solver function.\n *\n * @param p - The linear polynomial to convert.\n * @returns A function that takes a value of x and returns the result of the polynomial evaluated at x.\n * @since 1.0.0\n */\nexport const toSolver: (p: LinearPolynomial) => (x: number) => number = internal.toSolver\n\n// The implementation always runs the same `c1 === 0 ? Solution.none : ...`\n// branch. For `Monotonic`-branded polynomials the empty branch is provably\n// unreachable, but TS can't see that — the cast pairs the type-level promise\n// with the runtime brand check.\nexport const solveInverse: {\n /**\n * Solves a monotonic linear polynomial for a given value of y. Because the\n * polynomial is strictly monotonic, the inverse always has exactly one\n * solution — wrapped in `Solution.One`.\n *\n * @param p - The monotonic linear polynomial to solve.\n * @param y - The value of y to solve for.\n * @since 2.0.0\n */\n <T extends Monotonic>(p: LinearPolynomial<T>, y: number): Solution.One<number>\n /**\n * Solves a linear polynomial for a given value of y. Returns `Solution.none`\n * for constant polynomials (no inverse).\n *\n * @param p - The linear polynomial to solve.\n * @param y - The value of y to solve for.\n * @since 1.0.0\n */\n <T>(p: LinearPolynomial<T>, y: number): Solution.AtMostOne<number>\n /** @since 1.0.0 */\n (y: number): {\n <T extends Monotonic>(p: LinearPolynomial<T>): Solution.One<number>\n <T>(p: LinearPolynomial<T>): Solution.AtMostOne<number>\n }\n} = internal.solveInverse as never\n\n/**\n * Converts a linear polynomial to an inverse solver function.\n *\n * @param p - The linear polynomial to convert.\n * @since 1.0.0\n */\nexport const toInverseSolver: (p: LinearPolynomial) => (y: number) => Solution.AtMostOne<number> =\n internal.toInverseSolver\n\n/**\n * Finds the roots of a linear polynomial.\n *\n * @param p - The linear polynomial to find the roots of.\n * @since 1.0.0\n */\nexport const root: (p: LinearPolynomial) => Solution.AtMostOne<number> = (p) =>\n internal.solveInverse(p, 0)\n\n/**\n * Calculates the monotonicity of a linear polynomial.\n *\n * @param p - The linear polynomial to check.\n * @returns The guaranteed monotonicity of the polynomial.\n * @since 1.0.0\n */\nexport const monotonicity: (p: LinearPolynomial) => GuaranteedMonotonicity = internal.monotonicity\n\n/**\n * Type-narrowing predicate: refines a `LinearPolynomial<T>` to\n * `LinearPolynomial<T & Monotonic>` when the polynomial is strictly monotonic.\n *\n * @param p - The linear polynomial to check.\n * @returns `true` when `monotonicity(p)` is `'increasing'` or `'decreasing'`.\n * @since 2.0.0\n */\nexport const isMonotonic: <T>(p: LinearPolynomial<T>) => p is LinearPolynomial<T & Monotonic> =\n internal.isMonotonic\n\n/**\n * Type-narrowing predicate: refines to `LinearPolynomial<T & Increasing>`.\n *\n * @param p - The linear polynomial to check.\n * @returns `true` when `monotonicity(p)` is `'increasing'`.\n * @since 2.0.0\n */\nexport const isIncreasing: <T>(p: LinearPolynomial<T>) => p is LinearPolynomial<T & Increasing> =\n internal.isIncreasing\n\n/**\n * Type-narrowing predicate: refines to `LinearPolynomial<T & Decreasing>`.\n *\n * @param p - The linear polynomial to check.\n * @returns `true` when `monotonicity(p)` is `'decreasing'`.\n * @since 2.0.0\n */\nexport const isDecreasing: <T>(p: LinearPolynomial<T>) => p is LinearPolynomial<T & Decreasing> =\n internal.isDecreasing\n\n/**\n * Asserts that the linear polynomial is monotonic, throwing on failure.\n *\n * @param p - The linear polynomial to assert against.\n * @returns The same polynomial, typed with the `Monotonic` brand.\n * @throws When `monotonicity(p)` is `'constant'`.\n * @since 2.0.0\n */\nexport const asMonotonic: <T>(p: LinearPolynomial<T>) => LinearPolynomial<T & Monotonic> =\n internal.asMonotonic\n\n/**\n * Asserts that the linear polynomial is increasing, throwing on failure.\n *\n * @param p - The linear polynomial to assert against.\n * @returns The same polynomial, typed with the `Increasing` brand.\n * @throws When `monotonicity(p)` is not `'increasing'`.\n * @since 2.0.0\n */\nexport const asIncreasing: <T>(p: LinearPolynomial<T>) => LinearPolynomial<T & Increasing> =\n internal.asIncreasing\n\n/**\n * Asserts that the linear polynomial is decreasing, throwing on failure.\n *\n * @param p - The linear polynomial to assert against.\n * @returns The same polynomial, typed with the `Decreasing` brand.\n * @throws When `monotonicity(p)` is not `'decreasing'`.\n * @since 2.0.0\n */\nexport const asDecreasing: <T>(p: LinearPolynomial<T>) => LinearPolynomial<T & Decreasing> =\n internal.asDecreasing\n\n/**\n * Calculates the derivative of a linear polynomial.\n *\n * @param p - The linear polynomial to differentiate.\n * @returns The derivative of the linear polynomial.\n * @since 1.0.0\n */\nexport const derivative: (p: LinearPolynomial) => number = internal.derivative\n\nexport const antiderivative: {\n /**\n * Calculates the antiderivative of a linear polynomial.\n *\n * @param p - The linear polynomial to integrate.\n * @param constant - The constant of integration. Defaults to 0.\n * @returns The antiderivative of the linear polynomial.\n * @since 1.0.0\n */\n (p: LinearPolynomial, constant?: number): QuadraticPolynomial\n /**\n * Calculates the antiderivative of a linear polynomial.\n *\n * @param constant - The constant of integration. Defaults to 0.\n * @returns A function that takes a `LinearPolynomial` and returns the antiderivative of the polynomial.\n * @since 1.0.0\n */\n (constant: number): (p: LinearPolynomial) => QuadraticPolynomial\n} = internal.antiderivative\n\nexport const domain: {\n /**\n * Calculates the domain of a linear polynomial.\n *\n * @param p - The linear polynomial to check.\n * @param range - The range to check against.\n * @returns The domain of the polynomial within the given range.\n * @since 1.0.0\n */\n (p: LinearPolynomial, range: Interval): Solution.AtMostOne<Interval>\n /**\n * Calculates the domain of a linear polynomial.\n *\n * @param range - The range to check against.\n * @returns A function that takes a `LinearPolynomial` and returns the domain of the polynomial within the given range.\n * @since 1.0.0\n */\n (range: Interval): (p: LinearPolynomial) => Solution.AtMostOne<Interval>\n} = internal.domain\n\nexport const range: {\n /**\n * Calculates the range of a linear polynomial.\n *\n * @param p - The linear polynomial to check.\n * @param domain - The domain to check against.\n * @returns The range of the polynomial within the given domain.\n * @since 1.0.0\n */\n (p: LinearPolynomial, domain: Interval): Closed\n /**\n * Calculates the range of a linear polynomial.\n *\n * @param domain - The domain to check against.\n * @returns A function that takes a `LinearPolynomial` and returns the range of the polynomial within the given domain.\n * @since 1.0.0\n */\n (domain: Interval): (p: LinearPolynomial) => Closed\n} = internal.range\n\nexport const length: {\n /**\n * Calculates the length of a linear polynomial within a particular domain `Interval`.\n *\n * @param p - The linear polynomial to analyze.\n * @param domain - The domain to restrict the analysis to.\n * @returns The length of the linear polynomial in the specified domain.\n * @since 1.0.0\n */\n (p: LinearPolynomial, domain: Interval): number\n /**\n * Calculates the length of a linear polynomial within a particular domain `Interval`.\n *\n * @param domain - The domain to restrict the analysis to.\n * @returns A function that takes a `LinearPolynomial` and returns the length of the polynomial in the specified domain.\n * @since 1.0.0\n */\n (domain: Interval): (p: LinearPolynomial) => number\n} = internal.length\n","import type { Closed, Interval } from '../interval/interval'\nimport type { Pipeable } from '../utils'\nimport type * as Solution from '../solution/solution'\nimport type { Vector2 } from '../vector/vector2'\nimport type { Vector3 } from '../vector/vector3'\nimport type { CubicPolynomial } from './cubic'\nimport type { LinearPolynomial } from './linear'\nimport type { Monotonicity } from './monotonicity'\nimport * as internal from './quadratic.internal'\nimport type { QuadraticPolynomialTypeId } from './quadratic.internal.circular'\nimport type { Decreasing, Increasing, Monotonic, PolynomialTraits } from './traits'\n\nexport type { Monotonic, Increasing, Decreasing } from './traits'\n\n/**\n * A quadratic polynomial.\n *\n * All fields are readonly and immutable, and all operations create new instances.\n *\n * The `Traits` type parameter is a phantom marker that accumulates trait\n * brands as the polynomial is refined via `isMonotonic` / `asMonotonic` and\n * friends. Refinements may be parameterized by an `Interval` — a quadratic is\n * monotonic on an interval that avoids its extremum, even though it is not\n * monotonic globally.\n *\n * @since 1.0.0\n */\nexport interface QuadraticPolynomial<out Traits = unknown> extends Pipeable {\n readonly [QuadraticPolynomialTypeId]: QuadraticPolynomialTypeId\n readonly [PolynomialTraits]: Traits\n\n /**\n * The coefficient of the x^0 term.\n */\n readonly c0: number\n /**\n * The coefficient of the x^1 term.\n */\n readonly c1: number\n /**\n * The coefficient of the x^2 term.\n */\n readonly c2: number\n}\n\n/**\n * Checks if a value is a `QuadraticPolynomial`.\n *\n * @param v - The value to check.\n * @returns `true` if the value is a `QuadraticPolynomial`, `false` otherwise.\n * @since 1.0.0\n */\nexport const isQuadraticPolynomial: (v: unknown) => v is QuadraticPolynomial =\n internal.isQuadraticPolynomial\n\nexport const equals: {\n /**\n * Checks if two `QuadraticPolynomial` instances are approximately equal\n * within the default absolute tolerance ({@link EPSILON}).\n *\n * @param a - The first polynomial.\n * @param b - The second polynomial.\n * @returns `true` when each pair of coefficients is within tolerance.\n * @since 1.1.0\n */\n (a: QuadraticPolynomial, b: QuadraticPolynomial): boolean\n /**\n * Checks if two `QuadraticPolynomial` instances are approximately equal\n * within the default absolute tolerance ({@link EPSILON}).\n *\n * @param b - The second polynomial.\n * @returns A function that takes the first polynomial and returns the comparison result.\n * @since 1.1.0\n */\n (b: QuadraticPolynomial): (a: QuadraticPolynomial) => boolean\n} = internal.equals\n\n/**\n * Creates a new `QuadraticPolynomial` instance.\n *\n * @param c0 - The coefficient of the x^0 term. Defaults to 0.\n * @param c1 - The coefficient of the x^1 term. Defaults to 0.\n * @param c2 - The coefficient of the x^2 term. Defaults to 1.\n * @returns A new `QuadraticPolynomial` instance.\n * @since 1.0.0\n */\nexport const make: (c0?: number, c1?: number, c2?: number) => QuadraticPolynomial = internal.make\n\n/**\n * Creates a new `QuadraticPolynomial` instance from a vector.\n *\n * @param v - The vector to create the polynomial from.\n * @returns A new `QuadraticPolynomial` instance.\n * @since 1.0.0\n */\nexport const fromVector: (v: Vector3) => QuadraticPolynomial = internal.fromVector\n\n/**\n * Creates a new `QuadraticPolynomial` that interpolates the three given\n * points, treating each `Vector2` as an `(x, y)` pair. The three input `x`\n * values must be distinct.\n *\n * @param p0 - The first point.\n * @param p1 - The second point.\n * @param p2 - The third point.\n * @returns The unique quadratic polynomial passing through the three points.\n * @since 2.0.0\n */\nexport const fromPoints: (p0: Vector2, p1: Vector2, p2: Vector2) => QuadraticPolynomial =\n internal.fromPoints\n\nexport const solve: {\n /**\n * Solves the quadratic polynomial for a given x value.\n *\n * @param p - The quadratic polynomial.\n * @param x - The x value to solve for.\n * @returns The result of the polynomial at the given x value.\n * @since 1.0.0\n */\n (p: QuadraticPolynomial, x: number): number\n /**\n * Solves the quadratic polynomial for a given x value.\n *\n * @param x - The x value to solve for.\n * @returns A function that takes a quadratic polynomial and returns the result of the polynomial at the given x value.\n * @since 1.0.0\n */\n (x: number): (p: QuadraticPolynomial) => number\n} = internal.solve\n\n/**\n * Creates a solver function for the quadratic polynomial.\n *\n * @param p - The quadratic polynomial.\n * @returns A function that takes an x value and returns the result of the polynomial at that x value.\n */\nexport const toSolver: (p: QuadraticPolynomial) => (x: number) => number = internal.toSolver\n\nexport const solveInverse: {\n /**\n * Solves a monotonic quadratic polynomial for a given y value. Because the\n * polynomial is strictly monotonic (either globally, or over the interval\n * the `Monotonic` brand was attached for), the inverse has at most one\n * solution.\n *\n * @param p - The monotonic quadratic polynomial.\n * @param y - The y value to solve for.\n * @returns Zero or one solutions.\n * @since 2.0.0\n */\n <T extends Monotonic>(p: QuadraticPolynomial<T>, y: number): Solution.AtMostOne<number>\n /**\n * Solves the quadratic polynomial for a given y value.\n *\n * @param p - The quadratic polynomial.\n * @param y - The y value to solve for.\n * @returns The solutions to the polynomial at the given y value.\n * @since 1.0.0\n */\n <T>(p: QuadraticPolynomial<T>, y: number): Solution.AtMostTwo<number>\n /**\n * Solves the quadratic polynomial for a given y value.\n *\n * @param y - The y value to solve for.\n * @returns A function that takes a quadratic polynomial and returns the\n * solutions. Tightens to `Solution.AtMostOne<number>` for monotonic inputs.\n * @since 1.0.0\n */\n (y: number): {\n <T extends Monotonic>(p: QuadraticPolynomial<T>): Solution.AtMostOne<number>\n <T>(p: QuadraticPolynomial<T>): Solution.AtMostTwo<number>\n }\n} = internal.solveInverse as never\n\n/**\n * Creates an inverse solver function for the quadratic polynomial.\n *\n * @param p - The quadratic polynomial.\n * @returns A function that takes a y value and returns the solutions to the polynomial at that y value.\n */\nexport const toInverseSolver: (\n p: QuadraticPolynomial,\n) => (y: number) => Solution.AtMostTwo<number> = internal.toInverseSolver\n\n/**\n * Computes the derivative of the quadratic polynomial.\n *\n * @param p - The quadratic polynomial.\n * @returns The derivative of the polynomial as a linear polynomial.\n * @since 1.0.0\n */\nexport const derivative: (p: QuadraticPolynomial) => LinearPolynomial = internal.derivative\n\n/**\n * Finds the roots of the quadratic polynomial.\n *\n * @param p - The quadratic polynomial.\n * @returns The roots of the polynomial as a tuple of solutions.\n * @since 1.0.0\n */\nexport const roots: (p: QuadraticPolynomial) => Solution.AtMostTwo<number> = internal.roots\n\n/**\n * Finds the extreme point of the quadratic polynomial.\n *\n * @param p - The quadratic polynomial.\n * @returns The extreme point of the polynomial as a solution.\n * @since 1.0.0\n */\nexport const extreme: (p: QuadraticPolynomial) => Vector2 | null = internal.extreme\n\nexport const monotonicity: {\n /**\n * Computes the monotonicity of the quadratic polynomial over a given\n * interval. Throws when the interval has zero width — the question is\n * undefined at a single point.\n *\n * @param p - The quadratic polynomial.\n * @param i - The interval to compute the monotonicity over.\n * @returns The monotonicity of the polynomial over the interval.\n * @since 1.0.0\n */\n (p: QuadraticPolynomial, i?: Interval): Monotonicity\n /**\n * Computes the monotonicity of the quadratic polynomial over a given\n * interval. Throws when the interval has zero width.\n *\n * @param i - The interval to compute the monotonicity over.\n * @returns A function that takes a quadratic polynomial and returns the\n * monotonicity of the polynomial over the interval.\n * @since 1.0.0\n */\n (i: Interval): (p: QuadraticPolynomial) => Monotonicity\n} = internal.monotonicity\n\n/**\n * Type-narrowing predicate: refines a `QuadraticPolynomial<T>` to\n * `QuadraticPolynomial<T & Monotonic>` when the polynomial is strictly\n * monotonic over the given interval (or globally, when no interval is given).\n *\n * @param p - The quadratic polynomial to check.\n * @param i - Optional interval over which to check monotonicity.\n * @returns `true` when monotonicity is `'increasing'` or `'decreasing'`.\n * @since 2.0.0\n */\nexport const isMonotonic: {\n <T>(p: QuadraticPolynomial<T>, i?: Interval): p is QuadraticPolynomial<T & Monotonic>\n (i: Interval): <T>(p: QuadraticPolynomial<T>) => p is QuadraticPolynomial<T & Monotonic>\n} = internal.isMonotonic\n\n/**\n * Type-narrowing predicate: refines to `QuadraticPolynomial<T & Increasing>`.\n *\n * @since 2.0.0\n */\nexport const isIncreasing: {\n <T>(p: QuadraticPolynomial<T>, i?: Interval): p is QuadraticPolynomial<T & Increasing>\n (i: Interval): <T>(p: QuadraticPolynomial<T>) => p is QuadraticPolynomial<T & Increasing>\n} = internal.isIncreasing\n\n/**\n * Type-narrowing predicate: refines to `QuadraticPolynomial<T & Decreasing>`.\n *\n * @since 2.0.0\n */\nexport const isDecreasing: {\n <T>(p: QuadraticPolynomial<T>, i?: Interval): p is QuadraticPolynomial<T & Decreasing>\n (i: Interval): <T>(p: QuadraticPolynomial<T>) => p is QuadraticPolynomial<T & Decreasing>\n} = internal.isDecreasing\n\n/**\n * Asserts that the quadratic polynomial is monotonic, throwing on failure.\n *\n * @param p - The quadratic polynomial to assert against.\n * @param i - Optional interval over which to check monotonicity.\n * @returns The same polynomial, typed with the `Monotonic` brand.\n * @throws When the polynomial is not monotonic over the given (or global) interval.\n * @since 2.0.0\n */\nexport const asMonotonic: <T>(\n p: QuadraticPolynomial<T>,\n i?: Interval,\n) => QuadraticPolynomial<T & Monotonic> = internal.asMonotonic\n\n/**\n * Asserts that the quadratic polynomial is increasing, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asIncreasing: <T>(\n p: QuadraticPolynomial<T>,\n i?: Interval,\n) => QuadraticPolynomial<T & Increasing> = internal.asIncreasing\n\n/**\n * Asserts that the quadratic polynomial is decreasing, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asDecreasing: <T>(\n p: QuadraticPolynomial<T>,\n i?: Interval,\n) => QuadraticPolynomial<T & Decreasing> = internal.asDecreasing\n\nexport const antiderivative: {\n /**\n * Computes the antiderivative of the quadratic polynomial.\n *\n * @param p - The quadratic polynomial.\n * @param constant - The constant of integration. Defaults to 0.\n * @returns The antiderivative of the polynomial as a cubic polynomial.\n * @since 1.0.0\n */\n (p: QuadraticPolynomial, constant?: number): CubicPolynomial\n /**\n * Computes the antiderivative of the quadratic polynomial.\n *\n * @param constant - The constant of integration. Defaults to 0.\n * @returns A function that takes a quadratic polynomial and returns the antiderivative of the polynomial as a cubic polynomial.\n * @since 1.0.0\n */\n (constant: number): (p: QuadraticPolynomial) => CubicPolynomial\n} = internal.antiderivative\n\nexport const domain: {\n /**\n * Computes the domain of the quadratic polynomial over a given range.\n *\n * @param p - The quadratic polynomial.\n * @param range - The range to compute the domain over.\n * @returns The domain of the polynomial over the range.\n * @since 1.0.0\n */\n (p: QuadraticPolynomial, range: Interval): Solution.AtMostOne<Interval>\n /**\n * Computes the domain of the quadratic polynomial over a given range.\n *\n * @param range - The range to compute the domain over.\n * @returns A function that takes a quadratic polynomial and returns the domain of the polynomial over the range.\n * @since 1.0.0\n */\n (range: Interval): (p: QuadraticPolynomial) => Solution.AtMostOne<Interval>\n} = internal.domain\n\nexport const range: {\n /**\n * Computes the range of the quadratic polynomial over a given domain.\n *\n * @param p - The quadratic polynomial.\n * @param domain - The domain to compute the range over.\n * @returns The range of the polynomial over the domain.\n * @since 1.0.0\n */\n (p: QuadraticPolynomial, domain: Interval): Closed\n /**\n * Computes the range of the quadratic polynomial over a given domain.\n *\n * @param domain - The domain to compute the range over.\n * @returns A function that takes a quadratic polynomial and returns the range of the polynomial over the domain.\n * @since 1.0.0\n */\n (domain: Interval): (p: QuadraticPolynomial) => Closed\n} = internal.range\n\nexport const length: {\n /**\n * Computes the length of the quadratic polynomial over a given interval.\n *\n * @param p - The quadratic polynomial.\n * @param i - The interval to compute the length over.\n * @returns The length of the polynomial over the interval.\n * @since 1.0.0\n */\n (p: QuadraticPolynomial, i: Interval): number\n /**\n * Computes the length of the quadratic polynomial over a given interval.\n *\n * @param i - The interval to compute the length over.\n * @returns A function that takes a quadratic polynomial and returns the length of the polynomial over the interval.\n * @since 1.0.0\n */\n (i: Interval): (p: QuadraticPolynomial) => number\n} = internal.length\n\nexport const curvature: {\n /**\n * Computes the curvature of the quadratic polynomial at a given x value.\n *\n * @param p - The quadratic polynomial.\n * @param x - The x value to compute the curvature at.\n * @returns The curvature of the polynomial at the given x value.\n * @since 1.0.0\n */\n (p: QuadraticPolynomial, x: number): number\n /**\n * Computes the curvature of the quadratic polynomial at a given x value.\n *\n * @param x - The x value to compute the curvature at.\n * @returns A function that takes a quadratic polynomial and returns the curvature of the polynomial at the given x value.\n * @since 1.0.0\n */\n (x: number): (p: QuadraticPolynomial) => number\n} = internal.curvature\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,MAAa,qBAA4DA;AAEzE,MAAaC,WAoBTC;;;;;;;;;AAUJ,MAAaC,SAAuDC;;;;;;;;AASpE,MAAaC,eAA+CC;;;;;;;;;AAU5D,MAAa,iBACXC;;;;;;;;;AAUF,MAAaC,eAA6DC;AAE1E,MAAaC,UAkBTC;;;;;;;;AASJ,MAAaC,aAA2DC;AAMxE,MAAaC,iBAyBTC;;;;;;;AAQJ,MAAaC,oBACXC;;;;;;;AAQF,MAAa,QAA6D,MACxEF,eAAsB,GAAG,EAAE;;;;;;;;AAS7B,MAAaG,iBAAgEC;;;;;;;;;AAU7E,MAAaC,gBACXC;;;;;;;;AASF,MAAaC,iBACXC;;;;;;;;AASF,MAAaC,iBACXC;;;;;;;;;AAUF,MAAaC,gBACXC;;;;;;;;;AAUF,MAAaC,iBACXC;;;;;;;;;AAUF,MAAaC,iBACXC;;;;;;;;AASF,MAAaC,eAA8CC;AAE3D,MAAaC,mBAkBTC;AAEJ,MAAaC,WAkBTC;AAEJ,MAAaC,UAkBTC;AAEJ,MAAaC,WAkBTC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACzSJ,MAAa,wBACXC;AAEF,MAAa,SAoBTC;;;;;;;;;;AAWJ,MAAa,OAAuEC;;;;;;;;AASpF,MAAa,aAAkDC;;;;;;;;;;;;AAa/D,MAAa,aACXC;AAEF,MAAa,QAkBTC;;;;;;;AAQJ,MAAa,WAA8DC;AAE3E,MAAa,eAkCTC;;;;;;;AAQJ,MAAa,kBAEoCC;;;;;;;;AASjD,MAAa,aAA2DC;;;;;;;;AASxE,MAAa,QAAgEC;;;;;;;;AAS7E,MAAa,UAAsDC;AAEnE,MAAa,eAsBTC;;;;;;;;;;;AAYJ,MAAa,cAGTC;;;;;;AAOJ,MAAa,eAGTC;;;;;;AAOJ,MAAa,eAGTC;;;;;;;;;;AAWJ,MAAa,cAG6BC;;;;;;AAO1C,MAAa,eAG8BC;;;;;;AAO3C,MAAa,eAG8BC;AAE3C,MAAa,iBAkBTC;AAEJ,MAAa,SAkBTC;AAEJ,MAAa,QAkBTC;AAEJ,MAAa,SAkBTC;AAEJ,MAAa,YAkBTC"}
@@ -1,6 +1,8 @@
1
- import { t as Vector2 } from "./vector2-TV0UnlxY.mjs";
2
- import { t as Pipeable } from "./utils-DqTGyXrP.mjs";
3
- import { r as CubicCurve2d, t as RationalCubicCurve2d } from "./rationalCubic2d-BPLohNuI.mjs";
1
+ import { t as Vector2 } from "./vector2-DPUY3_eA.mjs";
2
+ import { t as Pipeable } from "./utils-MCckigYk.mjs";
3
+ import { n as Closed } from "./interval-Dy-RMEE3.mjs";
4
+ import { t as Interval2d } from "./interval2d-C2id9u31.mjs";
5
+ import { r as CubicCurve2d, t as RationalCubicCurve2d } from "./rationalCubic2d-DlQfBURs.mjs";
4
6
 
5
7
  //#region src/path/traits.d.ts
6
8
  /**
@@ -38,7 +40,7 @@ type PathTraits = typeof PathTraits;
38
40
  declare const CubicPath2dTypeId: unique symbol;
39
41
  type CubicPath2dTypeId = typeof CubicPath2dTypeId;
40
42
  declare namespace cubic2d_d_exports {
41
- export { Continuous, CubicPath2d, append$1 as append, asContinuous, fromArray$1 as fromArray, isContinuous, isCubicPath2d, length, make$1 as make, solve$1 as solve, solveByDistance, toPathData };
43
+ export { Continuous, CubicPath2d, append$1 as append, asContinuous, boundingBox, fromArray$1 as fromArray, isContinuous, isCubicPath2d, length, make$1 as make, solve$1 as solve, solveByDistance, toPathData };
42
44
  }
43
45
  /**
44
46
  * A cubic path in 2D space.
@@ -174,6 +176,15 @@ declare const solveByDistance: {
174
176
  */
175
177
  (s: number): (p: CubicPath2d) => Vector2;
176
178
  };
179
+ /**
180
+ * Computes the axis-aligned bounding box of the path — the smallest closed
181
+ * `Box2d` enclosing every segment.
182
+ *
183
+ * @param p - The cubic path.
184
+ * @returns A closed `Box2d` enclosing the path.
185
+ * @since 2.1.0
186
+ */
187
+ declare const boundingBox: (p: CubicPath2d) => Interval2d<Closed, Closed>;
177
188
  //#endregion
178
189
  //#region src/path/rationalCubic2d.internal.d.ts
179
190
  declare const RationalCubicPath2dTypeId: unique symbol;
@@ -294,4 +305,4 @@ declare const approximateAsCubicPath: {
294
305
  };
295
306
  //#endregion
296
307
  export { Continuous as a, cubic2d_d_exports as i, rationalCubic2d_d_exports as n, PathTraits as o, CubicPath2d as r, RationalCubicPath2d as t };
297
- //# sourceMappingURL=rationalCubic2d-D_-XWxcm.d.mts.map
308
+ //# sourceMappingURL=rationalCubic2d-B6g97ryJ.d.mts.map
@@ -2,8 +2,9 @@ import { t as __exportAll } from "./chunk-25Hzd3z8.mjs";
2
2
  import { Pipeable, dual, invariant } from "../utils.mjs";
3
3
  import { epsEquals } from "../number.mjs";
4
4
  import { r as magnitude } from "./vector2-CL1HDdPr.mjs";
5
- import { o as make$4, u as unit } from "./interval-CCEqzPgA.mjs";
6
- import { c as solve$4, f as solve$5, i as solve$6, l as derivative, s as length$2, t as approximateAsCubicCurves } from "./rationalCubic2d-CP4oGpnk.mjs";
5
+ import { c as make$4, p as unit } from "./interval-05CR6eBf.mjs";
6
+ import { r as union } from "./interval2d-8IBZnUOq.mjs";
7
+ import { a as boundingBox$2, c as length$2, i as solve$6, l as solve$4, m as solve$5, t as approximateAsCubicCurves, u as derivative } from "./rationalCubic2d-Bys2Uory.mjs";
7
8
  //#region src/path/cubic2d.internal.ts
8
9
  const CubicPath2dTypeId = Symbol("curvy/path/cubic2d");
9
10
  var CubicPath2dImpl = class extends Pipeable {
@@ -131,11 +132,18 @@ const solveByDistance$1 = dual(2, (p, s) => {
131
132
  const curve = (p instanceof CubicPath2dImpl ? p.curves : [...p])[k];
132
133
  return solve$4(curve, solveCurveByDistance(curve, segmentTarget, segmentLength));
133
134
  });
135
+ const boundingBox$1 = (p) => {
136
+ const iter = p[Symbol.iterator]();
137
+ let acc = boundingBox$2(iter.next().value);
138
+ for (let next = iter.next(); !next.done; next = iter.next()) acc = union(acc, boundingBox$2(next.value));
139
+ return acc;
140
+ };
134
141
  //#endregion
135
142
  //#region src/path/cubic2d.ts
136
143
  var cubic2d_exports = /* @__PURE__ */ __exportAll({
137
144
  append: () => append$2,
138
145
  asContinuous: () => asContinuous,
146
+ boundingBox: () => boundingBox,
139
147
  fromArray: () => fromArray$2,
140
148
  isContinuous: () => isContinuous,
141
149
  isCubicPath2d: () => isCubicPath2d,
@@ -203,6 +211,15 @@ const isContinuous = isContinuous$1;
203
211
  */
204
212
  const asContinuous = asContinuous$1;
205
213
  const solveByDistance = solveByDistance$1;
214
+ /**
215
+ * Computes the axis-aligned bounding box of the path — the smallest closed
216
+ * `Box2d` enclosing every segment.
217
+ *
218
+ * @param p - The cubic path.
219
+ * @returns A closed `Box2d` enclosing the path.
220
+ * @since 2.1.0
221
+ */
222
+ const boundingBox = boundingBox$1;
206
223
  //#endregion
207
224
  //#region src/path/rationalCubic2d.internal.ts
208
225
  const RationalCubicPath2dTypeId = Symbol("curvy/path/rationalCubic2d");
@@ -275,4 +292,4 @@ const approximateAsCubicPath = approximateAsCubicPath$1;
275
292
  //#endregion
276
293
  export { make$2 as i, rationalCubic2d_exports as n, cubic2d_exports as r, fromArray as t };
277
294
 
278
- //# sourceMappingURL=rationalCubic2d-CXa7Yren.mjs.map
295
+ //# sourceMappingURL=rationalCubic2d-BEgUGSFf.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rationalCubic2d-BEgUGSFf.mjs","names":["isCubicPath2d","make","fromArray","append","length","CubicCurve2d.length","Interval.unit","solve","CubicCurve2d.solve","derivative","cubicCurveInternal.derivative","Interval.make","Vector2.magnitude","QuadraticCurve2d.solve","toPathData","isContinuous","asContinuous","solveByDistance","boundingBox","CubicCurve2d.boundingBox","Interval2d.union","make","internal.make","fromArray","internal.fromArray","internal.isCubicPath2d","append","internal.append","internal.length","solve","internal.solve","internal.toPathData","internal.isContinuous","internal.asContinuous","internal.solveByDistance","internal.boundingBox","isRationalCubicPath2d","make","fromArray","append","solve","RationalCubicCurve2d.solve","approximateAsCubicPath","RationalCubicCurve2d.approximateAsCubicCurves","CubicPath2d.fromArray","internal.isRationalCubicPath2d","internal.make","internal.fromArray","internal.append","internal.solve","internal.approximateAsCubicPath"],"sources":["../../src/path/cubic2d.internal.ts","../../src/path/cubic2d.ts","../../src/path/rationalCubic2d.internal.ts","../../src/path/rationalCubic2d.ts"],"sourcesContent":["import * as Interval2d from '../interval/interval2d'\nimport * as CubicCurve2d from '../curve/cubic2d'\nimport * as cubicCurveInternal from '../curve/cubic2d.internal'\nimport * as QuadraticCurve2d from '../curve/quadratic2d'\nimport * as Interval from '../interval/interval'\nimport { dual, Pipeable } from '../utils'\nimport { invariant } from '../utils'\nimport { epsEquals } from '../number'\nimport * as Vector2 from '../vector/vector2'\nimport type { CubicPath2d } from './cubic2d'\nimport { PathTraits, type Continuous } from './traits'\n\nexport const CubicPath2dTypeId: unique symbol = Symbol('curvy/path/cubic2d')\nexport type CubicPath2dTypeId = typeof CubicPath2dTypeId\n\nexport class CubicPath2dImpl extends Pipeable implements CubicPath2d<unknown> {\n readonly [CubicPath2dTypeId]: CubicPath2dTypeId = CubicPath2dTypeId\n declare readonly [PathTraits]: unknown\n\n readonly curves: ReadonlyArray<CubicCurve2d.CubicCurve2d>\n\n constructor(curves: ReadonlyArray<CubicCurve2d.CubicCurve2d>) {\n invariant(curves.length > 0, 'cubic path requires at least one curve')\n super()\n this.curves = curves\n }\n\n [Symbol.iterator](): Iterator<CubicCurve2d.CubicCurve2d> {\n return this.curves[Symbol.iterator]()\n }\n}\n\nexport const isCubicPath2d = (p: unknown): p is CubicPath2d =>\n typeof p === 'object' && p !== null && CubicPath2dTypeId in p\n\nexport const make = (...curves: ReadonlyArray<CubicCurve2d.CubicCurve2d>): CubicPath2d =>\n new CubicPath2dImpl(curves)\n\nexport const fromArray = (curves: ReadonlyArray<CubicCurve2d.CubicCurve2d>): CubicPath2d =>\n new CubicPath2dImpl(curves)\n\nexport const append = dual<\n (c: CubicCurve2d.CubicCurve2d) => (p: CubicPath2d) => CubicPath2d,\n (p: CubicPath2d, c: CubicCurve2d.CubicCurve2d) => CubicPath2d\n>(2, (p: CubicPath2d, c: CubicCurve2d.CubicCurve2d) => fromArray([...p, c]))\n\nexport const length = (p: CubicPath2d) => {\n let total = 0\n for (const curve of p) {\n total += CubicCurve2d.length(curve, Interval.unit)\n }\n\n return total\n}\n\nexport const solve = dual<\n (u: number) => (p: CubicPath2d) => Vector2.Vector2,\n (p: CubicPath2d, u: number) => Vector2.Vector2\n>(2, (p: CubicPath2d, u: number) => {\n const curves = p instanceof CubicPath2dImpl ? p.curves : [...p]\n\n if (u === 1) {\n const last = curves.at(-1) as CubicCurve2d.CubicCurve2d\n return CubicCurve2d.solve(last, 1)\n }\n\n const t = u * curves.length\n const i = Math.floor(t)\n const curve = curves[i] as CubicCurve2d.CubicCurve2d\n return CubicCurve2d.solve(curve, t - i)\n})\n\n// Cumulative segment lengths cache. lengths[k] = total length through segment k.\n// Cached by path identity since paths are immutable.\nconst cumulativeLengthCache = new WeakMap<CubicPath2d, ReadonlyArray<number>>()\n\nconst getCumulativeLengths = (p: CubicPath2d): ReadonlyArray<number> => {\n let cached = cumulativeLengthCache.get(p)\n if (cached === undefined) {\n const lengths: Array<number> = []\n let total = 0\n for (const curve of p) {\n total += CubicCurve2d.length(curve, Interval.unit)\n lengths.push(total)\n }\n cached = lengths\n cumulativeLengthCache.set(p, cached)\n }\n return cached\n}\n\n// Newton's method to find the local parameter t ∈ [0, 1] within `curve` such\n// that the arc length from 0 to t equals `target`. Each iteration costs one\n// GL32 quadrature plus one velocity eval; converges in 3–5 iterations for\n// well-behaved curves. Falls back to bisection on cusps where speed → 0.\nconst solveCurveByDistance = (\n curve: CubicCurve2d.CubicCurve2d,\n target: number,\n segmentLength: number,\n): number => {\n if (target <= 0) {\n return 0\n }\n if (target >= segmentLength) {\n return 1\n }\n\n const derivative = cubicCurveInternal.derivative(curve)\n\n let t = target / segmentLength\n let lo = 0\n let hi = 1\n\n for (let iter = 0; iter < 16; iter++) {\n const currentLength = CubicCurve2d.length(curve, Interval.make(0, t))\n const error = currentLength - target\n\n if (Math.abs(error) < 1e-10) {\n return t\n }\n\n if (error > 0) {\n hi = t\n } else {\n lo = t\n }\n\n const speed = Vector2.magnitude(QuadraticCurve2d.solve(derivative, t))\n if (speed === 0) {\n // cusp — bisect instead\n t = (lo + hi) / 2\n continue\n }\n\n const next = t - error / speed\n // bracket-clamp Newton step; if it leaves the bracket, fall back to bisection\n t = next > lo && next < hi ? next : (lo + hi) / 2\n }\n\n return t\n}\n\n// Cubic Bernstein basis: P(t) = (1-t)³·p0 + 3(1-t)²t·p1 + 3(1-t)t²·p2 + t³·p3\n// expanded gives c0 = p0, c1 = -3p0 + 3p1, c2 = 3p0 - 6p1 + 3p2, c3 = -p0 + 3p1 - 3p2 + p3,\n// so: p0 = c0, p1 = c0 + c1/3, p2 = c0 + 2c1/3 + c2/3, p3 = c0 + c1 + c2 + c3.\nexport const toPathData = (p: CubicPath2d): string => {\n let result = ''\n let prevEndX = Number.NaN\n let prevEndY = Number.NaN\n\n for (const curve of p) {\n const c0x = curve.x.c0\n const c0y = curve.y.c0\n const c1x = curve.x.c1\n const c1y = curve.y.c1\n const c2x = curve.x.c2\n const c2y = curve.y.c2\n const c3x = curve.x.c3\n const c3y = curve.y.c3\n\n const startX = c0x\n const startY = c0y\n const ctrl1X = c0x + c1x / 3\n const ctrl1Y = c0y + c1y / 3\n const ctrl2X = c0x + (2 * c1x) / 3 + c2x / 3\n const ctrl2Y = c0y + (2 * c1y) / 3 + c2y / 3\n const endX = c0x + c1x + c2x + c3x\n const endY = c0y + c1y + c2y + c3y\n\n if (!epsEquals(startX, prevEndX) || !epsEquals(startY, prevEndY)) {\n result += ` M ${startX},${startY}`\n }\n result += ` C ${ctrl1X},${ctrl1Y} ${ctrl2X},${ctrl2Y} ${endX},${endY}`\n\n prevEndX = endX\n prevEndY = endY\n }\n\n return result.slice(1)\n}\n\nexport const isContinuous = <T>(p: CubicPath2d<T>): p is CubicPath2d<T & Continuous> => {\n let prevEndX = Number.NaN\n let prevEndY = Number.NaN\n let first = true\n\n for (const curve of p) {\n const startX = curve.x.c0\n const startY = curve.y.c0\n if (!first && (!epsEquals(startX, prevEndX) || !epsEquals(startY, prevEndY))) {\n return false\n }\n prevEndX = curve.x.c0 + curve.x.c1 + curve.x.c2 + curve.x.c3\n prevEndY = curve.y.c0 + curve.y.c1 + curve.y.c2 + curve.y.c3\n first = false\n }\n return true\n}\n\nexport const asContinuous = <T>(p: CubicPath2d<T>): CubicPath2d<T & Continuous> => {\n invariant(isContinuous(p), 'cubic path is not continuous')\n return p\n}\n\nexport const solveByDistance = dual<\n (s: number) => (p: CubicPath2d) => Vector2.Vector2,\n (p: CubicPath2d, s: number) => Vector2.Vector2\n>(2, (p: CubicPath2d, s: number) => {\n if (s <= 0) {\n return solve(p, 0)\n }\n if (s >= 1) {\n return solve(p, 1)\n }\n\n const lengths = getCumulativeLengths(p)\n const total = lengths[lengths.length - 1] as number\n const target = s * total\n\n // find segment k such that lengths[k-1] ≤ target ≤ lengths[k]\n let k = 0\n while (k < lengths.length - 1 && (lengths[k] as number) < target) {\n k++\n }\n\n const segmentStart = k === 0 ? 0 : (lengths[k - 1] as number)\n const segmentEnd = lengths[k] as number\n const segmentLength = segmentEnd - segmentStart\n const segmentTarget = target - segmentStart\n\n const curves = p instanceof CubicPath2dImpl ? p.curves : [...p]\n const curve = curves[k] as CubicCurve2d.CubicCurve2d\n const localT = solveCurveByDistance(curve, segmentTarget, segmentLength)\n\n return CubicCurve2d.solve(curve, localT)\n})\n\nexport const boundingBox = (\n p: CubicPath2d,\n): Interval2d.Interval2d<Interval.Closed, Interval.Closed> => {\n const iter = p[Symbol.iterator]()\n const first = iter.next()\n let acc = CubicCurve2d.boundingBox(first.value as CubicCurve2d.CubicCurve2d)\n for (let next = iter.next(); !next.done; next = iter.next()) {\n acc = Interval2d.union(acc, CubicCurve2d.boundingBox(next.value))\n }\n return acc\n}\n","import type { Interval2d } from '../interval/interval2d'\nimport type { CubicCurve2d } from '../curve/cubic2d'\nimport type { Closed } from '../interval/interval'\nimport type { Pipeable } from '../utils'\nimport type { Vector2 } from '../vector/vector2'\nimport type { CubicPath2dTypeId } from './cubic2d.internal'\nimport * as internal from './cubic2d.internal'\nimport type { Continuous, PathTraits } from './traits'\n\nexport type { Continuous } from './traits'\n\n/**\n * A cubic path in 2D space.\n *\n * All fields are readonly and immutable, and all operations create new instances.\n *\n * The `Trait` type parameter accumulates trait brands as the path is refined\n * via `isContinuous` / `asContinuous`.\n *\n * @since 1.0.0\n */\nexport interface CubicPath2d<out Trait = unknown> extends Pipeable, Iterable<CubicCurve2d> {\n readonly [CubicPath2dTypeId]: CubicPath2dTypeId\n readonly [PathTraits]: Trait\n}\n\n/**\n * Creates a new `CubicPath2d` instance from a sequence of curves.\n *\n * @param curves - The curves to create the path from.\n * @returns A new `CubicPath2d` instance.\n * @since 2.0.0\n */\nexport const make: (...curves: ReadonlyArray<CubicCurve2d>) => CubicPath2d = internal.make\n\n/**\n * Creates a new `CubicPath2d` instance from an array of curves.\n *\n * @param curves - The curves to create the path from.\n * @returns A new `CubicPath2d` instance.\n * @since 2.0.0\n */\nexport const fromArray: (curves: ReadonlyArray<CubicCurve2d>) => CubicPath2d = internal.fromArray\n\n/**\n * Checks if a value is a `CubicPath2d`.\n *\n * @param p - The value to check.\n * @returns `true` if the value is a `CubicPath2d`, `false` otherwise.\n * @since 1.0.0\n */\nexport const isCubicPath2d: (p: unknown) => p is CubicPath2d = internal.isCubicPath2d\n\nexport const append: {\n /**\n * Appends a cubic curve to a cubic path.\n *\n * @param c - The cubic curve to append.\n * @returns A function that takes a cubic path and returns a new cubic path.\n * @since 1.0.0\n */\n (c: CubicCurve2d): (p: CubicPath2d) => CubicPath2d\n /**\n * Appends a cubic curve to a cubic path.\n *\n * @param p - The cubic path to append to.\n * @param c - The cubic curve to append.\n * @returns A new cubic path.\n * @since 1.0.0\n */\n (p: CubicPath2d, c: CubicCurve2d): CubicPath2d\n} = internal.append\n\n/**\n * Calculates the length of a cubic path.\n *\n * @param p - The cubic path to calculate the length of.\n * @returns The length of the cubic path.\n * @since 1.0.0\n */\nexport const length: (p: CubicPath2d) => number = internal.length\n\nexport const solve: {\n /**\n * Solves a cubic path for a given parameter.\n *\n * @param u - The parameter to solve for.\n * @returns A function that takes a cubic path and returns the solved vector.\n * @since 1.0.0\n */\n (u: number): (p: CubicPath2d) => Vector2\n /**\n * Solves a cubic path for a given parameter.\n *\n * @param p - The cubic path to solve.\n * @param u - The parameter to solve for.\n * @returns The solved vector.\n * @since 1.0.0\n */\n (p: CubicPath2d, u: number): Vector2\n} = internal.solve\n\n/**\n * Serializes a cubic path as an SVG path data string (the value of a `<path>`\n * element's `d` attribute), using `M` and `C` commands. Discontinuities between\n * curves emit a fresh `M` command.\n *\n * @param p - The cubic path to serialize.\n * @returns The SVG path data string.\n * @since 2.0.0\n */\nexport const toPathData: (p: CubicPath2d) => string = internal.toPathData\n\n/**\n * Type-narrowing predicate: refines `CubicPath2d<T>` to\n * `CubicPath2d<T & Continuous>` when adjacent curves connect.\n *\n * @since 2.0.0\n */\nexport const isContinuous: <T>(p: CubicPath2d<T>) => p is CubicPath2d<T & Continuous> =\n internal.isContinuous\n\n/**\n * Asserts that the cubic path is continuous, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asContinuous: <T>(p: CubicPath2d<T>) => CubicPath2d<T & Continuous> =\n internal.asContinuous\n\nexport const solveByDistance: {\n /**\n * Solves a cubic path by normalized arc length. Unlike {@link solve}, which\n * is parameterized by curve `u`, this samples points at constant speed along\n * the path — `s = 0.5` returns the point exactly halfway along the curve by\n * arc length, regardless of how the underlying parameterization stretches.\n *\n * Cumulative segment lengths are cached by path identity so repeated calls\n * with the same path are fast.\n *\n * @param p - The cubic path to sample.\n * @param s - Normalized arc length in `[0, 1]`. Values outside the range are\n * clamped to path endpoints.\n * @returns The point on the path at the given normalized arc length.\n * @since 1.1.0\n */\n (p: CubicPath2d, s: number): Vector2\n /**\n * Solves a cubic path by normalized arc length.\n *\n * @param s - Normalized arc length in `[0, 1]`.\n * @returns A function that takes a cubic path and returns the point at that\n * arc length.\n * @since 1.1.0\n */\n (s: number): (p: CubicPath2d) => Vector2\n} = internal.solveByDistance\n\n/**\n * Computes the axis-aligned bounding box of the path — the smallest closed\n * `Box2d` enclosing every segment.\n *\n * @param p - The cubic path.\n * @returns A closed `Box2d` enclosing the path.\n * @since 2.1.0\n */\nexport const boundingBox: (p: CubicPath2d) => Interval2d<Closed, Closed> = internal.boundingBox\n","import type * as CubicCurve2d from '../curve/cubic2d'\nimport * as RationalCubicCurve2d from '../curve/rationalCubic2d'\nimport { dual, Pipeable } from '../utils'\nimport { invariant } from '../utils'\nimport type * as Vector2 from '../vector/vector2'\nimport * as CubicPath2d from './cubic2d'\nimport type { RationalCubicPath2d } from './rationalCubic2d'\n\nexport const RationalCubicPath2dTypeId: unique symbol = Symbol('curvy/path/rationalCubic2d')\nexport type RationalCubicPath2dTypeId = typeof RationalCubicPath2dTypeId\n\nexport class RationalCubicPath2dImpl extends Pipeable implements RationalCubicPath2d {\n readonly [RationalCubicPath2dTypeId]: RationalCubicPath2dTypeId = RationalCubicPath2dTypeId\n\n readonly curves: ReadonlyArray<RationalCubicCurve2d.RationalCubicCurve2d>\n\n constructor(curves: ReadonlyArray<RationalCubicCurve2d.RationalCubicCurve2d>) {\n invariant(curves.length > 0, 'rational cubic path requires at least one curve')\n super()\n this.curves = curves\n }\n\n [Symbol.iterator](): Iterator<RationalCubicCurve2d.RationalCubicCurve2d> {\n return this.curves[Symbol.iterator]()\n }\n}\n\nexport const isRationalCubicPath2d = (p: unknown): p is RationalCubicPath2d =>\n typeof p === 'object' && p !== null && RationalCubicPath2dTypeId in p\n\nexport const make = (\n ...curves: ReadonlyArray<RationalCubicCurve2d.RationalCubicCurve2d>\n): RationalCubicPath2d => new RationalCubicPath2dImpl(curves)\n\nexport const fromArray = (\n curves: ReadonlyArray<RationalCubicCurve2d.RationalCubicCurve2d>,\n): RationalCubicPath2d => new RationalCubicPath2dImpl(curves)\n\nexport const append = dual<\n (c: RationalCubicCurve2d.RationalCubicCurve2d) => (p: RationalCubicPath2d) => RationalCubicPath2d,\n (p: RationalCubicPath2d, c: RationalCubicCurve2d.RationalCubicCurve2d) => RationalCubicPath2d\n>(2, (p, c) => fromArray([...p, c]))\n\nexport const solve = dual<\n (u: number) => (p: RationalCubicPath2d) => Vector2.Vector2,\n (p: RationalCubicPath2d, u: number) => Vector2.Vector2\n>(2, (p: RationalCubicPath2d, u: number) => {\n const curves = p instanceof RationalCubicPath2dImpl ? p.curves : [...p]\n\n if (u === 1) {\n const last = curves.at(-1) as RationalCubicCurve2d.RationalCubicCurve2d\n return RationalCubicCurve2d.solve(last, 1)\n }\n\n const t = u * curves.length\n const i = Math.floor(t)\n const curve = curves[i] as RationalCubicCurve2d.RationalCubicCurve2d\n return RationalCubicCurve2d.solve(curve, t - i)\n})\n\n// Path-level approximation: per-segment approximation is delegated to the\n// curve module; we just concat the results. Segment count grows from N\n// (input) to roughly N × k where k depends on weight magnitude and tolerance —\n// uniform-weight segments stay 1:1.\nexport const approximateAsCubicPath = dual<\n (tolerance: number) => (p: RationalCubicPath2d) => CubicPath2d.CubicPath2d,\n (p: RationalCubicPath2d, tolerance: number) => CubicPath2d.CubicPath2d\n>(2, (p: RationalCubicPath2d, tolerance: number) => {\n const curves: Array<CubicCurve2d.CubicCurve2d> = []\n for (const segment of p) {\n for (const approx of RationalCubicCurve2d.approximateAsCubicCurves(segment, tolerance)) {\n curves.push(approx)\n }\n }\n return CubicPath2d.fromArray(curves)\n})\n","import type { RationalCubicCurve2d } from '../curve/rationalCubic2d'\nimport type { Pipeable } from '../utils'\nimport type { Vector2 } from '../vector/vector2'\nimport type { CubicPath2d } from './cubic2d'\nimport type { RationalCubicPath2dTypeId } from './rationalCubic2d.internal'\nimport * as internal from './rationalCubic2d.internal'\n\n/**\n * A rational cubic path in 2D space.\n *\n * Holds a non-empty sequence of `RationalCubicCurve2d` segments; iteration\n * yields the segments in order. The path parameter `u ∈ [0, 1]` is mapped\n * uniformly across segments — `u = 0` is the start of the first segment,\n * `u = 1` is the end of the last segment, and intermediate values pick a\n * segment by index and a local parameter within it.\n *\n * Counterpart to `CubicPath2d` for curves whose evaluation includes the\n * homogeneous-to-plane projection.\n *\n * All fields are readonly and immutable, and all operations create new instances.\n *\n * @since 2.1.0\n */\nexport interface RationalCubicPath2d extends Pipeable, Iterable<RationalCubicCurve2d> {\n readonly [RationalCubicPath2dTypeId]: RationalCubicPath2dTypeId\n}\n\n/**\n * Checks if a value is a `RationalCubicPath2d`.\n *\n * @param p - The value to check.\n * @returns `true` if the value is a `RationalCubicPath2d`, `false` otherwise.\n * @since 2.1.0\n */\nexport const isRationalCubicPath2d: (p: unknown) => p is RationalCubicPath2d =\n internal.isRationalCubicPath2d\n\n/**\n * Creates a new `RationalCubicPath2d` from a sequence of curves.\n *\n * @param curves - The curves to create the path from.\n * @returns A new `RationalCubicPath2d` instance.\n * @since 2.1.0\n */\nexport const make: (...curves: ReadonlyArray<RationalCubicCurve2d>) => RationalCubicPath2d =\n internal.make\n\n/**\n * Creates a new `RationalCubicPath2d` from an array of curves.\n *\n * @param curves - The curves to create the path from.\n * @returns A new `RationalCubicPath2d` instance.\n * @since 2.1.0\n */\nexport const fromArray: (curves: ReadonlyArray<RationalCubicCurve2d>) => RationalCubicPath2d =\n internal.fromArray\n\nexport const append: {\n /**\n * Appends a curve to a `RationalCubicPath2d`.\n *\n * @param c - The curve to append.\n * @returns A function that takes a path and returns a new path with the appended curve.\n * @since 2.1.0\n */\n (c: RationalCubicCurve2d): (p: RationalCubicPath2d) => RationalCubicPath2d\n /**\n * Appends a curve to a `RationalCubicPath2d`.\n *\n * @param p - The path to append to.\n * @param c - The curve to append.\n * @returns A new path with the appended curve.\n * @since 2.1.0\n */\n (p: RationalCubicPath2d, c: RationalCubicCurve2d): RationalCubicPath2d\n} = internal.append\n\nexport const solve: {\n /**\n * Evaluates the rational cubic path at parameter `u ∈ [0, 1]`.\n *\n * Picks the segment containing `u` (uniform mapping across segments) and\n * delegates to `RationalCubicCurve2d.solve` on that segment with the local\n * parameter.\n *\n * @param p - The path to evaluate.\n * @param u - The path parameter in `[0, 1]`.\n * @returns The point on the path at parameter `u`.\n * @since 2.1.0\n */\n (p: RationalCubicPath2d, u: number): Vector2\n /**\n * Evaluates the rational cubic path at parameter `u ∈ [0, 1]`.\n *\n * @param u - The path parameter in `[0, 1]`.\n * @returns A function that takes a path and returns the point at `u`.\n * @since 2.1.0\n */\n (u: number): (p: RationalCubicPath2d) => Vector2\n} = internal.solve\n\nexport const approximateAsCubicPath: {\n /**\n * Approximates the rational cubic path as a `CubicPath2d` via per-segment\n * recursive subdivision. Each input segment is split until its midpoint\n * deviates from a polynomial-cubic candidate by at most `tolerance`; the\n * surviving candidates are concatenated into a new path.\n *\n * Lossy in general — only exact when every input segment has uniform\n * weights, in which case segment count is preserved. Tighter tolerance\n * produces more segments.\n *\n * @param p - The rational cubic path to approximate.\n * @param tolerance - Maximum allowed midpoint deviation per segment; must be positive.\n * @returns A new `CubicPath2d` approximating the input.\n * @since 2.1.0\n */\n (p: RationalCubicPath2d, tolerance: number): CubicPath2d\n /**\n * Approximates the rational cubic path as a `CubicPath2d`.\n *\n * @param tolerance - Maximum allowed midpoint deviation per segment; must be positive.\n * @returns A function that takes a rational path and returns its approximation.\n * @since 2.1.0\n */\n (tolerance: number): (p: RationalCubicPath2d) => CubicPath2d\n} = internal.approximateAsCubicPath\n"],"mappings":"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"}
@@ -2,11 +2,12 @@ import { t as __exportAll } from "./chunk-25Hzd3z8.mjs";
2
2
  import { Pipeable, dual, invariant } from "../utils.mjs";
3
3
  import { i as make, n as cross, r as magnitude } from "./vector2-CL1HDdPr.mjs";
4
4
  import { n as transpose } from "./vector4-5KbjoHVj.mjs";
5
- import { c as size, d as unitOpen, s as scaleShift, t as biunit, u as unit } from "./interval-CCEqzPgA.mjs";
6
- import { a as match, i as map, o as none, s as one, t as clip } from "./solution-CbSWzXCn.mjs";
7
- import { A as GL32_X10, B as GL32_X6, C as GL32_W5, D as GL32_W9, E as GL32_W8, F as GL32_X15, H as GL32_X8, I as GL32_X2, L as GL32_X3, M as GL32_X12, N as GL32_X13, O as GL32_X0, P as GL32_X14, R as GL32_X4, S as GL32_W4, T as GL32_W7, U as GL32_X9, V as GL32_X7, _ as GL32_W13, a as isIncreasing$6, b as GL32_W2, c as roots, d as subdivide, f as GL32_W0, g as GL32_W12, h as GL32_W11, i as isDecreasing$6, j as GL32_X11, k as GL32_X1, l as solve$8, m as GL32_W10, n as derivative$5, o as isMonotonic$6, p as GL32_W1, s as make$1, u as solveInverse, v as GL32_W14, w as GL32_W6, x as GL32_W3, y as GL32_W15, z as GL32_X5 } from "./cubic-CYYEUHNm.mjs";
8
- import { a as make$3, c as solveInverse$2, d as isMonotonic$7, h as solveInverse$1, i as isMonotonic$8, l as isDecreasing$7, m as solve$9, n as isDecreasing$8, p as make$2, r as isIncreasing$8, s as solve$10, t as derivative$6, u as isIncreasing$7 } from "./quadratic-DEhuAKuE.mjs";
9
- import { i as cubicBezier, t as apply } from "./characteristic-BGRxcxUH.mjs";
5
+ import { l as scaleShift, m as unitOpen, p as unit, t as biunit, u as size } from "./interval-05CR6eBf.mjs";
6
+ import { a as match, i as map, o as none, s as one, t as clip } from "./solution-CrtLfqEq.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 range, d as solveInverse, f as subdivide, g as GL32_W11, h as GL32_W10, i as isDecreasing$6, j as GL32_X10, k as GL32_X0, l as roots, m as GL32_W1, n as derivative$5, o as isMonotonic$6, p as GL32_W0, s as make$1, u as solve$8, v as GL32_W13, w as GL32_W5, x as GL32_W2, y as GL32_W14, z as GL32_X4 } from "./cubic-CpHAx8cC.mjs";
8
+ import { _ as solveInverse$1, a as make$3, c as solve$10, d as isIncreasing$7, f as isMonotonic$7, g as solve$9, h as range$1, i as isMonotonic$8, l as solveInverse$2, m as make$2, n as isDecreasing$8, r as isIncreasing$8, s as range$2, t as derivative$6, u as isDecreasing$7 } from "./quadratic-CamozcFc.mjs";
9
+ import { n as make$4 } from "./interval2d-8IBZnUOq.mjs";
10
+ import { i as cubicBezier, t as apply } from "./characteristic-B9nCh_cx.mjs";
10
11
  //#region src/curve/linear2d.internal.ts
11
12
  const LinearCurve2dTypeId = Symbol("curvy/curve/linear2d");
12
13
  var LinearCurve2dImpl = class extends Pipeable {
@@ -40,6 +41,7 @@ const solveAtY$7 = dual(2, (c, y) => match(solveInverse$1(c.y, y), {
40
41
  onSome: ({ value: t }) => t < 0 || t > 1 ? none : one(solve$9(c.x, t))
41
42
  }));
42
43
  const length$5 = dual(2, (c, i) => Math.sqrt(c.x.c1 ** 2 + c.y.c1 ** 2) * Math.abs(i.end - i.start));
44
+ const boundingBox$5 = (c) => make$4(range$1(c.x, unit), range$1(c.y, unit));
43
45
  const isMonotonic$5 = (c) => isMonotonic$7(c.x) && isMonotonic$7(c.y);
44
46
  const isIncreasing$5 = (c) => isIncreasing$7(c.x) && isIncreasing$7(c.y);
45
47
  const isDecreasing$5 = (c) => isDecreasing$7(c.x) && isDecreasing$7(c.y);
@@ -55,6 +57,7 @@ var linear2d_exports = /* @__PURE__ */ __exportAll({
55
57
  asDecreasing: () => asDecreasing$4,
56
58
  asIncreasing: () => asIncreasing$4,
57
59
  asMonotonic: () => asMonotonic$4,
60
+ boundingBox: () => boundingBox$4,
58
61
  derivative: () => derivative$3,
59
62
  fromBezierPoints: () => fromBezierPoints$6,
60
63
  fromCoefficients: () => fromCoefficients$4,
@@ -121,6 +124,16 @@ const isLinearCurve2d = isLinearCurve2d$1;
121
124
  const derivative$3 = derivative$4;
122
125
  const solve$6 = solve$7;
123
126
  const length$4 = length$5;
127
+ /**
128
+ * Computes the axis-aligned bounding box of the curve over its parameter
129
+ * domain `[0, 1]`. For a linear curve this is the closed box enclosing the
130
+ * two endpoints.
131
+ *
132
+ * @param c - The linear curve.
133
+ * @returns A closed `Box2d` enclosing the curve.
134
+ * @since 2.1.0
135
+ */
136
+ const boundingBox$4 = boundingBox$5;
124
137
  const solveAtX$6 = solveAtX$7;
125
138
  const solveAtY$6 = solveAtY$7;
126
139
  /**
@@ -210,6 +223,7 @@ const curvature$3 = dual(2, (c, t) => {
210
223
  if (vMag === 0) return 0;
211
224
  return Math.abs(cross(v, a)) / vMag ** 3;
212
225
  });
226
+ const boundingBox$3 = (c) => make$4(range$2(c.x, unit), range$2(c.y, unit));
213
227
  const isMonotonic$3 = (c) => isMonotonic$8(c.x, unit) && isMonotonic$8(c.y, unit);
214
228
  const isIncreasing$3 = (c) => isIncreasing$8(c.x, unit) && isIncreasing$8(c.y, unit);
215
229
  const isDecreasing$3 = (c) => isDecreasing$8(c.x, unit) && isDecreasing$8(c.y, unit);
@@ -225,6 +239,7 @@ var quadratic2d_exports = /* @__PURE__ */ __exportAll({
225
239
  asDecreasing: () => asDecreasing$2,
226
240
  asIncreasing: () => asIncreasing$2,
227
241
  asMonotonic: () => asMonotonic$2,
242
+ boundingBox: () => boundingBox$2,
228
243
  curvature: () => curvature$2,
229
244
  derivative: () => derivative$1,
230
245
  fromBezierPoints: () => fromBezierPoints$4,
@@ -300,6 +315,16 @@ const solveAtY$4 = solveAtY$5;
300
315
  const derivative$1 = derivative$2;
301
316
  const curvature$2 = curvature$3;
302
317
  /**
318
+ * Computes the axis-aligned bounding box of the curve over its parameter
319
+ * domain `[0, 1]`. Accounts for interior extrema, so the box is tight against
320
+ * the curve and not just the control polygon.
321
+ *
322
+ * @param c - The quadratic curve.
323
+ * @returns A closed `Box2d` enclosing the curve.
324
+ * @since 2.1.0
325
+ */
326
+ const boundingBox$2 = boundingBox$3;
327
+ /**
303
328
  * Type-narrowing predicate: refines both axes' traits to include `Monotonic`
304
329
  * when both x and y polynomials are monotonic over the unit interval `[0, 1]`.
305
330
  *
@@ -372,6 +397,7 @@ const curvature$1 = dual(2, (c, t) => {
372
397
  if (vMag === 0) return 0;
373
398
  return Math.abs(cross(v, a)) / vMag ** 3;
374
399
  });
400
+ const boundingBox$1 = (c) => make$4(range(c.x, unit), range(c.y, unit));
375
401
  const isMonotonic$1 = (c) => isMonotonic$6(c.x, unit) && isMonotonic$6(c.y, unit);
376
402
  const isIncreasing$1 = (c) => isIncreasing$6(c.x, unit) && isIncreasing$6(c.y, unit);
377
403
  const isDecreasing$1 = (c) => isDecreasing$6(c.x, unit) && isDecreasing$6(c.y, unit);
@@ -387,6 +413,7 @@ var cubic2d_exports = /* @__PURE__ */ __exportAll({
387
413
  asDecreasing: () => asDecreasing,
388
414
  asIncreasing: () => asIncreasing,
389
415
  asMonotonic: () => asMonotonic,
416
+ boundingBox: () => boundingBox,
390
417
  curvature: () => curvature,
391
418
  fromBezierPoints: () => fromBezierPoints$2,
392
419
  fromCoefficients: () => fromCoefficients,
@@ -454,6 +481,16 @@ const solveAtX$2 = solveAtX$3;
454
481
  const solveAtY$2 = solveAtY$3;
455
482
  const curvature = curvature$1;
456
483
  /**
484
+ * Computes the axis-aligned bounding box of the curve over its parameter
485
+ * domain `[0, 1]`. Accounts for up to two interior extrema per axis, so the
486
+ * box is tight against the curve and not just the control polygon.
487
+ *
488
+ * @param c - The cubic curve.
489
+ * @returns A closed `Box2d` enclosing the curve.
490
+ * @since 2.1.0
491
+ */
492
+ const boundingBox = boundingBox$1;
493
+ /**
457
494
  * Type-narrowing predicate: refines both axes' traits to include `Monotonic`
458
495
  * when both x and y polynomials are monotonic over the unit interval `[0, 1]`.
459
496
  *
@@ -653,6 +690,6 @@ const solveAtX = solveAtX$1;
653
690
  const solveAtY = solveAtY$1;
654
691
  const approximateAsCubicCurves = approximateAsCubicCurves$1;
655
692
  //#endregion
656
- export { cubic2d_exports as a, solve$2 as c, quadratic2d_exports as d, solve$4 as f, solve$6 as h, solve as i, derivative as l, linear2d_exports as m, fromBezierPoints as n, fromPolynomials$2 as o, length$4 as p, rationalCubic2d_exports as r, length as s, approximateAsCubicCurves as t, length$2 as u };
693
+ export { linear2d_exports as _, boundingBox as a, length as c, boundingBox$2 as d, length$2 as f, length$4 as g, boundingBox$4 as h, solve as i, solve$2 as l, solve$4 as m, fromBezierPoints as n, cubic2d_exports as o, quadratic2d_exports as p, rationalCubic2d_exports as r, fromPolynomials$2 as s, approximateAsCubicCurves as t, derivative as u, solve$6 as v };
657
694
 
658
- //# sourceMappingURL=rationalCubic2d-CP4oGpnk.mjs.map
695
+ //# sourceMappingURL=rationalCubic2d-Bys2Uory.mjs.map