curvy 2.0.0-alpha.2 → 2.0.0-alpha.4

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 (63) hide show
  1. package/dist/characteristic/index.d.mts +9 -9
  2. package/dist/characteristic/index.mjs +1 -1
  3. package/dist/curve/index.d.mts +10 -2
  4. package/dist/curve/index.mjs +1 -1
  5. package/dist/interval/index.d.mts +9 -3
  6. package/dist/interval/index.mjs +2 -2
  7. package/dist/matrix/index.d.mts +9 -2
  8. package/dist/path/index.d.mts +15 -223
  9. package/dist/path/index.mjs +6 -6
  10. package/dist/path/index.mjs.map +1 -1
  11. package/dist/polynomial/index.d.mts +9 -2
  12. package/dist/polynomial/index.mjs +2 -2
  13. package/dist/shared/{characteristic-B9nCh_cx.mjs → characteristic-DLlhja-I.mjs} +9 -9
  14. package/dist/shared/{characteristic-B9nCh_cx.mjs.map → characteristic-DLlhja-I.mjs.map} +1 -1
  15. package/dist/shared/{cubic-CpHAx8cC.mjs → cubic-CMonq6bg.mjs} +26 -5
  16. package/dist/shared/cubic-CMonq6bg.mjs.map +1 -0
  17. package/dist/shared/cubic-DkBqcZf-.d.mts +121 -0
  18. package/dist/shared/interval-Bhzeqp8M.d.mts +62 -0
  19. package/dist/shared/{interval-05CR6eBf.mjs → interval-X1EYuf-T.mjs} +2 -2
  20. package/dist/shared/{interval-05CR6eBf.mjs.map → interval-X1EYuf-T.mjs.map} +1 -1
  21. package/dist/shared/interval2d-BMk5UYXD.d.mts +29 -0
  22. package/dist/shared/{interval2d-8IBZnUOq.mjs → interval2d-ca0J1NMr.mjs} +8 -8
  23. package/dist/shared/{interval2d-8IBZnUOq.mjs.map → interval2d-ca0J1NMr.mjs.map} +1 -1
  24. package/dist/shared/matrix4x4-CaytTaB_.d.mts +168 -0
  25. package/dist/shared/{quadratic-CamozcFc.mjs → quadratic-DyeMtvET.mjs} +20 -2
  26. package/dist/shared/quadratic-DyeMtvET.mjs.map +1 -0
  27. package/dist/shared/rationalCubic2d-D-UevGKu.d.mts +60 -0
  28. package/dist/shared/{rationalCubic2d-Bys2Uory.mjs → rationalCubic2d-D658ltUM.mjs} +17 -17
  29. package/dist/shared/{rationalCubic2d-Bys2Uory.mjs.map → rationalCubic2d-D658ltUM.mjs.map} +1 -1
  30. package/dist/shared/rationalCubic2d-MgMSJaAU.d.mts +104 -0
  31. package/dist/shared/{rationalCubic2d-BEgUGSFf.mjs → rationalCubic2d-Vw4qGPZj.mjs} +9 -9
  32. package/dist/shared/{rationalCubic2d-BEgUGSFf.mjs.map → rationalCubic2d-Vw4qGPZj.mjs.map} +1 -1
  33. package/dist/shared/{solution-CrtLfqEq.mjs → solution-3TDATEMn.mjs} +28 -2
  34. package/dist/shared/solution-3TDATEMn.mjs.map +1 -0
  35. package/dist/shared/solution-DInDT2Hq.d.mts +60 -0
  36. package/dist/shared/{vector2-CL1HDdPr.mjs → vector2-CCuJx1rX.mjs} +6 -6
  37. package/dist/shared/{vector2-CL1HDdPr.mjs.map → vector2-CCuJx1rX.mjs.map} +1 -1
  38. package/dist/shared/vector2-euuV_bNQ.d.mts +58 -0
  39. package/dist/shared/vector3-3Xx7GVk7.d.mts +37 -0
  40. package/dist/shared/{vector3-D-tv_aKL.mjs → vector3-C-qgKAjR.mjs} +2 -2
  41. package/dist/shared/{vector3-D-tv_aKL.mjs.map → vector3-C-qgKAjR.mjs.map} +1 -1
  42. package/dist/shared/{vector4-5KbjoHVj.mjs → vector4-BhOKDhD5.mjs} +2 -2
  43. package/dist/shared/{vector4-5KbjoHVj.mjs.map → vector4-BhOKDhD5.mjs.map} +1 -1
  44. package/dist/solution/index.d.mts +7 -2
  45. package/dist/solution/index.mjs +1 -1
  46. package/dist/splines/index.d.mts +37 -606
  47. package/dist/splines/index.mjs +193 -35
  48. package/dist/splines/index.mjs.map +1 -1
  49. package/dist/vector/index.d.mts +10 -3
  50. package/dist/vector/index.mjs +3 -3
  51. package/package.json +1 -1
  52. package/dist/shared/cubic-BajUY0JT.d.mts +0 -1100
  53. package/dist/shared/cubic-CpHAx8cC.mjs.map +0 -1
  54. package/dist/shared/interval-Dy-RMEE3.d.mts +0 -533
  55. package/dist/shared/interval2d-C2id9u31.d.mts +0 -172
  56. package/dist/shared/matrix4x4-Dm_tSiH1.d.mts +0 -1183
  57. package/dist/shared/quadratic-CamozcFc.mjs.map +0 -1
  58. package/dist/shared/rationalCubic2d-B6g97ryJ.d.mts +0 -308
  59. package/dist/shared/rationalCubic2d-DlQfBURs.d.mts +0 -818
  60. package/dist/shared/solution-CrtLfqEq.mjs.map +0 -1
  61. package/dist/shared/solution-sNQ-ZVhN.d.mts +0 -251
  62. package/dist/shared/vector2-DPUY3_eA.d.mts +0 -470
  63. package/dist/shared/vector3-DqeOZtOB.d.mts +0 -703
@@ -1,10 +1,10 @@
1
1
  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
- import { r as magnitude } from "./vector2-CL1HDdPr.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";
4
+ import { i as magnitude } from "./vector2-CCuJx1rX.mjs";
5
+ import { c as make$4, p as unit } from "./interval-X1EYuf-T.mjs";
6
+ import { r as union } from "./interval2d-ca0J1NMr.mjs";
7
+ import { a as boundingBox$2, d as derivative, h as solve$5, i as solve$6, l as length$2, t as approximateAsCubicCurves, u as solve$4 } from "./rationalCubic2d-D658ltUM.mjs";
8
8
  //#region src/path/cubic2d.internal.ts
9
9
  const CubicPath2dTypeId = Symbol("curvy/path/cubic2d");
10
10
  var CubicPath2dImpl = class extends Pipeable {
@@ -217,7 +217,7 @@ const solveByDistance = solveByDistance$1;
217
217
  *
218
218
  * @param p - The cubic path.
219
219
  * @returns A closed `Box2d` enclosing the path.
220
- * @since 2.1.0
220
+ * @since 2.0.0
221
221
  */
222
222
  const boundingBox = boundingBox$1;
223
223
  //#endregion
@@ -267,7 +267,7 @@ var rationalCubic2d_exports = /* @__PURE__ */ __exportAll({
267
267
  *
268
268
  * @param p - The value to check.
269
269
  * @returns `true` if the value is a `RationalCubicPath2d`, `false` otherwise.
270
- * @since 2.1.0
270
+ * @since 2.0.0
271
271
  */
272
272
  const isRationalCubicPath2d = isRationalCubicPath2d$1;
273
273
  /**
@@ -275,7 +275,7 @@ const isRationalCubicPath2d = isRationalCubicPath2d$1;
275
275
  *
276
276
  * @param curves - The curves to create the path from.
277
277
  * @returns A new `RationalCubicPath2d` instance.
278
- * @since 2.1.0
278
+ * @since 2.0.0
279
279
  */
280
280
  const make = make$1;
281
281
  /**
@@ -283,7 +283,7 @@ const make = make$1;
283
283
  *
284
284
  * @param curves - The curves to create the path from.
285
285
  * @returns A new `RationalCubicPath2d` instance.
286
- * @since 2.1.0
286
+ * @since 2.0.0
287
287
  */
288
288
  const fromArray = fromArray$1;
289
289
  const append = append$1;
@@ -292,4 +292,4 @@ const approximateAsCubicPath = approximateAsCubicPath$1;
292
292
  //#endregion
293
293
  export { make$2 as i, rationalCubic2d_exports as n, cubic2d_exports as r, fromArray as t };
294
294
 
295
- //# sourceMappingURL=rationalCubic2d-BEgUGSFf.mjs.map
295
+ //# sourceMappingURL=rationalCubic2d-Vw4qGPZj.mjs.map
@@ -1 +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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"}
1
+ {"version":3,"file":"rationalCubic2d-Vw4qGPZj.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.0.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.0.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.0.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.0.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.0.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.0.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.0.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.0.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.0.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.0.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.0.0\n */\n (tolerance: number): (p: RationalCubicPath2d) => CubicPath2d\n} = internal.approximateAsCubicPath\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./chunk-25Hzd3z8.mjs";
2
2
  import { Pipeable, dual, invariant } from "../utils.mjs";
3
- import { n as contains } from "./interval-05CR6eBf.mjs";
3
+ import { n as contains } from "./interval-X1EYuf-T.mjs";
4
4
  //#region src/solution/solution.internal.ts
5
5
  const EMPTY_ITERATOR = { next: () => ({
6
6
  done: true,
@@ -100,6 +100,10 @@ const max$1 = ((s) => {
100
100
  case "three": return Math.max(s.values[0], s.values[1], s.values[2]);
101
101
  }
102
102
  });
103
+ const unsafeValue$1 = (s, message) => {
104
+ invariant(isSome$1(s), message ?? "Solution.unsafeValue on empty Solution");
105
+ return s.value;
106
+ };
103
107
  const unsafeLast$1 = (s) => {
104
108
  invariant(isSome$1(s), "Solution.unsafeLast on empty Solution");
105
109
  return last$1(s);
@@ -163,6 +167,7 @@ var solution_exports = /* @__PURE__ */ __exportAll({
163
167
  unsafeLast: () => unsafeLast,
164
168
  unsafeMax: () => unsafeMax,
165
169
  unsafeMin: () => unsafeMin,
170
+ unsafeValue: () => unsafeValue,
166
171
  valueOrUndefined: () => valueOrUndefined
167
172
  });
168
173
  /**
@@ -239,6 +244,27 @@ const min = min$1;
239
244
  */
240
245
  const max = max$1;
241
246
  /**
247
+ * Returns the primary value of the solution (i.e. `s.value`). Throws on
248
+ * `None`, optionally with a caller-provided message.
249
+ *
250
+ * Useful when the type system can't prove non-emptiness but you have a domain
251
+ * reason to assert it — e.g. inverting a polynomial you know to be monotonic
252
+ * without going through the trait refiner first:
253
+ *
254
+ * ```ts
255
+ * const x = CubicPolynomial.solveInverse(p, y).pipe(
256
+ * Solution.unsafeValue('expected a monotonic inverse'),
257
+ * )
258
+ * ```
259
+ *
260
+ * @since 2.0.0
261
+ */
262
+ const unsafeValue = ((...args) => {
263
+ if (args.length >= 1 && typeof args[0] === "object" && args[0] !== null) return unsafeValue$1(args[0], args[1]);
264
+ const message = args[0];
265
+ return (s) => unsafeValue$1(s, message);
266
+ });
267
+ /**
242
268
  * Returns the last value in the solution. Throws if empty.
243
269
  *
244
270
  * @since 2.0.0
@@ -303,4 +329,4 @@ const match = match$1;
303
329
  //#endregion
304
330
  export { match as a, solution_exports as c, map as i, two as l, fromArray as n, none as o, isNone as r, one as s, clip as t };
305
331
 
306
- //# sourceMappingURL=solution-CrtLfqEq.mjs.map
332
+ //# sourceMappingURL=solution-3TDATEMn.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solution-3TDATEMn.mjs","names":["none","one","two","three","fromArray","isNone","isSome","valueOrUndefined","last","min","max","unsafeValue","unsafeLast","unsafeMin","unsafeMax","filter","clip","Interval.contains","map","match","internal.none","internal.one","internal.two","internal.three","internal.fromArray","internal.isNone","internal.isSome","internal.valueOrUndefined","internal.last","internal.min","internal.max","internal.unsafeValue","internal.unsafeLast","internal.unsafeMin","internal.unsafeMax","internal.filter","internal.clip","internal.map","internal.match"],"sources":["../../src/solution/solution.internal.ts","../../src/solution/solution.ts"],"sourcesContent":["import * as Interval from '../interval/interval'\nimport { dual, Pipeable } from '../utils'\nimport type {\n AtMostOne,\n AtMostThree,\n AtMostTwo,\n None,\n One,\n Solution,\n Some,\n Three,\n Two,\n} from './solution'\nimport { invariant } from '../utils'\n\n// Empty iterator — shared across all None instances since None has no data.\nconst EMPTY_ITERATOR: Iterator<never> = {\n next: () => ({ done: true, value: undefined as never }),\n}\n\nclass NoneImpl extends Pipeable implements None {\n readonly _tag = 'none' as const\n readonly length = 0 as const;\n\n [Symbol.iterator](): Iterator<never> {\n return EMPTY_ITERATOR\n }\n}\n\nclass OneImpl<T> extends Pipeable implements One<T> {\n readonly _tag = 'one' as const\n readonly length = 1 as const\n\n constructor(readonly value: T) {\n super()\n }\n\n [Symbol.iterator](): Iterator<T> {\n return [this.value][Symbol.iterator]()\n }\n}\n\nclass TwoImpl<T> extends Pipeable implements Two<T> {\n readonly _tag = 'two' as const\n readonly length = 2 as const\n\n constructor(readonly values: readonly [T, T]) {\n super()\n }\n\n get value(): T {\n return this.values[0]\n }\n\n [Symbol.iterator](): Iterator<T> {\n return this.values[Symbol.iterator]()\n }\n}\n\nclass ThreeImpl<T> extends Pipeable implements Three<T> {\n readonly _tag = 'three' as const\n readonly length = 3 as const\n\n constructor(readonly values: readonly [T, T, T]) {\n super()\n }\n\n get value(): T {\n return this.values[0]\n }\n\n [Symbol.iterator](): Iterator<T> {\n return this.values[Symbol.iterator]()\n }\n}\n\nexport const NONE_INSTANCE: None = new NoneImpl()\n\nexport const none: None = NONE_INSTANCE\n\nexport const one = <T>(value: T): One<T> => new OneImpl(value)\n\nexport const two = <T>(a: T, b: T): Two<T> => new TwoImpl([a, b])\n\nexport const three = <T>(a: T, b: T, c: T): Three<T> => new ThreeImpl([a, b, c])\n\nexport const fromArray = <T>(arr: ReadonlyArray<T>): Solution<T> => {\n switch (arr.length) {\n case 0:\n return NONE_INSTANCE\n case 1:\n return one(arr[0] as T)\n case 2:\n return two(arr[0] as T, arr[1] as T)\n case 3:\n return three(arr[0] as T, arr[1] as T, arr[2] as T)\n default:\n invariant(false, `Solution can hold at most 3 values, got ${arr.length}`)\n }\n}\n\nexport const isNone = <T>(s: Solution<T>): s is None => s._tag === 'none'\n\nexport const isSome = <T>(s: Solution<T>): s is Some<T> => s._tag !== 'none'\n\nexport const valueOrUndefined = <T>(s: Solution<T>): T | undefined =>\n isNone(s) ? undefined : s.value\n\nexport const last: {\n <T>(s: Some<T>): T\n <T>(s: Solution<T>): T | undefined\n} = (<T>(s: Solution<T>): T | undefined => {\n switch (s._tag) {\n case 'none':\n return undefined\n case 'one':\n return s.value\n case 'two':\n return s.values[1]\n case 'three':\n return s.values[2]\n }\n}) as never\n\nexport const min: {\n (s: Some<number>): number\n (s: Solution<number>): number | undefined\n} = ((s: Solution<number>): number | undefined => {\n switch (s._tag) {\n case 'none':\n return undefined\n case 'one':\n return s.value\n case 'two':\n return Math.min(s.values[0], s.values[1])\n case 'three':\n return Math.min(s.values[0], s.values[1], s.values[2])\n }\n}) as never\n\nexport const max: {\n (s: Some<number>): number\n (s: Solution<number>): number | undefined\n} = ((s: Solution<number>): number | undefined => {\n switch (s._tag) {\n case 'none':\n return undefined\n case 'one':\n return s.value\n case 'two':\n return Math.max(s.values[0], s.values[1])\n case 'three':\n return Math.max(s.values[0], s.values[1], s.values[2])\n }\n}) as never\n\nexport const unsafeValue = <T>(s: Solution<T>, message?: string): T => {\n invariant(isSome(s), message ?? 'Solution.unsafeValue on empty Solution')\n return s.value\n}\n\nexport const unsafeLast = <T>(s: Solution<T>): T => {\n invariant(isSome(s), 'Solution.unsafeLast on empty Solution')\n return last(s)\n}\n\nexport const unsafeMin = (s: Solution<number>): number => {\n invariant(isSome(s), 'Solution.unsafeMin on empty Solution')\n return min(s)\n}\n\nexport const unsafeMax = (s: Solution<number>): number => {\n invariant(isSome(s), 'Solution.unsafeMax on empty Solution')\n return max(s)\n}\n\nexport const filter = <T>(s: Solution<T>, predicate: (v: T) => boolean): Solution<T> => {\n switch (s._tag) {\n case 'none':\n return s\n case 'one':\n return predicate(s.value) ? s : NONE_INSTANCE\n case 'two': {\n const a = predicate(s.values[0])\n const b = predicate(s.values[1])\n if (a && b) {\n return s\n }\n if (a) {\n return one(s.values[0])\n }\n if (b) {\n return one(s.values[1])\n }\n return NONE_INSTANCE\n }\n case 'three': {\n const survivors: Array<T> = []\n if (predicate(s.values[0])) {\n survivors.push(s.values[0])\n }\n if (predicate(s.values[1])) {\n survivors.push(s.values[1])\n }\n if (predicate(s.values[2])) {\n survivors.push(s.values[2])\n }\n return fromArray(survivors)\n }\n }\n}\n\nexport const clip = dual(\n 2,\n (s: Solution<number>, i: Interval.Interval): Solution<number> =>\n filter(s, (v) => Interval.contains(i, v)),\n)\n\nexport const map = dual(2, <A, B>(s: Solution<A>, f: (v: A) => B): Solution<B> => {\n switch (s._tag) {\n case 'none':\n return s\n case 'one':\n return one(f(s.value))\n case 'two':\n return two(f(s.values[0]), f(s.values[1]))\n case 'three':\n return three(f(s.values[0]), f(s.values[1]), f(s.values[2]))\n }\n})\n\nexport const match = dual(\n 2,\n <T, A, B>(\n self: Solution<T>,\n matcher: { readonly onNone: () => A; readonly onSome: (s: Some<T>) => B },\n ): A | B => (isNone(self) ? matcher.onNone() : matcher.onSome(self)),\n)\n\n// Re-export type aliases that the namespace consumers expect to see at runtime.\n// (Pure type re-exports — no runtime cost.)\nexport type { AtMostOne, AtMostThree, AtMostTwo, None, One, Solution, Some, Three, Two }\n","import type { Interval } from '../interval/interval'\nimport type { Pipeable } from '../utils'\nimport * as internal from './solution.internal'\n\n/**\n * A `Solution<T>` represents the result of an operation that may produce\n * between zero and three values of `T`. It generalizes the zoo of \"0 or 1\",\n * \"0 to 2\", \"0 to 3\" return shapes used throughout curvy under one type, and\n * provides a small namespace of operations (`value`, `last`, `min`, `max`,\n * `filter`, `map`, `match`, …) for working with the result.\n *\n * Each variant carries a `_tag` discriminator and a `length` field, is\n * iterable via `Symbol.iterator` (so existing `for..of` and spread patterns\n * keep working), and is `Pipeable` (so a `Solution` value can be the head of\n * a `pipe` chain).\n *\n * Variant-specific accessors:\n * - `One<T>`, `Two<T>`, and `Three<T>` all expose `.value: T` (the first /\n * primary value).\n * - `Two<T>` and `Three<T>` additionally expose `.values: readonly [T, ...]`\n * for explicit positional access.\n *\n * Operations that return narrower cardinalities (e.g. inverse-solving a\n * monotonic polynomial) use the `AtMost{One,Two,Three}` aliases to express\n * \"this could be empty, but it'll have at most N values.\"\n *\n * @since 2.0.0\n */\nexport type Solution<T> = None | One<T> | Two<T> | Three<T>\n\n/**\n * The empty solution.\n *\n * @since 2.0.0\n */\nexport interface None extends Pipeable, Iterable<never> {\n readonly _tag: 'none'\n readonly length: 0\n}\n\n/** @since 2.0.0 */\nexport interface One<T> extends Pipeable, Iterable<T> {\n readonly _tag: 'one'\n readonly length: 1\n readonly value: T\n}\n\n/** @since 2.0.0 */\nexport interface Two<T> extends Pipeable, Iterable<T> {\n readonly _tag: 'two'\n readonly length: 2\n readonly value: T\n readonly values: readonly [T, T]\n}\n\n/** @since 2.0.0 */\nexport interface Three<T> extends Pipeable, Iterable<T> {\n readonly _tag: 'three'\n readonly length: 3\n readonly value: T\n readonly values: readonly [T, T, T]\n}\n\n/**\n * Any non-empty solution. All `Some<T>` values expose `.value: T` directly —\n * no narrowing required to read the primary value.\n *\n * @since 2.0.0\n */\nexport type Some<T> = One<T> | Two<T> | Three<T>\n\n/**\n * `None | One<T>` — return type of operations that produce at most one value\n * (e.g. inverse-solving a strictly monotonic polynomial).\n *\n * @since 2.0.0\n */\nexport type AtMostOne<T> = None | One<T>\n\n/**\n * `None | One<T> | Two<T>` — return type of operations that produce at most\n * two values (e.g. inverse-solving an unrestricted quadratic polynomial).\n *\n * @since 2.0.0\n */\nexport type AtMostTwo<T> = None | One<T> | Two<T>\n\n/**\n * `None | One<T> | Two<T> | Three<T>` — equivalent to `Solution<T>`.\n *\n * @since 2.0.0\n */\nexport type AtMostThree<T> = Solution<T>\n\n/**\n * The empty solution. Reused across calls — never reallocated.\n *\n * @since 2.0.0\n */\nexport const none: None = internal.none\n\n/**\n * Constructs a single-value solution.\n *\n * @since 2.0.0\n */\nexport const one: <T>(value: T) => One<T> = internal.one\n\n/**\n * Constructs a two-value solution.\n *\n * @since 2.0.0\n */\nexport const two: <T>(a: T, b: T) => Two<T> = internal.two\n\n/**\n * Constructs a three-value solution.\n *\n * @since 2.0.0\n */\nexport const three: <T>(a: T, b: T, c: T) => Three<T> = internal.three\n\n/**\n * Constructs a `Solution<T>` from a runtime array. Throws if the array has\n * more than three elements.\n *\n * @since 2.0.0\n */\nexport const fromArray: <T>(arr: ReadonlyArray<T>) => Solution<T> = internal.fromArray\n\n/**\n * Type-narrowing predicate: refines `Solution<T>` to `None`.\n *\n * @since 2.0.0\n */\nexport const isNone: <T>(s: Solution<T>) => s is None = internal.isNone\n\n/**\n * Type-narrowing predicate: refines `Solution<T>` to `Some<T>` (non-empty).\n * After narrowing, `.value` is directly accessible without further checks.\n *\n * @since 2.0.0\n */\nexport const isSome: <T>(s: Solution<T>) => s is Some<T> = internal.isSome\n\n/**\n * Returns the primary (first) value if the solution is non-empty, or\n * `undefined` if empty. Pair with `.value` access on `Some<T>`-narrowed\n * inputs to avoid the `undefined` possibility.\n *\n * @since 2.0.0\n */\nexport const valueOrUndefined: <T>(s: Solution<T>) => T | undefined = internal.valueOrUndefined\n\n/**\n * Returns the last value in the solution, or `undefined` if empty. When\n * called on a `Some<T>`, the result is guaranteed to be `T`.\n *\n * @since 2.0.0\n */\nexport const last: {\n <T>(s: Some<T>): T\n <T>(s: Solution<T>): T | undefined\n} = internal.last\n\n/**\n * Returns the smallest numeric value in the solution, or `undefined` if empty.\n * When called on a `Some<number>`, the result is guaranteed to be `number`.\n *\n * @since 2.0.0\n */\nexport const min: {\n (s: Some<number>): number\n (s: Solution<number>): number | undefined\n} = internal.min\n\n/**\n * Returns the largest numeric value in the solution, or `undefined` if empty.\n * When called on a `Some<number>`, the result is guaranteed to be `number`.\n *\n * @since 2.0.0\n */\nexport const max: {\n (s: Some<number>): number\n (s: Solution<number>): number | undefined\n} = internal.max\n\n/**\n * Returns the primary value of the solution (i.e. `s.value`). Throws on\n * `None`, optionally with a caller-provided message.\n *\n * Useful when the type system can't prove non-emptiness but you have a domain\n * reason to assert it — e.g. inverting a polynomial you know to be monotonic\n * without going through the trait refiner first:\n *\n * ```ts\n * const x = CubicPolynomial.solveInverse(p, y).pipe(\n * Solution.unsafeValue('expected a monotonic inverse'),\n * )\n * ```\n *\n * @since 2.0.0\n */\nexport const unsafeValue: {\n <T>(s: Solution<T>, message?: string): T\n (message: string): <T>(s: Solution<T>) => T\n} = ((...args: ReadonlyArray<unknown>) => {\n if (args.length >= 1 && typeof args[0] === 'object' && args[0] !== null) {\n return internal.unsafeValue(args[0] as Solution<unknown>, args[1] as string | undefined)\n }\n const message = args[0] as string\n return <T>(s: Solution<T>) => internal.unsafeValue(s, message)\n}) as never\n\n/**\n * Returns the last value in the solution. Throws if empty.\n *\n * @since 2.0.0\n */\nexport const unsafeLast: <T>(s: Solution<T>) => T = internal.unsafeLast\n\n/**\n * Returns the smallest numeric value in the solution. Throws on empty.\n *\n * @since 2.0.0\n */\nexport const unsafeMin: (s: Solution<number>) => number = internal.unsafeMin\n\n/**\n * Returns the largest numeric value in the solution. Throws on empty.\n *\n * @since 2.0.0\n */\nexport const unsafeMax: (s: Solution<number>) => number = internal.unsafeMax\n\n/**\n * Filters the solution by a predicate. Result cardinality is at most that of\n * the input.\n *\n * @since 2.0.0\n */\nexport const filter: <T>(s: Solution<T>, predicate: (v: T) => boolean) => Solution<T> =\n internal.filter\n\n/**\n * Restricts the solution to values contained within an interval. Endpoint\n * inclusivity follows the interval's `kind` — pass an open variant (e.g.\n * `Interval.makeOpen(0, 1)` or `Interval.unitOpen`) for strict containment.\n *\n * @param s - The solution to clip.\n * @param i - The interval to retain values within.\n * @since 2.0.0\n */\nexport const clip: {\n (i: Interval): (s: Solution<number>) => Solution<number>\n (s: Solution<number>, i: Interval): Solution<number>\n} = internal.clip\n\n/**\n * Maps every value in the solution to a new value. Result cardinality matches\n * the input.\n *\n * @since 2.0.0\n */\nexport const map: {\n <A, B>(s: Solution<A>, f: (v: A) => B): Solution<B>\n <A, B>(f: (v: A) => B): (s: Solution<A>) => Solution<B>\n} = internal.map\n\n// Drops `None` from the union of the input solution type — used by `match` to\n// give `onSome` a tighter parameter type. Distributive: a `Solution.AtMostOne<T>`\n// becomes `One<T>`; a full `Solution<T>` keeps `Some<T>`.\ntype SomeOf<S> = S extends None ? never : S\n\n/**\n * Pattern matches on a solution, calling `onNone` for the empty case and\n * `onSome` for any non-empty case. The `onSome` parameter is typed against\n * the input's narrowed shape — for an `AtMostOne<T>` input, `onSome` receives\n * `One<T>` and can read `.value` directly.\n *\n * @example\n * ```ts\n * const result = polynomial.pipe(\n * LinearPolynomial.solveInverse(0),\n * Solution.match({\n * onNone: () => null,\n * onSome: ({ value }) => Math.abs(value),\n * }),\n * )\n * ```\n *\n * @since 2.0.0\n */\nexport const match: {\n <S extends Solution<unknown>, A, B>(\n self: S,\n matcher: { readonly onNone: () => A; readonly onSome: (s: SomeOf<S>) => B },\n ): A | B\n <S extends Solution<unknown>, A, B>(matcher: {\n readonly onNone: () => A\n readonly onSome: (s: SomeOf<S>) => B\n }): (self: S) => A | B\n} = internal.match as never\n"],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { t as Pipeable } from "./utils-MCckigYk.mjs";
2
+
3
+ //#region src/solution/solution.d.ts
4
+ /**
5
+ * A `Solution<T>` represents the result of an operation that may produce
6
+ * between zero and three values of `T`. It generalizes the zoo of "0 or 1",
7
+ * "0 to 2", "0 to 3" return shapes used throughout curvy under one type, and
8
+ * provides a small namespace of operations (`value`, `last`, `min`, `max`,
9
+ * `filter`, `map`, `match`, …) for working with the result.
10
+ *
11
+ * Each variant carries a `_tag` discriminator and a `length` field, is
12
+ * iterable via `Symbol.iterator` (so existing `for..of` and spread patterns
13
+ * keep working), and is `Pipeable` (so a `Solution` value can be the head of
14
+ * a `pipe` chain).
15
+ *
16
+ * Variant-specific accessors:
17
+ * - `One<T>`, `Two<T>`, and `Three<T>` all expose `.value: T` (the first /
18
+ * primary value).
19
+ * - `Two<T>` and `Three<T>` additionally expose `.values: readonly [T, ...]`
20
+ * for explicit positional access.
21
+ *
22
+ * Operations that return narrower cardinalities (e.g. inverse-solving a
23
+ * monotonic polynomial) use the `AtMost{One,Two,Three}` aliases to express
24
+ * "this could be empty, but it'll have at most N values."
25
+ *
26
+ * @since 2.0.0
27
+ */
28
+ type Solution<T> = None | One<T> | Two<T> | Three<T>;
29
+ /**
30
+ * The empty solution.
31
+ *
32
+ * @since 2.0.0
33
+ */
34
+ interface None extends Pipeable, Iterable<never> {
35
+ readonly _tag: 'none';
36
+ readonly length: 0;
37
+ }
38
+ /** @since 2.0.0 */
39
+ interface One<T> extends Pipeable, Iterable<T> {
40
+ readonly _tag: 'one';
41
+ readonly length: 1;
42
+ readonly value: T;
43
+ }
44
+ /** @since 2.0.0 */
45
+ interface Two<T> extends Pipeable, Iterable<T> {
46
+ readonly _tag: 'two';
47
+ readonly length: 2;
48
+ readonly value: T;
49
+ readonly values: readonly [T, T];
50
+ }
51
+ /** @since 2.0.0 */
52
+ interface Three<T> extends Pipeable, Iterable<T> {
53
+ readonly _tag: 'three';
54
+ readonly length: 3;
55
+ readonly value: T;
56
+ readonly values: readonly [T, T, T];
57
+ }
58
+ //#endregion
59
+ export { Solution as t };
60
+ //# sourceMappingURL=solution-DInDT2Hq.d.mts.map
@@ -46,7 +46,7 @@ const isVector2 = isVector2$1;
46
46
  *
47
47
  * @param v - The value to check.
48
48
  * @returns `true` if the value is a `Vector2.Weighted`, `false` otherwise.
49
- * @since 2.1.0
49
+ * @since 2.0.0
50
50
  */
51
51
  const isWeighted = isWeighted$1;
52
52
  /**
@@ -57,7 +57,7 @@ const isWeighted = isWeighted$1;
57
57
  * @param y - The y component.
58
58
  * @param weight - The positive scalar weight.
59
59
  * @returns A new `Vector2.Weighted` instance.
60
- * @since 2.1.0
60
+ * @since 2.0.0
61
61
  */
62
62
  const makeWeighted = makeWeighted$1;
63
63
  const withWeight = withWeight$1;
@@ -66,7 +66,7 @@ const withWeight = withWeight$1;
66
66
  *
67
67
  * @param w - The weighted point.
68
68
  * @returns A new `Vector2` instance with the same x and y components.
69
- * @since 2.1.0
69
+ * @since 2.0.0
70
70
  */
71
71
  const unweighted = unweighted$1;
72
72
  const weightedEquals = weightedEquals$1;
@@ -80,7 +80,7 @@ const make = make$1;
80
80
  * @param inputs - Exactly two items of any type.
81
81
  * @param project - A function returning a fixed-arity tuple of numbers — one per output channel.
82
82
  * @returns A tuple of `Vector2`s with the same arity as the projection's return tuple.
83
- * @since 2.1.0
83
+ * @since 2.0.0
84
84
  */
85
85
  const transpose = transpose$1;
86
86
  /**
@@ -182,6 +182,6 @@ const setR = setR$1;
182
182
  const getTheta = getTheta$1;
183
183
  const setTheta = setTheta$1;
184
184
  //#endregion
185
- export { makeWeighted as a, vector2_exports as c, make as i, cross as n, scale as o, magnitude as r, subtract as s, add as t };
185
+ export { make as a, subtract as c, magnitude as i, vector2_exports as l, cross as n, makeWeighted as o, isVector2 as r, scale as s, add as t };
186
186
 
187
- //# sourceMappingURL=vector2-CL1HDdPr.mjs.map
187
+ //# sourceMappingURL=vector2-CCuJx1rX.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"vector2-CL1HDdPr.mjs","names":["internal.isVector2","internal.isWeighted","internal.makeWeighted","internal.withWeight","internal.unweighted","internal.weightedEquals","internal.equals","internal.make","internal.transpose","internal.fromPolar","internal.magnitude","internal.normalize","internal.dot","internal.cross","internal.components","internal.softmax","internal.add","internal.subtract","internal.hadamard","internal.scale","internal.getX","internal.setX","internal.getY","internal.setY","internal.setR","internal.getTheta","internal.setTheta"],"sources":["../../src/vector/vector2.ts"],"sourcesContent":["import type { TwoDimensional } from '../dimensions'\nimport type { Pipeable } from '../utils'\nimport type { Vector2TypeId, WeightedVector2TypeId } from './vector2.internal'\nimport * as internal from './vector2.internal'\n\n/**\n * A 2D vector.\n *\n * All fields are readonly and immutable, and all operations create new instances.\n *\n * @since 1.0.0\n */\nexport interface Vector2 extends Pipeable, TwoDimensional<number> {\n readonly [Vector2TypeId]: Vector2TypeId\n}\n\n/**\n * A 2D point with an associated positive scalar weight.\n *\n * Used by rational primitives (e.g. `RationalBezier2d`) where each control\n * point carries an influence weight. The interface is structurally distinct\n * from `Vector2` — its brand prevents accidental use with vector arithmetic\n * (`add`, `subtract`, `scale`, etc.) where weighted operations are not\n * well-defined.\n *\n * Construct via {@link makeWeighted} (from raw components) or\n * {@link withWeight} (from an existing `Vector2`).\n *\n * @since 2.1.0\n */\nexport interface Weighted extends Pipeable {\n readonly [WeightedVector2TypeId]: WeightedVector2TypeId\n readonly x: number\n readonly y: number\n readonly weight: number\n}\n\n/**\n * Checks if a value is a `Vector2`.\n *\n * @param v - The value to check.\n * @returns `true` if the value is a `Vector2`, `false` otherwise.\n * @since 1.0.0\n */\nexport const isVector2: (v: unknown) => v is Vector2 = internal.isVector2\n\n/**\n * Checks if a value is a `Vector2.Weighted`.\n *\n * @param v - The value to check.\n * @returns `true` if the value is a `Vector2.Weighted`, `false` otherwise.\n * @since 2.1.0\n */\nexport const isWeighted: (v: unknown) => v is Weighted = internal.isWeighted\n\n/**\n * Creates a new `Vector2.Weighted` from raw components. The weight must be\n * finite and positive.\n *\n * @param x - The x component.\n * @param y - The y component.\n * @param weight - The positive scalar weight.\n * @returns A new `Vector2.Weighted` instance.\n * @since 2.1.0\n */\nexport const makeWeighted: (x: number, y: number, weight: number) => Weighted =\n internal.makeWeighted\n\nexport const withWeight: {\n /**\n * Promotes a `Vector2` to a `Vector2.Weighted` by attaching the given\n * positive scalar weight.\n *\n * @param v - The point to weight.\n * @param weight - The positive scalar weight.\n * @returns A new `Vector2.Weighted` instance.\n * @since 2.1.0\n */\n (v: Vector2, weight: number): Weighted\n /**\n * Promotes a `Vector2` to a `Vector2.Weighted` by attaching the given\n * positive scalar weight.\n *\n * @param weight - The positive scalar weight.\n * @returns A function that takes a `Vector2` and returns a weighted point.\n * @since 2.1.0\n */\n (weight: number): (v: Vector2) => Weighted\n} = internal.withWeight\n\n/**\n * Strips the weight from a `Vector2.Weighted`, returning the underlying point.\n *\n * @param w - The weighted point.\n * @returns A new `Vector2` instance with the same x and y components.\n * @since 2.1.0\n */\nexport const unweighted: (w: Weighted) => Vector2 = internal.unweighted\n\nexport const weightedEquals: {\n /**\n * Checks if two `Vector2.Weighted` instances are approximately equal —\n * point components and weight all within the default absolute tolerance.\n *\n * @param a - The first weighted point.\n * @param b - The second weighted point.\n * @returns `true` when components and weight are within tolerance.\n * @since 2.1.0\n */\n (a: Weighted, b: Weighted): boolean\n /**\n * Checks if two `Vector2.Weighted` instances are approximately equal.\n *\n * @param b - The second weighted point.\n * @returns A function that takes the first weighted point and returns the comparison result.\n * @since 2.1.0\n */\n (b: Weighted): (a: Weighted) => boolean\n} = internal.weightedEquals\n\nexport const equals: {\n /**\n * Checks if two `Vector2` instances are approximately equal within the\n * default absolute tolerance ({@link EPSILON}).\n *\n * @param a - The first vector.\n * @param b - The second vector.\n * @returns `true` when each pair of components is within tolerance.\n * @since 1.1.0\n */\n (a: Vector2, b: Vector2): boolean\n /**\n * Checks if two `Vector2` instances are approximately equal within the\n * default absolute tolerance ({@link EPSILON}).\n *\n * @param b - The second vector.\n * @returns A function that takes the first vector and returns the comparison result.\n * @since 1.1.0\n */\n (b: Vector2): (a: Vector2) => boolean\n} = internal.equals\n\nexport const make: {\n /**\n * Creates a new `Vector2` instance.\n *\n * @param xy - The x and y components of the vector.\n * @returns A new `Vector2` instance.\n * @since 1.0.0\n */\n (xy: number): Vector2\n /**\n * Creates a new `Vector2` instance.\n *\n * @param x - The x component of the vector.\n * @param y - The y component of the vector.\n * @returns A new `Vector2` instance.\n * @since 1.0.0\n */\n (x: number, y: number): Vector2\n} = internal.make\n\n/**\n * Transposes a 2-tuple of items into one or more `Vector2`s, one per channel\n * extracted by the projection function. See {@link Vector4.transpose} for the\n * full operation description; this is the 2-component analog.\n *\n * @param inputs - Exactly two items of any type.\n * @param project - A function returning a fixed-arity tuple of numbers — one per output channel.\n * @returns A tuple of `Vector2`s with the same arity as the projection's return tuple.\n * @since 2.1.0\n */\nexport const transpose: <T, const Channels extends ReadonlyArray<number>>(\n inputs: readonly [T, T],\n project: (item: T) => Channels,\n) => { readonly [K in keyof Channels]: Vector2 } = internal.transpose\n\n/**\n * Creates a new `Vector2` instance from polar coordinates.\n *\n * @param r - The radius.\n * @param theta - The angle, in radians.\n * @returns A new `Vector2` instance.\n * @since 1.0.0\n */\nexport const fromPolar: (r: number, theta: number) => Vector2 = internal.fromPolar\n\n/**\n * Calculates the magnitude of a `Vector2`.\n *\n * @param vector - The vector to calculate the magnitude of.\n * @returns The magnitude of the vector.\n * @since 1.0.0\n */\nexport const magnitude: (vector: Vector2) => number = internal.magnitude\n\n/**\n * Normalizes a `Vector2`.\n *\n * @param vector - The vector to normalize.\n * @returns A new `Vector2` instance with the same direction and a magnitude of 1.\n * @since 1.0.0\n */\nexport const normalize: (vector: Vector2) => Vector2 = internal.normalize\n\nexport const dot: {\n /**\n * Calculates the dot product of two `Vector2` instances.\n *\n * @param a - The first vector.\n * @param b - The second vector.\n * @returns The dot product of the two vectors.\n * @since 1.0.0\n */\n (a: Vector2, b: Vector2): number\n /**\n * Calculates the dot product of two `Vector2` instances.\n *\n * @param b - The second vector.\n * @returns A function that takes the first vector and returns the dot product.\n * @since 1.0.0\n */\n (b: Vector2): (a: Vector2) => number\n} = internal.dot\n\nexport const cross: {\n /**\n * Calculates the cross product of two `Vector2` instances.\n *\n * @param a - The first vector.\n * @param b - The second vector.\n * @returns The cross product of the two vectors.\n * @since 1.0.0\n */\n (a: Vector2, b: Vector2): number\n /**\n * Calculates the cross product of two `Vector2` instances.\n *\n * @param b - The second vector.\n * @returns A function that takes the first vector and returns the cross product.\n * @since 1.0.0\n */\n (b: Vector2): (a: Vector2) => number\n} = internal.cross\n\n/**\n * Returns the components of a `Vector2` as an array.\n *\n * @param r - The radius.\n * @param theta - The angle, in radians.\n * @returns A new `Vector2` instance.\n * @since 1.0.0\n */\nexport const components: (v: Vector2) => [number, number] = internal.components\n\n/**\n * Applies the softmax function to a `Vector2`.\n *\n * @param v - The vector to apply the softmax function to.\n * @returns A new `Vector2` instance with the softmax applied.\n * @since 1.0.0\n */\nexport const softmax: (v: Vector2) => Vector2 = internal.softmax\n\n/**\n * Creates a zero vector.\n *\n * @returns A new `Vector2` instance with both components set to 0.\n * @since 1.0.0\n */\nexport const zero = make(0)\n\n/**\n * Creates a unit vector.\n *\n * @returns A new `Vector2` instance with both components set to 1.\n * @since 1.0.0\n */\nexport const unit = make(1)\n\nexport const add: {\n /**\n * Adds two `Vector2` instances together.\n *\n * @param a - The first vector.\n * @param b - The second vector.\n * @returns A new `Vector2` instance representing the sum of the two vectors.\n * @since 1.0.0\n */\n (a: Vector2, b: Vector2): Vector2\n /**\n * Adds two `Vector2` instances together.\n *\n * @param b - The second vector.\n * @returns A function that takes the first vector and returns the sum.\n * @since 1.0.0\n */\n (b: Vector2): (a: Vector2) => Vector2\n} = internal.add\n\nexport const subtract: {\n /**\n * Subtracts one `Vector2` instance from another.\n *\n * @param a - The first vector.\n * @param b - The second vector.\n * @returns A new `Vector2` instance representing the difference of the two vectors.\n * @since 1.0.0\n */\n (a: Vector2, b: Vector2): Vector2\n /**\n * Subtracts one `Vector2` instance from another.\n *\n * @param b - The second vector.\n * @returns A function that takes the first vector and returns the difference.\n * @since 1.0.0\n */\n (b: Vector2): (a: Vector2) => Vector2\n} = internal.subtract\n\nexport const hadamard: {\n /**\n * Performs the Hadamard product of two `Vector2` instances.\n *\n * @param a - The first vector.\n * @param b - The second vector.\n * @returns A new `Vector2` instance representing the Hadamard product of the two vectors.\n * @since 1.0.0\n */\n (a: Vector2, b: Vector2): Vector2\n /**\n * Performs the Hadamard product of two `Vector2` instances.\n *\n * @param b - The second vector.\n * @returns A function that takes the first vector and returns the Hadamard product.\n * @since 1.0.0\n */\n (b: Vector2): (a: Vector2) => Vector2\n} = internal.hadamard\n\nexport const scale: {\n /**\n * Scales a `Vector2` by a scalar value.\n *\n * @param s - The scalar value to scale by.\n * @returns A function that takes a vector and returns the scaled vector.\n * @since 1.0.0\n */\n (s: number): (v: Vector2) => Vector2\n /**\n * Scales a `Vector2` by a scalar value.\n *\n * @param v - The vector to scale.\n * @param s - The scalar value to scale by.\n * @returns A new `Vector2` instance representing the scaled vector.\n * @since 1.0.0\n */\n (v: Vector2, s: number): Vector2\n} = internal.scale\n\n/**\n * Gets the x component of a `Vector2`.\n *\n * @param v - The vector to get the x component from.\n * @returns The x component of the vector.\n * @since 1.0.0\n */\nexport const getX: (v: Vector2) => number = internal.getX\n\nexport const setX: {\n /**\n * Sets the x component of a `Vector2`.\n *\n * @param v - The vector to set the x component of.\n * @param x - The new x component.\n * @returns A new `Vector2` instance with the updated x component.\n * @since 1.0.0\n */\n (v: Vector2, x: number): Vector2\n /**\n * Sets the x component of a `Vector2`.\n *\n * @param x - The new x component.\n * @returns A function that takes a vector and returns the updated vector.\n * @since 1.0.0\n */\n (x: number): (v: Vector2) => Vector2\n} = internal.setX\n\n/**\n * Gets the y component of a `Vector2`.\n *\n * @param v - The vector to get the y component from.\n * @returns The y component of the vector.\n * @since 1.0.0\n */\nexport const getY: (v: Vector2) => number = internal.getY\n\nexport const setY: {\n /**\n * Sets the y component of a `Vector2`.\n *\n * @param v - The vector to set the y component of.\n * @param y - The new y component.\n * @returns A new `Vector2` instance with the updated y component.\n * @since 1.0.0\n */\n (v: Vector2, y: number): Vector2\n /**\n * Sets the y component of a `Vector2`.\n *\n * @param y - The new y component.\n * @returns A function that takes a vector and returns the updated vector.\n * @since 1.0.0\n */\n (y: number): (v: Vector2) => Vector2\n} = internal.setY\n\n/**\n * Gets the radius of a `Vector2`.\n *\n * @param v - The vector to get the radius from.\n * @returns The radius of the vector.\n * @since 1.0.0\n */\nexport const getR: (v: Vector2) => number = magnitude\n\nexport const setR: {\n /**\n * Sets the radius of a `Vector2`.\n *\n * @param v - The vector to set the radius of.\n * @param r - The new radius.\n * @returns A new `Vector2` instance with the updated radius.\n * @since 1.0.0\n */\n (v: Vector2, r: number): Vector2\n /**\n * Sets the radius of a `Vector2`.\n *\n * @param r - The new radius.\n * @returns A function that takes a vector and returns the updated vector.\n * @since 1.0.0\n */\n (r: number): (v: Vector2) => Vector2\n} = internal.setR\n\n/**\n * Gets the angle of a `Vector2`.\n *\n * @param v - The vector to get the angle from.\n * @returns The angle of the vector in radians.\n * @since 1.0.0\n */\nexport const getTheta: (v: Vector2) => number = internal.getTheta\n\nexport const setTheta: {\n /**\n * Sets the angle of a `Vector2`.\n *\n * @param v - The vector to set the angle of.\n * @param theta - The new angle, in radians.\n * @returns A new `Vector2` instance with the updated angle.\n * @since 1.0.0\n */\n (v: Vector2, theta: number): Vector2\n /**\n * Sets the angle of a `Vector2`.\n *\n * @param theta - The new angle, in radians.\n * @returns A function that takes a vector and returns the updated vector.\n * @since 1.0.0\n */\n (theta: number): (v: Vector2) => Vector2\n} = internal.setTheta\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,MAAa,YAA0CA;;;;;;;;AASvD,MAAa,aAA4CC;;;;;;;;;;;AAYzD,MAAa,eACXC;AAEF,MAAa,aAoBTC;;;;;;;;AASJ,MAAa,aAAuCC;AAEpD,MAAa,iBAmBTC;AAEJ,MAAa,SAoBTC;AAEJ,MAAa,OAkBTC;;;;;;;;;;;AAYJ,MAAa,YAGsCC;;;;;;;;;AAUnD,MAAa,YAAmDC;;;;;;;;AAShE,MAAa,YAAyCC;;;;;;;;AAStD,MAAa,YAA0CC;AAEvD,MAAa,MAkBTC;AAEJ,MAAa,QAkBTC;;;;;;;;;AAUJ,MAAa,aAA+CC;;;;;;;;AAS5D,MAAa,UAAmCC;;;;;;;AAQhD,MAAa,OAAO,KAAK,EAAE;;;;;;;AAQ3B,MAAa,OAAO,KAAK,EAAE;AAE3B,MAAa,MAkBTC;AAEJ,MAAa,WAkBTC;AAEJ,MAAa,WAkBTC;AAEJ,MAAa,QAkBTC;;;;;;;;AASJ,MAAa,OAA+BC;AAE5C,MAAa,OAkBTC;;;;;;;;AASJ,MAAa,OAA+BC;AAE5C,MAAa,OAkBTC;;;;;;;;AASJ,MAAa,OAA+B;AAE5C,MAAa,OAkBTC;;;;;;;;AASJ,MAAa,WAAmCC;AAEhD,MAAa,WAkBTC"}
1
+ {"version":3,"file":"vector2-CCuJx1rX.mjs","names":["internal.isVector2","internal.isWeighted","internal.makeWeighted","internal.withWeight","internal.unweighted","internal.weightedEquals","internal.equals","internal.make","internal.transpose","internal.fromPolar","internal.magnitude","internal.normalize","internal.dot","internal.cross","internal.components","internal.softmax","internal.add","internal.subtract","internal.hadamard","internal.scale","internal.getX","internal.setX","internal.getY","internal.setY","internal.setR","internal.getTheta","internal.setTheta"],"sources":["../../src/vector/vector2.ts"],"sourcesContent":["import type { TwoDimensional } from '../dimensions'\nimport type { Pipeable } from '../utils'\nimport type { Vector2TypeId, WeightedVector2TypeId } from './vector2.internal'\nimport * as internal from './vector2.internal'\n\n/**\n * A 2D vector.\n *\n * All fields are readonly and immutable, and all operations create new instances.\n *\n * @since 1.0.0\n */\nexport interface Vector2 extends Pipeable, TwoDimensional<number> {\n readonly [Vector2TypeId]: Vector2TypeId\n}\n\n/**\n * A 2D point with an associated positive scalar weight.\n *\n * Used by rational primitives (e.g. `RationalBezier2d`) where each control\n * point carries an influence weight. The interface is structurally distinct\n * from `Vector2` — its brand prevents accidental use with vector arithmetic\n * (`add`, `subtract`, `scale`, etc.) where weighted operations are not\n * well-defined.\n *\n * Construct via {@link makeWeighted} (from raw components) or\n * {@link withWeight} (from an existing `Vector2`).\n *\n * @since 2.0.0\n */\nexport interface Weighted extends Pipeable {\n readonly [WeightedVector2TypeId]: WeightedVector2TypeId\n readonly x: number\n readonly y: number\n readonly weight: number\n}\n\n/**\n * Checks if a value is a `Vector2`.\n *\n * @param v - The value to check.\n * @returns `true` if the value is a `Vector2`, `false` otherwise.\n * @since 1.0.0\n */\nexport const isVector2: (v: unknown) => v is Vector2 = internal.isVector2\n\n/**\n * Checks if a value is a `Vector2.Weighted`.\n *\n * @param v - The value to check.\n * @returns `true` if the value is a `Vector2.Weighted`, `false` otherwise.\n * @since 2.0.0\n */\nexport const isWeighted: (v: unknown) => v is Weighted = internal.isWeighted\n\n/**\n * Creates a new `Vector2.Weighted` from raw components. The weight must be\n * finite and positive.\n *\n * @param x - The x component.\n * @param y - The y component.\n * @param weight - The positive scalar weight.\n * @returns A new `Vector2.Weighted` instance.\n * @since 2.0.0\n */\nexport const makeWeighted: (x: number, y: number, weight: number) => Weighted =\n internal.makeWeighted\n\nexport const withWeight: {\n /**\n * Promotes a `Vector2` to a `Vector2.Weighted` by attaching the given\n * positive scalar weight.\n *\n * @param v - The point to weight.\n * @param weight - The positive scalar weight.\n * @returns A new `Vector2.Weighted` instance.\n * @since 2.0.0\n */\n (v: Vector2, weight: number): Weighted\n /**\n * Promotes a `Vector2` to a `Vector2.Weighted` by attaching the given\n * positive scalar weight.\n *\n * @param weight - The positive scalar weight.\n * @returns A function that takes a `Vector2` and returns a weighted point.\n * @since 2.0.0\n */\n (weight: number): (v: Vector2) => Weighted\n} = internal.withWeight\n\n/**\n * Strips the weight from a `Vector2.Weighted`, returning the underlying point.\n *\n * @param w - The weighted point.\n * @returns A new `Vector2` instance with the same x and y components.\n * @since 2.0.0\n */\nexport const unweighted: (w: Weighted) => Vector2 = internal.unweighted\n\nexport const weightedEquals: {\n /**\n * Checks if two `Vector2.Weighted` instances are approximately equal —\n * point components and weight all within the default absolute tolerance.\n *\n * @param a - The first weighted point.\n * @param b - The second weighted point.\n * @returns `true` when components and weight are within tolerance.\n * @since 2.0.0\n */\n (a: Weighted, b: Weighted): boolean\n /**\n * Checks if two `Vector2.Weighted` instances are approximately equal.\n *\n * @param b - The second weighted point.\n * @returns A function that takes the first weighted point and returns the comparison result.\n * @since 2.0.0\n */\n (b: Weighted): (a: Weighted) => boolean\n} = internal.weightedEquals\n\nexport const equals: {\n /**\n * Checks if two `Vector2` instances are approximately equal within the\n * default absolute tolerance ({@link EPSILON}).\n *\n * @param a - The first vector.\n * @param b - The second vector.\n * @returns `true` when each pair of components is within tolerance.\n * @since 1.1.0\n */\n (a: Vector2, b: Vector2): boolean\n /**\n * Checks if two `Vector2` instances are approximately equal within the\n * default absolute tolerance ({@link EPSILON}).\n *\n * @param b - The second vector.\n * @returns A function that takes the first vector and returns the comparison result.\n * @since 1.1.0\n */\n (b: Vector2): (a: Vector2) => boolean\n} = internal.equals\n\nexport const make: {\n /**\n * Creates a new `Vector2` instance.\n *\n * @param xy - The x and y components of the vector.\n * @returns A new `Vector2` instance.\n * @since 1.0.0\n */\n (xy: number): Vector2\n /**\n * Creates a new `Vector2` instance.\n *\n * @param x - The x component of the vector.\n * @param y - The y component of the vector.\n * @returns A new `Vector2` instance.\n * @since 1.0.0\n */\n (x: number, y: number): Vector2\n} = internal.make\n\n/**\n * Transposes a 2-tuple of items into one or more `Vector2`s, one per channel\n * extracted by the projection function. See {@link Vector4.transpose} for the\n * full operation description; this is the 2-component analog.\n *\n * @param inputs - Exactly two items of any type.\n * @param project - A function returning a fixed-arity tuple of numbers — one per output channel.\n * @returns A tuple of `Vector2`s with the same arity as the projection's return tuple.\n * @since 2.0.0\n */\nexport const transpose: <T, const Channels extends ReadonlyArray<number>>(\n inputs: readonly [T, T],\n project: (item: T) => Channels,\n) => { readonly [K in keyof Channels]: Vector2 } = internal.transpose\n\n/**\n * Creates a new `Vector2` instance from polar coordinates.\n *\n * @param r - The radius.\n * @param theta - The angle, in radians.\n * @returns A new `Vector2` instance.\n * @since 1.0.0\n */\nexport const fromPolar: (r: number, theta: number) => Vector2 = internal.fromPolar\n\n/**\n * Calculates the magnitude of a `Vector2`.\n *\n * @param vector - The vector to calculate the magnitude of.\n * @returns The magnitude of the vector.\n * @since 1.0.0\n */\nexport const magnitude: (vector: Vector2) => number = internal.magnitude\n\n/**\n * Normalizes a `Vector2`.\n *\n * @param vector - The vector to normalize.\n * @returns A new `Vector2` instance with the same direction and a magnitude of 1.\n * @since 1.0.0\n */\nexport const normalize: (vector: Vector2) => Vector2 = internal.normalize\n\nexport const dot: {\n /**\n * Calculates the dot product of two `Vector2` instances.\n *\n * @param a - The first vector.\n * @param b - The second vector.\n * @returns The dot product of the two vectors.\n * @since 1.0.0\n */\n (a: Vector2, b: Vector2): number\n /**\n * Calculates the dot product of two `Vector2` instances.\n *\n * @param b - The second vector.\n * @returns A function that takes the first vector and returns the dot product.\n * @since 1.0.0\n */\n (b: Vector2): (a: Vector2) => number\n} = internal.dot\n\nexport const cross: {\n /**\n * Calculates the cross product of two `Vector2` instances.\n *\n * @param a - The first vector.\n * @param b - The second vector.\n * @returns The cross product of the two vectors.\n * @since 1.0.0\n */\n (a: Vector2, b: Vector2): number\n /**\n * Calculates the cross product of two `Vector2` instances.\n *\n * @param b - The second vector.\n * @returns A function that takes the first vector and returns the cross product.\n * @since 1.0.0\n */\n (b: Vector2): (a: Vector2) => number\n} = internal.cross\n\n/**\n * Returns the components of a `Vector2` as an array.\n *\n * @param r - The radius.\n * @param theta - The angle, in radians.\n * @returns A new `Vector2` instance.\n * @since 1.0.0\n */\nexport const components: (v: Vector2) => [number, number] = internal.components\n\n/**\n * Applies the softmax function to a `Vector2`.\n *\n * @param v - The vector to apply the softmax function to.\n * @returns A new `Vector2` instance with the softmax applied.\n * @since 1.0.0\n */\nexport const softmax: (v: Vector2) => Vector2 = internal.softmax\n\n/**\n * Creates a zero vector.\n *\n * @returns A new `Vector2` instance with both components set to 0.\n * @since 1.0.0\n */\nexport const zero = make(0)\n\n/**\n * Creates a unit vector.\n *\n * @returns A new `Vector2` instance with both components set to 1.\n * @since 1.0.0\n */\nexport const unit = make(1)\n\nexport const add: {\n /**\n * Adds two `Vector2` instances together.\n *\n * @param a - The first vector.\n * @param b - The second vector.\n * @returns A new `Vector2` instance representing the sum of the two vectors.\n * @since 1.0.0\n */\n (a: Vector2, b: Vector2): Vector2\n /**\n * Adds two `Vector2` instances together.\n *\n * @param b - The second vector.\n * @returns A function that takes the first vector and returns the sum.\n * @since 1.0.0\n */\n (b: Vector2): (a: Vector2) => Vector2\n} = internal.add\n\nexport const subtract: {\n /**\n * Subtracts one `Vector2` instance from another.\n *\n * @param a - The first vector.\n * @param b - The second vector.\n * @returns A new `Vector2` instance representing the difference of the two vectors.\n * @since 1.0.0\n */\n (a: Vector2, b: Vector2): Vector2\n /**\n * Subtracts one `Vector2` instance from another.\n *\n * @param b - The second vector.\n * @returns A function that takes the first vector and returns the difference.\n * @since 1.0.0\n */\n (b: Vector2): (a: Vector2) => Vector2\n} = internal.subtract\n\nexport const hadamard: {\n /**\n * Performs the Hadamard product of two `Vector2` instances.\n *\n * @param a - The first vector.\n * @param b - The second vector.\n * @returns A new `Vector2` instance representing the Hadamard product of the two vectors.\n * @since 1.0.0\n */\n (a: Vector2, b: Vector2): Vector2\n /**\n * Performs the Hadamard product of two `Vector2` instances.\n *\n * @param b - The second vector.\n * @returns A function that takes the first vector and returns the Hadamard product.\n * @since 1.0.0\n */\n (b: Vector2): (a: Vector2) => Vector2\n} = internal.hadamard\n\nexport const scale: {\n /**\n * Scales a `Vector2` by a scalar value.\n *\n * @param s - The scalar value to scale by.\n * @returns A function that takes a vector and returns the scaled vector.\n * @since 1.0.0\n */\n (s: number): (v: Vector2) => Vector2\n /**\n * Scales a `Vector2` by a scalar value.\n *\n * @param v - The vector to scale.\n * @param s - The scalar value to scale by.\n * @returns A new `Vector2` instance representing the scaled vector.\n * @since 1.0.0\n */\n (v: Vector2, s: number): Vector2\n} = internal.scale\n\n/**\n * Gets the x component of a `Vector2`.\n *\n * @param v - The vector to get the x component from.\n * @returns The x component of the vector.\n * @since 1.0.0\n */\nexport const getX: (v: Vector2) => number = internal.getX\n\nexport const setX: {\n /**\n * Sets the x component of a `Vector2`.\n *\n * @param v - The vector to set the x component of.\n * @param x - The new x component.\n * @returns A new `Vector2` instance with the updated x component.\n * @since 1.0.0\n */\n (v: Vector2, x: number): Vector2\n /**\n * Sets the x component of a `Vector2`.\n *\n * @param x - The new x component.\n * @returns A function that takes a vector and returns the updated vector.\n * @since 1.0.0\n */\n (x: number): (v: Vector2) => Vector2\n} = internal.setX\n\n/**\n * Gets the y component of a `Vector2`.\n *\n * @param v - The vector to get the y component from.\n * @returns The y component of the vector.\n * @since 1.0.0\n */\nexport const getY: (v: Vector2) => number = internal.getY\n\nexport const setY: {\n /**\n * Sets the y component of a `Vector2`.\n *\n * @param v - The vector to set the y component of.\n * @param y - The new y component.\n * @returns A new `Vector2` instance with the updated y component.\n * @since 1.0.0\n */\n (v: Vector2, y: number): Vector2\n /**\n * Sets the y component of a `Vector2`.\n *\n * @param y - The new y component.\n * @returns A function that takes a vector and returns the updated vector.\n * @since 1.0.0\n */\n (y: number): (v: Vector2) => Vector2\n} = internal.setY\n\n/**\n * Gets the radius of a `Vector2`.\n *\n * @param v - The vector to get the radius from.\n * @returns The radius of the vector.\n * @since 1.0.0\n */\nexport const getR: (v: Vector2) => number = magnitude\n\nexport const setR: {\n /**\n * Sets the radius of a `Vector2`.\n *\n * @param v - The vector to set the radius of.\n * @param r - The new radius.\n * @returns A new `Vector2` instance with the updated radius.\n * @since 1.0.0\n */\n (v: Vector2, r: number): Vector2\n /**\n * Sets the radius of a `Vector2`.\n *\n * @param r - The new radius.\n * @returns A function that takes a vector and returns the updated vector.\n * @since 1.0.0\n */\n (r: number): (v: Vector2) => Vector2\n} = internal.setR\n\n/**\n * Gets the angle of a `Vector2`.\n *\n * @param v - The vector to get the angle from.\n * @returns The angle of the vector in radians.\n * @since 1.0.0\n */\nexport const getTheta: (v: Vector2) => number = internal.getTheta\n\nexport const setTheta: {\n /**\n * Sets the angle of a `Vector2`.\n *\n * @param v - The vector to set the angle of.\n * @param theta - The new angle, in radians.\n * @returns A new `Vector2` instance with the updated angle.\n * @since 1.0.0\n */\n (v: Vector2, theta: number): Vector2\n /**\n * Sets the angle of a `Vector2`.\n *\n * @param theta - The new angle, in radians.\n * @returns A function that takes a vector and returns the updated vector.\n * @since 1.0.0\n */\n (theta: number): (v: Vector2) => Vector2\n} = internal.setTheta\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,MAAa,YAA0CA;;;;;;;;AASvD,MAAa,aAA4CC;;;;;;;;;;;AAYzD,MAAa,eACXC;AAEF,MAAa,aAoBTC;;;;;;;;AASJ,MAAa,aAAuCC;AAEpD,MAAa,iBAmBTC;AAEJ,MAAa,SAoBTC;AAEJ,MAAa,OAkBTC;;;;;;;;;;;AAYJ,MAAa,YAGsCC;;;;;;;;;AAUnD,MAAa,YAAmDC;;;;;;;;AAShE,MAAa,YAAyCC;;;;;;;;AAStD,MAAa,YAA0CC;AAEvD,MAAa,MAkBTC;AAEJ,MAAa,QAkBTC;;;;;;;;;AAUJ,MAAa,aAA+CC;;;;;;;;AAS5D,MAAa,UAAmCC;;;;;;;AAQhD,MAAa,OAAO,KAAK,EAAE;;;;;;;AAQ3B,MAAa,OAAO,KAAK,EAAE;AAE3B,MAAa,MAkBTC;AAEJ,MAAa,WAkBTC;AAEJ,MAAa,WAkBTC;AAEJ,MAAa,QAkBTC;;;;;;;;AASJ,MAAa,OAA+BC;AAE5C,MAAa,OAkBTC;;;;;;;;AASJ,MAAa,OAA+BC;AAE5C,MAAa,OAkBTC;;;;;;;;AASJ,MAAa,OAA+B;AAE5C,MAAa,OAkBTC;;;;;;;;AASJ,MAAa,WAAmCC;AAEhD,MAAa,WAkBTC"}
@@ -0,0 +1,58 @@
1
+ import { t as Pipeable } from "./utils-MCckigYk.mjs";
2
+
3
+ //#region src/dimensions.d.ts
4
+ interface TwoDimensional<out T1, out T2 = T1> {
5
+ readonly x: T1;
6
+ readonly y: T2;
7
+ readonly 0: T1;
8
+ readonly 1: T2;
9
+ }
10
+ interface ThreeDimensional<out T1, out T2 = T1, out T3 = T2> extends TwoDimensional<T1, T2> {
11
+ readonly z: T3;
12
+ readonly 2: T3;
13
+ }
14
+ interface FourDimensional<out T1, out T2 = T1, out T3 = T2, out T4 = T3> extends ThreeDimensional<T1, T2, T3> {
15
+ readonly w: T4;
16
+ readonly 3: T4;
17
+ }
18
+ //#endregion
19
+ //#region src/vector/vector2.internal.d.ts
20
+ declare const Vector2TypeId: unique symbol;
21
+ type Vector2TypeId = typeof Vector2TypeId;
22
+ declare const WeightedVector2TypeId: unique symbol;
23
+ type WeightedVector2TypeId = typeof WeightedVector2TypeId;
24
+ //#endregion
25
+ //#region src/vector/vector2.d.ts
26
+ /**
27
+ * A 2D vector.
28
+ *
29
+ * All fields are readonly and immutable, and all operations create new instances.
30
+ *
31
+ * @since 1.0.0
32
+ */
33
+ interface Vector2 extends Pipeable, TwoDimensional<number> {
34
+ readonly [Vector2TypeId]: Vector2TypeId;
35
+ }
36
+ /**
37
+ * A 2D point with an associated positive scalar weight.
38
+ *
39
+ * Used by rational primitives (e.g. `RationalBezier2d`) where each control
40
+ * point carries an influence weight. The interface is structurally distinct
41
+ * from `Vector2` — its brand prevents accidental use with vector arithmetic
42
+ * (`add`, `subtract`, `scale`, etc.) where weighted operations are not
43
+ * well-defined.
44
+ *
45
+ * Construct via {@link makeWeighted} (from raw components) or
46
+ * {@link withWeight} (from an existing `Vector2`).
47
+ *
48
+ * @since 2.0.0
49
+ */
50
+ interface Weighted extends Pipeable {
51
+ readonly [WeightedVector2TypeId]: WeightedVector2TypeId;
52
+ readonly x: number;
53
+ readonly y: number;
54
+ readonly weight: number;
55
+ }
56
+ //#endregion
57
+ export { TwoDimensional as a, ThreeDimensional as i, Weighted as n, FourDimensional as r, Vector2 as t };
58
+ //# sourceMappingURL=vector2-euuV_bNQ.d.mts.map
@@ -0,0 +1,37 @@
1
+ import { i as ThreeDimensional, r as FourDimensional } from "./vector2-euuV_bNQ.mjs";
2
+ import { t as Pipeable } from "./utils-MCckigYk.mjs";
3
+
4
+ //#region src/vector/vector4.internal.d.ts
5
+ declare const Vector4TypeId: unique symbol;
6
+ type Vector4TypeId = typeof Vector4TypeId;
7
+ //#endregion
8
+ //#region src/vector/vector4.d.ts
9
+ /**
10
+ * A 4D vector.
11
+ *
12
+ * All fields are readonly and immutable, and all operations create new instances.
13
+ *
14
+ * @since 1.0.0
15
+ */
16
+ interface Vector4 extends Pipeable, FourDimensional<number> {
17
+ readonly [Vector4TypeId]: Vector4TypeId;
18
+ }
19
+ //#endregion
20
+ //#region src/vector/vector3.internal.d.ts
21
+ declare const Vector3TypeId: unique symbol;
22
+ type Vector3TypeId = typeof Vector3TypeId;
23
+ //#endregion
24
+ //#region src/vector/vector3.d.ts
25
+ /**
26
+ * A 3D vector.
27
+ *
28
+ * All fields are readonly and immutable, and all operations create new instances.
29
+ *
30
+ * @since 1.0.0
31
+ */
32
+ interface Vector3 extends Pipeable, ThreeDimensional<number> {
33
+ readonly [Vector3TypeId]: Vector3TypeId;
34
+ }
35
+ //#endregion
36
+ export { Vector4 as n, Vector3 as t };
37
+ //# sourceMappingURL=vector3-3Xx7GVk7.d.mts.map
@@ -54,7 +54,7 @@ const make = make$1;
54
54
  * @param inputs - Exactly three items of any type.
55
55
  * @param project - A function returning a fixed-arity tuple of numbers — one per output channel.
56
56
  * @returns A tuple of `Vector3`s with the same arity as the projection's return tuple.
57
- * @since 2.1.0
57
+ * @since 2.0.0
58
58
  */
59
59
  const transpose = transpose$1;
60
60
  /**
@@ -201,4 +201,4 @@ const setPhi = setPhi$1;
201
201
  //#endregion
202
202
  export { vector3_exports as n, make as t };
203
203
 
204
- //# sourceMappingURL=vector3-D-tv_aKL.mjs.map
204
+ //# sourceMappingURL=vector3-C-qgKAjR.mjs.map