@expofp/geometry 3.8.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 +139 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +42 -0
- package/dist/lib/angles.d.ts +36 -0
- package/dist/lib/angles.js +50 -0
- package/dist/lib/box.d.ts +282 -0
- package/dist/lib/box.js +362 -0
- package/dist/lib/geo.d.ts +98 -0
- package/dist/lib/geo.js +159 -0
- package/dist/lib/intersections.d.ts +30 -0
- package/dist/lib/intersections.js +72 -0
- package/dist/lib/line.d.ts +134 -0
- package/dist/lib/line.js +167 -0
- package/dist/lib/mesh.d.ts +166 -0
- package/dist/lib/mesh.js +162 -0
- package/dist/lib/point.d.ts +206 -0
- package/dist/lib/point.js +237 -0
- package/dist/lib/polygon.d.ts +169 -0
- package/dist/lib/polygon.js +220 -0
- package/dist/lib/rect.d.ts +200 -0
- package/dist/lib/rect.js +269 -0
- package/package.json +31 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { pointLerp } from './point.js';
|
|
2
|
+
import { rectCorners } from './rect.js';
|
|
3
|
+
/** Default tolerance for elevation comparison. */
|
|
4
|
+
const DEFAULT_ELEVATION_TOLERANCE = 1e-3;
|
|
5
|
+
/**
|
|
6
|
+
* Computes the crossing of lines `a` and `b` using the parametric form. Returns the crossing
|
|
7
|
+
* point plus flags indicating whether the crossing lies within each segment's `[0, 1]` parameter
|
|
8
|
+
* range. Returns `null` only when the lines are parallel (denominator is zero) or when both lines
|
|
9
|
+
* have a defined elevation and they differ by more than `elevationTolerance`.
|
|
10
|
+
* @param a - first line segment, defined by `p0` and `p1`
|
|
11
|
+
* @param b - second line segment, defined by `p0` and `p1`
|
|
12
|
+
* @param elevationTolerance - maximum elevation difference for a crossing to be reported; defaults to `1e-3`
|
|
13
|
+
* @returns `{ point, onLine1, onLine2 }`, or `null` when the lines are parallel or elevation-incompatible
|
|
14
|
+
*/
|
|
15
|
+
export function lineIntersection(a, b, elevationTolerance = DEFAULT_ELEVATION_TOLERANCE) {
|
|
16
|
+
if (a.elevation != null &&
|
|
17
|
+
b.elevation != null &&
|
|
18
|
+
Math.abs(a.elevation - b.elevation) > elevationTolerance) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const { x: x1, y: y1 } = a.p0, { x: x2, y: y2 } = a.p1;
|
|
22
|
+
const { x: x3, y: y3 } = b.p0, { x: x4, y: y4 } = b.p1;
|
|
23
|
+
const denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
|
|
24
|
+
if (denom === 0)
|
|
25
|
+
return null;
|
|
26
|
+
const t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / denom;
|
|
27
|
+
const u = ((x1 - x3) * (y1 - y2) - (y1 - y3) * (x1 - x2)) / denom;
|
|
28
|
+
const point = pointLerp(a.p0, a.p1, t);
|
|
29
|
+
point.z = a.elevation ?? b.elevation ?? 0;
|
|
30
|
+
return { point, onLine1: t >= 0 && t <= 1, onLine2: u >= 0 && u <= 1 };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Returns the intersection point of two line segments `a` and `b`, or `null` when the segments
|
|
34
|
+
* do not cross. See `lineIntersection` for the full crossing result (includes out-of-segment
|
|
35
|
+
* flags). See `intersectLineRect` for the higher-level helper.
|
|
36
|
+
* @param a - first segment, defined by `p0` and `p1`
|
|
37
|
+
* @param b - second segment, defined by `p0` and `p1`
|
|
38
|
+
* @param elevationTolerance - maximum elevation difference for a crossing to be reported; defaults to `1e-3`
|
|
39
|
+
* @returns the intersection {@link Point}, or `null` if the segments are parallel or non-crossing
|
|
40
|
+
*/
|
|
41
|
+
function segmentIntersection(a, b, elevationTolerance) {
|
|
42
|
+
const r = lineIntersection(a, b, elevationTolerance);
|
|
43
|
+
return r?.onLine1 && r.onLine2 ? r.point : null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Returns the points where a line segment crosses a rect's edges. Works for any `RectLike`,
|
|
47
|
+
* including a rotated rect or an unrotated `Box` (a `Box` satisfies `RectLike` and is treated
|
|
48
|
+
* as a rect with rotation 0). When both `line` and `rect` have a defined elevation that differs
|
|
49
|
+
* by more than `elevationTolerance`, returns an empty array.
|
|
50
|
+
* @param line - the segment, defined by `p0` and `p1`
|
|
51
|
+
* @param rect - the rect (possibly rotated; a `Box` is accepted as an unrotated rect)
|
|
52
|
+
* @param elevationTolerance - maximum elevation difference for a crossing to be reported; defaults to `1e-3`
|
|
53
|
+
* @returns the intersection points (0–2 for a convex rect)
|
|
54
|
+
*/
|
|
55
|
+
export function intersectLineRect(line, rect, elevationTolerance = DEFAULT_ELEVATION_TOLERANCE) {
|
|
56
|
+
if (line.elevation != null &&
|
|
57
|
+
rect.elevation != null &&
|
|
58
|
+
Math.abs(line.elevation - rect.elevation) > elevationTolerance) {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
const resultZ = line.elevation ?? rect.elevation ?? 0;
|
|
62
|
+
const corners = rectCorners(rect);
|
|
63
|
+
const hits = [];
|
|
64
|
+
for (let i = 0; i < 4; i++) {
|
|
65
|
+
const hit = segmentIntersection(line, { p0: corners[i], p1: corners[(i + 1) % 4] }, elevationTolerance);
|
|
66
|
+
if (hit) {
|
|
67
|
+
hit.z = resultZ;
|
|
68
|
+
hits.push(hit);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return hits;
|
|
72
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Point, type Point2Like } from './point.js';
|
|
2
|
+
import type { RectLike } from './rect.js';
|
|
3
|
+
/** Structural line segment with 2D endpoints and an optional planar elevation. */
|
|
4
|
+
export interface LineLike {
|
|
5
|
+
/** Start point (2D). */
|
|
6
|
+
readonly p0: Point2Like;
|
|
7
|
+
/** End point (2D). */
|
|
8
|
+
readonly p1: Point2Like;
|
|
9
|
+
/** Planar elevation (z). When absent the segment is treated as elevation-agnostic (matches any). */
|
|
10
|
+
readonly elevation?: number;
|
|
11
|
+
}
|
|
12
|
+
/** A line segment between two 2D points at a given elevation. */
|
|
13
|
+
export declare class Line {
|
|
14
|
+
/** Marker so callers can narrow the type at runtime. */
|
|
15
|
+
readonly isLine = true;
|
|
16
|
+
/** Internal mutable start point (2D). */
|
|
17
|
+
private _p0;
|
|
18
|
+
/** Internal mutable end point (2D). */
|
|
19
|
+
private _p1;
|
|
20
|
+
/** Internal mutable elevation (z). */
|
|
21
|
+
private _elevation;
|
|
22
|
+
/**
|
|
23
|
+
* @param p0 - start point (2D)
|
|
24
|
+
* @param p1 - end point (2D)
|
|
25
|
+
* @param elevation - planar elevation (z); defaults to 0
|
|
26
|
+
*/
|
|
27
|
+
constructor(p0: Point2Like, p1: Point2Like, elevation?: number);
|
|
28
|
+
/**
|
|
29
|
+
* Start point (2D).
|
|
30
|
+
* @returns a readonly `{ x, y }` view of the start point
|
|
31
|
+
*/
|
|
32
|
+
get p0(): Readonly<Point2Like>;
|
|
33
|
+
/**
|
|
34
|
+
* End point (2D).
|
|
35
|
+
* @returns a readonly `{ x, y }` view of the end point
|
|
36
|
+
*/
|
|
37
|
+
get p1(): Readonly<Point2Like>;
|
|
38
|
+
/**
|
|
39
|
+
* Planar elevation (z coordinate of the segment's plane).
|
|
40
|
+
* @returns the current elevation
|
|
41
|
+
*/
|
|
42
|
+
get elevation(): number;
|
|
43
|
+
/**
|
|
44
|
+
* Mutates this segment in place, replacing p0, p1, and optionally elevation. When `elevation`
|
|
45
|
+
* is omitted the current elevation is preserved. Prefer the constructor for one-off segments;
|
|
46
|
+
* use this only for hot-path reuse.
|
|
47
|
+
* @param p0 - new start point (2D); stored as a fresh `{ x, y }` copy
|
|
48
|
+
* @param p1 - new end point (2D); stored as a fresh `{ x, y }` copy
|
|
49
|
+
* @param elevation - new elevation; defaults to the current elevation when omitted
|
|
50
|
+
* @returns `this`
|
|
51
|
+
*/
|
|
52
|
+
set(p0: Point2Like, p1: Point2Like, elevation?: number): this;
|
|
53
|
+
/**
|
|
54
|
+
* Length of this segment.
|
|
55
|
+
* @returns the distance between p0 and p1
|
|
56
|
+
*/
|
|
57
|
+
length(): number;
|
|
58
|
+
/**
|
|
59
|
+
* Midpoint of this segment.
|
|
60
|
+
* @param target - optional point to write into; defaults to a new {@link Point}
|
|
61
|
+
* @returns the midpoint
|
|
62
|
+
*/
|
|
63
|
+
center(target?: Point): Point;
|
|
64
|
+
/**
|
|
65
|
+
* Direction of this segment in radians.
|
|
66
|
+
* @returns the angle in radians
|
|
67
|
+
*/
|
|
68
|
+
angle(): number;
|
|
69
|
+
/**
|
|
70
|
+
* Points where this line crosses `rect`.
|
|
71
|
+
* @param rect - the rect (possibly rotated; a `Box` is accepted as an unrotated rect)
|
|
72
|
+
* @param elevationTolerance - maximum elevation difference for a crossing to be reported; defaults to `1e-3`
|
|
73
|
+
* @returns the intersection points
|
|
74
|
+
*/
|
|
75
|
+
intersectRect(rect: RectLike, elevationTolerance?: number): Point[];
|
|
76
|
+
/**
|
|
77
|
+
* Nearest point on this segment to `point`, with parameter and distance.
|
|
78
|
+
* @param point - the point to project onto this segment
|
|
79
|
+
* @param target - optional point to write the projected position into; defaults to a new {@link Point}
|
|
80
|
+
* @returns `{ projected, t, distance }`
|
|
81
|
+
*/
|
|
82
|
+
projectPoint(point: Point2Like, target?: Point): {
|
|
83
|
+
projected: Point;
|
|
84
|
+
t: number;
|
|
85
|
+
distance: number;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Intersection with another segment `other` on the infinite lines.
|
|
89
|
+
* @param other - the other segment
|
|
90
|
+
* @param elevationTolerance - maximum elevation difference for a crossing to be reported; defaults to `1e-3`
|
|
91
|
+
* @returns the crossing data, or `null` when the lines are parallel or elevations are incompatible
|
|
92
|
+
*/
|
|
93
|
+
intersect(other: LineLike, elevationTolerance?: number): {
|
|
94
|
+
point: Point;
|
|
95
|
+
onLine1: boolean;
|
|
96
|
+
onLine2: boolean;
|
|
97
|
+
} | null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Euclidean length of a line segment.
|
|
101
|
+
* @param line the segment
|
|
102
|
+
* @returns the distance between `line.p0` and `line.p1`
|
|
103
|
+
*/
|
|
104
|
+
export declare function lineLength(line: LineLike): number;
|
|
105
|
+
/**
|
|
106
|
+
* Midpoint of a line segment.
|
|
107
|
+
* @param line the segment
|
|
108
|
+
* @param target optional point to write into; defaults to a new {@link Point}
|
|
109
|
+
* @returns the midpoint
|
|
110
|
+
*/
|
|
111
|
+
export declare function lineCenter(line: LineLike, target?: Point): Point;
|
|
112
|
+
/**
|
|
113
|
+
* Direction of the segment p0→p1 in radians.
|
|
114
|
+
* @param p0 start point
|
|
115
|
+
* @param p1 end point
|
|
116
|
+
* @returns the angle in radians
|
|
117
|
+
*/
|
|
118
|
+
export declare function lineAngle(p0: Point2Like, p1: Point2Like): number;
|
|
119
|
+
/**
|
|
120
|
+
* Projects `point` onto the nearest position on segment `line`, returning the projected point,
|
|
121
|
+
* the normalized parameter `t` (clamped to `[0, 1]`), and the distance from `point` to the
|
|
122
|
+
* projection. For a zero-length segment, `t` is `0`, the projected point equals `line.p0`, and
|
|
123
|
+
* the distance is the distance from `point` to `p0`.
|
|
124
|
+
* @param line - the segment to project onto
|
|
125
|
+
* @param point - the point to project
|
|
126
|
+
* @param target - optional point to write the projected position into; defaults to a new {@link Point}
|
|
127
|
+
* @returns `{ projected, t, distance }` where `t ∈ [0, 1]`
|
|
128
|
+
*/
|
|
129
|
+
export declare function lineProjectPoint(line: LineLike, point: Point2Like, target?: Point): {
|
|
130
|
+
projected: Point;
|
|
131
|
+
t: number;
|
|
132
|
+
distance: number;
|
|
133
|
+
};
|
|
134
|
+
//# sourceMappingURL=line.d.ts.map
|
package/dist/lib/line.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { intersectLineRect, lineIntersection } from './intersections.js';
|
|
2
|
+
import { Point, pointDistance, pointLerp } from './point.js';
|
|
3
|
+
/** A line segment between two 2D points at a given elevation. */
|
|
4
|
+
export class Line {
|
|
5
|
+
/** Marker so callers can narrow the type at runtime. */
|
|
6
|
+
isLine = true;
|
|
7
|
+
/** Internal mutable start point (2D). */
|
|
8
|
+
_p0;
|
|
9
|
+
/** Internal mutable end point (2D). */
|
|
10
|
+
_p1;
|
|
11
|
+
/** Internal mutable elevation (z). */
|
|
12
|
+
_elevation;
|
|
13
|
+
/**
|
|
14
|
+
* @param p0 - start point (2D)
|
|
15
|
+
* @param p1 - end point (2D)
|
|
16
|
+
* @param elevation - planar elevation (z); defaults to 0
|
|
17
|
+
*/
|
|
18
|
+
constructor(p0, p1, elevation = 0) {
|
|
19
|
+
this._p0 = { x: p0.x, y: p0.y };
|
|
20
|
+
this._p1 = { x: p1.x, y: p1.y };
|
|
21
|
+
this._elevation = elevation;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Start point (2D).
|
|
25
|
+
* @returns a readonly `{ x, y }` view of the start point
|
|
26
|
+
*/
|
|
27
|
+
get p0() {
|
|
28
|
+
return this._p0;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* End point (2D).
|
|
32
|
+
* @returns a readonly `{ x, y }` view of the end point
|
|
33
|
+
*/
|
|
34
|
+
get p1() {
|
|
35
|
+
return this._p1;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Planar elevation (z coordinate of the segment's plane).
|
|
39
|
+
* @returns the current elevation
|
|
40
|
+
*/
|
|
41
|
+
get elevation() {
|
|
42
|
+
return this._elevation;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Mutates this segment in place, replacing p0, p1, and optionally elevation. When `elevation`
|
|
46
|
+
* is omitted the current elevation is preserved. Prefer the constructor for one-off segments;
|
|
47
|
+
* use this only for hot-path reuse.
|
|
48
|
+
* @param p0 - new start point (2D); stored as a fresh `{ x, y }` copy
|
|
49
|
+
* @param p1 - new end point (2D); stored as a fresh `{ x, y }` copy
|
|
50
|
+
* @param elevation - new elevation; defaults to the current elevation when omitted
|
|
51
|
+
* @returns `this`
|
|
52
|
+
*/
|
|
53
|
+
set(p0, p1, elevation = this._elevation) {
|
|
54
|
+
this._p0 = { x: p0.x, y: p0.y };
|
|
55
|
+
this._p1 = { x: p1.x, y: p1.y };
|
|
56
|
+
this._elevation = elevation;
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Length of this segment.
|
|
61
|
+
* @returns the distance between p0 and p1
|
|
62
|
+
*/
|
|
63
|
+
length() {
|
|
64
|
+
return lineLength(this);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Midpoint of this segment.
|
|
68
|
+
* @param target - optional point to write into; defaults to a new {@link Point}
|
|
69
|
+
* @returns the midpoint
|
|
70
|
+
*/
|
|
71
|
+
center(target) {
|
|
72
|
+
return lineCenter(this, target);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Direction of this segment in radians.
|
|
76
|
+
* @returns the angle in radians
|
|
77
|
+
*/
|
|
78
|
+
angle() {
|
|
79
|
+
return lineAngle(this.p0, this.p1);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Points where this line crosses `rect`.
|
|
83
|
+
* @param rect - the rect (possibly rotated; a `Box` is accepted as an unrotated rect)
|
|
84
|
+
* @param elevationTolerance - maximum elevation difference for a crossing to be reported; defaults to `1e-3`
|
|
85
|
+
* @returns the intersection points
|
|
86
|
+
*/
|
|
87
|
+
intersectRect(rect, elevationTolerance) {
|
|
88
|
+
return intersectLineRect(this, rect, elevationTolerance);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Nearest point on this segment to `point`, with parameter and distance.
|
|
92
|
+
* @param point - the point to project onto this segment
|
|
93
|
+
* @param target - optional point to write the projected position into; defaults to a new {@link Point}
|
|
94
|
+
* @returns `{ projected, t, distance }`
|
|
95
|
+
*/
|
|
96
|
+
projectPoint(point, target) {
|
|
97
|
+
return lineProjectPoint(this, point, target);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Intersection with another segment `other` on the infinite lines.
|
|
101
|
+
* @param other - the other segment
|
|
102
|
+
* @param elevationTolerance - maximum elevation difference for a crossing to be reported; defaults to `1e-3`
|
|
103
|
+
* @returns the crossing data, or `null` when the lines are parallel or elevations are incompatible
|
|
104
|
+
*/
|
|
105
|
+
intersect(other, elevationTolerance) {
|
|
106
|
+
return lineIntersection(this, other, elevationTolerance);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Euclidean length of a line segment.
|
|
111
|
+
* @param line the segment
|
|
112
|
+
* @returns the distance between `line.p0` and `line.p1`
|
|
113
|
+
*/
|
|
114
|
+
export function lineLength(line) {
|
|
115
|
+
return pointDistance(line.p0, line.p1);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Midpoint of a line segment.
|
|
119
|
+
* @param line the segment
|
|
120
|
+
* @param target optional point to write into; defaults to a new {@link Point}
|
|
121
|
+
* @returns the midpoint
|
|
122
|
+
*/
|
|
123
|
+
export function lineCenter(line, target) {
|
|
124
|
+
return pointLerp(line.p0, line.p1, 0.5, target);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Direction of the segment p0→p1 in radians.
|
|
128
|
+
* @param p0 start point
|
|
129
|
+
* @param p1 end point
|
|
130
|
+
* @returns the angle in radians
|
|
131
|
+
*/
|
|
132
|
+
export function lineAngle(p0, p1) {
|
|
133
|
+
return Math.atan2(p1.y - p0.y, p1.x - p0.x);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Projects `point` onto the nearest position on segment `line`, returning the projected point,
|
|
137
|
+
* the normalized parameter `t` (clamped to `[0, 1]`), and the distance from `point` to the
|
|
138
|
+
* projection. For a zero-length segment, `t` is `0`, the projected point equals `line.p0`, and
|
|
139
|
+
* the distance is the distance from `point` to `p0`.
|
|
140
|
+
* @param line - the segment to project onto
|
|
141
|
+
* @param point - the point to project
|
|
142
|
+
* @param target - optional point to write the projected position into; defaults to a new {@link Point}
|
|
143
|
+
* @returns `{ projected, t, distance }` where `t ∈ [0, 1]`
|
|
144
|
+
*/
|
|
145
|
+
export function lineProjectPoint(line, point, target) {
|
|
146
|
+
// Read inputs to locals — alias-safe even if `target` overlaps with `line` points.
|
|
147
|
+
const p0x = line.p0.x, p0y = line.p0.y;
|
|
148
|
+
const p1x = line.p1.x, p1y = line.p1.y;
|
|
149
|
+
const px = point.x, py = point.y;
|
|
150
|
+
const dx = p1x - p0x, dy = p1y - p0y;
|
|
151
|
+
const lenSq = dx * dx + dy * dy;
|
|
152
|
+
let t;
|
|
153
|
+
if (lenSq === 0) {
|
|
154
|
+
t = 0;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const dot = (px - p0x) * dx + (py - p0y) * dy;
|
|
158
|
+
t = dot / lenSq;
|
|
159
|
+
t = t < 0 ? 0 : t > 1 ? 1 : t;
|
|
160
|
+
}
|
|
161
|
+
// Inline the lerp (avoid two transient {x,y} allocations on this hot path); `target` may alias an
|
|
162
|
+
// input, but all coords were copied to locals above. The distance uses the saved px/py snapshot so it
|
|
163
|
+
// stays correct even when `target === point`.
|
|
164
|
+
const projected = (target ?? new Point()).set(p0x + dx * t, p0y + dy * t, line.elevation ?? 0);
|
|
165
|
+
const distance = pointDistance({ x: px, y: py }, projected);
|
|
166
|
+
return { projected, t, distance };
|
|
167
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { Box } from './box.js';
|
|
2
|
+
import { Point, type Point2Like, type PointLike } from './point.js';
|
|
3
|
+
import type { Polygon } from './polygon.js';
|
|
4
|
+
/** A triplet of vertex indices forming a triangle. */
|
|
5
|
+
export type TriangleIndex = readonly [number, number, number];
|
|
6
|
+
/** Structural mesh: vertices plus triangle indices. */
|
|
7
|
+
export interface MeshLike {
|
|
8
|
+
/** Mesh vertices (may carry a z coordinate). */
|
|
9
|
+
readonly vertices: readonly PointLike[];
|
|
10
|
+
/** Triangle index triplets. */
|
|
11
|
+
readonly indices: readonly TriangleIndex[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A 3D triangle mesh: vertices carry an optional z coordinate, plus triangle index triplets.
|
|
15
|
+
* Immutable value object: readonly getters; transforms return a new instance unless a `target`
|
|
16
|
+
* is passed. For a planar triangulated polygon with area/containment use `Polygon` instead.
|
|
17
|
+
*/
|
|
18
|
+
export declare class Mesh {
|
|
19
|
+
/** Marker so callers can narrow the type at runtime. */
|
|
20
|
+
readonly isMesh = true;
|
|
21
|
+
/** Internal mutable vertex array (3D). */
|
|
22
|
+
private _vertices;
|
|
23
|
+
/** Internal triangle index array. */
|
|
24
|
+
private _indices;
|
|
25
|
+
/** Cached axis-aligned bounding box (xy only). */
|
|
26
|
+
private _bounds;
|
|
27
|
+
/**
|
|
28
|
+
* Constructs a mesh from a vertex list and triangle index triplets.
|
|
29
|
+
* @param vertices - source vertices; each is cloned into a {@link Point} (default `[]`)
|
|
30
|
+
* @param indices - triangle index triplets referencing positions in `vertices` (default `[]`)
|
|
31
|
+
*/
|
|
32
|
+
constructor(vertices?: readonly PointLike[], indices?: readonly TriangleIndex[]);
|
|
33
|
+
/**
|
|
34
|
+
* Readonly array of mesh vertices as {@link Point} instances.
|
|
35
|
+
* @returns the vertex array
|
|
36
|
+
*/
|
|
37
|
+
get vertices(): readonly Point[];
|
|
38
|
+
/**
|
|
39
|
+
* Readonly array of triangle index triplets.
|
|
40
|
+
* @returns the index array
|
|
41
|
+
*/
|
|
42
|
+
get indices(): readonly TriangleIndex[];
|
|
43
|
+
/**
|
|
44
|
+
* Cached axis-aligned bounding {@link Box} of this mesh (xy only, z ignored).
|
|
45
|
+
* @returns the bounding box
|
|
46
|
+
*/
|
|
47
|
+
get bounds(): Box;
|
|
48
|
+
/**
|
|
49
|
+
* Mutates this mesh in place, replacing vertices/indices and refreshing the cached bounds.
|
|
50
|
+
* Vertices are copied into fresh {@link Point}s — do not optimize this clone away; transform
|
|
51
|
+
* free functions rely on it to avoid aliasing shared vertices. Use only for hot-path reuse.
|
|
52
|
+
* @param vertices - new vertex list
|
|
53
|
+
* @param indices - new triangle index list
|
|
54
|
+
* @returns `this`
|
|
55
|
+
*/
|
|
56
|
+
set(vertices: readonly PointLike[], indices: readonly TriangleIndex[]): this;
|
|
57
|
+
/**
|
|
58
|
+
* Merges two or more meshes into a single {@link Mesh}, offsetting each mesh's triangle indices
|
|
59
|
+
* by the cumulative vertex count so they remain valid. Forwards to {@link meshMerge}.
|
|
60
|
+
* @param meshes - meshes to merge
|
|
61
|
+
* @returns a new merged mesh
|
|
62
|
+
*/
|
|
63
|
+
static merge(...meshes: MeshLike[]): Mesh;
|
|
64
|
+
/**
|
|
65
|
+
* Returns a new mesh translated by `offset`. Forwards to {@link meshTranslate}.
|
|
66
|
+
* @param offset - translation vector
|
|
67
|
+
* @param target - optional mesh to write into instead of allocating a new one
|
|
68
|
+
* @returns translated mesh
|
|
69
|
+
*/
|
|
70
|
+
translate(offset: PointLike, target?: Mesh): Mesh;
|
|
71
|
+
/**
|
|
72
|
+
* Returns a new mesh scaled by `factor` about `origin`. Forwards to {@link meshScale}.
|
|
73
|
+
* @param factor - uniform scale or per-axis `{ x, y }` scale
|
|
74
|
+
* @param origin - the fixed point of the scaling; defaults to the bounding-box center
|
|
75
|
+
* @param target - optional mesh to write into instead of allocating a new one
|
|
76
|
+
* @returns scaled mesh
|
|
77
|
+
*/
|
|
78
|
+
scale(factor: number | Point2Like, origin?: Point2Like, target?: Mesh): Mesh;
|
|
79
|
+
/**
|
|
80
|
+
* Returns a new mesh rotated by `angle` radians about `origin`. Forwards to {@link meshRotate}.
|
|
81
|
+
* @param angle - rotation angle in radians (positive = clockwise in y-down space)
|
|
82
|
+
* @param origin - the pivot of the rotation; defaults to the bounding-box center
|
|
83
|
+
* @param target - optional mesh to write into instead of allocating a new one
|
|
84
|
+
* @returns rotated mesh
|
|
85
|
+
*/
|
|
86
|
+
rotate(angle: number, origin?: Point2Like, target?: Mesh): Mesh;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Computes the axis-aligned bounding {@link Box} of a mesh by sweeping all vertex xy coordinates.
|
|
90
|
+
* The z component is ignored — bounds are always in the xy plane.
|
|
91
|
+
* @param m - mesh or mesh-like object
|
|
92
|
+
* @returns the bounding box
|
|
93
|
+
*/
|
|
94
|
+
export declare function meshBounds(m: MeshLike): Box;
|
|
95
|
+
/**
|
|
96
|
+
* Merges two or more meshes into a single mesh, offsetting each mesh's triangle indices by the
|
|
97
|
+
* cumulative vertex count so they remain valid. When `target` is provided the result is written
|
|
98
|
+
* into it, preserving the target's concrete type (e.g. a `Polygon` target stays a `Polygon`).
|
|
99
|
+
* @param meshes - meshes to merge
|
|
100
|
+
* @param target - mesh to write into; receives the merged vertices and indices
|
|
101
|
+
* @returns `target` with the merged data
|
|
102
|
+
*/
|
|
103
|
+
export declare function meshMerge<T extends Mesh | Polygon>(meshes: readonly MeshLike[], target: T): T;
|
|
104
|
+
/**
|
|
105
|
+
* Merges two or more meshes into a single new {@link Mesh}, offsetting each mesh's triangle
|
|
106
|
+
* indices by the cumulative vertex count so they remain valid.
|
|
107
|
+
* @param meshes - meshes to merge
|
|
108
|
+
* @returns a new merged mesh
|
|
109
|
+
*/
|
|
110
|
+
export declare function meshMerge(meshes: readonly MeshLike[]): Mesh;
|
|
111
|
+
/**
|
|
112
|
+
* Returns a new mesh whose vertices are translated by `offset`. Writes into `target` when
|
|
113
|
+
* provided, preserving the target's concrete type (e.g. a `Polygon` target stays a `Polygon`).
|
|
114
|
+
* @param m - source mesh
|
|
115
|
+
* @param offset - translation vector; `z` defaults to 0
|
|
116
|
+
* @param target - mesh to write into; receives the translated vertices in place
|
|
117
|
+
* @returns `target` with updated vertices
|
|
118
|
+
*/
|
|
119
|
+
export declare function meshTranslate<T extends Mesh | Polygon>(m: MeshLike, offset: PointLike, target: T): T;
|
|
120
|
+
/**
|
|
121
|
+
* Returns a new {@link Mesh} whose vertices are translated by `offset`. Does not mutate `m`.
|
|
122
|
+
* @param m - source mesh
|
|
123
|
+
* @param offset - translation vector; `z` defaults to 0
|
|
124
|
+
* @returns new translated mesh
|
|
125
|
+
*/
|
|
126
|
+
export declare function meshTranslate(m: MeshLike, offset: PointLike): Mesh;
|
|
127
|
+
/**
|
|
128
|
+
* Returns a new mesh whose vertices are scaled by `factor` about `origin`. The xy coordinates
|
|
129
|
+
* are scaled; z is preserved unchanged. Writes into `target` when provided.
|
|
130
|
+
* @param m - source mesh
|
|
131
|
+
* @param factor - uniform scale or per-axis `{ x, y }` scale
|
|
132
|
+
* @param origin - the fixed point of the scaling; defaults to the mesh's bounding-box center
|
|
133
|
+
* @param target - mesh to write into; receives the scaled vertices in place
|
|
134
|
+
* @returns `target` with updated vertices
|
|
135
|
+
*/
|
|
136
|
+
export declare function meshScale<T extends Mesh | Polygon>(m: MeshLike, factor: number | Point2Like, origin: Point2Like, target: T): T;
|
|
137
|
+
/**
|
|
138
|
+
* Returns a new {@link Mesh} whose vertices are scaled by `factor` about `origin`. Does not
|
|
139
|
+
* mutate `m`.
|
|
140
|
+
* @param m - source mesh
|
|
141
|
+
* @param factor - uniform scale or per-axis `{ x, y }` scale
|
|
142
|
+
* @param origin - the fixed point of the scaling; defaults to the mesh's bounding-box center
|
|
143
|
+
* @returns new scaled mesh
|
|
144
|
+
*/
|
|
145
|
+
export declare function meshScale(m: MeshLike, factor: number | Point2Like, origin?: Point2Like): Mesh;
|
|
146
|
+
/**
|
|
147
|
+
* Returns a new mesh whose vertices are rotated by `angle` radians about `origin`. The xy
|
|
148
|
+
* coordinates are rotated; z is preserved unchanged. Positive angles rotate clockwise in
|
|
149
|
+
* y-down coordinate space. Writes into `target` when provided.
|
|
150
|
+
* @param m - source mesh
|
|
151
|
+
* @param angle - rotation angle in radians (positive = clockwise in y-down space)
|
|
152
|
+
* @param origin - the pivot of the rotation; defaults to the mesh's bounding-box center
|
|
153
|
+
* @param target - mesh to write into; receives the rotated vertices in place
|
|
154
|
+
* @returns `target` with updated vertices
|
|
155
|
+
*/
|
|
156
|
+
export declare function meshRotate<T extends Mesh | Polygon>(m: MeshLike, angle: number, origin: Point2Like, target: T): T;
|
|
157
|
+
/**
|
|
158
|
+
* Returns a new {@link Mesh} whose vertices are rotated by `angle` radians about `origin`. Does
|
|
159
|
+
* not mutate `m`.
|
|
160
|
+
* @param m - source mesh
|
|
161
|
+
* @param angle - rotation angle in radians (positive = clockwise in y-down space)
|
|
162
|
+
* @param origin - the pivot of the rotation; defaults to the mesh's bounding-box center
|
|
163
|
+
* @returns new rotated mesh
|
|
164
|
+
*/
|
|
165
|
+
export declare function meshRotate(m: MeshLike, angle: number, origin?: Point2Like): Mesh;
|
|
166
|
+
//# sourceMappingURL=mesh.d.ts.map
|