@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,150 @@
1
+ /**
2
+ * Immutable oblate ellipsoid of revolution.
3
+ *
4
+ * Axis lengths are expressed in metres. The semi-major axis lies in the
5
+ * equatorial plane and the semi-minor axis follows the polar axis. Instances
6
+ * validate their dimensions and precompute the coefficients required by
7
+ * geodetic conversions.
8
+ */
9
+ declare class Ellipsoid {
10
+ private readonly identifier;
11
+ private readonly major;
12
+ private readonly minor;
13
+ /** WGS 84 reference ellipsoid used by EPSG:4978 and EPSG:4979. */
14
+ static readonly WGS84: Ellipsoid;
15
+ /** Geodetic Reference System 1980 ellipsoid. */
16
+ static readonly GRS80: Ellipsoid;
17
+ /** Geodetic Reference System 1967 ellipsoid. */
18
+ static readonly GRS67: Ellipsoid;
19
+ /** Australian National Spheroid. */
20
+ static readonly ANS: Ellipsoid;
21
+ /** World Geodetic System 1972 ellipsoid. */
22
+ static readonly WGS72: Ellipsoid;
23
+ /** Clarke 1858 ellipsoid. */
24
+ static readonly Clarke1858: Ellipsoid;
25
+ /** Clarke 1880 ellipsoid. */
26
+ static readonly Clarke1880: Ellipsoid;
27
+ private constructor();
28
+ /**
29
+ * Creates an ellipsoid from its semi-major axis and inverse flattening.
30
+ *
31
+ * `Infinity` represents a sphere.
32
+ *
33
+ * @param name - Stable human-readable ellipsoid name.
34
+ * @param semiMajorAxis - Equatorial semi-major axis in metres.
35
+ * @param inverseFlattening - Reciprocal flattening, or `Infinity` for a sphere.
36
+ * @returns A validated immutable ellipsoid.
37
+ */
38
+ static fromSemiMajorAxisAndInverseFlattening(name: string, semiMajorAxis: number, inverseFlattening: number): Ellipsoid;
39
+ /**
40
+ * Creates an ellipsoid from its semi-major axis and flattening.
41
+ *
42
+ * @param name - Stable human-readable ellipsoid name.
43
+ * @param semiMajorAxis - Equatorial semi-major axis in metres.
44
+ * @param flattening - Flattening in the interval `[0, 1)`.
45
+ * @returns A validated immutable ellipsoid.
46
+ */
47
+ static fromSemiMajorAxisAndFlattening(name: string, semiMajorAxis: number, flattening: number): Ellipsoid;
48
+ /**
49
+ * Creates an ellipsoid from its semi-major and semi-minor axes.
50
+ *
51
+ * @param name - Stable human-readable ellipsoid name.
52
+ * @param semiMajorAxis - Equatorial semi-major axis in metres.
53
+ * @param semiMinorAxis - Polar semi-minor axis in metres.
54
+ * @returns A validated immutable ellipsoid.
55
+ */
56
+ static fromAxes(name: string, semiMajorAxis: number, semiMinorAxis: number): Ellipsoid;
57
+ /**
58
+ * Creates a spherical reference surface.
59
+ *
60
+ * @param name - Stable human-readable sphere name.
61
+ * @param radius - Radius in metres.
62
+ * @returns An ellipsoid with zero flattening.
63
+ */
64
+ static sphere(name: string, radius: number): Ellipsoid;
65
+ /** Stable human-readable identifier. */
66
+ get name(): string;
67
+ /** Equatorial semi-major axis in metres. */
68
+ get semiMajorAxis(): number;
69
+ /** Polar semi-minor axis in metres. */
70
+ get semiMinorAxis(): number;
71
+ /** Largest ellipsoid radius in metres. */
72
+ get maximumRadius(): number;
73
+ /** Smallest ellipsoid radius in metres. */
74
+ get minimumRadius(): number;
75
+ /** Ellipsoid flattening `(a - b) / a`. */
76
+ get flattening(): number;
77
+ /** Reciprocal flattening, or `Infinity` for a sphere. */
78
+ get inverseFlattening(): number;
79
+ /** First eccentricity squared `e^2`. */
80
+ get squaredEccentricity(): number;
81
+ /** Compatibility alias for {@link squaredEccentricity}. */
82
+ get sqrEccentricity(): number;
83
+ /** First eccentricity `e`. */
84
+ get eccentricity(): number;
85
+ /** Second eccentricity squared `e'^2`. */
86
+ get secondSquaredEccentricity(): number;
87
+ /** Linear eccentricity in metres. */
88
+ get linearEccentricity(): number;
89
+ /** Precomputed coefficient `1 - e^2`. */
90
+ get oneMinusSquaredEccentricity(): number;
91
+ /** Compatibility alias for {@link oneMinusSquaredEccentricity}. */
92
+ get oneMinusSqrEccentricity(): number;
93
+ /** Semi-latus rectum in metres. */
94
+ get semiLatusRectum(): number;
95
+ /**
96
+ * Returns the prime-vertical radius of curvature at a geodetic latitude.
97
+ *
98
+ * @param latitudeRadians - Geodetic latitude in radians.
99
+ * @returns Prime-vertical radius in metres.
100
+ */
101
+ primeVerticalRadius(latitudeRadians: number): number;
102
+ /**
103
+ * Returns the meridional radius of curvature at a geodetic latitude.
104
+ *
105
+ * @param latitudeRadians - Geodetic latitude in radians.
106
+ * @returns Meridional radius in metres.
107
+ */
108
+ meridionalRadius(latitudeRadians: number): number;
109
+ /**
110
+ * Returns the geocentric surface radius at a latitude.
111
+ *
112
+ * @param latitudeRadians - Geocentric latitude in radians.
113
+ * @returns Distance from the ellipsoid centre to its surface in metres.
114
+ */
115
+ radiusAtLatitude(latitudeRadians: number): number;
116
+ /**
117
+ * Intersects a normalized geocentric direction with the ellipsoid surface.
118
+ *
119
+ * @param x - ECEF X component of a normalized direction.
120
+ * @param y - ECEF Y component of a normalized direction.
121
+ * @param z - ECEF Z component of a normalized direction.
122
+ * @returns Distance from the centre to the surface in metres.
123
+ */
124
+ radiusAtPosition(x: number, y: number, z: number): number;
125
+ /**
126
+ * Tests geometric equality independently from the ellipsoid name.
127
+ *
128
+ * @param other - Ellipsoid to compare.
129
+ * @returns `true` when both axes are exactly equal.
130
+ */
131
+ equals(other: Ellipsoid): boolean;
132
+ /**
133
+ * Creates a uniformly scaled ellipsoid.
134
+ *
135
+ * @param scale - Positive uniform scale applied to both axes.
136
+ * @param name - Name assigned to the scaled instance.
137
+ * @returns A new ellipsoid with unchanged flattening.
138
+ */
139
+ scaled(scale: number, name?: string): Ellipsoid;
140
+ /**
141
+ * Compatibility alias for {@link scaled}.
142
+ *
143
+ * @param name - Name assigned to the cloned instance.
144
+ * @param scale - Positive uniform scale applied to both axes.
145
+ * @returns A new ellipsoid.
146
+ */
147
+ clone(name: string, scale?: number): Ellipsoid;
148
+ }
149
+
150
+ export { Ellipsoid };
@@ -0,0 +1,3 @@
1
+ export { Ellipsoid } from './chunk-RJFTT4KI.js';
2
+ //# sourceMappingURL=ellipsoid.js.map
3
+ //# sourceMappingURL=ellipsoid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"ellipsoid.js"}
@@ -0,0 +1,257 @@
1
+ import { Ellipsoid } from './ellipsoid.js';
2
+
3
+ /**
4
+ * Mutable three-dimensional Cartesian coordinate.
5
+ *
6
+ * Axis meaning depends on the coordinate system that produces the value. ECEF
7
+ * uses metres along the conventional Earth-fixed X, Y and Z axes. ENU uses
8
+ * metres along east, north and up. NED uses metres along north, east and down.
9
+ */
10
+ interface ICartesian3 {
11
+ /** First Cartesian component in metres. */
12
+ x: number;
13
+ /** Second Cartesian component in metres. */
14
+ y: number;
15
+ /** Third Cartesian component in metres. */
16
+ z: number;
17
+ }
18
+ /**
19
+ * Mutable geodetic coordinate on a reference ellipsoid.
20
+ *
21
+ * The angular unit is determined by the method returning or accepting the
22
+ * object. Methods are explicitly suffixed with `Degrees` or `Radians`.
23
+ */
24
+ interface IGeodeticCoordinates {
25
+ /** Geodetic latitude, not geocentric latitude. */
26
+ latitude: number;
27
+ /** Longitude east of the reference meridian. */
28
+ longitude: number;
29
+ /** Ellipsoidal height in metres. */
30
+ height: number;
31
+ }
32
+ /**
33
+ * Canonical local tangent basis expressed as ECEF unit vectors.
34
+ *
35
+ * The basis describes physical directions independently from a coordinate
36
+ * convention. ENU orders it as east, north, up. NED orders it as north, east,
37
+ * down, where down is the opposite of up.
38
+ */
39
+ interface ILocalTangentBasis {
40
+ /** Unit vector pointing east. */
41
+ east: ICartesian3;
42
+ /** Unit vector pointing north. */
43
+ north: ICartesian3;
44
+ /** Unit vector normal to the ellipsoid and pointing up. */
45
+ up: ICartesian3;
46
+ }
47
+
48
+ /**
49
+ * Immutable geodetic reference system backed by one reference ellipsoid.
50
+ *
51
+ * ECEF follows EPSG:4978 axis conventions: X crosses latitude 0 and longitude
52
+ * 0, Y crosses latitude 0 and longitude 90 degrees east, and Z crosses the
53
+ * north pole. Cartesian distances and ellipsoidal heights are expressed in
54
+ * metres.
55
+ */
56
+ declare class GeodeticSystem {
57
+ readonly ellipsoid: Ellipsoid;
58
+ /** Shared WGS84 geodetic system. The instance is immutable. */
59
+ static readonly WGS84: GeodeticSystem;
60
+ /**
61
+ * Creates a geodetic system.
62
+ *
63
+ * @param ellipsoid - Reference ellipsoid. Defaults to WGS84.
64
+ */
65
+ constructor(ellipsoid?: Ellipsoid);
66
+ /**
67
+ * Converts geodetic coordinates in radians to ECEF.
68
+ *
69
+ * @param latitudeRadians - Geodetic latitude in radians.
70
+ * @param longitudeRadians - Longitude in radians east of the reference meridian.
71
+ * @param height - Ellipsoidal height in metres.
72
+ * @param target - Optional mutable output object, used to avoid an allocation.
73
+ * @returns The target populated with ECEF metres.
74
+ */
75
+ geodeticRadiansToEcef(latitudeRadians: number, longitudeRadians: number, height?: number, target?: ICartesian3): ICartesian3;
76
+ /**
77
+ * Converts geodetic coordinates in degrees to ECEF.
78
+ *
79
+ * @param latitudeDegrees - Geodetic latitude in degrees.
80
+ * @param longitudeDegrees - Longitude in degrees east of the reference meridian.
81
+ * @param height - Ellipsoidal height in metres.
82
+ * @param target - Optional mutable output object, used to avoid an allocation.
83
+ * @returns The target populated with ECEF metres.
84
+ */
85
+ geodeticDegreesToEcef(latitudeDegrees: number, longitudeDegrees: number, height?: number, target?: ICartesian3): ICartesian3;
86
+ /**
87
+ * Converts ECEF coordinates to geodetic coordinates in radians.
88
+ *
89
+ * Bowring initialization followed by a bounded fixed-point refinement gives
90
+ * stable results at the equator, at the poles, below the ellipsoid and at
91
+ * orbital altitudes. The ellipsoid centre is rejected because it has no
92
+ * unique latitude or longitude.
93
+ *
94
+ * @param position - ECEF coordinate in metres.
95
+ * @param target - Optional mutable output object, used to avoid an allocation.
96
+ * @returns Geodetic latitude and longitude in radians, with height in metres.
97
+ */
98
+ ecefToGeodeticRadians(position: ICartesian3, target?: IGeodeticCoordinates): IGeodeticCoordinates;
99
+ /**
100
+ * Converts ECEF coordinates to geodetic coordinates in degrees.
101
+ *
102
+ * @param position - ECEF coordinate in metres.
103
+ * @param target - Optional mutable output object, used to avoid an allocation.
104
+ * @returns Geodetic latitude and longitude in degrees, with height in metres.
105
+ */
106
+ ecefToGeodeticDegrees(position: ICartesian3, target?: IGeodeticCoordinates): IGeodeticCoordinates;
107
+ /**
108
+ * Returns the outward ellipsoid-normal unit vector at geodetic coordinates.
109
+ *
110
+ * @param latitudeRadians - Geodetic latitude in radians.
111
+ * @param longitudeRadians - Longitude in radians.
112
+ * @param target - Optional mutable output object.
113
+ * @returns Unit vector expressed in ECEF axes.
114
+ */
115
+ geodeticSurfaceNormalRadians(latitudeRadians: number, longitudeRadians: number, target?: ICartesian3): ICartesian3;
116
+ /**
117
+ * Returns the outward ellipsoid-normal unit vector at geodetic coordinates.
118
+ *
119
+ * @param latitudeDegrees - Geodetic latitude in degrees.
120
+ * @param longitudeDegrees - Longitude in degrees.
121
+ * @param target - Optional mutable output object.
122
+ * @returns Unit vector expressed in ECEF axes.
123
+ */
124
+ geodeticSurfaceNormalDegrees(latitudeDegrees: number, longitudeDegrees: number, target?: ICartesian3): ICartesian3;
125
+ /**
126
+ * Creates an immutable local east, north, up tangent plane.
127
+ *
128
+ * @param latitudeRadians - Origin geodetic latitude in radians.
129
+ * @param longitudeRadians - Origin longitude in radians.
130
+ * @param height - Origin ellipsoidal height in metres.
131
+ * @returns A local tangent plane bound to this geodetic system.
132
+ */
133
+ createLocalTangentPlaneRadians(latitudeRadians: number, longitudeRadians: number, height?: number): LocalTangentPlane;
134
+ /**
135
+ * Creates an immutable local east, north, up tangent plane.
136
+ *
137
+ * @param latitudeDegrees - Origin geodetic latitude in degrees.
138
+ * @param longitudeDegrees - Origin longitude in degrees.
139
+ * @param height - Origin ellipsoidal height in metres.
140
+ * @returns A local tangent plane bound to this geodetic system.
141
+ */
142
+ createLocalTangentPlaneDegrees(latitudeDegrees: number, longitudeDegrees: number, height?: number): LocalTangentPlane;
143
+ }
144
+ /**
145
+ * Immutable local tangent plane anchored to a geodetic coordinate.
146
+ *
147
+ * ENU axes are X east, Y north and Z up. NED axes are X north, Y east and Z
148
+ * down. All local values are metres. The stored matrices use column-major
149
+ * order and multiply column vectors, matching glTF and 3D Tiles transforms.
150
+ */
151
+ declare class LocalTangentPlane {
152
+ readonly system: GeodeticSystem;
153
+ private readonly origin;
154
+ private readonly originCartesian;
155
+ private readonly tangentBasis;
156
+ private readonly toEnu;
157
+ private readonly fromEnu;
158
+ private readonly toNed;
159
+ private readonly fromNed;
160
+ /**
161
+ * Creates a local tangent plane.
162
+ *
163
+ * Prefer {@link GeodeticSystem.createLocalTangentPlaneRadians} or
164
+ * {@link GeodeticSystem.createLocalTangentPlaneDegrees}, which make the
165
+ * angular unit explicit at the call site.
166
+ *
167
+ * @param system - Geodetic reference system.
168
+ * @param originRadians - Origin with angular components in radians.
169
+ */
170
+ constructor(system: GeodeticSystem, originRadians: IGeodeticCoordinates);
171
+ /** Origin geodetic coordinate with latitude and longitude in radians. */
172
+ get originRadians(): IGeodeticCoordinates;
173
+ /** Origin geodetic coordinate with latitude and longitude in degrees. */
174
+ get originDegrees(): IGeodeticCoordinates;
175
+ /** Origin expressed as ECEF metres. */
176
+ get originEcef(): ICartesian3;
177
+ /** Canonical east, north and up tangent basis expressed as ECEF unit vectors. */
178
+ get basis(): ILocalTangentBasis;
179
+ /** Column-major matrix transforming ECEF positions to ENU positions. */
180
+ get ecefToEnuMatrix(): Float64Array;
181
+ /** Column-major matrix transforming ENU positions to ECEF positions. */
182
+ get enuToEcefMatrix(): Float64Array;
183
+ /** Column-major matrix transforming ECEF positions to NED positions. */
184
+ get ecefToNedMatrix(): Float64Array;
185
+ /** Column-major matrix transforming NED positions to ECEF positions. */
186
+ get nedToEcefMatrix(): Float64Array;
187
+ /**
188
+ * Converts an ECEF position to local ENU metres.
189
+ *
190
+ * @param position - ECEF position in metres.
191
+ * @param target - Optional mutable output object.
192
+ * @returns Local coordinate with X east, Y north and Z up.
193
+ */
194
+ ecefToEnu(position: ICartesian3, target?: ICartesian3): ICartesian3;
195
+ /**
196
+ * Converts a local ENU position to ECEF metres.
197
+ *
198
+ * @param position - Local coordinate with X east, Y north and Z up.
199
+ * @param target - Optional mutable output object.
200
+ * @returns ECEF coordinate in metres.
201
+ */
202
+ enuToEcef(position: ICartesian3, target?: ICartesian3): ICartesian3;
203
+ /**
204
+ * Converts an ECEF position to local NED metres.
205
+ *
206
+ * @param position - ECEF position in metres.
207
+ * @param target - Optional mutable output object.
208
+ * @returns Local coordinate with X north, Y east and Z down.
209
+ */
210
+ ecefToNed(position: ICartesian3, target?: ICartesian3): ICartesian3;
211
+ /**
212
+ * Converts a local NED position to ECEF metres.
213
+ *
214
+ * @param position - Local coordinate with X north, Y east and Z down.
215
+ * @param target - Optional mutable output object.
216
+ * @returns ECEF coordinate in metres.
217
+ */
218
+ nedToEcef(position: ICartesian3, target?: ICartesian3): ICartesian3;
219
+ /**
220
+ * Converts geodetic radians directly to local ENU metres.
221
+ *
222
+ * @param latitudeRadians - Geodetic latitude in radians.
223
+ * @param longitudeRadians - Longitude in radians.
224
+ * @param height - Ellipsoidal height in metres.
225
+ * @param target - Optional mutable output object.
226
+ * @returns Local coordinate with X east, Y north and Z up.
227
+ */
228
+ geodeticRadiansToEnu(latitudeRadians: number, longitudeRadians: number, height?: number, target?: ICartesian3): ICartesian3;
229
+ /**
230
+ * Converts geodetic degrees directly to local ENU metres.
231
+ *
232
+ * @param latitudeDegrees - Geodetic latitude in degrees.
233
+ * @param longitudeDegrees - Longitude in degrees.
234
+ * @param height - Ellipsoidal height in metres.
235
+ * @param target - Optional mutable output object.
236
+ * @returns Local coordinate with X east, Y north and Z up.
237
+ */
238
+ geodeticDegreesToEnu(latitudeDegrees: number, longitudeDegrees: number, height?: number, target?: ICartesian3): ICartesian3;
239
+ /**
240
+ * Converts local ENU metres directly to geodetic radians.
241
+ *
242
+ * @param position - Local coordinate with X east, Y north and Z up.
243
+ * @param target - Optional mutable output object.
244
+ * @returns Geodetic latitude and longitude in radians, with height in metres.
245
+ */
246
+ enuToGeodeticRadians(position: ICartesian3, target?: IGeodeticCoordinates): IGeodeticCoordinates;
247
+ /**
248
+ * Converts local ENU metres directly to geodetic degrees.
249
+ *
250
+ * @param position - Local coordinate with X east, Y north and Z up.
251
+ * @param target - Optional mutable output object.
252
+ * @returns Geodetic latitude and longitude in degrees, with height in metres.
253
+ */
254
+ enuToGeodeticDegrees(position: ICartesian3, target?: IGeodeticCoordinates): IGeodeticCoordinates;
255
+ }
256
+
257
+ export { GeodeticSystem as G, type ICartesian3 as I, LocalTangentPlane as L, type IGeodeticCoordinates as a, type ILocalTangentBasis as b };
@@ -0,0 +1,39 @@
1
+ export { Ellipsoid } from './ellipsoid.js';
2
+ export { G as GeodeticSystem, I as ICartesian3, a as IGeodeticCoordinates, b as ILocalTangentBasis, L as LocalTangentPlane } from './geodetic-system-DRpWY8qG.js';
3
+
4
+ /** Number of radians in one degree. */
5
+ declare const DEGREES_TO_RADIANS: number;
6
+ /** Number of degrees in one radian. */
7
+ declare const RADIANS_TO_DEGREES: number;
8
+ /** Full turn in radians. */
9
+ declare const TWO_PI: number;
10
+ /**
11
+ * Converts an angle from degrees to radians.
12
+ *
13
+ * @param degrees - Angle in degrees.
14
+ * @returns The equivalent angle in radians.
15
+ */
16
+ declare function toRadians(degrees: number): number;
17
+ /**
18
+ * Converts an angle from radians to degrees.
19
+ *
20
+ * @param radians - Angle in radians.
21
+ * @returns The equivalent angle in degrees.
22
+ */
23
+ declare function toDegrees(radians: number): number;
24
+ /**
25
+ * Normalizes a longitude to the half-open interval `[-PI, PI)`.
26
+ *
27
+ * @param longitudeRadians - Longitude in radians.
28
+ * @returns Normalized longitude in radians.
29
+ */
30
+ declare function normalizeLongitudeRadians(longitudeRadians: number): number;
31
+ /**
32
+ * Normalizes a longitude to the half-open interval `[-180, 180)`.
33
+ *
34
+ * @param longitudeDegrees - Longitude in degrees.
35
+ * @returns Normalized longitude in degrees.
36
+ */
37
+ declare function normalizeLongitudeDegrees(longitudeDegrees: number): number;
38
+
39
+ export { DEGREES_TO_RADIANS, RADIANS_TO_DEGREES, TWO_PI, normalizeLongitudeDegrees, normalizeLongitudeRadians, toDegrees, toRadians };
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { DEGREES_TO_RADIANS, GeodeticSystem, LocalTangentPlane, RADIANS_TO_DEGREES, TWO_PI, normalizeLongitudeDegrees, normalizeLongitudeRadians, toDegrees, toRadians } from './chunk-WYCQOUE7.js';
2
+ export { Ellipsoid } from './chunk-RJFTT4KI.js';
3
+ //# sourceMappingURL=index.js.map
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,2 @@
1
+ import './ellipsoid.js';
2
+ export { G as GeodeticSystem, L as LocalTangentPlane } from './geodetic-system-DRpWY8qG.js';
package/dist/system.js ADDED
@@ -0,0 +1,4 @@
1
+ export { GeodeticSystem, LocalTangentPlane } from './chunk-WYCQOUE7.js';
2
+ import './chunk-RJFTT4KI.js';
3
+ //# sourceMappingURL=system.js.map
4
+ //# sourceMappingURL=system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"system.js"}
package/package.json ADDED
@@ -0,0 +1,89 @@
1
+ {
2
+ "name": "@spacexr/geodesy",
3
+ "version": "0.1.0",
4
+ "description": "Renderer-neutral ellipsoid, geodetic, ECEF and local tangent frame primitives for SpaceXR.",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "author": "Guillaume Pelletier (SpaceXR)",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/pandaGaume/geodesy_ts.git"
11
+ },
12
+ "homepage": "https://github.com/pandaGaume/geodesy_ts#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/pandaGaume/geodesy_ts/issues"
15
+ },
16
+ "keywords": [
17
+ "geodesy",
18
+ "ecef",
19
+ "ellipsoid",
20
+ "wgs84",
21
+ "enu",
22
+ "ned",
23
+ "spacexr"
24
+ ],
25
+ "engines": {
26
+ "node": ">=20.11.0"
27
+ },
28
+ "sideEffects": false,
29
+ "files": [
30
+ "dist",
31
+ "src",
32
+ "LICENSE",
33
+ "README.md",
34
+ "CHANGELOG.md"
35
+ ],
36
+ "main": "./dist/index.js",
37
+ "module": "./dist/index.js",
38
+ "types": "./dist/index.d.ts",
39
+ "exports": {
40
+ ".": {
41
+ "types": "./dist/index.d.ts",
42
+ "import": "./dist/index.js",
43
+ "default": "./dist/index.js"
44
+ },
45
+ "./ellipsoid": {
46
+ "types": "./dist/ellipsoid.d.ts",
47
+ "import": "./dist/ellipsoid.js",
48
+ "default": "./dist/ellipsoid.js"
49
+ },
50
+ "./system": {
51
+ "types": "./dist/system.d.ts",
52
+ "import": "./dist/system.js",
53
+ "default": "./dist/system.js"
54
+ },
55
+ "./package.json": "./package.json"
56
+ },
57
+ "publishConfig": {
58
+ "access": "public"
59
+ },
60
+ "scripts": {
61
+ "build": "tsup",
62
+ "clean": "rimraf dist coverage docs/api",
63
+ "typecheck": "tsc -p tsconfig.json --noEmit",
64
+ "test": "vitest run --coverage.enabled=false",
65
+ "test:watch": "vitest",
66
+ "lint": "eslint \"src/**/*.ts\" \"tests/**/*.ts\"",
67
+ "lint:fix": "eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix",
68
+ "format": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\" \"*.{json,md}\"",
69
+ "format:fix": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\" \"*.{json,md}\"",
70
+ "docs": "typedoc --options typedoc.json",
71
+ "check": "npm run format && npm run lint && npm run typecheck && npm run test && npm run build && npm run docs",
72
+ "prepublishOnly": "npm run check"
73
+ },
74
+ "devDependencies": {
75
+ "@types/node": "^20.11.0",
76
+ "@typescript-eslint/eslint-plugin": "^7.0.0",
77
+ "@typescript-eslint/parser": "^7.0.0",
78
+ "eslint": "^8.57.0",
79
+ "eslint-config-prettier": "^9.1.0",
80
+ "eslint-plugin-prettier": "^5.1.0",
81
+ "prettier": "^3.2.0",
82
+ "rimraf": "~6.0.1",
83
+ "tslib": "^2.8.1",
84
+ "tsup": "^8.5.1",
85
+ "typedoc": "^0.28.0",
86
+ "typescript": "^5.4.0",
87
+ "vitest": "4.1.11"
88
+ }
89
+ }
package/src/angles.ts ADDED
@@ -0,0 +1,48 @@
1
+ /** Number of radians in one degree. */
2
+ export const DEGREES_TO_RADIANS = Math.PI / 180;
3
+
4
+ /** Number of degrees in one radian. */
5
+ export const RADIANS_TO_DEGREES = 180 / Math.PI;
6
+
7
+ /** Full turn in radians. */
8
+ export const TWO_PI = Math.PI * 2;
9
+
10
+ /**
11
+ * Converts an angle from degrees to radians.
12
+ *
13
+ * @param degrees - Angle in degrees.
14
+ * @returns The equivalent angle in radians.
15
+ */
16
+ export function toRadians(degrees: number): number {
17
+ return degrees * DEGREES_TO_RADIANS;
18
+ }
19
+
20
+ /**
21
+ * Converts an angle from radians to degrees.
22
+ *
23
+ * @param radians - Angle in radians.
24
+ * @returns The equivalent angle in degrees.
25
+ */
26
+ export function toDegrees(radians: number): number {
27
+ return radians * RADIANS_TO_DEGREES;
28
+ }
29
+
30
+ /**
31
+ * Normalizes a longitude to the half-open interval `[-PI, PI)`.
32
+ *
33
+ * @param longitudeRadians - Longitude in radians.
34
+ * @returns Normalized longitude in radians.
35
+ */
36
+ export function normalizeLongitudeRadians(longitudeRadians: number): number {
37
+ return ((((longitudeRadians + Math.PI) % TWO_PI) + TWO_PI) % TWO_PI) - Math.PI;
38
+ }
39
+
40
+ /**
41
+ * Normalizes a longitude to the half-open interval `[-180, 180)`.
42
+ *
43
+ * @param longitudeDegrees - Longitude in degrees.
44
+ * @returns Normalized longitude in degrees.
45
+ */
46
+ export function normalizeLongitudeDegrees(longitudeDegrees: number): number {
47
+ return ((((longitudeDegrees + 180) % 360) + 360) % 360) - 180;
48
+ }