modern-path2d 1.6.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +237 -2
- package/dist/index.d.cts +129 -2
- package/dist/index.d.mts +129 -2
- package/dist/index.d.ts +129 -2
- package/dist/index.js +2 -2
- package/dist/index.mjs +234 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -598,7 +598,7 @@ function getDirectedArea(vertices) {
|
|
|
598
598
|
function cross(ax, ay, bx, by, cx, cy) {
|
|
599
599
|
return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
|
|
600
600
|
}
|
|
601
|
-
function windingNumber(px, py, polygon) {
|
|
601
|
+
function windingNumber$1(px, py, polygon) {
|
|
602
602
|
const polygonLen = polygon.length;
|
|
603
603
|
let wn = 0;
|
|
604
604
|
for (let i = 0, j = polygonLen - 2; i < polygonLen; j = i, i += 2) {
|
|
@@ -703,7 +703,7 @@ function nonzeroFillRule(paths) {
|
|
|
703
703
|
const wnList = [];
|
|
704
704
|
for (let p = 0, pLen = testPoints.length; p < pLen; p++) {
|
|
705
705
|
const [x, y] = testPoints[p];
|
|
706
|
-
const winding = windingNumber(x, y, paths[j]);
|
|
706
|
+
const winding = windingNumber$1(x, y, paths[j]);
|
|
707
707
|
wnMap[winding] = (wnMap[winding] ?? 0) + 1;
|
|
708
708
|
wnList.push(winding);
|
|
709
709
|
}
|
|
@@ -726,6 +726,120 @@ function nonzeroFillRule(paths) {
|
|
|
726
726
|
return results;
|
|
727
727
|
}
|
|
728
728
|
|
|
729
|
+
function isLeft(ax, ay, bx, by, px, py) {
|
|
730
|
+
return (bx - ax) * (py - ay) - (px - ax) * (by - ay);
|
|
731
|
+
}
|
|
732
|
+
function windingNumber(px, py, vertices) {
|
|
733
|
+
const len = vertices.length;
|
|
734
|
+
let wn = 0;
|
|
735
|
+
for (let i = 0; i < len; i += 2) {
|
|
736
|
+
const ax = vertices[i];
|
|
737
|
+
const ay = vertices[i + 1];
|
|
738
|
+
const k = (i + 2) % len;
|
|
739
|
+
const bx = vertices[k];
|
|
740
|
+
const by = vertices[k + 1];
|
|
741
|
+
if (ay <= py) {
|
|
742
|
+
if (by > py && isLeft(ax, ay, bx, by, px, py) > 0) {
|
|
743
|
+
wn++;
|
|
744
|
+
}
|
|
745
|
+
} else {
|
|
746
|
+
if (by <= py && isLeft(ax, ay, bx, by, px, py) < 0) {
|
|
747
|
+
wn--;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
return wn;
|
|
752
|
+
}
|
|
753
|
+
function crossingNumber(px, py, vertices) {
|
|
754
|
+
const len = vertices.length;
|
|
755
|
+
let cn = 0;
|
|
756
|
+
for (let i = 0; i < len; i += 2) {
|
|
757
|
+
const ax = vertices[i];
|
|
758
|
+
const ay = vertices[i + 1];
|
|
759
|
+
const k = (i + 2) % len;
|
|
760
|
+
const bx = vertices[k];
|
|
761
|
+
const by = vertices[k + 1];
|
|
762
|
+
if (ay <= py && by > py || ay > py && by <= py) {
|
|
763
|
+
const t = (py - ay) / (by - ay);
|
|
764
|
+
if (px < ax + t * (bx - ax)) {
|
|
765
|
+
cn++;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
return cn;
|
|
770
|
+
}
|
|
771
|
+
function segmentDistance(px, py, ax, ay, bx, by) {
|
|
772
|
+
const dx = bx - ax;
|
|
773
|
+
const dy = by - ay;
|
|
774
|
+
const lenSq = dx * dx + dy * dy;
|
|
775
|
+
let t = lenSq === 0 ? 0 : ((px - ax) * dx + (py - ay) * dy) / lenSq;
|
|
776
|
+
if (t < 0) {
|
|
777
|
+
t = 0;
|
|
778
|
+
} else if (t > 1) {
|
|
779
|
+
t = 1;
|
|
780
|
+
}
|
|
781
|
+
const cx = ax + t * dx;
|
|
782
|
+
const cy = ay + t * dy;
|
|
783
|
+
return Math.hypot(px - cx, py - cy);
|
|
784
|
+
}
|
|
785
|
+
function pointInPolygon(point, vertices, fillRule = "nonzero") {
|
|
786
|
+
if (vertices.length < 6) {
|
|
787
|
+
return false;
|
|
788
|
+
}
|
|
789
|
+
if (fillRule === "evenodd") {
|
|
790
|
+
return (crossingNumber(point.x, point.y, vertices) & 1) === 1;
|
|
791
|
+
}
|
|
792
|
+
return windingNumber(point.x, point.y, vertices) !== 0;
|
|
793
|
+
}
|
|
794
|
+
function pointInPolygons(point, polygons, fillRule = "nonzero") {
|
|
795
|
+
const { x, y } = point;
|
|
796
|
+
if (fillRule === "evenodd") {
|
|
797
|
+
let cn = 0;
|
|
798
|
+
for (let i = 0, len = polygons.length; i < len; i++) {
|
|
799
|
+
const ring = polygons[i];
|
|
800
|
+
if (ring.length >= 6) {
|
|
801
|
+
cn += crossingNumber(x, y, ring);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
return (cn & 1) === 1;
|
|
805
|
+
}
|
|
806
|
+
let wn = 0;
|
|
807
|
+
for (let i = 0, len = polygons.length; i < len; i++) {
|
|
808
|
+
const ring = polygons[i];
|
|
809
|
+
if (ring.length >= 6) {
|
|
810
|
+
wn += windingNumber(x, y, ring);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
return wn !== 0;
|
|
814
|
+
}
|
|
815
|
+
function pointToSegmentDistance(point, a, b) {
|
|
816
|
+
return segmentDistance(point.x, point.y, a.x, a.y, b.x, b.y);
|
|
817
|
+
}
|
|
818
|
+
function pointToPolylineDistance(point, vertices, closed = false) {
|
|
819
|
+
const len = vertices.length;
|
|
820
|
+
if (len < 2) {
|
|
821
|
+
return Infinity;
|
|
822
|
+
}
|
|
823
|
+
const { x: px, y: py } = point;
|
|
824
|
+
if (len === 2) {
|
|
825
|
+
return Math.hypot(px - vertices[0], py - vertices[1]);
|
|
826
|
+
}
|
|
827
|
+
let min = Infinity;
|
|
828
|
+
for (let i = 0; i < len - 2; i += 2) {
|
|
829
|
+
const d = segmentDistance(px, py, vertices[i], vertices[i + 1], vertices[i + 2], vertices[i + 3]);
|
|
830
|
+
if (d < min) {
|
|
831
|
+
min = d;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
if (closed && len >= 6) {
|
|
835
|
+
const d = segmentDistance(px, py, vertices[len - 2], vertices[len - 1], vertices[0], vertices[1]);
|
|
836
|
+
if (d < min) {
|
|
837
|
+
min = d;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
return min;
|
|
841
|
+
}
|
|
842
|
+
|
|
729
843
|
function quadraticBezierP0(t, p) {
|
|
730
844
|
const k = 1 - t;
|
|
731
845
|
return k * k * p;
|
|
@@ -2713,6 +2827,40 @@ class Curve {
|
|
|
2713
2827
|
const { min, max } = this.getMinMax();
|
|
2714
2828
|
return new BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
2715
2829
|
}
|
|
2830
|
+
/**
|
|
2831
|
+
* Test whether a point lies inside the area enclosed by this curve.
|
|
2832
|
+
*
|
|
2833
|
+
* The curve is sampled via {@link getAdaptiveVertices} into a single implicitly closed
|
|
2834
|
+
* ring. This is purely geometric (it ignores any `fill`/`stroke` style), mirroring
|
|
2835
|
+
* `CanvasRenderingContext2D.isPointInPath`.
|
|
2836
|
+
*
|
|
2837
|
+
* Composites that hold multiple sub-paths (e.g. {@link Path2D}) override this so holes
|
|
2838
|
+
* are honored — a single `Curve` is always one ring.
|
|
2839
|
+
*/
|
|
2840
|
+
isPointInFill(point, options = {}) {
|
|
2841
|
+
return pointInPolygon(point, this.getAdaptiveVertices(), options.fillRule);
|
|
2842
|
+
}
|
|
2843
|
+
/**
|
|
2844
|
+
* Test whether a point lies on this curve's stroke, i.e. within `strokeWidth / 2 + tolerance`
|
|
2845
|
+
* of the sampled outline. The point must be in the same coordinate space as the curve.
|
|
2846
|
+
*
|
|
2847
|
+
* Options: `strokeWidth` (path units, default `1`), `tolerance` (extra hit slack in path
|
|
2848
|
+
* units, default `0` — useful for thin strokes; no coordinate scaling is assumed, so convert
|
|
2849
|
+
* pixel tolerance to path units upstream if your path is normalized), and `closed` (whether
|
|
2850
|
+
* to include the closing edge from the last vertex back to the first).
|
|
2851
|
+
*/
|
|
2852
|
+
isPointInStroke(point, options = {}) {
|
|
2853
|
+
const { strokeWidth = 1, tolerance = 0, closed = false } = options;
|
|
2854
|
+
const distance = pointToPolylineDistance(point, this.getAdaptiveVertices(), closed);
|
|
2855
|
+
return distance <= strokeWidth / 2 + tolerance;
|
|
2856
|
+
}
|
|
2857
|
+
/**
|
|
2858
|
+
* Concise PathKit-style fill containment test: `contains(x, y)` is shorthand for
|
|
2859
|
+
* {@link isPointInFill} with a `{ x, y }` point.
|
|
2860
|
+
*/
|
|
2861
|
+
contains(x, y, options = {}) {
|
|
2862
|
+
return this.isPointInFill({ x, y }, options);
|
|
2863
|
+
}
|
|
2716
2864
|
getFillVertices(_options) {
|
|
2717
2865
|
return this.getAdaptiveVertices();
|
|
2718
2866
|
}
|
|
@@ -3852,6 +4000,17 @@ class CurvePath extends CompositeCurve {
|
|
|
3852
4000
|
super.getFillVertices(options)
|
|
3853
4001
|
);
|
|
3854
4002
|
}
|
|
4003
|
+
/**
|
|
4004
|
+
* Same as {@link Curve.isPointInStroke}, but `closed` defaults to this sub-path's actual
|
|
4005
|
+
* closed-ness: explicitly `autoClose`, or geometrically closed (first vertex === last).
|
|
4006
|
+
*/
|
|
4007
|
+
isPointInStroke(point, options = {}) {
|
|
4008
|
+
const { strokeWidth = 1, tolerance = 0 } = options;
|
|
4009
|
+
const vertices = this.getAdaptiveVertices();
|
|
4010
|
+
const len = vertices.length;
|
|
4011
|
+
const closed = options.closed ?? (this.autoClose || len >= 6 && vertices[0] === vertices[len - 2] && vertices[1] === vertices[len - 1]);
|
|
4012
|
+
return pointToPolylineDistance(point, vertices, closed) <= strokeWidth / 2 + tolerance;
|
|
4013
|
+
}
|
|
3855
4014
|
_setCurrentPoint(point) {
|
|
3856
4015
|
this.currentPoint = new Vector2(point.x, point.y);
|
|
3857
4016
|
if (!this.startPoint) {
|
|
@@ -4215,6 +4374,40 @@ class Path2D extends CompositeCurve {
|
|
|
4215
4374
|
});
|
|
4216
4375
|
return this;
|
|
4217
4376
|
}
|
|
4377
|
+
/**
|
|
4378
|
+
* Test whether a point lies inside the filled area of this path.
|
|
4379
|
+
*
|
|
4380
|
+
* Each sub-path ({@link CurvePath}) is sampled into its own ring and all rings are
|
|
4381
|
+
* evaluated together via {@link pointInPolygons}, so holes (donut / hollow shapes) are
|
|
4382
|
+
* honored. This is purely geometric and ignores `style.fill` — for the `fill: 'none'`
|
|
4383
|
+
* fallback, gate the call upstream (see {@link Path2DSet.hitTest}).
|
|
4384
|
+
*
|
|
4385
|
+
* Defaults `fillRule` to `style.fillRule`, then `'nonzero'` (matching SVG/Canvas).
|
|
4386
|
+
*/
|
|
4387
|
+
isPointInFill(point, options = {}) {
|
|
4388
|
+
const fillRule = options.fillRule ?? this.style.fillRule ?? "nonzero";
|
|
4389
|
+
return pointInPolygons(
|
|
4390
|
+
point,
|
|
4391
|
+
this.curves.map((curve) => curve.getAdaptiveVertices()),
|
|
4392
|
+
fillRule
|
|
4393
|
+
);
|
|
4394
|
+
}
|
|
4395
|
+
/**
|
|
4396
|
+
* Test whether a point lies on this path's stroke. A hit on any sub-path counts.
|
|
4397
|
+
*
|
|
4398
|
+
* Defaults `strokeWidth` to this path's own {@link strokeWidth} (which is `0` when
|
|
4399
|
+
* `style.stroke` is `'none'`). Each sub-path infers its own closed-ness unless `closed`
|
|
4400
|
+
* is given explicitly.
|
|
4401
|
+
*/
|
|
4402
|
+
isPointInStroke(point, options = {}) {
|
|
4403
|
+
const strokeWidth = options.strokeWidth ?? this.strokeWidth;
|
|
4404
|
+
const { tolerance = 0, closed } = options;
|
|
4405
|
+
return this.curves.some((curve) => curve.isPointInStroke(point, {
|
|
4406
|
+
strokeWidth,
|
|
4407
|
+
tolerance,
|
|
4408
|
+
closed
|
|
4409
|
+
}));
|
|
4410
|
+
}
|
|
4218
4411
|
getMinMax(min = Vector2.MAX, max = Vector2.MIN, withStyle = true) {
|
|
4219
4412
|
const strokeWidth = this.strokeWidth;
|
|
4220
4413
|
this.curves.forEach((curve) => {
|
|
@@ -4392,6 +4585,44 @@ class Path2DSet {
|
|
|
4392
4585
|
this.paths = paths;
|
|
4393
4586
|
this.viewBox = viewBox;
|
|
4394
4587
|
}
|
|
4588
|
+
/**
|
|
4589
|
+
* Test whether a point lies inside the filled area of any path in this set.
|
|
4590
|
+
* Purely geometric (ignores `fill: 'none'`); use {@link hitTest} for style-aware hits.
|
|
4591
|
+
*/
|
|
4592
|
+
isPointInFill(point, options = {}) {
|
|
4593
|
+
return this.paths.some((path) => path.isPointInFill(point, options));
|
|
4594
|
+
}
|
|
4595
|
+
/**
|
|
4596
|
+
* Concise PathKit-style fill containment test across the whole set; shorthand for
|
|
4597
|
+
* {@link isPointInFill} with a `{ x, y }` point.
|
|
4598
|
+
*/
|
|
4599
|
+
contains(x, y, options = {}) {
|
|
4600
|
+
return this.isPointInFill({ x, y }, options);
|
|
4601
|
+
}
|
|
4602
|
+
/**
|
|
4603
|
+
* Find the topmost path hit by a point, or `undefined` if none.
|
|
4604
|
+
*
|
|
4605
|
+
* Paths are tested top-to-bottom (last drawn first). For each path a fill hit is checked
|
|
4606
|
+
* first (skipped when `style.fill` is `'none'`), then — if `stroke` is enabled — a stroke
|
|
4607
|
+
* hit (skipped when `style.stroke` is `'none'`). This honors the "fill: none falls back to
|
|
4608
|
+
* stroke" rule; the coordinate space of `point` must match the paths (no scaling assumed).
|
|
4609
|
+
*
|
|
4610
|
+
* Options: `stroke` (also test strokes, default `true`), `tolerance` (extra stroke hit slack
|
|
4611
|
+
* in path units, default `0`), and `fillRule` (overrides each path's own fill rule).
|
|
4612
|
+
*/
|
|
4613
|
+
hitTest(point, options = {}) {
|
|
4614
|
+
const { stroke = true, tolerance, fillRule } = options;
|
|
4615
|
+
for (let i = this.paths.length - 1; i >= 0; i--) {
|
|
4616
|
+
const path = this.paths[i];
|
|
4617
|
+
if ((path.style.fill ?? "#000") !== "none" && path.isPointInFill(point, { fillRule })) {
|
|
4618
|
+
return path;
|
|
4619
|
+
}
|
|
4620
|
+
if (stroke && (path.style.stroke ?? "none") !== "none" && path.isPointInStroke(point, { tolerance })) {
|
|
4621
|
+
return path;
|
|
4622
|
+
}
|
|
4623
|
+
}
|
|
4624
|
+
return void 0;
|
|
4625
|
+
}
|
|
4395
4626
|
getBoundingBox(withStyle = true) {
|
|
4396
4627
|
if (!this.paths.length) {
|
|
4397
4628
|
return void 0;
|
|
@@ -4583,6 +4814,10 @@ exports.parseCssArg = parseCssArg;
|
|
|
4583
4814
|
exports.parseCssArgs = parseCssArgs;
|
|
4584
4815
|
exports.parseCssFunctions = parseCssFunctions;
|
|
4585
4816
|
exports.parsePathDataArgs = parsePathDataArgs;
|
|
4817
|
+
exports.pointInPolygon = pointInPolygon;
|
|
4818
|
+
exports.pointInPolygons = pointInPolygons;
|
|
4819
|
+
exports.pointToPolylineDistance = pointToPolylineDistance;
|
|
4820
|
+
exports.pointToSegmentDistance = pointToSegmentDistance;
|
|
4586
4821
|
exports.quadraticBezier = quadraticBezier;
|
|
4587
4822
|
exports.setCanvasContext = setCanvasContext;
|
|
4588
4823
|
exports.strokeTriangulate = strokeTriangulate;
|
package/dist/index.d.cts
CHANGED
|
@@ -308,6 +308,45 @@ interface NonzeroFillRuleResult {
|
|
|
308
308
|
}
|
|
309
309
|
declare function nonzeroFillRule(paths: number[][]): NonzeroFillRuleResult[];
|
|
310
310
|
|
|
311
|
+
/**
|
|
312
|
+
* Test whether a point lies inside a single polygon ring.
|
|
313
|
+
*
|
|
314
|
+
* `vertices` is a flat `[x0, y0, x1, y1, ...]` array and is treated as implicitly closed
|
|
315
|
+
* (the last vertex connects back to the first). A ring with fewer than 3 points has no
|
|
316
|
+
* area and always returns `false`.
|
|
317
|
+
*
|
|
318
|
+
* @param point The point to test.
|
|
319
|
+
* @param vertices Flat vertex array of the ring.
|
|
320
|
+
* @param fillRule `'nonzero'` (default, matches SVG/Canvas) or `'evenodd'`.
|
|
321
|
+
*/
|
|
322
|
+
declare function pointInPolygon(point: Vector2Like, vertices: number[], fillRule?: FillRule): boolean;
|
|
323
|
+
/**
|
|
324
|
+
* Test whether a point lies inside a shape composed of multiple rings (sub-paths).
|
|
325
|
+
*
|
|
326
|
+
* This is the multi-ring counterpart of {@link pointInPolygon} and is what donut /
|
|
327
|
+
* hollow shapes need: every ring is evaluated together so holes are honored.
|
|
328
|
+
* - `'nonzero'`: sum the signed winding numbers of all rings, inside if the total ≠ 0.
|
|
329
|
+
* - `'evenodd'`: sum the ray-crossing counts of all rings, inside if the total is odd.
|
|
330
|
+
*
|
|
331
|
+
* @param point The point to test.
|
|
332
|
+
* @param polygons Array of flat vertex arrays, one per ring.
|
|
333
|
+
* @param fillRule `'nonzero'` (default) or `'evenodd'`.
|
|
334
|
+
*/
|
|
335
|
+
declare function pointInPolygons(point: Vector2Like, polygons: number[][], fillRule?: FillRule): boolean;
|
|
336
|
+
/**
|
|
337
|
+
* Shortest distance from a point to a single line segment a→b.
|
|
338
|
+
*/
|
|
339
|
+
declare function pointToSegmentDistance(point: Vector2Like, a: Vector2Like, b: Vector2Like): number;
|
|
340
|
+
/**
|
|
341
|
+
* Shortest distance from a point to a polyline.
|
|
342
|
+
*
|
|
343
|
+
* @param point The point to test.
|
|
344
|
+
* @param vertices Flat `[x0, y0, x1, y1, ...]` array of the polyline.
|
|
345
|
+
* @param closed When `true`, also considers the closing edge from the last vertex back
|
|
346
|
+
* to the first (use for closed paths, e.g. `z`/`Z` or `CurvePath.autoClose`).
|
|
347
|
+
*/
|
|
348
|
+
declare function pointToPolylineDistance(point: Vector2Like, vertices: number[], closed?: boolean): number;
|
|
349
|
+
|
|
311
350
|
declare function quadraticBezier(t: number, p0: number, p1: number, p2: number): number;
|
|
312
351
|
|
|
313
352
|
type LineCap = 'butt' | 'round' | 'square';
|
|
@@ -333,6 +372,14 @@ interface LineStyle {
|
|
|
333
372
|
}
|
|
334
373
|
declare function strokeTriangulate(points: number[], options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
335
374
|
|
|
375
|
+
interface IsPointInFillOptions {
|
|
376
|
+
fillRule?: FillRule;
|
|
377
|
+
}
|
|
378
|
+
interface IsPointInStrokeOptions {
|
|
379
|
+
strokeWidth?: number;
|
|
380
|
+
tolerance?: number;
|
|
381
|
+
closed?: boolean;
|
|
382
|
+
}
|
|
336
383
|
declare abstract class Curve {
|
|
337
384
|
arcLengthDivision: number;
|
|
338
385
|
protected _lengths: number[];
|
|
@@ -363,6 +410,32 @@ declare abstract class Curve {
|
|
|
363
410
|
max: Vector2;
|
|
364
411
|
};
|
|
365
412
|
getBoundingBox(): BoundingBox;
|
|
413
|
+
/**
|
|
414
|
+
* Test whether a point lies inside the area enclosed by this curve.
|
|
415
|
+
*
|
|
416
|
+
* The curve is sampled via {@link getAdaptiveVertices} into a single implicitly closed
|
|
417
|
+
* ring. This is purely geometric (it ignores any `fill`/`stroke` style), mirroring
|
|
418
|
+
* `CanvasRenderingContext2D.isPointInPath`.
|
|
419
|
+
*
|
|
420
|
+
* Composites that hold multiple sub-paths (e.g. {@link Path2D}) override this so holes
|
|
421
|
+
* are honored — a single `Curve` is always one ring.
|
|
422
|
+
*/
|
|
423
|
+
isPointInFill(point: Vector2Like, options?: IsPointInFillOptions): boolean;
|
|
424
|
+
/**
|
|
425
|
+
* Test whether a point lies on this curve's stroke, i.e. within `strokeWidth / 2 + tolerance`
|
|
426
|
+
* of the sampled outline. The point must be in the same coordinate space as the curve.
|
|
427
|
+
*
|
|
428
|
+
* Options: `strokeWidth` (path units, default `1`), `tolerance` (extra hit slack in path
|
|
429
|
+
* units, default `0` — useful for thin strokes; no coordinate scaling is assumed, so convert
|
|
430
|
+
* pixel tolerance to path units upstream if your path is normalized), and `closed` (whether
|
|
431
|
+
* to include the closing edge from the last vertex back to the first).
|
|
432
|
+
*/
|
|
433
|
+
isPointInStroke(point: Vector2Like, options?: IsPointInStrokeOptions): boolean;
|
|
434
|
+
/**
|
|
435
|
+
* Concise PathKit-style fill containment test: `contains(x, y)` is shorthand for
|
|
436
|
+
* {@link isPointInFill} with a `{ x, y }` point.
|
|
437
|
+
*/
|
|
438
|
+
contains(x: number, y: number, options?: IsPointInFillOptions): boolean;
|
|
366
439
|
getFillVertices(_options?: FillTriangulateOptions): number[];
|
|
367
440
|
fillTriangulate(options?: FillTriangulateOptions): FillTriangulatedResult;
|
|
368
441
|
strokeTriangulate(options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
@@ -559,6 +632,11 @@ declare class CurvePath extends CompositeCurve {
|
|
|
559
632
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
560
633
|
getAdaptiveVertices(output?: number[]): number[];
|
|
561
634
|
getFillVertices(options?: FillTriangulateOptions): number[];
|
|
635
|
+
/**
|
|
636
|
+
* Same as {@link Curve.isPointInStroke}, but `closed` defaults to this sub-path's actual
|
|
637
|
+
* closed-ness: explicitly `autoClose`, or geometrically closed (first vertex === last).
|
|
638
|
+
*/
|
|
639
|
+
isPointInStroke(point: Vector2Like, options?: IsPointInStrokeOptions): boolean;
|
|
562
640
|
protected _setCurrentPoint(point: Vector2Like): this;
|
|
563
641
|
protected _connetLineTo(curve: Curve): this;
|
|
564
642
|
closePath(): this;
|
|
@@ -617,6 +695,25 @@ declare class Path2D<T = any> extends CompositeCurve<CurvePath> {
|
|
|
617
695
|
skew(ax: number, ay?: number, target?: Vector2Like): this;
|
|
618
696
|
rotate(rad: number, target?: Vector2Like): this;
|
|
619
697
|
bold(b: number): this;
|
|
698
|
+
/**
|
|
699
|
+
* Test whether a point lies inside the filled area of this path.
|
|
700
|
+
*
|
|
701
|
+
* Each sub-path ({@link CurvePath}) is sampled into its own ring and all rings are
|
|
702
|
+
* evaluated together via {@link pointInPolygons}, so holes (donut / hollow shapes) are
|
|
703
|
+
* honored. This is purely geometric and ignores `style.fill` — for the `fill: 'none'`
|
|
704
|
+
* fallback, gate the call upstream (see {@link Path2DSet.hitTest}).
|
|
705
|
+
*
|
|
706
|
+
* Defaults `fillRule` to `style.fillRule`, then `'nonzero'` (matching SVG/Canvas).
|
|
707
|
+
*/
|
|
708
|
+
isPointInFill(point: Vector2Like, options?: IsPointInFillOptions): boolean;
|
|
709
|
+
/**
|
|
710
|
+
* Test whether a point lies on this path's stroke. A hit on any sub-path counts.
|
|
711
|
+
*
|
|
712
|
+
* Defaults `strokeWidth` to this path's own {@link strokeWidth} (which is `0` when
|
|
713
|
+
* `style.stroke` is `'none'`). Each sub-path infers its own closed-ness unless `closed`
|
|
714
|
+
* is given explicitly.
|
|
715
|
+
*/
|
|
716
|
+
isPointInStroke(point: Vector2Like, options?: IsPointInStrokeOptions): boolean;
|
|
620
717
|
getMinMax(min?: Vector2, max?: Vector2, withStyle?: boolean): {
|
|
621
718
|
min: Vector2;
|
|
622
719
|
max: Vector2;
|
|
@@ -641,6 +738,36 @@ declare class Path2DSet<T = any> {
|
|
|
641
738
|
paths: Path2D<T>[];
|
|
642
739
|
viewBox?: number[] | undefined;
|
|
643
740
|
constructor(paths?: Path2D<T>[], viewBox?: number[] | undefined);
|
|
741
|
+
/**
|
|
742
|
+
* Test whether a point lies inside the filled area of any path in this set.
|
|
743
|
+
* Purely geometric (ignores `fill: 'none'`); use {@link hitTest} for style-aware hits.
|
|
744
|
+
*/
|
|
745
|
+
isPointInFill(point: Vector2Like, options?: {
|
|
746
|
+
fillRule?: FillRule;
|
|
747
|
+
}): boolean;
|
|
748
|
+
/**
|
|
749
|
+
* Concise PathKit-style fill containment test across the whole set; shorthand for
|
|
750
|
+
* {@link isPointInFill} with a `{ x, y }` point.
|
|
751
|
+
*/
|
|
752
|
+
contains(x: number, y: number, options?: {
|
|
753
|
+
fillRule?: FillRule;
|
|
754
|
+
}): boolean;
|
|
755
|
+
/**
|
|
756
|
+
* Find the topmost path hit by a point, or `undefined` if none.
|
|
757
|
+
*
|
|
758
|
+
* Paths are tested top-to-bottom (last drawn first). For each path a fill hit is checked
|
|
759
|
+
* first (skipped when `style.fill` is `'none'`), then — if `stroke` is enabled — a stroke
|
|
760
|
+
* hit (skipped when `style.stroke` is `'none'`). This honors the "fill: none falls back to
|
|
761
|
+
* stroke" rule; the coordinate space of `point` must match the paths (no scaling assumed).
|
|
762
|
+
*
|
|
763
|
+
* Options: `stroke` (also test strokes, default `true`), `tolerance` (extra stroke hit slack
|
|
764
|
+
* in path units, default `0`), and `fillRule` (overrides each path's own fill rule).
|
|
765
|
+
*/
|
|
766
|
+
hitTest(point: Vector2Like, options?: {
|
|
767
|
+
stroke?: boolean;
|
|
768
|
+
tolerance?: number;
|
|
769
|
+
fillRule?: FillRule;
|
|
770
|
+
}): Path2D<T> | undefined;
|
|
644
771
|
getBoundingBox(withStyle?: boolean): BoundingBox | undefined;
|
|
645
772
|
toTriangulatedSvgString(result?: TriangulatedResult | TriangulatedResult[], padding?: number): string;
|
|
646
773
|
toTriangulatedSvg(result?: TriangulatedResult | TriangulatedResult[], padding?: number): SVGElement;
|
|
@@ -694,5 +821,5 @@ declare function svgToDom(svg: string | SVGElement): SVGElement;
|
|
|
694
821
|
|
|
695
822
|
declare function svgToPath2DSet(svg: string | SVGElement): Path2DSet;
|
|
696
823
|
|
|
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 };
|
|
824
|
+
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 };
|
|
825
|
+
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
|
@@ -308,6 +308,45 @@ interface NonzeroFillRuleResult {
|
|
|
308
308
|
}
|
|
309
309
|
declare function nonzeroFillRule(paths: number[][]): NonzeroFillRuleResult[];
|
|
310
310
|
|
|
311
|
+
/**
|
|
312
|
+
* Test whether a point lies inside a single polygon ring.
|
|
313
|
+
*
|
|
314
|
+
* `vertices` is a flat `[x0, y0, x1, y1, ...]` array and is treated as implicitly closed
|
|
315
|
+
* (the last vertex connects back to the first). A ring with fewer than 3 points has no
|
|
316
|
+
* area and always returns `false`.
|
|
317
|
+
*
|
|
318
|
+
* @param point The point to test.
|
|
319
|
+
* @param vertices Flat vertex array of the ring.
|
|
320
|
+
* @param fillRule `'nonzero'` (default, matches SVG/Canvas) or `'evenodd'`.
|
|
321
|
+
*/
|
|
322
|
+
declare function pointInPolygon(point: Vector2Like, vertices: number[], fillRule?: FillRule): boolean;
|
|
323
|
+
/**
|
|
324
|
+
* Test whether a point lies inside a shape composed of multiple rings (sub-paths).
|
|
325
|
+
*
|
|
326
|
+
* This is the multi-ring counterpart of {@link pointInPolygon} and is what donut /
|
|
327
|
+
* hollow shapes need: every ring is evaluated together so holes are honored.
|
|
328
|
+
* - `'nonzero'`: sum the signed winding numbers of all rings, inside if the total ≠ 0.
|
|
329
|
+
* - `'evenodd'`: sum the ray-crossing counts of all rings, inside if the total is odd.
|
|
330
|
+
*
|
|
331
|
+
* @param point The point to test.
|
|
332
|
+
* @param polygons Array of flat vertex arrays, one per ring.
|
|
333
|
+
* @param fillRule `'nonzero'` (default) or `'evenodd'`.
|
|
334
|
+
*/
|
|
335
|
+
declare function pointInPolygons(point: Vector2Like, polygons: number[][], fillRule?: FillRule): boolean;
|
|
336
|
+
/**
|
|
337
|
+
* Shortest distance from a point to a single line segment a→b.
|
|
338
|
+
*/
|
|
339
|
+
declare function pointToSegmentDistance(point: Vector2Like, a: Vector2Like, b: Vector2Like): number;
|
|
340
|
+
/**
|
|
341
|
+
* Shortest distance from a point to a polyline.
|
|
342
|
+
*
|
|
343
|
+
* @param point The point to test.
|
|
344
|
+
* @param vertices Flat `[x0, y0, x1, y1, ...]` array of the polyline.
|
|
345
|
+
* @param closed When `true`, also considers the closing edge from the last vertex back
|
|
346
|
+
* to the first (use for closed paths, e.g. `z`/`Z` or `CurvePath.autoClose`).
|
|
347
|
+
*/
|
|
348
|
+
declare function pointToPolylineDistance(point: Vector2Like, vertices: number[], closed?: boolean): number;
|
|
349
|
+
|
|
311
350
|
declare function quadraticBezier(t: number, p0: number, p1: number, p2: number): number;
|
|
312
351
|
|
|
313
352
|
type LineCap = 'butt' | 'round' | 'square';
|
|
@@ -333,6 +372,14 @@ interface LineStyle {
|
|
|
333
372
|
}
|
|
334
373
|
declare function strokeTriangulate(points: number[], options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
335
374
|
|
|
375
|
+
interface IsPointInFillOptions {
|
|
376
|
+
fillRule?: FillRule;
|
|
377
|
+
}
|
|
378
|
+
interface IsPointInStrokeOptions {
|
|
379
|
+
strokeWidth?: number;
|
|
380
|
+
tolerance?: number;
|
|
381
|
+
closed?: boolean;
|
|
382
|
+
}
|
|
336
383
|
declare abstract class Curve {
|
|
337
384
|
arcLengthDivision: number;
|
|
338
385
|
protected _lengths: number[];
|
|
@@ -363,6 +410,32 @@ declare abstract class Curve {
|
|
|
363
410
|
max: Vector2;
|
|
364
411
|
};
|
|
365
412
|
getBoundingBox(): BoundingBox;
|
|
413
|
+
/**
|
|
414
|
+
* Test whether a point lies inside the area enclosed by this curve.
|
|
415
|
+
*
|
|
416
|
+
* The curve is sampled via {@link getAdaptiveVertices} into a single implicitly closed
|
|
417
|
+
* ring. This is purely geometric (it ignores any `fill`/`stroke` style), mirroring
|
|
418
|
+
* `CanvasRenderingContext2D.isPointInPath`.
|
|
419
|
+
*
|
|
420
|
+
* Composites that hold multiple sub-paths (e.g. {@link Path2D}) override this so holes
|
|
421
|
+
* are honored — a single `Curve` is always one ring.
|
|
422
|
+
*/
|
|
423
|
+
isPointInFill(point: Vector2Like, options?: IsPointInFillOptions): boolean;
|
|
424
|
+
/**
|
|
425
|
+
* Test whether a point lies on this curve's stroke, i.e. within `strokeWidth / 2 + tolerance`
|
|
426
|
+
* of the sampled outline. The point must be in the same coordinate space as the curve.
|
|
427
|
+
*
|
|
428
|
+
* Options: `strokeWidth` (path units, default `1`), `tolerance` (extra hit slack in path
|
|
429
|
+
* units, default `0` — useful for thin strokes; no coordinate scaling is assumed, so convert
|
|
430
|
+
* pixel tolerance to path units upstream if your path is normalized), and `closed` (whether
|
|
431
|
+
* to include the closing edge from the last vertex back to the first).
|
|
432
|
+
*/
|
|
433
|
+
isPointInStroke(point: Vector2Like, options?: IsPointInStrokeOptions): boolean;
|
|
434
|
+
/**
|
|
435
|
+
* Concise PathKit-style fill containment test: `contains(x, y)` is shorthand for
|
|
436
|
+
* {@link isPointInFill} with a `{ x, y }` point.
|
|
437
|
+
*/
|
|
438
|
+
contains(x: number, y: number, options?: IsPointInFillOptions): boolean;
|
|
366
439
|
getFillVertices(_options?: FillTriangulateOptions): number[];
|
|
367
440
|
fillTriangulate(options?: FillTriangulateOptions): FillTriangulatedResult;
|
|
368
441
|
strokeTriangulate(options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
@@ -559,6 +632,11 @@ declare class CurvePath extends CompositeCurve {
|
|
|
559
632
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
560
633
|
getAdaptiveVertices(output?: number[]): number[];
|
|
561
634
|
getFillVertices(options?: FillTriangulateOptions): number[];
|
|
635
|
+
/**
|
|
636
|
+
* Same as {@link Curve.isPointInStroke}, but `closed` defaults to this sub-path's actual
|
|
637
|
+
* closed-ness: explicitly `autoClose`, or geometrically closed (first vertex === last).
|
|
638
|
+
*/
|
|
639
|
+
isPointInStroke(point: Vector2Like, options?: IsPointInStrokeOptions): boolean;
|
|
562
640
|
protected _setCurrentPoint(point: Vector2Like): this;
|
|
563
641
|
protected _connetLineTo(curve: Curve): this;
|
|
564
642
|
closePath(): this;
|
|
@@ -617,6 +695,25 @@ declare class Path2D<T = any> extends CompositeCurve<CurvePath> {
|
|
|
617
695
|
skew(ax: number, ay?: number, target?: Vector2Like): this;
|
|
618
696
|
rotate(rad: number, target?: Vector2Like): this;
|
|
619
697
|
bold(b: number): this;
|
|
698
|
+
/**
|
|
699
|
+
* Test whether a point lies inside the filled area of this path.
|
|
700
|
+
*
|
|
701
|
+
* Each sub-path ({@link CurvePath}) is sampled into its own ring and all rings are
|
|
702
|
+
* evaluated together via {@link pointInPolygons}, so holes (donut / hollow shapes) are
|
|
703
|
+
* honored. This is purely geometric and ignores `style.fill` — for the `fill: 'none'`
|
|
704
|
+
* fallback, gate the call upstream (see {@link Path2DSet.hitTest}).
|
|
705
|
+
*
|
|
706
|
+
* Defaults `fillRule` to `style.fillRule`, then `'nonzero'` (matching SVG/Canvas).
|
|
707
|
+
*/
|
|
708
|
+
isPointInFill(point: Vector2Like, options?: IsPointInFillOptions): boolean;
|
|
709
|
+
/**
|
|
710
|
+
* Test whether a point lies on this path's stroke. A hit on any sub-path counts.
|
|
711
|
+
*
|
|
712
|
+
* Defaults `strokeWidth` to this path's own {@link strokeWidth} (which is `0` when
|
|
713
|
+
* `style.stroke` is `'none'`). Each sub-path infers its own closed-ness unless `closed`
|
|
714
|
+
* is given explicitly.
|
|
715
|
+
*/
|
|
716
|
+
isPointInStroke(point: Vector2Like, options?: IsPointInStrokeOptions): boolean;
|
|
620
717
|
getMinMax(min?: Vector2, max?: Vector2, withStyle?: boolean): {
|
|
621
718
|
min: Vector2;
|
|
622
719
|
max: Vector2;
|
|
@@ -641,6 +738,36 @@ declare class Path2DSet<T = any> {
|
|
|
641
738
|
paths: Path2D<T>[];
|
|
642
739
|
viewBox?: number[] | undefined;
|
|
643
740
|
constructor(paths?: Path2D<T>[], viewBox?: number[] | undefined);
|
|
741
|
+
/**
|
|
742
|
+
* Test whether a point lies inside the filled area of any path in this set.
|
|
743
|
+
* Purely geometric (ignores `fill: 'none'`); use {@link hitTest} for style-aware hits.
|
|
744
|
+
*/
|
|
745
|
+
isPointInFill(point: Vector2Like, options?: {
|
|
746
|
+
fillRule?: FillRule;
|
|
747
|
+
}): boolean;
|
|
748
|
+
/**
|
|
749
|
+
* Concise PathKit-style fill containment test across the whole set; shorthand for
|
|
750
|
+
* {@link isPointInFill} with a `{ x, y }` point.
|
|
751
|
+
*/
|
|
752
|
+
contains(x: number, y: number, options?: {
|
|
753
|
+
fillRule?: FillRule;
|
|
754
|
+
}): boolean;
|
|
755
|
+
/**
|
|
756
|
+
* Find the topmost path hit by a point, or `undefined` if none.
|
|
757
|
+
*
|
|
758
|
+
* Paths are tested top-to-bottom (last drawn first). For each path a fill hit is checked
|
|
759
|
+
* first (skipped when `style.fill` is `'none'`), then — if `stroke` is enabled — a stroke
|
|
760
|
+
* hit (skipped when `style.stroke` is `'none'`). This honors the "fill: none falls back to
|
|
761
|
+
* stroke" rule; the coordinate space of `point` must match the paths (no scaling assumed).
|
|
762
|
+
*
|
|
763
|
+
* Options: `stroke` (also test strokes, default `true`), `tolerance` (extra stroke hit slack
|
|
764
|
+
* in path units, default `0`), and `fillRule` (overrides each path's own fill rule).
|
|
765
|
+
*/
|
|
766
|
+
hitTest(point: Vector2Like, options?: {
|
|
767
|
+
stroke?: boolean;
|
|
768
|
+
tolerance?: number;
|
|
769
|
+
fillRule?: FillRule;
|
|
770
|
+
}): Path2D<T> | undefined;
|
|
644
771
|
getBoundingBox(withStyle?: boolean): BoundingBox | undefined;
|
|
645
772
|
toTriangulatedSvgString(result?: TriangulatedResult | TriangulatedResult[], padding?: number): string;
|
|
646
773
|
toTriangulatedSvg(result?: TriangulatedResult | TriangulatedResult[], padding?: number): SVGElement;
|
|
@@ -694,5 +821,5 @@ declare function svgToDom(svg: string | SVGElement): SVGElement;
|
|
|
694
821
|
|
|
695
822
|
declare function svgToPath2DSet(svg: string | SVGElement): Path2DSet;
|
|
696
823
|
|
|
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 };
|
|
824
|
+
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 };
|
|
825
|
+
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 };
|