modern-path2d 1.6.0 → 1.7.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 +55 -0
- package/dist/index.cjs +478 -57
- package/dist/index.d.cts +185 -4
- package/dist/index.d.mts +185 -4
- package/dist/index.d.ts +185 -4
- package/dist/index.js +2 -2
- package/dist/index.mjs +475 -58
- package/package.json +2 -1
package/dist/index.d.cts
CHANGED
|
@@ -298,7 +298,12 @@ declare function getDirectedArea(vertices: number[]): number;
|
|
|
298
298
|
declare const PI: number;
|
|
299
299
|
declare const PI_2: number;
|
|
300
300
|
declare function toKebabCase(str: string): string;
|
|
301
|
-
|
|
301
|
+
/**
|
|
302
|
+
* Intersection of line p1→p2 with line q1→q2, or `null` when the segments are parallel
|
|
303
|
+
* (`crossRS === 0`) or the intersection lies too far off p1→p2 (`|t| > 1`). Callers must
|
|
304
|
+
* handle `null` (e.g. `Path2D.bold` skips the join when there is no usable point).
|
|
305
|
+
*/
|
|
306
|
+
declare function getIntersectionPoint(p1: Vector2, p2: Vector2, q1: Vector2, q2: Vector2): Vector2 | null;
|
|
302
307
|
|
|
303
308
|
interface NonzeroFillRuleResult {
|
|
304
309
|
index: number;
|
|
@@ -308,6 +313,45 @@ interface NonzeroFillRuleResult {
|
|
|
308
313
|
}
|
|
309
314
|
declare function nonzeroFillRule(paths: number[][]): NonzeroFillRuleResult[];
|
|
310
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Test whether a point lies inside a single polygon ring.
|
|
318
|
+
*
|
|
319
|
+
* `vertices` is a flat `[x0, y0, x1, y1, ...]` array and is treated as implicitly closed
|
|
320
|
+
* (the last vertex connects back to the first). A ring with fewer than 3 points has no
|
|
321
|
+
* area and always returns `false`.
|
|
322
|
+
*
|
|
323
|
+
* @param point The point to test.
|
|
324
|
+
* @param vertices Flat vertex array of the ring.
|
|
325
|
+
* @param fillRule `'nonzero'` (default, matches SVG/Canvas) or `'evenodd'`.
|
|
326
|
+
*/
|
|
327
|
+
declare function pointInPolygon(point: Vector2Like, vertices: number[], fillRule?: FillRule): boolean;
|
|
328
|
+
/**
|
|
329
|
+
* Test whether a point lies inside a shape composed of multiple rings (sub-paths).
|
|
330
|
+
*
|
|
331
|
+
* This is the multi-ring counterpart of {@link pointInPolygon} and is what donut /
|
|
332
|
+
* hollow shapes need: every ring is evaluated together so holes are honored.
|
|
333
|
+
* - `'nonzero'`: sum the signed winding numbers of all rings, inside if the total ≠ 0.
|
|
334
|
+
* - `'evenodd'`: sum the ray-crossing counts of all rings, inside if the total is odd.
|
|
335
|
+
*
|
|
336
|
+
* @param point The point to test.
|
|
337
|
+
* @param polygons Array of flat vertex arrays, one per ring.
|
|
338
|
+
* @param fillRule `'nonzero'` (default) or `'evenodd'`.
|
|
339
|
+
*/
|
|
340
|
+
declare function pointInPolygons(point: Vector2Like, polygons: number[][], fillRule?: FillRule): boolean;
|
|
341
|
+
/**
|
|
342
|
+
* Shortest distance from a point to a single line segment a→b.
|
|
343
|
+
*/
|
|
344
|
+
declare function pointToSegmentDistance(point: Vector2Like, a: Vector2Like, b: Vector2Like): number;
|
|
345
|
+
/**
|
|
346
|
+
* Shortest distance from a point to a polyline.
|
|
347
|
+
*
|
|
348
|
+
* @param point The point to test.
|
|
349
|
+
* @param vertices Flat `[x0, y0, x1, y1, ...]` array of the polyline.
|
|
350
|
+
* @param closed When `true`, also considers the closing edge from the last vertex back
|
|
351
|
+
* to the first (use for closed paths, e.g. `z`/`Z` or `CurvePath.autoClose`).
|
|
352
|
+
*/
|
|
353
|
+
declare function pointToPolylineDistance(point: Vector2Like, vertices: number[], closed?: boolean): number;
|
|
354
|
+
|
|
311
355
|
declare function quadraticBezier(t: number, p0: number, p1: number, p2: number): number;
|
|
312
356
|
|
|
313
357
|
type LineCap = 'butt' | 'round' | 'square';
|
|
@@ -333,10 +377,39 @@ interface LineStyle {
|
|
|
333
377
|
}
|
|
334
378
|
declare function strokeTriangulate(points: number[], options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
335
379
|
|
|
380
|
+
interface IsPointInFillOptions {
|
|
381
|
+
fillRule?: FillRule;
|
|
382
|
+
}
|
|
383
|
+
interface IsPointInStrokeOptions {
|
|
384
|
+
strokeWidth?: number;
|
|
385
|
+
tolerance?: number;
|
|
386
|
+
closed?: boolean;
|
|
387
|
+
}
|
|
336
388
|
declare abstract class Curve {
|
|
337
389
|
arcLengthDivision: number;
|
|
338
390
|
protected _lengths: number[];
|
|
391
|
+
protected _adaptiveCache?: number[];
|
|
392
|
+
/**
|
|
393
|
+
* Parent composite, set lazily when a composite caches its children. Lets
|
|
394
|
+
* {@link invalidate} propagate up so an ancestor's caches refresh too.
|
|
395
|
+
*/
|
|
396
|
+
_owner?: Curve;
|
|
397
|
+
protected _invalidating: boolean;
|
|
339
398
|
abstract getPoint(t: number, output?: Vector2): Vector2;
|
|
399
|
+
/**
|
|
400
|
+
* Drop cached arc lengths and the cached sampled outline used by hit testing, then
|
|
401
|
+
* bubble up to {@link _owner}. Called automatically by {@link applyTransform} and the
|
|
402
|
+
* `Path2D` mutators; call it manually after mutating control-point coordinates in place —
|
|
403
|
+
* the caches cannot observe such mutations.
|
|
404
|
+
*/
|
|
405
|
+
invalidate(): this;
|
|
406
|
+
/** Clears this curve's own caches. Composites also clear their children (see override). */
|
|
407
|
+
protected _invalidateSelf(): void;
|
|
408
|
+
/**
|
|
409
|
+
* Sampled outline cached for repeated hit tests (read-only — do not mutate the result).
|
|
410
|
+
* Invalidated by {@link invalidate}.
|
|
411
|
+
*/
|
|
412
|
+
protected _getCachedAdaptiveVertices(): number[];
|
|
340
413
|
getPointAt(u: number, output?: Vector2): Vector2;
|
|
341
414
|
isClockwise(): boolean;
|
|
342
415
|
getControlPointRefs(): Vector2[];
|
|
@@ -363,6 +436,32 @@ declare abstract class Curve {
|
|
|
363
436
|
max: Vector2;
|
|
364
437
|
};
|
|
365
438
|
getBoundingBox(): BoundingBox;
|
|
439
|
+
/**
|
|
440
|
+
* Test whether a point lies inside the area enclosed by this curve.
|
|
441
|
+
*
|
|
442
|
+
* The curve is sampled via {@link getAdaptiveVertices} into a single implicitly closed
|
|
443
|
+
* ring. This is purely geometric (it ignores any `fill`/`stroke` style), mirroring
|
|
444
|
+
* `CanvasRenderingContext2D.isPointInPath`.
|
|
445
|
+
*
|
|
446
|
+
* Composites that hold multiple sub-paths (e.g. {@link Path2D}) override this so holes
|
|
447
|
+
* are honored — a single `Curve` is always one ring.
|
|
448
|
+
*/
|
|
449
|
+
isPointInFill(point: Vector2Like, options?: IsPointInFillOptions): boolean;
|
|
450
|
+
/**
|
|
451
|
+
* Test whether a point lies on this curve's stroke, i.e. within `strokeWidth / 2 + tolerance`
|
|
452
|
+
* of the sampled outline. The point must be in the same coordinate space as the curve.
|
|
453
|
+
*
|
|
454
|
+
* Options: `strokeWidth` (path units, default `1`), `tolerance` (extra hit slack in path
|
|
455
|
+
* units, default `0` — useful for thin strokes; no coordinate scaling is assumed, so convert
|
|
456
|
+
* pixel tolerance to path units upstream if your path is normalized), and `closed` (whether
|
|
457
|
+
* to include the closing edge from the last vertex back to the first).
|
|
458
|
+
*/
|
|
459
|
+
isPointInStroke(point: Vector2Like, options?: IsPointInStrokeOptions): boolean;
|
|
460
|
+
/**
|
|
461
|
+
* Concise PathKit-style fill containment test: `contains(x, y)` is shorthand for
|
|
462
|
+
* {@link isPointInFill} with a `{ x, y }` point.
|
|
463
|
+
*/
|
|
464
|
+
contains(x: number, y: number, options?: IsPointInFillOptions): boolean;
|
|
366
465
|
getFillVertices(_options?: FillTriangulateOptions): number[];
|
|
367
466
|
fillTriangulate(options?: FillTriangulateOptions): FillTriangulatedResult;
|
|
368
467
|
strokeTriangulate(options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
@@ -397,6 +496,21 @@ declare class RoundCurve extends Curve {
|
|
|
397
496
|
isClockwise(): boolean;
|
|
398
497
|
protected _getDeltaAngle(): number;
|
|
399
498
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
499
|
+
/**
|
|
500
|
+
* Point on the ellipse at an absolute angle (mirrors {@link getPoint}'s parameterization,
|
|
501
|
+
* ignoring `_diff`).
|
|
502
|
+
*/
|
|
503
|
+
protected _pointAtAngle(angle: number, output: Vector2): Vector2;
|
|
504
|
+
/**
|
|
505
|
+
* Analytical bounds of the (elliptical) arc: the start/end points plus the per-axis
|
|
506
|
+
* extrema angles that fall within the swept interval. Matches {@link getPoint}, so it is
|
|
507
|
+
* exact for `ArcCurve`/`EllipseCurve`. The `_diff` offset (used only by the legacy
|
|
508
|
+
* `_getAdaptiveVerticesByCircle` path) is intentionally ignored here.
|
|
509
|
+
*/
|
|
510
|
+
getMinMax(min?: Vector2, max?: Vector2): {
|
|
511
|
+
min: Vector2;
|
|
512
|
+
max: Vector2;
|
|
513
|
+
};
|
|
400
514
|
toCommands(): Path2DCommand[];
|
|
401
515
|
drawTo(ctx: CanvasRenderingContext2D): this;
|
|
402
516
|
applyTransform(transform: Transform2D): this;
|
|
@@ -414,7 +528,10 @@ declare class ArcCurve extends RoundCurve {
|
|
|
414
528
|
|
|
415
529
|
declare class CompositeCurve<T extends Curve = Curve> extends Curve {
|
|
416
530
|
curves: T[];
|
|
531
|
+
protected _adaptiveCacheLen: number;
|
|
417
532
|
constructor(curves?: T[]);
|
|
533
|
+
protected _invalidateSelf(): void;
|
|
534
|
+
protected _getCachedAdaptiveVertices(): number[];
|
|
418
535
|
getFlatCurves(): Curve[];
|
|
419
536
|
addCurve(curve: T): this;
|
|
420
537
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
@@ -526,7 +643,12 @@ declare class RectangleCurve extends PolygonCurve {
|
|
|
526
643
|
copyFrom(source: RectangleCurve): this;
|
|
527
644
|
}
|
|
528
645
|
|
|
529
|
-
|
|
646
|
+
/**
|
|
647
|
+
* A rounded rectangle, modelled as a real composite of 4 `LineCurve` edges + 4 quarter
|
|
648
|
+
* `ArcCurve` corners (like {@link RectangleCurve}). `getPoint`/`getLength`/`getMinMax`/
|
|
649
|
+
* `toCommands` therefore describe the actual rounded outline — not a bare ellipse.
|
|
650
|
+
*/
|
|
651
|
+
declare class RoundRectangleCurve extends CompositeCurve {
|
|
530
652
|
x: number;
|
|
531
653
|
y: number;
|
|
532
654
|
width: number;
|
|
@@ -559,6 +681,11 @@ declare class CurvePath extends CompositeCurve {
|
|
|
559
681
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
560
682
|
getAdaptiveVertices(output?: number[]): number[];
|
|
561
683
|
getFillVertices(options?: FillTriangulateOptions): number[];
|
|
684
|
+
/**
|
|
685
|
+
* Same as {@link Curve.isPointInStroke}, but `closed` defaults to this sub-path's actual
|
|
686
|
+
* closed-ness: explicitly `autoClose`, or geometrically closed (first vertex === last).
|
|
687
|
+
*/
|
|
688
|
+
isPointInStroke(point: Vector2Like, options?: IsPointInStrokeOptions): boolean;
|
|
562
689
|
protected _setCurrentPoint(point: Vector2Like): this;
|
|
563
690
|
protected _connetLineTo(curve: Curve): this;
|
|
564
691
|
closePath(): this;
|
|
@@ -590,6 +717,8 @@ declare class CurvePath extends CompositeCurve {
|
|
|
590
717
|
*/
|
|
591
718
|
declare class Path2D<T = any> extends CompositeCurve<CurvePath> {
|
|
592
719
|
protected _meta?: T;
|
|
720
|
+
protected _ringsCache?: number[][];
|
|
721
|
+
protected _ringsCacheLen: number;
|
|
593
722
|
currentCurve: CurvePath;
|
|
594
723
|
style: Partial<Path2DStyle>;
|
|
595
724
|
get startPoint(): Vector2 | undefined;
|
|
@@ -617,6 +746,28 @@ declare class Path2D<T = any> extends CompositeCurve<CurvePath> {
|
|
|
617
746
|
skew(ax: number, ay?: number, target?: Vector2Like): this;
|
|
618
747
|
rotate(rad: number, target?: Vector2Like): this;
|
|
619
748
|
bold(b: number): this;
|
|
749
|
+
/**
|
|
750
|
+
* Test whether a point lies inside the filled area of this path.
|
|
751
|
+
*
|
|
752
|
+
* Each sub-path ({@link CurvePath}) is sampled into its own ring and all rings are
|
|
753
|
+
* evaluated together via {@link pointInPolygons}, so holes (donut / hollow shapes) are
|
|
754
|
+
* honored. This is purely geometric and ignores `style.fill` — for the `fill: 'none'`
|
|
755
|
+
* fallback, gate the call upstream (see {@link Path2DSet.hitTest}).
|
|
756
|
+
*
|
|
757
|
+
* Defaults `fillRule` to `style.fillRule`, then `'nonzero'` (matching SVG/Canvas).
|
|
758
|
+
*/
|
|
759
|
+
protected _invalidateSelf(): void;
|
|
760
|
+
/** Per-sub-path sampled rings, cached for repeated hit tests. */
|
|
761
|
+
protected _getRings(): number[][];
|
|
762
|
+
isPointInFill(point: Vector2Like, options?: IsPointInFillOptions): boolean;
|
|
763
|
+
/**
|
|
764
|
+
* Test whether a point lies on this path's stroke. A hit on any sub-path counts.
|
|
765
|
+
*
|
|
766
|
+
* Defaults `strokeWidth` to this path's own {@link strokeWidth} (which is `0` when
|
|
767
|
+
* `style.stroke` is `'none'`). Each sub-path infers its own closed-ness unless `closed`
|
|
768
|
+
* is given explicitly.
|
|
769
|
+
*/
|
|
770
|
+
isPointInStroke(point: Vector2Like, options?: IsPointInStrokeOptions): boolean;
|
|
620
771
|
getMinMax(min?: Vector2, max?: Vector2, withStyle?: boolean): {
|
|
621
772
|
min: Vector2;
|
|
622
773
|
max: Vector2;
|
|
@@ -641,6 +792,36 @@ declare class Path2DSet<T = any> {
|
|
|
641
792
|
paths: Path2D<T>[];
|
|
642
793
|
viewBox?: number[] | undefined;
|
|
643
794
|
constructor(paths?: Path2D<T>[], viewBox?: number[] | undefined);
|
|
795
|
+
/**
|
|
796
|
+
* Test whether a point lies inside the filled area of any path in this set.
|
|
797
|
+
* Purely geometric (ignores `fill: 'none'`); use {@link hitTest} for style-aware hits.
|
|
798
|
+
*/
|
|
799
|
+
isPointInFill(point: Vector2Like, options?: {
|
|
800
|
+
fillRule?: FillRule;
|
|
801
|
+
}): boolean;
|
|
802
|
+
/**
|
|
803
|
+
* Concise PathKit-style fill containment test across the whole set; shorthand for
|
|
804
|
+
* {@link isPointInFill} with a `{ x, y }` point.
|
|
805
|
+
*/
|
|
806
|
+
contains(x: number, y: number, options?: {
|
|
807
|
+
fillRule?: FillRule;
|
|
808
|
+
}): boolean;
|
|
809
|
+
/**
|
|
810
|
+
* Find the topmost path hit by a point, or `undefined` if none.
|
|
811
|
+
*
|
|
812
|
+
* Paths are tested top-to-bottom (last drawn first). For each path a fill hit is checked
|
|
813
|
+
* first (skipped when `style.fill` is `'none'`), then — if `stroke` is enabled — a stroke
|
|
814
|
+
* hit (skipped when `style.stroke` is `'none'`). This honors the "fill: none falls back to
|
|
815
|
+
* stroke" rule; the coordinate space of `point` must match the paths (no scaling assumed).
|
|
816
|
+
*
|
|
817
|
+
* Options: `stroke` (also test strokes, default `true`), `tolerance` (extra stroke hit slack
|
|
818
|
+
* in path units, default `0`), and `fillRule` (overrides each path's own fill rule).
|
|
819
|
+
*/
|
|
820
|
+
hitTest(point: Vector2Like, options?: {
|
|
821
|
+
stroke?: boolean;
|
|
822
|
+
tolerance?: number;
|
|
823
|
+
fillRule?: FillRule;
|
|
824
|
+
}): Path2D<T> | undefined;
|
|
644
825
|
getBoundingBox(withStyle?: boolean): BoundingBox | undefined;
|
|
645
826
|
toTriangulatedSvgString(result?: TriangulatedResult | TriangulatedResult[], padding?: number): string;
|
|
646
827
|
toTriangulatedSvg(result?: TriangulatedResult | TriangulatedResult[], padding?: number): SVGElement;
|
|
@@ -694,5 +875,5 @@ declare function svgToDom(svg: string | SVGElement): SVGElement;
|
|
|
694
875
|
|
|
695
876
|
declare function svgToPath2DSet(svg: string | SVGElement): Path2DSet;
|
|
696
877
|
|
|
697
|
-
export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPolygonCurve, FFDControlGrid, LineCurve, PI, PI_2, Path2D, Path2DSet, PolygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Transform2D, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parseCssArg, parseCssArgs, parseCssFunctions, parsePathDataArgs, quadraticBezier, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };
|
|
698
|
-
export type { CssFunction, CssFunctionArg, DrawPointOptions, FillRule, FillTriangulateOptions, FillTriangulatedResult, LineCap, LineJoin, LineStyle, ParseCssFunctionContext, Path2DCommand, Path2DData, Path2DDrawStyle, Path2DStyle, StrokeLinecap, StrokeLinejoin, StrokeTriangulateOptions, StrokeTriangulatedResult, TransformableObject, TriangulatedResult, Vector2Like };
|
|
878
|
+
export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPolygonCurve, FFDControlGrid, LineCurve, PI, PI_2, Path2D, Path2DSet, PolygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Transform2D, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parseCssArg, parseCssArgs, parseCssFunctions, parsePathDataArgs, pointInPolygon, pointInPolygons, pointToPolylineDistance, pointToSegmentDistance, quadraticBezier, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };
|
|
879
|
+
export type { CssFunction, CssFunctionArg, DrawPointOptions, FillRule, FillTriangulateOptions, FillTriangulatedResult, IsPointInFillOptions, IsPointInStrokeOptions, LineCap, LineJoin, LineStyle, ParseCssFunctionContext, Path2DCommand, Path2DData, Path2DDrawStyle, Path2DStyle, StrokeLinecap, StrokeLinejoin, StrokeTriangulateOptions, StrokeTriangulatedResult, TransformableObject, TriangulatedResult, Vector2Like };
|
package/dist/index.d.mts
CHANGED
|
@@ -298,7 +298,12 @@ declare function getDirectedArea(vertices: number[]): number;
|
|
|
298
298
|
declare const PI: number;
|
|
299
299
|
declare const PI_2: number;
|
|
300
300
|
declare function toKebabCase(str: string): string;
|
|
301
|
-
|
|
301
|
+
/**
|
|
302
|
+
* Intersection of line p1→p2 with line q1→q2, or `null` when the segments are parallel
|
|
303
|
+
* (`crossRS === 0`) or the intersection lies too far off p1→p2 (`|t| > 1`). Callers must
|
|
304
|
+
* handle `null` (e.g. `Path2D.bold` skips the join when there is no usable point).
|
|
305
|
+
*/
|
|
306
|
+
declare function getIntersectionPoint(p1: Vector2, p2: Vector2, q1: Vector2, q2: Vector2): Vector2 | null;
|
|
302
307
|
|
|
303
308
|
interface NonzeroFillRuleResult {
|
|
304
309
|
index: number;
|
|
@@ -308,6 +313,45 @@ interface NonzeroFillRuleResult {
|
|
|
308
313
|
}
|
|
309
314
|
declare function nonzeroFillRule(paths: number[][]): NonzeroFillRuleResult[];
|
|
310
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Test whether a point lies inside a single polygon ring.
|
|
318
|
+
*
|
|
319
|
+
* `vertices` is a flat `[x0, y0, x1, y1, ...]` array and is treated as implicitly closed
|
|
320
|
+
* (the last vertex connects back to the first). A ring with fewer than 3 points has no
|
|
321
|
+
* area and always returns `false`.
|
|
322
|
+
*
|
|
323
|
+
* @param point The point to test.
|
|
324
|
+
* @param vertices Flat vertex array of the ring.
|
|
325
|
+
* @param fillRule `'nonzero'` (default, matches SVG/Canvas) or `'evenodd'`.
|
|
326
|
+
*/
|
|
327
|
+
declare function pointInPolygon(point: Vector2Like, vertices: number[], fillRule?: FillRule): boolean;
|
|
328
|
+
/**
|
|
329
|
+
* Test whether a point lies inside a shape composed of multiple rings (sub-paths).
|
|
330
|
+
*
|
|
331
|
+
* This is the multi-ring counterpart of {@link pointInPolygon} and is what donut /
|
|
332
|
+
* hollow shapes need: every ring is evaluated together so holes are honored.
|
|
333
|
+
* - `'nonzero'`: sum the signed winding numbers of all rings, inside if the total ≠ 0.
|
|
334
|
+
* - `'evenodd'`: sum the ray-crossing counts of all rings, inside if the total is odd.
|
|
335
|
+
*
|
|
336
|
+
* @param point The point to test.
|
|
337
|
+
* @param polygons Array of flat vertex arrays, one per ring.
|
|
338
|
+
* @param fillRule `'nonzero'` (default) or `'evenodd'`.
|
|
339
|
+
*/
|
|
340
|
+
declare function pointInPolygons(point: Vector2Like, polygons: number[][], fillRule?: FillRule): boolean;
|
|
341
|
+
/**
|
|
342
|
+
* Shortest distance from a point to a single line segment a→b.
|
|
343
|
+
*/
|
|
344
|
+
declare function pointToSegmentDistance(point: Vector2Like, a: Vector2Like, b: Vector2Like): number;
|
|
345
|
+
/**
|
|
346
|
+
* Shortest distance from a point to a polyline.
|
|
347
|
+
*
|
|
348
|
+
* @param point The point to test.
|
|
349
|
+
* @param vertices Flat `[x0, y0, x1, y1, ...]` array of the polyline.
|
|
350
|
+
* @param closed When `true`, also considers the closing edge from the last vertex back
|
|
351
|
+
* to the first (use for closed paths, e.g. `z`/`Z` or `CurvePath.autoClose`).
|
|
352
|
+
*/
|
|
353
|
+
declare function pointToPolylineDistance(point: Vector2Like, vertices: number[], closed?: boolean): number;
|
|
354
|
+
|
|
311
355
|
declare function quadraticBezier(t: number, p0: number, p1: number, p2: number): number;
|
|
312
356
|
|
|
313
357
|
type LineCap = 'butt' | 'round' | 'square';
|
|
@@ -333,10 +377,39 @@ interface LineStyle {
|
|
|
333
377
|
}
|
|
334
378
|
declare function strokeTriangulate(points: number[], options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
335
379
|
|
|
380
|
+
interface IsPointInFillOptions {
|
|
381
|
+
fillRule?: FillRule;
|
|
382
|
+
}
|
|
383
|
+
interface IsPointInStrokeOptions {
|
|
384
|
+
strokeWidth?: number;
|
|
385
|
+
tolerance?: number;
|
|
386
|
+
closed?: boolean;
|
|
387
|
+
}
|
|
336
388
|
declare abstract class Curve {
|
|
337
389
|
arcLengthDivision: number;
|
|
338
390
|
protected _lengths: number[];
|
|
391
|
+
protected _adaptiveCache?: number[];
|
|
392
|
+
/**
|
|
393
|
+
* Parent composite, set lazily when a composite caches its children. Lets
|
|
394
|
+
* {@link invalidate} propagate up so an ancestor's caches refresh too.
|
|
395
|
+
*/
|
|
396
|
+
_owner?: Curve;
|
|
397
|
+
protected _invalidating: boolean;
|
|
339
398
|
abstract getPoint(t: number, output?: Vector2): Vector2;
|
|
399
|
+
/**
|
|
400
|
+
* Drop cached arc lengths and the cached sampled outline used by hit testing, then
|
|
401
|
+
* bubble up to {@link _owner}. Called automatically by {@link applyTransform} and the
|
|
402
|
+
* `Path2D` mutators; call it manually after mutating control-point coordinates in place —
|
|
403
|
+
* the caches cannot observe such mutations.
|
|
404
|
+
*/
|
|
405
|
+
invalidate(): this;
|
|
406
|
+
/** Clears this curve's own caches. Composites also clear their children (see override). */
|
|
407
|
+
protected _invalidateSelf(): void;
|
|
408
|
+
/**
|
|
409
|
+
* Sampled outline cached for repeated hit tests (read-only — do not mutate the result).
|
|
410
|
+
* Invalidated by {@link invalidate}.
|
|
411
|
+
*/
|
|
412
|
+
protected _getCachedAdaptiveVertices(): number[];
|
|
340
413
|
getPointAt(u: number, output?: Vector2): Vector2;
|
|
341
414
|
isClockwise(): boolean;
|
|
342
415
|
getControlPointRefs(): Vector2[];
|
|
@@ -363,6 +436,32 @@ declare abstract class Curve {
|
|
|
363
436
|
max: Vector2;
|
|
364
437
|
};
|
|
365
438
|
getBoundingBox(): BoundingBox;
|
|
439
|
+
/**
|
|
440
|
+
* Test whether a point lies inside the area enclosed by this curve.
|
|
441
|
+
*
|
|
442
|
+
* The curve is sampled via {@link getAdaptiveVertices} into a single implicitly closed
|
|
443
|
+
* ring. This is purely geometric (it ignores any `fill`/`stroke` style), mirroring
|
|
444
|
+
* `CanvasRenderingContext2D.isPointInPath`.
|
|
445
|
+
*
|
|
446
|
+
* Composites that hold multiple sub-paths (e.g. {@link Path2D}) override this so holes
|
|
447
|
+
* are honored — a single `Curve` is always one ring.
|
|
448
|
+
*/
|
|
449
|
+
isPointInFill(point: Vector2Like, options?: IsPointInFillOptions): boolean;
|
|
450
|
+
/**
|
|
451
|
+
* Test whether a point lies on this curve's stroke, i.e. within `strokeWidth / 2 + tolerance`
|
|
452
|
+
* of the sampled outline. The point must be in the same coordinate space as the curve.
|
|
453
|
+
*
|
|
454
|
+
* Options: `strokeWidth` (path units, default `1`), `tolerance` (extra hit slack in path
|
|
455
|
+
* units, default `0` — useful for thin strokes; no coordinate scaling is assumed, so convert
|
|
456
|
+
* pixel tolerance to path units upstream if your path is normalized), and `closed` (whether
|
|
457
|
+
* to include the closing edge from the last vertex back to the first).
|
|
458
|
+
*/
|
|
459
|
+
isPointInStroke(point: Vector2Like, options?: IsPointInStrokeOptions): boolean;
|
|
460
|
+
/**
|
|
461
|
+
* Concise PathKit-style fill containment test: `contains(x, y)` is shorthand for
|
|
462
|
+
* {@link isPointInFill} with a `{ x, y }` point.
|
|
463
|
+
*/
|
|
464
|
+
contains(x: number, y: number, options?: IsPointInFillOptions): boolean;
|
|
366
465
|
getFillVertices(_options?: FillTriangulateOptions): number[];
|
|
367
466
|
fillTriangulate(options?: FillTriangulateOptions): FillTriangulatedResult;
|
|
368
467
|
strokeTriangulate(options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
@@ -397,6 +496,21 @@ declare class RoundCurve extends Curve {
|
|
|
397
496
|
isClockwise(): boolean;
|
|
398
497
|
protected _getDeltaAngle(): number;
|
|
399
498
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
499
|
+
/**
|
|
500
|
+
* Point on the ellipse at an absolute angle (mirrors {@link getPoint}'s parameterization,
|
|
501
|
+
* ignoring `_diff`).
|
|
502
|
+
*/
|
|
503
|
+
protected _pointAtAngle(angle: number, output: Vector2): Vector2;
|
|
504
|
+
/**
|
|
505
|
+
* Analytical bounds of the (elliptical) arc: the start/end points plus the per-axis
|
|
506
|
+
* extrema angles that fall within the swept interval. Matches {@link getPoint}, so it is
|
|
507
|
+
* exact for `ArcCurve`/`EllipseCurve`. The `_diff` offset (used only by the legacy
|
|
508
|
+
* `_getAdaptiveVerticesByCircle` path) is intentionally ignored here.
|
|
509
|
+
*/
|
|
510
|
+
getMinMax(min?: Vector2, max?: Vector2): {
|
|
511
|
+
min: Vector2;
|
|
512
|
+
max: Vector2;
|
|
513
|
+
};
|
|
400
514
|
toCommands(): Path2DCommand[];
|
|
401
515
|
drawTo(ctx: CanvasRenderingContext2D): this;
|
|
402
516
|
applyTransform(transform: Transform2D): this;
|
|
@@ -414,7 +528,10 @@ declare class ArcCurve extends RoundCurve {
|
|
|
414
528
|
|
|
415
529
|
declare class CompositeCurve<T extends Curve = Curve> extends Curve {
|
|
416
530
|
curves: T[];
|
|
531
|
+
protected _adaptiveCacheLen: number;
|
|
417
532
|
constructor(curves?: T[]);
|
|
533
|
+
protected _invalidateSelf(): void;
|
|
534
|
+
protected _getCachedAdaptiveVertices(): number[];
|
|
418
535
|
getFlatCurves(): Curve[];
|
|
419
536
|
addCurve(curve: T): this;
|
|
420
537
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
@@ -526,7 +643,12 @@ declare class RectangleCurve extends PolygonCurve {
|
|
|
526
643
|
copyFrom(source: RectangleCurve): this;
|
|
527
644
|
}
|
|
528
645
|
|
|
529
|
-
|
|
646
|
+
/**
|
|
647
|
+
* A rounded rectangle, modelled as a real composite of 4 `LineCurve` edges + 4 quarter
|
|
648
|
+
* `ArcCurve` corners (like {@link RectangleCurve}). `getPoint`/`getLength`/`getMinMax`/
|
|
649
|
+
* `toCommands` therefore describe the actual rounded outline — not a bare ellipse.
|
|
650
|
+
*/
|
|
651
|
+
declare class RoundRectangleCurve extends CompositeCurve {
|
|
530
652
|
x: number;
|
|
531
653
|
y: number;
|
|
532
654
|
width: number;
|
|
@@ -559,6 +681,11 @@ declare class CurvePath extends CompositeCurve {
|
|
|
559
681
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
560
682
|
getAdaptiveVertices(output?: number[]): number[];
|
|
561
683
|
getFillVertices(options?: FillTriangulateOptions): number[];
|
|
684
|
+
/**
|
|
685
|
+
* Same as {@link Curve.isPointInStroke}, but `closed` defaults to this sub-path's actual
|
|
686
|
+
* closed-ness: explicitly `autoClose`, or geometrically closed (first vertex === last).
|
|
687
|
+
*/
|
|
688
|
+
isPointInStroke(point: Vector2Like, options?: IsPointInStrokeOptions): boolean;
|
|
562
689
|
protected _setCurrentPoint(point: Vector2Like): this;
|
|
563
690
|
protected _connetLineTo(curve: Curve): this;
|
|
564
691
|
closePath(): this;
|
|
@@ -590,6 +717,8 @@ declare class CurvePath extends CompositeCurve {
|
|
|
590
717
|
*/
|
|
591
718
|
declare class Path2D<T = any> extends CompositeCurve<CurvePath> {
|
|
592
719
|
protected _meta?: T;
|
|
720
|
+
protected _ringsCache?: number[][];
|
|
721
|
+
protected _ringsCacheLen: number;
|
|
593
722
|
currentCurve: CurvePath;
|
|
594
723
|
style: Partial<Path2DStyle>;
|
|
595
724
|
get startPoint(): Vector2 | undefined;
|
|
@@ -617,6 +746,28 @@ declare class Path2D<T = any> extends CompositeCurve<CurvePath> {
|
|
|
617
746
|
skew(ax: number, ay?: number, target?: Vector2Like): this;
|
|
618
747
|
rotate(rad: number, target?: Vector2Like): this;
|
|
619
748
|
bold(b: number): this;
|
|
749
|
+
/**
|
|
750
|
+
* Test whether a point lies inside the filled area of this path.
|
|
751
|
+
*
|
|
752
|
+
* Each sub-path ({@link CurvePath}) is sampled into its own ring and all rings are
|
|
753
|
+
* evaluated together via {@link pointInPolygons}, so holes (donut / hollow shapes) are
|
|
754
|
+
* honored. This is purely geometric and ignores `style.fill` — for the `fill: 'none'`
|
|
755
|
+
* fallback, gate the call upstream (see {@link Path2DSet.hitTest}).
|
|
756
|
+
*
|
|
757
|
+
* Defaults `fillRule` to `style.fillRule`, then `'nonzero'` (matching SVG/Canvas).
|
|
758
|
+
*/
|
|
759
|
+
protected _invalidateSelf(): void;
|
|
760
|
+
/** Per-sub-path sampled rings, cached for repeated hit tests. */
|
|
761
|
+
protected _getRings(): number[][];
|
|
762
|
+
isPointInFill(point: Vector2Like, options?: IsPointInFillOptions): boolean;
|
|
763
|
+
/**
|
|
764
|
+
* Test whether a point lies on this path's stroke. A hit on any sub-path counts.
|
|
765
|
+
*
|
|
766
|
+
* Defaults `strokeWidth` to this path's own {@link strokeWidth} (which is `0` when
|
|
767
|
+
* `style.stroke` is `'none'`). Each sub-path infers its own closed-ness unless `closed`
|
|
768
|
+
* is given explicitly.
|
|
769
|
+
*/
|
|
770
|
+
isPointInStroke(point: Vector2Like, options?: IsPointInStrokeOptions): boolean;
|
|
620
771
|
getMinMax(min?: Vector2, max?: Vector2, withStyle?: boolean): {
|
|
621
772
|
min: Vector2;
|
|
622
773
|
max: Vector2;
|
|
@@ -641,6 +792,36 @@ declare class Path2DSet<T = any> {
|
|
|
641
792
|
paths: Path2D<T>[];
|
|
642
793
|
viewBox?: number[] | undefined;
|
|
643
794
|
constructor(paths?: Path2D<T>[], viewBox?: number[] | undefined);
|
|
795
|
+
/**
|
|
796
|
+
* Test whether a point lies inside the filled area of any path in this set.
|
|
797
|
+
* Purely geometric (ignores `fill: 'none'`); use {@link hitTest} for style-aware hits.
|
|
798
|
+
*/
|
|
799
|
+
isPointInFill(point: Vector2Like, options?: {
|
|
800
|
+
fillRule?: FillRule;
|
|
801
|
+
}): boolean;
|
|
802
|
+
/**
|
|
803
|
+
* Concise PathKit-style fill containment test across the whole set; shorthand for
|
|
804
|
+
* {@link isPointInFill} with a `{ x, y }` point.
|
|
805
|
+
*/
|
|
806
|
+
contains(x: number, y: number, options?: {
|
|
807
|
+
fillRule?: FillRule;
|
|
808
|
+
}): boolean;
|
|
809
|
+
/**
|
|
810
|
+
* Find the topmost path hit by a point, or `undefined` if none.
|
|
811
|
+
*
|
|
812
|
+
* Paths are tested top-to-bottom (last drawn first). For each path a fill hit is checked
|
|
813
|
+
* first (skipped when `style.fill` is `'none'`), then — if `stroke` is enabled — a stroke
|
|
814
|
+
* hit (skipped when `style.stroke` is `'none'`). This honors the "fill: none falls back to
|
|
815
|
+
* stroke" rule; the coordinate space of `point` must match the paths (no scaling assumed).
|
|
816
|
+
*
|
|
817
|
+
* Options: `stroke` (also test strokes, default `true`), `tolerance` (extra stroke hit slack
|
|
818
|
+
* in path units, default `0`), and `fillRule` (overrides each path's own fill rule).
|
|
819
|
+
*/
|
|
820
|
+
hitTest(point: Vector2Like, options?: {
|
|
821
|
+
stroke?: boolean;
|
|
822
|
+
tolerance?: number;
|
|
823
|
+
fillRule?: FillRule;
|
|
824
|
+
}): Path2D<T> | undefined;
|
|
644
825
|
getBoundingBox(withStyle?: boolean): BoundingBox | undefined;
|
|
645
826
|
toTriangulatedSvgString(result?: TriangulatedResult | TriangulatedResult[], padding?: number): string;
|
|
646
827
|
toTriangulatedSvg(result?: TriangulatedResult | TriangulatedResult[], padding?: number): SVGElement;
|
|
@@ -694,5 +875,5 @@ declare function svgToDom(svg: string | SVGElement): SVGElement;
|
|
|
694
875
|
|
|
695
876
|
declare function svgToPath2DSet(svg: string | SVGElement): Path2DSet;
|
|
696
877
|
|
|
697
|
-
export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPolygonCurve, FFDControlGrid, LineCurve, PI, PI_2, Path2D, Path2DSet, PolygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Transform2D, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parseCssArg, parseCssArgs, parseCssFunctions, parsePathDataArgs, quadraticBezier, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };
|
|
698
|
-
export type { CssFunction, CssFunctionArg, DrawPointOptions, FillRule, FillTriangulateOptions, FillTriangulatedResult, LineCap, LineJoin, LineStyle, ParseCssFunctionContext, Path2DCommand, Path2DData, Path2DDrawStyle, Path2DStyle, StrokeLinecap, StrokeLinejoin, StrokeTriangulateOptions, StrokeTriangulatedResult, TransformableObject, TriangulatedResult, Vector2Like };
|
|
878
|
+
export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPolygonCurve, FFDControlGrid, LineCurve, PI, PI_2, Path2D, Path2DSet, PolygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Transform2D, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parseCssArg, parseCssArgs, parseCssFunctions, parsePathDataArgs, pointInPolygon, pointInPolygons, pointToPolylineDistance, pointToSegmentDistance, quadraticBezier, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };
|
|
879
|
+
export type { CssFunction, CssFunctionArg, DrawPointOptions, FillRule, FillTriangulateOptions, FillTriangulatedResult, IsPointInFillOptions, IsPointInStrokeOptions, LineCap, LineJoin, LineStyle, ParseCssFunctionContext, Path2DCommand, Path2DData, Path2DDrawStyle, Path2DStyle, StrokeLinecap, StrokeLinejoin, StrokeTriangulateOptions, StrokeTriangulatedResult, TransformableObject, TriangulatedResult, Vector2Like };
|