@spacexr/geodesy 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ellipsoid.ts"],"names":[],"mappings":"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","file":"chunk-RJFTT4KI.js","sourcesContent":["/**\n * Immutable oblate ellipsoid of revolution.\n *\n * Axis lengths are expressed in metres. The semi-major axis lies in the\n * equatorial plane and the semi-minor axis follows the polar axis. Instances\n * validate their dimensions and precompute the coefficients required by\n * geodetic conversions.\n */\nexport class Ellipsoid {\n /** WGS 84 reference ellipsoid used by EPSG:4978 and EPSG:4979. */\n public static readonly WGS84 = Ellipsoid.fromSemiMajorAxisAndInverseFlattening(\"WGS84\", 6378137, 298.257223563);\n\n /** Geodetic Reference System 1980 ellipsoid. */\n public static readonly GRS80 = Ellipsoid.fromSemiMajorAxisAndInverseFlattening(\"GRS80\", 6378137, 298.257222101);\n\n /** Geodetic Reference System 1967 ellipsoid. */\n public static readonly GRS67 = Ellipsoid.fromSemiMajorAxisAndInverseFlattening(\"GRS67\", 6378160, 298.25);\n\n /** Australian National Spheroid. */\n public static readonly ANS = Ellipsoid.fromSemiMajorAxisAndInverseFlattening(\"ANS\", 6378160, 298.25);\n\n /** World Geodetic System 1972 ellipsoid. */\n public static readonly WGS72 = Ellipsoid.fromSemiMajorAxisAndInverseFlattening(\"WGS72\", 6378135, 298.26);\n\n /** Clarke 1858 ellipsoid. */\n public static readonly Clarke1858 = Ellipsoid.fromSemiMajorAxisAndInverseFlattening(\"Clarke1858\", 6378293.645, 294.26);\n\n /** Clarke 1880 ellipsoid. */\n public static readonly Clarke1880 = Ellipsoid.fromSemiMajorAxisAndInverseFlattening(\"Clarke1880\", 6378249.145, 293.465);\n\n private constructor(\n private readonly identifier: string,\n private readonly major: number,\n private readonly minor: number,\n ) {\n if (identifier.trim().length === 0) throw new RangeError(\"Ellipsoid name must not be empty.\");\n if (!Number.isFinite(major) || major <= 0) throw new RangeError(\"Semi-major axis must be a positive finite number.\");\n if (!Number.isFinite(minor) || minor <= 0) throw new RangeError(\"Semi-minor axis must be a positive finite number.\");\n if (minor > major)\n throw new RangeError(\"An oblate ellipsoid requires the semi-minor axis to be no greater than the semi-major axis.\");\n }\n\n /**\n * Creates an ellipsoid from its semi-major axis and inverse flattening.\n *\n * `Infinity` represents a sphere.\n *\n * @param name - Stable human-readable ellipsoid name.\n * @param semiMajorAxis - Equatorial semi-major axis in metres.\n * @param inverseFlattening - Reciprocal flattening, or `Infinity` for a sphere.\n * @returns A validated immutable ellipsoid.\n */\n public static fromSemiMajorAxisAndInverseFlattening(name: string, semiMajorAxis: number, inverseFlattening: number): Ellipsoid {\n if (inverseFlattening !== Number.POSITIVE_INFINITY && (!Number.isFinite(inverseFlattening) || inverseFlattening <= 1)) {\n throw new RangeError(\"Inverse flattening must be greater than one, or Infinity for a sphere.\");\n }\n const flattening = inverseFlattening === Number.POSITIVE_INFINITY ? 0 : 1 / inverseFlattening;\n return new Ellipsoid(name, semiMajorAxis, semiMajorAxis * (1 - flattening));\n }\n\n /**\n * Creates an ellipsoid from its semi-major axis and flattening.\n *\n * @param name - Stable human-readable ellipsoid name.\n * @param semiMajorAxis - Equatorial semi-major axis in metres.\n * @param flattening - Flattening in the interval `[0, 1)`.\n * @returns A validated immutable ellipsoid.\n */\n public static fromSemiMajorAxisAndFlattening(name: string, semiMajorAxis: number, flattening: number): Ellipsoid {\n if (!Number.isFinite(flattening) || flattening < 0 || flattening >= 1) {\n throw new RangeError(\"Flattening must be a finite number in the interval [0, 1).\");\n }\n return new Ellipsoid(name, semiMajorAxis, semiMajorAxis * (1 - flattening));\n }\n\n /**\n * Creates an ellipsoid from its semi-major and semi-minor axes.\n *\n * @param name - Stable human-readable ellipsoid name.\n * @param semiMajorAxis - Equatorial semi-major axis in metres.\n * @param semiMinorAxis - Polar semi-minor axis in metres.\n * @returns A validated immutable ellipsoid.\n */\n public static fromAxes(name: string, semiMajorAxis: number, semiMinorAxis: number): Ellipsoid {\n return new Ellipsoid(name, semiMajorAxis, semiMinorAxis);\n }\n\n /**\n * Creates a spherical reference surface.\n *\n * @param name - Stable human-readable sphere name.\n * @param radius - Radius in metres.\n * @returns An ellipsoid with zero flattening.\n */\n public static sphere(name: string, radius: number): Ellipsoid {\n return new Ellipsoid(name, radius, radius);\n }\n\n /** Stable human-readable identifier. */\n public get name(): string {\n return this.identifier;\n }\n\n /** Equatorial semi-major axis in metres. */\n public get semiMajorAxis(): number {\n return this.major;\n }\n\n /** Polar semi-minor axis in metres. */\n public get semiMinorAxis(): number {\n return this.minor;\n }\n\n /** Largest ellipsoid radius in metres. */\n public get maximumRadius(): number {\n return this.major;\n }\n\n /** Smallest ellipsoid radius in metres. */\n public get minimumRadius(): number {\n return this.minor;\n }\n\n /** Ellipsoid flattening `(a - b) / a`. */\n public get flattening(): number {\n return (this.major - this.minor) / this.major;\n }\n\n /** Reciprocal flattening, or `Infinity` for a sphere. */\n public get inverseFlattening(): number {\n const flattening = this.flattening;\n return flattening === 0 ? Number.POSITIVE_INFINITY : 1 / flattening;\n }\n\n /** First eccentricity squared `e^2`. */\n public get squaredEccentricity(): number {\n return 1 - (this.minor * this.minor) / (this.major * this.major);\n }\n\n /** Compatibility alias for {@link squaredEccentricity}. */\n public get sqrEccentricity(): number {\n return this.squaredEccentricity;\n }\n\n /** First eccentricity `e`. */\n public get eccentricity(): number {\n return Math.sqrt(this.squaredEccentricity);\n }\n\n /** Second eccentricity squared `e'^2`. */\n public get secondSquaredEccentricity(): number {\n return (this.major * this.major - this.minor * this.minor) / (this.minor * this.minor);\n }\n\n /** Linear eccentricity in metres. */\n public get linearEccentricity(): number {\n return Math.sqrt(this.major * this.major - this.minor * this.minor);\n }\n\n /** Precomputed coefficient `1 - e^2`. */\n public get oneMinusSquaredEccentricity(): number {\n return 1 - this.squaredEccentricity;\n }\n\n /** Compatibility alias for {@link oneMinusSquaredEccentricity}. */\n public get oneMinusSqrEccentricity(): number {\n return this.oneMinusSquaredEccentricity;\n }\n\n /** Semi-latus rectum in metres. */\n public get semiLatusRectum(): number {\n return this.major * this.oneMinusSquaredEccentricity;\n }\n\n /**\n * Returns the prime-vertical radius of curvature at a geodetic latitude.\n *\n * @param latitudeRadians - Geodetic latitude in radians.\n * @returns Prime-vertical radius in metres.\n */\n public primeVerticalRadius(latitudeRadians: number): number {\n const sine = Math.sin(latitudeRadians);\n return this.major / Math.sqrt(1 - this.squaredEccentricity * sine * sine);\n }\n\n /**\n * Returns the meridional radius of curvature at a geodetic latitude.\n *\n * @param latitudeRadians - Geodetic latitude in radians.\n * @returns Meridional radius in metres.\n */\n public meridionalRadius(latitudeRadians: number): number {\n const sine = Math.sin(latitudeRadians);\n const denominator = 1 - this.squaredEccentricity * sine * sine;\n return (this.major * this.oneMinusSquaredEccentricity) / Math.pow(denominator, 1.5);\n }\n\n /**\n * Returns the geocentric surface radius at a latitude.\n *\n * @param latitudeRadians - Geocentric latitude in radians.\n * @returns Distance from the ellipsoid centre to its surface in metres.\n */\n public radiusAtLatitude(latitudeRadians: number): number {\n const cosine = Math.cos(latitudeRadians);\n const sine = Math.sin(latitudeRadians);\n const majorSquared = this.major * this.major;\n const minorSquared = this.minor * this.minor;\n return Math.sqrt(\n ((majorSquared * cosine) ** 2 + (minorSquared * sine) ** 2) / ((this.major * cosine) ** 2 + (this.minor * sine) ** 2),\n );\n }\n\n /**\n * Intersects a normalized geocentric direction with the ellipsoid surface.\n *\n * @param x - ECEF X component of a normalized direction.\n * @param y - ECEF Y component of a normalized direction.\n * @param z - ECEF Z component of a normalized direction.\n * @returns Distance from the centre to the surface in metres.\n */\n public radiusAtPosition(x: number, y: number, z: number): number {\n const norm = Math.hypot(x, y, z);\n if (Math.abs(norm - 1) > 1e-12) throw new RangeError(\"Direction passed to radiusAtPosition must be normalized.\");\n const denominator = (x * x + y * y) / (this.major * this.major) + (z * z) / (this.minor * this.minor);\n return 1 / Math.sqrt(denominator);\n }\n\n /**\n * Tests geometric equality independently from the ellipsoid name.\n *\n * @param other - Ellipsoid to compare.\n * @returns `true` when both axes are exactly equal.\n */\n public equals(other: Ellipsoid): boolean {\n return other.major === this.major && other.minor === this.minor;\n }\n\n /**\n * Creates a uniformly scaled ellipsoid.\n *\n * @param scale - Positive uniform scale applied to both axes.\n * @param name - Name assigned to the scaled instance.\n * @returns A new ellipsoid with unchanged flattening.\n */\n public scaled(scale: number, name = `${this.name} x ${scale}`): Ellipsoid {\n if (!Number.isFinite(scale) || scale <= 0) throw new RangeError(\"Ellipsoid scale must be a positive finite number.\");\n return new Ellipsoid(name, this.major * scale, this.minor * scale);\n }\n\n /**\n * Compatibility alias for {@link scaled}.\n *\n * @param name - Name assigned to the cloned instance.\n * @param scale - Positive uniform scale applied to both axes.\n * @returns A new ellipsoid.\n */\n public clone(name: string, scale = 1): Ellipsoid {\n return this.scaled(scale, name);\n }\n}\n"]}
@@ -0,0 +1,488 @@
1
+ import { Ellipsoid } from './chunk-RJFTT4KI.js';
2
+
3
+ // src/angles.ts
4
+ var DEGREES_TO_RADIANS = Math.PI / 180;
5
+ var RADIANS_TO_DEGREES = 180 / Math.PI;
6
+ var TWO_PI = Math.PI * 2;
7
+ function toRadians(degrees) {
8
+ return degrees * DEGREES_TO_RADIANS;
9
+ }
10
+ function toDegrees(radians) {
11
+ return radians * RADIANS_TO_DEGREES;
12
+ }
13
+ function normalizeLongitudeRadians(longitudeRadians) {
14
+ return ((longitudeRadians + Math.PI) % TWO_PI + TWO_PI) % TWO_PI - Math.PI;
15
+ }
16
+ function normalizeLongitudeDegrees(longitudeDegrees) {
17
+ return ((longitudeDegrees + 180) % 360 + 360) % 360 - 180;
18
+ }
19
+
20
+ // src/geodetic-system.ts
21
+ var POLE_EPSILON = 1e-12;
22
+ var CONVERGENCE_EPSILON = 1e-14;
23
+ var MAX_GEODETIC_ITERATIONS = 10;
24
+ function cartesianTarget(target) {
25
+ return target ?? { x: 0, y: 0, z: 0 };
26
+ }
27
+ function geodeticTarget(target) {
28
+ return target ?? { latitude: 0, longitude: 0, height: 0 };
29
+ }
30
+ function validateGeodetic(latitudeRadians, longitudeRadians, height) {
31
+ if (!Number.isFinite(latitudeRadians) || latitudeRadians < -Math.PI / 2 || latitudeRadians > Math.PI / 2) {
32
+ throw new RangeError("Geodetic latitude must be a finite value in the interval [-PI/2, PI/2].");
33
+ }
34
+ if (!Number.isFinite(longitudeRadians)) throw new RangeError("Geodetic longitude must be finite.");
35
+ if (!Number.isFinite(height)) throw new RangeError("Ellipsoidal height must be finite.");
36
+ }
37
+ function validateCartesian(position) {
38
+ if (!Number.isFinite(position.x) || !Number.isFinite(position.y) || !Number.isFinite(position.z)) {
39
+ throw new RangeError("Cartesian coordinates must be finite.");
40
+ }
41
+ }
42
+ function dot(left, right) {
43
+ return left.x * right.x + left.y * right.y + left.z * right.z;
44
+ }
45
+ var GeodeticSystem = class _GeodeticSystem {
46
+ /**
47
+ * Creates a geodetic system.
48
+ *
49
+ * @param ellipsoid - Reference ellipsoid. Defaults to WGS84.
50
+ */
51
+ constructor(ellipsoid = Ellipsoid.WGS84) {
52
+ this.ellipsoid = ellipsoid;
53
+ }
54
+ ellipsoid;
55
+ /** Shared WGS84 geodetic system. The instance is immutable. */
56
+ static WGS84 = new _GeodeticSystem(Ellipsoid.WGS84);
57
+ /**
58
+ * Converts geodetic coordinates in radians to ECEF.
59
+ *
60
+ * @param latitudeRadians - Geodetic latitude in radians.
61
+ * @param longitudeRadians - Longitude in radians east of the reference meridian.
62
+ * @param height - Ellipsoidal height in metres.
63
+ * @param target - Optional mutable output object, used to avoid an allocation.
64
+ * @returns The target populated with ECEF metres.
65
+ */
66
+ geodeticRadiansToEcef(latitudeRadians, longitudeRadians, height = 0, target) {
67
+ validateGeodetic(latitudeRadians, longitudeRadians, height);
68
+ const output = cartesianTarget(target);
69
+ const sineLatitude = Math.sin(latitudeRadians);
70
+ const cosineLatitude = Math.cos(latitudeRadians);
71
+ const cosineLongitude = Math.cos(longitudeRadians);
72
+ const sineLongitude = Math.sin(longitudeRadians);
73
+ const primeVerticalRadius = this.ellipsoid.primeVerticalRadius(latitudeRadians);
74
+ const horizontalRadius = (primeVerticalRadius + height) * cosineLatitude;
75
+ output.x = horizontalRadius * cosineLongitude;
76
+ output.y = horizontalRadius * sineLongitude;
77
+ output.z = (primeVerticalRadius * this.ellipsoid.oneMinusSquaredEccentricity + height) * sineLatitude;
78
+ return output;
79
+ }
80
+ /**
81
+ * Converts geodetic coordinates in degrees to ECEF.
82
+ *
83
+ * @param latitudeDegrees - Geodetic latitude in degrees.
84
+ * @param longitudeDegrees - Longitude in degrees east of the reference meridian.
85
+ * @param height - Ellipsoidal height in metres.
86
+ * @param target - Optional mutable output object, used to avoid an allocation.
87
+ * @returns The target populated with ECEF metres.
88
+ */
89
+ geodeticDegreesToEcef(latitudeDegrees, longitudeDegrees, height = 0, target) {
90
+ return this.geodeticRadiansToEcef(toRadians(latitudeDegrees), toRadians(longitudeDegrees), height, target);
91
+ }
92
+ /**
93
+ * Converts ECEF coordinates to geodetic coordinates in radians.
94
+ *
95
+ * Bowring initialization followed by a bounded fixed-point refinement gives
96
+ * stable results at the equator, at the poles, below the ellipsoid and at
97
+ * orbital altitudes. The ellipsoid centre is rejected because it has no
98
+ * unique latitude or longitude.
99
+ *
100
+ * @param position - ECEF coordinate in metres.
101
+ * @param target - Optional mutable output object, used to avoid an allocation.
102
+ * @returns Geodetic latitude and longitude in radians, with height in metres.
103
+ */
104
+ ecefToGeodeticRadians(position, target) {
105
+ validateCartesian(position);
106
+ const output = geodeticTarget(target);
107
+ const { x, y, z } = position;
108
+ const distanceFromAxis = Math.hypot(x, y);
109
+ if (distanceFromAxis < POLE_EPSILON) {
110
+ if (Math.abs(z) < POLE_EPSILON) throw new RangeError("The ellipsoid centre has no unique geodetic coordinate.");
111
+ output.latitude = z > 0 ? Math.PI / 2 : -Math.PI / 2;
112
+ output.longitude = 0;
113
+ output.height = Math.abs(z) - this.ellipsoid.semiMinorAxis;
114
+ return output;
115
+ }
116
+ const major = this.ellipsoid.semiMajorAxis;
117
+ const minor = this.ellipsoid.semiMinorAxis;
118
+ const eccentricitySquared = this.ellipsoid.squaredEccentricity;
119
+ const secondEccentricitySquared = this.ellipsoid.secondSquaredEccentricity;
120
+ const longitude = Math.atan2(y, x);
121
+ const bowringAngle = Math.atan2(z * major, distanceFromAxis * minor);
122
+ const sineBowring = Math.sin(bowringAngle);
123
+ const cosineBowring = Math.cos(bowringAngle);
124
+ let latitude = Math.atan2(
125
+ z + secondEccentricitySquared * minor * sineBowring ** 3,
126
+ distanceFromAxis - eccentricitySquared * major * cosineBowring ** 3
127
+ );
128
+ let height = 0;
129
+ for (let iteration = 0; iteration < MAX_GEODETIC_ITERATIONS; iteration++) {
130
+ const sineLatitude2 = Math.sin(latitude);
131
+ const cosineLatitude2 = Math.cos(latitude);
132
+ const primeVerticalRadius2 = this.ellipsoid.primeVerticalRadius(latitude);
133
+ height = Math.abs(cosineLatitude2) > 1e-10 ? distanceFromAxis / cosineLatitude2 - primeVerticalRadius2 : z / sineLatitude2 - primeVerticalRadius2 * this.ellipsoid.oneMinusSquaredEccentricity;
134
+ const denominator = 1 - eccentricitySquared * primeVerticalRadius2 / (primeVerticalRadius2 + height);
135
+ const nextLatitude = Math.atan2(z, distanceFromAxis * denominator);
136
+ if (Math.abs(nextLatitude - latitude) <= CONVERGENCE_EPSILON) {
137
+ latitude = nextLatitude;
138
+ break;
139
+ }
140
+ latitude = nextLatitude;
141
+ }
142
+ const sineLatitude = Math.sin(latitude);
143
+ const cosineLatitude = Math.cos(latitude);
144
+ const primeVerticalRadius = this.ellipsoid.primeVerticalRadius(latitude);
145
+ height = Math.abs(cosineLatitude) > 1e-10 ? distanceFromAxis / cosineLatitude - primeVerticalRadius : z / sineLatitude - primeVerticalRadius * this.ellipsoid.oneMinusSquaredEccentricity;
146
+ output.latitude = latitude;
147
+ output.longitude = normalizeLongitudeRadians(longitude);
148
+ output.height = height;
149
+ return output;
150
+ }
151
+ /**
152
+ * Converts ECEF coordinates to geodetic coordinates in degrees.
153
+ *
154
+ * @param position - ECEF coordinate in metres.
155
+ * @param target - Optional mutable output object, used to avoid an allocation.
156
+ * @returns Geodetic latitude and longitude in degrees, with height in metres.
157
+ */
158
+ ecefToGeodeticDegrees(position, target) {
159
+ const output = this.ecefToGeodeticRadians(position, target);
160
+ output.latitude = toDegrees(output.latitude);
161
+ output.longitude = toDegrees(output.longitude);
162
+ return output;
163
+ }
164
+ /**
165
+ * Returns the outward ellipsoid-normal unit vector at geodetic coordinates.
166
+ *
167
+ * @param latitudeRadians - Geodetic latitude in radians.
168
+ * @param longitudeRadians - Longitude in radians.
169
+ * @param target - Optional mutable output object.
170
+ * @returns Unit vector expressed in ECEF axes.
171
+ */
172
+ geodeticSurfaceNormalRadians(latitudeRadians, longitudeRadians, target) {
173
+ validateGeodetic(latitudeRadians, longitudeRadians, 0);
174
+ const output = cartesianTarget(target);
175
+ const cosineLatitude = Math.cos(latitudeRadians);
176
+ output.x = cosineLatitude * Math.cos(longitudeRadians);
177
+ output.y = cosineLatitude * Math.sin(longitudeRadians);
178
+ output.z = Math.sin(latitudeRadians);
179
+ return output;
180
+ }
181
+ /**
182
+ * Returns the outward ellipsoid-normal unit vector at geodetic coordinates.
183
+ *
184
+ * @param latitudeDegrees - Geodetic latitude in degrees.
185
+ * @param longitudeDegrees - Longitude in degrees.
186
+ * @param target - Optional mutable output object.
187
+ * @returns Unit vector expressed in ECEF axes.
188
+ */
189
+ geodeticSurfaceNormalDegrees(latitudeDegrees, longitudeDegrees, target) {
190
+ return this.geodeticSurfaceNormalRadians(toRadians(latitudeDegrees), toRadians(longitudeDegrees), target);
191
+ }
192
+ /**
193
+ * Creates an immutable local east, north, up tangent plane.
194
+ *
195
+ * @param latitudeRadians - Origin geodetic latitude in radians.
196
+ * @param longitudeRadians - Origin longitude in radians.
197
+ * @param height - Origin ellipsoidal height in metres.
198
+ * @returns A local tangent plane bound to this geodetic system.
199
+ */
200
+ createLocalTangentPlaneRadians(latitudeRadians, longitudeRadians, height = 0) {
201
+ return new LocalTangentPlane(this, { latitude: latitudeRadians, longitude: longitudeRadians, height });
202
+ }
203
+ /**
204
+ * Creates an immutable local east, north, up tangent plane.
205
+ *
206
+ * @param latitudeDegrees - Origin geodetic latitude in degrees.
207
+ * @param longitudeDegrees - Origin longitude in degrees.
208
+ * @param height - Origin ellipsoidal height in metres.
209
+ * @returns A local tangent plane bound to this geodetic system.
210
+ */
211
+ createLocalTangentPlaneDegrees(latitudeDegrees, longitudeDegrees, height = 0) {
212
+ return this.createLocalTangentPlaneRadians(toRadians(latitudeDegrees), toRadians(longitudeDegrees), height);
213
+ }
214
+ };
215
+ var LocalTangentPlane = class {
216
+ /**
217
+ * Creates a local tangent plane.
218
+ *
219
+ * Prefer {@link GeodeticSystem.createLocalTangentPlaneRadians} or
220
+ * {@link GeodeticSystem.createLocalTangentPlaneDegrees}, which make the
221
+ * angular unit explicit at the call site.
222
+ *
223
+ * @param system - Geodetic reference system.
224
+ * @param originRadians - Origin with angular components in radians.
225
+ */
226
+ constructor(system, originRadians) {
227
+ this.system = system;
228
+ validateGeodetic(originRadians.latitude, originRadians.longitude, originRadians.height);
229
+ this.origin = { ...originRadians, longitude: normalizeLongitudeRadians(originRadians.longitude) };
230
+ this.originCartesian = system.geodeticRadiansToEcef(this.origin.latitude, this.origin.longitude, this.origin.height);
231
+ const sineLatitude = Math.sin(this.origin.latitude);
232
+ const cosineLatitude = Math.cos(this.origin.latitude);
233
+ const sineLongitude = Math.sin(this.origin.longitude);
234
+ const cosineLongitude = Math.cos(this.origin.longitude);
235
+ this.tangentBasis = {
236
+ east: { x: -sineLongitude, y: cosineLongitude, z: 0 },
237
+ north: {
238
+ x: -sineLatitude * cosineLongitude,
239
+ y: -sineLatitude * sineLongitude,
240
+ z: cosineLatitude
241
+ },
242
+ up: {
243
+ x: cosineLatitude * cosineLongitude,
244
+ y: cosineLatitude * sineLongitude,
245
+ z: sineLatitude
246
+ }
247
+ };
248
+ const { east, north, up } = this.tangentBasis;
249
+ this.toEnu = new Float64Array([
250
+ east.x,
251
+ north.x,
252
+ up.x,
253
+ 0,
254
+ east.y,
255
+ north.y,
256
+ up.y,
257
+ 0,
258
+ east.z,
259
+ north.z,
260
+ up.z,
261
+ 0,
262
+ -dot(east, this.originCartesian),
263
+ -dot(north, this.originCartesian),
264
+ -dot(up, this.originCartesian),
265
+ 1
266
+ ]);
267
+ this.fromEnu = new Float64Array([
268
+ east.x,
269
+ east.y,
270
+ east.z,
271
+ 0,
272
+ north.x,
273
+ north.y,
274
+ north.z,
275
+ 0,
276
+ up.x,
277
+ up.y,
278
+ up.z,
279
+ 0,
280
+ this.originCartesian.x,
281
+ this.originCartesian.y,
282
+ this.originCartesian.z,
283
+ 1
284
+ ]);
285
+ this.toNed = new Float64Array([
286
+ north.x,
287
+ east.x,
288
+ -up.x,
289
+ 0,
290
+ north.y,
291
+ east.y,
292
+ -up.y,
293
+ 0,
294
+ north.z,
295
+ east.z,
296
+ -up.z,
297
+ 0,
298
+ -dot(north, this.originCartesian),
299
+ -dot(east, this.originCartesian),
300
+ dot(up, this.originCartesian),
301
+ 1
302
+ ]);
303
+ this.fromNed = new Float64Array([
304
+ north.x,
305
+ north.y,
306
+ north.z,
307
+ 0,
308
+ east.x,
309
+ east.y,
310
+ east.z,
311
+ 0,
312
+ -up.x,
313
+ -up.y,
314
+ -up.z,
315
+ 0,
316
+ this.originCartesian.x,
317
+ this.originCartesian.y,
318
+ this.originCartesian.z,
319
+ 1
320
+ ]);
321
+ }
322
+ system;
323
+ origin;
324
+ originCartesian;
325
+ tangentBasis;
326
+ toEnu;
327
+ fromEnu;
328
+ toNed;
329
+ fromNed;
330
+ /** Origin geodetic coordinate with latitude and longitude in radians. */
331
+ get originRadians() {
332
+ return { ...this.origin };
333
+ }
334
+ /** Origin geodetic coordinate with latitude and longitude in degrees. */
335
+ get originDegrees() {
336
+ return {
337
+ latitude: toDegrees(this.origin.latitude),
338
+ longitude: toDegrees(this.origin.longitude),
339
+ height: this.origin.height
340
+ };
341
+ }
342
+ /** Origin expressed as ECEF metres. */
343
+ get originEcef() {
344
+ return { ...this.originCartesian };
345
+ }
346
+ /** Canonical east, north and up tangent basis expressed as ECEF unit vectors. */
347
+ get basis() {
348
+ return {
349
+ east: { ...this.tangentBasis.east },
350
+ north: { ...this.tangentBasis.north },
351
+ up: { ...this.tangentBasis.up }
352
+ };
353
+ }
354
+ /** Column-major matrix transforming ECEF positions to ENU positions. */
355
+ get ecefToEnuMatrix() {
356
+ return new Float64Array(this.toEnu);
357
+ }
358
+ /** Column-major matrix transforming ENU positions to ECEF positions. */
359
+ get enuToEcefMatrix() {
360
+ return new Float64Array(this.fromEnu);
361
+ }
362
+ /** Column-major matrix transforming ECEF positions to NED positions. */
363
+ get ecefToNedMatrix() {
364
+ return new Float64Array(this.toNed);
365
+ }
366
+ /** Column-major matrix transforming NED positions to ECEF positions. */
367
+ get nedToEcefMatrix() {
368
+ return new Float64Array(this.fromNed);
369
+ }
370
+ /**
371
+ * Converts an ECEF position to local ENU metres.
372
+ *
373
+ * @param position - ECEF position in metres.
374
+ * @param target - Optional mutable output object.
375
+ * @returns Local coordinate with X east, Y north and Z up.
376
+ */
377
+ ecefToEnu(position, target) {
378
+ validateCartesian(position);
379
+ const output = cartesianTarget(target);
380
+ const delta = {
381
+ x: position.x - this.originCartesian.x,
382
+ y: position.y - this.originCartesian.y,
383
+ z: position.z - this.originCartesian.z
384
+ };
385
+ output.x = dot(this.tangentBasis.east, delta);
386
+ output.y = dot(this.tangentBasis.north, delta);
387
+ output.z = dot(this.tangentBasis.up, delta);
388
+ return output;
389
+ }
390
+ /**
391
+ * Converts a local ENU position to ECEF metres.
392
+ *
393
+ * @param position - Local coordinate with X east, Y north and Z up.
394
+ * @param target - Optional mutable output object.
395
+ * @returns ECEF coordinate in metres.
396
+ */
397
+ enuToEcef(position, target) {
398
+ validateCartesian(position);
399
+ const output = cartesianTarget(target);
400
+ output.x = this.originCartesian.x + this.tangentBasis.east.x * position.x + this.tangentBasis.north.x * position.y + this.tangentBasis.up.x * position.z;
401
+ output.y = this.originCartesian.y + this.tangentBasis.east.y * position.x + this.tangentBasis.north.y * position.y + this.tangentBasis.up.y * position.z;
402
+ output.z = this.originCartesian.z + this.tangentBasis.east.z * position.x + this.tangentBasis.north.z * position.y + this.tangentBasis.up.z * position.z;
403
+ return output;
404
+ }
405
+ /**
406
+ * Converts an ECEF position to local NED metres.
407
+ *
408
+ * @param position - ECEF position in metres.
409
+ * @param target - Optional mutable output object.
410
+ * @returns Local coordinate with X north, Y east and Z down.
411
+ */
412
+ ecefToNed(position, target) {
413
+ validateCartesian(position);
414
+ const output = cartesianTarget(target);
415
+ const delta = {
416
+ x: position.x - this.originCartesian.x,
417
+ y: position.y - this.originCartesian.y,
418
+ z: position.z - this.originCartesian.z
419
+ };
420
+ output.x = dot(this.tangentBasis.north, delta);
421
+ output.y = dot(this.tangentBasis.east, delta);
422
+ output.z = -dot(this.tangentBasis.up, delta);
423
+ return output;
424
+ }
425
+ /**
426
+ * Converts a local NED position to ECEF metres.
427
+ *
428
+ * @param position - Local coordinate with X north, Y east and Z down.
429
+ * @param target - Optional mutable output object.
430
+ * @returns ECEF coordinate in metres.
431
+ */
432
+ nedToEcef(position, target) {
433
+ validateCartesian(position);
434
+ const output = cartesianTarget(target);
435
+ output.x = this.originCartesian.x + this.tangentBasis.north.x * position.x + this.tangentBasis.east.x * position.y - this.tangentBasis.up.x * position.z;
436
+ output.y = this.originCartesian.y + this.tangentBasis.north.y * position.x + this.tangentBasis.east.y * position.y - this.tangentBasis.up.y * position.z;
437
+ output.z = this.originCartesian.z + this.tangentBasis.north.z * position.x + this.tangentBasis.east.z * position.y - this.tangentBasis.up.z * position.z;
438
+ return output;
439
+ }
440
+ /**
441
+ * Converts geodetic radians directly to local ENU metres.
442
+ *
443
+ * @param latitudeRadians - Geodetic latitude in radians.
444
+ * @param longitudeRadians - Longitude in radians.
445
+ * @param height - Ellipsoidal height in metres.
446
+ * @param target - Optional mutable output object.
447
+ * @returns Local coordinate with X east, Y north and Z up.
448
+ */
449
+ geodeticRadiansToEnu(latitudeRadians, longitudeRadians, height = 0, target) {
450
+ return this.ecefToEnu(this.system.geodeticRadiansToEcef(latitudeRadians, longitudeRadians, height), target);
451
+ }
452
+ /**
453
+ * Converts geodetic degrees directly to local ENU metres.
454
+ *
455
+ * @param latitudeDegrees - Geodetic latitude in degrees.
456
+ * @param longitudeDegrees - Longitude in degrees.
457
+ * @param height - Ellipsoidal height in metres.
458
+ * @param target - Optional mutable output object.
459
+ * @returns Local coordinate with X east, Y north and Z up.
460
+ */
461
+ geodeticDegreesToEnu(latitudeDegrees, longitudeDegrees, height = 0, target) {
462
+ return this.ecefToEnu(this.system.geodeticDegreesToEcef(latitudeDegrees, longitudeDegrees, height), target);
463
+ }
464
+ /**
465
+ * Converts local ENU metres directly to geodetic radians.
466
+ *
467
+ * @param position - Local coordinate with X east, Y north and Z up.
468
+ * @param target - Optional mutable output object.
469
+ * @returns Geodetic latitude and longitude in radians, with height in metres.
470
+ */
471
+ enuToGeodeticRadians(position, target) {
472
+ return this.system.ecefToGeodeticRadians(this.enuToEcef(position), target);
473
+ }
474
+ /**
475
+ * Converts local ENU metres directly to geodetic degrees.
476
+ *
477
+ * @param position - Local coordinate with X east, Y north and Z up.
478
+ * @param target - Optional mutable output object.
479
+ * @returns Geodetic latitude and longitude in degrees, with height in metres.
480
+ */
481
+ enuToGeodeticDegrees(position, target) {
482
+ return this.system.ecefToGeodeticDegrees(this.enuToEcef(position), target);
483
+ }
484
+ };
485
+
486
+ export { DEGREES_TO_RADIANS, GeodeticSystem, LocalTangentPlane, RADIANS_TO_DEGREES, TWO_PI, normalizeLongitudeDegrees, normalizeLongitudeRadians, toDegrees, toRadians };
487
+ //# sourceMappingURL=chunk-WYCQOUE7.js.map
488
+ //# sourceMappingURL=chunk-WYCQOUE7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/angles.ts","../src/geodetic-system.ts"],"names":["sineLatitude","cosineLatitude","primeVerticalRadius"],"mappings":"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","file":"chunk-WYCQOUE7.js","sourcesContent":["/** Number of radians in one degree. */\nexport const DEGREES_TO_RADIANS = Math.PI / 180;\n\n/** Number of degrees in one radian. */\nexport const RADIANS_TO_DEGREES = 180 / Math.PI;\n\n/** Full turn in radians. */\nexport const TWO_PI = Math.PI * 2;\n\n/**\n * Converts an angle from degrees to radians.\n *\n * @param degrees - Angle in degrees.\n * @returns The equivalent angle in radians.\n */\nexport function toRadians(degrees: number): number {\n return degrees * DEGREES_TO_RADIANS;\n}\n\n/**\n * Converts an angle from radians to degrees.\n *\n * @param radians - Angle in radians.\n * @returns The equivalent angle in degrees.\n */\nexport function toDegrees(radians: number): number {\n return radians * RADIANS_TO_DEGREES;\n}\n\n/**\n * Normalizes a longitude to the half-open interval `[-PI, PI)`.\n *\n * @param longitudeRadians - Longitude in radians.\n * @returns Normalized longitude in radians.\n */\nexport function normalizeLongitudeRadians(longitudeRadians: number): number {\n return ((((longitudeRadians + Math.PI) % TWO_PI) + TWO_PI) % TWO_PI) - Math.PI;\n}\n\n/**\n * Normalizes a longitude to the half-open interval `[-180, 180)`.\n *\n * @param longitudeDegrees - Longitude in degrees.\n * @returns Normalized longitude in degrees.\n */\nexport function normalizeLongitudeDegrees(longitudeDegrees: number): number {\n return ((((longitudeDegrees + 180) % 360) + 360) % 360) - 180;\n}\n","import { normalizeLongitudeRadians, toDegrees, toRadians } from \"./angles\";\nimport { Ellipsoid } from \"./ellipsoid\";\nimport type { ICartesian3, IGeodeticCoordinates, ILocalTangentBasis } from \"./types\";\n\nconst POLE_EPSILON = 1e-12;\nconst CONVERGENCE_EPSILON = 1e-14;\nconst MAX_GEODETIC_ITERATIONS = 10;\n\nfunction cartesianTarget(target?: ICartesian3): ICartesian3 {\n return target ?? { x: 0, y: 0, z: 0 };\n}\n\nfunction geodeticTarget(target?: IGeodeticCoordinates): IGeodeticCoordinates {\n return target ?? { latitude: 0, longitude: 0, height: 0 };\n}\n\nfunction validateGeodetic(latitudeRadians: number, longitudeRadians: number, height: number): void {\n if (!Number.isFinite(latitudeRadians) || latitudeRadians < -Math.PI / 2 || latitudeRadians > Math.PI / 2) {\n throw new RangeError(\"Geodetic latitude must be a finite value in the interval [-PI/2, PI/2].\");\n }\n if (!Number.isFinite(longitudeRadians)) throw new RangeError(\"Geodetic longitude must be finite.\");\n if (!Number.isFinite(height)) throw new RangeError(\"Ellipsoidal height must be finite.\");\n}\n\nfunction validateCartesian(position: ICartesian3): void {\n if (!Number.isFinite(position.x) || !Number.isFinite(position.y) || !Number.isFinite(position.z)) {\n throw new RangeError(\"Cartesian coordinates must be finite.\");\n }\n}\n\nfunction dot(left: ICartesian3, right: ICartesian3): number {\n return left.x * right.x + left.y * right.y + left.z * right.z;\n}\n\n/**\n * Immutable geodetic reference system backed by one reference ellipsoid.\n *\n * ECEF follows EPSG:4978 axis conventions: X crosses latitude 0 and longitude\n * 0, Y crosses latitude 0 and longitude 90 degrees east, and Z crosses the\n * north pole. Cartesian distances and ellipsoidal heights are expressed in\n * metres.\n */\nexport class GeodeticSystem {\n /** Shared WGS84 geodetic system. The instance is immutable. */\n public static readonly WGS84 = new GeodeticSystem(Ellipsoid.WGS84);\n\n /**\n * Creates a geodetic system.\n *\n * @param ellipsoid - Reference ellipsoid. Defaults to WGS84.\n */\n public constructor(public readonly ellipsoid: Ellipsoid = Ellipsoid.WGS84) {}\n\n /**\n * Converts geodetic coordinates in radians to ECEF.\n *\n * @param latitudeRadians - Geodetic latitude in radians.\n * @param longitudeRadians - Longitude in radians east of the reference meridian.\n * @param height - Ellipsoidal height in metres.\n * @param target - Optional mutable output object, used to avoid an allocation.\n * @returns The target populated with ECEF metres.\n */\n public geodeticRadiansToEcef(latitudeRadians: number, longitudeRadians: number, height = 0, target?: ICartesian3): ICartesian3 {\n validateGeodetic(latitudeRadians, longitudeRadians, height);\n const output = cartesianTarget(target);\n const sineLatitude = Math.sin(latitudeRadians);\n const cosineLatitude = Math.cos(latitudeRadians);\n const cosineLongitude = Math.cos(longitudeRadians);\n const sineLongitude = Math.sin(longitudeRadians);\n const primeVerticalRadius = this.ellipsoid.primeVerticalRadius(latitudeRadians);\n const horizontalRadius = (primeVerticalRadius + height) * cosineLatitude;\n output.x = horizontalRadius * cosineLongitude;\n output.y = horizontalRadius * sineLongitude;\n output.z = (primeVerticalRadius * this.ellipsoid.oneMinusSquaredEccentricity + height) * sineLatitude;\n return output;\n }\n\n /**\n * Converts geodetic coordinates in degrees to ECEF.\n *\n * @param latitudeDegrees - Geodetic latitude in degrees.\n * @param longitudeDegrees - Longitude in degrees east of the reference meridian.\n * @param height - Ellipsoidal height in metres.\n * @param target - Optional mutable output object, used to avoid an allocation.\n * @returns The target populated with ECEF metres.\n */\n public geodeticDegreesToEcef(latitudeDegrees: number, longitudeDegrees: number, height = 0, target?: ICartesian3): ICartesian3 {\n return this.geodeticRadiansToEcef(toRadians(latitudeDegrees), toRadians(longitudeDegrees), height, target);\n }\n\n /**\n * Converts ECEF coordinates to geodetic coordinates in radians.\n *\n * Bowring initialization followed by a bounded fixed-point refinement gives\n * stable results at the equator, at the poles, below the ellipsoid and at\n * orbital altitudes. The ellipsoid centre is rejected because it has no\n * unique latitude or longitude.\n *\n * @param position - ECEF coordinate in metres.\n * @param target - Optional mutable output object, used to avoid an allocation.\n * @returns Geodetic latitude and longitude in radians, with height in metres.\n */\n public ecefToGeodeticRadians(position: ICartesian3, target?: IGeodeticCoordinates): IGeodeticCoordinates {\n validateCartesian(position);\n const output = geodeticTarget(target);\n const { x, y, z } = position;\n const distanceFromAxis = Math.hypot(x, y);\n if (distanceFromAxis < POLE_EPSILON) {\n if (Math.abs(z) < POLE_EPSILON) throw new RangeError(\"The ellipsoid centre has no unique geodetic coordinate.\");\n output.latitude = z > 0 ? Math.PI / 2 : -Math.PI / 2;\n output.longitude = 0;\n output.height = Math.abs(z) - this.ellipsoid.semiMinorAxis;\n return output;\n }\n\n const major = this.ellipsoid.semiMajorAxis;\n const minor = this.ellipsoid.semiMinorAxis;\n const eccentricitySquared = this.ellipsoid.squaredEccentricity;\n const secondEccentricitySquared = this.ellipsoid.secondSquaredEccentricity;\n const longitude = Math.atan2(y, x);\n const bowringAngle = Math.atan2(z * major, distanceFromAxis * minor);\n const sineBowring = Math.sin(bowringAngle);\n const cosineBowring = Math.cos(bowringAngle);\n let latitude = Math.atan2(\n z + secondEccentricitySquared * minor * sineBowring ** 3,\n distanceFromAxis - eccentricitySquared * major * cosineBowring ** 3,\n );\n\n let height = 0;\n for (let iteration = 0; iteration < MAX_GEODETIC_ITERATIONS; iteration++) {\n const sineLatitude = Math.sin(latitude);\n const cosineLatitude = Math.cos(latitude);\n const primeVerticalRadius = this.ellipsoid.primeVerticalRadius(latitude);\n height =\n Math.abs(cosineLatitude) > 1e-10\n ? distanceFromAxis / cosineLatitude - primeVerticalRadius\n : z / sineLatitude - primeVerticalRadius * this.ellipsoid.oneMinusSquaredEccentricity;\n const denominator = 1 - (eccentricitySquared * primeVerticalRadius) / (primeVerticalRadius + height);\n const nextLatitude = Math.atan2(z, distanceFromAxis * denominator);\n if (Math.abs(nextLatitude - latitude) <= CONVERGENCE_EPSILON) {\n latitude = nextLatitude;\n break;\n }\n latitude = nextLatitude;\n }\n\n const sineLatitude = Math.sin(latitude);\n const cosineLatitude = Math.cos(latitude);\n const primeVerticalRadius = this.ellipsoid.primeVerticalRadius(latitude);\n height =\n Math.abs(cosineLatitude) > 1e-10\n ? distanceFromAxis / cosineLatitude - primeVerticalRadius\n : z / sineLatitude - primeVerticalRadius * this.ellipsoid.oneMinusSquaredEccentricity;\n\n output.latitude = latitude;\n output.longitude = normalizeLongitudeRadians(longitude);\n output.height = height;\n return output;\n }\n\n /**\n * Converts ECEF coordinates to geodetic coordinates in degrees.\n *\n * @param position - ECEF coordinate in metres.\n * @param target - Optional mutable output object, used to avoid an allocation.\n * @returns Geodetic latitude and longitude in degrees, with height in metres.\n */\n public ecefToGeodeticDegrees(position: ICartesian3, target?: IGeodeticCoordinates): IGeodeticCoordinates {\n const output = this.ecefToGeodeticRadians(position, target);\n output.latitude = toDegrees(output.latitude);\n output.longitude = toDegrees(output.longitude);\n return output;\n }\n\n /**\n * Returns the outward ellipsoid-normal unit vector at geodetic coordinates.\n *\n * @param latitudeRadians - Geodetic latitude in radians.\n * @param longitudeRadians - Longitude in radians.\n * @param target - Optional mutable output object.\n * @returns Unit vector expressed in ECEF axes.\n */\n public geodeticSurfaceNormalRadians(latitudeRadians: number, longitudeRadians: number, target?: ICartesian3): ICartesian3 {\n validateGeodetic(latitudeRadians, longitudeRadians, 0);\n const output = cartesianTarget(target);\n const cosineLatitude = Math.cos(latitudeRadians);\n output.x = cosineLatitude * Math.cos(longitudeRadians);\n output.y = cosineLatitude * Math.sin(longitudeRadians);\n output.z = Math.sin(latitudeRadians);\n return output;\n }\n\n /**\n * Returns the outward ellipsoid-normal unit vector at geodetic coordinates.\n *\n * @param latitudeDegrees - Geodetic latitude in degrees.\n * @param longitudeDegrees - Longitude in degrees.\n * @param target - Optional mutable output object.\n * @returns Unit vector expressed in ECEF axes.\n */\n public geodeticSurfaceNormalDegrees(latitudeDegrees: number, longitudeDegrees: number, target?: ICartesian3): ICartesian3 {\n return this.geodeticSurfaceNormalRadians(toRadians(latitudeDegrees), toRadians(longitudeDegrees), target);\n }\n\n /**\n * Creates an immutable local east, north, up tangent plane.\n *\n * @param latitudeRadians - Origin geodetic latitude in radians.\n * @param longitudeRadians - Origin longitude in radians.\n * @param height - Origin ellipsoidal height in metres.\n * @returns A local tangent plane bound to this geodetic system.\n */\n public createLocalTangentPlaneRadians(latitudeRadians: number, longitudeRadians: number, height = 0): LocalTangentPlane {\n return new LocalTangentPlane(this, { latitude: latitudeRadians, longitude: longitudeRadians, height });\n }\n\n /**\n * Creates an immutable local east, north, up tangent plane.\n *\n * @param latitudeDegrees - Origin geodetic latitude in degrees.\n * @param longitudeDegrees - Origin longitude in degrees.\n * @param height - Origin ellipsoidal height in metres.\n * @returns A local tangent plane bound to this geodetic system.\n */\n public createLocalTangentPlaneDegrees(latitudeDegrees: number, longitudeDegrees: number, height = 0): LocalTangentPlane {\n return this.createLocalTangentPlaneRadians(toRadians(latitudeDegrees), toRadians(longitudeDegrees), height);\n }\n}\n\n/**\n * Immutable local tangent plane anchored to a geodetic coordinate.\n *\n * ENU axes are X east, Y north and Z up. NED axes are X north, Y east and Z\n * down. All local values are metres. The stored matrices use column-major\n * order and multiply column vectors, matching glTF and 3D Tiles transforms.\n */\nexport class LocalTangentPlane {\n private readonly origin: IGeodeticCoordinates;\n private readonly originCartesian: ICartesian3;\n private readonly tangentBasis: ILocalTangentBasis;\n private readonly toEnu: Float64Array;\n private readonly fromEnu: Float64Array;\n private readonly toNed: Float64Array;\n private readonly fromNed: Float64Array;\n\n /**\n * Creates a local tangent plane.\n *\n * Prefer {@link GeodeticSystem.createLocalTangentPlaneRadians} or\n * {@link GeodeticSystem.createLocalTangentPlaneDegrees}, which make the\n * angular unit explicit at the call site.\n *\n * @param system - Geodetic reference system.\n * @param originRadians - Origin with angular components in radians.\n */\n public constructor(\n public readonly system: GeodeticSystem,\n originRadians: IGeodeticCoordinates,\n ) {\n validateGeodetic(originRadians.latitude, originRadians.longitude, originRadians.height);\n this.origin = { ...originRadians, longitude: normalizeLongitudeRadians(originRadians.longitude) };\n this.originCartesian = system.geodeticRadiansToEcef(this.origin.latitude, this.origin.longitude, this.origin.height);\n const sineLatitude = Math.sin(this.origin.latitude);\n const cosineLatitude = Math.cos(this.origin.latitude);\n const sineLongitude = Math.sin(this.origin.longitude);\n const cosineLongitude = Math.cos(this.origin.longitude);\n this.tangentBasis = {\n east: { x: -sineLongitude, y: cosineLongitude, z: 0 },\n north: {\n x: -sineLatitude * cosineLongitude,\n y: -sineLatitude * sineLongitude,\n z: cosineLatitude,\n },\n up: {\n x: cosineLatitude * cosineLongitude,\n y: cosineLatitude * sineLongitude,\n z: sineLatitude,\n },\n };\n const { east, north, up } = this.tangentBasis;\n this.toEnu = new Float64Array([\n east.x,\n north.x,\n up.x,\n 0,\n east.y,\n north.y,\n up.y,\n 0,\n east.z,\n north.z,\n up.z,\n 0,\n -dot(east, this.originCartesian),\n -dot(north, this.originCartesian),\n -dot(up, this.originCartesian),\n 1,\n ]);\n this.fromEnu = new Float64Array([\n east.x,\n east.y,\n east.z,\n 0,\n north.x,\n north.y,\n north.z,\n 0,\n up.x,\n up.y,\n up.z,\n 0,\n this.originCartesian.x,\n this.originCartesian.y,\n this.originCartesian.z,\n 1,\n ]);\n this.toNed = new Float64Array([\n north.x,\n east.x,\n -up.x,\n 0,\n north.y,\n east.y,\n -up.y,\n 0,\n north.z,\n east.z,\n -up.z,\n 0,\n -dot(north, this.originCartesian),\n -dot(east, this.originCartesian),\n dot(up, this.originCartesian),\n 1,\n ]);\n this.fromNed = new Float64Array([\n north.x,\n north.y,\n north.z,\n 0,\n east.x,\n east.y,\n east.z,\n 0,\n -up.x,\n -up.y,\n -up.z,\n 0,\n this.originCartesian.x,\n this.originCartesian.y,\n this.originCartesian.z,\n 1,\n ]);\n }\n\n /** Origin geodetic coordinate with latitude and longitude in radians. */\n public get originRadians(): IGeodeticCoordinates {\n return { ...this.origin };\n }\n\n /** Origin geodetic coordinate with latitude and longitude in degrees. */\n public get originDegrees(): IGeodeticCoordinates {\n return {\n latitude: toDegrees(this.origin.latitude),\n longitude: toDegrees(this.origin.longitude),\n height: this.origin.height,\n };\n }\n\n /** Origin expressed as ECEF metres. */\n public get originEcef(): ICartesian3 {\n return { ...this.originCartesian };\n }\n\n /** Canonical east, north and up tangent basis expressed as ECEF unit vectors. */\n public get basis(): ILocalTangentBasis {\n return {\n east: { ...this.tangentBasis.east },\n north: { ...this.tangentBasis.north },\n up: { ...this.tangentBasis.up },\n };\n }\n\n /** Column-major matrix transforming ECEF positions to ENU positions. */\n public get ecefToEnuMatrix(): Float64Array {\n return new Float64Array(this.toEnu);\n }\n\n /** Column-major matrix transforming ENU positions to ECEF positions. */\n public get enuToEcefMatrix(): Float64Array {\n return new Float64Array(this.fromEnu);\n }\n\n /** Column-major matrix transforming ECEF positions to NED positions. */\n public get ecefToNedMatrix(): Float64Array {\n return new Float64Array(this.toNed);\n }\n\n /** Column-major matrix transforming NED positions to ECEF positions. */\n public get nedToEcefMatrix(): Float64Array {\n return new Float64Array(this.fromNed);\n }\n\n /**\n * Converts an ECEF position to local ENU metres.\n *\n * @param position - ECEF position in metres.\n * @param target - Optional mutable output object.\n * @returns Local coordinate with X east, Y north and Z up.\n */\n public ecefToEnu(position: ICartesian3, target?: ICartesian3): ICartesian3 {\n validateCartesian(position);\n const output = cartesianTarget(target);\n const delta = {\n x: position.x - this.originCartesian.x,\n y: position.y - this.originCartesian.y,\n z: position.z - this.originCartesian.z,\n };\n output.x = dot(this.tangentBasis.east, delta);\n output.y = dot(this.tangentBasis.north, delta);\n output.z = dot(this.tangentBasis.up, delta);\n return output;\n }\n\n /**\n * Converts a local ENU position to ECEF metres.\n *\n * @param position - Local coordinate with X east, Y north and Z up.\n * @param target - Optional mutable output object.\n * @returns ECEF coordinate in metres.\n */\n public enuToEcef(position: ICartesian3, target?: ICartesian3): ICartesian3 {\n validateCartesian(position);\n const output = cartesianTarget(target);\n output.x =\n this.originCartesian.x +\n this.tangentBasis.east.x * position.x +\n this.tangentBasis.north.x * position.y +\n this.tangentBasis.up.x * position.z;\n output.y =\n this.originCartesian.y +\n this.tangentBasis.east.y * position.x +\n this.tangentBasis.north.y * position.y +\n this.tangentBasis.up.y * position.z;\n output.z =\n this.originCartesian.z +\n this.tangentBasis.east.z * position.x +\n this.tangentBasis.north.z * position.y +\n this.tangentBasis.up.z * position.z;\n return output;\n }\n\n /**\n * Converts an ECEF position to local NED metres.\n *\n * @param position - ECEF position in metres.\n * @param target - Optional mutable output object.\n * @returns Local coordinate with X north, Y east and Z down.\n */\n public ecefToNed(position: ICartesian3, target?: ICartesian3): ICartesian3 {\n validateCartesian(position);\n const output = cartesianTarget(target);\n const delta = {\n x: position.x - this.originCartesian.x,\n y: position.y - this.originCartesian.y,\n z: position.z - this.originCartesian.z,\n };\n output.x = dot(this.tangentBasis.north, delta);\n output.y = dot(this.tangentBasis.east, delta);\n output.z = -dot(this.tangentBasis.up, delta);\n return output;\n }\n\n /**\n * Converts a local NED position to ECEF metres.\n *\n * @param position - Local coordinate with X north, Y east and Z down.\n * @param target - Optional mutable output object.\n * @returns ECEF coordinate in metres.\n */\n public nedToEcef(position: ICartesian3, target?: ICartesian3): ICartesian3 {\n validateCartesian(position);\n const output = cartesianTarget(target);\n output.x =\n this.originCartesian.x +\n this.tangentBasis.north.x * position.x +\n this.tangentBasis.east.x * position.y -\n this.tangentBasis.up.x * position.z;\n output.y =\n this.originCartesian.y +\n this.tangentBasis.north.y * position.x +\n this.tangentBasis.east.y * position.y -\n this.tangentBasis.up.y * position.z;\n output.z =\n this.originCartesian.z +\n this.tangentBasis.north.z * position.x +\n this.tangentBasis.east.z * position.y -\n this.tangentBasis.up.z * position.z;\n return output;\n }\n\n /**\n * Converts geodetic radians directly to local ENU metres.\n *\n * @param latitudeRadians - Geodetic latitude in radians.\n * @param longitudeRadians - Longitude in radians.\n * @param height - Ellipsoidal height in metres.\n * @param target - Optional mutable output object.\n * @returns Local coordinate with X east, Y north and Z up.\n */\n public geodeticRadiansToEnu(latitudeRadians: number, longitudeRadians: number, height = 0, target?: ICartesian3): ICartesian3 {\n return this.ecefToEnu(this.system.geodeticRadiansToEcef(latitudeRadians, longitudeRadians, height), target);\n }\n\n /**\n * Converts geodetic degrees directly to local ENU metres.\n *\n * @param latitudeDegrees - Geodetic latitude in degrees.\n * @param longitudeDegrees - Longitude in degrees.\n * @param height - Ellipsoidal height in metres.\n * @param target - Optional mutable output object.\n * @returns Local coordinate with X east, Y north and Z up.\n */\n public geodeticDegreesToEnu(latitudeDegrees: number, longitudeDegrees: number, height = 0, target?: ICartesian3): ICartesian3 {\n return this.ecefToEnu(this.system.geodeticDegreesToEcef(latitudeDegrees, longitudeDegrees, height), target);\n }\n\n /**\n * Converts local ENU metres directly to geodetic radians.\n *\n * @param position - Local coordinate with X east, Y north and Z up.\n * @param target - Optional mutable output object.\n * @returns Geodetic latitude and longitude in radians, with height in metres.\n */\n public enuToGeodeticRadians(position: ICartesian3, target?: IGeodeticCoordinates): IGeodeticCoordinates {\n return this.system.ecefToGeodeticRadians(this.enuToEcef(position), target);\n }\n\n /**\n * Converts local ENU metres directly to geodetic degrees.\n *\n * @param position - Local coordinate with X east, Y north and Z up.\n * @param target - Optional mutable output object.\n * @returns Geodetic latitude and longitude in degrees, with height in metres.\n */\n public enuToGeodeticDegrees(position: ICartesian3, target?: IGeodeticCoordinates): IGeodeticCoordinates {\n return this.system.ecefToGeodeticDegrees(this.enuToEcef(position), target);\n }\n}\n"]}