curvy 2.0.0-alpha.2 → 2.0.0-alpha.5
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.
- package/dist/characteristic/{index.d.mts → characteristic.d.ts} +15 -23
- package/dist/characteristic/index.d.ts +1 -0
- package/dist/characteristic/index.mjs +1 -1
- package/dist/curve/cubic2d.d.ts +219 -0
- package/dist/curve/index.d.ts +12 -0
- package/dist/curve/index.mjs +1 -1
- package/dist/curve/linear2d.d.ts +199 -0
- package/dist/curve/quadratic2d.d.ts +227 -0
- package/dist/curve/rationalCubic2d.d.ts +200 -0
- package/dist/dimensions.d.ts +23 -0
- package/dist/interval/index.d.ts +6 -0
- package/dist/interval/index.mjs +2 -2
- package/dist/interval/interval.d.ts +525 -0
- package/dist/interval/interval2d.d.ts +167 -0
- package/dist/length.d.ts +32 -0
- package/dist/matrix/index.d.ts +9 -0
- package/dist/matrix/matrix2x2.d.ts +339 -0
- package/dist/matrix/matrix3x3.d.ts +400 -0
- package/dist/matrix/matrix4x4.d.ts +443 -0
- package/dist/number.d.ts +276 -0
- package/dist/path/cubic2d.d.ts +155 -0
- package/dist/path/index.d.ts +12 -0
- package/dist/path/index.mjs +6 -6
- package/dist/path/index.mjs.map +1 -1
- package/dist/path/linear2d.d.ts +135 -0
- package/dist/path/quadratic2d.d.ts +127 -0
- package/dist/path/rationalCubic2d.d.ts +120 -0
- package/dist/path/traits.d.ts +31 -0
- package/dist/polynomial/cubic.d.ts +381 -0
- package/dist/polynomial/index.d.ts +9 -0
- package/dist/polynomial/index.mjs +2 -2
- package/dist/polynomial/linear.d.ts +321 -0
- package/dist/polynomial/monotonicity.d.ts +3 -0
- package/dist/polynomial/quadratic.d.ts +375 -0
- package/dist/polynomial/traits.d.ts +56 -0
- package/dist/shared/{characteristic-B9nCh_cx.mjs → characteristic-DLlhja-I.mjs} +9 -9
- package/dist/shared/{characteristic-B9nCh_cx.mjs.map → characteristic-DLlhja-I.mjs.map} +1 -1
- package/dist/shared/{cubic-CpHAx8cC.mjs → cubic-CMonq6bg.mjs} +26 -5
- package/dist/shared/cubic-CMonq6bg.mjs.map +1 -0
- package/dist/shared/{interval-05CR6eBf.mjs → interval-X1EYuf-T.mjs} +2 -2
- package/dist/shared/{interval-05CR6eBf.mjs.map → interval-X1EYuf-T.mjs.map} +1 -1
- package/dist/shared/{interval2d-8IBZnUOq.mjs → interval2d-ca0J1NMr.mjs} +8 -8
- package/dist/shared/{interval2d-8IBZnUOq.mjs.map → interval2d-ca0J1NMr.mjs.map} +1 -1
- package/dist/shared/{quadratic-CamozcFc.mjs → quadratic-DyeMtvET.mjs} +20 -2
- package/dist/shared/quadratic-DyeMtvET.mjs.map +1 -0
- package/dist/shared/{rationalCubic2d-Bys2Uory.mjs → rationalCubic2d-D658ltUM.mjs} +17 -17
- package/dist/shared/{rationalCubic2d-Bys2Uory.mjs.map → rationalCubic2d-D658ltUM.mjs.map} +1 -1
- package/dist/shared/{rationalCubic2d-BEgUGSFf.mjs → rationalCubic2d-Vw4qGPZj.mjs} +9 -9
- package/dist/shared/{rationalCubic2d-BEgUGSFf.mjs.map → rationalCubic2d-Vw4qGPZj.mjs.map} +1 -1
- package/dist/shared/{solution-CrtLfqEq.mjs → solution-3TDATEMn.mjs} +28 -2
- package/dist/shared/solution-3TDATEMn.mjs.map +1 -0
- package/dist/shared/{vector2-CL1HDdPr.mjs → vector2-CCuJx1rX.mjs} +6 -6
- package/dist/shared/{vector2-CL1HDdPr.mjs.map → vector2-CCuJx1rX.mjs.map} +1 -1
- package/dist/shared/{vector3-D-tv_aKL.mjs → vector3-C-qgKAjR.mjs} +2 -2
- package/dist/shared/{vector3-D-tv_aKL.mjs.map → vector3-C-qgKAjR.mjs.map} +1 -1
- package/dist/shared/{vector4-5KbjoHVj.mjs → vector4-BhOKDhD5.mjs} +2 -2
- package/dist/shared/{vector4-5KbjoHVj.mjs.map → vector4-BhOKDhD5.mjs.map} +1 -1
- package/dist/solution/index.d.ts +3 -0
- package/dist/solution/index.mjs +1 -1
- package/dist/{shared/solution-sNQ-ZVhN.d.mts → solution/solution.d.ts} +81 -68
- package/dist/splines/basis2d.d.ts +122 -0
- package/dist/splines/bezier2d.d.ts +202 -0
- package/dist/splines/cardinal2d.d.ts +273 -0
- package/dist/splines/hermite2d.d.ts +117 -0
- package/dist/splines/index.d.ts +15 -0
- package/dist/splines/index.mjs +193 -35
- package/dist/splines/index.mjs.map +1 -1
- package/dist/splines/rationalBezier2d.d.ts +148 -0
- package/dist/splines/util.d.ts +5 -0
- package/dist/utils.d.ts +73 -0
- package/dist/vector/index.d.ts +9 -0
- package/dist/vector/index.mjs +3 -3
- package/dist/vector/vector2.d.ts +446 -0
- package/dist/vector/vector3.d.ts +449 -0
- package/dist/vector/vector4.d.ts +253 -0
- package/package.json +13 -13
- package/dist/curve/index.d.mts +0 -2
- package/dist/interval/index.d.mts +0 -3
- package/dist/matrix/index.d.mts +0 -2
- package/dist/number.d.mts +0 -280
- package/dist/path/index.d.mts +0 -261
- package/dist/polynomial/index.d.mts +0 -2
- package/dist/shared/cubic-BajUY0JT.d.mts +0 -1100
- package/dist/shared/cubic-CpHAx8cC.mjs.map +0 -1
- package/dist/shared/interval-Dy-RMEE3.d.mts +0 -533
- package/dist/shared/interval2d-C2id9u31.d.mts +0 -172
- package/dist/shared/matrix4x4-Dm_tSiH1.d.mts +0 -1183
- package/dist/shared/quadratic-CamozcFc.mjs.map +0 -1
- package/dist/shared/rationalCubic2d-B6g97ryJ.d.mts +0 -308
- package/dist/shared/rationalCubic2d-DlQfBURs.d.mts +0 -818
- package/dist/shared/solution-CrtLfqEq.mjs.map +0 -1
- package/dist/shared/utils-MCckigYk.d.mts +0 -76
- package/dist/shared/vector2-DPUY3_eA.d.mts +0 -470
- package/dist/shared/vector3-DqeOZtOB.d.mts +0 -703
- package/dist/solution/index.d.mts +0 -2
- package/dist/splines/index.d.mts +0 -701
- package/dist/utils.d.mts +0 -2
- package/dist/vector/index.d.mts +0 -3
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { Interval2d } from '../interval/interval2d';
|
|
2
|
+
import type { CubicCurve2d } from '../curve/cubic2d';
|
|
3
|
+
import type { Closed } from '../interval/interval';
|
|
4
|
+
import type { Pipeable } from '../utils';
|
|
5
|
+
import type { Vector2 } from '../vector/vector2';
|
|
6
|
+
|
|
7
|
+
import type { Continuous, PathTraits } from './traits';
|
|
8
|
+
|
|
9
|
+
declare const CubicPath2dTypeId: unique symbol;
|
|
10
|
+
type CubicPath2dTypeId = typeof CubicPath2dTypeId;
|
|
11
|
+
|
|
12
|
+
export type { Continuous } from './traits';
|
|
13
|
+
/**
|
|
14
|
+
* A cubic path in 2D space.
|
|
15
|
+
*
|
|
16
|
+
* All fields are readonly and immutable, and all operations create new instances.
|
|
17
|
+
*
|
|
18
|
+
* The `Trait` type parameter accumulates trait brands as the path is refined
|
|
19
|
+
* via `isContinuous` / `asContinuous`.
|
|
20
|
+
*
|
|
21
|
+
* @since 1.0.0
|
|
22
|
+
*/
|
|
23
|
+
export interface CubicPath2d<out Trait = unknown> extends Pipeable, Iterable<CubicCurve2d> {
|
|
24
|
+
readonly [CubicPath2dTypeId]: CubicPath2dTypeId;
|
|
25
|
+
readonly [PathTraits]: Trait;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Creates a new `CubicPath2d` instance from a sequence of curves.
|
|
29
|
+
*
|
|
30
|
+
* @param curves - The curves to create the path from.
|
|
31
|
+
* @returns A new `CubicPath2d` instance.
|
|
32
|
+
* @since 2.0.0
|
|
33
|
+
*/
|
|
34
|
+
export declare const make: (...curves: ReadonlyArray<CubicCurve2d>) => CubicPath2d;
|
|
35
|
+
/**
|
|
36
|
+
* Creates a new `CubicPath2d` instance from an array of curves.
|
|
37
|
+
*
|
|
38
|
+
* @param curves - The curves to create the path from.
|
|
39
|
+
* @returns A new `CubicPath2d` instance.
|
|
40
|
+
* @since 2.0.0
|
|
41
|
+
*/
|
|
42
|
+
export declare const fromArray: (curves: ReadonlyArray<CubicCurve2d>) => CubicPath2d;
|
|
43
|
+
/**
|
|
44
|
+
* Checks if a value is a `CubicPath2d`.
|
|
45
|
+
*
|
|
46
|
+
* @param p - The value to check.
|
|
47
|
+
* @returns `true` if the value is a `CubicPath2d`, `false` otherwise.
|
|
48
|
+
* @since 1.0.0
|
|
49
|
+
*/
|
|
50
|
+
export declare const isCubicPath2d: (p: unknown) => p is CubicPath2d;
|
|
51
|
+
export declare const append: {
|
|
52
|
+
/**
|
|
53
|
+
* Appends a cubic curve to a cubic path.
|
|
54
|
+
*
|
|
55
|
+
* @param c - The cubic curve to append.
|
|
56
|
+
* @returns A function that takes a cubic path and returns a new cubic path.
|
|
57
|
+
* @since 1.0.0
|
|
58
|
+
*/
|
|
59
|
+
(c: CubicCurve2d): (p: CubicPath2d) => CubicPath2d;
|
|
60
|
+
/**
|
|
61
|
+
* Appends a cubic curve to a cubic path.
|
|
62
|
+
*
|
|
63
|
+
* @param p - The cubic path to append to.
|
|
64
|
+
* @param c - The cubic curve to append.
|
|
65
|
+
* @returns A new cubic path.
|
|
66
|
+
* @since 1.0.0
|
|
67
|
+
*/
|
|
68
|
+
(p: CubicPath2d, c: CubicCurve2d): CubicPath2d;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Calculates the length of a cubic path.
|
|
72
|
+
*
|
|
73
|
+
* @param p - The cubic path to calculate the length of.
|
|
74
|
+
* @returns The length of the cubic path.
|
|
75
|
+
* @since 1.0.0
|
|
76
|
+
*/
|
|
77
|
+
export declare const length: (p: CubicPath2d) => number;
|
|
78
|
+
export declare const solve: {
|
|
79
|
+
/**
|
|
80
|
+
* Solves a cubic path for a given parameter.
|
|
81
|
+
*
|
|
82
|
+
* @param u - The parameter to solve for.
|
|
83
|
+
* @returns A function that takes a cubic path and returns the solved vector.
|
|
84
|
+
* @since 1.0.0
|
|
85
|
+
*/
|
|
86
|
+
(u: number): (p: CubicPath2d) => Vector2;
|
|
87
|
+
/**
|
|
88
|
+
* Solves a cubic path for a given parameter.
|
|
89
|
+
*
|
|
90
|
+
* @param p - The cubic path to solve.
|
|
91
|
+
* @param u - The parameter to solve for.
|
|
92
|
+
* @returns The solved vector.
|
|
93
|
+
* @since 1.0.0
|
|
94
|
+
*/
|
|
95
|
+
(p: CubicPath2d, u: number): Vector2;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Serializes a cubic path as an SVG path data string (the value of a `<path>`
|
|
99
|
+
* element's `d` attribute), using `M` and `C` commands. Discontinuities between
|
|
100
|
+
* curves emit a fresh `M` command.
|
|
101
|
+
*
|
|
102
|
+
* @param p - The cubic path to serialize.
|
|
103
|
+
* @returns The SVG path data string.
|
|
104
|
+
* @since 2.0.0
|
|
105
|
+
*/
|
|
106
|
+
export declare const toPathData: (p: CubicPath2d) => string;
|
|
107
|
+
/**
|
|
108
|
+
* Type-narrowing predicate: refines `CubicPath2d<T>` to
|
|
109
|
+
* `CubicPath2d<T & Continuous>` when adjacent curves connect.
|
|
110
|
+
*
|
|
111
|
+
* @since 2.0.0
|
|
112
|
+
*/
|
|
113
|
+
export declare const isContinuous: <T>(p: CubicPath2d<T>) => p is CubicPath2d<T & Continuous>;
|
|
114
|
+
/**
|
|
115
|
+
* Asserts that the cubic path is continuous, throwing on failure.
|
|
116
|
+
*
|
|
117
|
+
* @since 2.0.0
|
|
118
|
+
*/
|
|
119
|
+
export declare const asContinuous: <T>(p: CubicPath2d<T>) => CubicPath2d<T & Continuous>;
|
|
120
|
+
export declare const solveByDistance: {
|
|
121
|
+
/**
|
|
122
|
+
* Solves a cubic path by normalized arc length. Unlike {@link solve}, which
|
|
123
|
+
* is parameterized by curve `u`, this samples points at constant speed along
|
|
124
|
+
* the path — `s = 0.5` returns the point exactly halfway along the curve by
|
|
125
|
+
* arc length, regardless of how the underlying parameterization stretches.
|
|
126
|
+
*
|
|
127
|
+
* Cumulative segment lengths are cached by path identity so repeated calls
|
|
128
|
+
* with the same path are fast.
|
|
129
|
+
*
|
|
130
|
+
* @param p - The cubic path to sample.
|
|
131
|
+
* @param s - Normalized arc length in `[0, 1]`. Values outside the range are
|
|
132
|
+
* clamped to path endpoints.
|
|
133
|
+
* @returns The point on the path at the given normalized arc length.
|
|
134
|
+
* @since 1.1.0
|
|
135
|
+
*/
|
|
136
|
+
(p: CubicPath2d, s: number): Vector2;
|
|
137
|
+
/**
|
|
138
|
+
* Solves a cubic path by normalized arc length.
|
|
139
|
+
*
|
|
140
|
+
* @param s - Normalized arc length in `[0, 1]`.
|
|
141
|
+
* @returns A function that takes a cubic path and returns the point at that
|
|
142
|
+
* arc length.
|
|
143
|
+
* @since 1.1.0
|
|
144
|
+
*/
|
|
145
|
+
(s: number): (p: CubicPath2d) => Vector2;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Computes the axis-aligned bounding box of the path — the smallest closed
|
|
149
|
+
* `Box2d` enclosing every segment.
|
|
150
|
+
*
|
|
151
|
+
* @param p - The cubic path.
|
|
152
|
+
* @returns A closed `Box2d` enclosing the path.
|
|
153
|
+
* @since 2.0.0
|
|
154
|
+
*/
|
|
155
|
+
export declare const boundingBox: (p: CubicPath2d) => Interval2d<Closed, Closed>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as LinearPath2dNs from './linear2d';
|
|
2
|
+
import * as QuadraticPath2dNs from './quadratic2d';
|
|
3
|
+
import * as CubicPath2dNs from './cubic2d';
|
|
4
|
+
import * as RationalCubicPath2dNs from './rationalCubic2d';
|
|
5
|
+
export { LinearPath2dNs as LinearPath2d };
|
|
6
|
+
export type LinearPath2d = LinearPath2dNs.LinearPath2d;
|
|
7
|
+
export { QuadraticPath2dNs as QuadraticPath2d };
|
|
8
|
+
export type QuadraticPath2d = QuadraticPath2dNs.QuadraticPath2d;
|
|
9
|
+
export { CubicPath2dNs as CubicPath2d };
|
|
10
|
+
export type CubicPath2d = CubicPath2dNs.CubicPath2d;
|
|
11
|
+
export { RationalCubicPath2dNs as RationalCubicPath2d };
|
|
12
|
+
export type RationalCubicPath2d = RationalCubicPath2dNs.RationalCubicPath2d;
|
package/dist/path/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { t as __exportAll } from "../shared/chunk-25Hzd3z8.mjs";
|
|
2
2
|
import { Pipeable, dual, invariant } from "../utils.mjs";
|
|
3
3
|
import { epsEquals } from "../number.mjs";
|
|
4
|
-
import { p as unit } from "../shared/interval-
|
|
5
|
-
import { r as union } from "../shared/interval2d-
|
|
6
|
-
import {
|
|
7
|
-
import { n as rationalCubic2d_exports, r as cubic2d_exports } from "../shared/rationalCubic2d-
|
|
4
|
+
import { p as unit } from "../shared/interval-X1EYuf-T.mjs";
|
|
5
|
+
import { r as union } from "../shared/interval2d-ca0J1NMr.mjs";
|
|
6
|
+
import { _ as length$4, f as boundingBox$5, g as boundingBox$4, h as solve$5, p as length$5, y as solve$4 } from "../shared/rationalCubic2d-D658ltUM.mjs";
|
|
7
|
+
import { n as rationalCubic2d_exports, r as cubic2d_exports } from "../shared/rationalCubic2d-Vw4qGPZj.mjs";
|
|
8
8
|
//#region src/path/linear2d.internal.ts
|
|
9
9
|
const LinearPath2dTypeId = Symbol("curvy/path/linear2d");
|
|
10
10
|
var LinearPath2dImpl = class extends Pipeable {
|
|
@@ -158,7 +158,7 @@ const asContinuous$2 = asContinuous$3;
|
|
|
158
158
|
*
|
|
159
159
|
* @param p - The linear path.
|
|
160
160
|
* @returns A closed `Box2d` enclosing the path.
|
|
161
|
-
* @since 2.
|
|
161
|
+
* @since 2.0.0
|
|
162
162
|
*/
|
|
163
163
|
const boundingBox$2 = boundingBox$3;
|
|
164
164
|
//#endregion
|
|
@@ -316,7 +316,7 @@ const asContinuous = asContinuous$1;
|
|
|
316
316
|
*
|
|
317
317
|
* @param p - The quadratic path.
|
|
318
318
|
* @returns A closed `Box2d` enclosing the path.
|
|
319
|
-
* @since 2.
|
|
319
|
+
* @since 2.0.0
|
|
320
320
|
*/
|
|
321
321
|
const boundingBox = boundingBox$1;
|
|
322
322
|
//#endregion
|
package/dist/path/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["isLinearPath2d","make","fromArray","append","length","LinearCurve2d.length","Interval.unit","solve","LinearCurve2d.solve","toPathData","isContinuous","asContinuous","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","boundingBox","internal.boundingBox","isQuadraticPath2d","make","fromArray","append","length","QuadraticCurve2d.length","Interval.unit","solve","QuadraticCurve2d.solve","toPathData","isContinuous","asContinuous","boundingBox","QuadraticCurve2d.boundingBox","Interval2d.union","internal.make","internal.fromArray","internal.isQuadraticPath2d","internal.append","internal.length","internal.solve","internal.toPathData","internal.isContinuous","internal.asContinuous","internal.boundingBox"],"sources":["../../src/path/linear2d.internal.ts","../../src/path/linear2d.ts","../../src/path/quadratic2d.internal.ts","../../src/path/quadratic2d.ts"],"sourcesContent":["import * as Interval2d from '../interval/interval2d'\nimport * as LinearCurve2d from '../curve/linear2d'\nimport * as Interval from '../interval/interval'\nimport { dual, Pipeable } from '../utils'\nimport { invariant } from '../utils'\nimport { epsEquals } from '../number'\nimport type { Vector2 } from '../vector/vector2'\nimport type { LinearPath2d } from './linear2d'\nimport { PathTraits, type Continuous } from './traits'\n\nexport const LinearPath2dTypeId: unique symbol = Symbol('curvy/path/linear2d')\nexport type LinearPath2dTypeId = typeof LinearPath2dTypeId\n\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\nexport const isLinearPath2d = (p: unknown): p is LinearPath2d =>\n typeof p === 'object' && p !== null && LinearPath2dTypeId in p\n\nexport const make = (...curves: ReadonlyArray<LinearCurve2d.LinearCurve2d>): LinearPath2d =>\n new LinearPath2dImpl(curves)\n\nexport const fromArray = (curves: ReadonlyArray<LinearCurve2d.LinearCurve2d>) =>\n new LinearPath2dImpl(curves)\n\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\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\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\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\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\nexport const asContinuous = <T>(p: LinearPath2d<T>): LinearPath2d<T & Continuous> => {\n invariant(isContinuous(p), 'linear path is not continuous')\n return p\n}\n\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'\nimport type { LinearCurve2d } from '../curve/linear2d'\nimport type { Closed } from '../interval/interval'\nimport type { Pipeable } from '../utils'\nimport type { Vector2 } from '../vector/vector2'\nimport type { LinearPath2dTypeId } from './linear2d.internal'\nimport * as internal from './linear2d.internal'\nimport type { Continuous, PathTraits } from './traits'\n\nexport type { Continuous } from './traits'\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 * 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.1.0\n */\nexport const boundingBox: (p: LinearPath2d) => Interval2d<Closed, Closed> = internal.boundingBox\n","import * as Interval2d from '../interval/interval2d'\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 type { Vector2 } from '../vector/vector2'\nimport type { QuadraticPath2d } from './quadratic2d'\nimport { PathTraits, type Continuous } from './traits'\n\nexport const QuadraticPath2dTypeId: unique symbol = Symbol('curvy/path/quadratic2d')\nexport type QuadraticPath2dTypeId = typeof QuadraticPath2dTypeId\n\nexport class QuadraticPath2dImpl extends Pipeable implements QuadraticPath2d<unknown> {\n readonly [QuadraticPath2dTypeId]: QuadraticPath2dTypeId = QuadraticPath2dTypeId\n declare readonly [PathTraits]: unknown\n\n readonly curves: ReadonlyArray<QuadraticCurve2d.QuadraticCurve2d>\n\n constructor(curves: ReadonlyArray<QuadraticCurve2d.QuadraticCurve2d>) {\n super()\n this.curves = curves\n }\n\n [Symbol.iterator](): Iterator<QuadraticCurve2d.QuadraticCurve2d> {\n return this.curves[Symbol.iterator]()\n }\n}\n\nexport const isQuadraticPath2d = (p: unknown): p is QuadraticPath2d =>\n typeof p === 'object' && p !== null && QuadraticPath2dTypeId in p\n\nexport const make = (\n ...curves: ReadonlyArray<QuadraticCurve2d.QuadraticCurve2d>\n): QuadraticPath2d => new QuadraticPath2dImpl(curves)\n\nexport const fromArray = (\n curves: ReadonlyArray<QuadraticCurve2d.QuadraticCurve2d>,\n): QuadraticPath2d => new QuadraticPath2dImpl(curves)\n\nexport const append = dual<\n (c: QuadraticCurve2d.QuadraticCurve2d) => (p: QuadraticPath2d) => QuadraticPath2d,\n (p: QuadraticPath2d, c: QuadraticCurve2d.QuadraticCurve2d) => QuadraticPath2d\n>(2, (p: QuadraticPath2d, c: QuadraticCurve2d.QuadraticCurve2d) => fromArray([...p, c]))\n\nexport const length = (p: QuadraticPath2d) => {\n let total = 0\n for (const curve of p) {\n total += QuadraticCurve2d.length(curve, Interval.unit)\n }\n\n return total\n}\n\nexport const solve = dual<\n (u: number) => (p: QuadraticPath2d) => Vector2,\n (p: QuadraticPath2d, u: number) => Vector2\n>(2, (p: QuadraticPath2d, u: number) => {\n const curves = p instanceof QuadraticPath2dImpl ? p.curves : [...p]\n\n if (u === 1) {\n const last = curves.at(-1) as QuadraticCurve2d.QuadraticCurve2d\n return QuadraticCurve2d.solve(last, 1)\n }\n\n const t = u * curves.length\n const i = Math.floor(t)\n const curve = curves[i] as QuadraticCurve2d.QuadraticCurve2d\n return QuadraticCurve2d.solve(curve, t - i)\n})\n\n// Quadratic Bernstein basis: P(t) = (1-t)²·p0 + 2(1-t)t·p1 + t²·p2\n// expanded gives c0 = p0, c1 = -2p0 + 2p1, c2 = p0 - 2p1 + p2, so:\n// p0 = c0, p1 = c0 + c1/2, p2 = c0 + c1 + c2.\nexport const toPathData = (p: QuadraticPath2d): 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\n const startX = c0x\n const startY = c0y\n const ctrlX = c0x + c1x / 2\n const ctrlY = c0y + c1y / 2\n const endX = c0x + c1x + c2x\n const endY = c0y + c1y + c2y\n\n if (!epsEquals(startX, prevEndX) || !epsEquals(startY, prevEndY)) {\n result += ` M ${startX},${startY}`\n }\n result += ` Q ${ctrlX},${ctrlY} ${endX},${endY}`\n\n prevEndX = endX\n prevEndY = endY\n }\n\n return result.slice(1)\n}\n\nexport const isContinuous = <T>(p: QuadraticPath2d<T>): p is QuadraticPath2d<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\n prevEndY = curve.y.c0 + curve.y.c1 + curve.y.c2\n first = false\n }\n return true\n}\n\nexport const asContinuous = <T>(p: QuadraticPath2d<T>): QuadraticPath2d<T & Continuous> => {\n invariant(isContinuous(p), 'quadratic path is not continuous')\n return p\n}\n\nexport const boundingBox = (\n p: QuadraticPath2d,\n): Interval2d.Interval2d<Interval.Closed, Interval.Closed> => {\n const iter = p[Symbol.iterator]()\n const first = iter.next()\n let acc = QuadraticCurve2d.boundingBox(first.value as QuadraticCurve2d.QuadraticCurve2d)\n for (let next = iter.next(); !next.done; next = iter.next()) {\n acc = Interval2d.union(acc, QuadraticCurve2d.boundingBox(next.value))\n }\n return acc\n}\n","import type { Interval2d } from '../interval/interval2d'\nimport type { QuadraticCurve2d } from '../curve/quadratic2d'\nimport type { Closed } from '../interval/interval'\nimport type { Pipeable } from '../utils'\nimport type { Vector2 } from '../vector/vector2'\nimport type { QuadraticPath2dTypeId } from './quadratic2d.internal'\nimport * as internal from './quadratic2d.internal'\nimport type { Continuous, PathTraits } from './traits'\n\nexport type { Continuous } from './traits'\n\n/**\n * A quadratic 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 QuadraticPath2d<out Trait = unknown> extends Pipeable, Iterable<QuadraticCurve2d> {\n readonly [QuadraticPath2dTypeId]: QuadraticPath2dTypeId\n readonly [PathTraits]: Trait\n}\n\n/**\n * Creates a new `QuadraticPath2d` instance from a sequence of curves.\n *\n * @param curves - The curves to create the path from.\n * @returns A new `QuadraticPath2d` instance.\n * @since 2.0.0\n */\nexport const make: (...curves: ReadonlyArray<QuadraticCurve2d>) => QuadraticPath2d = internal.make\n\n/**\n * Creates a new `QuadraticPath2d` instance from an array of curves.\n *\n * @param curves - The curves to create the path from.\n * @returns A new `QuadraticPath2d` instance.\n * @since 2.0.0\n */\nexport const fromArray: (curves: ReadonlyArray<QuadraticCurve2d>) => QuadraticPath2d =\n internal.fromArray\n\n/**\n * Checks if a value is a `QuadraticPath2d`.\n *\n * @param p - The value to check.\n * @returns `true` if the value is a `QuadraticPath2d`, `false` otherwise.\n * @since 1.0.0\n */\nexport const isQuadraticPath2d: (p: unknown) => p is QuadraticPath2d = internal.isQuadraticPath2d\n\nexport const append: {\n /**\n * Appends a quadratic curve to a quadratic path.\n *\n * @param c - The quadratic curve to append.\n * @returns A function that takes a quadratic path and returns a new quadratic path.\n * @since 1.0.0\n */\n (c: QuadraticCurve2d): (p: QuadraticPath2d) => QuadraticPath2d\n /**\n * Appends a quadratic curve to a quadratic path.\n *\n * @param p - The quadratic path to append to.\n * @param c - The quadratic curve to append.\n * @returns A new `QuadraticPath2d` instance with the appended curve.\n * @since 1.0.0\n */\n (p: QuadraticPath2d, c: QuadraticCurve2d): QuadraticPath2d\n} = internal.append\n\n/**\n * Calculates the length of a quadratic path.\n *\n * @param p - The quadratic path to calculate the length of.\n * @returns The length of the path.\n */\nexport const length: (p: QuadraticPath2d) => number = internal.length\n\nexport const solve: {\n /**\n * Solves a quadratic path at a given parameter.\n *\n * @param u - The parameter to solve for.\n * @returns A function that takes a quadratic path and returns the solved point.\n * @since 1.0.0\n */\n (u: number): (p: QuadraticPath2d) => Vector2\n /**\n * Solves a quadratic path at a given parameter.\n *\n * @param p - The quadratic path to solve.\n * @param u - The parameter to solve for.\n * @returns The solved point.\n * @since 1.0.0\n */\n (p: QuadraticPath2d, u: number): Vector2\n} = internal.solve\n\n/**\n * Serializes a quadratic path as an SVG path data string (the value of a\n * `<path>` element's `d` attribute), using `M` and `Q` commands. Discontinuities\n * between curves emit a fresh `M` command.\n *\n * @param p - The quadratic path to serialize.\n * @returns The SVG path data string.\n * @since 2.0.0\n */\nexport const toPathData: (p: QuadraticPath2d) => string = internal.toPathData\n\n/**\n * Type-narrowing predicate: refines `QuadraticPath2d<T>` to\n * `QuadraticPath2d<T & Continuous>` when adjacent curves connect.\n *\n * @since 2.0.0\n */\nexport const isContinuous: <T>(p: QuadraticPath2d<T>) => p is QuadraticPath2d<T & Continuous> =\n internal.isContinuous\n\n/**\n * Asserts that the quadratic path is continuous, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asContinuous: <T>(p: QuadraticPath2d<T>) => QuadraticPath2d<T & Continuous> =\n internal.asContinuous\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 quadratic path.\n * @returns A closed `Box2d` enclosing the path.\n * @since 2.1.0\n */\nexport const boundingBox: (p: QuadraticPath2d) => Interval2d<Closed, Closed> = internal.boundingBox\n"],"mappings":";;;;;;;;AAUA,MAAa,qBAAoC,OAAO,sBAAsB;AAG9E,IAAa,mBAAb,cAAsC,SAA0C;CAC9E,CAAU,sBAA0C;CAGpD;CAEA,YAAY,QAAoD;EAC9D,OAAO;EACP,KAAK,SAAS;;CAGhB,CAAC,OAAO,YAAmD;EACzD,OAAO,KAAK,OAAO,OAAO,WAAW;;;AAIzC,MAAaA,oBAAkB,MAC7B,OAAO,MAAM,YAAY,MAAM,QAAQ,sBAAsB;AAE/D,MAAaC,UAAQ,GAAG,WACtB,IAAI,iBAAiB,OAAO;AAE9B,MAAaC,eAAa,WACxB,IAAI,iBAAiB,OAAO;AAE9B,MAAaC,WAAS,KAGpB,IAAI,GAAiB,MAAmCD,YAAU,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC;AAE/E,MAAaE,YAAU,MAAoB;CACzC,IAAI,QAAQ;CACZ,KAAK,MAAM,SAAS,GAClB,SAASC,SAAqB,OAAOC,KAAc;CAGrD,OAAO;;AAGT,MAAaC,UAAQ,KAGnB,IAAI,GAAiB,MAAc;CACnC,MAAM,SAAS,aAAa,mBAAmB,EAAE,SAAS,CAAC,GAAG,EAAE;CAEhE,IAAI,MAAM,GAER,OAAOC,QADM,OAAO,GAAG,GACI,EAAM,EAAE;CAGrC,MAAM,IAAI,IAAI,OAAO;CACrB,MAAM,IAAI,KAAK,MAAM,EAAE;CACvB,MAAM,QAAQ,OAAO;CACrB,OAAOA,QAAoB,OAAO,IAAI,EAAE;EACxC;AAEF,MAAaC,gBAAc,MAA4B;CACrD,IAAI,SAAS;CACb,IAAI,WAAW;CACf,IAAI,WAAW;CAEf,KAAK,MAAM,SAAS,GAAG;EACrB,MAAM,SAAS,MAAM,EAAE;EACvB,MAAM,SAAS,MAAM,EAAE;EACvB,MAAM,OAAO,MAAM,EAAE,KAAK,MAAM,EAAE;EAClC,MAAM,OAAO,MAAM,EAAE,KAAK,MAAM,EAAE;EAElC,IAAI,CAAC,UAAU,QAAQ,SAAS,IAAI,CAAC,UAAU,QAAQ,SAAS,EAC9D,UAAU,MAAM,OAAO,GAAG;EAE5B,UAAU,MAAM,KAAK,GAAG;EAExB,WAAW;EACX,WAAW;;CAGb,OAAO,OAAO,MAAM,EAAE;;AAGxB,MAAaC,kBAAmB,MAA0D;CACxF,IAAI,WAAW;CACf,IAAI,WAAW;CACf,IAAI,QAAQ;CAEZ,KAAK,MAAM,SAAS,GAAG;EACrB,MAAM,SAAS,MAAM,EAAE;EACvB,MAAM,SAAS,MAAM,EAAE;EACvB,IAAI,CAAC,UAAU,CAAC,UAAU,QAAQ,SAAS,IAAI,CAAC,UAAU,QAAQ,SAAS,GACzE,OAAO;EAET,WAAW,MAAM,EAAE,KAAK,MAAM,EAAE;EAChC,WAAW,MAAM,EAAE,KAAK,MAAM,EAAE;EAChC,QAAQ;;CAEV,OAAO;;AAGT,MAAaC,kBAAmB,MAAqD;CACnF,UAAUD,eAAa,EAAE,EAAE,gCAAgC;CAC3D,OAAO;;AAGT,MAAaE,iBACX,MAC4D;CAC5D,MAAM,OAAO,EAAE,OAAO,WAAW;CAGjC,IAAI,MAAMC,cAFI,KAAK,MAEiB,CAAM,MAAqC;CAC/E,KAAK,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC,KAAK,MAAM,OAAO,KAAK,MAAM,EACzD,MAAMC,MAAiB,KAAKD,cAA0B,KAAK,MAAM,CAAC;CAEpE,OAAO;;;;;;;;;;;;;;;;;;;;;;;AC3FT,MAAaE,SAAkEC;;;;;;;;AAS/E,MAAaC,cAAoEC;;;;;;;;AASjF,MAAa,iBAAoDC;AAEjE,MAAaC,WAkBTC;;;;;;;;AASJ,MAAaC,WAAsCC;AAEnD,MAAaC,UAkBTC;;;;;;;;;;AAWJ,MAAaC,eAA0CC;;;;;;;;;;AAWvD,MAAaC,iBACXC;;;;;;;;;AAUF,MAAaC,iBACXC;;;;;;;;;AAUF,MAAaC,gBAA+DC;;;ACvI5E,MAAa,wBAAuC,OAAO,yBAAyB;AAGpF,IAAa,sBAAb,cAAyC,SAA6C;CACpF,CAAU,yBAAgD;CAG1D;CAEA,YAAY,QAA0D;EACpE,OAAO;EACP,KAAK,SAAS;;CAGhB,CAAC,OAAO,YAAyD;EAC/D,OAAO,KAAK,OAAO,OAAO,WAAW;;;AAIzC,MAAaC,uBAAqB,MAChC,OAAO,MAAM,YAAY,MAAM,QAAQ,yBAAyB;AAElE,MAAaC,UACX,GAAG,WACiB,IAAI,oBAAoB,OAAO;AAErD,MAAaC,eACX,WACoB,IAAI,oBAAoB,OAAO;AAErD,MAAaC,WAAS,KAGpB,IAAI,GAAoB,MAAyCD,YAAU,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC;AAExF,MAAaE,YAAU,MAAuB;CAC5C,IAAI,QAAQ;CACZ,KAAK,MAAM,SAAS,GAClB,SAASC,SAAwB,OAAOC,KAAc;CAGxD,OAAO;;AAGT,MAAaC,UAAQ,KAGnB,IAAI,GAAoB,MAAc;CACtC,MAAM,SAAS,aAAa,sBAAsB,EAAE,SAAS,CAAC,GAAG,EAAE;CAEnE,IAAI,MAAM,GAER,OAAOC,QADM,OAAO,GAAG,GACO,EAAM,EAAE;CAGxC,MAAM,IAAI,IAAI,OAAO;CACrB,MAAM,IAAI,KAAK,MAAM,EAAE;CACvB,MAAM,QAAQ,OAAO;CACrB,OAAOA,QAAuB,OAAO,IAAI,EAAE;EAC3C;AAKF,MAAaC,gBAAc,MAA+B;CACxD,IAAI,SAAS;CACb,IAAI,WAAW;CACf,IAAI,WAAW;CAEf,KAAK,MAAM,SAAS,GAAG;EACrB,MAAM,MAAM,MAAM,EAAE;EACpB,MAAM,MAAM,MAAM,EAAE;EACpB,MAAM,MAAM,MAAM,EAAE;EACpB,MAAM,MAAM,MAAM,EAAE;EACpB,MAAM,MAAM,MAAM,EAAE;EACpB,MAAM,MAAM,MAAM,EAAE;EAEpB,MAAM,SAAS;EACf,MAAM,SAAS;EACf,MAAM,QAAQ,MAAM,MAAM;EAC1B,MAAM,QAAQ,MAAM,MAAM;EAC1B,MAAM,OAAO,MAAM,MAAM;EACzB,MAAM,OAAO,MAAM,MAAM;EAEzB,IAAI,CAAC,UAAU,QAAQ,SAAS,IAAI,CAAC,UAAU,QAAQ,SAAS,EAC9D,UAAU,MAAM,OAAO,GAAG;EAE5B,UAAU,MAAM,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG;EAE1C,WAAW;EACX,WAAW;;CAGb,OAAO,OAAO,MAAM,EAAE;;AAGxB,MAAaC,kBAAmB,MAAgE;CAC9F,IAAI,WAAW;CACf,IAAI,WAAW;CACf,IAAI,QAAQ;CAEZ,KAAK,MAAM,SAAS,GAAG;EACrB,MAAM,SAAS,MAAM,EAAE;EACvB,MAAM,SAAS,MAAM,EAAE;EACvB,IAAI,CAAC,UAAU,CAAC,UAAU,QAAQ,SAAS,IAAI,CAAC,UAAU,QAAQ,SAAS,GACzE,OAAO;EAET,WAAW,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE;EAC7C,WAAW,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE;EAC7C,QAAQ;;CAEV,OAAO;;AAGT,MAAaC,kBAAmB,MAA2D;CACzF,UAAUD,eAAa,EAAE,EAAE,mCAAmC;CAC9D,OAAO;;AAGT,MAAaE,iBACX,MAC4D;CAC5D,MAAM,OAAO,EAAE,OAAO,WAAW;CAEjC,IAAI,MAAMC,cADI,KAAK,MACoB,CAAM,MAA2C;CACxF,KAAK,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC,KAAK,MAAM,OAAO,KAAK,MAAM,EACzD,MAAMC,MAAiB,KAAKD,cAA6B,KAAK,MAAM,CAAC;CAEvE,OAAO;;;;;;;;;;;;;;;;;;;;;;;ACzGT,MAAa,OAAwEE;;;;;;;;AASrF,MAAa,YACXC;;;;;;;;AASF,MAAa,oBAA0DC;AAEvE,MAAa,SAkBTC;;;;;;;AAQJ,MAAa,SAAyCC;AAEtD,MAAa,QAkBTC;;;;;;;;;;AAWJ,MAAa,aAA6CC;;;;;;;AAQ1D,MAAa,eACXC;;;;;;AAOF,MAAa,eACXC;;;;;;;;;AAUF,MAAa,cAAkEC"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["isLinearPath2d","make","fromArray","append","length","LinearCurve2d.length","Interval.unit","solve","LinearCurve2d.solve","toPathData","isContinuous","asContinuous","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","boundingBox","internal.boundingBox","isQuadraticPath2d","make","fromArray","append","length","QuadraticCurve2d.length","Interval.unit","solve","QuadraticCurve2d.solve","toPathData","isContinuous","asContinuous","boundingBox","QuadraticCurve2d.boundingBox","Interval2d.union","internal.make","internal.fromArray","internal.isQuadraticPath2d","internal.append","internal.length","internal.solve","internal.toPathData","internal.isContinuous","internal.asContinuous","internal.boundingBox"],"sources":["../../src/path/linear2d.internal.ts","../../src/path/linear2d.ts","../../src/path/quadratic2d.internal.ts","../../src/path/quadratic2d.ts"],"sourcesContent":["import * as Interval2d from '../interval/interval2d'\nimport * as LinearCurve2d from '../curve/linear2d'\nimport * as Interval from '../interval/interval'\nimport { dual, Pipeable } from '../utils'\nimport { invariant } from '../utils'\nimport { epsEquals } from '../number'\nimport type { Vector2 } from '../vector/vector2'\nimport type { LinearPath2d } from './linear2d'\nimport { PathTraits, type Continuous } from './traits'\n\nexport const LinearPath2dTypeId: unique symbol = Symbol('curvy/path/linear2d')\nexport type LinearPath2dTypeId = typeof LinearPath2dTypeId\n\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\nexport const isLinearPath2d = (p: unknown): p is LinearPath2d =>\n typeof p === 'object' && p !== null && LinearPath2dTypeId in p\n\nexport const make = (...curves: ReadonlyArray<LinearCurve2d.LinearCurve2d>): LinearPath2d =>\n new LinearPath2dImpl(curves)\n\nexport const fromArray = (curves: ReadonlyArray<LinearCurve2d.LinearCurve2d>) =>\n new LinearPath2dImpl(curves)\n\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\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\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\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\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\nexport const asContinuous = <T>(p: LinearPath2d<T>): LinearPath2d<T & Continuous> => {\n invariant(isContinuous(p), 'linear path is not continuous')\n return p\n}\n\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'\nimport type { LinearCurve2d } from '../curve/linear2d'\nimport type { Closed } from '../interval/interval'\nimport type { Pipeable } from '../utils'\nimport type { Vector2 } from '../vector/vector2'\nimport type { LinearPath2dTypeId } from './linear2d.internal'\nimport * as internal from './linear2d.internal'\nimport type { Continuous, PathTraits } from './traits'\n\nexport type { Continuous } from './traits'\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 * 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'\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 type { Vector2 } from '../vector/vector2'\nimport type { QuadraticPath2d } from './quadratic2d'\nimport { PathTraits, type Continuous } from './traits'\n\nexport const QuadraticPath2dTypeId: unique symbol = Symbol('curvy/path/quadratic2d')\nexport type QuadraticPath2dTypeId = typeof QuadraticPath2dTypeId\n\nexport class QuadraticPath2dImpl extends Pipeable implements QuadraticPath2d<unknown> {\n readonly [QuadraticPath2dTypeId]: QuadraticPath2dTypeId = QuadraticPath2dTypeId\n declare readonly [PathTraits]: unknown\n\n readonly curves: ReadonlyArray<QuadraticCurve2d.QuadraticCurve2d>\n\n constructor(curves: ReadonlyArray<QuadraticCurve2d.QuadraticCurve2d>) {\n super()\n this.curves = curves\n }\n\n [Symbol.iterator](): Iterator<QuadraticCurve2d.QuadraticCurve2d> {\n return this.curves[Symbol.iterator]()\n }\n}\n\nexport const isQuadraticPath2d = (p: unknown): p is QuadraticPath2d =>\n typeof p === 'object' && p !== null && QuadraticPath2dTypeId in p\n\nexport const make = (\n ...curves: ReadonlyArray<QuadraticCurve2d.QuadraticCurve2d>\n): QuadraticPath2d => new QuadraticPath2dImpl(curves)\n\nexport const fromArray = (\n curves: ReadonlyArray<QuadraticCurve2d.QuadraticCurve2d>,\n): QuadraticPath2d => new QuadraticPath2dImpl(curves)\n\nexport const append = dual<\n (c: QuadraticCurve2d.QuadraticCurve2d) => (p: QuadraticPath2d) => QuadraticPath2d,\n (p: QuadraticPath2d, c: QuadraticCurve2d.QuadraticCurve2d) => QuadraticPath2d\n>(2, (p: QuadraticPath2d, c: QuadraticCurve2d.QuadraticCurve2d) => fromArray([...p, c]))\n\nexport const length = (p: QuadraticPath2d) => {\n let total = 0\n for (const curve of p) {\n total += QuadraticCurve2d.length(curve, Interval.unit)\n }\n\n return total\n}\n\nexport const solve = dual<\n (u: number) => (p: QuadraticPath2d) => Vector2,\n (p: QuadraticPath2d, u: number) => Vector2\n>(2, (p: QuadraticPath2d, u: number) => {\n const curves = p instanceof QuadraticPath2dImpl ? p.curves : [...p]\n\n if (u === 1) {\n const last = curves.at(-1) as QuadraticCurve2d.QuadraticCurve2d\n return QuadraticCurve2d.solve(last, 1)\n }\n\n const t = u * curves.length\n const i = Math.floor(t)\n const curve = curves[i] as QuadraticCurve2d.QuadraticCurve2d\n return QuadraticCurve2d.solve(curve, t - i)\n})\n\n// Quadratic Bernstein basis: P(t) = (1-t)²·p0 + 2(1-t)t·p1 + t²·p2\n// expanded gives c0 = p0, c1 = -2p0 + 2p1, c2 = p0 - 2p1 + p2, so:\n// p0 = c0, p1 = c0 + c1/2, p2 = c0 + c1 + c2.\nexport const toPathData = (p: QuadraticPath2d): 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\n const startX = c0x\n const startY = c0y\n const ctrlX = c0x + c1x / 2\n const ctrlY = c0y + c1y / 2\n const endX = c0x + c1x + c2x\n const endY = c0y + c1y + c2y\n\n if (!epsEquals(startX, prevEndX) || !epsEquals(startY, prevEndY)) {\n result += ` M ${startX},${startY}`\n }\n result += ` Q ${ctrlX},${ctrlY} ${endX},${endY}`\n\n prevEndX = endX\n prevEndY = endY\n }\n\n return result.slice(1)\n}\n\nexport const isContinuous = <T>(p: QuadraticPath2d<T>): p is QuadraticPath2d<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\n prevEndY = curve.y.c0 + curve.y.c1 + curve.y.c2\n first = false\n }\n return true\n}\n\nexport const asContinuous = <T>(p: QuadraticPath2d<T>): QuadraticPath2d<T & Continuous> => {\n invariant(isContinuous(p), 'quadratic path is not continuous')\n return p\n}\n\nexport const boundingBox = (\n p: QuadraticPath2d,\n): Interval2d.Interval2d<Interval.Closed, Interval.Closed> => {\n const iter = p[Symbol.iterator]()\n const first = iter.next()\n let acc = QuadraticCurve2d.boundingBox(first.value as QuadraticCurve2d.QuadraticCurve2d)\n for (let next = iter.next(); !next.done; next = iter.next()) {\n acc = Interval2d.union(acc, QuadraticCurve2d.boundingBox(next.value))\n }\n return acc\n}\n","import type { Interval2d } from '../interval/interval2d'\nimport type { QuadraticCurve2d } from '../curve/quadratic2d'\nimport type { Closed } from '../interval/interval'\nimport type { Pipeable } from '../utils'\nimport type { Vector2 } from '../vector/vector2'\nimport type { QuadraticPath2dTypeId } from './quadratic2d.internal'\nimport * as internal from './quadratic2d.internal'\nimport type { Continuous, PathTraits } from './traits'\n\nexport type { Continuous } from './traits'\n\n/**\n * A quadratic 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 QuadraticPath2d<out Trait = unknown> extends Pipeable, Iterable<QuadraticCurve2d> {\n readonly [QuadraticPath2dTypeId]: QuadraticPath2dTypeId\n readonly [PathTraits]: Trait\n}\n\n/**\n * Creates a new `QuadraticPath2d` instance from a sequence of curves.\n *\n * @param curves - The curves to create the path from.\n * @returns A new `QuadraticPath2d` instance.\n * @since 2.0.0\n */\nexport const make: (...curves: ReadonlyArray<QuadraticCurve2d>) => QuadraticPath2d = internal.make\n\n/**\n * Creates a new `QuadraticPath2d` instance from an array of curves.\n *\n * @param curves - The curves to create the path from.\n * @returns A new `QuadraticPath2d` instance.\n * @since 2.0.0\n */\nexport const fromArray: (curves: ReadonlyArray<QuadraticCurve2d>) => QuadraticPath2d =\n internal.fromArray\n\n/**\n * Checks if a value is a `QuadraticPath2d`.\n *\n * @param p - The value to check.\n * @returns `true` if the value is a `QuadraticPath2d`, `false` otherwise.\n * @since 1.0.0\n */\nexport const isQuadraticPath2d: (p: unknown) => p is QuadraticPath2d = internal.isQuadraticPath2d\n\nexport const append: {\n /**\n * Appends a quadratic curve to a quadratic path.\n *\n * @param c - The quadratic curve to append.\n * @returns A function that takes a quadratic path and returns a new quadratic path.\n * @since 1.0.0\n */\n (c: QuadraticCurve2d): (p: QuadraticPath2d) => QuadraticPath2d\n /**\n * Appends a quadratic curve to a quadratic path.\n *\n * @param p - The quadratic path to append to.\n * @param c - The quadratic curve to append.\n * @returns A new `QuadraticPath2d` instance with the appended curve.\n * @since 1.0.0\n */\n (p: QuadraticPath2d, c: QuadraticCurve2d): QuadraticPath2d\n} = internal.append\n\n/**\n * Calculates the length of a quadratic path.\n *\n * @param p - The quadratic path to calculate the length of.\n * @returns The length of the path.\n */\nexport const length: (p: QuadraticPath2d) => number = internal.length\n\nexport const solve: {\n /**\n * Solves a quadratic path at a given parameter.\n *\n * @param u - The parameter to solve for.\n * @returns A function that takes a quadratic path and returns the solved point.\n * @since 1.0.0\n */\n (u: number): (p: QuadraticPath2d) => Vector2\n /**\n * Solves a quadratic path at a given parameter.\n *\n * @param p - The quadratic path to solve.\n * @param u - The parameter to solve for.\n * @returns The solved point.\n * @since 1.0.0\n */\n (p: QuadraticPath2d, u: number): Vector2\n} = internal.solve\n\n/**\n * Serializes a quadratic path as an SVG path data string (the value of a\n * `<path>` element's `d` attribute), using `M` and `Q` commands. Discontinuities\n * between curves emit a fresh `M` command.\n *\n * @param p - The quadratic path to serialize.\n * @returns The SVG path data string.\n * @since 2.0.0\n */\nexport const toPathData: (p: QuadraticPath2d) => string = internal.toPathData\n\n/**\n * Type-narrowing predicate: refines `QuadraticPath2d<T>` to\n * `QuadraticPath2d<T & Continuous>` when adjacent curves connect.\n *\n * @since 2.0.0\n */\nexport const isContinuous: <T>(p: QuadraticPath2d<T>) => p is QuadraticPath2d<T & Continuous> =\n internal.isContinuous\n\n/**\n * Asserts that the quadratic path is continuous, throwing on failure.\n *\n * @since 2.0.0\n */\nexport const asContinuous: <T>(p: QuadraticPath2d<T>) => QuadraticPath2d<T & Continuous> =\n internal.asContinuous\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 quadratic path.\n * @returns A closed `Box2d` enclosing the path.\n * @since 2.0.0\n */\nexport const boundingBox: (p: QuadraticPath2d) => Interval2d<Closed, Closed> = internal.boundingBox\n"],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { Interval2d } from '../interval/interval2d';
|
|
2
|
+
import type { LinearCurve2d } from '../curve/linear2d';
|
|
3
|
+
import type { Closed } from '../interval/interval';
|
|
4
|
+
import type { Pipeable } from '../utils';
|
|
5
|
+
import type { Vector2 } from '../vector/vector2';
|
|
6
|
+
|
|
7
|
+
import type { Continuous, PathTraits } from './traits';
|
|
8
|
+
|
|
9
|
+
declare const LinearPath2dTypeId: unique symbol;
|
|
10
|
+
type LinearPath2dTypeId = typeof LinearPath2dTypeId;
|
|
11
|
+
|
|
12
|
+
export type { Continuous } from './traits';
|
|
13
|
+
/**
|
|
14
|
+
* A linear path in 2D space.
|
|
15
|
+
*
|
|
16
|
+
* All fields are readonly and immutable, and all operations create new instances.
|
|
17
|
+
*
|
|
18
|
+
* The `Trait` type parameter accumulates trait brands as the path is refined
|
|
19
|
+
* via `isContinuous` / `asContinuous`. A `Continuous` path's `toPathData`
|
|
20
|
+
* skips the per-segment discontinuity check.
|
|
21
|
+
*
|
|
22
|
+
* @since 1.0.0
|
|
23
|
+
*/
|
|
24
|
+
export interface LinearPath2d<out Trait = unknown> extends Pipeable, Iterable<LinearCurve2d> {
|
|
25
|
+
readonly [LinearPath2dTypeId]: LinearPath2dTypeId;
|
|
26
|
+
readonly [PathTraits]: Trait;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates a new `LinearPath2d` instance from a sequence of curves.
|
|
30
|
+
*
|
|
31
|
+
* @param curves - The curves to create the path from.
|
|
32
|
+
* @returns A new `LinearPath2d` instance.
|
|
33
|
+
* @since 2.0.0
|
|
34
|
+
*/
|
|
35
|
+
export declare const make: (...curves: ReadonlyArray<LinearCurve2d>) => LinearPath2d;
|
|
36
|
+
/**
|
|
37
|
+
* Creates a new `LinearPath2d` instance from an array of curves.
|
|
38
|
+
*
|
|
39
|
+
* @param curves - The curves to create the path from.
|
|
40
|
+
* @returns A new `LinearPath2d` instance.
|
|
41
|
+
* @since 2.0.0
|
|
42
|
+
*/
|
|
43
|
+
export declare const fromArray: (curves: ReadonlyArray<LinearCurve2d>) => LinearPath2d;
|
|
44
|
+
/**
|
|
45
|
+
* Checks if a value is a `LinearPath2d`.
|
|
46
|
+
*
|
|
47
|
+
* @param p - The value to check.
|
|
48
|
+
* @returns `true` if the value is a `LinearPath2d`, `false` otherwise.
|
|
49
|
+
* @since 1.0.0
|
|
50
|
+
*/
|
|
51
|
+
export declare const isLinearPath2d: (p: unknown) => p is LinearPath2d;
|
|
52
|
+
export declare const append: {
|
|
53
|
+
/**
|
|
54
|
+
* Appends a linear curve to a linear path.
|
|
55
|
+
*
|
|
56
|
+
* @param c - The linear curve to append.
|
|
57
|
+
* @returns A function that takes a linear path and returns a new linear path.
|
|
58
|
+
* @since 1.0.0
|
|
59
|
+
*/
|
|
60
|
+
(c: LinearCurve2d): (p: LinearPath2d) => LinearPath2d;
|
|
61
|
+
/**
|
|
62
|
+
* Appends a linear curve to a linear path.
|
|
63
|
+
*
|
|
64
|
+
* @param p - The linear path to append to.
|
|
65
|
+
* @param c - The linear curve to append.
|
|
66
|
+
* @returns A new `LinearPath2d` instance with the appended curve.
|
|
67
|
+
* @since 1.0.0
|
|
68
|
+
*/
|
|
69
|
+
(p: LinearPath2d, c: LinearCurve2d): LinearPath2d;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Calculates the length of a linear path.
|
|
73
|
+
*
|
|
74
|
+
* @param p - The linear path to calculate the length of.
|
|
75
|
+
* @returns The length of the linear path.
|
|
76
|
+
* @since 1.0.0
|
|
77
|
+
*/
|
|
78
|
+
export declare const length: (p: LinearPath2d) => number;
|
|
79
|
+
export declare const solve: {
|
|
80
|
+
/**
|
|
81
|
+
* Solves a linear path for a given parameter.
|
|
82
|
+
*
|
|
83
|
+
* @param u - The parameter to solve for.
|
|
84
|
+
* @returns A function that takes a linear path and returns the solved point.
|
|
85
|
+
* @since 1.0.0
|
|
86
|
+
*/
|
|
87
|
+
(u: number): (p: LinearPath2d) => Vector2;
|
|
88
|
+
/**
|
|
89
|
+
* Solves a linear path for a given parameter.
|
|
90
|
+
*
|
|
91
|
+
* @param p - The linear path to solve.
|
|
92
|
+
* @param u - The parameter to solve for.
|
|
93
|
+
* @returns The solved point on the linear path.
|
|
94
|
+
* @since 1.0.0
|
|
95
|
+
*/
|
|
96
|
+
(p: LinearPath2d, u: number): Vector2;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Serializes a linear path as an SVG path data string (the value of a `<path>`
|
|
100
|
+
* element's `d` attribute), using `M` and `L` commands. Discontinuities between
|
|
101
|
+
* curves emit a fresh `M` command.
|
|
102
|
+
*
|
|
103
|
+
* @param p - The linear path to serialize.
|
|
104
|
+
* @returns The SVG path data string.
|
|
105
|
+
* @since 2.0.0
|
|
106
|
+
*/
|
|
107
|
+
export declare const toPathData: (p: LinearPath2d) => string;
|
|
108
|
+
/**
|
|
109
|
+
* Type-narrowing predicate: refines `LinearPath2d<T>` to
|
|
110
|
+
* `LinearPath2d<T & Continuous>` when adjacent curves connect at their join
|
|
111
|
+
* points.
|
|
112
|
+
*
|
|
113
|
+
* @param p - The linear path to check.
|
|
114
|
+
* @returns `true` when the path is continuous (G⁰).
|
|
115
|
+
* @since 2.0.0
|
|
116
|
+
*/
|
|
117
|
+
export declare const isContinuous: <T>(p: LinearPath2d<T>) => p is LinearPath2d<T & Continuous>;
|
|
118
|
+
/**
|
|
119
|
+
* Asserts that the linear path is continuous, throwing on failure.
|
|
120
|
+
*
|
|
121
|
+
* @param p - The linear path to assert against.
|
|
122
|
+
* @returns The same path, typed with the `Continuous` brand.
|
|
123
|
+
* @throws When the path has a discontinuity between adjacent curves.
|
|
124
|
+
* @since 2.0.0
|
|
125
|
+
*/
|
|
126
|
+
export declare const asContinuous: <T>(p: LinearPath2d<T>) => LinearPath2d<T & Continuous>;
|
|
127
|
+
/**
|
|
128
|
+
* Computes the axis-aligned bounding box of the path — the smallest closed
|
|
129
|
+
* `Box2d` enclosing every segment.
|
|
130
|
+
*
|
|
131
|
+
* @param p - The linear path.
|
|
132
|
+
* @returns A closed `Box2d` enclosing the path.
|
|
133
|
+
* @since 2.0.0
|
|
134
|
+
*/
|
|
135
|
+
export declare const boundingBox: (p: LinearPath2d) => Interval2d<Closed, Closed>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { Interval2d } from '../interval/interval2d';
|
|
2
|
+
import type { QuadraticCurve2d } from '../curve/quadratic2d';
|
|
3
|
+
import type { Closed } from '../interval/interval';
|
|
4
|
+
import type { Pipeable } from '../utils';
|
|
5
|
+
import type { Vector2 } from '../vector/vector2';
|
|
6
|
+
|
|
7
|
+
import type { Continuous, PathTraits } from './traits';
|
|
8
|
+
|
|
9
|
+
declare const QuadraticPath2dTypeId: unique symbol;
|
|
10
|
+
type QuadraticPath2dTypeId = typeof QuadraticPath2dTypeId;
|
|
11
|
+
|
|
12
|
+
export type { Continuous } from './traits';
|
|
13
|
+
/**
|
|
14
|
+
* A quadratic path in 2D space.
|
|
15
|
+
*
|
|
16
|
+
* All fields are readonly and immutable, and all operations create new instances.
|
|
17
|
+
*
|
|
18
|
+
* The `Trait` type parameter accumulates trait brands as the path is refined
|
|
19
|
+
* via `isContinuous` / `asContinuous`.
|
|
20
|
+
*
|
|
21
|
+
* @since 1.0.0
|
|
22
|
+
*/
|
|
23
|
+
export interface QuadraticPath2d<out Trait = unknown> extends Pipeable, Iterable<QuadraticCurve2d> {
|
|
24
|
+
readonly [QuadraticPath2dTypeId]: QuadraticPath2dTypeId;
|
|
25
|
+
readonly [PathTraits]: Trait;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Creates a new `QuadraticPath2d` instance from a sequence of curves.
|
|
29
|
+
*
|
|
30
|
+
* @param curves - The curves to create the path from.
|
|
31
|
+
* @returns A new `QuadraticPath2d` instance.
|
|
32
|
+
* @since 2.0.0
|
|
33
|
+
*/
|
|
34
|
+
export declare const make: (...curves: ReadonlyArray<QuadraticCurve2d>) => QuadraticPath2d;
|
|
35
|
+
/**
|
|
36
|
+
* Creates a new `QuadraticPath2d` instance from an array of curves.
|
|
37
|
+
*
|
|
38
|
+
* @param curves - The curves to create the path from.
|
|
39
|
+
* @returns A new `QuadraticPath2d` instance.
|
|
40
|
+
* @since 2.0.0
|
|
41
|
+
*/
|
|
42
|
+
export declare const fromArray: (curves: ReadonlyArray<QuadraticCurve2d>) => QuadraticPath2d;
|
|
43
|
+
/**
|
|
44
|
+
* Checks if a value is a `QuadraticPath2d`.
|
|
45
|
+
*
|
|
46
|
+
* @param p - The value to check.
|
|
47
|
+
* @returns `true` if the value is a `QuadraticPath2d`, `false` otherwise.
|
|
48
|
+
* @since 1.0.0
|
|
49
|
+
*/
|
|
50
|
+
export declare const isQuadraticPath2d: (p: unknown) => p is QuadraticPath2d;
|
|
51
|
+
export declare const append: {
|
|
52
|
+
/**
|
|
53
|
+
* Appends a quadratic curve to a quadratic path.
|
|
54
|
+
*
|
|
55
|
+
* @param c - The quadratic curve to append.
|
|
56
|
+
* @returns A function that takes a quadratic path and returns a new quadratic path.
|
|
57
|
+
* @since 1.0.0
|
|
58
|
+
*/
|
|
59
|
+
(c: QuadraticCurve2d): (p: QuadraticPath2d) => QuadraticPath2d;
|
|
60
|
+
/**
|
|
61
|
+
* Appends a quadratic curve to a quadratic path.
|
|
62
|
+
*
|
|
63
|
+
* @param p - The quadratic path to append to.
|
|
64
|
+
* @param c - The quadratic curve to append.
|
|
65
|
+
* @returns A new `QuadraticPath2d` instance with the appended curve.
|
|
66
|
+
* @since 1.0.0
|
|
67
|
+
*/
|
|
68
|
+
(p: QuadraticPath2d, c: QuadraticCurve2d): QuadraticPath2d;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Calculates the length of a quadratic path.
|
|
72
|
+
*
|
|
73
|
+
* @param p - The quadratic path to calculate the length of.
|
|
74
|
+
* @returns The length of the path.
|
|
75
|
+
*/
|
|
76
|
+
export declare const length: (p: QuadraticPath2d) => number;
|
|
77
|
+
export declare const solve: {
|
|
78
|
+
/**
|
|
79
|
+
* Solves a quadratic path at a given parameter.
|
|
80
|
+
*
|
|
81
|
+
* @param u - The parameter to solve for.
|
|
82
|
+
* @returns A function that takes a quadratic path and returns the solved point.
|
|
83
|
+
* @since 1.0.0
|
|
84
|
+
*/
|
|
85
|
+
(u: number): (p: QuadraticPath2d) => Vector2;
|
|
86
|
+
/**
|
|
87
|
+
* Solves a quadratic path at a given parameter.
|
|
88
|
+
*
|
|
89
|
+
* @param p - The quadratic path to solve.
|
|
90
|
+
* @param u - The parameter to solve for.
|
|
91
|
+
* @returns The solved point.
|
|
92
|
+
* @since 1.0.0
|
|
93
|
+
*/
|
|
94
|
+
(p: QuadraticPath2d, u: number): Vector2;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Serializes a quadratic path as an SVG path data string (the value of a
|
|
98
|
+
* `<path>` element's `d` attribute), using `M` and `Q` commands. Discontinuities
|
|
99
|
+
* between curves emit a fresh `M` command.
|
|
100
|
+
*
|
|
101
|
+
* @param p - The quadratic path to serialize.
|
|
102
|
+
* @returns The SVG path data string.
|
|
103
|
+
* @since 2.0.0
|
|
104
|
+
*/
|
|
105
|
+
export declare const toPathData: (p: QuadraticPath2d) => string;
|
|
106
|
+
/**
|
|
107
|
+
* Type-narrowing predicate: refines `QuadraticPath2d<T>` to
|
|
108
|
+
* `QuadraticPath2d<T & Continuous>` when adjacent curves connect.
|
|
109
|
+
*
|
|
110
|
+
* @since 2.0.0
|
|
111
|
+
*/
|
|
112
|
+
export declare const isContinuous: <T>(p: QuadraticPath2d<T>) => p is QuadraticPath2d<T & Continuous>;
|
|
113
|
+
/**
|
|
114
|
+
* Asserts that the quadratic path is continuous, throwing on failure.
|
|
115
|
+
*
|
|
116
|
+
* @since 2.0.0
|
|
117
|
+
*/
|
|
118
|
+
export declare const asContinuous: <T>(p: QuadraticPath2d<T>) => QuadraticPath2d<T & Continuous>;
|
|
119
|
+
/**
|
|
120
|
+
* Computes the axis-aligned bounding box of the path — the smallest closed
|
|
121
|
+
* `Box2d` enclosing every segment.
|
|
122
|
+
*
|
|
123
|
+
* @param p - The quadratic path.
|
|
124
|
+
* @returns A closed `Box2d` enclosing the path.
|
|
125
|
+
* @since 2.0.0
|
|
126
|
+
*/
|
|
127
|
+
export declare const boundingBox: (p: QuadraticPath2d) => Interval2d<Closed, Closed>;
|