@weasel-js/geom 1.10.0 → 1.11.0
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/README.md +140 -16
- package/dist/3d/index.d.ts +29 -2
- package/dist/3d/index.js +49 -1
- package/dist/3d/index.js.map +1 -1
- package/dist/booleans/index.d.ts +34 -10
- package/dist/booleans/index.js +344 -352
- package/dist/booleans/index.js.map +1 -1
- package/dist/{chunk-MDT7F32A.js → chunk-6XSJY3TC.js} +10 -39
- package/dist/chunk-6XSJY3TC.js.map +1 -0
- package/dist/chunk-7KLJZFBY.js +573 -0
- package/dist/chunk-7KLJZFBY.js.map +1 -0
- package/dist/chunk-B53BERKG.js +386 -0
- package/dist/chunk-B53BERKG.js.map +1 -0
- package/dist/chunk-CE7IY7TB.js +104 -0
- package/dist/chunk-CE7IY7TB.js.map +1 -0
- package/dist/chunk-HGF5OVEN.js +129 -0
- package/dist/chunk-HGF5OVEN.js.map +1 -0
- package/dist/chunk-J2O2B54M.js +800 -0
- package/dist/chunk-J2O2B54M.js.map +1 -0
- package/dist/chunk-Q66NA2FU.js +174 -0
- package/dist/chunk-Q66NA2FU.js.map +1 -0
- package/dist/chunk-SASMXDBE.js +443 -0
- package/dist/chunk-SASMXDBE.js.map +1 -0
- package/dist/chunk-UI3FUWXM.js +533 -0
- package/dist/chunk-UI3FUWXM.js.map +1 -0
- package/dist/curvature-PkoLduGc.d.ts +454 -0
- package/dist/curves/index.d.ts +14 -5
- package/dist/curves/index.js +33 -111
- package/dist/curves/index.js.map +1 -1
- package/dist/index.d.ts +1697 -205
- package/dist/index.js +4729 -1308
- package/dist/index.js.map +1 -1
- package/dist/nd/index.d.ts +91 -27
- package/dist/nd/index.js +282 -0
- package/dist/nd/index.js.map +1 -1
- package/dist/path-BW8d_2RY.d.ts +157 -0
- package/dist/portCurve-C5HDWuuV.d.ts +30 -0
- package/dist/tessellate/index.d.ts +18 -4
- package/dist/tessellate/index.js +21 -277
- package/dist/tessellate/index.js.map +1 -1
- package/dist/warp/index.d.ts +252 -0
- package/dist/warp/index.js +1316 -0
- package/dist/warp/index.js.map +1 -0
- package/package.json +5 -1
- package/dist/chunk-MDT7F32A.js.map +0 -1
- package/dist/chunk-OXH3NOXC.js +0 -62
- package/dist/chunk-OXH3NOXC.js.map +0 -1
- package/dist/chunk-URQMDR6Q.js +0 -80
- package/dist/chunk-URQMDR6Q.js.map +0 -1
- package/dist/chunk-WQMYOCFB.js +0 -167
- package/dist/chunk-WQMYOCFB.js.map +0 -1
- package/dist/chunk-XS6ERH3X.js +0 -34
- package/dist/chunk-XS6ERH3X.js.map +0 -1
- package/dist/cubicMath-CFXbq6vp.d.ts +0 -116
- package/dist/path-Bf9KeVxC.d.ts +0 -44
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export {
|
|
1
|
+
import { c as PathOpenFill, P as PolygonPath, d as PathFillRule, a as Path, R as RectPath, b as Point, C as CornerSpec, e as CornerPiece } from './path-BW8d_2RY.js';
|
|
2
|
+
export { f as CORNER_FIT_TOLERANCE, g as CORNER_KEYWORDS, h as CornerKeyword, i as CornerShape, j as CornerShapeFrame, k as compactCorners, l as cornerAt, m as cornerCenter, n as cornerKeywordOf, o as cornerShapeK, p as cornerShapePieces, q as cornerShapePoint, r as cornerSpecAt, s as cubicPointAt, t as hasCorners, u as isCornerShape, v as lerpCorners, w as nextCornerShape, x as scaleCorners, y as splitCubicAtT, z as withCorner, A as withoutCorners } from './path-BW8d_2RY.js';
|
|
3
|
+
import { A as AnchorSet, P as PenAnchor, a as SpiroPoint, S as SpiroKind, b as Scale2 } from './curvature-PkoLduGc.js';
|
|
4
|
+
export { c as AnchorRect, d as CombTooth, e as CurvatureCombOptions, C as CurvatureSource, E as EulerFit, f as EulerSegment, g as SPIRO_KINDS, h as SegmentComb, i as SegmentHit, j as SpiroSegment, k as anchorAt, l as anchorCount, m as anchorsInRect, n as anchorsToPath, o as combTeeth, p as countPathAnchors, q as cubicCurvatureAt, r as cubicCurvatureSource, s as cubicDerivativeAt, t as curvatureComb, u as deleteAnchorsAt, v as editAnchorSet, w as eulerAngleAt, x as eulerCurvatureAt, y as eulerCurvatureDerivativesAt, z as eulerPointAt, B as fitEulerSegment, D as flatAnchorIndex, F as insertAnchorOnSegment, G as isAnchorSmooth, H as isSpiroKind, I as isStraightSegment, J as locateAnchor, K as moveHandleTo, L as nearestSegmentT, M as openSubpathAt, N as pathToAnchors, O as placeEulerSegment, Q as pxExtent, R as scaleDelta, T as screenAngleOf, U as segmentAt, V as segmentEnds, W as solveSpiro, X as standoff, Y as translateAnchorBy, Z as withinPxBox, _ as withinPxRadius } from './curvature-PkoLduGc.js';
|
|
5
|
+
export { P as PORT_REACH } from './portCurve-C5HDWuuV.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Scalar / 2-vector primitives and the kernel-wide epsilon policy.
|
|
@@ -70,28 +71,35 @@ declare const ZOOM_FLOOR = 1e-9;
|
|
|
70
71
|
declare function normalizeZoom(zoom: number): number;
|
|
71
72
|
|
|
72
73
|
/** `[a, b, c, d, e, f]`: `x' = a·x + c·y + e`, `y' = b·x + d·y + f`. */
|
|
73
|
-
type
|
|
74
|
+
type Affine = readonly [number, number, number, number, number, number];
|
|
74
75
|
/** The transform that leaves a point where it is. */
|
|
75
|
-
declare function identity$1():
|
|
76
|
+
declare function identity$1(): Affine;
|
|
76
77
|
/** A pure translation by `(tx, ty)`. */
|
|
77
|
-
declare function translate(tx: number, ty: number):
|
|
78
|
+
declare function translate(tx: number, ty: number): Affine;
|
|
78
79
|
/** A pure scale about the origin. Scale about another point by composing
|
|
79
80
|
* translate → scale → inverse translate with `multiply`. */
|
|
80
|
-
declare function scale(sx: number, sy: number):
|
|
81
|
+
declare function scale(sx: number, sy: number): Affine;
|
|
81
82
|
/** A pure rotation about the origin, in radians, clockwise in canvas
|
|
82
83
|
* coordinates (y down). */
|
|
83
|
-
declare function rotate(rad: number):
|
|
84
|
+
declare function rotate(rad: number): Affine;
|
|
84
85
|
/** Compose: result applies `n` first, then `m` (m·n). */
|
|
85
|
-
declare function multiply$1(m:
|
|
86
|
+
declare function multiply$1(m: Affine, n: Affine): Affine;
|
|
86
87
|
/** Inverse, or null when the matrix is singular, non-finite, or too
|
|
87
88
|
* ill-conditioned to invert meaningfully at its own scale. */
|
|
88
|
-
declare function invert$1(m:
|
|
89
|
+
declare function invert$1(m: Affine): Affine | null;
|
|
89
90
|
/** Apply to a point, returning a tuple. Cold-path use; hot loops inline. */
|
|
90
|
-
declare function applyToPoint(m:
|
|
91
|
+
declare function applyToPoint(m: Affine, x: number, y: number): [number, number];
|
|
91
92
|
/** Affine that maps source box (sx,sy,sw,sh) onto destination box (dx,dy,dw,dh). */
|
|
92
|
-
declare function boxToBox(sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number):
|
|
93
|
+
declare function boxToBox(sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): Affine;
|
|
93
94
|
/** Rotation by `rad` about pivot (cx,cy): translate(c)·rotate·translate(-c). */
|
|
94
|
-
declare function rotateAboutPoint(cx: number, cy: number, rad: number):
|
|
95
|
+
declare function rotateAboutPoint(cx: number, cy: number, rad: number): Affine;
|
|
96
|
+
/**
|
|
97
|
+
* Apply an affine to an interleaved coord stream, returning a fresh f64
|
|
98
|
+
* buffer. Command codes are unaffected — for a Bezier the transformed control
|
|
99
|
+
* points define the transformed curve exactly (affine invariance), so callers
|
|
100
|
+
* pass `path.coords` straight through and keep `path.commands` as-is.
|
|
101
|
+
*/
|
|
102
|
+
declare function transformCoords(coords: ArrayLike<number>, m: Affine): Float64Array;
|
|
95
103
|
|
|
96
104
|
/** Axis-aligned box as [minX, minY, maxX, maxY]. */
|
|
97
105
|
type Box = readonly [number, number, number, number];
|
|
@@ -196,6 +204,9 @@ declare function cubicEvalAt(x0: number, y0: number, x1: number, y1: number, x2:
|
|
|
196
204
|
* quadratic endpoints. c1 = q0 + 2/3(ctrl-q0), c2 = q1 + 2/3(ctrl-q1).
|
|
197
205
|
*/
|
|
198
206
|
declare function elevateQuadraticToCubic(q0x: number, q0y: number, cx: number, cy: number, q1x: number, q1y: number): [number, number, number, number];
|
|
207
|
+
/** The parameters in (0, 1) where one coordinate of a cubic, with control
|
|
208
|
+
* values `p0..p3`, turns: the roots of its derivative. */
|
|
209
|
+
declare function cubicAxisExtremaTs(p0: number, p1: number, p2: number, p3: number): number[];
|
|
199
210
|
/** Tight AABB of a cubic, evaluating only extrema that lie on the curve. */
|
|
200
211
|
declare function cubicBounds(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): Box;
|
|
201
212
|
/** Quadratic Bezier point at parameter t (Bernstein form). */
|
|
@@ -291,14 +302,15 @@ declare function flattenQuadratic(x0: number, y0: number, x1: number, y1: number
|
|
|
291
302
|
* Like `flattenCubic` but also appends to `arcOut`, for each new flattened
|
|
292
303
|
* point, its *cumulative distance from the segment start* — not a normalized
|
|
293
304
|
* fraction. The caller divides each by the segment's total flattened arc
|
|
294
|
-
* length to yield t ∈ (0, 1].
|
|
305
|
+
* length to yield t ∈ (0, 1]. `maxTurn`, in radians, also bounds how far each
|
|
306
|
+
* piece's control polygon may turn.
|
|
295
307
|
*/
|
|
296
|
-
declare function flattenCubicWithArcLen(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, tolerance: number, out: number[], arcOut: number[]): number;
|
|
308
|
+
declare function flattenCubicWithArcLen(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, tolerance: number, out: number[], arcOut: number[], maxTurn?: number): number;
|
|
297
309
|
/** Flatten a quadratic bezier into line segments within `tolerance`, appending
|
|
298
310
|
* points to `out` and their cumulative arc lengths to `arcOut`. The arc
|
|
299
311
|
* lengths are what lets per-anchor color and dash phase be interpolated
|
|
300
312
|
* evenly along the curve rather than per segment. */
|
|
301
|
-
declare function flattenQuadraticWithArcLen(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, tolerance: number, out: number[], arcOut: number[]): number;
|
|
313
|
+
declare function flattenQuadraticWithArcLen(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, tolerance: number, out: number[], arcOut: number[], maxTurn?: number): number;
|
|
302
314
|
|
|
303
315
|
/**
|
|
304
316
|
* Even-odd ray-cast point-in-polygon over an interleaved, unclosed contour
|
|
@@ -367,6 +379,9 @@ declare class PathBuilder {
|
|
|
367
379
|
}
|
|
368
380
|
/** Construct a `RectPath` (the fast-path subtype). */
|
|
369
381
|
declare function rectPath(x: number, y: number, width: number, height: number): RectPath;
|
|
382
|
+
/** `path` as a command stream drawing the same outline. A rect becomes its four
|
|
383
|
+
* corners clockwise from `(x, y)`, the order `countPathAnchors` numbers them in. */
|
|
384
|
+
declare function asPolygonPath(path: Path): PolygonPath;
|
|
370
385
|
/** Build an open polyline from a flat list of points — the same geometry as
|
|
371
386
|
* {@link polygonFromPoints} without the closing edge. A freehand stroke and a
|
|
372
387
|
* measurement line want this; a region wants the closed one. */
|
|
@@ -413,10 +428,133 @@ declare function linePath(a: {
|
|
|
413
428
|
/**
|
|
414
429
|
* AABB of a `Path`, returned as a `RectPath` for direct reuse with rect-fast-path machinery.
|
|
415
430
|
* Control points are NOT included directly; they're used only to compute extrema that actually
|
|
416
|
-
* lie on the curve. Empty paths (no commands) return a zero-size rect anchored at the origin.
|
|
431
|
+
* lie on the curve. Corner shapes are bounded as they are drawn, expanded. Empty paths (no commands) return a zero-size rect anchored at the origin.
|
|
417
432
|
*/
|
|
418
433
|
declare function boundsOfPath(path: Path): RectPath;
|
|
419
434
|
|
|
435
|
+
/**
|
|
436
|
+
* Corner expansion: a path's corner specs turned into the plain geometry
|
|
437
|
+
* that every reader draws, hits, bounds, and exports.
|
|
438
|
+
*/
|
|
439
|
+
|
|
440
|
+
/** Where and how a corner anchor can be cut. */
|
|
441
|
+
interface CornerFrame {
|
|
442
|
+
/** Flat anchor index. */
|
|
443
|
+
index: number;
|
|
444
|
+
/** The anchor. */
|
|
445
|
+
x: number;
|
|
446
|
+
y: number;
|
|
447
|
+
/** Unit direction from the anchor into the wedge the cut is taken from. */
|
|
448
|
+
bisector: Point;
|
|
449
|
+
/** Half the angle between the two edges at the anchor. */
|
|
450
|
+
halfAngle: number;
|
|
451
|
+
/** How far along each edge the stored spec cuts, its setback, after clamping. */
|
|
452
|
+
trim: number;
|
|
453
|
+
/** The longest cut the edges allow while the neighbors keep theirs. */
|
|
454
|
+
maxTrim: number;
|
|
455
|
+
}
|
|
456
|
+
/** Every anchor of `path` that can take a corner, with the cut its spec
|
|
457
|
+
* makes now. */
|
|
458
|
+
declare function cornerFrames(path: PolygonPath): CornerFrame[];
|
|
459
|
+
/** The frame of the corner at flat anchor `index`, or null when that anchor
|
|
460
|
+
* cannot take one. */
|
|
461
|
+
declare function cornerFrameAt(path: PolygonPath, index: number): CornerFrame | null;
|
|
462
|
+
/** A path with its corners expanded, and where its anchors came from. */
|
|
463
|
+
interface ResolvedCorners {
|
|
464
|
+
path: PolygonPath;
|
|
465
|
+
/**
|
|
466
|
+
* For each anchor of `path` (each M, L, C, or Q, as `countPathAnchors`
|
|
467
|
+
* counts them), the anchor of the source path it belongs to, in the same
|
|
468
|
+
* numbering. Every point a corner's cut adds belongs to that corner's
|
|
469
|
+
* anchor. Null when the expansion added none.
|
|
470
|
+
*/
|
|
471
|
+
anchorSources: Uint32Array | null;
|
|
472
|
+
}
|
|
473
|
+
/** {@link resolveCorners}, also answering which source anchor each anchor of
|
|
474
|
+
* the result came from, so an array kept per anchor (`vertexColors`) can be
|
|
475
|
+
* carried onto it with {@link remapPerAnchor}. */
|
|
476
|
+
declare function resolveCornersWithSources(path: PolygonPath): ResolvedCorners;
|
|
477
|
+
/**
|
|
478
|
+
* `path` with its corner specs expanded into plain geometry and dropped: each
|
|
479
|
+
* corner is cut `radius` along both edges and spans the cut with its shape's
|
|
480
|
+
* superellipse (`cornerShapePieces`). Each cut is clamped so the cuts on
|
|
481
|
+
* either end of a segment never overlap. A path with no corners comes back
|
|
482
|
+
* as itself, and so does a rect.
|
|
483
|
+
*/
|
|
484
|
+
declare function resolveCorners<P extends Path>(path: P): P;
|
|
485
|
+
/** `values`, `stride` numbers per source anchor, as `stride` per anchor of
|
|
486
|
+
* the expanded path that `sources` describes. */
|
|
487
|
+
declare function remapPerAnchor<T>(values: readonly T[], sources: Uint32Array, stride: number): T[];
|
|
488
|
+
/** One corner of a path as its expansion draws it. */
|
|
489
|
+
interface CornerCut {
|
|
490
|
+
/** Flat anchor index. */
|
|
491
|
+
index: number;
|
|
492
|
+
anchor: Point;
|
|
493
|
+
spec: CornerSpec;
|
|
494
|
+
/** Where the cut leaves the edge into the anchor, and where it rejoins the edge out of it. */
|
|
495
|
+
start: Point;
|
|
496
|
+
end: Point;
|
|
497
|
+
/** The outline from `start` to `end`. */
|
|
498
|
+
pieces: CornerPiece[];
|
|
499
|
+
}
|
|
500
|
+
/** Every corner `path` cuts, in path order. */
|
|
501
|
+
declare function cornerCuts(path: PolygonPath): CornerCut[];
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Putting corner specs back on a path an operation rebuilt from expanded
|
|
505
|
+
* geometry. Booleans, trims and cuts work on what a path draws, its corners
|
|
506
|
+
* cut and spanned (`resolveCorners`); wherever a corner's cut comes through
|
|
507
|
+
* whole, it folds back into its anchor and spec, and only a corner the
|
|
508
|
+
* operation cut into or moved stays expanded.
|
|
509
|
+
*/
|
|
510
|
+
|
|
511
|
+
/** A corner a rebuilt path may hold expanded: the anchor and spec it folds
|
|
512
|
+
* back into, and the cut it is drawn as, from `start` to `end`. */
|
|
513
|
+
interface CornerTrace {
|
|
514
|
+
anchor: Point;
|
|
515
|
+
spec: CornerSpec;
|
|
516
|
+
start: Point;
|
|
517
|
+
end: Point;
|
|
518
|
+
pieces: readonly CornerPiece[];
|
|
519
|
+
}
|
|
520
|
+
/** How far a point may sit from where a corner draws it and still count as on it. */
|
|
521
|
+
declare const CORNER_RESTORE_TOLERANCE = 0.001;
|
|
522
|
+
/** The corners `path` cuts, as {@link restoreCorners} looks for them. */
|
|
523
|
+
declare function cornerTraces(path: Path): CornerTrace[];
|
|
524
|
+
/**
|
|
525
|
+
* `result` with the corners of `sources` folded back in wherever it still
|
|
526
|
+
* draws them whole: an operation's output, rebuilt from what the sources
|
|
527
|
+
* draw. A corner the operation cut into, or whose edges it moved, stays as
|
|
528
|
+
* the plain geometry it already is.
|
|
529
|
+
*/
|
|
530
|
+
declare function keepCorners(sources: readonly Path[], result: PolygonPath, tolerance?: number): PolygonPath;
|
|
531
|
+
/**
|
|
532
|
+
* `result` with each of `traces` it draws whole folded back into its anchor
|
|
533
|
+
* and spec. A trace counts as drawn when a run of anchors goes from one end
|
|
534
|
+
* of its cut to the other along it, the edges either side carry on to its
|
|
535
|
+
* anchor, and the folded corner cuts the same again. Specs `result` already
|
|
536
|
+
* holds are kept.
|
|
537
|
+
*/
|
|
538
|
+
declare function restoreCorners(result: PolygonPath, traces: readonly CornerTrace[], tolerance?: number): PolygonPath;
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* The corners an offset outline would hold as corners: each of the source's,
|
|
542
|
+
* moved to where its offset edges meet and resized so its cut keeps the
|
|
543
|
+
* same center.
|
|
544
|
+
*/
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Where the corners of `path` would sit on its outline grown by `distance`
|
|
548
|
+
* (shrunk by a negative one), for `restoreCorners` to look for. A corner
|
|
549
|
+
* moves with its edges and keeps its center, so its setback changes by
|
|
550
|
+
* `distance / tan(half the corner's angle)`: a round corner at a right angle
|
|
551
|
+
* grows its radius by exactly `distance`, and is then exactly what the offset
|
|
552
|
+
* draws. A shape whose offset is no longer that shape, or a corner between
|
|
553
|
+
* curved edges, draws differently from its trace, so `restoreCorners` leaves
|
|
554
|
+
* it expanded. A corner shrunk to nothing has no trace.
|
|
555
|
+
*/
|
|
556
|
+
declare function offsetCornerTraces(path: Path, distance: number): CornerTrace[];
|
|
557
|
+
|
|
420
558
|
/**
|
|
421
559
|
* AABB union over a heterogeneous set of `Path` poses. Returns the
|
|
422
560
|
* envelope as a `RectPath`, or `null` for empty input — analog of
|
|
@@ -452,12 +590,12 @@ declare function translatePath(path: Path, dx: number, dy: number): Path;
|
|
|
452
590
|
*/
|
|
453
591
|
declare function scalePathToBounds(path: Path, target: RectPath): Path;
|
|
454
592
|
|
|
455
|
-
/** Apply an
|
|
593
|
+
/** Apply an `Affine` to a path's geometry. Never mutates the input.
|
|
456
594
|
*
|
|
457
595
|
* Axis-aligned maps (no rotation/shear: `m[1]` and `m[2]` within 1e-9 of 0) keep a
|
|
458
596
|
* `RectPath` a rect, normalizing negative extent (mirror). Rotation or
|
|
459
597
|
* shear promotes the rect's four corners to a `PolygonPath`. */
|
|
460
|
-
declare function transformPath(path: Path, m:
|
|
598
|
+
declare function transformPath(path: Path, m: Affine): Path;
|
|
461
599
|
|
|
462
600
|
/**
|
|
463
601
|
* Translation-only compose/decompose for `Path` poses, the analog of
|
|
@@ -478,7 +616,8 @@ declare function decomposePath(parent: Path, world: Path): Path;
|
|
|
478
616
|
/** Split a path into one path per subpath, cutting at each `M`. A path with a
|
|
479
617
|
* single subpath comes back as a one-element array. `fillRule` is propagated
|
|
480
618
|
* unchanged, so even-odd compound paths with interior "holes" lose the hole
|
|
481
|
-
* semantics — each subpath becomes its own filled region.
|
|
619
|
+
* semantics — each subpath becomes its own filled region. Each subpath keeps
|
|
620
|
+
* the corner specs of its own anchors. */
|
|
482
621
|
declare function splitSubpaths(path: PolygonPath): PolygonPath[];
|
|
483
622
|
|
|
484
623
|
/** Whether any subpath of `path` lacks the `Z` that closes it. */
|
|
@@ -513,7 +652,7 @@ declare function pathSignedArea(path: Path): number;
|
|
|
513
652
|
/**
|
|
514
653
|
* `path` with every contour traversed backwards: same region, same curves,
|
|
515
654
|
* opposite winding. A closed contour keeps its starting point; an open one
|
|
516
|
-
* starts from where it used to end.
|
|
655
|
+
* starts from where it used to end. Corner specs stay on their anchors.
|
|
517
656
|
*/
|
|
518
657
|
declare function reversePath(path: PolygonPath): PolygonPath;
|
|
519
658
|
|
|
@@ -538,26 +677,60 @@ declare function reversePath(path: PolygonPath): PolygonPath;
|
|
|
538
677
|
declare function pathFromD(d: string, onWarn?: (message: string) => void): ReturnType<PathBuilder['build']>;
|
|
539
678
|
|
|
540
679
|
/**
|
|
541
|
-
* A
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
*
|
|
545
|
-
* routed edge, a tick on a curve, a badge near an arrowhead. Curves are
|
|
546
|
-
* flattened first, so the fraction is arc length along the drawn shape rather
|
|
547
|
-
* than a curve parameter, which is what makes 0.5 look like the middle.
|
|
680
|
+
* A path measured once by arc length, so many stations along it cost a binary
|
|
681
|
+
* search each rather than a fresh flatten: what `pointAlongPath` answers one
|
|
682
|
+
* fraction at a time, and what anything placing or bending geometry along a
|
|
683
|
+
* path reads many times over.
|
|
548
684
|
*/
|
|
549
685
|
|
|
550
|
-
/**
|
|
686
|
+
/** A point on a path and its heading there. */
|
|
551
687
|
interface PathStation {
|
|
552
688
|
point: Point;
|
|
553
689
|
/** Unit vector along the path at `point`, pointing toward the end. */
|
|
554
690
|
tangent: Point;
|
|
555
691
|
}
|
|
556
|
-
/** Options for
|
|
557
|
-
interface
|
|
692
|
+
/** Options for {@link measurePath}. */
|
|
693
|
+
interface MeasurePathOptions {
|
|
558
694
|
/** Curve flattening tolerance, in world units. Default 0.5. */
|
|
559
695
|
flattenTolerance?: number;
|
|
560
696
|
}
|
|
697
|
+
/** A measured path: its length, and the station at any distance along it. */
|
|
698
|
+
interface PathMeasure {
|
|
699
|
+
/** Total arc length, every subpath counted in order. */
|
|
700
|
+
readonly length: number;
|
|
701
|
+
/** True when the path is a single closed contour, so a distance past the
|
|
702
|
+
* end can wrap round to the start. */
|
|
703
|
+
readonly closed: boolean;
|
|
704
|
+
/**
|
|
705
|
+
* The station `s` along the path, `s` clamped to `0..length`.
|
|
706
|
+
*
|
|
707
|
+
* The tangent is the heading of the flattened segment under `s`. With
|
|
708
|
+
* `smooth`, it is instead blended across each segment from the heading at
|
|
709
|
+
* one vertex to the next, so geometry bent along it turns without facets.
|
|
710
|
+
*/
|
|
711
|
+
at(s: number, smooth?: boolean): PathStation;
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Measure `path` by arc length. Subpaths are measured in order and treated as
|
|
715
|
+
* one run, the way a browser measures a whole `<path>`. Returns `null` for a
|
|
716
|
+
* path with no points; a path of zero length answers at its single point,
|
|
717
|
+
* heading along +X.
|
|
718
|
+
*/
|
|
719
|
+
declare function measurePath(path: Path, opts?: MeasurePathOptions): PathMeasure | null;
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* A station along a path: where it is at a fraction of its length, and which
|
|
723
|
+
* way it is heading there.
|
|
724
|
+
*
|
|
725
|
+
* For anything positioned *along* geometry rather than beside it — a label on a
|
|
726
|
+
* routed edge, a tick on a curve, a badge near an arrowhead. Curves are
|
|
727
|
+
* flattened first, so the fraction is arc length along the drawn shape rather
|
|
728
|
+
* than a curve parameter, which is what makes 0.5 look like the middle. For
|
|
729
|
+
* many stations along one path, measure it once with `measurePath`.
|
|
730
|
+
*/
|
|
731
|
+
|
|
732
|
+
/** Options for `pointAlongPath`. */
|
|
733
|
+
type PointAlongPathOptions = MeasurePathOptions;
|
|
561
734
|
/**
|
|
562
735
|
* Where `path` is at `t` of its total length, and its heading there.
|
|
563
736
|
*
|
|
@@ -568,6 +741,144 @@ interface PointAlongPathOptions {
|
|
|
568
741
|
*/
|
|
569
742
|
declare function pointAlongPath(path: Path, t: number, opts?: PointAlongPathOptions): PathStation | null;
|
|
570
743
|
|
|
744
|
+
/** One cubic segment, `[x0, y0, x1, y1, x2, y2, x3, y3]`, and whether it was
|
|
745
|
+
* drawn straight. A straight one keeps its controls at its thirds, so it
|
|
746
|
+
* interpolates and warps as a line would. */
|
|
747
|
+
interface CubicSegment {
|
|
748
|
+
c: [number, number, number, number, number, number, number, number];
|
|
749
|
+
line: boolean;
|
|
750
|
+
}
|
|
751
|
+
/** One contour of segments, each starting where the one before it ends. */
|
|
752
|
+
interface CubicContour {
|
|
753
|
+
segs: CubicSegment[];
|
|
754
|
+
closed: boolean;
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* `path`'s contours as cubic segments. A closed contour whose last point
|
|
758
|
+
* stops short of its first gains the straight closing edge it is drawn with;
|
|
759
|
+
* zero-length straight segments are dropped. A contour with no segments is a
|
|
760
|
+
* lone point and is left out. Corner specs are expanded first.
|
|
761
|
+
*/
|
|
762
|
+
declare function pathToCubicContours(path: Path): CubicContour[];
|
|
763
|
+
/** The path drawing `contours`: a straight segment as `L`, the rest as `C`. */
|
|
764
|
+
declare function cubicContoursToPath(contours: readonly CubicContour[], fillRule?: PathFillRule): PolygonPath;
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Shape interpolation between two paths: the steps of a blend, or the frames
|
|
768
|
+
* of a morph.
|
|
769
|
+
*
|
|
770
|
+
* The two shapes are matched once — contour to contour, then segment to
|
|
771
|
+
* segment — and every step is a straight lerp of the matched control points.
|
|
772
|
+
* Where one contour has fewer segments, its longest ones are split in half
|
|
773
|
+
* until the counts agree, which adds anchors without moving the outline.
|
|
774
|
+
*/
|
|
775
|
+
|
|
776
|
+
/** How a blend matches the second shape's anchors to the first's. */
|
|
777
|
+
interface BlendPathsOptions {
|
|
778
|
+
/**
|
|
779
|
+
* Choose, for each pair of contours, the start point (and, when `reverse`
|
|
780
|
+
* is unset, the direction) of the second that keeps matched anchors
|
|
781
|
+
* closest, with both contours centered on their own middles first so that
|
|
782
|
+
* where the shapes sit does not decide it. Default `true`.
|
|
783
|
+
*/
|
|
784
|
+
autoAlign?: boolean;
|
|
785
|
+
/**
|
|
786
|
+
* Turn the second shape's start point this many anchors further round each
|
|
787
|
+
* closed contour, after any `autoAlign` choice. Negative turns it back.
|
|
788
|
+
* Default 0.
|
|
789
|
+
*/
|
|
790
|
+
startOffset?: number;
|
|
791
|
+
/** Run the second shape's contours backwards. Unset, `autoAlign` decides;
|
|
792
|
+
* without it, they run as drawn. */
|
|
793
|
+
reverse?: boolean;
|
|
794
|
+
}
|
|
795
|
+
/** Two shapes matched for interpolation. */
|
|
796
|
+
interface PathBlend {
|
|
797
|
+
/** The shape `t` of the way from the first to the second: exactly the
|
|
798
|
+
* first at 0 and the second at 1, up to the anchors matching added. */
|
|
799
|
+
at(t: number): PolygonPath;
|
|
800
|
+
/** Segments per matched pair of contours. */
|
|
801
|
+
readonly segmentCounts: readonly number[];
|
|
802
|
+
}
|
|
803
|
+
/** The shape `t` of the way from `a` to `b`. Matching once with
|
|
804
|
+
* {@link prepareBlend} is cheaper when several steps are wanted. */
|
|
805
|
+
declare function blendPaths(a: Path, b: Path, t: number, opts?: BlendPathsOptions): PolygonPath;
|
|
806
|
+
/** Match `a` to `b` for interpolation. */
|
|
807
|
+
declare function prepareBlend(a: Path, b: Path, opts?: BlendPathsOptions): PathBlend;
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
* Bend a shape along a spine: the shape's x becomes distance along the spine
|
|
811
|
+
* and its y distance off it, along the spine's normal. A straight edge of the
|
|
812
|
+
* shape comes out curved wherever the spine bends, so each segment is
|
|
813
|
+
* sampled through the warp and refit to cubics within a tolerance; anchors
|
|
814
|
+
* stay where they were, so a corner of the shape stays a corner.
|
|
815
|
+
*/
|
|
816
|
+
|
|
817
|
+
/** How a shape is laid along its spine. */
|
|
818
|
+
interface BendAlongPathOptions {
|
|
819
|
+
/**
|
|
820
|
+
* `'stretch'`, the default, spreads the shape's width over the spine's
|
|
821
|
+
* whole length. `'natural'` keeps its width: one unit across the shape is
|
|
822
|
+
* one unit along the spine, starting at the spine's start, and a shape
|
|
823
|
+
* longer than the spine runs on straight past its end.
|
|
824
|
+
*/
|
|
825
|
+
fit?: 'stretch' | 'natural';
|
|
826
|
+
/** Where across the shape's height the spine runs, 0 at its top and 1 at
|
|
827
|
+
* its bottom. Default 0.5, the middle. */
|
|
828
|
+
baseline?: number;
|
|
829
|
+
/** Lay the shape on the other side of the spine, mirrored across it. */
|
|
830
|
+
flip?: boolean;
|
|
831
|
+
/** How far the refit curves may stray from the exact bend, in world
|
|
832
|
+
* units. Default 0.5. */
|
|
833
|
+
tolerance?: number;
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* `shape` bent along `spine`. A spine heading left to right keeps the shape
|
|
837
|
+
* upright; one heading the other way turns it over, as a road sign painted
|
|
838
|
+
* along a lane does. Returns `null` when the spine has no length or the shape
|
|
839
|
+
* nothing to bend.
|
|
840
|
+
*/
|
|
841
|
+
declare function bendAlongPath(shape: Path, spine: Path, opts?: BendAlongPathOptions): PolygonPath | null;
|
|
842
|
+
|
|
843
|
+
/** How copies are spaced along a path. */
|
|
844
|
+
interface RepeatAlongPathOptions {
|
|
845
|
+
/**
|
|
846
|
+
* How many copies. With no `spacing`, they spread evenly over the whole
|
|
847
|
+
* path — end to end on an open one, evenly round a closed one — and the
|
|
848
|
+
* default is 5. With a `spacing`, it caps the run; unset, as many as fit.
|
|
849
|
+
*/
|
|
850
|
+
count?: number;
|
|
851
|
+
/** Distance along the path from one copy's center to the next. */
|
|
852
|
+
spacing?: number;
|
|
853
|
+
/** Where a spaced run that is shorter than the path sits on it. Default
|
|
854
|
+
* `'start'`. */
|
|
855
|
+
align?: 'start' | 'center' | 'end';
|
|
856
|
+
/** Slide every copy this far along the path. On an open path a copy slid
|
|
857
|
+
* off either end is dropped; round a closed one it wraps. Default 0. */
|
|
858
|
+
offset?: number;
|
|
859
|
+
/** Turn each copy to the path's heading where it sits. Default `true`. */
|
|
860
|
+
orient?: boolean;
|
|
861
|
+
/** Curve flattening tolerance for measuring the path. Default 0.5. */
|
|
862
|
+
flattenTolerance?: number;
|
|
863
|
+
}
|
|
864
|
+
/** Where one copy sits. */
|
|
865
|
+
interface RepeatStation {
|
|
866
|
+
point: Point;
|
|
867
|
+
/** The path's heading there, radians clockwise from +X in a y-down frame. */
|
|
868
|
+
angle: number;
|
|
869
|
+
/** Arc length from the path's start. */
|
|
870
|
+
distance: number;
|
|
871
|
+
}
|
|
872
|
+
/** The stations copies sit at along `path`, in order. Empty for a path with
|
|
873
|
+
* no points. */
|
|
874
|
+
declare function stationsAlongPath(path: Path, opts?: RepeatAlongPathOptions): RepeatStation[];
|
|
875
|
+
/**
|
|
876
|
+
* Copies of `shape`, each centered on a station along `path` — its bounding
|
|
877
|
+
* box's middle on the path — and, with `orient`, turned to the heading
|
|
878
|
+
* there. The shape's own +X runs along the path.
|
|
879
|
+
*/
|
|
880
|
+
declare function repeatAlongPath(shape: Path, path: Path, opts?: RepeatAlongPathOptions): Path[];
|
|
881
|
+
|
|
571
882
|
/**
|
|
572
883
|
* Pure-geometry distance from a point to a path's boundary (stroke), with
|
|
573
884
|
* no fill-side logic. Used by pickers that want to know "how close is this
|
|
@@ -585,6 +896,326 @@ declare function pointAlongPath(path: Path, t: number, opts?: PointAlongPathOpti
|
|
|
585
896
|
* combine with `pathContainsPoint` at the call site. */
|
|
586
897
|
declare function pathDistanceToPoint(path: Path, px: number, py: number): number;
|
|
587
898
|
|
|
899
|
+
/** Where two Bézier segments cross, by subdivision then Newton refinement. */
|
|
900
|
+
|
|
901
|
+
/** One crossing of segments `a` and `b`: the parameter on each, and the point. */
|
|
902
|
+
interface SegmentCrossing {
|
|
903
|
+
ta: number;
|
|
904
|
+
tb: number;
|
|
905
|
+
x: number;
|
|
906
|
+
y: number;
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Every point where segment `a` crosses or touches segment `b` — each a line,
|
|
910
|
+
* quadratic or cubic given by its control points — with the parameter on
|
|
911
|
+
* each. Two lines are solved exactly; a curve is subdivided until its pieces
|
|
912
|
+
* are flat, their chords crossed, and the answer refined against the curves.
|
|
913
|
+
* Segments that overlap along a stretch report at most a few points of it.
|
|
914
|
+
* Sorted by `ta`.
|
|
915
|
+
*/
|
|
916
|
+
declare function intersectSegments(a: Point[], b: Point[]): SegmentCrossing[];
|
|
917
|
+
|
|
918
|
+
/** A path's stroke as a flat list of segments, each knowing where it sits. */
|
|
919
|
+
|
|
920
|
+
/** One segment of a path's stroke, in the order the path draws them. */
|
|
921
|
+
interface PathSegment {
|
|
922
|
+
/** Control points: 2 for a line, 3 for a quadratic, 4 for a cubic. */
|
|
923
|
+
pts: Point[];
|
|
924
|
+
/** Index of its subpath among the path's subpaths. */
|
|
925
|
+
sub: number;
|
|
926
|
+
/** Index within its subpath. */
|
|
927
|
+
index: number;
|
|
928
|
+
/** Segments in its subpath. */
|
|
929
|
+
count: number;
|
|
930
|
+
/** Whether its subpath is closed, so its last segment meets its first. */
|
|
931
|
+
closed: boolean;
|
|
932
|
+
/** Axis-aligned box of the control points, which holds the segment. */
|
|
933
|
+
box: {
|
|
934
|
+
x0: number;
|
|
935
|
+
y0: number;
|
|
936
|
+
x1: number;
|
|
937
|
+
y1: number;
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
/** `path`'s stroke as segments: a closed subpath includes its closing edge,
|
|
941
|
+
* an open one does not, and a zero-length line is left out. */
|
|
942
|
+
declare function pathSegments(path: Path): PathSegment[];
|
|
943
|
+
|
|
944
|
+
/** Where paths cross one another and themselves. */
|
|
945
|
+
|
|
946
|
+
/** A place on a path's stroke: which segment, and how far along it. */
|
|
947
|
+
interface PathStop {
|
|
948
|
+
/** Index of the path in the list it came from. */
|
|
949
|
+
path: number;
|
|
950
|
+
sub: number;
|
|
951
|
+
/** Segment index within the subpath. */
|
|
952
|
+
index: number;
|
|
953
|
+
/** Parameter on that segment, in [0, 1]. */
|
|
954
|
+
t: number;
|
|
955
|
+
}
|
|
956
|
+
/** A point where two strokes cross or touch, and where it falls on each. */
|
|
957
|
+
interface PathCrossing {
|
|
958
|
+
x: number;
|
|
959
|
+
y: number;
|
|
960
|
+
a: PathStop;
|
|
961
|
+
b: PathStop;
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Every crossing among `paths`: between each pair, and — unless `self` is
|
|
965
|
+
* false — of a path with itself, leaving out the joint where one segment
|
|
966
|
+
* meets the next. Points where strokes merely touch count too. With `of`,
|
|
967
|
+
* only the crossings involving that one path.
|
|
968
|
+
*/
|
|
969
|
+
declare function pathCrossings(paths: readonly Path[], opts?: {
|
|
970
|
+
self?: boolean;
|
|
971
|
+
of?: number;
|
|
972
|
+
}): PathCrossing[];
|
|
973
|
+
|
|
974
|
+
/**
|
|
975
|
+
* Geometric snapping onto paths: the points on a set of strokes a drawn or
|
|
976
|
+
* dragged point can lock to, and which of them a probe lands on.
|
|
977
|
+
*/
|
|
978
|
+
|
|
979
|
+
/**
|
|
980
|
+
* What a snap target is.
|
|
981
|
+
*
|
|
982
|
+
* - `anchor` — an end of a segment: a path's anchors, a box's corners.
|
|
983
|
+
* - `center` — a point a caller names as the middle of something: a text or
|
|
984
|
+
* image box's center, given to {@link createPathSnapIndex} as a target.
|
|
985
|
+
* - `intersection` — where two strokes cross, or one crosses itself.
|
|
986
|
+
* - `tangent` — where a line from the query's origin touches a curve.
|
|
987
|
+
* - `perpendicular` — where a line from the origin meets a stroke square on.
|
|
988
|
+
* - `midpoint` — the middle of a segment by length.
|
|
989
|
+
* - `extremum` — on a curve, where its tangent turns horizontal or vertical.
|
|
990
|
+
* - `quadrant` — where a closed subpath crosses the horizontal and vertical
|
|
991
|
+
* lines through the center of its box: a circle's four compass points.
|
|
992
|
+
* - `nearest` — the closest point on any stroke, when nothing else is in range.
|
|
993
|
+
*/
|
|
994
|
+
type PathSnapKind = 'anchor' | 'center' | 'intersection' | 'tangent' | 'perpendicular' | 'midpoint' | 'extremum' | 'quadrant' | 'nearest';
|
|
995
|
+
/** Every snap kind, in the order a picker lists them. */
|
|
996
|
+
declare const PATH_SNAP_KINDS: readonly PathSnapKind[];
|
|
997
|
+
/** The kinds whose targets stand whatever the probe. */
|
|
998
|
+
type StaticPathSnapKind = 'anchor' | 'center' | 'intersection' | 'midpoint' | 'extremum' | 'quadrant';
|
|
999
|
+
/** A target the probe landed on. */
|
|
1000
|
+
interface PathSnapHit {
|
|
1001
|
+
kind: PathSnapKind;
|
|
1002
|
+
x: number;
|
|
1003
|
+
y: number;
|
|
1004
|
+
/** Distance from the probe, in the query's `radius` units. */
|
|
1005
|
+
distance: number;
|
|
1006
|
+
/** Indices of the paths that make the target: two for a crossing between
|
|
1007
|
+
* paths, one otherwise. */
|
|
1008
|
+
paths: readonly number[];
|
|
1009
|
+
}
|
|
1010
|
+
/** A query for {@link findPathSnap}. */
|
|
1011
|
+
interface PathSnapQuery {
|
|
1012
|
+
/** How far from the probe a target may be, in the paths' units times
|
|
1013
|
+
* `scale`. */
|
|
1014
|
+
radius: number;
|
|
1015
|
+
/** Per-axis scale from the paths' units to the units `radius` is in — a
|
|
1016
|
+
* view's, to measure the radius in screen pixels under any zoom. Default
|
|
1017
|
+
* `{ x: 1, y: 1 }`. */
|
|
1018
|
+
scale?: {
|
|
1019
|
+
x: number;
|
|
1020
|
+
y: number;
|
|
1021
|
+
};
|
|
1022
|
+
/** Kinds to consider. Absent, all of them. */
|
|
1023
|
+
kinds?: Iterable<PathSnapKind>;
|
|
1024
|
+
/** Where the line being drawn starts. Tangent and perpendicular targets are
|
|
1025
|
+
* measured from it, and there are none without it. */
|
|
1026
|
+
origin?: Point;
|
|
1027
|
+
/** Paths by index that offer no targets — the ones a drag is moving. */
|
|
1028
|
+
skip?: (path: number) => boolean;
|
|
1029
|
+
}
|
|
1030
|
+
/** A target that stands whatever the probe: an anchor, a center, a crossing,
|
|
1031
|
+
* a midpoint, an extremum or a quadrant point. */
|
|
1032
|
+
interface PathSnapTarget {
|
|
1033
|
+
kind: StaticPathSnapKind;
|
|
1034
|
+
x: number;
|
|
1035
|
+
y: number;
|
|
1036
|
+
paths: readonly number[];
|
|
1037
|
+
}
|
|
1038
|
+
/** A set of paths, prepared for repeated snapping. Static targets are
|
|
1039
|
+
* computed on first use and kept. */
|
|
1040
|
+
interface PathSnapIndex {
|
|
1041
|
+
readonly paths: readonly Path[];
|
|
1042
|
+
/** Each path's segments. */
|
|
1043
|
+
readonly segments: readonly (readonly PathSegment[])[];
|
|
1044
|
+
/** The targets that do not depend on the probe, of one kind. */
|
|
1045
|
+
targets(kind: StaticPathSnapKind): readonly PathSnapTarget[];
|
|
1046
|
+
}
|
|
1047
|
+
/** Prepare `paths` for {@link findPathSnap}. Build one per set of paths and
|
|
1048
|
+
* reuse it while they stand: a crossing search is quadratic in segments.
|
|
1049
|
+
* `extra` adds targets of the caller's own — the center of a box, a point
|
|
1050
|
+
* with no segment at it — each naming the path it belongs to. */
|
|
1051
|
+
declare function createPathSnapIndex(paths: readonly Path[], extra?: readonly PathSnapTarget[]): PathSnapIndex;
|
|
1052
|
+
/**
|
|
1053
|
+
* The snap target nearest `probe` within `query.radius`, or null when none
|
|
1054
|
+
* is in range. Every enabled kind competes on distance, except `nearest`,
|
|
1055
|
+
* which answers only when no other target is in range.
|
|
1056
|
+
*/
|
|
1057
|
+
declare function findPathSnap(index: PathSnapIndex, probe: Point, query: PathSnapQuery): PathSnapHit | null;
|
|
1058
|
+
/**
|
|
1059
|
+
* Every snap target within `query.radius` of `probe`, unsorted. `nearest`
|
|
1060
|
+
* hits appear only when no other target is in range. Tangent and perpendicular targets
|
|
1061
|
+
* closer to the origin than the radius are dropped, so a line cannot snap
|
|
1062
|
+
* back onto its own start.
|
|
1063
|
+
*/
|
|
1064
|
+
declare function findPathSnaps(index: PathSnapIndex, probe: Point, query: PathSnapQuery): PathSnapHit[];
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* Trim: remove the piece of a stroke between the crossings on either side of
|
|
1068
|
+
* a point, as a drafting trim does.
|
|
1069
|
+
*/
|
|
1070
|
+
|
|
1071
|
+
/** Options for {@link trimPathAt}. */
|
|
1072
|
+
interface TrimPathOptions {
|
|
1073
|
+
/** How far from the stroke `probe` may be. Default: any distance. */
|
|
1074
|
+
radius?: number;
|
|
1075
|
+
}
|
|
1076
|
+
/** What {@link trimPathAt} did. */
|
|
1077
|
+
interface TrimResult {
|
|
1078
|
+
/** The path with the piece gone; it has no commands when nothing is left. */
|
|
1079
|
+
path: PolygonPath;
|
|
1080
|
+
/** The piece removed, as an open path. */
|
|
1081
|
+
removed: PolygonPath;
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Remove the piece of `path`'s stroke that `probe` is nearest, bounded by the
|
|
1085
|
+
* nearest crossings on either side — with any of `cutters`, or with the path
|
|
1086
|
+
* itself. On an open subpath an end with no crossing before it bounds the
|
|
1087
|
+
* piece too, so a subpath touched only at its ends goes whole; a closed
|
|
1088
|
+
* subpath is opened, and one crossed at a single point is removed whole.
|
|
1089
|
+
*
|
|
1090
|
+
* Returns null when the probe is further than `radius` from the stroke, or
|
|
1091
|
+
* when nothing crosses or touches the subpath it is on. Curves are split where they are
|
|
1092
|
+
* cut and keep their type; other subpaths are left as they were.
|
|
1093
|
+
*/
|
|
1094
|
+
declare function trimPathAt(path: Path, cutters: readonly Path[], probe: Point, opts?: TrimPathOptions): TrimResult | null;
|
|
1095
|
+
|
|
1096
|
+
/** What stays put of a path while some of its anchors move. */
|
|
1097
|
+
interface PathAwayFromAnchors {
|
|
1098
|
+
/** The segments touching none of the moving anchors, as open runs; a
|
|
1099
|
+
* subpath none of them is on stays as it was. */
|
|
1100
|
+
path: PolygonPath;
|
|
1101
|
+
/** Every anchor that is not moving, a lone one with no segment left at it
|
|
1102
|
+
* included. */
|
|
1103
|
+
anchors: Point[];
|
|
1104
|
+
}
|
|
1105
|
+
/**
|
|
1106
|
+
* The part of `path` that holds still while the anchors at `moving` (flat
|
|
1107
|
+
* indices, as anchor editing numbers them) are dragged: every segment with a
|
|
1108
|
+
* moving anchor at either end is dropped, and so are the moving anchors.
|
|
1109
|
+
*/
|
|
1110
|
+
declare function pathAwayFromAnchors(path: PolygonPath, moving: Iterable<number>): PathAwayFromAnchors;
|
|
1111
|
+
|
|
1112
|
+
/**
|
|
1113
|
+
* Growing an open end of a path along its tangent: by a distance, or until it
|
|
1114
|
+
* meets another stroke.
|
|
1115
|
+
*/
|
|
1116
|
+
|
|
1117
|
+
/** One end of an open subpath. `sub` counts subpaths as the path's anchor set
|
|
1118
|
+
* (`pathToAnchors`) does, a bare `M` included. */
|
|
1119
|
+
interface OpenPathEnd {
|
|
1120
|
+
sub: number;
|
|
1121
|
+
end: 'first' | 'last';
|
|
1122
|
+
}
|
|
1123
|
+
/** Every end of every open subpath of `path` that has a direction to grow in. */
|
|
1124
|
+
declare function openPathEnds(path: Path): OpenPathEnd[];
|
|
1125
|
+
/** Where `end` sits and the unit direction it points out along, or null when
|
|
1126
|
+
* it is no open end or has no direction there. */
|
|
1127
|
+
declare function openEndRay(path: Path, end: OpenPathEnd): {
|
|
1128
|
+
at: Point;
|
|
1129
|
+
dir: Point;
|
|
1130
|
+
} | null;
|
|
1131
|
+
/**
|
|
1132
|
+
* `path` with `end` carried `distance` further along its tangent, by
|
|
1133
|
+
* `lengthenPathEnd` in `'tangent'` mode: a straight end segment grows longer,
|
|
1134
|
+
* and a curved one gains a straight segment, which keeps the tangent
|
|
1135
|
+
* continuous. Null when the end is not open or has no direction, or
|
|
1136
|
+
* `distance` is not positive.
|
|
1137
|
+
*/
|
|
1138
|
+
declare function lengthenOpenEnd(path: Path, end: OpenPathEnd, distance: number): PolygonPath | null;
|
|
1139
|
+
/** Options for {@link extendToMeet}. */
|
|
1140
|
+
interface ExtendToMeetOptions {
|
|
1141
|
+
/** The furthest the end may travel. Default: as far as any stroke reaches. */
|
|
1142
|
+
maxDistance?: number;
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1145
|
+
* Extend `end` of `path` along its tangent to the first stroke it meets —
|
|
1146
|
+
* one of `boundaries`, or `path`'s own other segments. Returns the extended
|
|
1147
|
+
* path, the point it now ends at and how far it went, or null when the
|
|
1148
|
+
* tangent meets nothing.
|
|
1149
|
+
*/
|
|
1150
|
+
declare function extendToMeet(path: Path, boundaries: readonly Path[], end: OpenPathEnd, opts?: ExtendToMeetOptions): {
|
|
1151
|
+
path: PolygonPath;
|
|
1152
|
+
at: Point;
|
|
1153
|
+
distance: number;
|
|
1154
|
+
} | null;
|
|
1155
|
+
|
|
1156
|
+
/**
|
|
1157
|
+
* Grow or trim an open subpath at one of its ends. Lengthen drags this, and
|
|
1158
|
+
* Extend to next path reaches it through `lengthenOpenEnd`.
|
|
1159
|
+
*
|
|
1160
|
+
* A positive distance extends the end outward: straight along the end tangent,
|
|
1161
|
+
* or along a circular arc with the curvature the end has, which meets the path
|
|
1162
|
+
* with matching direction and curvature. A straight end segment is lengthened
|
|
1163
|
+
* in place; a curved one is continued with a new segment. A negative distance
|
|
1164
|
+
* trims the path back along itself by arc length, whichever way it would have
|
|
1165
|
+
* grown.
|
|
1166
|
+
*
|
|
1167
|
+
* The arc rather than extrapolating the end cubic past t = 1: a cubic's
|
|
1168
|
+
* leading term takes over beyond its range, so a continued curve swings off
|
|
1169
|
+
* and curls on itself within a segment's length, while the arc keeps the
|
|
1170
|
+
* curvature the end shows for as long as it is drawn.
|
|
1171
|
+
*/
|
|
1172
|
+
|
|
1173
|
+
/** How `lengthenPathEnd` grows an end: straight on, or bending as the end bends. */
|
|
1174
|
+
type LengthenMode = 'tangent' | 'curvature';
|
|
1175
|
+
/** Where an end is, which way it heads out of the path, and how it bends there. */
|
|
1176
|
+
interface PathEndFrame {
|
|
1177
|
+
point: Point;
|
|
1178
|
+
/** Unit vector pointing out of the path. */
|
|
1179
|
+
tangent: Point;
|
|
1180
|
+
/** Signed curvature along `tangent`: positive turns toward `(-tangent.y, tangent.x)`. */
|
|
1181
|
+
curvature: number;
|
|
1182
|
+
}
|
|
1183
|
+
/** The end of an open subpath that the anchor at `flatIndex` is, or null when it is
|
|
1184
|
+
* an inner anchor, on a closed subpath, or alone in its subpath. */
|
|
1185
|
+
declare function openEndAt(set: AnchorSet, flatIndex: number): OpenPathEnd | null;
|
|
1186
|
+
/** Flat index of the anchor at `end`, or -1 when there is none. */
|
|
1187
|
+
declare function pathEndAnchorIndex(set: AnchorSet, end: OpenPathEnd): number;
|
|
1188
|
+
/** The frame at `end`, or null when it is not the end of an open subpath of two or
|
|
1189
|
+
* more anchors, or the path has no direction there. */
|
|
1190
|
+
declare function pathEndFrame(set: AnchorSet, end: OpenPathEnd): PathEndFrame | null;
|
|
1191
|
+
/**
|
|
1192
|
+
* Lengthen `end` by `distance` (see the module comment), in place. A curvature arc
|
|
1193
|
+
* stops at one full turn. Returns false when `end` is not the end of an open
|
|
1194
|
+
* subpath or nothing changed.
|
|
1195
|
+
*/
|
|
1196
|
+
declare function lengthenPathEnd(set: AnchorSet, end: OpenPathEnd, distance: number, mode: LengthenMode): boolean;
|
|
1197
|
+
/**
|
|
1198
|
+
* The distance `lengthenPathEnd` takes for its new end to land nearest `point`: the
|
|
1199
|
+
* point projected onto the end tangent, or for a curvature lengthening, measured
|
|
1200
|
+
* around the circle of curvature. A measurement around the circle can name the
|
|
1201
|
+
* same spot a turn apart; it answers the one nearest `near`, so a drag passing
|
|
1202
|
+
* half a turn keeps going instead of jumping back.
|
|
1203
|
+
*/
|
|
1204
|
+
declare function lengthToward(set: AnchorSet, end: OpenPathEnd, mode: LengthenMode, point: Point, near?: number): number;
|
|
1205
|
+
|
|
1206
|
+
/**
|
|
1207
|
+
* Controls for the one cubic that replaces `prev → removed → next` when
|
|
1208
|
+
* `removed` is deleted. The new controls keep the directions the curve leaves
|
|
1209
|
+
* `prev` and arrives at `next` with, and their lengths are least-squares fitted
|
|
1210
|
+
* to samples of the two segments being replaced, so the curve keeps its shape
|
|
1211
|
+
* as closely as one cubic can. Where `removed` was inserted by splitting a
|
|
1212
|
+
* cubic, the original cubic comes back.
|
|
1213
|
+
*/
|
|
1214
|
+
declare function fitCubicThroughDeletion(prev: PenAnchor, removed: PenAnchor, next: PenAnchor): {
|
|
1215
|
+
c1: Point;
|
|
1216
|
+
c2: Point;
|
|
1217
|
+
};
|
|
1218
|
+
|
|
588
1219
|
/**
|
|
589
1220
|
* Schneider (1990, Graphics Gems I) adaptive cubic-Bezier fitter.
|
|
590
1221
|
* Given a sequence of sample points, returns a `PolygonPath` whose `C`
|
|
@@ -595,6 +1226,275 @@ declare function pathDistanceToPoint(path: Path, px: number, py: number): number
|
|
|
595
1226
|
* degenerate cubic. For empty input, returns an empty polygon path.
|
|
596
1227
|
*/
|
|
597
1228
|
declare function schneiderFit(samples: ReadonlyArray<Point>, errorTolerance: number): PolygonPath;
|
|
1229
|
+
/**
|
|
1230
|
+
* The single cubic from the first sample to the last that best fits the
|
|
1231
|
+
* samples between, with its control points held to the given unit tangents:
|
|
1232
|
+
* `tStart` leaving the first sample, `tEnd` leaving the last one backward.
|
|
1233
|
+
* Only the two handle lengths are solved for.
|
|
1234
|
+
*
|
|
1235
|
+
* `params` is the curve parameter each sample starts at, chord length when
|
|
1236
|
+
* omitted; `passes` is how many times those are refined and the lengths
|
|
1237
|
+
* solved again.
|
|
1238
|
+
*/
|
|
1239
|
+
declare function fitCubicWithTangents(samples: ReadonlyArray<Point>, tStart: Point, tEnd: Point, opts?: {
|
|
1240
|
+
params?: ReadonlyArray<number>;
|
|
1241
|
+
passes?: number;
|
|
1242
|
+
}): {
|
|
1243
|
+
cp1: Point;
|
|
1244
|
+
cp2: Point;
|
|
1245
|
+
};
|
|
1246
|
+
|
|
1247
|
+
/** Options for {@link simplifyPath}. */
|
|
1248
|
+
interface SimplifyPathOptions {
|
|
1249
|
+
/**
|
|
1250
|
+
* An anchor whose path turns by more than this many degrees is a corner:
|
|
1251
|
+
* it is kept, and the curve is refitted on either side of it. Default 40.
|
|
1252
|
+
*/
|
|
1253
|
+
cornerAngle?: number;
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* `path` refitted with as few anchors as hold it within `tolerance`: every
|
|
1257
|
+
* point sampled along the original lies within `tolerance` of the result.
|
|
1258
|
+
* Corners (see {@link SimplifyPathOptions.cornerAngle}) and the ends of open
|
|
1259
|
+
* subpaths stay where they are; the runs between them are refitted as smooth
|
|
1260
|
+
* cubics, Schneider-style, and a run that lies within `tolerance` of a line
|
|
1261
|
+
* becomes one straight segment. Fill rules carry over.
|
|
1262
|
+
*/
|
|
1263
|
+
declare function simplifyPath(path: PolygonPath, tolerance: number, opts?: SimplifyPathOptions): PolygonPath;
|
|
1264
|
+
/** One subpath of {@link simplifyPath}: its anchors refitted, corners and
|
|
1265
|
+
* open ends kept. */
|
|
1266
|
+
declare function simplifySubpath(sub: PenAnchor[], closed: boolean, tolerance: number, opts?: SimplifyPathOptions): PenAnchor[];
|
|
1267
|
+
/**
|
|
1268
|
+
* The anchors of `sub` from index `from` to `to`, refitted the way
|
|
1269
|
+
* {@link simplifyPath} refits a subpath: as few as hold the span within
|
|
1270
|
+
* `tolerance`, corners inside it kept. Indices run modulo the subpath's
|
|
1271
|
+
* length, so on a closed subpath `to` may pass its end and wrap; the span is
|
|
1272
|
+
* shorter than one full turn. The two end anchors stay where they are and
|
|
1273
|
+
* keep their handles facing out of the span. Answers the anchors from `from`
|
|
1274
|
+
* to `to`, both included, to splice in place of the originals.
|
|
1275
|
+
*/
|
|
1276
|
+
declare function simplifySpan(sub: PenAnchor[], closed: boolean, from: number, to: number, tolerance: number, opts?: SimplifyPathOptions): PenAnchor[];
|
|
1277
|
+
|
|
1278
|
+
/** Options for {@link growRegion}. */
|
|
1279
|
+
interface GrowRegionOptions {
|
|
1280
|
+
/** How a convex corner turns. `'miter'` keeps it sharp, as a pseudo-distance
|
|
1281
|
+
* field draws it; `'round'` follows the true distance. Default `'miter'`. */
|
|
1282
|
+
join?: 'miter' | 'round';
|
|
1283
|
+
/** Past this ratio of miter length to distance a miter corner is beveled.
|
|
1284
|
+
* Default 4. */
|
|
1285
|
+
miterLimit?: number;
|
|
1286
|
+
/** How far a grown curve may stray from the true offset, in the path's
|
|
1287
|
+
* units. Default 0.1. */
|
|
1288
|
+
tolerance?: number;
|
|
1289
|
+
}
|
|
1290
|
+
/**
|
|
1291
|
+
* The region `path` fills under `'nonzero'`, grown by `distance` (> 0), as a
|
|
1292
|
+
* path that fills it under `'nonzero'`. Every subpath counts as closed. Each
|
|
1293
|
+
* contour is replaced by its offset, so where grown parts meet the contours
|
|
1294
|
+
* overlap rather than merge, and a hole grown shut winds back on itself and
|
|
1295
|
+
* fills. At an inside corner the two offset edges are cut back to where they
|
|
1296
|
+
* cross; where they do not, the gap is passed through the corner's original
|
|
1297
|
+
* point, which closes it with a loop inside the fill.
|
|
1298
|
+
*
|
|
1299
|
+
* What it costs: one segment per curve, more where `tolerance` needs the curve
|
|
1300
|
+
* split; a miter corner between two straight edges costs nothing, one beside
|
|
1301
|
+
* a curve gains an anchor or two, a round corner an arc, and an inside corner
|
|
1302
|
+
* whose edges do not cross two.
|
|
1303
|
+
*/
|
|
1304
|
+
declare function growRegion(path: Path, distance: number, opts?: GrowRegionOptions): PolygonPath;
|
|
1305
|
+
|
|
1306
|
+
/**
|
|
1307
|
+
* Simplify only where `flatIndexes` say: each unbroken run of those anchors
|
|
1308
|
+
* along a subpath is refitted as one span by the fitter {@link simplifyPath}
|
|
1309
|
+
* uses (`simplifySpan`), so only anchors the shape does not need, within
|
|
1310
|
+
* `tolerance`, go. A run's first and last anchors stay, and every anchor
|
|
1311
|
+
* outside a run is left as it was. A closed subpath named whole is simplified
|
|
1312
|
+
* whole. Answers whether any anchor went; a run the fit cannot thin is left
|
|
1313
|
+
* untouched.
|
|
1314
|
+
*/
|
|
1315
|
+
declare function simplifyAnchorsAt(set: AnchorSet, flatIndexes: Iterable<number>, tolerance: number, opts?: SimplifyPathOptions): boolean;
|
|
1316
|
+
|
|
1317
|
+
/**
|
|
1318
|
+
* Resample: a path's anchors spread evenly along it by arc length, and its
|
|
1319
|
+
* curves refitted through them.
|
|
1320
|
+
*/
|
|
1321
|
+
|
|
1322
|
+
/** Options for {@link resamplePath}. */
|
|
1323
|
+
interface ResamplePathOptions {
|
|
1324
|
+
/** How many anchors the result holds across all its subpaths. Default: as
|
|
1325
|
+
* many as `path` has. Ignored when `spacing` is given. */
|
|
1326
|
+
count?: number;
|
|
1327
|
+
/** The distance along the path between neighboring anchors, in path units.
|
|
1328
|
+
* Each run between fixed anchors is cut into the whole number of equal
|
|
1329
|
+
* pieces nearest this. */
|
|
1330
|
+
spacing?: number;
|
|
1331
|
+
/** Keep every corner anchor (`isAnchorSmooth` false) where it is, with its
|
|
1332
|
+
* corner, and resample the runs between. Default `true`. Open ends are
|
|
1333
|
+
* kept either way. */
|
|
1334
|
+
keepCorners?: boolean;
|
|
1335
|
+
/** How far the result may stray from the original, in path units. A piece
|
|
1336
|
+
* that cannot follow the original this closely is halved, so the result can
|
|
1337
|
+
* hold more anchors than `count` asks for. Default 0.5. */
|
|
1338
|
+
tolerance?: number;
|
|
1339
|
+
}
|
|
1340
|
+
/**
|
|
1341
|
+
* `path` with its anchors spread evenly along each run between fixed anchors
|
|
1342
|
+
* ({@link ResamplePathOptions}), each new anchor heading the way the original
|
|
1343
|
+
* does there. Anchors that were smooth stay smooth, and the curves between
|
|
1344
|
+
* are fitted to the original. A closed subpath with no fixed anchor keeps
|
|
1345
|
+
* its first one as the place the even spacing starts from. Fill rules carry
|
|
1346
|
+
* over.
|
|
1347
|
+
*/
|
|
1348
|
+
declare function resamplePath(path: PolygonPath, opts?: ResamplePathOptions): PolygonPath;
|
|
1349
|
+
|
|
1350
|
+
/** The parameters in (0, 1) where the segment from `a` to `b` turns in x or
|
|
1351
|
+
* y, ascending, or none for a straight segment. */
|
|
1352
|
+
declare function segmentExtremaTs(a: PenAnchor, b: PenAnchor): number[];
|
|
1353
|
+
/**
|
|
1354
|
+
* Split every curved segment of `set` at its extremes
|
|
1355
|
+
* ({@link segmentExtremaTs}), in place. `include(sub, segIdx)` limits it to
|
|
1356
|
+
* some segments, named as `segmentEnds` names them; absent, every one.
|
|
1357
|
+
* Returns the new anchors' flat indices in the edited set. Each new anchor is
|
|
1358
|
+
* smooth, and every anchor after one moves up an index.
|
|
1359
|
+
*/
|
|
1360
|
+
declare function addExtremaAnchors(set: AnchorSet, include?: (sub: number, segIdx: number) => boolean): number[];
|
|
1361
|
+
|
|
1362
|
+
/**
|
|
1363
|
+
* Anchor selections walked along the path: grown or shrunk by one anchor,
|
|
1364
|
+
* every Nth anchor, anchors by kind, and the complement. Each takes the
|
|
1365
|
+
* decoded set and a selection as flat indices, and returns a new selection
|
|
1366
|
+
* as sorted flat indices; none of them edits the set.
|
|
1367
|
+
*
|
|
1368
|
+
* "Along the path" means within a subpath: an anchor's neighbors are the
|
|
1369
|
+
* anchors before and after it there, and a closed subpath's first and last
|
|
1370
|
+
* anchors are neighbors.
|
|
1371
|
+
*/
|
|
1372
|
+
|
|
1373
|
+
/** `selected` with each selected anchor's neighbors along the path added. */
|
|
1374
|
+
declare function growAnchorSelection(set: AnchorSet, selected: Iterable<number>): number[];
|
|
1375
|
+
/**
|
|
1376
|
+
* `selected` less every anchor at the edge of a selected run: one with a
|
|
1377
|
+
* neighbor that is unselected, or none on one side, as an open subpath's ends
|
|
1378
|
+
* have. A closed subpath selected all the way round has no edge and stays.
|
|
1379
|
+
*/
|
|
1380
|
+
declare function shrinkAnchorSelection(set: AnchorSet, selected: Iterable<number>): number[];
|
|
1381
|
+
/**
|
|
1382
|
+
* Every `n`th anchor along each subpath, counting from its first selected
|
|
1383
|
+
* anchor. With nothing selected, every subpath counts from its first anchor;
|
|
1384
|
+
* otherwise only subpaths holding a selected anchor take part. A closed
|
|
1385
|
+
* subpath is walked once round, so the count does not wrap onto itself.
|
|
1386
|
+
*/
|
|
1387
|
+
declare function everyNthAnchor(set: AnchorSet, n: number, selected?: Iterable<number>): number[];
|
|
1388
|
+
/** Every anchor `keep` says yes to. */
|
|
1389
|
+
declare function anchorsWhere(set: AnchorSet, keep: (anchor: PenAnchor) => boolean): number[];
|
|
1390
|
+
/** Every corner anchor: one whose handles are not collinear through it, or
|
|
1391
|
+
* that lacks one (`isAnchorSmooth` false). */
|
|
1392
|
+
declare function cornerAnchors(set: AnchorSet): number[];
|
|
1393
|
+
/** Every smooth anchor (`isAnchorSmooth`). */
|
|
1394
|
+
declare function smoothAnchors(set: AnchorSet): number[];
|
|
1395
|
+
/** Every anchor `selected` leaves out. */
|
|
1396
|
+
declare function invertAnchorSelection(set: AnchorSet, selected: Iterable<number>): number[];
|
|
1397
|
+
|
|
1398
|
+
/**
|
|
1399
|
+
* Average and Join: anchor-set edits that bring anchors together. Both mutate
|
|
1400
|
+
* the model `pathToAnchors` produces in place, like the edits in
|
|
1401
|
+
* `anchorEdits`, and address anchors by flat index.
|
|
1402
|
+
*/
|
|
1403
|
+
|
|
1404
|
+
/** Which coordinates {@link averageAnchorsAt} averages: `'x'` lines the
|
|
1405
|
+
* anchors up on one vertical, `'y'` on one horizontal, `'both'` stacks them
|
|
1406
|
+
* on one point. */
|
|
1407
|
+
type AverageAxis = 'x' | 'y' | 'both';
|
|
1408
|
+
/** One end of an open subpath. */
|
|
1409
|
+
interface SubpathEnd {
|
|
1410
|
+
sub: number;
|
|
1411
|
+
end: 'first' | 'last';
|
|
1412
|
+
}
|
|
1413
|
+
/** How {@link joinSubpathEnds} spans the gap between two ends apart. */
|
|
1414
|
+
interface JoinOptions {
|
|
1415
|
+
/** Absent, a straight segment. Given, a curve leaving each end along the
|
|
1416
|
+
* direction its path was heading there, each handle `tension` times the
|
|
1417
|
+
* gap long; `0` is a straight segment. */
|
|
1418
|
+
tension?: number;
|
|
1419
|
+
}
|
|
1420
|
+
/**
|
|
1421
|
+
* Move each anchor in `flatIndexes` to their mean position, along `axis`.
|
|
1422
|
+
* Each anchor carries its handles with it. Returns false, changing nothing,
|
|
1423
|
+
* when fewer than two of the indexes name anchors.
|
|
1424
|
+
*/
|
|
1425
|
+
declare function averageAnchorsAt(set: AnchorSet, flatIndexes: Iterable<number>, axis?: AverageAxis): boolean;
|
|
1426
|
+
/** The open-subpath end anchor `flatIndex` names, or null for an interior
|
|
1427
|
+
* anchor or one on a closed subpath. A lone anchor reads as `'last'`. */
|
|
1428
|
+
declare function subpathEndAt(set: AnchorSet, flatIndex: number): SubpathEnd | null;
|
|
1429
|
+
/**
|
|
1430
|
+
* Join the two open-subpath ends `a` and `b`. The two ends of one subpath
|
|
1431
|
+
* close it; ends of two subpaths make one subpath, `a`'s run followed by
|
|
1432
|
+
* `b`'s, in the slot of whichever came first. Ends that coincide merge into
|
|
1433
|
+
* one anchor, keeping the handle on either side; ends apart are bridged by a
|
|
1434
|
+
* straight segment, or with `options.tension` by a curve meeting each end
|
|
1435
|
+
* tangentially. Returns false, changing nothing, when the ends are not two
|
|
1436
|
+
* distinct ends of open subpaths.
|
|
1437
|
+
*/
|
|
1438
|
+
declare function joinSubpathEnds(set: AnchorSet, a: SubpathEnd, b: SubpathEnd, options?: JoinOptions): boolean;
|
|
1439
|
+
/** {@link joinSubpathEnds} for two anchors named by flat index, each the end
|
|
1440
|
+
* of an open subpath. */
|
|
1441
|
+
declare function joinAnchorsAt(set: AnchorSet, flatA: number, flatB: number, options?: JoinOptions): boolean;
|
|
1442
|
+
/**
|
|
1443
|
+
* The two open-subpath ends nearest each other that `accept` allows, on two
|
|
1444
|
+
* different subpaths. Null when there are no two such subpaths.
|
|
1445
|
+
*/
|
|
1446
|
+
declare function closestOpenEnds(set: AnchorSet, accept?: (a: SubpathEnd, b: SubpathEnd) => boolean): [SubpathEnd, SubpathEnd] | null;
|
|
1447
|
+
|
|
1448
|
+
/**
|
|
1449
|
+
* Spiro curves as cubic paths, and back. A solved curve is written as cubics,
|
|
1450
|
+
* each spiral segment split into as many as it takes to stay within tolerance,
|
|
1451
|
+
* so most anchors of the path are not spiro points. `at` records which are:
|
|
1452
|
+
* `at[i]` is the flat anchor index of point `i`, counted across subpaths. The
|
|
1453
|
+
* points are then read back out of the path itself, so whatever moves the path
|
|
1454
|
+
* — a move, a resize, a rotation — moves them with it.
|
|
1455
|
+
*/
|
|
1456
|
+
|
|
1457
|
+
/** One subpath of a spiro curve: its points, and whether it closes. */
|
|
1458
|
+
interface SpiroContour {
|
|
1459
|
+
points: SpiroPoint[];
|
|
1460
|
+
closed: boolean;
|
|
1461
|
+
}
|
|
1462
|
+
/** A spiro curve written as a cubic path, with the anchor each point became. */
|
|
1463
|
+
interface SpiroPath {
|
|
1464
|
+
path: PolygonPath;
|
|
1465
|
+
/** The flat anchor index of each point, in contour order. */
|
|
1466
|
+
at: number[];
|
|
1467
|
+
}
|
|
1468
|
+
/** Options for {@link spiroToPath}. */
|
|
1469
|
+
interface SpiroToPathOptions {
|
|
1470
|
+
/** The furthest a cubic may stray from its spiral, as a fraction of that
|
|
1471
|
+
* segment's arc length. Default `1e-4`. */
|
|
1472
|
+
tolerance?: number;
|
|
1473
|
+
/** The path being reshaped, whose fill rules the result keeps. */
|
|
1474
|
+
like?: PolygonPath;
|
|
1475
|
+
}
|
|
1476
|
+
/**
|
|
1477
|
+
* Solve each contour and write it as a cubic path. Straight segments carry no
|
|
1478
|
+
* handles.
|
|
1479
|
+
*/
|
|
1480
|
+
declare function spiroToPath(contours: readonly SpiroContour[], options?: SpiroToPathOptions): SpiroPath;
|
|
1481
|
+
/**
|
|
1482
|
+
* The spiro points `path` holds, given the kind of each and the anchor each
|
|
1483
|
+
* became. Null when `kinds` and `at` do not describe `path`: the counts
|
|
1484
|
+
* differ, an index is out of order or out of range, or a subpath does not
|
|
1485
|
+
* start on a point.
|
|
1486
|
+
*/
|
|
1487
|
+
declare function spiroContoursOf(path: PolygonPath, kinds: readonly SpiroKind[], at: readonly number[]): SpiroContour[] | null;
|
|
1488
|
+
/** The straight-sided path through each contour's points: what an editor
|
|
1489
|
+
* shows and moves in place of the curve. */
|
|
1490
|
+
declare function spiroControlPath(contours: readonly SpiroContour[]): PolygonPath;
|
|
1491
|
+
/**
|
|
1492
|
+
* Read an edited control path back as contours: every anchor is a point.
|
|
1493
|
+
* Kinds follow from `before`, the contours the edit started from: point for
|
|
1494
|
+
* point when the count is unchanged, else by position, with an anchor that
|
|
1495
|
+
* lands nowhere a point was taking `fallback`. Handles are ignored.
|
|
1496
|
+
*/
|
|
1497
|
+
declare function spiroContoursFromControl(control: PolygonPath, before: readonly SpiroContour[], fallback?: SpiroKind): SpiroContour[];
|
|
598
1498
|
|
|
599
1499
|
/**
|
|
600
1500
|
* Path hit-testing: path-vs-point (filled region and stroke distance),
|
|
@@ -630,7 +1530,7 @@ interface StrokeHitTestOptions {
|
|
|
630
1530
|
* transform no world distance equals it. */
|
|
631
1531
|
slop?: {
|
|
632
1532
|
px: number;
|
|
633
|
-
transform:
|
|
1533
|
+
transform: Affine;
|
|
634
1534
|
};
|
|
635
1535
|
}
|
|
636
1536
|
/** Filled-region hit-test for a path. Rect short-circuits to AABB; polygons run ray-cast / winding per `fillRule`. */
|
|
@@ -669,12 +1569,13 @@ declare function polygonContainsPath(polygon: readonly Point[], path: Path, opts
|
|
|
669
1569
|
declare function polygonIntersectsPath(polygon: readonly Point[], path: Path, opts?: PolygonIntersectsPathOptions): boolean;
|
|
670
1570
|
|
|
671
1571
|
/**
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
* points
|
|
675
|
-
*
|
|
1572
|
+
* The affine map carrying the points of `from` closest to those of `to`, by
|
|
1573
|
+
* least squares; both are interleaved `x, y` streams of the same length. When
|
|
1574
|
+
* the points lie on one line an affine map is not determined, and the
|
|
1575
|
+
* similarity (turn, even scale and move) is returned instead. Null for fewer
|
|
1576
|
+
* than two distinct points.
|
|
676
1577
|
*/
|
|
677
|
-
declare function
|
|
1578
|
+
declare function fitAffine(from: ArrayLike<number>, to: ArrayLike<number>): Affine | null;
|
|
678
1579
|
|
|
679
1580
|
/**
|
|
680
1581
|
* Ergonomic builders for tiny shape paths used by chrome / overlays / markers.
|
|
@@ -730,9 +1631,9 @@ declare function translated(m: GlMat3, tx: number, ty: number): GlMat3;
|
|
|
730
1631
|
declare function scaled(m: GlMat3, sx: number, sy: number): GlMat3;
|
|
731
1632
|
/** This layout read as the kernel's 6-element affine. The two carry the same
|
|
732
1633
|
* logical order, so the conversion is a repack and nothing else. */
|
|
733
|
-
declare function toAffine(m: GlMat3):
|
|
1634
|
+
declare function toAffine(m: GlMat3): Affine;
|
|
734
1635
|
/** The kernel's affine in this layout. The inverse of {@link toAffine}. */
|
|
735
|
-
declare function fromAffine(a:
|
|
1636
|
+
declare function fromAffine(a: Affine): GlMat3;
|
|
736
1637
|
/** Inverse of an affine matrix, or `null` when `@weasel-js/geom`'s `invert`
|
|
737
1638
|
* finds it singular — the same rule, read through this layout. */
|
|
738
1639
|
declare function invert(m: GlMat3): GlMat3 | null;
|
|
@@ -757,7 +1658,7 @@ declare function meanScaleOf(m: GlMat3): number;
|
|
|
757
1658
|
declare function minScaleOf(m: GlMat3): number;
|
|
758
1659
|
/** The renderer's 3x3 matrix operations, as one namespace. These work on the
|
|
759
1660
|
* 9-element form the GL uniform upload wants — distinct from the 6-element
|
|
760
|
-
*
|
|
1661
|
+
* `Affine`, though the logical element order is the same. */
|
|
761
1662
|
declare const mat3: {
|
|
762
1663
|
identity: typeof identity;
|
|
763
1664
|
toAffine: typeof toAffine;
|
|
@@ -996,77 +1897,6 @@ declare function meanScale(s: {
|
|
|
996
1897
|
y: number;
|
|
997
1898
|
}): number;
|
|
998
1899
|
|
|
999
|
-
/**
|
|
1000
|
-
* Screen-pixel lengths in world units, per axis.
|
|
1001
|
-
*
|
|
1002
|
-
* Chrome declares its hit zones in screen pixels — an 8px handle stays 8px at
|
|
1003
|
-
* every zoom, because it paints in screen space. Converting one such length to
|
|
1004
|
-
* world units with a single scalar (see `meanScale`) is exact only under
|
|
1005
|
-
* uniform zoom; per-axis it is too generous on one axis and too mean on the
|
|
1006
|
-
* other, so the pickable region stops matching the painted one.
|
|
1007
|
-
*
|
|
1008
|
-
* Prefer {@link withinPxBox} / {@link withinPxRadius}, which compare in screen
|
|
1009
|
-
* space and so can't drift from the paint at all. {@link pxExtent} is for the
|
|
1010
|
-
* cases that must stay in world units — a tolerance handed to geometry that
|
|
1011
|
-
* doesn't know about the view.
|
|
1012
|
-
*/
|
|
1013
|
-
interface Scale2 {
|
|
1014
|
-
x: number;
|
|
1015
|
-
y: number;
|
|
1016
|
-
}
|
|
1017
|
-
/** One screen-pixel length as world-space extents, per axis. `scale` is a
|
|
1018
|
-
* view's, so neither axis is zero (see `View`).
|
|
1019
|
-
*
|
|
1020
|
-
* With `rotation`, the axes are a frame turned that far from world, and each
|
|
1021
|
-
* extent is how far along it an edge across it must move to move `px` on
|
|
1022
|
-
* screen — which, under non-uniform zoom, is not the extent along the screen
|
|
1023
|
-
* axis nearest to it. */
|
|
1024
|
-
declare function pxExtent(px: number, scale: Scale2, rotation?: number): {
|
|
1025
|
-
x: number;
|
|
1026
|
-
y: number;
|
|
1027
|
-
};
|
|
1028
|
-
/** World delta → screen delta. Only the scale participates: translation
|
|
1029
|
-
* cancels in a difference, and the kit's views carry no skew. */
|
|
1030
|
-
declare function scaleDelta(dx: number, dy: number, scale: Scale2): {
|
|
1031
|
-
x: number;
|
|
1032
|
-
y: number;
|
|
1033
|
-
};
|
|
1034
|
-
/**
|
|
1035
|
-
* Is a world-space delta inside a screen-space square of half-extent `px`?
|
|
1036
|
-
*
|
|
1037
|
-
* The square is axis-aligned **on screen**, which is what a handle painted in
|
|
1038
|
-
* screen space actually is — so this stays true under non-uniform zoom and
|
|
1039
|
-
* under a rotated target, where an axis-aligned world-space test is a rotated
|
|
1040
|
-
* rectangle on screen.
|
|
1041
|
-
*/
|
|
1042
|
-
declare function withinPxBox(dx: number, dy: number, px: number, scale: Scale2): boolean;
|
|
1043
|
-
/** Is a world-space delta inside a screen-space circle of radius `px`? */
|
|
1044
|
-
declare function withinPxRadius(dx: number, dy: number, px: number, scale: Scale2): boolean;
|
|
1045
|
-
/**
|
|
1046
|
-
* A world point pushed `px` screen pixels off an edge, along the edge's normal
|
|
1047
|
-
* as it lands on screen. `normal` is the edge's outward normal in world space.
|
|
1048
|
-
*
|
|
1049
|
-
* Scaling the world normal by the view is not the same thing: under
|
|
1050
|
-
* non-uniform zoom the image of a normal is no longer perpendicular to the
|
|
1051
|
-
* image of its edge, so chrome placed that way drifts sideways and sits closer
|
|
1052
|
-
* than `px`. Returns the point in world coords and the on-screen unit normal.
|
|
1053
|
-
*/
|
|
1054
|
-
declare function standoff(anchor: {
|
|
1055
|
-
x: number;
|
|
1056
|
-
y: number;
|
|
1057
|
-
}, normal: {
|
|
1058
|
-
x: number;
|
|
1059
|
-
y: number;
|
|
1060
|
-
}, px: number, scale: Scale2): {
|
|
1061
|
-
x: number;
|
|
1062
|
-
y: number;
|
|
1063
|
-
nx: number;
|
|
1064
|
-
ny: number;
|
|
1065
|
-
};
|
|
1066
|
-
/** The screen angle a frame turned `rotation` from world lands its x axis at.
|
|
1067
|
-
* Equals `rotation` under uniform zoom; non-uniform zoom bends it. */
|
|
1068
|
-
declare function screenAngleOf(rotation: number, scale: Scale2): number;
|
|
1069
|
-
|
|
1070
1900
|
/** Pivot (`cx`, `cy`) and angle resolved from a pose's rotation convention. */
|
|
1071
1901
|
interface PoseRotation {
|
|
1072
1902
|
cx: number;
|
|
@@ -1098,11 +1928,25 @@ declare function rotatePathAround(path: Path, cx: number, cy: number, rotation:
|
|
|
1098
1928
|
/**
|
|
1099
1929
|
* The linear part of a box pose that its box, rotation, and flips cannot
|
|
1100
1930
|
* hold: a skew, or a scale that differs by axis. `[a, b, c, d]` in
|
|
1101
|
-
* `
|
|
1931
|
+
* `Affine` order (`x' = a·x + c·y`, `y' = b·x + d·y`), applied about the
|
|
1102
1932
|
* box center to what the node draws in its unrotated box, before the
|
|
1103
1933
|
* rotation. Absent is the identity.
|
|
1104
1934
|
*/
|
|
1105
1935
|
type PoseLinear = readonly [a: number, b: number, c: number, d: number];
|
|
1936
|
+
/**
|
|
1937
|
+
* Axis-aligned rectangle in world space. The optional `rotation` (radians,
|
|
1938
|
+
* around the AABB center) and `transform` (inside it, about the same center)
|
|
1939
|
+
* let chrome carry the frame a box is drawn in without a parallel type;
|
|
1940
|
+
* `poseFrameOf` composes the two. routing and core call it `Bounds`.
|
|
1941
|
+
*/
|
|
1942
|
+
interface FramedBox {
|
|
1943
|
+
x: number;
|
|
1944
|
+
y: number;
|
|
1945
|
+
width: number;
|
|
1946
|
+
height: number;
|
|
1947
|
+
rotation?: number;
|
|
1948
|
+
transform?: PoseLinear;
|
|
1949
|
+
}
|
|
1106
1950
|
/** `transform` when it changes anything, `null` for absent or the identity. */
|
|
1107
1951
|
declare function poseLinearOf(pose: unknown): PoseLinear | null;
|
|
1108
1952
|
/**
|
|
@@ -1111,133 +1955,781 @@ declare function poseLinearOf(pose: unknown): PoseLinear | null;
|
|
|
1111
1955
|
* `null` when the pose has neither, or is not a box, so a caller can skip
|
|
1112
1956
|
* the step.
|
|
1113
1957
|
*/
|
|
1114
|
-
declare function poseFrameOf(pose: unknown):
|
|
1958
|
+
declare function poseFrameOf(pose: unknown): Affine | null;
|
|
1115
1959
|
/**
|
|
1116
1960
|
* The inverse of {@link poseFrameOf}: where a parent-frame point falls in the
|
|
1117
1961
|
* pose's unrotated box frame. `null` when there is no frame to undo, or when
|
|
1118
1962
|
* the `transform` is singular and nothing maps back.
|
|
1119
1963
|
*/
|
|
1120
|
-
declare function poseFrameInverseOf(pose: unknown):
|
|
1964
|
+
declare function poseFrameInverseOf(pose: unknown): Affine | null;
|
|
1121
1965
|
/** `path`, given in the pose's unrotated box frame, as the node draws it. */
|
|
1122
1966
|
declare function pathThroughPoseFrame(path: Path, pose: unknown): Path;
|
|
1123
1967
|
|
|
1124
1968
|
/**
|
|
1125
|
-
*
|
|
1126
|
-
* `
|
|
1127
|
-
*
|
|
1128
|
-
*
|
|
1129
|
-
*
|
|
1130
|
-
* Callers address anchors by flat index — the sequential position in walk
|
|
1131
|
-
* order across all subpaths, which is what `enumerateAnchors` reports.
|
|
1132
|
-
* {@link locateAnchor} and {@link flatAnchorIndex} convert to and from the
|
|
1133
|
-
* `(sub, idx)` pair.
|
|
1134
|
-
*
|
|
1135
|
-
* The two orders agree because `pathToAnchors` and `enumerateAnchors`
|
|
1136
|
-
* walk the same command stream and emit one anchor per M/L/C/Q, less the
|
|
1137
|
-
* end of a closing curve that lands on its subpath's first point.
|
|
1138
|
-
* `countPathAnchors`, which sizes the renderer's per-anchor arrays, counts
|
|
1139
|
-
* that end too and so can be one higher per closed subpath.
|
|
1969
|
+
* Flat indices of every anchor a round brush covers as it moves from `from` to
|
|
1970
|
+
* `to`: those within `radiusPx` of that segment, measured on screen. A dab is a
|
|
1971
|
+
* segment of zero length. `scale` is the view's, so the brush stays round on
|
|
1972
|
+
* screen under non-uniform zoom; omitted, one unit is one pixel.
|
|
1140
1973
|
*/
|
|
1974
|
+
declare function anchorsUnderBrush(set: AnchorSet, from: Point, to: Point, opts: {
|
|
1975
|
+
radiusPx: number;
|
|
1976
|
+
scale?: Scale2;
|
|
1977
|
+
}): number[];
|
|
1141
1978
|
|
|
1142
|
-
/**
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1979
|
+
/**
|
|
1980
|
+
* How a path maps onto itself under one transform `m`: `partners[i]` is the
|
|
1981
|
+
* flat index of the anchor that anchor `i` lands on, and `flips[i]` whether
|
|
1982
|
+
* its in-handle lands on that anchor's out-handle — a mirror reverses which
|
|
1983
|
+
* way a path runs, a rotation does not. An anchor `m` fixes is its own
|
|
1984
|
+
* partner.
|
|
1985
|
+
*/
|
|
1986
|
+
interface AnchorSymmetry {
|
|
1987
|
+
readonly m: Affine;
|
|
1988
|
+
readonly partners: readonly number[];
|
|
1989
|
+
readonly flips: readonly boolean[];
|
|
1153
1990
|
}
|
|
1154
|
-
/** Total anchors across every subpath. */
|
|
1155
|
-
declare function anchorCount(set: AnchorSet): number;
|
|
1156
|
-
/** Flat index → `(sub, idx)`. Returns null when out of range. */
|
|
1157
|
-
declare function locateAnchor(set: AnchorSet, flatIndex: number): {
|
|
1158
|
-
sub: number;
|
|
1159
|
-
idx: number;
|
|
1160
|
-
} | null;
|
|
1161
|
-
/** `(sub, idx)` → flat index. Returns -1 when out of range. */
|
|
1162
|
-
declare function flatAnchorIndex(set: AnchorSet, sub: number, idx: number): number;
|
|
1163
|
-
/** Resolve a flat index to the anchor itself. Null when out of range. */
|
|
1164
|
-
declare function anchorAt(set: AnchorSet, flatIndex: number): PenAnchor | null;
|
|
1165
1991
|
/**
|
|
1166
|
-
*
|
|
1167
|
-
*
|
|
1168
|
-
*
|
|
1992
|
+
* The pairing that makes `set` its own image under `m`, or `null` when it is
|
|
1993
|
+
* not one: every anchor, handles included, must land on a distinct anchor
|
|
1994
|
+
* within `tolerance` on each axis.
|
|
1169
1995
|
*/
|
|
1170
|
-
declare function
|
|
1171
|
-
/**
|
|
1172
|
-
declare function
|
|
1996
|
+
declare function anchorSymmetry(set: AnchorSet, m: Affine, tolerance?: number): AnchorSymmetry | null;
|
|
1997
|
+
/** Every transform in `group` that `set` is its own image under, paired. */
|
|
1998
|
+
declare function anchorSymmetries(set: AnchorSet, group: readonly Affine[], tolerance?: number): AnchorSymmetry[];
|
|
1173
1999
|
/**
|
|
1174
|
-
*
|
|
1175
|
-
*
|
|
1176
|
-
*
|
|
2000
|
+
* Translate the anchors `flats` by `(dx, dy)` the way `translateAnchorBy`
|
|
2001
|
+
* does, and every image of each under `syms` by the transformed delta, so a
|
|
2002
|
+
* path that was its own image under each of them still is. `syms` should be
|
|
2003
|
+
* the whole symmetry group less its identity, as `anchorSymmetries` gives it
|
|
2004
|
+
* for a group; with a part of one, the anchors it fixes are only partly held.
|
|
2005
|
+
* An anchor that is itself being dragged moves as dragged.
|
|
1177
2006
|
*/
|
|
1178
|
-
declare function
|
|
2007
|
+
declare function translateAnchorsSymmetric(set: AnchorSet, flats: readonly number[], dx: number, dy: number, syms: readonly AnchorSymmetry[]): boolean;
|
|
1179
2008
|
/**
|
|
1180
|
-
*
|
|
1181
|
-
*
|
|
1182
|
-
*
|
|
1183
|
-
*
|
|
1184
|
-
*
|
|
1185
|
-
* one splits by de Casteljau, so the two halves trace the original path.
|
|
2009
|
+
* Move one handle to `(toX, toY)` and every image of it under `syms` to the
|
|
2010
|
+
* image of that point, so a path that was its own image under each of them
|
|
2011
|
+
* still is. A handle a transform maps onto itself keeps to where that
|
|
2012
|
+
* transform allows; one mapped onto its own anchor's opposite handle drives
|
|
2013
|
+
* that handle.
|
|
1186
2014
|
*
|
|
1187
|
-
*
|
|
1188
|
-
*
|
|
2015
|
+
* Otherwise a smooth anchor keeps the opposite handle opposite, as
|
|
2016
|
+
* `moveHandleTo` does, unless `breakSmoothness`, and that handle's images
|
|
2017
|
+
* follow it. Every handle is written once, from its target, so no anchor
|
|
2018
|
+
* re-aims a handle another image already placed.
|
|
1189
2019
|
*/
|
|
1190
|
-
declare function
|
|
2020
|
+
declare function moveHandleSymmetric(set: AnchorSet, flat: number, side: 'in' | 'out', toX: number, toY: number, breakSmoothness: boolean, syms: readonly AnchorSymmetry[]): boolean;
|
|
2021
|
+
|
|
2022
|
+
/** Where on a segment a bend is held, as `segmentAt` reports it. */
|
|
2023
|
+
interface BendGrip {
|
|
1191
2024
|
sub: number;
|
|
1192
2025
|
segIdx: number;
|
|
2026
|
+
/** Curve parameter of the held point. */
|
|
1193
2027
|
t: number;
|
|
1194
|
-
}
|
|
1195
|
-
/**
|
|
1196
|
-
|
|
2028
|
+
}
|
|
2029
|
+
/**
|
|
2030
|
+
* Bend one segment so the point held at `grip.t` moves by `(dx, dy)`, by
|
|
2031
|
+
* moving its two control handles: each by an amount weighted toward the end it
|
|
2032
|
+
* belongs to, together exactly enough to carry the held point along. A straight
|
|
2033
|
+
* segment becomes a curve. Where an end anchor was smooth, its other handle
|
|
2034
|
+
* turns to stay in line, keeping its length, so the neighboring segment bends
|
|
2035
|
+
* with it rather than kinking.
|
|
2036
|
+
*
|
|
2037
|
+
* Returns false when the segment doesn't exist.
|
|
2038
|
+
*/
|
|
2039
|
+
declare function bendSegment(set: AnchorSet, grip: BendGrip, dx: number, dy: number): boolean;
|
|
2040
|
+
|
|
2041
|
+
/**
|
|
2042
|
+
* `smudgePath` — one dab of a smudge brush: the outline under a round brush
|
|
2043
|
+
* moved along the brush's motion, most at its center and not at all at its rim.
|
|
2044
|
+
*/
|
|
2045
|
+
|
|
2046
|
+
/** Options for {@link smudgePath}. */
|
|
2047
|
+
interface SmudgePathOptions {
|
|
2048
|
+
/** The brush's center before this dab's motion. */
|
|
2049
|
+
center: Point;
|
|
2050
|
+
/** How far the brush moved. */
|
|
2051
|
+
delta: Point;
|
|
2052
|
+
/** The brush's radius, in the path's units. */
|
|
2053
|
+
radius: number;
|
|
2054
|
+
/** How much of `delta` a point under the brush's center moves: `1` all of it. Default 1. */
|
|
2055
|
+
strength?: number;
|
|
2056
|
+
/**
|
|
2057
|
+
* The longest a segment under the brush may be before an anchor is added at its
|
|
2058
|
+
* middle, in the path's units, so the brush has points to move where it needs
|
|
2059
|
+
* them. Default a third of `radius`; `Infinity` adds none.
|
|
2060
|
+
*/
|
|
2061
|
+
detail?: number;
|
|
2062
|
+
}
|
|
2063
|
+
/**
|
|
2064
|
+
* `path` with the outline under the brush pushed along `delta`. A point at distance
|
|
2065
|
+
* `d` from `center` moves by `delta × strength × (1 − (d/radius)²)²`, and an anchor's
|
|
2066
|
+
* handles move with it, so a smooth anchor stays smooth. First, every segment that
|
|
2067
|
+
* passes under the brush and is longer than `detail` is split at its middle until it
|
|
2068
|
+
* is not, so a long straight edge bends where the brush meets it. Returns `path`
|
|
2069
|
+
* itself when nothing is under the brush.
|
|
2070
|
+
*/
|
|
2071
|
+
declare function smudgePath(path: PolygonPath, opts: SmudgePathOptions): PolygonPath;
|
|
2072
|
+
|
|
2073
|
+
/**
|
|
2074
|
+
* Collapse the handles of the anchors at `flatIndexes` onto their anchors,
|
|
2075
|
+
* leaving sharp corners. A segment whose ends both lose their handles turns
|
|
2076
|
+
* straight.
|
|
2077
|
+
*
|
|
2078
|
+
* Returns false when every handle was already on its anchor. A segment that
|
|
2079
|
+
* stays curved because its far end keeps a handle still encodes a control at
|
|
2080
|
+
* this end, so it decodes as a handle sitting on the anchor: retracted.
|
|
2081
|
+
*/
|
|
2082
|
+
declare function retractHandles(set: AnchorSet, flatIndexes: Iterable<number>): boolean;
|
|
2083
|
+
/**
|
|
2084
|
+
* Give each anchor at `flatIndexes` two handles of equal length pointing in
|
|
2085
|
+
* opposite directions, so the curve passes through it smoothly. The shared
|
|
2086
|
+
* direction splits the difference between the two handles' own directions,
|
|
2087
|
+
* and the shared length is their mean; an anchor with one handle mirrors it.
|
|
2088
|
+
*
|
|
2089
|
+
* Skipped: an anchor with no handles, and the ends of an open subpath, which
|
|
2090
|
+
* have only one segment to shape. Returns false when nothing changed.
|
|
2091
|
+
*/
|
|
2092
|
+
declare function makeHandlesSymmetric(set: AnchorSet, flatIndexes: Iterable<number>): boolean;
|
|
2093
|
+
/**
|
|
2094
|
+
* Where a handle lands when dragged toward `to` but held to its current
|
|
2095
|
+
* direction from `anchor`: `to` projected onto that ray. The length never
|
|
2096
|
+
* goes below zero, so the handle can shrink onto the anchor but not flip
|
|
2097
|
+
* through it. A handle already sitting on its anchor has no direction to
|
|
2098
|
+
* keep and follows `to` freely.
|
|
2099
|
+
*/
|
|
2100
|
+
declare function handleAlongItsAngle(anchor: Point, handle: Point, to: Point): Point;
|
|
2101
|
+
/**
|
|
2102
|
+
* Where a handle lands when dragged toward `to` but held to its current
|
|
2103
|
+
* length from `anchor`: on the circle of that length, aimed at `to`. A `to`
|
|
2104
|
+
* on the anchor itself gives no direction, and leaves the handle where it is.
|
|
2105
|
+
*/
|
|
2106
|
+
declare function handleAtItsLength(anchor: Point, handle: Point, to: Point): Point;
|
|
2107
|
+
|
|
2108
|
+
/**
|
|
2109
|
+
* Soft selection over an anchor set: how strongly an edit to some anchors
|
|
2110
|
+
* carries to the anchors near them, by distance measured along the path.
|
|
2111
|
+
*
|
|
2112
|
+
* Distance is arc length along the drawn curve, not a straight line, so two
|
|
2113
|
+
* anchors that sit close across a gap in a shape are as far apart as the
|
|
2114
|
+
* path between them. A `scale` measures it in screen pixels under a view's
|
|
2115
|
+
* zoom, per axis.
|
|
2116
|
+
*/
|
|
2117
|
+
|
|
2118
|
+
/** How influence fades from 1 at a selected anchor to 0 at the radius:
|
|
2119
|
+
* `smooth` eases out and in, `linear` falls evenly, `sharp` drops fast and
|
|
2120
|
+
* tails off. */
|
|
2121
|
+
type SoftFalloff = 'smooth' | 'linear' | 'sharp';
|
|
2122
|
+
/**
|
|
2123
|
+
* The weight `falloff` gives a point `distance` from the selection, for a
|
|
2124
|
+
* radius of `radius`: 1 at distance 0, 0 at the radius and beyond.
|
|
2125
|
+
*/
|
|
2126
|
+
declare function softFalloff(falloff: SoftFalloff, distance: number, radius: number): number;
|
|
2127
|
+
/** Arc length along one segment, sampled at evenly spaced curve parameters. */
|
|
2128
|
+
interface SegmentMeasure {
|
|
2129
|
+
/** Arc length from the subpath's start to each sample; sample `i` is at
|
|
2130
|
+
* parameter `i / (lengths.length - 1)`. */
|
|
2131
|
+
lengths: Float64Array;
|
|
2132
|
+
}
|
|
2133
|
+
/** Arc lengths along one subpath, as {@link measureAnchorPath} takes them. */
|
|
2134
|
+
interface AnchorSubpathMeasure {
|
|
2135
|
+
closed: boolean;
|
|
2136
|
+
/** Flat index of the subpath's first anchor. */
|
|
2137
|
+
first: number;
|
|
2138
|
+
/** Arc length from the subpath's start to each anchor. */
|
|
2139
|
+
at: Float64Array;
|
|
2140
|
+
/** Total length, the closing segment included on a closed subpath. */
|
|
2141
|
+
length: number;
|
|
2142
|
+
/** Segment `i` runs from anchor `i` to anchor `i + 1`, wrapping on a closed subpath. */
|
|
2143
|
+
segments: SegmentMeasure[];
|
|
2144
|
+
}
|
|
2145
|
+
/** Arc lengths along every subpath of an anchor set, as
|
|
2146
|
+
* {@link measureAnchorPath} takes them. Read it with
|
|
2147
|
+
* {@link softSelectionWeights} and {@link softSelectionBand}. */
|
|
2148
|
+
interface AnchorPathMeasure {
|
|
2149
|
+
readonly subpaths: readonly AnchorSubpathMeasure[];
|
|
2150
|
+
}
|
|
2151
|
+
/** Options for {@link measureAnchorPath}. */
|
|
2152
|
+
interface MeasureAnchorPathOptions {
|
|
2153
|
+
/** Per-axis factor applied before measuring — a view's scale, to measure in
|
|
2154
|
+
* screen pixels. Default 1 on both axes. */
|
|
2155
|
+
scale?: {
|
|
2156
|
+
x: number;
|
|
2157
|
+
y: number;
|
|
2158
|
+
};
|
|
2159
|
+
/** Samples taken along each curved segment. Default 24. */
|
|
2160
|
+
samples?: number;
|
|
2161
|
+
}
|
|
2162
|
+
/** Measure the arc length along every subpath of `set`. */
|
|
2163
|
+
declare function measureAnchorPath(set: AnchorSet, opts?: MeasureAnchorPathOptions): AnchorPathMeasure;
|
|
2164
|
+
/**
|
|
2165
|
+
* How much of an edit to the `selected` anchors each anchor receives: 1 for
|
|
2166
|
+
* a selected anchor, the falloff of its distance along the path for one
|
|
2167
|
+
* within `radius` of the nearest selected anchor on its subpath. Anchors
|
|
2168
|
+
* that receive nothing are absent, as are anchors on a subpath with no
|
|
2169
|
+
* selected anchor.
|
|
2170
|
+
*/
|
|
2171
|
+
declare function softSelectionWeights(measure: AnchorPathMeasure, selected: Iterable<number>, radius: number, falloff: SoftFalloff): Map<number, number>;
|
|
2172
|
+
/**
|
|
2173
|
+
* The stretches of path within `radius` of the `selected` anchors, as world
|
|
2174
|
+
* polylines drawn on `set`. `measure` is of the set the distances are taken
|
|
2175
|
+
* on — the path as it was when the edit began — and `set` the geometry to
|
|
2176
|
+
* draw on, which must have the same anchors. A stretch crossing the seam of a
|
|
2177
|
+
* closed subpath comes back as one run.
|
|
2178
|
+
*/
|
|
2179
|
+
declare function softSelectionBand(measure: AnchorPathMeasure, set: AnchorSet, selected: Iterable<number>, radius: number): Point[][];
|
|
2180
|
+
|
|
2181
|
+
/** A curved segment's balance line: from its first handle's tip to its
|
|
2182
|
+
* second's, with a grip at the middle. */
|
|
2183
|
+
interface HandleBalance {
|
|
1197
2184
|
sub: number;
|
|
1198
2185
|
segIdx: number;
|
|
1199
|
-
/**
|
|
2186
|
+
/** Flat index of the anchor the segment starts at, which names the segment
|
|
2187
|
+
* the way an anchor's flat index names the anchor. */
|
|
2188
|
+
flat: number;
|
|
2189
|
+
/** Tip of the segment's first handle, the start anchor's out-handle. */
|
|
2190
|
+
from: Point;
|
|
2191
|
+
/** Tip of the segment's second handle, the end anchor's in-handle. */
|
|
2192
|
+
to: Point;
|
|
2193
|
+
/** Midway between the two tips. */
|
|
2194
|
+
grip: Point;
|
|
2195
|
+
}
|
|
2196
|
+
/**
|
|
2197
|
+
* The balance line of every curved segment in `set` that has both handles
|
|
2198
|
+
* pulled off their anchors. Dragging a line's grip scales both handles
|
|
2199
|
+
* together ({@link scaleSegmentHandles}), which fills the curve out toward
|
|
2200
|
+
* its corner or flattens it toward its chord without turning either end.
|
|
2201
|
+
*/
|
|
2202
|
+
declare function handleBalances(set: AnchorSet): HandleBalance[];
|
|
2203
|
+
/**
|
|
2204
|
+
* Scale both handles of segment `(sub, segIdx)` by `factor`, each along its
|
|
2205
|
+
* own direction, so the segment keeps its end tangents. A smooth anchor at
|
|
2206
|
+
* either end stays smooth: its other handle points the same way as before.
|
|
2207
|
+
* `factor` below zero counts as zero, which retracts both handles.
|
|
2208
|
+
*
|
|
2209
|
+
* Under `syms`, as `anchorSymmetries` gives them, every image of either handle
|
|
2210
|
+
* moves to the image of where that handle goes, the way `moveHandleSymmetric`
|
|
2211
|
+
* moves a dragged handle's.
|
|
2212
|
+
*
|
|
2213
|
+
* Returns false when the segment has no balance line or nothing moved.
|
|
2214
|
+
*/
|
|
2215
|
+
declare function scaleSegmentHandles(set: AnchorSet, sub: number, segIdx: number, factor: number, syms?: readonly AnchorSymmetry[]): boolean;
|
|
2216
|
+
/**
|
|
2217
|
+
* The factor {@link scaleSegmentHandles} takes to bring segment
|
|
2218
|
+
* `(sub, segIdx)`'s grip as near `to` as scaling can: `to` projected onto the
|
|
2219
|
+
* line the grip slides along as both handles grow. 1 when the segment has no
|
|
2220
|
+
* balance line.
|
|
2221
|
+
*/
|
|
2222
|
+
declare function balanceFactorToward(set: AnchorSet, sub: number, segIdx: number, to: Point): number;
|
|
2223
|
+
/**
|
|
2224
|
+
* Give both handles of segment `(sub, segIdx)` the same proportion: each
|
|
2225
|
+
* reaches the same fraction of the way from its anchor to the corner where
|
|
2226
|
+
* the two handle lines cross, that fraction being the mean of the two they
|
|
2227
|
+
* had. Where the lines don't cross ahead of both handles, both take the mean
|
|
2228
|
+
* length instead. Directions are kept either way.
|
|
2229
|
+
*
|
|
2230
|
+
* Returns false when the segment has no balance line or the handles already
|
|
2231
|
+
* match.
|
|
2232
|
+
*/
|
|
2233
|
+
declare function equalizeSegmentHandles(set: AnchorSet, sub: number, segIdx: number): boolean;
|
|
2234
|
+
|
|
2235
|
+
/**
|
|
2236
|
+
* Make each smooth anchor at `flatIndexes` curvature-continuous: the curve
|
|
2237
|
+
* bends as tightly just after the anchor as just before it, so it shows no
|
|
2238
|
+
* kink in its curvature there. Only handle lengths change — each handle keeps
|
|
2239
|
+
* its direction, so the anchor stays smooth and the tangent stays put — and
|
|
2240
|
+
* the product of the two lengths is kept, so the anchor's pull on the curve
|
|
2241
|
+
* stays about as strong.
|
|
2242
|
+
*
|
|
2243
|
+
* Absent `flatIndexes`, every anchor in the set. Moving one anchor's handles
|
|
2244
|
+
* changes the curvature at its neighbors, so the fixes are repeated until
|
|
2245
|
+
* they settle.
|
|
2246
|
+
*
|
|
2247
|
+
* Skipped, because lengths alone cannot do it: a corner, an anchor missing a
|
|
2248
|
+
* handle, an end of an open subpath, and an anchor the curve bends opposite
|
|
2249
|
+
* ways either side of, or straight through on one side.
|
|
2250
|
+
*
|
|
2251
|
+
* Returns false when nothing changed.
|
|
2252
|
+
*/
|
|
2253
|
+
declare function harmonizeAnchors(set: AnchorSet, flatIndexes?: Iterable<number>): boolean;
|
|
2254
|
+
|
|
2255
|
+
/**
|
|
2256
|
+
* Where each point of an edited path came from, so an array kept per point (a skin's
|
|
2257
|
+
* weights) can follow an edit that inserts, deletes, or reorders points.
|
|
2258
|
+
*/
|
|
2259
|
+
|
|
2260
|
+
/**
|
|
2261
|
+
* Where a point of an edited path came from: point `a` of the path before the edit, or for a
|
|
2262
|
+
* point the edit made, a blend `t` of the way from point `a` to point `b`.
|
|
2263
|
+
*/
|
|
2264
|
+
interface PointOrigin {
|
|
2265
|
+
a: number;
|
|
2266
|
+
b: number;
|
|
1200
2267
|
t: number;
|
|
1201
|
-
/**
|
|
2268
|
+
/** On an anchor's own point: its subpath now runs the other way through it. */
|
|
2269
|
+
reversed?: true;
|
|
2270
|
+
}
|
|
2271
|
+
/**
|
|
2272
|
+
* `editAnchorSet`, answering also where each point of the new path came from.
|
|
2273
|
+
*
|
|
2274
|
+
* An anchor the edit kept, moved or not, keeps its points. One the edit put exactly where an
|
|
2275
|
+
* anchor was takes that anchor's, each handle by where it is, so a subpath turned around
|
|
2276
|
+
* keeps its weights. A handle an edit gave an anchor that had none takes the anchor's point. An anchor the edit made is a blend of the nearest kept anchors either side
|
|
2277
|
+
* of it in its subpath, by its distance to each, or a copy of the one it has; its origin is
|
|
2278
|
+
* `null` when its subpath has none.
|
|
2279
|
+
*/
|
|
2280
|
+
declare function editAnchorSetTracked(path: PolygonPath, edit: (set: AnchorSet) => boolean | void): {
|
|
2281
|
+
path: PolygonPath;
|
|
2282
|
+
origins: (PointOrigin | null)[];
|
|
2283
|
+
} | null;
|
|
2284
|
+
/**
|
|
2285
|
+
* An array kept per point of a path, carried through an edit: `origins` is what
|
|
2286
|
+
* {@link editAnchorSetTracked} answered. A point with no origin, and an origin past the
|
|
2287
|
+
* array's end, read 0.
|
|
2288
|
+
*/
|
|
2289
|
+
declare function remapPointValues(values: ArrayLike<number>, origins: readonly (PointOrigin | null)[]): number[];
|
|
2290
|
+
|
|
2291
|
+
/**
|
|
2292
|
+
* Arrays kept per anchor of a path — vertex colors, stroke widths — carried through an edit
|
|
2293
|
+
* that `editAnchorSetTracked` reported.
|
|
2294
|
+
*/
|
|
2295
|
+
|
|
2296
|
+
/**
|
|
2297
|
+
* Where each anchor of `after` came from, in anchors of `before` as `countPathAnchors` counts
|
|
2298
|
+
* them, given the point `origins` `editAnchorSetTracked` answered for the edit: anchor `a`, or
|
|
2299
|
+
* for an anchor the edit made, a blend `t` of the way from `a` to `b`. `reversed` marks an
|
|
2300
|
+
* anchor whose subpath now runs the other way through it. Null for an anchor with no origin.
|
|
2301
|
+
*/
|
|
2302
|
+
declare function anchorOriginsOf(before: PolygonPath, after: PolygonPath, origins: readonly (PointOrigin | null)[]): (PointOrigin | null)[];
|
|
2303
|
+
/**
|
|
2304
|
+
* An array kept per anchor of a path, `stride` numbers each — four color channels, say —
|
|
2305
|
+
* carried through an edit from `before` to `after`, with `origins` as
|
|
2306
|
+
* `editAnchorSetTracked` answered. An anchor the edit kept keeps its numbers; one it
|
|
2307
|
+
* made blends those of the anchors it came between. An anchor with no origin reads 0. Anchors
|
|
2308
|
+
* are counted as `countPathAnchors` counts them.
|
|
2309
|
+
*/
|
|
2310
|
+
declare function remapAnchorValues(values: ArrayLike<number>, stride: number, before: PolygonPath, after: PolygonPath, origins: readonly (PointOrigin | null)[]): number[];
|
|
2311
|
+
|
|
2312
|
+
/**
|
|
2313
|
+
* Geometric constraints on a path's anchors. Each names anchors by flat index,
|
|
2314
|
+
* the walk-order numbering `enumerateAnchors` and `anchorAt` use, and is plain
|
|
2315
|
+
* JSON, so a list of them can be kept in scene data and saved with it.
|
|
2316
|
+
*/
|
|
2317
|
+
/** Two anchors by flat index: the straight line from the first to the second. */
|
|
2318
|
+
type AnchorPair = readonly [number, number];
|
|
2319
|
+
/**
|
|
2320
|
+
* One constraint. `fixed` holds an anchor where it was before an edit, so it
|
|
2321
|
+
* moves with its node but not with any edit of the path. `horizontal` and
|
|
2322
|
+
* `vertical` read the axes of the frame the solve is given; `length` is in
|
|
2323
|
+
* the path's own units. `tangent` keeps an anchor's two handles on one line
|
|
2324
|
+
* through it, pointing apart (G1 continuity), their lengths free; it needs
|
|
2325
|
+
* both handles. `onPath` holds an anchor on the path's segment from
|
|
2326
|
+
* `segment[0]` to `segment[1]`, anywhere along it.
|
|
2327
|
+
*/
|
|
2328
|
+
type PathConstraint = {
|
|
2329
|
+
readonly kind: 'fixed' | 'tangent';
|
|
2330
|
+
readonly anchor: number;
|
|
2331
|
+
} | {
|
|
2332
|
+
readonly kind: 'horizontal' | 'vertical';
|
|
2333
|
+
readonly segment: AnchorPair;
|
|
2334
|
+
} | {
|
|
2335
|
+
readonly kind: 'parallel' | 'perpendicular' | 'equalLength';
|
|
2336
|
+
readonly segments: readonly [AnchorPair, AnchorPair];
|
|
2337
|
+
} | {
|
|
2338
|
+
readonly kind: 'length';
|
|
2339
|
+
readonly segment: AnchorPair;
|
|
2340
|
+
readonly length: number;
|
|
2341
|
+
} | {
|
|
2342
|
+
readonly kind: 'coincident';
|
|
2343
|
+
readonly anchors: AnchorPair;
|
|
2344
|
+
} | {
|
|
2345
|
+
readonly kind: 'onPath';
|
|
2346
|
+
readonly anchor: number;
|
|
2347
|
+
readonly segment: AnchorPair;
|
|
2348
|
+
};
|
|
2349
|
+
/** Every kind of {@link PathConstraint}. */
|
|
2350
|
+
type PathConstraintKind = PathConstraint['kind'];
|
|
2351
|
+
/** The anchors `c` reads, in the order it names them; an anchor named twice is listed twice. */
|
|
2352
|
+
declare function constraintAnchors(c: PathConstraint): number[];
|
|
2353
|
+
/**
|
|
2354
|
+
* `c` with every anchor index passed through `to`, or null when `to` answers
|
|
2355
|
+
* `undefined` for any of them — the anchor is gone, and so is the constraint.
|
|
2356
|
+
*/
|
|
2357
|
+
declare function mapConstraintAnchors(c: PathConstraint, to: (anchor: number) => number | undefined): PathConstraint | null;
|
|
2358
|
+
/** Whether every anchor `c` names is an index below `count`. */
|
|
2359
|
+
declare function constraintFits(c: PathConstraint, count: number): boolean;
|
|
2360
|
+
|
|
2361
|
+
/**
|
|
2362
|
+
* The points a constraint solve reads, and the coordinate vector it works in:
|
|
2363
|
+
* anchors, then each anchor's handles as offsets from it (see `ResidualSpace`).
|
|
2364
|
+
*/
|
|
2365
|
+
|
|
2366
|
+
/** An anchor the solver reads and writes, with its handles where it has them. */
|
|
2367
|
+
interface ConstraintPoint {
|
|
1202
2368
|
x: number;
|
|
1203
2369
|
y: number;
|
|
2370
|
+
inHandle?: {
|
|
2371
|
+
x: number;
|
|
2372
|
+
y: number;
|
|
2373
|
+
};
|
|
2374
|
+
outHandle?: {
|
|
2375
|
+
x: number;
|
|
2376
|
+
y: number;
|
|
2377
|
+
};
|
|
2378
|
+
}
|
|
2379
|
+
/** One handle of an anchor. */
|
|
2380
|
+
interface HandleRef {
|
|
2381
|
+
anchor: number;
|
|
2382
|
+
side: 'in' | 'out';
|
|
1204
2383
|
}
|
|
1205
2384
|
/**
|
|
1206
|
-
*
|
|
1207
|
-
*
|
|
1208
|
-
|
|
1209
|
-
|
|
2385
|
+
* Whether `c` can be solved over `points`: every anchor it names exists, and
|
|
2386
|
+
* a `tangent` anchor has both handles.
|
|
2387
|
+
*/
|
|
2388
|
+
declare function constraintApplies(c: PathConstraint, points: readonly ConstraintPoint[]): boolean;
|
|
2389
|
+
|
|
2390
|
+
/**
|
|
2391
|
+
* A damped Gauss-Newton solve for anchor constraints: from the state an edit
|
|
2392
|
+
* left, the smallest weighted move of the anchors and handles that makes
|
|
2393
|
+
* every residual zero. Each step is the minimum-norm solution of the
|
|
2394
|
+
* linearized system, `Δ = -M Jᵀ (J M Jᵀ + λI)⁻¹ r`, where `M` weighs how
|
|
2395
|
+
* freely each coordinate may move; λ grows when a step makes things worse and
|
|
2396
|
+
* shrinks when it helps, which is the Levenberg-Marquardt schedule run on the
|
|
2397
|
+
* constraint side.
|
|
1210
2398
|
*
|
|
1211
|
-
*
|
|
1212
|
-
*
|
|
1213
|
-
* affine, so the curve's parameterization, and therefore `t`, carries
|
|
1214
|
-
* straight back to world space.
|
|
2399
|
+
* A handle is a coordinate of its own only where a `tangent` reads it; any
|
|
2400
|
+
* other rides with its anchor, as an offset nothing changes.
|
|
1215
2401
|
*/
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
2402
|
+
|
|
2403
|
+
/** Options for {@link solveConstraints}. */
|
|
2404
|
+
interface SolveConstraintsOptions {
|
|
2405
|
+
/** Anchors the edit put where they are — the dragged ones. They move only when no other anchor can satisfy the constraints. */
|
|
2406
|
+
held?: Iterable<number>;
|
|
2407
|
+
/** Handles the edit put where they are, held the way `held` holds anchors. */
|
|
2408
|
+
heldHandles?: Iterable<HandleRef>;
|
|
2409
|
+
/** Where each anchor was before the edit, which is where a `fixed` constraint keeps it. Default: where it is now. */
|
|
2410
|
+
reference?: readonly (ConstraintPoint | undefined)[];
|
|
2411
|
+
/** Radians the frame `horizontal` and `vertical` read is turned from the world's axes. Default 0. */
|
|
2412
|
+
axisAngle?: number;
|
|
2413
|
+
/** A frame per constraint, by index, over `axisAngle` — for constraints gathered from paths drawn in different frames. */
|
|
2414
|
+
axisAngles?: readonly (number | undefined)[];
|
|
2415
|
+
/** Indices of constraints to leave out of the solve — ones already known not to hold. */
|
|
2416
|
+
skip?: Iterable<number>;
|
|
2417
|
+
/** Default 100. */
|
|
2418
|
+
maxIterations?: number;
|
|
2419
|
+
/** The largest residual the solve stops at. Default 1e-7. */
|
|
2420
|
+
tolerance?: number;
|
|
2421
|
+
}
|
|
2422
|
+
/** What {@link solveConstraints} answers. */
|
|
2423
|
+
interface SolveConstraintsResult {
|
|
2424
|
+
/** Every anchor, moved, with its handles. */
|
|
2425
|
+
points: ConstraintPoint[];
|
|
2426
|
+
/** Whether every constraint the solve took holds within its tolerance. */
|
|
2427
|
+
converged: boolean;
|
|
2428
|
+
iterations: number;
|
|
2429
|
+
/** Indices of the constraints that do not hold in `points`, skipped ones included. */
|
|
2430
|
+
unsatisfied: number[];
|
|
2431
|
+
}
|
|
2432
|
+
/**
|
|
2433
|
+
* Move `points` the least that makes `constraints` hold. Anchors named by a
|
|
2434
|
+
* `fixed` constraint go back to `reference` and stay there; `held` anchors
|
|
2435
|
+
* and `heldHandles` stay where they are when the rest can satisfy the
|
|
2436
|
+
* constraints, and give way as little as they must when not. When the
|
|
2437
|
+
* constraints cannot all hold, `converged` is false and `unsatisfied` names
|
|
2438
|
+
* the ones that do not.
|
|
2439
|
+
*/
|
|
2440
|
+
declare function solveConstraints(points: readonly ConstraintPoint[], constraints: readonly PathConstraint[], opts?: SolveConstraintsOptions): SolveConstraintsResult;
|
|
2441
|
+
|
|
2442
|
+
/**
|
|
2443
|
+
* Whether constraints hold for a set of points, and whether a solve made them
|
|
2444
|
+
* hold only by collapsing what they measure.
|
|
2445
|
+
*/
|
|
2446
|
+
|
|
2447
|
+
/** The residual, in the path's units, under which a constraint counts as holding. */
|
|
2448
|
+
declare const CONSTRAINT_TOLERANCE = 0.001;
|
|
2449
|
+
/** Options for {@link unsatisfiedConstraints}. */
|
|
2450
|
+
interface UnsatisfiedConstraintsOptions {
|
|
2451
|
+
axisAngle?: number;
|
|
2452
|
+
/** A frame per constraint, by index, over `axisAngle`. */
|
|
2453
|
+
axisAngles?: readonly (number | undefined)[];
|
|
2454
|
+
/** Where a `fixed` anchor belongs. Absent, a `fixed` constraint always holds. */
|
|
2455
|
+
reference?: readonly (ConstraintPoint | undefined)[];
|
|
2456
|
+
/** Default {@link CONSTRAINT_TOLERANCE}. */
|
|
2457
|
+
tolerance?: number;
|
|
2458
|
+
}
|
|
2459
|
+
/**
|
|
2460
|
+
* Indices of the constraints that do not hold for `points`: a residual past
|
|
2461
|
+
* the tolerance, an anchor index the points do not have, or a tangent on an
|
|
2462
|
+
* anchor missing a handle.
|
|
2463
|
+
*/
|
|
2464
|
+
declare function unsatisfiedConstraints(points: readonly ConstraintPoint[], constraints: readonly PathConstraint[], opts?: UnsatisfiedConstraintsOptions): number[];
|
|
2465
|
+
|
|
2466
|
+
/**
|
|
2467
|
+
* Constraints on a `PolygonPath`: solving them over its anchors, and carrying
|
|
2468
|
+
* them through an edit that renumbers the anchors.
|
|
2469
|
+
*/
|
|
2470
|
+
|
|
2471
|
+
/** Every anchor of `path`, by flat index, with the handles it has. */
|
|
2472
|
+
declare function pathAnchorPoints(path: PolygonPath): ConstraintPoint[];
|
|
2473
|
+
/** {@link solveConstraints} over `path`'s anchors, and `path` with them moved. */
|
|
2474
|
+
interface SolvePathConstraintsResult extends SolveConstraintsResult {
|
|
2475
|
+
/** `path` with each anchor moved where the solve put it, its handles moved with it; `path` itself when none moved. */
|
|
2476
|
+
path: PolygonPath;
|
|
2477
|
+
}
|
|
2478
|
+
/**
|
|
2479
|
+
* Solve `constraints` over the anchors of `path` and write the result back,
|
|
2480
|
+
* carrying each moved anchor's handles with it so its curves keep their
|
|
2481
|
+
* shape, except where a `tangent` turned them.
|
|
2482
|
+
*/
|
|
2483
|
+
declare function solvePathConstraints(path: PolygonPath, constraints: readonly PathConstraint[], opts?: SolveConstraintsOptions): SolvePathConstraintsResult;
|
|
2484
|
+
/**
|
|
2485
|
+
* `path` with its anchors and handles where `to` puts them, given `from`,
|
|
2486
|
+
* where they are now; `path` itself when nothing moved.
|
|
2487
|
+
*/
|
|
2488
|
+
declare function withAnchorPoints(path: PolygonPath, from: readonly ConstraintPoint[], to: readonly ConstraintPoint[]): PolygonPath;
|
|
2489
|
+
/**
|
|
2490
|
+
* For each anchor of `after`, the anchor of `before` it is: the one whose
|
|
2491
|
+
* point `origins` says it was copied from. An anchor the edit made has none.
|
|
2492
|
+
* `origins` is what `editAnchorSetTracked` answered for the edit.
|
|
2493
|
+
*/
|
|
2494
|
+
declare function anchorsBefore(before: PolygonPath, after: PolygonPath, origins: readonly (PointOrigin | null)[]): (number | undefined)[];
|
|
2495
|
+
/**
|
|
2496
|
+
* `constraints` renumbered for the anchors of a path after an edit, given
|
|
2497
|
+
* `wasAnchor` — for each new anchor, the old one it is, as
|
|
2498
|
+
* {@link anchorsBefore} answers. A constraint naming an anchor the edit
|
|
2499
|
+
* removed is dropped; `from` holds each kept one's index in `constraints`.
|
|
2500
|
+
*/
|
|
2501
|
+
declare function remapConstraints(constraints: readonly PathConstraint[], wasAnchor: readonly (number | undefined)[]): {
|
|
2502
|
+
constraints: PathConstraint[];
|
|
2503
|
+
from: number[];
|
|
2504
|
+
};
|
|
2505
|
+
/**
|
|
2506
|
+
* The segment of `path` joining anchors `a` and `b`, as the pair in the order
|
|
2507
|
+
* the path runs it, or null when no segment joins them.
|
|
2508
|
+
*/
|
|
2509
|
+
declare function segmentBetween(path: PolygonPath, a: number, b: number): AnchorPair | null;
|
|
2510
|
+
|
|
2511
|
+
/**
|
|
2512
|
+
* Finishing an edit of constrained paths so their constraints hold: one path
|
|
2513
|
+
* on its own, or several solved together when links — constraints naming
|
|
2514
|
+
* anchors of more than one — tie them.
|
|
2515
|
+
*/
|
|
2516
|
+
|
|
2517
|
+
/** Options for {@link constrainPathEdit}. */
|
|
2518
|
+
interface ConstrainPathEditOptions {
|
|
2519
|
+
/**
|
|
2520
|
+
* Where each point of the edited path came from, as `editAnchorSetTracked`
|
|
2521
|
+
* answers. Absent, the edit is taken to keep every anchor's number, and one
|
|
2522
|
+
* that changes the anchor count drops every constraint.
|
|
2523
|
+
*/
|
|
2524
|
+
origins?: readonly (PointOrigin | null)[];
|
|
2525
|
+
/** See {@link SolveConstraintsOptions.axisAngle}. */
|
|
2526
|
+
axisAngle?: number;
|
|
2527
|
+
}
|
|
2528
|
+
/** What {@link constrainPathEdit} answers. */
|
|
2529
|
+
interface ConstrainedPathEdit {
|
|
2530
|
+
/** The edited path with the constraints holding again. */
|
|
2531
|
+
path: PolygonPath;
|
|
2532
|
+
/** The constraints renumbered for `path`'s anchors. */
|
|
2533
|
+
constraints: PathConstraint[];
|
|
2534
|
+
/** Whether every constraint that held before the edit holds after it. */
|
|
2535
|
+
converged: boolean;
|
|
2536
|
+
/** Indices into `constraints` of the ones that do not hold, including any that already did not before the edit. */
|
|
2537
|
+
unsatisfied: number[];
|
|
2538
|
+
}
|
|
2539
|
+
/** One path of a {@link constrainPathsEdit}: its edit, and its own constraints. */
|
|
2540
|
+
interface PathsEditItem extends ConstrainPathEditOptions {
|
|
2541
|
+
before: PolygonPath;
|
|
2542
|
+
/** `before` as the edit left it; `before` itself for a path the edit did not touch. */
|
|
2543
|
+
after: PolygonPath;
|
|
2544
|
+
constraints: readonly PathConstraint[];
|
|
2545
|
+
}
|
|
1220
2546
|
/**
|
|
1221
|
-
*
|
|
1222
|
-
*
|
|
1223
|
-
*
|
|
1224
|
-
*
|
|
2547
|
+
* A constraint across paths. Its anchors are numbered over the anchors of
|
|
2548
|
+
* `paths` — indices into the items — one after another in that order: with
|
|
2549
|
+
* `paths: [2, 0]` and a 5-anchor item 2, anchor 6 is item 0's anchor 1. Its
|
|
2550
|
+
* `horizontal` and `vertical` read the world's axes.
|
|
2551
|
+
*/
|
|
2552
|
+
interface PathLink {
|
|
2553
|
+
constraint: PathConstraint;
|
|
2554
|
+
paths: readonly number[];
|
|
2555
|
+
}
|
|
2556
|
+
/** What {@link constrainPathsEdit} answers. */
|
|
2557
|
+
interface ConstrainedPathsEdit {
|
|
2558
|
+
/** Each item, in order: its path with the constraints holding, and its own constraints renumbered for it. */
|
|
2559
|
+
items: {
|
|
2560
|
+
path: PolygonPath;
|
|
2561
|
+
constraints: PathConstraint[];
|
|
2562
|
+
unsatisfied: number[];
|
|
2563
|
+
}[];
|
|
2564
|
+
/** Each link renumbered over its paths' anchors after the edit; null when the edit removed an anchor it names. */
|
|
2565
|
+
links: {
|
|
2566
|
+
constraint: PathConstraint | null;
|
|
2567
|
+
satisfied: boolean;
|
|
2568
|
+
}[];
|
|
2569
|
+
/** Whether every constraint that held before the edit holds after it. */
|
|
2570
|
+
converged: boolean;
|
|
2571
|
+
}
|
|
2572
|
+
/**
|
|
2573
|
+
* An edit of constrained paths, finished so their constraints and the links
|
|
2574
|
+
* between them hold, as one solve over every anchor: the anchors and handles
|
|
2575
|
+
* the edit moved are held, and so are the anchors of a path it left alone
|
|
2576
|
+
* (`after === before`), except one held on a segment; `fixed` anchors go
|
|
2577
|
+
* back to where they were, and the rest move the least they must. A constraint
|
|
2578
|
+
* that did not hold before the edit is left out of the solve, and reported.
|
|
2579
|
+
* Each item's own `horizontal` and `vertical` read its own `axisAngle`.
|
|
2580
|
+
*/
|
|
2581
|
+
declare function constrainPathsEdit(items: readonly PathsEditItem[], links?: readonly PathLink[]): ConstrainedPathsEdit;
|
|
2582
|
+
/**
|
|
2583
|
+
* An edit of a constrained path, `before` → `after`, finished so its
|
|
2584
|
+
* constraints hold: the anchors and handles the edit moved are held, `fixed`
|
|
2585
|
+
* anchors go back to where they were, and the rest move the least they must.
|
|
2586
|
+
* A constraint that did not hold before the edit conflicts with the others
|
|
2587
|
+
* and is left out of the solve rather than allowed to pull them out of true;
|
|
2588
|
+
* `unsatisfied` reports it.
|
|
2589
|
+
*/
|
|
2590
|
+
declare function constrainPathEdit(before: PolygonPath, after: PolygonPath, constraints: readonly PathConstraint[], opts?: ConstrainPathEditOptions): ConstrainedPathEdit;
|
|
2591
|
+
|
|
2592
|
+
/**
|
|
2593
|
+
* Which constraints conflict: not merely the ones a failed solve leaves
|
|
2594
|
+
* unsatisfied, but a smallest set that cannot all hold together, found by a
|
|
2595
|
+
* deletion filter — drop each member in turn, and keep it out when what is
|
|
2596
|
+
* left still fails. Every member of the answer is needed for the conflict.
|
|
2597
|
+
*/
|
|
2598
|
+
|
|
2599
|
+
/** Options for {@link conflictingConstraints}. */
|
|
2600
|
+
interface ConflictingConstraintsOptions {
|
|
2601
|
+
/** Radians the frame `horizontal` and `vertical` read is turned from the world's axes. Default 0. */
|
|
2602
|
+
axisAngle?: number;
|
|
2603
|
+
/** A frame per constraint, by index, over `axisAngle`. */
|
|
2604
|
+
axisAngles?: readonly (number | undefined)[];
|
|
2605
|
+
/** Where each anchor belongs for a `fixed` constraint. Default: where it is now. */
|
|
2606
|
+
reference?: readonly (ConstraintPoint | undefined)[];
|
|
2607
|
+
}
|
|
2608
|
+
/**
|
|
2609
|
+
* The constraints of `constraints` that conflict over `points`: for every
|
|
2610
|
+
* group of them sharing anchors that cannot all hold, a smallest subset that
|
|
2611
|
+
* still cannot — each member needed, the later ones in the list kept in
|
|
2612
|
+
* preference to the earlier — and every constraint that cannot apply at all.
|
|
2613
|
+
* Sorted; empty when every constraint can hold at once.
|
|
2614
|
+
*/
|
|
2615
|
+
declare function conflictingConstraints(points: readonly ConstraintPoint[], constraints: readonly PathConstraint[], opts?: ConflictingConstraintsOptions): number[];
|
|
2616
|
+
|
|
2617
|
+
/**
|
|
2618
|
+
* Edits to a path's order rather than its shape: where a subpath starts, and
|
|
2619
|
+
* which way it runs. Each mutates an `AnchorSet` in place, like the edits in
|
|
2620
|
+
* `anchorEdits`, and moves anchors whole, so anything an anchor carries beside
|
|
2621
|
+
* its point and handles travels with it.
|
|
2622
|
+
*/
|
|
2623
|
+
|
|
2624
|
+
/**
|
|
2625
|
+
* Make the anchor at `flatIndex` its subpath's first. A closed subpath turns
|
|
2626
|
+
* so it starts there, keeping its direction. An open subpath can only start
|
|
2627
|
+
* at one of its ends: its last anchor makes it run the other way, and an
|
|
2628
|
+
* interior anchor changes nothing. Returns whether the set changed.
|
|
2629
|
+
*/
|
|
2630
|
+
declare function setSubpathStart(set: AnchorSet, flatIndex: number): boolean;
|
|
2631
|
+
/**
|
|
2632
|
+
* Run each subpath in `subs` the other way, every one when `subs` is absent.
|
|
2633
|
+
* The shape is unchanged: each anchor's handles trade places. A closed
|
|
2634
|
+
* subpath keeps its start anchor, as `reversePath` does; an open one starts
|
|
2635
|
+
* where it used to end. Returns whether any subpath had a segment to turn.
|
|
2636
|
+
*/
|
|
2637
|
+
declare function reverseSubpaths(set: AnchorSet, subs?: Iterable<number>): boolean;
|
|
2638
|
+
/**
|
|
2639
|
+
* Where each anchor at `flatIndexes` sits once `reverseSubpaths(set, subs)`
|
|
2640
|
+
* has run: an anchor keeps its point, so a selection can follow it. Indexes
|
|
2641
|
+
* outside the set are dropped.
|
|
2642
|
+
*/
|
|
2643
|
+
declare function flatIndexesAfterReverse(set: AnchorSet, flatIndexes: Iterable<number>, subs?: Iterable<number>): number[];
|
|
2644
|
+
/** The subpaths holding the anchors at `flatIndexes`, each once, in order. */
|
|
2645
|
+
declare function subpathsOfAnchors(set: AnchorSet, flatIndexes: Iterable<number>): number[];
|
|
2646
|
+
/** A mark showing which way a path runs: a point on it and the unit vector of its heading there. */
|
|
2647
|
+
interface DirectionMark {
|
|
2648
|
+
x: number;
|
|
2649
|
+
y: number;
|
|
2650
|
+
dx: number;
|
|
2651
|
+
dy: number;
|
|
2652
|
+
/** The subpath the mark is on. */
|
|
2653
|
+
sub: number;
|
|
2654
|
+
}
|
|
2655
|
+
/**
|
|
2656
|
+
* One {@link DirectionMark} at the middle of every segment of `set`, closing
|
|
2657
|
+
* segments included, in walk order. A segment with no length gets none.
|
|
2658
|
+
*/
|
|
2659
|
+
declare function directionMarks(set: AnchorSet): DirectionMark[];
|
|
2660
|
+
|
|
2661
|
+
/**
|
|
2662
|
+
* Straight and curved segments, converted in place. A segment runs from one
|
|
2663
|
+
* anchor to the next, the closing segment of a closed subpath included, and is
|
|
2664
|
+
* named `(sub, segIdx)` as `segmentAt` reports it.
|
|
2665
|
+
*/
|
|
2666
|
+
|
|
2667
|
+
/** A segment of an `AnchorSet`: `segIdx === sub.length - 1` is a closed
|
|
2668
|
+
* subpath's closing segment. */
|
|
2669
|
+
interface SegmentRef {
|
|
2670
|
+
sub: number;
|
|
2671
|
+
segIdx: number;
|
|
2672
|
+
}
|
|
2673
|
+
/** What a segment is made: a line, a curve, or the other of what it is. */
|
|
2674
|
+
type SegmentType = 'line' | 'curve';
|
|
2675
|
+
/**
|
|
2676
|
+
* The segments both of whose ends are among `flatIndexes`, in walk order.
|
|
2677
|
+
* Two adjacent selected anchors select the segment between them; a closed
|
|
2678
|
+
* subpath with every anchor selected has all its segments.
|
|
2679
|
+
*/
|
|
2680
|
+
declare function segmentsBetweenAnchors(set: AnchorSet, flatIndexes: Iterable<number>): SegmentRef[];
|
|
2681
|
+
/** Whether segment `seg` is straight, or null when it does not exist. */
|
|
2682
|
+
declare function isSegmentStraight(set: AnchorSet, seg: SegmentRef): boolean | null;
|
|
2683
|
+
/**
|
|
2684
|
+
* Make each segment in `segs` straight or curved without moving its anchors.
|
|
2685
|
+
* A line becomes a curve with its handles a third of the way in from each
|
|
2686
|
+
* end, which draws the same line; a curve becomes a line by dropping the two
|
|
2687
|
+
* handles that shape it, leaving the handles of the segments beside it alone.
|
|
2688
|
+
* With no `to`, every segment turns curved when any of them is straight, and
|
|
2689
|
+
* straight when all are curved: one press flips the lot.
|
|
1225
2690
|
*
|
|
1226
|
-
*
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
2691
|
+
* Returns whether any segment changed.
|
|
2692
|
+
*/
|
|
2693
|
+
declare function convertSegments(set: AnchorSet, segs: readonly SegmentRef[], to?: SegmentType): boolean;
|
|
2694
|
+
|
|
2695
|
+
/**
|
|
2696
|
+
* Anchors as numbers a person types: the position of the selected anchors,
|
|
2697
|
+
* and for a lone anchor its handles' positions, angles and lengths. Reading
|
|
2698
|
+
* answers what a field shows; writing sets a value on every selected anchor,
|
|
2699
|
+
* or offsets each by an amount.
|
|
2700
|
+
*/
|
|
2701
|
+
|
|
2702
|
+
/** One number of an anchor. Handle angles are degrees counterclockwise from
|
|
2703
|
+
* +x as drawn, where y grows downward; lengths and positions are in the
|
|
2704
|
+
* set's own units. */
|
|
2705
|
+
type AnchorField = 'x' | 'y' | 'inX' | 'inY' | 'inAngle' | 'inLength' | 'outX' | 'outY' | 'outAngle' | 'outLength';
|
|
2706
|
+
/** Every {@link AnchorField}, in the order a panel lists them. */
|
|
2707
|
+
declare const ANCHOR_FIELDS: readonly AnchorField[];
|
|
2708
|
+
/** What a typed field asks for: a value for every anchor, or an amount added to each one's own. */
|
|
2709
|
+
type NumberEntry = {
|
|
2710
|
+
to: number;
|
|
2711
|
+
} | {
|
|
2712
|
+
by: number;
|
|
2713
|
+
};
|
|
2714
|
+
/**
|
|
2715
|
+
* What each field shows for the anchors at `flatIndexes`: a number where
|
|
2716
|
+
* they agree, `null` where they differ, and no key for a field that does not
|
|
2717
|
+
* apply. Position applies to any selection; handle fields only to a single
|
|
2718
|
+
* anchor, and only for a handle it has.
|
|
1230
2719
|
*/
|
|
1231
|
-
|
|
2720
|
+
type AnchorFieldValues = Partial<Record<AnchorField, number | null>>;
|
|
2721
|
+
/** The fields for the anchors at `flatIndexes`; `{}` when none of them exists. */
|
|
2722
|
+
declare function readAnchorFields(set: AnchorSet, flatIndexes: Iterable<number>): AnchorFieldValues;
|
|
1232
2723
|
/**
|
|
1233
|
-
*
|
|
1234
|
-
*
|
|
1235
|
-
*
|
|
1236
|
-
*
|
|
2724
|
+
* Write `entry` into `field` of every anchor at `flatIndexes`. Moving an
|
|
2725
|
+
* anchor carries its handles. A handle field moves the handle as a drag to
|
|
2726
|
+
* the typed spot would (`moveHandleTo`): on a smooth anchor the opposite
|
|
2727
|
+
* handle mirrors it, taking its turn and its length, and on a corner it stays
|
|
2728
|
+
* where it is. An anchor without that handle is skipped. An angle keeps the
|
|
2729
|
+
* handle's length, and a length keeps its angle. Returns whether anything
|
|
2730
|
+
* moved.
|
|
1237
2731
|
*/
|
|
1238
|
-
declare function
|
|
1239
|
-
/** Flat indices of every anchor whose on-curve point falls inside `rect`. */
|
|
1240
|
-
declare function anchorsInRect(set: AnchorSet, rect: AnchorRect): number[];
|
|
2732
|
+
declare function writeAnchorField(set: AnchorSet, flatIndexes: Iterable<number>, field: AnchorField, entry: NumberEntry): boolean;
|
|
1241
2733
|
|
|
1242
2734
|
/**
|
|
1243
2735
|
* Anchor lookup across several paths, measured on screen: which existing
|
|
@@ -1363,4 +2855,4 @@ declare function reviveTypedArrays(value: unknown): unknown;
|
|
|
1363
2855
|
/** `tagTypedArrays` as a `JSON.stringify` replacer. */
|
|
1364
2856
|
declare function typedArrayReplacer(_key: string, value: unknown): unknown;
|
|
1365
2857
|
|
|
1366
|
-
export { type
|
|
2858
|
+
export { ANCHOR_FIELDS, type Affine, type AnchorField, type AnchorFieldValues, type AnchorPair, type AnchorPathMeasure, AnchorSet, type AnchorSubpathMeasure, type AnchorSymmetry, type AverageAxis, type BendAlongPathOptions, type BendGrip, type BezierEasing, type BlendPathsOptions, type Box, CONSTRAINT_TOLERANCE, CORNER_RESTORE_TOLERANCE, type ConflictingConstraintsOptions, type ConstrainPathEditOptions, type ConstrainedPathEdit, type ConstrainedPathsEdit, type ConstraintPoint, type CornerCut, type CornerFrame, CornerPiece, CornerSpec, type CornerTrace, type CubicContour, type CubicCoords, type CubicSegment, type CurveNearest, DEFAULT_FLATTEN_TOLERANCE, type DirectionMark, EASINGS, EPS, type EasingFn, type EasingName, type EasingSpec, type ExtendToMeetOptions, type FramedBox, type GlMat3, type GrowRegionOptions, type HandleBalance, type HandleRef, type JoinOptions, type LengthenMode, type LineCoords, type MeasureAnchorPathOptions, type MeasurePathOptions, type NumberEntry, type NumberTypedArray, type OpenPathEnd, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_SNAP_KINDS, PATH_Z, Path, type PathAnchorHit, type PathAwayFromAnchors, type PathBlend, PathBuilder, type PathCommandCode, type PathCommandName, type PathConstraint, type PathConstraintKind, type PathCrossing, type PathEndFrame, PathFillRule, type PathInWorldPose, type PathLink, type PathMeasure, type PathNearest, PathOpenFill, type PathSegment, type PathSnapHit, type PathSnapIndex, type PathSnapKind, type PathSnapQuery, type PathSnapTarget, type PathStation, type PathStop, type PathsEditItem, PenAnchor, type PlaceRectOptions, type PlacedRect, type Placement, type PlacementAlign, type PlacementSide, Point, type PointAlongPathOptions, type PointInPathOptions, type PointOrigin, type PolygonIntersectsPathOptions, PolygonPath, type PoseLinear, type PoseRotation, type QuadraticCoords, type Rect, RectPath, type RepeatAlongPathOptions, type RepeatStation, type ResamplePathOptions, type ResolvedCorners, SPRING_PRESETS, Scale2, type SegmentCrossing, type SegmentMeasure, type SegmentRef, type SegmentType, type SimplifyPathOptions, type SmudgePathOptions, type SoftFalloff, type SolveConstraintsOptions, type SolveConstraintsResult, type SolvePathConstraintsResult, type SpiroContour, SpiroKind, type SpiroPath, SpiroPoint, type SpiroToPathOptions, type SpringPreset, type SpringPresetName, type StaticPathSnapKind, type StrokeHitTestOptions, type SubpathEnd, TYPED_ARRAY_CONSTRUCTORS, type TaggedTypedArray, type TrimPathOptions, type TrimResult, type TypedArrayTag, type UnsatisfiedConstraintsOptions, type View, ZOOM_FLOOR, addExtremaAnchors, anchorOriginsOf, anchorSymmetries, anchorSymmetry, anchorsBefore, anchorsUnderBrush, anchorsWhere, applyToPoint, approxEq, asPolygonPath, averageAnchorsAt, balanceFactorToward, bendAlongPath, bendSegment, blendPaths, boundsOfCoords, boundsOfPath, boxContainsBox, boxContainsPoint, boxToBox, circlePath, clamp, clampRectWithin, closestOpenEnds, composePath, conflictingConstraints, constrainPathEdit, constrainPathsEdit, constraintAnchors, constraintApplies, constraintFits, convertSegments, cornerAnchors, cornerCuts, cornerFrameAt, cornerFrames, cornerTraces, createPathSnapIndex, cross, cubicAxisExtremaTs, cubicBezierEasing, cubicBounds, cubicContoursToPath, cubicEvalAt, decomposePath, defaultOpenFill, directionMarks, dot, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorSetTracked, elevateQuadraticToCubic, ellipsePath, equalizeSegmentHandles, everyNthAnchor, extendToMeet, fillsOpenSubpaths, findPathSnap, findPathSnaps, fitAffine, fitCubicThroughDeletion, fitCubicWithTangents, flatIndexesAfterReverse, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, forEachSegment, growAnchorSelection, growRegion, handleAlongItsAngle, handleAtItsLength, handleBalances, harmonizeAnchors, hasOpenSubpath, identity$1 as identity, intersectSegments, invert$1 as invert, invertAnchorSelection, isSegmentStraight, joinAnchorsAt, joinSubpathEnds, keepCorners, len2, lengthToward, lengthenOpenEnd, lengthenPathEnd, linePath, linear, makeHandlesSymmetric, mapConstraintAnchors, mat3, meanScale, measureAnchorPath, measurePath, moveHandleSymmetric, multiply$1 as multiply, nearestOnCubic, nearestOnLine, nearestOnPath, nearestOnQuadratic, nearestPathAnchor, normalizeZoom, offsetCornerTraces, openEndAt, openEndRay, openPathEnds, pathAnchorPoints, pathAwayFromAnchors, pathCommandCoordCount, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathCrossings, pathDistanceToPoint, pathEndAnchorIndex, pathEndFrame, pathFromD, pathInPoseFrame, pathInWorld, pathIntersectsPolygon, pathIntersectsRect, pathSegments, pathSignedArea, pathThroughPoseFrame, pathToCubicContours, placeRect, pointAlongPath, pointInPath, pointInPolygon, pointSegmentDist2, polygonContainsPath, polygonFromPoints, polygonIntersectsPath, polylineFromPoints, portControls, portCurvePoints, poseFrameInverseOf, poseFrameOf, poseLinearOf, poseRotationOf, prepareBlend, quadraticEvalAt, readAnchorFields, rectMarkerPath, rectPath, rectToContour, regularPolygonPath, remapAnchorValues, remapConstraints, remapPerAnchor, remapPointValues, repeatAlongPath, resamplePath, resolveCorners, resolveCornersWithSources, resolveEasing, restoreCorners, retractHandles, reverseAnchors, reversePath, reverseSubpaths, reviveTypedArrays, rotate, rotateAboutPoint, rotatePathAround, roundRectPath, scale, scalePathToBounds, scaleSegmentHandles, schneiderFit, segmentBetween, segmentExtremaTs, segmentsBetweenAnchors, segmentsCross, setDefaultOpenFill, setSubpathStart, shrinkAnchorSelection, sign, simplifyAnchorsAt, simplifyPath, simplifySpan, simplifySubpath, smoothAnchors, smudgePath, softFalloff, softSelectionBand, softSelectionWeights, solveConstraints, solvePathConstraints, spiroContoursFromControl, spiroContoursOf, spiroControlPath, spiroToPath, splitByClosure, splitCubicAt, splitLineAt, splitQuadraticAt, splitSubpaths, squarePath, starPath, stationsAlongPath, strokeHitTest, sub, subpathEndAt, subpathsOfAnchors, tagTypedArray, tagTypedArrays, transformCoords, transformPath, translate, translateAnchorsSymmetric, translatePath, trimPathAt, typedArrayReplacer, unionBoundsPath, unionBox, unsatisfiedConstraints, untagTypedArray, viewToMat3, withAnchorPoints, worldEditToStorage, writeAnchorField };
|