@navaramap/three-api 0.1.1 → 0.2.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/LICENSE +1 -1
- package/dist/featureGeometry.d.ts +82 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +131 -51
- package/dist/index.umd.cjs +1 -1
- package/package.json +5 -5
- package/src/featureGeometry.ts +255 -0
- package/src/index.ts +19 -0
package/LICENSE
CHANGED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { NormalizeWASMClass } from '@navaramap/core';
|
|
2
|
+
import { PolygonMaterial, PolylineMaterial } from '@navaramap/engine-api';
|
|
3
|
+
/**
|
|
4
|
+
* Geometry builders for standalone polygon and polyline meshes, using the
|
|
5
|
+
* vector layer's construction. Positions are RTE-encoded.
|
|
6
|
+
*/
|
|
7
|
+
/** A polygon layer material, as a plain object. */
|
|
8
|
+
export type PolygonGeometryMaterial = NormalizeWASMClass<PolygonMaterial>;
|
|
9
|
+
/** A polyline layer material, as a plain object. */
|
|
10
|
+
export type PolylineGeometryMaterial = NormalizeWASMClass<PolylineMaterial>;
|
|
11
|
+
/** A geographic bounding box, in degrees. */
|
|
12
|
+
export type GeographicExtent = {
|
|
13
|
+
west: number;
|
|
14
|
+
south: number;
|
|
15
|
+
east: number;
|
|
16
|
+
north: number;
|
|
17
|
+
};
|
|
18
|
+
export type PolygonGeometryData = {
|
|
19
|
+
positionHigh: Float32Array;
|
|
20
|
+
positionLow: Float32Array;
|
|
21
|
+
/** Absent for a `clampToGround` polygon. */
|
|
22
|
+
normal?: Float32Array;
|
|
23
|
+
/** `xyz` = extrusion direction, `w` = 0 on the bottom cap, 1 on the top. */
|
|
24
|
+
scaleNormalAndCap: Float32Array;
|
|
25
|
+
indices: Uint32Array;
|
|
26
|
+
extent: GeographicExtent;
|
|
27
|
+
};
|
|
28
|
+
export type PolylineGeometryData = {
|
|
29
|
+
position: Float32Array;
|
|
30
|
+
positionHigh: Float32Array;
|
|
31
|
+
positionLow: Float32Array;
|
|
32
|
+
startHigh: Float32Array;
|
|
33
|
+
startLow: Float32Array;
|
|
34
|
+
endHigh: Float32Array;
|
|
35
|
+
endLow: Float32Array;
|
|
36
|
+
startNormal: Float32Array;
|
|
37
|
+
endNormalAndTextureCoordinateNormalizationX: Float32Array;
|
|
38
|
+
rightNormalAndTextureCoordinateNormalizationY: Float32Array;
|
|
39
|
+
indices: Uint32Array;
|
|
40
|
+
extent: GeographicExtent;
|
|
41
|
+
};
|
|
42
|
+
/** Flat `[lng, lat, height, ...]`, or ECEF `[x, y, z, ...]` when geocentric. */
|
|
43
|
+
export type GeometryRing = Float64Array;
|
|
44
|
+
/**
|
|
45
|
+
* Builds the geometry of one standalone polygon.
|
|
46
|
+
*
|
|
47
|
+
* @param rings - Outer ring first, then holes.
|
|
48
|
+
* @param geocentric - Read the positions as ECEF metres.
|
|
49
|
+
* @param material - A `polygon` layer material. Outline options are ignored.
|
|
50
|
+
* @throws When `material` does not deserialize.
|
|
51
|
+
* @returns `undefined` when the outer ring has fewer than three vertices or is
|
|
52
|
+
* collinear.
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildPolygonGeometry(rings: readonly GeometryRing[], geocentric: boolean, material: PolygonGeometryMaterial): PolygonGeometryData | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Builds the geometry of one standalone polyline.
|
|
57
|
+
*
|
|
58
|
+
* @param positions - Flat `[lng, lat, height, ...]`, or ECEF when `geocentric`.
|
|
59
|
+
* @param geocentric - Read the positions as ECEF metres.
|
|
60
|
+
* @param ring - Join a repeated first vertex as a seam instead of two caps.
|
|
61
|
+
* @param material - A `polyline` layer material.
|
|
62
|
+
* @throws When `material` does not deserialize.
|
|
63
|
+
* @returns `undefined` when fewer than two distinct positions remain.
|
|
64
|
+
*/
|
|
65
|
+
export declare function buildPolylineGeometry(positions: Float64Array, geocentric: boolean, ring: boolean, material: PolylineGeometryMaterial): PolylineGeometryData | undefined;
|
|
66
|
+
/** A height range in metres, relative to the ellipsoid. */
|
|
67
|
+
export type HeightRange = {
|
|
68
|
+
min: number;
|
|
69
|
+
max: number;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* `[min, max]` height a clamp-to-ground polygon volume over `extent` must
|
|
73
|
+
* span to enclose the ground heights `range`, given the flat cap triangles
|
|
74
|
+
* {@link buildPolygonGeometry} produces.
|
|
75
|
+
*/
|
|
76
|
+
export declare function polygonGroundVolume(range: HeightRange, extent: GeographicExtent): [number, number];
|
|
77
|
+
/**
|
|
78
|
+
* `[min, max]` height a clamp-to-ground polyline volume over `extent` must
|
|
79
|
+
* span to enclose the ground heights `range`, given the straight segments
|
|
80
|
+
* {@link buildPolylineGeometry} produces.
|
|
81
|
+
*/
|
|
82
|
+
export declare function polylineGroundVolume(range: HeightRange, extent: GeographicExtent): [number, number];
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { GeodeticPlacement } from './frames';
|
|
|
4
4
|
export type { LatLngHeight, LatLng } from '@navaramap/core';
|
|
5
5
|
export type { Window, Transform, CameraFrustum, Plane, Ray, Vec2, Vec3, } from '@navaramap/core';
|
|
6
6
|
export type { GeodeticPlacement } from './frames';
|
|
7
|
+
export * from './featureGeometry';
|
|
7
8
|
export * from './intersection';
|
|
8
9
|
export * from './rte';
|
|
9
10
|
export * from './ellipsoidGeodesic';
|
|
@@ -49,6 +50,14 @@ export declare function convertScreenToWorld(windowObject: WindowObject, camera:
|
|
|
49
50
|
* @returns Unit normal vector pointing outward from the ellipsoid surface
|
|
50
51
|
*/
|
|
51
52
|
export declare function geodeticSurfaceNormal(lle: LatLngHeight): Vector3;
|
|
53
|
+
/**
|
|
54
|
+
* Projects a Cartesian position onto the WGS84 ellipsoid surface along the
|
|
55
|
+
* geodetic normal.
|
|
56
|
+
* @param xyz - Cartesian Vector3 in Earth-Centered Earth-Fixed (ECEF) coordinates
|
|
57
|
+
* @returns The surface position in ECEF coordinates, or undefined when the
|
|
58
|
+
* position is too close to the ellipsoid's center to project
|
|
59
|
+
*/
|
|
60
|
+
export declare function scaleToGeodeticSurface(xyz: Vector3): Vector3 | undefined;
|
|
52
61
|
/**
|
|
53
62
|
* Creates a local East-North-Up (ENU) reference frame transformation matrix at a position.
|
|
54
63
|
* @param origin - Origin position in ECEF coordinates
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import e, { CameraFrustum as t, EllipsoidGeodesic as n, LLE as r, Ray as i, Transform as a, Vec2 as o, Vec3 as s, Window as c, angleToDegree as l, angleToRadian as u,
|
|
1
|
+
import e, { CameraFrustum as t, EllipsoidGeodesic as n, LLE as r, Ray as i, Transform as a, Vec2 as o, Vec3 as s, Window as c, angleToDegree as l, angleToRadian as u, buildPolygonGeometry as d, buildPolylineGeometry as f, eastNorthUpToFixedFrame as p, encodePosition as m, geodeticSurfaceNormal as h, geodeticToXyz as g, getHeightFromEllipsoid as _, getPickRay as v, getPlaneFromPointNormal as y, getRayPlaneIntersection as b, getWGS84Eccentricity as ee, getWGS84EccentricitySquared as te, getWGS84Flattening as ne, getWGS84SemiMajorAxis as re, getWGS84SemiMinorAxis as ie, northEastDownToFixedFrame as ae, northUpEastToFixedFrame as oe, northWestUpToFixedFrame as x, polygonGroundVolume as S, polylineGroundVolume as C, scaleToGeodeticSurface as w, screenToWorld as T, worldToScreen as E, xyzToGeodetic as D } from "@navaramap/engine-api";
|
|
2
2
|
import { Euler as O, MathUtils as k, Matrix4 as A, Plane as j, Ray as M, Vector2 as N, Vector3 as P } from "three";
|
|
3
3
|
//#region src/frames.ts
|
|
4
4
|
function F() {
|
|
@@ -13,44 +13,118 @@ function I(e, t) {
|
|
|
13
13
|
return n;
|
|
14
14
|
}
|
|
15
15
|
//#endregion
|
|
16
|
+
//#region src/featureGeometry.ts
|
|
17
|
+
function L(e) {
|
|
18
|
+
return {
|
|
19
|
+
west: l(e.west),
|
|
20
|
+
south: l(e.south),
|
|
21
|
+
east: l(e.east),
|
|
22
|
+
north: l(e.north)
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function R(e) {
|
|
26
|
+
let t = 0;
|
|
27
|
+
for (let n of e) t += n.length;
|
|
28
|
+
let n = new Float64Array(t), r = 0;
|
|
29
|
+
for (let t of e) n.set(t, r), r += t.length;
|
|
30
|
+
return n;
|
|
31
|
+
}
|
|
32
|
+
function z(e) {
|
|
33
|
+
let t = new Uint32Array(e.length);
|
|
34
|
+
for (let n = 0; n < e.length; n++) t[n] = e[n].length / 3;
|
|
35
|
+
return t;
|
|
36
|
+
}
|
|
37
|
+
function B(e, t, n) {
|
|
38
|
+
let r = d(R(e), z(e), t, n);
|
|
39
|
+
if (r) try {
|
|
40
|
+
let e = r.position_3d_high(), t = r.position_3d_low(), n = r.extent;
|
|
41
|
+
if (!e || !t || !n) throw Error("buildPolygonGeometry: incomplete RTE geometry");
|
|
42
|
+
let i = r.scale_normal_and_cap();
|
|
43
|
+
if (!i) throw Error("buildPolygonGeometry: missing extrusion attribute");
|
|
44
|
+
return {
|
|
45
|
+
positionHigh: e,
|
|
46
|
+
positionLow: t,
|
|
47
|
+
normal: r.normal(),
|
|
48
|
+
scaleNormalAndCap: i,
|
|
49
|
+
indices: r.indices(),
|
|
50
|
+
extent: L(n)
|
|
51
|
+
};
|
|
52
|
+
} finally {
|
|
53
|
+
r.free();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function V(e, t, n, r) {
|
|
57
|
+
let i = f(e, t, n, r);
|
|
58
|
+
if (i) try {
|
|
59
|
+
let e = i.position_high(), t = i.position_low(), n = i.start_high(), r = i.start_low(), a = i.end_high(), o = i.end_low(), s = i.start_normals(), c = i.end_normal_and_texture_coordinate_normalization_x(), l = i.extent;
|
|
60
|
+
if (!e || !t || !n || !r || !a || !o || !s || !c || !l) throw Error("buildPolylineGeometry: incomplete RTE geometry");
|
|
61
|
+
return {
|
|
62
|
+
position: i.position(),
|
|
63
|
+
positionHigh: e,
|
|
64
|
+
positionLow: t,
|
|
65
|
+
startHigh: n,
|
|
66
|
+
startLow: r,
|
|
67
|
+
endHigh: a,
|
|
68
|
+
endLow: o,
|
|
69
|
+
startNormal: s,
|
|
70
|
+
endNormalAndTextureCoordinateNormalizationX: c,
|
|
71
|
+
rightNormalAndTextureCoordinateNormalizationY: i.right_normal_and_texture_coordinate_normalization_y(),
|
|
72
|
+
indices: i.indices(),
|
|
73
|
+
extent: L(l)
|
|
74
|
+
};
|
|
75
|
+
} finally {
|
|
76
|
+
i.free();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function H(e, t, n) {
|
|
80
|
+
let r = e(t.min, t.max, u(n.west), u(n.south), u(n.east), u(n.north));
|
|
81
|
+
return [r[0], r[1]];
|
|
82
|
+
}
|
|
83
|
+
function U(e, t) {
|
|
84
|
+
return H(S, e, t);
|
|
85
|
+
}
|
|
86
|
+
function W(e, t) {
|
|
87
|
+
return H(C, e, t);
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
16
90
|
//#region src/intersection.ts
|
|
17
|
-
function
|
|
18
|
-
let n = new s(e.x, e.y, e.z), r = new s(t.x, t.y, t.z), i =
|
|
91
|
+
function G(e, t) {
|
|
92
|
+
let n = new s(e.x, e.y, e.z), r = new s(t.x, t.y, t.z), i = y(n, r), a = new P(i.normal.x, i.normal.y, i.normal.z), o = new j(a, -i.distance);
|
|
19
93
|
return i.free(), o;
|
|
20
94
|
}
|
|
21
|
-
function
|
|
95
|
+
function K(e, n, r) {
|
|
22
96
|
let i = new c(e.width, e.height, e.pixelRatio);
|
|
23
97
|
i.width *= i.pixelRatio, i.height *= i.pixelRatio;
|
|
24
|
-
let s = new a(n.position.x, n.position.y, n.position.z, n.quaternion.x, n.quaternion.y, n.quaternion.z, n.quaternion.w, n.scale.x, n.scale.y, n.scale.z), l = new t(n.near, n.far, u(n.fov), n.aspect), d =
|
|
98
|
+
let s = new a(n.position.x, n.position.y, n.position.z, n.quaternion.x, n.quaternion.y, n.quaternion.z, n.quaternion.w, n.scale.x, n.scale.y, n.scale.z), l = new t(n.near, n.far, u(n.fov), n.aspect), d = v(i, s, l, new o(r.x, r.y)), f = new P(d.origin.x, d.origin.y, d.origin.z), p = new P(d.direction.x, d.direction.y, d.direction.z), m = new M(f, p);
|
|
25
99
|
return d.free(), m;
|
|
26
100
|
}
|
|
27
|
-
function
|
|
28
|
-
let n = new i(new s(e.origin.x, e.origin.y, e.origin.z), new s(e.direction.x, e.direction.y, e.direction.z)), r =
|
|
101
|
+
function q(e, t) {
|
|
102
|
+
let n = new i(new s(e.origin.x, e.origin.y, e.origin.z), new s(e.direction.x, e.direction.y, e.direction.z)), r = y(new s(t.normal.x * -t.constant, t.normal.y * -t.constant, t.normal.z * -t.constant), new s(t.normal.x, t.normal.y, t.normal.z)), a = b(n, r);
|
|
29
103
|
if (a) {
|
|
30
104
|
let e = new P(a.x, a.y, a.z);
|
|
31
105
|
return a.free(), e;
|
|
32
106
|
}
|
|
33
107
|
}
|
|
34
|
-
function
|
|
108
|
+
function se(e) {
|
|
35
109
|
let t = new s(e.x, e.y, e.z);
|
|
36
|
-
return
|
|
110
|
+
return _(t);
|
|
37
111
|
}
|
|
38
112
|
//#endregion
|
|
39
113
|
//#region src/rte.ts
|
|
40
|
-
var
|
|
41
|
-
function
|
|
42
|
-
let r =
|
|
114
|
+
var ce = Object.freeze({ value: 1 });
|
|
115
|
+
function le(e, t = new P(), n = new P()) {
|
|
116
|
+
let r = m(e.x, e.y, e.z);
|
|
43
117
|
return t.set(r.high.x, r.high.y, r.high.z), n.set(r.low.x, r.low.y, r.low.z), r.free(), {
|
|
44
118
|
high: t,
|
|
45
119
|
low: n
|
|
46
120
|
};
|
|
47
121
|
}
|
|
48
|
-
var
|
|
122
|
+
var ue = (e, t, n = new A()) => {
|
|
49
123
|
n.multiplyMatrices(t, e);
|
|
50
124
|
let r = n.elements;
|
|
51
125
|
return r[12] = 0, r[13] = 0, r[14] = 0, n;
|
|
52
126
|
};
|
|
53
|
-
function
|
|
127
|
+
function de(e, t, n = new P(), r = new A()) {
|
|
54
128
|
r.multiplyMatrices(e, t), n.setFromMatrixPosition(r);
|
|
55
129
|
let i = r.elements;
|
|
56
130
|
return i[12] = 0, i[13] = 0, i[14] = 0, {
|
|
@@ -58,14 +132,14 @@ function U(e, t, n = new P(), r = new A()) {
|
|
|
58
132
|
rotationScale: r
|
|
59
133
|
};
|
|
60
134
|
}
|
|
61
|
-
var
|
|
62
|
-
|
|
63
|
-
let n =
|
|
135
|
+
var J = new A(), Y = new P(), fe = (e, t) => {
|
|
136
|
+
J.copy(t).invert(), Y.copy(e).applyMatrix4(J);
|
|
137
|
+
let n = m(Y.x, Y.y, Y.z), r = n.high, i = n.low, a = {
|
|
64
138
|
high: new P(r.x, r.y, r.z),
|
|
65
139
|
low: new P(i.x, i.y, i.z)
|
|
66
140
|
};
|
|
67
141
|
return n.free(), a;
|
|
68
|
-
},
|
|
142
|
+
}, pe = class {
|
|
69
143
|
_raw;
|
|
70
144
|
constructor(e, t) {
|
|
71
145
|
this._raw = new n(new r(u(e.lat), u(e.lng), e.height), new r(u(t.lat), u(t.lng), t.height));
|
|
@@ -121,14 +195,14 @@ var W = new A(), G = new P(), K = (e, t) => {
|
|
|
121
195
|
};
|
|
122
196
|
//#endregion
|
|
123
197
|
//#region src/index.ts
|
|
124
|
-
async function
|
|
198
|
+
async function me() {
|
|
125
199
|
await e();
|
|
126
200
|
}
|
|
127
|
-
function
|
|
128
|
-
let t =
|
|
201
|
+
function X(e) {
|
|
202
|
+
let t = g(new r(u(e.lat), u(e.lng), e.height)), n = new P(t.x, t.y, t.z);
|
|
129
203
|
return t.free(), n;
|
|
130
204
|
}
|
|
131
|
-
function
|
|
205
|
+
function he(e) {
|
|
132
206
|
let t = new s(e.x, e.y, e.z), n = D(t), r = {
|
|
133
207
|
lat: l(n.lat),
|
|
134
208
|
lng: l(n.lng),
|
|
@@ -136,13 +210,13 @@ function X(e) {
|
|
|
136
210
|
};
|
|
137
211
|
return n.free(), r;
|
|
138
212
|
}
|
|
139
|
-
function
|
|
213
|
+
function ge(e) {
|
|
140
214
|
return u(e);
|
|
141
215
|
}
|
|
142
|
-
function
|
|
216
|
+
function _e(e) {
|
|
143
217
|
return l(e);
|
|
144
218
|
}
|
|
145
|
-
function
|
|
219
|
+
function ve(e, n, r) {
|
|
146
220
|
let i = new c(e.width, e.height, e.pixelRatio);
|
|
147
221
|
i.width *= i.pixelRatio, i.height *= i.pixelRatio;
|
|
148
222
|
let s = new a(n.position.x, n.position.y, n.position.z, n.quaternion.x, n.quaternion.y, n.quaternion.z, n.quaternion.w, n.scale.x, n.scale.y, n.scale.z), l = new t(n.near, n.far, u(n.fov), n.aspect), d = T(i, s, l, new o(r.x, r.y));
|
|
@@ -150,37 +224,43 @@ function ie(e, n, r) {
|
|
|
150
224
|
let f = new P(d.x, d.y, d.z);
|
|
151
225
|
return d.free(), f;
|
|
152
226
|
}
|
|
153
|
-
function
|
|
154
|
-
let t =
|
|
227
|
+
function ye(e) {
|
|
228
|
+
let t = h(new r(u(e.lat), u(e.lng), e.height)), n = new P(t.x, t.y, t.z);
|
|
229
|
+
return t.free(), n;
|
|
230
|
+
}
|
|
231
|
+
function be(e) {
|
|
232
|
+
let t = w(new s(e.x, e.y, e.z));
|
|
233
|
+
if (!t) return;
|
|
234
|
+
let n = new P(t.x, t.y, t.z);
|
|
155
235
|
return t.free(), n;
|
|
156
236
|
}
|
|
157
|
-
function
|
|
158
|
-
let t = new s(e.x, e.y, e.z), n =
|
|
237
|
+
function xe(e) {
|
|
238
|
+
let t = new s(e.x, e.y, e.z), n = p(t);
|
|
159
239
|
return new A().fromArray(n);
|
|
160
240
|
}
|
|
161
|
-
function
|
|
162
|
-
let t = new s(e.x, e.y, e.z), n =
|
|
241
|
+
function Se(e) {
|
|
242
|
+
let t = new s(e.x, e.y, e.z), n = ae(t);
|
|
163
243
|
return new A().fromArray(n);
|
|
164
244
|
}
|
|
165
|
-
function
|
|
166
|
-
let t = new s(e.x, e.y, e.z), n =
|
|
245
|
+
function Z(e) {
|
|
246
|
+
let t = new s(e.x, e.y, e.z), n = oe(t);
|
|
167
247
|
return new A().fromArray(n);
|
|
168
248
|
}
|
|
169
|
-
function
|
|
170
|
-
let t = new s(e.x, e.y, e.z), n =
|
|
249
|
+
function Ce(e) {
|
|
250
|
+
let t = new s(e.x, e.y, e.z), n = x(t);
|
|
171
251
|
return new A().fromArray(n);
|
|
172
252
|
}
|
|
173
|
-
function
|
|
174
|
-
return
|
|
253
|
+
function Q(e) {
|
|
254
|
+
return Z(e).multiply(F());
|
|
175
255
|
}
|
|
176
|
-
function
|
|
177
|
-
return I(
|
|
256
|
+
function $(e) {
|
|
257
|
+
return I(Q(X({
|
|
178
258
|
lng: e.lng,
|
|
179
259
|
lat: e.lat,
|
|
180
260
|
height: e.height ?? 0
|
|
181
261
|
})), e);
|
|
182
262
|
}
|
|
183
|
-
function
|
|
263
|
+
function we(e, n, r) {
|
|
184
264
|
let i = new c(e.width, e.height, e.pixelRatio);
|
|
185
265
|
i.width *= i.pixelRatio, i.height *= i.pixelRatio;
|
|
186
266
|
let o = new a(n.position.x, n.position.y, n.position.z, n.quaternion.x, n.quaternion.y, n.quaternion.z, n.quaternion.w, n.scale.x, n.scale.y, n.scale.z), l = new t(n.near, n.far, u(n.fov), n.aspect), d = E(i, o, l, new s(r.x, r.y, r.z));
|
|
@@ -188,20 +268,20 @@ function ue(e, n, r) {
|
|
|
188
268
|
let f = new N(d.x, d.y);
|
|
189
269
|
return d.free(), f;
|
|
190
270
|
}
|
|
191
|
-
function
|
|
192
|
-
return
|
|
271
|
+
function Te() {
|
|
272
|
+
return re();
|
|
193
273
|
}
|
|
194
|
-
function
|
|
195
|
-
return
|
|
274
|
+
function Ee() {
|
|
275
|
+
return ie();
|
|
196
276
|
}
|
|
197
|
-
function
|
|
198
|
-
return
|
|
277
|
+
function De() {
|
|
278
|
+
return te();
|
|
199
279
|
}
|
|
200
|
-
function
|
|
201
|
-
return
|
|
280
|
+
function Oe() {
|
|
281
|
+
return ne();
|
|
202
282
|
}
|
|
203
|
-
function
|
|
204
|
-
return
|
|
283
|
+
function ke() {
|
|
284
|
+
return ee();
|
|
205
285
|
}
|
|
206
286
|
//#endregion
|
|
207
|
-
export {
|
|
287
|
+
export { pe as EllipsoidGeodesic, ce as RTE_ONE_UNIFORM, B as buildPolygonGeometry, V as buildPolylineGeometry, fe as calcCameraPosition, ue as calcModelMatrixRTE, de as composeWorldMatrixForRTE, ve as convertScreenToWorld, we as convertWorldToScreen, ge as degreeToRadian, xe as eastNorthUpToFixedFrame, le as encodePositionRTE, ye as geodeticSurfaceNormal, X as geodeticToVector3, se as getHeightFromEllipsoid, K as getPickRay, G as getPlaneFromPointNormal, q as getRayPlaneIntersection, ke as getWGS84Eccentricity, De as getWGS84EccentricitySquared, Oe as getWGS84Flattening, Te as getWGS84SemiMajorAxis, Ee as getWGS84SemiMinorAxis, $ as headingPitchRollToFixedFrame, me as initNavaraApi, Se as northEastDownToFixedFrame, Z as northUpEastToFixedFrame, Ce as northWestUpToFixedFrame, U as polygonGroundVolume, W as polylineGroundVolume, _e as radianToDegree, be as scaleToGeodeticSurface, he as vector3ToGeodetic, Q as westUpNorthToFixedFrame };
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("@navaramap/engine-api"),require("three")):typeof define==`function`&&define.amd?define([`exports`,`@navaramap/engine-api`,`three`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.NavaraThreeApi={},e._navaramap_engine_api,e.three))})(this,function(e,t,n){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var s=o(t),l=0,u=s.length,d;l<u;l++)d=s[l],!c.call(e,d)&&d!==n&&i(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=a(t,d))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:r(s(e)),l(t||!e||!e.__esModule||!c.call(e,`default`)?i(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);function u(){return new n.Matrix4().makeRotationY(Math.PI/2)}function d(e,t){let r=new n.Matrix4().multiplyMatrices(e,new n.Matrix4().makeRotationFromEuler(new n.Euler(-n.MathUtils.degToRad(t.pitch??0),-n.MathUtils.degToRad(t.heading??0),n.MathUtils.degToRad(t.roll??0),`YXZ`)));if(t.scale!==void 0){let e=t.scale;r.scale(typeof e==`number`?new n.Vector3(e,e,e):new n.Vector3(e.x,e.y,e.z))}return r}function f(e,r){let i=new t.Vec3(e.x,e.y,e.z),a=new t.Vec3(r.x,r.y,r.z),o=(0,t.getPlaneFromPointNormal)(i,a),s=new n.Vector3(o.normal.x,o.normal.y,o.normal.z),c=new n.Plane(s,-o.distance);return o.free(),c}function
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("@navaramap/engine-api"),require("three")):typeof define==`function`&&define.amd?define([`exports`,`@navaramap/engine-api`,`three`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.NavaraThreeApi={},e._navaramap_engine_api,e.three))})(this,function(e,t,n){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var s=o(t),l=0,u=s.length,d;l<u;l++)d=s[l],!c.call(e,d)&&d!==n&&i(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=a(t,d))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:r(s(e)),l(t||!e||!e.__esModule||!c.call(e,`default`)?i(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);function u(){return new n.Matrix4().makeRotationY(Math.PI/2)}function d(e,t){let r=new n.Matrix4().multiplyMatrices(e,new n.Matrix4().makeRotationFromEuler(new n.Euler(-n.MathUtils.degToRad(t.pitch??0),-n.MathUtils.degToRad(t.heading??0),n.MathUtils.degToRad(t.roll??0),`YXZ`)));if(t.scale!==void 0){let e=t.scale;r.scale(typeof e==`number`?new n.Vector3(e,e,e):new n.Vector3(e.x,e.y,e.z))}return r}function f(e){return{west:(0,t.angleToDegree)(e.west),south:(0,t.angleToDegree)(e.south),east:(0,t.angleToDegree)(e.east),north:(0,t.angleToDegree)(e.north)}}function p(e){let t=0;for(let n of e)t+=n.length;let n=new Float64Array(t),r=0;for(let t of e)n.set(t,r),r+=t.length;return n}function m(e){let t=new Uint32Array(e.length);for(let n=0;n<e.length;n++)t[n]=e[n].length/3;return t}function h(e,n,r){let i=(0,t.buildPolygonGeometry)(p(e),m(e),n,r);if(i)try{let e=i.position_3d_high(),t=i.position_3d_low(),n=i.extent;if(!e||!t||!n)throw Error(`buildPolygonGeometry: incomplete RTE geometry`);let r=i.scale_normal_and_cap();if(!r)throw Error(`buildPolygonGeometry: missing extrusion attribute`);return{positionHigh:e,positionLow:t,normal:i.normal(),scaleNormalAndCap:r,indices:i.indices(),extent:f(n)}}finally{i.free()}}function g(e,n,r,i){let a=(0,t.buildPolylineGeometry)(e,n,r,i);if(a)try{let e=a.position_high(),t=a.position_low(),n=a.start_high(),r=a.start_low(),i=a.end_high(),o=a.end_low(),s=a.start_normals(),c=a.end_normal_and_texture_coordinate_normalization_x(),l=a.extent;if(!e||!t||!n||!r||!i||!o||!s||!c||!l)throw Error(`buildPolylineGeometry: incomplete RTE geometry`);return{position:a.position(),positionHigh:e,positionLow:t,startHigh:n,startLow:r,endHigh:i,endLow:o,startNormal:s,endNormalAndTextureCoordinateNormalizationX:c,rightNormalAndTextureCoordinateNormalizationY:a.right_normal_and_texture_coordinate_normalization_y(),indices:a.indices(),extent:f(l)}}finally{a.free()}}function _(e,n,r){let i=e(n.min,n.max,(0,t.angleToRadian)(r.west),(0,t.angleToRadian)(r.south),(0,t.angleToRadian)(r.east),(0,t.angleToRadian)(r.north));return[i[0],i[1]]}function v(e,n){return _(t.polygonGroundVolume,e,n)}function y(e,n){return _(t.polylineGroundVolume,e,n)}function b(e,r){let i=new t.Vec3(e.x,e.y,e.z),a=new t.Vec3(r.x,r.y,r.z),o=(0,t.getPlaneFromPointNormal)(i,a),s=new n.Vector3(o.normal.x,o.normal.y,o.normal.z),c=new n.Plane(s,-o.distance);return o.free(),c}function x(e,r,i){let a=new t.Window(e.width,e.height,e.pixelRatio);a.width*=a.pixelRatio,a.height*=a.pixelRatio;let o=new t.Transform(r.position.x,r.position.y,r.position.z,r.quaternion.x,r.quaternion.y,r.quaternion.z,r.quaternion.w,r.scale.x,r.scale.y,r.scale.z),s=new t.CameraFrustum(r.near,r.far,(0,t.angleToRadian)(r.fov),r.aspect),c=(0,t.getPickRay)(a,o,s,new t.Vec2(i.x,i.y)),l=new n.Vector3(c.origin.x,c.origin.y,c.origin.z),u=new n.Vector3(c.direction.x,c.direction.y,c.direction.z),d=new n.Ray(l,u);return c.free(),d}function S(e,r){let i=new t.Ray(new t.Vec3(e.origin.x,e.origin.y,e.origin.z),new t.Vec3(e.direction.x,e.direction.y,e.direction.z)),a=(0,t.getPlaneFromPointNormal)(new t.Vec3(r.normal.x*-r.constant,r.normal.y*-r.constant,r.normal.z*-r.constant),new t.Vec3(r.normal.x,r.normal.y,r.normal.z)),o=(0,t.getRayPlaneIntersection)(i,a);if(o){let e=new n.Vector3(o.x,o.y,o.z);return o.free(),e}}function C(e){let n=new t.Vec3(e.x,e.y,e.z);return(0,t.getHeightFromEllipsoid)(n)}var w=Object.freeze({value:1});function T(e,r=new n.Vector3,i=new n.Vector3){let a=(0,t.encodePosition)(e.x,e.y,e.z);return r.set(a.high.x,a.high.y,a.high.z),i.set(a.low.x,a.low.y,a.low.z),a.free(),{high:r,low:i}}var E=(e,t,r=new n.Matrix4)=>{r.multiplyMatrices(t,e);let i=r.elements;return i[12]=0,i[13]=0,i[14]=0,r};function D(e,t,r=new n.Vector3,i=new n.Matrix4){i.multiplyMatrices(e,t),r.setFromMatrixPosition(i);let a=i.elements;return a[12]=0,a[13]=0,a[14]=0,{position:r,rotationScale:i}}var O=new n.Matrix4,k=new n.Vector3,A=(e,r)=>{O.copy(r).invert(),k.copy(e).applyMatrix4(O);let i=(0,t.encodePosition)(k.x,k.y,k.z),a=i.high,o=i.low,s={high:new n.Vector3(a.x,a.y,a.z),low:new n.Vector3(o.x,o.y,o.z)};return i.free(),s},j=class{_raw;constructor(e,n){this._raw=new t.EllipsoidGeodesic(new t.LLE((0,t.angleToRadian)(e.lat),(0,t.angleToRadian)(e.lng),e.height),new t.LLE((0,t.angleToRadian)(n.lat),(0,t.angleToRadian)(n.lng),n.height))}get distance(){return this._raw.distance}get converged(){return this._raw.converged}get startHeading(){return(0,t.angleToDegree)(this._raw.start_heading)}get endHeading(){return(0,t.angleToDegree)(this._raw.end_heading)}get start(){let e=this._raw.start;return{lat:(0,t.angleToDegree)(e.lat),lng:(0,t.angleToDegree)(e.lng),height:e.height}}get end(){let e=this._raw.end;return{lat:(0,t.angleToDegree)(e.lat),lng:(0,t.angleToDegree)(e.lng),height:e.height}}interpolatePoints(e){let n=this._raw.interpolateGeodeticPoints(e??null),r=[];for(let e of n)r.push({lat:(0,t.angleToDegree)(e.lat),lng:(0,t.angleToDegree)(e.lng),height:e.height}),e.free();return r}interpolateDistance(e){let n=this._raw.interpolateDistance(e),r={lat:(0,t.angleToDegree)(n.lat),lng:(0,t.angleToDegree)(n.lng),height:n.height};return n.free(),r}dispose(){this._raw.free()}};async function M(){await(0,t.default)()}function N(e){let r=(0,t.geodeticToXyz)(new t.LLE((0,t.angleToRadian)(e.lat),(0,t.angleToRadian)(e.lng),e.height)),i=new n.Vector3(r.x,r.y,r.z);return r.free(),i}function P(e){let n=new t.Vec3(e.x,e.y,e.z),r=(0,t.xyzToGeodetic)(n),i={lat:(0,t.angleToDegree)(r.lat),lng:(0,t.angleToDegree)(r.lng),height:r.height};return r.free(),i}function F(e){return(0,t.angleToRadian)(e)}function I(e){return(0,t.angleToDegree)(e)}function L(e,r,i){let a=new t.Window(e.width,e.height,e.pixelRatio);a.width*=a.pixelRatio,a.height*=a.pixelRatio;let o=new t.Transform(r.position.x,r.position.y,r.position.z,r.quaternion.x,r.quaternion.y,r.quaternion.z,r.quaternion.w,r.scale.x,r.scale.y,r.scale.z),s=new t.CameraFrustum(r.near,r.far,(0,t.angleToRadian)(r.fov),r.aspect),c=(0,t.screenToWorld)(a,o,s,new t.Vec2(i.x,i.y));if(!c)return;let l=new n.Vector3(c.x,c.y,c.z);return c.free(),l}function R(e){let r=(0,t.geodeticSurfaceNormal)(new t.LLE((0,t.angleToRadian)(e.lat),(0,t.angleToRadian)(e.lng),e.height)),i=new n.Vector3(r.x,r.y,r.z);return r.free(),i}function z(e){let r=(0,t.scaleToGeodeticSurface)(new t.Vec3(e.x,e.y,e.z));if(!r)return;let i=new n.Vector3(r.x,r.y,r.z);return r.free(),i}function B(e){let r=new t.Vec3(e.x,e.y,e.z),i=(0,t.eastNorthUpToFixedFrame)(r);return new n.Matrix4().fromArray(i)}function V(e){let r=new t.Vec3(e.x,e.y,e.z),i=(0,t.northEastDownToFixedFrame)(r);return new n.Matrix4().fromArray(i)}function H(e){let r=new t.Vec3(e.x,e.y,e.z),i=(0,t.northUpEastToFixedFrame)(r);return new n.Matrix4().fromArray(i)}function U(e){let r=new t.Vec3(e.x,e.y,e.z),i=(0,t.northWestUpToFixedFrame)(r);return new n.Matrix4().fromArray(i)}function W(e){return H(e).multiply(u())}function G(e){return d(W(N({lng:e.lng,lat:e.lat,height:e.height??0})),e)}function K(e,r,i){let a=new t.Window(e.width,e.height,e.pixelRatio);a.width*=a.pixelRatio,a.height*=a.pixelRatio;let o=new t.Transform(r.position.x,r.position.y,r.position.z,r.quaternion.x,r.quaternion.y,r.quaternion.z,r.quaternion.w,r.scale.x,r.scale.y,r.scale.z),s=new t.CameraFrustum(r.near,r.far,(0,t.angleToRadian)(r.fov),r.aspect),c=(0,t.worldToScreen)(a,o,s,new t.Vec3(i.x,i.y,i.z));if(!c)return;let l=new n.Vector2(c.x,c.y);return c.free(),l}function q(){return(0,t.getWGS84SemiMajorAxis)()}function J(){return(0,t.getWGS84SemiMinorAxis)()}function Y(){return(0,t.getWGS84EccentricitySquared)()}function X(){return(0,t.getWGS84Flattening)()}function Z(){return(0,t.getWGS84Eccentricity)()}e.EllipsoidGeodesic=j,e.RTE_ONE_UNIFORM=w,e.buildPolygonGeometry=h,e.buildPolylineGeometry=g,e.calcCameraPosition=A,e.calcModelMatrixRTE=E,e.composeWorldMatrixForRTE=D,e.convertScreenToWorld=L,e.convertWorldToScreen=K,e.degreeToRadian=F,e.eastNorthUpToFixedFrame=B,e.encodePositionRTE=T,e.geodeticSurfaceNormal=R,e.geodeticToVector3=N,e.getHeightFromEllipsoid=C,e.getPickRay=x,e.getPlaneFromPointNormal=b,e.getRayPlaneIntersection=S,e.getWGS84Eccentricity=Z,e.getWGS84EccentricitySquared=Y,e.getWGS84Flattening=X,e.getWGS84SemiMajorAxis=q,e.getWGS84SemiMinorAxis=J,e.headingPitchRollToFixedFrame=G,e.initNavaraApi=M,e.northEastDownToFixedFrame=V,e.northUpEastToFixedFrame=H,e.northWestUpToFixedFrame=U,e.polygonGroundVolume=v,e.polylineGroundVolume=y,e.radianToDegree=I,e.scaleToGeodeticSurface=z,e.vector3ToGeodetic=P,e.westUpNorthToFixedFrame=W});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@navaramap/three-api",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"main": "dist/index.umd.cjs",
|
|
6
6
|
"module": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"license": "MIT OR Apache-2.0",
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "git+https://github.com/
|
|
15
|
+
"url": "git+https://github.com/maplibre/navara.git",
|
|
16
16
|
"directory": "web/navara_three_api"
|
|
17
17
|
},
|
|
18
18
|
"publishConfig": {
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"three": ">=0.183.0"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@navaramap/core": "0.
|
|
26
|
-
"@navaramap/engine-api": "0.
|
|
25
|
+
"@navaramap/core": "0.2.0",
|
|
26
|
+
"@navaramap/engine-api": "0.2.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@types/three": "0.185.
|
|
29
|
+
"@types/three": "0.185.4",
|
|
30
30
|
"three": "0.185.1"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import type { NormalizeWASMClass } from "@navaramap/core";
|
|
2
|
+
import {
|
|
3
|
+
buildPolygonGeometry as buildPolygonGeometryWasm,
|
|
4
|
+
buildPolylineGeometry as buildPolylineGeometryWasm,
|
|
5
|
+
polygonGroundVolume as polygonGroundVolumeWasm,
|
|
6
|
+
polylineGroundVolume as polylineGroundVolumeWasm,
|
|
7
|
+
angleToDegree,
|
|
8
|
+
angleToRadian,
|
|
9
|
+
type PolygonMaterial,
|
|
10
|
+
type PolylineMaterial,
|
|
11
|
+
} from "@navaramap/engine-api";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Geometry builders for standalone polygon and polyline meshes, using the
|
|
15
|
+
* vector layer's construction. Positions are RTE-encoded.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** A polygon layer material, as a plain object. */
|
|
19
|
+
export type PolygonGeometryMaterial = NormalizeWASMClass<PolygonMaterial>;
|
|
20
|
+
|
|
21
|
+
/** A polyline layer material, as a plain object. */
|
|
22
|
+
export type PolylineGeometryMaterial = NormalizeWASMClass<PolylineMaterial>;
|
|
23
|
+
|
|
24
|
+
/** A geographic bounding box, in degrees. */
|
|
25
|
+
export type GeographicExtent = {
|
|
26
|
+
west: number;
|
|
27
|
+
south: number;
|
|
28
|
+
east: number;
|
|
29
|
+
north: number;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type PolygonGeometryData = {
|
|
33
|
+
positionHigh: Float32Array;
|
|
34
|
+
positionLow: Float32Array;
|
|
35
|
+
/** Absent for a `clampToGround` polygon. */
|
|
36
|
+
normal?: Float32Array;
|
|
37
|
+
/** `xyz` = extrusion direction, `w` = 0 on the bottom cap, 1 on the top. */
|
|
38
|
+
scaleNormalAndCap: Float32Array;
|
|
39
|
+
indices: Uint32Array;
|
|
40
|
+
extent: GeographicExtent;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type PolylineGeometryData = {
|
|
44
|
+
position: Float32Array;
|
|
45
|
+
positionHigh: Float32Array;
|
|
46
|
+
positionLow: Float32Array;
|
|
47
|
+
startHigh: Float32Array;
|
|
48
|
+
startLow: Float32Array;
|
|
49
|
+
endHigh: Float32Array;
|
|
50
|
+
endLow: Float32Array;
|
|
51
|
+
startNormal: Float32Array;
|
|
52
|
+
endNormalAndTextureCoordinateNormalizationX: Float32Array;
|
|
53
|
+
rightNormalAndTextureCoordinateNormalizationY: Float32Array;
|
|
54
|
+
indices: Uint32Array;
|
|
55
|
+
extent: GeographicExtent;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/** Flat `[lng, lat, height, ...]`, or ECEF `[x, y, z, ...]` when geocentric. */
|
|
59
|
+
export type GeometryRing = Float64Array;
|
|
60
|
+
|
|
61
|
+
function toDegrees(extent: {
|
|
62
|
+
west: number;
|
|
63
|
+
south: number;
|
|
64
|
+
east: number;
|
|
65
|
+
north: number;
|
|
66
|
+
}): GeographicExtent {
|
|
67
|
+
return {
|
|
68
|
+
west: angleToDegree(extent.west),
|
|
69
|
+
south: angleToDegree(extent.south),
|
|
70
|
+
east: angleToDegree(extent.east),
|
|
71
|
+
north: angleToDegree(extent.north),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Concatenates rings; the builder splits them by `ringLengths`. */
|
|
76
|
+
function concatRings(rings: readonly GeometryRing[]): Float64Array {
|
|
77
|
+
let total = 0;
|
|
78
|
+
for (const ring of rings) total += ring.length;
|
|
79
|
+
|
|
80
|
+
const coordinates = new Float64Array(total);
|
|
81
|
+
let offset = 0;
|
|
82
|
+
for (const ring of rings) {
|
|
83
|
+
coordinates.set(ring, offset);
|
|
84
|
+
offset += ring.length;
|
|
85
|
+
}
|
|
86
|
+
return coordinates;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function ringLengths(rings: readonly GeometryRing[]): Uint32Array {
|
|
90
|
+
const lengths = new Uint32Array(rings.length);
|
|
91
|
+
for (let i = 0; i < rings.length; i++) {
|
|
92
|
+
lengths[i] = rings[i].length / 3;
|
|
93
|
+
}
|
|
94
|
+
return lengths;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Builds the geometry of one standalone polygon.
|
|
99
|
+
*
|
|
100
|
+
* @param rings - Outer ring first, then holes.
|
|
101
|
+
* @param geocentric - Read the positions as ECEF metres.
|
|
102
|
+
* @param material - A `polygon` layer material. Outline options are ignored.
|
|
103
|
+
* @throws When `material` does not deserialize.
|
|
104
|
+
* @returns `undefined` when the outer ring has fewer than three vertices or is
|
|
105
|
+
* collinear.
|
|
106
|
+
*/
|
|
107
|
+
export function buildPolygonGeometry(
|
|
108
|
+
rings: readonly GeometryRing[],
|
|
109
|
+
geocentric: boolean,
|
|
110
|
+
material: PolygonGeometryMaterial,
|
|
111
|
+
): PolygonGeometryData | undefined {
|
|
112
|
+
const built = buildPolygonGeometryWasm(
|
|
113
|
+
concatRings(rings),
|
|
114
|
+
ringLengths(rings),
|
|
115
|
+
geocentric,
|
|
116
|
+
material,
|
|
117
|
+
);
|
|
118
|
+
if (!built) return undefined;
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
const positionHigh = built.position_3d_high();
|
|
122
|
+
const positionLow = built.position_3d_low();
|
|
123
|
+
const extent = built.extent;
|
|
124
|
+
if (!positionHigh || !positionLow || !extent) {
|
|
125
|
+
throw new Error("buildPolygonGeometry: incomplete RTE geometry");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const scaleNormalAndCap = built.scale_normal_and_cap();
|
|
129
|
+
if (!scaleNormalAndCap) {
|
|
130
|
+
throw new Error("buildPolygonGeometry: missing extrusion attribute");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
positionHigh,
|
|
135
|
+
positionLow,
|
|
136
|
+
normal: built.normal(),
|
|
137
|
+
scaleNormalAndCap,
|
|
138
|
+
indices: built.indices(),
|
|
139
|
+
extent: toDegrees(extent),
|
|
140
|
+
};
|
|
141
|
+
} finally {
|
|
142
|
+
built.free();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Builds the geometry of one standalone polyline.
|
|
148
|
+
*
|
|
149
|
+
* @param positions - Flat `[lng, lat, height, ...]`, or ECEF when `geocentric`.
|
|
150
|
+
* @param geocentric - Read the positions as ECEF metres.
|
|
151
|
+
* @param ring - Join a repeated first vertex as a seam instead of two caps.
|
|
152
|
+
* @param material - A `polyline` layer material.
|
|
153
|
+
* @throws When `material` does not deserialize.
|
|
154
|
+
* @returns `undefined` when fewer than two distinct positions remain.
|
|
155
|
+
*/
|
|
156
|
+
export function buildPolylineGeometry(
|
|
157
|
+
positions: Float64Array,
|
|
158
|
+
geocentric: boolean,
|
|
159
|
+
ring: boolean,
|
|
160
|
+
material: PolylineGeometryMaterial,
|
|
161
|
+
): PolylineGeometryData | undefined {
|
|
162
|
+
const built = buildPolylineGeometryWasm(
|
|
163
|
+
positions,
|
|
164
|
+
geocentric,
|
|
165
|
+
ring,
|
|
166
|
+
material,
|
|
167
|
+
);
|
|
168
|
+
if (!built) return undefined;
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
const positionHigh = built.position_high();
|
|
172
|
+
const positionLow = built.position_low();
|
|
173
|
+
const startHigh = built.start_high();
|
|
174
|
+
const startLow = built.start_low();
|
|
175
|
+
const endHigh = built.end_high();
|
|
176
|
+
const endLow = built.end_low();
|
|
177
|
+
const startNormal = built.start_normals();
|
|
178
|
+
const endNormal = built.end_normal_and_texture_coordinate_normalization_x();
|
|
179
|
+
const extent = built.extent;
|
|
180
|
+
if (
|
|
181
|
+
!positionHigh ||
|
|
182
|
+
!positionLow ||
|
|
183
|
+
!startHigh ||
|
|
184
|
+
!startLow ||
|
|
185
|
+
!endHigh ||
|
|
186
|
+
!endLow ||
|
|
187
|
+
!startNormal ||
|
|
188
|
+
!endNormal ||
|
|
189
|
+
!extent
|
|
190
|
+
) {
|
|
191
|
+
throw new Error("buildPolylineGeometry: incomplete RTE geometry");
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
position: built.position(),
|
|
196
|
+
positionHigh,
|
|
197
|
+
positionLow,
|
|
198
|
+
startHigh,
|
|
199
|
+
startLow,
|
|
200
|
+
endHigh,
|
|
201
|
+
endLow,
|
|
202
|
+
startNormal,
|
|
203
|
+
endNormalAndTextureCoordinateNormalizationX: endNormal,
|
|
204
|
+
rightNormalAndTextureCoordinateNormalizationY:
|
|
205
|
+
built.right_normal_and_texture_coordinate_normalization_y(),
|
|
206
|
+
indices: built.indices(),
|
|
207
|
+
extent: toDegrees(extent),
|
|
208
|
+
};
|
|
209
|
+
} finally {
|
|
210
|
+
built.free();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** A height range in metres, relative to the ellipsoid. */
|
|
215
|
+
export type HeightRange = { min: number; max: number };
|
|
216
|
+
|
|
217
|
+
function groundVolume(
|
|
218
|
+
build: typeof polygonGroundVolumeWasm,
|
|
219
|
+
range: HeightRange,
|
|
220
|
+
extent: GeographicExtent,
|
|
221
|
+
): [number, number] {
|
|
222
|
+
const heights = build(
|
|
223
|
+
range.min,
|
|
224
|
+
range.max,
|
|
225
|
+
angleToRadian(extent.west),
|
|
226
|
+
angleToRadian(extent.south),
|
|
227
|
+
angleToRadian(extent.east),
|
|
228
|
+
angleToRadian(extent.north),
|
|
229
|
+
);
|
|
230
|
+
return [heights[0], heights[1]];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* `[min, max]` height a clamp-to-ground polygon volume over `extent` must
|
|
235
|
+
* span to enclose the ground heights `range`, given the flat cap triangles
|
|
236
|
+
* {@link buildPolygonGeometry} produces.
|
|
237
|
+
*/
|
|
238
|
+
export function polygonGroundVolume(
|
|
239
|
+
range: HeightRange,
|
|
240
|
+
extent: GeographicExtent,
|
|
241
|
+
): [number, number] {
|
|
242
|
+
return groundVolume(polygonGroundVolumeWasm, range, extent);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* `[min, max]` height a clamp-to-ground polyline volume over `extent` must
|
|
247
|
+
* span to enclose the ground heights `range`, given the straight segments
|
|
248
|
+
* {@link buildPolylineGeometry} produces.
|
|
249
|
+
*/
|
|
250
|
+
export function polylineGroundVolume(
|
|
251
|
+
range: HeightRange,
|
|
252
|
+
extent: GeographicExtent,
|
|
253
|
+
): [number, number] {
|
|
254
|
+
return groundVolume(polylineGroundVolumeWasm, range, extent);
|
|
255
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ import initApi, {
|
|
|
13
13
|
screenToWorld,
|
|
14
14
|
worldToScreen,
|
|
15
15
|
geodeticSurfaceNormal as nvGeodeticSurfaceNormal,
|
|
16
|
+
scaleToGeodeticSurface as nvScaleToGeodeticSurface,
|
|
16
17
|
eastNorthUpToFixedFrame as nvEastNorthUpToFixedFrame,
|
|
17
18
|
northEastDownToFixedFrame as nvNorthEastDownToFixedFrame,
|
|
18
19
|
northUpEastToFixedFrame as nvNorthUpEastToFixedFrame,
|
|
@@ -43,6 +44,7 @@ export type {
|
|
|
43
44
|
} from "@navaramap/core";
|
|
44
45
|
export type { GeodeticPlacement } from "./frames";
|
|
45
46
|
|
|
47
|
+
export * from "./featureGeometry";
|
|
46
48
|
export * from "./intersection";
|
|
47
49
|
export * from "./rte";
|
|
48
50
|
export * from "./ellipsoidGeodesic";
|
|
@@ -173,6 +175,23 @@ export function geodeticSurfaceNormal(lle: LatLngHeight): Vector3 {
|
|
|
173
175
|
return result;
|
|
174
176
|
}
|
|
175
177
|
|
|
178
|
+
/**
|
|
179
|
+
* Projects a Cartesian position onto the WGS84 ellipsoid surface along the
|
|
180
|
+
* geodetic normal.
|
|
181
|
+
* @param xyz - Cartesian Vector3 in Earth-Centered Earth-Fixed (ECEF) coordinates
|
|
182
|
+
* @returns The surface position in ECEF coordinates, or undefined when the
|
|
183
|
+
* position is too close to the ellipsoid's center to project
|
|
184
|
+
*/
|
|
185
|
+
export function scaleToGeodeticSurface(xyz: Vector3): Vector3 | undefined {
|
|
186
|
+
const pos = nvScaleToGeodeticSurface(new Vec3(xyz.x, xyz.y, xyz.z));
|
|
187
|
+
if (!pos) {
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
const result = new Vector3(pos.x, pos.y, pos.z);
|
|
191
|
+
pos.free();
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
194
|
+
|
|
176
195
|
/**
|
|
177
196
|
* Creates a local East-North-Up (ENU) reference frame transformation matrix at a position.
|
|
178
197
|
* @param origin - Origin position in ECEF coordinates
|