{"version":3,"file":"rationalCubic2d-H1J2Fjyy.mjs","names":["isLinearPath2d","make","fromArray","append","length","LinearCurve2d.length","Interval.unit","solve","LinearCurve2d.solve","toPathData","isContinuous","asContinuous","isIncreasingX","LinearPolynomial.isIncreasing","isDecreasingX","LinearPolynomial.isDecreasing","isMonotonicX","isIncreasingY","isDecreasingY","isMonotonicY","asIncreasingX","asDecreasingX","asMonotonicX","asIncreasingY","asDecreasingY","asMonotonicY","solveAtX","Solution.one","LinearCurve2d.solveAtX","Solution.isNone","Solution.none","solveAtY","LinearCurve2d.solveAtY","boundingBox","LinearCurve2d.boundingBox","Interval2d.union","make","internal.make","fromArray","internal.fromArray","internal.isLinearPath2d","append","internal.append","length","internal.length","solve","internal.solve","toPathData","internal.toPathData","isContinuous","internal.isContinuous","asContinuous","internal.asContinuous","isIncreasingX","internal.isIncreasingX","isDecreasingX","internal.isDecreasingX","isMonotonicX","internal.isMonotonicX","isIncreasingY","internal.isIncreasingY","isDecreasingY","internal.isDecreasingY","isMonotonicY","internal.isMonotonicY","asIncreasingX","internal.asIncreasingX","asDecreasingX","internal.asDecreasingX","asMonotonicX","internal.asMonotonicX","asIncreasingY","internal.asIncreasingY","asDecreasingY","internal.asDecreasingY","asMonotonicY","internal.asMonotonicY","solveAtX","internal.solveAtX","solveAtY","internal.solveAtY","boundingBox","internal.boundingBox","isCubicPath2d","make","fromArray","append","length","CubicCurve2d.length","Interval.unit","solve","CubicCurve2d.solve","derivative","cubicCurveInternal.derivative","Interval.make","Vector2.magnitude","QuadraticCurve2d.solve","toPathData","isContinuous","asContinuous","isIncreasingX","CubicPolynomial.isIncreasing","isDecreasingX","CubicPolynomial.isDecreasing","isMonotonicX","isIncreasingY","isDecreasingY","isMonotonicY","asIncreasingX","asDecreasingX","asMonotonicX","asIncreasingY","asDecreasingY","asMonotonicY","solveAtX","Solution.one","CubicCurve2d.solveAtX","Solution.isNone","Solution.none","solveAtY","CubicCurve2d.solveAtY","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.isIncreasingX","internal.isDecreasingX","internal.isMonotonicX","internal.isIncreasingY","internal.isDecreasingY","internal.isMonotonicY","internal.asIncreasingX","internal.asDecreasingX","internal.asMonotonicX","internal.asIncreasingY","internal.asDecreasingY","internal.asMonotonicY","internal.solveAtX","internal.solveAtY","internal.solveByDistance","boundingBox","internal.boundingBox","isRationalCubicPath2d","make","fromArray","append","solve","RationalCubicCurve2d.solve","boundingBox","RationalCubicCurve2d.boundingBox","Interval2d.union","approximateAsCubicPath","RationalCubicCurve2d.approximateAsCubicCurves","CubicPath2d.fromArray","internal.isRationalCubicPath2d","internal.make","internal.fromArray","internal.append","internal.solve","internal.boundingBox","internal.approximateAsCubicPath"],"sources":["../../src/path/linear2d.internal.ts","../../src/path/linear2d.ts","../../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.ts'\nimport * as LinearCurve2d from '../curve/linear2d.ts'\nimport * as Interval from '../interval/interval.ts'\nimport * as LinearPolynomial from '../polynomial/linear.ts'\nimport * as Solution from '../solution/solution.ts'\nimport { dual, Pipeable } from '../utils.ts'\nimport { invariant } from '../utils.ts'\nimport { EPSILON, epsEquals } from '../number.ts'\nimport type { Vector2 } from '../vector/vector2.ts'\nimport type { LinearPath2d } from './linear2d.ts'\nimport {\n  PathTraits,\n  type Continuous,\n  type DecreasingX,\n  type DecreasingY,\n  type IncreasingX,\n  type IncreasingY,\n  type MonotonicX,\n  type MonotonicY,\n} from './traits.ts'\n\nexport const LinearPath2dTypeId: unique symbol = Symbol('curvy/path/linear2d')\nexport type LinearPath2dTypeId = typeof LinearPath2dTypeId\n\n/** @internal */\nexport class LinearPath2dImpl extends Pipeable implements LinearPath2d<unknown> {\n  readonly [LinearPath2dTypeId]: LinearPath2dTypeId = LinearPath2dTypeId\n  declare readonly [PathTraits]: unknown\n\n  readonly curves: ReadonlyArray<LinearCurve2d.LinearCurve2d>\n\n  constructor(curves: ReadonlyArray<LinearCurve2d.LinearCurve2d>) {\n    super()\n    this.curves = curves\n  }\n\n  [Symbol.iterator](): Iterator<LinearCurve2d.LinearCurve2d> {\n    return this.curves[Symbol.iterator]()\n  }\n}\n\n/** @internal */\nexport const isLinearPath2d = (p: unknown): p is LinearPath2d =>\n  typeof p === 'object' && p !== null && LinearPath2dTypeId in p\n\n/** @internal */\nexport const make = (...curves: ReadonlyArray<LinearCurve2d.LinearCurve2d>): LinearPath2d =>\n  new LinearPath2dImpl(curves)\n\n/** @internal */\nexport const fromArray = (curves: ReadonlyArray<LinearCurve2d.LinearCurve2d>) =>\n  new LinearPath2dImpl(curves)\n\n/** @internal */\nexport const append = dual<\n  (c: LinearCurve2d.LinearCurve2d) => (p: LinearPath2d) => LinearPath2d,\n  (p: LinearPath2d, c: LinearCurve2d.LinearCurve2d) => LinearPath2d\n>(2, (p: LinearPath2d, c: LinearCurve2d.LinearCurve2d) => fromArray([...p, c]))\n\n/** @internal */\nexport const length = (p: LinearPath2d) => {\n  let total = 0\n  for (const curve of p) {\n    total += LinearCurve2d.length(curve, Interval.unit)\n  }\n\n  return total\n}\n\n/** @internal */\nexport const solve = dual<\n  (u: number) => (p: LinearPath2d) => Vector2,\n  (p: LinearPath2d, u: number) => Vector2\n>(2, (p: LinearPath2d, u: number) => {\n  const curves = p instanceof LinearPath2dImpl ? p.curves : [...p]\n\n  if (u === 1) {\n    const last = curves.at(-1) as LinearCurve2d.LinearCurve2d\n    return LinearCurve2d.solve(last, 1)\n  }\n\n  const t = u * curves.length\n  const i = Math.floor(t)\n  const curve = curves[i] as LinearCurve2d.LinearCurve2d\n  return LinearCurve2d.solve(curve, t - i)\n})\n\n/** @internal */\nexport const toPathData = (p: LinearPath2d): string => {\n  let result = ''\n  let prevEndX = Number.NaN\n  let prevEndY = Number.NaN\n\n  for (const curve of p) {\n    const startX = curve.x.c0\n    const startY = curve.y.c0\n    const endX = curve.x.c0 + curve.x.c1\n    const endY = curve.y.c0 + curve.y.c1\n\n    if (!epsEquals(startX, prevEndX) || !epsEquals(startY, prevEndY)) {\n      result += ` M ${startX},${startY}`\n    }\n    result += ` L ${endX},${endY}`\n\n    prevEndX = endX\n    prevEndY = endY\n  }\n\n  return result.slice(1)\n}\n\n/** @internal */\nexport const isContinuous = <T>(p: LinearPath2d<T>): p is LinearPath2d<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\n    prevEndY = curve.y.c0 + curve.y.c1\n    first = false\n  }\n  return true\n}\n\n/** @internal */\nexport const asContinuous = <T>(p: LinearPath2d<T>): LinearPath2d<T & Continuous> => {\n  invariant(isContinuous(p), 'linear path is not continuous')\n  return p\n}\n\n// Per-axis monotonicity refiners. A path is monotonic-on-an-axis when every\n// segment's per-axis polynomial is strictly monotonic in the same direction\n// AND adjacent segments' ranges on that axis don't overlap (modulo float\n// tolerance) — so the path's u → axis mapping is monotonic across joins.\n\n/** @internal */\nexport const isIncreasingX = <T>(p: LinearPath2d<T>): p is LinearPath2d<T & IncreasingX> => {\n  let prevEnd = Number.NEGATIVE_INFINITY\n  for (const c of p) {\n    if (!LinearPolynomial.isIncreasing(c.x)) {\n      return false\n    }\n    if (c.x.c0 < prevEnd - EPSILON) {\n      return false\n    }\n    prevEnd = c.x.c0 + c.x.c1\n  }\n  return true\n}\n\n/** @internal */\nexport const isDecreasingX = <T>(p: LinearPath2d<T>): p is LinearPath2d<T & DecreasingX> => {\n  let prevEnd = Number.POSITIVE_INFINITY\n  for (const c of p) {\n    if (!LinearPolynomial.isDecreasing(c.x)) {\n      return false\n    }\n    if (c.x.c0 > prevEnd + EPSILON) {\n      return false\n    }\n    prevEnd = c.x.c0 + c.x.c1\n  }\n  return true\n}\n\n/** @internal */\nexport const isMonotonicX = <T>(p: LinearPath2d<T>): p is LinearPath2d<T & MonotonicX> =>\n  isIncreasingX(p) || isDecreasingX(p)\n\n/** @internal */\nexport const isIncreasingY = <T>(p: LinearPath2d<T>): p is LinearPath2d<T & IncreasingY> => {\n  let prevEnd = Number.NEGATIVE_INFINITY\n  for (const c of p) {\n    if (!LinearPolynomial.isIncreasing(c.y)) {\n      return false\n    }\n    if (c.y.c0 < prevEnd - EPSILON) {\n      return false\n    }\n    prevEnd = c.y.c0 + c.y.c1\n  }\n  return true\n}\n\n/** @internal */\nexport const isDecreasingY = <T>(p: LinearPath2d<T>): p is LinearPath2d<T & DecreasingY> => {\n  let prevEnd = Number.POSITIVE_INFINITY\n  for (const c of p) {\n    if (!LinearPolynomial.isDecreasing(c.y)) {\n      return false\n    }\n    if (c.y.c0 > prevEnd + EPSILON) {\n      return false\n    }\n    prevEnd = c.y.c0 + c.y.c1\n  }\n  return true\n}\n\n/** @internal */\nexport const isMonotonicY = <T>(p: LinearPath2d<T>): p is LinearPath2d<T & MonotonicY> =>\n  isIncreasingY(p) || isDecreasingY(p)\n\n/** @internal */\nexport const asIncreasingX = <T>(p: LinearPath2d<T>): LinearPath2d<T & IncreasingX> => {\n  invariant(isIncreasingX(p), 'linear path is not increasing in x')\n  return p\n}\n\n/** @internal */\nexport const asDecreasingX = <T>(p: LinearPath2d<T>): LinearPath2d<T & DecreasingX> => {\n  invariant(isDecreasingX(p), 'linear path is not decreasing in x')\n  return p\n}\n\n/** @internal */\nexport const asMonotonicX = <T>(p: LinearPath2d<T>): LinearPath2d<T & MonotonicX> => {\n  invariant(isMonotonicX(p), 'linear path is not monotonic in x')\n  return p\n}\n\n/** @internal */\nexport const asIncreasingY = <T>(p: LinearPath2d<T>): LinearPath2d<T & IncreasingY> => {\n  invariant(isIncreasingY(p), 'linear path is not increasing in y')\n  return p\n}\n\n/** @internal */\nexport const asDecreasingY = <T>(p: LinearPath2d<T>): LinearPath2d<T & DecreasingY> => {\n  invariant(isDecreasingY(p), 'linear path is not decreasing in y')\n  return p\n}\n\n/** @internal */\nexport const asMonotonicY = <T>(p: LinearPath2d<T>): LinearPath2d<T & MonotonicY> => {\n  invariant(isMonotonicY(p), 'linear path is not monotonic in y')\n  return p\n}\n\n// solveAtX/solveAtY for `Monotonic{X,Y}` paths. Two defenses against float\n// drift at interior knots (where adjacent segments both bracket the query):\n//   1. Snap to t=0/t=1 endpoint y when the query is within EPSILON of a\n//      segment's start or end.\n//   2. Fall through to the next bracketing segment on `none`. Linear paths\n//      don't currently surface drift (degree-1 `c0 + c1 = x` is stable), but\n//      the same shape applies for symmetry with quadratic / cubic.\n/** @internal */\nexport const solveAtX = dual(2, (p: LinearPath2d, x: number): Solution.AtMostOne<number> => {\n  for (const c of p) {\n    const sx = c.x.c0\n    const ex = c.x.c0 + c.x.c1\n    const lo = Math.min(sx, ex)\n    const hi = Math.max(sx, ex)\n    if (x >= lo - EPSILON && x <= hi + EPSILON) {\n      if (epsEquals(x, sx)) {\n        return Solution.one(c.y.c0)\n      }\n      if (epsEquals(x, ex)) {\n        return Solution.one(c.y.c0 + c.y.c1)\n      }\n      const sol = LinearCurve2d.solveAtX(c, x)\n      if (!Solution.isNone(sol)) {\n        return sol\n      }\n    }\n  }\n  return Solution.none\n})\n\n/** @internal */\nexport const solveAtY = dual(2, (p: LinearPath2d, y: number): Solution.AtMostOne<number> => {\n  for (const c of p) {\n    const sy = c.y.c0\n    const ey = c.y.c0 + c.y.c1\n    const lo = Math.min(sy, ey)\n    const hi = Math.max(sy, ey)\n    if (y >= lo - EPSILON && y <= hi + EPSILON) {\n      if (epsEquals(y, sy)) {\n        return Solution.one(c.x.c0)\n      }\n      if (epsEquals(y, ey)) {\n        return Solution.one(c.x.c0 + c.x.c1)\n      }\n      const sol = LinearCurve2d.solveAtY(c, y)\n      if (!Solution.isNone(sol)) {\n        return sol\n      }\n    }\n  }\n  return Solution.none\n})\n\n/** @internal */\nexport const boundingBox = (\n  p: LinearPath2d,\n): Interval2d.Interval2d<Interval.Closed, Interval.Closed> => {\n  const iter = p[Symbol.iterator]()\n  const first = iter.next()\n  // path invariant: at least one curve, so first.value is defined\n  let acc = LinearCurve2d.boundingBox(first.value as LinearCurve2d.LinearCurve2d)\n  for (let next = iter.next(); !next.done; next = iter.next()) {\n    acc = Interval2d.union(acc, LinearCurve2d.boundingBox(next.value))\n  }\n  return acc\n}\n","import type { Interval2d } from '../interval/interval2d.ts'\nimport type { LinearCurve2d } from '../curve/linear2d.ts'\nimport type { Closed } from '../interval/interval.ts'\nimport type * as Solution from '../solution/solution.ts'\nimport type { Pipeable } from '../utils.ts'\nimport type { Vector2 } from '../vector/vector2.ts'\nimport type { LinearPath2dTypeId } from './linear2d.internal.ts'\nimport * as internal from './linear2d.internal.ts'\nimport type {\n  Continuous,\n  DecreasingX,\n  DecreasingY,\n  IncreasingX,\n  IncreasingY,\n  MonotonicX,\n  MonotonicY,\n  PathTraits,\n} from './traits.ts'\n\nexport type {\n  Continuous,\n  DecreasingX,\n  DecreasingY,\n  IncreasingX,\n  IncreasingY,\n  MonotonicX,\n  MonotonicY,\n} from './traits.ts'\n\n/**\n * A linear 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`. A `Continuous` path's `toPathData`\n * skips the per-segment discontinuity check.\n *\n * @since 1.0.0\n */\nexport interface LinearPath2d<out Trait = unknown> extends Pipeable, Iterable<LinearCurve2d> {\n  readonly [LinearPath2dTypeId]: LinearPath2dTypeId\n  readonly [PathTraits]: Trait\n}\n\n/**\n * Creates a new `LinearPath2d` instance from a sequence of curves.\n *\n * @param curves - The curves to create the path from.\n * @returns A new `LinearPath2d` instance.\n * @since 2.0.0\n */\nexport const make: (...curves: ReadonlyArray<LinearCurve2d>) => LinearPath2d = internal.make\n\n/**\n * Creates a new `LinearPath2d` instance from an array of curves.\n *\n * @param curves - The curves to create the path from.\n * @returns A new `LinearPath2d` instance.\n * @since 2.0.0\n */\nexport const fromArray: (curves: ReadonlyArray<LinearCurve2d>) => LinearPath2d = internal.fromArray\n\n/**\n * Checks if a value is a `LinearPath2d`.\n *\n * @param p - The value to check.\n * @returns `true` if the value is a `LinearPath2d`, `false` otherwise.\n * @since 1.0.0\n */\nexport const isLinearPath2d: (p: unknown) => p is LinearPath2d = internal.isLinearPath2d\n\nexport const append: {\n  /**\n   * Appends a linear curve to a linear path.\n   *\n   * @param c - The linear curve to append.\n   * @returns A function that takes a linear path and returns a new linear path.\n   * @since 1.0.0\n   */\n  (c: LinearCurve2d): (p: LinearPath2d) => LinearPath2d\n  /**\n   * Appends a linear curve to a linear path.\n   *\n   * @param p - The linear path to append to.\n   * @param c - The linear curve to append.\n   * @returns A new `LinearPath2d` instance with the appended curve.\n   * @since 1.0.0\n   */\n  (p: LinearPath2d, c: LinearCurve2d): LinearPath2d\n} = internal.append\n\n/**\n * Calculates the length of a linear path.\n *\n * @param p - The linear path to calculate the length of.\n * @returns The length of the linear path.\n * @since 1.0.0\n */\nexport const length: (p: LinearPath2d) => number = internal.length\n\nexport const solve: {\n  /**\n   * Solves a linear path for a given parameter.\n   *\n   * @param u - The parameter to solve for.\n   * @returns A function that takes a linear path and returns the solved point.\n   * @since 1.0.0\n   */\n  (u: number): (p: LinearPath2d) => Vector2\n  /**\n   * Solves a linear path for a given parameter.\n   *\n   * @param p - The linear path to solve.\n   * @param u - The parameter to solve for.\n   * @returns The solved point on the linear path.\n   * @since 1.0.0\n   */\n  (p: LinearPath2d, u: number): Vector2\n} = internal.solve\n\n/**\n * Serializes a linear path as an SVG path data string (the value of a `<path>`\n * element's `d` attribute), using `M` and `L` commands. Discontinuities between\n * curves emit a fresh `M` command.\n *\n * @param p - The linear path to serialize.\n * @returns The SVG path data string.\n * @since 2.0.0\n */\nexport const toPathData: (p: LinearPath2d) => string = internal.toPathData\n\n/**\n * Type-narrowing predicate: refines `LinearPath2d<T>` to\n * `LinearPath2d<T & Continuous>` when adjacent curves connect at their join\n * points.\n *\n * @param p - The linear path to check.\n * @returns `true` when the path is continuous (G⁰).\n * @since 2.0.0\n */\nexport const isContinuous: <T>(p: LinearPath2d<T>) => p is LinearPath2d<T & Continuous> =\n  internal.isContinuous\n\n/**\n * Asserts that the linear path is continuous, throwing on failure.\n *\n * @param p - The linear path to assert against.\n * @returns The same path, typed with the `Continuous` brand.\n * @throws When the path has a discontinuity between adjacent curves.\n * @since 2.0.0\n */\nexport const asContinuous: <T>(p: LinearPath2d<T>) => LinearPath2d<T & Continuous> =\n  internal.asContinuous\n\n/**\n * Type-narrowing predicate: refines `LinearPath2d<T>` to\n * `LinearPath2d<T & IncreasingX>` when every segment's x-polynomial is\n * strictly increasing and adjacent segments' x-ranges don't overlap.\n *\n * @since 2.0.0\n */\nexport const isIncreasingX: <T>(p: LinearPath2d<T>) => p is LinearPath2d<T & IncreasingX> =\n  internal.isIncreasingX\n\n/**\n * Type-narrowing predicate: refines `LinearPath2d<T>` to\n * `LinearPath2d<T & DecreasingX>` when every segment's x-polynomial is\n * strictly decreasing and adjacent segments' x-ranges don't overlap.\n *\n * @since 2.0.0\n */\nexport const isDecreasingX: <T>(p: LinearPath2d<T>) => p is LinearPath2d<T & DecreasingX> =\n  internal.isDecreasingX\n\n/**\n * Type-narrowing predicate: refines `LinearPath2d<T>` to\n * `LinearPath2d<T & MonotonicX>` when the path is either increasing or\n * decreasing in x along its full parameter domain.\n *\n * @since 2.0.0\n */\nexport const isMonotonicX: <T>(p: LinearPath2d<T>) => p is LinearPath2d<T & MonotonicX> =\n  internal.isMonotonicX\n\n/**\n * Type-narrowing predicate: refines `LinearPath2d<T>` to\n * `LinearPath2d<T & IncreasingY>`. The y-axis analog of {@link isIncreasingX}.\n *\n * @since 2.0.0\n */\nexport const isIncreasingY: <T>(p: LinearPath2d<T>) => p is LinearPath2d<T & IncreasingY> =\n  internal.isIncreasingY\n\n/**\n * Type-narrowing predicate: refines `LinearPath2d<T>` to\n * `LinearPath2d<T & DecreasingY>`. The y-axis analog of {@link isDecreasingX}.\n *\n * @since 2.0.0\n */\nexport const isDecreasingY: <T>(p: LinearPath2d<T>) => p is LinearPath2d<T & DecreasingY> =\n  internal.isDecreasingY\n\n/**\n * Type-narrowing predicate: refines `LinearPath2d<T>` to\n * `LinearPath2d<T & MonotonicY>`. The y-axis analog of {@link isMonotonicX}.\n *\n * @since 2.0.0\n */\nexport const isMonotonicY: <T>(p: LinearPath2d<T>) => p is LinearPath2d<T & MonotonicY> =\n  internal.isMonotonicY\n\n/**\n * Asserts that the path is strictly increasing in x, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asIncreasingX: <T>(p: LinearPath2d<T>) => LinearPath2d<T & IncreasingX> =\n  internal.asIncreasingX\n\n/**\n * Asserts that the path is strictly decreasing in x, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asDecreasingX: <T>(p: LinearPath2d<T>) => LinearPath2d<T & DecreasingX> =\n  internal.asDecreasingX\n\n/**\n * Asserts that the path is monotonic in x, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asMonotonicX: <T>(p: LinearPath2d<T>) => LinearPath2d<T & MonotonicX> =\n  internal.asMonotonicX\n\n/**\n * Asserts that the path is strictly increasing in y, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asIncreasingY: <T>(p: LinearPath2d<T>) => LinearPath2d<T & IncreasingY> =\n  internal.asIncreasingY\n\n/**\n * Asserts that the path is strictly decreasing in y, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asDecreasingY: <T>(p: LinearPath2d<T>) => LinearPath2d<T & DecreasingY> =\n  internal.asDecreasingY\n\n/**\n * Asserts that the path is monotonic in y, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asMonotonicY: <T>(p: LinearPath2d<T>) => LinearPath2d<T & MonotonicY> =\n  internal.asMonotonicY\n\nexport const solveAtX: {\n  /**\n   * Evaluates the path's y value at a given x. Requires the path to carry the\n   * `MonotonicX` brand — without it, an x query could match multiple\n   * segments and the return cardinality would be unbounded.\n   *\n   * Returns `Solution.none` when x falls outside the path's x-range.\n   *\n   * @param p - A path branded `MonotonicX`.\n   * @param x - The x coordinate.\n   * @returns The y value at x, or `none` when x is outside the path's range.\n   * @since 2.0.0\n   */\n  <T extends MonotonicX>(p: LinearPath2d<T>, x: number): Solution.AtMostOne<number>\n  /** @since 2.0.0 */\n  (x: number): <T extends MonotonicX>(p: LinearPath2d<T>) => Solution.AtMostOne<number>\n} = internal.solveAtX as never\n\nexport const solveAtY: {\n  /**\n   * Evaluates the path's x value at a given y. Requires the path to carry the\n   * `MonotonicY` brand. Returns `Solution.none` when y is outside the path's\n   * y-range.\n   *\n   * @param p - A path branded `MonotonicY`.\n   * @param y - The y coordinate.\n   * @returns The x value at y, or `none` when y is outside the path's range.\n   * @since 2.0.0\n   */\n  <T extends MonotonicY>(p: LinearPath2d<T>, y: number): Solution.AtMostOne<number>\n  /** @since 2.0.0 */\n  (y: number): <T extends MonotonicY>(p: LinearPath2d<T>) => Solution.AtMostOne<number>\n} = internal.solveAtY as never\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 linear path.\n * @returns A closed `Box2d` enclosing the path.\n * @since 2.0.0\n */\nexport const boundingBox: (p: LinearPath2d) => Interval2d<Closed, Closed> = internal.boundingBox\n","import * as Interval2d from '../interval/interval2d.ts'\nimport * as CubicCurve2d from '../curve/cubic2d.ts'\nimport * as cubicCurveInternal from '../curve/cubic2d.internal.ts'\nimport * as QuadraticCurve2d from '../curve/quadratic2d.ts'\nimport * as Interval from '../interval/interval.ts'\nimport * as CubicPolynomial from '../polynomial/cubic.ts'\nimport * as Solution from '../solution/solution.ts'\nimport { dual, Pipeable } from '../utils.ts'\nimport { invariant } from '../utils.ts'\nimport { EPSILON, epsEquals } from '../number.ts'\nimport * as Vector2 from '../vector/vector2.ts'\nimport type { CubicPath2d } from './cubic2d.ts'\nimport {\n  PathTraits,\n  type Continuous,\n  type DecreasingX,\n  type DecreasingY,\n  type IncreasingX,\n  type IncreasingY,\n  type MonotonicX,\n  type MonotonicY,\n} from './traits.ts'\n\nexport const CubicPath2dTypeId: unique symbol = Symbol('curvy/path/cubic2d')\nexport type CubicPath2dTypeId = typeof CubicPath2dTypeId\n\n/** @internal */\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\n/** @internal */\nexport const isCubicPath2d = (p: unknown): p is CubicPath2d =>\n  typeof p === 'object' && p !== null && CubicPath2dTypeId in p\n\n/** @internal */\nexport const make = (...curves: ReadonlyArray<CubicCurve2d.CubicCurve2d>): CubicPath2d =>\n  new CubicPath2dImpl(curves)\n\n/** @internal */\nexport const fromArray = (curves: ReadonlyArray<CubicCurve2d.CubicCurve2d>): CubicPath2d =>\n  new CubicPath2dImpl(curves)\n\n/** @internal */\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\n/** @internal */\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\n/** @internal */\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.\n/** @internal */\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\n/** @internal */\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\n/** @internal */\nexport const asContinuous = <T>(p: CubicPath2d<T>): CubicPath2d<T & Continuous> => {\n  invariant(isContinuous(p), 'cubic path is not continuous')\n  return p\n}\n\n// Per-axis monotonicity for the path: every segment's axis polynomial must be\n// strictly monotonic over the unit interval AND adjacent segments' axis\n// ranges must not overlap (modulo EPSILON for float drift).\n/** @internal */\nexport const isIncreasingX = <T>(p: CubicPath2d<T>): p is CubicPath2d<T & IncreasingX> => {\n  let prevEnd = Number.NEGATIVE_INFINITY\n  for (const c of p) {\n    if (!CubicPolynomial.isIncreasing(c.x, Interval.unit)) {\n      return false\n    }\n    if (c.x.c0 < prevEnd - EPSILON) {\n      return false\n    }\n    prevEnd = c.x.c0 + c.x.c1 + c.x.c2 + c.x.c3\n  }\n  return true\n}\n\n/** @internal */\nexport const isDecreasingX = <T>(p: CubicPath2d<T>): p is CubicPath2d<T & DecreasingX> => {\n  let prevEnd = Number.POSITIVE_INFINITY\n  for (const c of p) {\n    if (!CubicPolynomial.isDecreasing(c.x, Interval.unit)) {\n      return false\n    }\n    if (c.x.c0 > prevEnd + EPSILON) {\n      return false\n    }\n    prevEnd = c.x.c0 + c.x.c1 + c.x.c2 + c.x.c3\n  }\n  return true\n}\n\n/** @internal */\nexport const isMonotonicX = <T>(p: CubicPath2d<T>): p is CubicPath2d<T & MonotonicX> =>\n  isIncreasingX(p) || isDecreasingX(p)\n\n/** @internal */\nexport const isIncreasingY = <T>(p: CubicPath2d<T>): p is CubicPath2d<T & IncreasingY> => {\n  let prevEnd = Number.NEGATIVE_INFINITY\n  for (const c of p) {\n    if (!CubicPolynomial.isIncreasing(c.y, Interval.unit)) {\n      return false\n    }\n    if (c.y.c0 < prevEnd - EPSILON) {\n      return false\n    }\n    prevEnd = c.y.c0 + c.y.c1 + c.y.c2 + c.y.c3\n  }\n  return true\n}\n\n/** @internal */\nexport const isDecreasingY = <T>(p: CubicPath2d<T>): p is CubicPath2d<T & DecreasingY> => {\n  let prevEnd = Number.POSITIVE_INFINITY\n  for (const c of p) {\n    if (!CubicPolynomial.isDecreasing(c.y, Interval.unit)) {\n      return false\n    }\n    if (c.y.c0 > prevEnd + EPSILON) {\n      return false\n    }\n    prevEnd = c.y.c0 + c.y.c1 + c.y.c2 + c.y.c3\n  }\n  return true\n}\n\n/** @internal */\nexport const isMonotonicY = <T>(p: CubicPath2d<T>): p is CubicPath2d<T & MonotonicY> =>\n  isIncreasingY(p) || isDecreasingY(p)\n\n/** @internal */\nexport const asIncreasingX = <T>(p: CubicPath2d<T>): CubicPath2d<T & IncreasingX> => {\n  invariant(isIncreasingX(p), 'cubic path is not increasing in x')\n  return p\n}\n\n/** @internal */\nexport const asDecreasingX = <T>(p: CubicPath2d<T>): CubicPath2d<T & DecreasingX> => {\n  invariant(isDecreasingX(p), 'cubic path is not decreasing in x')\n  return p\n}\n\n/** @internal */\nexport const asMonotonicX = <T>(p: CubicPath2d<T>): CubicPath2d<T & MonotonicX> => {\n  invariant(isMonotonicX(p), 'cubic path is not monotonic in x')\n  return p\n}\n\n/** @internal */\nexport const asIncreasingY = <T>(p: CubicPath2d<T>): CubicPath2d<T & IncreasingY> => {\n  invariant(isIncreasingY(p), 'cubic path is not increasing in y')\n  return p\n}\n\n/** @internal */\nexport const asDecreasingY = <T>(p: CubicPath2d<T>): CubicPath2d<T & DecreasingY> => {\n  invariant(isDecreasingY(p), 'cubic path is not decreasing in y')\n  return p\n}\n\n/** @internal */\nexport const asMonotonicY = <T>(p: CubicPath2d<T>): CubicPath2d<T & MonotonicY> => {\n  invariant(isMonotonicY(p), 'cubic path is not monotonic in y')\n  return p\n}\n\n// At an interior knot, two adjacent segments both bracket the query — one's\n// right endpoint and the next's left endpoint are (within float drift) the\n// same value. The per-curve cubic-root solver can return `none` for both\n// brackets when the true root sits just outside [0, 1] due to that drift. We\n// handle this two ways:\n//   1. If the query is within EPSILON of a segment's start or end, evaluate y\n//      directly at t=0 or t=1 — skips polynomial inversion entirely.\n//   2. Otherwise, if a bracketing segment returns `none`, fall through to the\n//      next bracketing segment. `MonotonicX` admits at most one real solution\n//      across the path, so retrying after `none` is safe.\n/** @internal */\nexport const solveAtX = dual(2, (p: CubicPath2d, x: number): Solution.AtMostOne<number> => {\n  for (const c of p) {\n    const sx = c.x.c0\n    const ex = c.x.c0 + c.x.c1 + c.x.c2 + c.x.c3\n    const lo = Math.min(sx, ex)\n    const hi = Math.max(sx, ex)\n    if (x >= lo - EPSILON && x <= hi + EPSILON) {\n      if (epsEquals(x, sx)) {\n        return Solution.one(c.y.c0)\n      }\n      if (epsEquals(x, ex)) {\n        return Solution.one(c.y.c0 + c.y.c1 + c.y.c2 + c.y.c3)\n      }\n      const sol = CubicCurve2d.solveAtX(c, x) as Solution.AtMostOne<number>\n      if (!Solution.isNone(sol)) {\n        return sol\n      }\n    }\n  }\n  return Solution.none\n})\n\n/** @internal */\nexport const solveAtY = dual(2, (p: CubicPath2d, y: number): Solution.AtMostOne<number> => {\n  for (const c of p) {\n    const sy = c.y.c0\n    const ey = c.y.c0 + c.y.c1 + c.y.c2 + c.y.c3\n    const lo = Math.min(sy, ey)\n    const hi = Math.max(sy, ey)\n    if (y >= lo - EPSILON && y <= hi + EPSILON) {\n      if (epsEquals(y, sy)) {\n        return Solution.one(c.x.c0)\n      }\n      if (epsEquals(y, ey)) {\n        return Solution.one(c.x.c0 + c.x.c1 + c.x.c2 + c.x.c3)\n      }\n      const sol = CubicCurve2d.solveAtY(c, y) as Solution.AtMostOne<number>\n      if (!Solution.isNone(sol)) {\n        return sol\n      }\n    }\n  }\n  return Solution.none\n})\n\n/** @internal */\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\n/** @internal */\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.ts'\nimport type { CubicCurve2d } from '../curve/cubic2d.ts'\nimport type { Closed } from '../interval/interval.ts'\nimport type * as Solution from '../solution/solution.ts'\nimport type { Pipeable } from '../utils.ts'\nimport type { Vector2 } from '../vector/vector2.ts'\nimport type { CubicPath2dTypeId } from './cubic2d.internal.ts'\nimport * as internal from './cubic2d.internal.ts'\nimport type {\n  Continuous,\n  DecreasingX,\n  DecreasingY,\n  IncreasingX,\n  IncreasingY,\n  MonotonicX,\n  MonotonicY,\n  PathTraits,\n} from './traits.ts'\n\nexport type {\n  Continuous,\n  DecreasingX,\n  DecreasingY,\n  IncreasingX,\n  IncreasingY,\n  MonotonicX,\n  MonotonicY,\n} from './traits.ts'\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\n/**\n * Type-narrowing predicate: refines `CubicPath2d<T>` to\n * `CubicPath2d<T & IncreasingX>` when every segment's x-polynomial is\n * strictly increasing on `[0, 1]` and adjacent segments' x-ranges don't\n * overlap.\n *\n * @since 2.0.0\n */\nexport const isIncreasingX: <T>(p: CubicPath2d<T>) => p is CubicPath2d<T & IncreasingX> =\n  internal.isIncreasingX\n\n/**\n * Type-narrowing predicate: refines `CubicPath2d<T>` to\n * `CubicPath2d<T & DecreasingX>`.\n *\n * @since 2.0.0\n */\nexport const isDecreasingX: <T>(p: CubicPath2d<T>) => p is CubicPath2d<T & DecreasingX> =\n  internal.isDecreasingX\n\n/**\n * Type-narrowing predicate: refines `CubicPath2d<T>` to\n * `CubicPath2d<T & MonotonicX>`.\n *\n * @since 2.0.0\n */\nexport const isMonotonicX: <T>(p: CubicPath2d<T>) => p is CubicPath2d<T & MonotonicX> =\n  internal.isMonotonicX\n\n/**\n * Type-narrowing predicate: refines `CubicPath2d<T>` to\n * `CubicPath2d<T & IncreasingY>`.\n *\n * @since 2.0.0\n */\nexport const isIncreasingY: <T>(p: CubicPath2d<T>) => p is CubicPath2d<T & IncreasingY> =\n  internal.isIncreasingY\n\n/**\n * Type-narrowing predicate: refines `CubicPath2d<T>` to\n * `CubicPath2d<T & DecreasingY>`.\n *\n * @since 2.0.0\n */\nexport const isDecreasingY: <T>(p: CubicPath2d<T>) => p is CubicPath2d<T & DecreasingY> =\n  internal.isDecreasingY\n\n/**\n * Type-narrowing predicate: refines `CubicPath2d<T>` to\n * `CubicPath2d<T & MonotonicY>`.\n *\n * @since 2.0.0\n */\nexport const isMonotonicY: <T>(p: CubicPath2d<T>) => p is CubicPath2d<T & MonotonicY> =\n  internal.isMonotonicY\n\n/**\n * Asserts that the path is strictly increasing in x, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asIncreasingX: <T>(p: CubicPath2d<T>) => CubicPath2d<T & IncreasingX> =\n  internal.asIncreasingX\n\n/**\n * Asserts that the path is strictly decreasing in x, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asDecreasingX: <T>(p: CubicPath2d<T>) => CubicPath2d<T & DecreasingX> =\n  internal.asDecreasingX\n\n/**\n * Asserts that the path is monotonic in x, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asMonotonicX: <T>(p: CubicPath2d<T>) => CubicPath2d<T & MonotonicX> =\n  internal.asMonotonicX\n\n/**\n * Asserts that the path is strictly increasing in y, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asIncreasingY: <T>(p: CubicPath2d<T>) => CubicPath2d<T & IncreasingY> =\n  internal.asIncreasingY\n\n/**\n * Asserts that the path is strictly decreasing in y, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asDecreasingY: <T>(p: CubicPath2d<T>) => CubicPath2d<T & DecreasingY> =\n  internal.asDecreasingY\n\n/**\n * Asserts that the path is monotonic in y, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asMonotonicY: <T>(p: CubicPath2d<T>) => CubicPath2d<T & MonotonicY> =\n  internal.asMonotonicY\n\nexport const solveAtX: {\n  /**\n   * Evaluates the path's y value at a given x. Requires the path to carry\n   * the `MonotonicX` brand. Returns `Solution.none` when x is outside the\n   * path's x-range.\n   *\n   * @param p - A path branded `MonotonicX`.\n   * @param x - The x coordinate.\n   * @returns The y value at x, or `none` when x is outside the path's range.\n   * @since 2.0.0\n   */\n  <T extends MonotonicX>(p: CubicPath2d<T>, x: number): Solution.AtMostOne<number>\n  /** @since 2.0.0 */\n  (x: number): <T extends MonotonicX>(p: CubicPath2d<T>) => Solution.AtMostOne<number>\n} = internal.solveAtX as never\n\nexport const solveAtY: {\n  /**\n   * Evaluates the path's x value at a given y. Requires the path to carry\n   * the `MonotonicY` brand. Returns `Solution.none` when y is outside the\n   * path's y-range.\n   *\n   * @param p - A path branded `MonotonicY`.\n   * @param y - The y coordinate.\n   * @returns The x value at y, or `none` when y is outside the path's range.\n   * @since 2.0.0\n   */\n  <T extends MonotonicY>(p: CubicPath2d<T>, y: number): Solution.AtMostOne<number>\n  /** @since 2.0.0 */\n  (y: number): <T extends MonotonicY>(p: CubicPath2d<T>) => Solution.AtMostOne<number>\n} = internal.solveAtY as never\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.ts'\nimport * as RationalCubicCurve2d from '../curve/rationalCubic2d.ts'\nimport type * as Interval from '../interval/interval.ts'\nimport * as Interval2d from '../interval/interval2d.ts'\nimport { dual, Pipeable } from '../utils.ts'\nimport { invariant } from '../utils.ts'\nimport type * as Vector2 from '../vector/vector2.ts'\nimport * as CubicPath2d from './cubic2d.ts'\nimport type { RationalCubicPath2d } from './rationalCubic2d.ts'\n\nexport const RationalCubicPath2dTypeId: unique symbol = Symbol('curvy/path/rationalCubic2d')\nexport type RationalCubicPath2dTypeId = typeof RationalCubicPath2dTypeId\n\n/** @internal */\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\n/** @internal */\nexport const isRationalCubicPath2d = (p: unknown): p is RationalCubicPath2d =>\n  typeof p === 'object' && p !== null && RationalCubicPath2dTypeId in p\n\n/** @internal */\nexport const make = (\n  ...curves: ReadonlyArray<RationalCubicCurve2d.RationalCubicCurve2d>\n): RationalCubicPath2d => new RationalCubicPath2dImpl(curves)\n\n/** @internal */\nexport const fromArray = (\n  curves: ReadonlyArray<RationalCubicCurve2d.RationalCubicCurve2d>,\n): RationalCubicPath2d => new RationalCubicPath2dImpl(curves)\n\n/** @internal */\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\n/** @internal */\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 bounding box: per-segment box is delegated to the curve module\n// (subdivision + hull union, tight to within `tolerance` per side); the path\n// box is then their union. Since each segment box's slack is ≤ tolerance per\n// side, the unioned box's slack is also ≤ tolerance per side — the same\n// guarantee holds at the path level.\n/** @internal */\nexport const boundingBox = dual<\n  (\n    tolerance: number,\n  ) => (p: RationalCubicPath2d) => Interval2d.Interval2d<Interval.Closed, Interval.Closed>,\n  (\n    p: RationalCubicPath2d,\n    tolerance: number,\n  ) => Interval2d.Interval2d<Interval.Closed, Interval.Closed>\n>(2, (p: RationalCubicPath2d, tolerance: number) => {\n  const iter = p[Symbol.iterator]()\n  const first = iter.next()\n  let acc = RationalCubicCurve2d.boundingBox(\n    first.value as RationalCubicCurve2d.RationalCubicCurve2d,\n    tolerance,\n  )\n  for (let next = iter.next(); !next.done; next = iter.next()) {\n    acc = Interval2d.union(acc, RationalCubicCurve2d.boundingBox(next.value, tolerance))\n  }\n  return acc\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.\n/** @internal */\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.ts'\nimport type { Closed } from '../interval/interval.ts'\nimport type { Interval2d } from '../interval/interval2d.ts'\nimport type { Pipeable } from '../utils.ts'\nimport type { Vector2 } from '../vector/vector2.ts'\nimport type { CubicPath2d } from './cubic2d.ts'\nimport type { RationalCubicPath2dTypeId } from './rationalCubic2d.internal.ts'\nimport * as internal from './rationalCubic2d.internal.ts'\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 boundingBox: {\n  /**\n   * Computes a closed axis-aligned bounding box for a rational cubic path,\n   * tight to within `tolerance` per side.\n   *\n   * Per-segment delegates to `RationalCubicCurve2d.boundingBox(c, tolerance)`\n   * — recursive subdivision producing a hull-AABB union tight to within\n   * `tolerance` per side. The path box is the union of segment boxes; since\n   * each segment box has slack ≤ tolerance per side, so does the union.\n   *\n   * @param p - The rational cubic path.\n   * @param tolerance - Maximum allowed slack per side; must be positive.\n   * @returns A closed `Interval2d` enclosing the path, tight to within `tolerance`.\n   * @since 2.0.0\n   */\n  (p: RationalCubicPath2d, tolerance: number): Interval2d<Closed, Closed>\n  /**\n   * Computes a closed axis-aligned bounding box for a rational cubic path.\n   *\n   * @param tolerance - Maximum allowed slack per side; must be positive.\n   * @returns A function that takes a path and returns its bounding box.\n   * @since 2.0.0\n   */\n  (tolerance: number): (p: RationalCubicPath2d) => Interval2d<Closed, Closed>\n} = internal.boundingBox\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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"}