@itowns/geographic 2.44.3-next.43 → 2.45.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/package.json CHANGED
@@ -1,16 +1,15 @@
1
1
  {
2
2
  "name": "@itowns/geographic",
3
- "version": "2.44.3-next.43",
3
+ "version": "2.45.0",
4
4
  "description": "Geodesy",
5
5
  "type": "module",
6
6
  "main": "lib/Main.js",
7
- "exports": {
8
- ".": "./lib/Main.js"
9
- },
7
+ "exports": "./lib/Main.js",
8
+ "types": "./lib/Main.d.ts",
10
9
  "scripts": {
11
10
  "build": "",
12
11
  "lint": "eslint \"src/**/*.{js,ts,tsx}\" \"test/**/*.js\"",
13
- "transpile": "cross-env BABEL_DISABLE_CACHE=1 babel src --out-dir lib --extensions .js,.ts",
12
+ "transpile": "tsc && cross-env BABEL_DISABLE_CACHE=1 babel src --out-dir lib --extensions .js,.ts",
14
13
  "test-unit": "npm run base-test-unit test/unit",
15
14
  "base-test-unit": "cross-env BABEL_DISABLE_CACHE=1 mocha --import=../../config/babel-register/register.mjs",
16
15
  "test-with-coverage": "c8 -n src -r html cross-env npm run test-unit",
@@ -3,7 +3,7 @@
3
3
  * Class: CoordStars
4
4
  * Description: get coord of stars like earth...
5
5
  */
6
- import Coordinates from 'Coordinates';
6
+ import Coordinates from './Coordinates';
7
7
 
8
8
  const CoordStars = {
9
9
 
@@ -22,48 +22,48 @@ const CoordStars = {
22
22
  const J2000 = 2451545;
23
23
  const e = rad * 23.4397; // obliquity of the Earth
24
24
 
25
- function toJulian(date) {
25
+ function toJulian(date: Date | number) {
26
26
  return date.valueOf() / dayMs - 0.5 + J1970;
27
27
  }
28
28
 
29
- function toDays(date) {
29
+ function toDays(date: Date | number) {
30
30
  return toJulian(date) - J2000;
31
31
  }
32
32
 
33
- function getRightAscension(l, b) {
33
+ function getRightAscension(l: number, b: number) {
34
34
  return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l));
35
35
  }
36
36
 
37
- function getDeclination(l, b) {
37
+ function getDeclination(l: number, b: number) {
38
38
  return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l));
39
39
  }
40
40
 
41
- function getAzimuth(H, phi, dec) {
41
+ function getAzimuth(H: number, phi: number, dec: number) {
42
42
  return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi));
43
43
  }
44
44
 
45
- function getAltitude(H, phi, dec) {
45
+ function getAltitude(H: number, phi: number, dec: number) {
46
46
  return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H));
47
47
  }
48
48
 
49
- function getSiderealTime(d, lw) {
49
+ function getSiderealTime(d: number, lw: number) {
50
50
  return rad * (280.16 + 360.9856235 * d) - lw;
51
51
  }
52
52
 
53
- function getSolarMeanAnomaly(d) {
53
+ function getSolarMeanAnomaly(d: number) {
54
54
  return rad * (357.5291 + 0.98560028 * d);
55
55
  }
56
56
 
57
- function getEquationOfCenter(M) {
57
+ function getEquationOfCenter(M: number) {
58
58
  return rad * (1.9148 * sin(M) + 0.0200 * sin(2 * M) + 0.0003 * sin(3 * M));
59
59
  }
60
60
 
61
- function getEclipticLongitude(M, C) {
61
+ function getEclipticLongitude(M: number, C: number) {
62
62
  const P = rad * 102.9372; // perihelion of the Earth
63
63
  return M + C + P + PI;
64
64
  }
65
65
 
66
- return function getSunPosition(date, lat, lon) {
66
+ return function getSunPosition(date: Date | number, lat: number, lon: number) {
67
67
  const lw = rad * -lon;
68
68
  const phi = rad * lat;
69
69
  const d = toDays(date);
@@ -82,16 +82,22 @@ const CoordStars = {
82
82
  H,
83
83
  SiderealTime: t,
84
84
  altitude: getAltitude(H, phi, D),
85
- azimuth: getAzimuth(H, phi, D) + PI / 2, // + PI// - PI/2 // origin: north !!! not like original Mourner code but more classical ref
85
+ azimuth: getAzimuth(H, phi, D) + PI / 2, // + PI// - PI/2
86
+ // origin: north !!! not like original Mourner code but more
87
+ // classical ref
86
88
  };
87
89
  };
88
90
  },
89
91
 
90
92
  // Return scene coordinate ({x,y,z}) of sun
91
- getSunPositionInScene(date, lat, lon) {
93
+ getSunPositionInScene(date: Date | number, lat: number, lon: number) {
94
+ if (typeof date !== 'number') {
95
+ date = date.valueOf();
96
+ }
92
97
  const sun = CoordStars.getSunPosition()(date, lat, lon);
93
98
  const dayMilliSec = 24 * 3600000;
94
- const longitude = sun.ascension + ((date % dayMilliSec) / dayMilliSec) * -360 + 180; // cause midday
99
+ const longitude = sun.ascension +
100
+ ((date % dayMilliSec) / dayMilliSec) * -360 + 180; // cause midday
95
101
  const coSunCarto = new Coordinates('EPSG:4326', longitude, lat, 50000000)
96
102
  .as('EPSG:4978').toVector3();
97
103
 
@@ -1,6 +1,6 @@
1
1
  import * as THREE from 'three';
2
2
  import proj4 from 'proj4';
3
- import Ellipsoid from 'Ellipsoid';
3
+ import Ellipsoid from './Ellipsoid';
4
4
  import * as CRS from './Crs';
5
5
 
6
6
  import type { ProjectionLike } from './Crs';
package/src/Ellipsoid.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as THREE from 'three';
2
2
  import proj4 from 'proj4';
3
- import Coordinates from 'Coordinates';
3
+ import Coordinates from './Coordinates';
4
4
 
5
5
  /**
6
6
  * Length of the semi-axes of the WGS84 ellipsoid.
package/src/Main.ts ADDED
@@ -0,0 +1,8 @@
1
+ // Geodesic tools
2
+ export { default as Extent } from './Extent';
3
+ export { default as Coordinates } from './Coordinates';
4
+ export * as CRS from './Crs';
5
+ export { default as CoordStars } from './CoordStars';
6
+ export * as OrientationUtils from './OrientationUtils';
7
+ export { default as Ellipsoid, ellipsoidSizes } from './Ellipsoid';
8
+
@@ -0,0 +1,493 @@
1
+ import { Euler, MathUtils, Matrix4, Quaternion, Vector3 } from 'three';
2
+ import proj4 from 'proj4';
3
+ import type { ProjectionDefinition } from 'proj4';
4
+ import Coordinates from './Coordinates';
5
+
6
+ const DEG2RAD = MathUtils.DEG2RAD;
7
+ const matrix = new Matrix4();
8
+ const north = new Vector3();
9
+ const east = new Vector3();
10
+ const axis = new Vector3().set(0, 0, 1);
11
+ const coord = new Coordinates('EPSG:4326', 0, 0, 0);
12
+ const euler = new Euler();
13
+ const quat = new Quaternion();
14
+
15
+ interface EulerAngles {
16
+ /** angle in degrees */
17
+ roll: number;
18
+ /** angle in degrees */
19
+ pitch: number;
20
+ /** angle in degrees */
21
+ heading: number;
22
+ }
23
+
24
+ interface PhotogrammetryAngles {
25
+ /** angle in degrees */
26
+ omega: number;
27
+ /** angle in degrees */
28
+ phi: number;
29
+ /** angle in degrees */
30
+ kappa: number;
31
+ }
32
+
33
+ type Attitude = Partial<EulerAngles> | Partial<PhotogrammetryAngles>;
34
+
35
+ type QuaternionFunction = (coords: Coordinates, target?: Quaternion) => Quaternion;
36
+
37
+ type ProjectionLike = ProjectionDefinition | string;
38
+ type LCCProjection = { long0: number, lat0: number };
39
+ type TMercProjection = { a: number, b: number, e?: number, long0: number };
40
+
41
+ /**
42
+ * The transform from the platform frame to the local East, North, Up (ENU)
43
+ * frame is `RotationZ(heading).RotationX(pitch).RotationY(roll)`.
44
+ *
45
+ * @param roll - angle in degrees. Default is 0.
46
+ * @param pitch - angle in degrees. Default is 0.
47
+ * @param heading - angle in degrees. Default is 0
48
+ * @param target - output Quaternion
49
+ *
50
+ * @returns The target quaternion
51
+ */
52
+ export function quaternionFromRollPitchHeading(
53
+ roll = 0,
54
+ pitch = 0,
55
+ heading = 0,
56
+ target = new Quaternion(),
57
+ ) {
58
+ roll *= DEG2RAD;
59
+ pitch *= DEG2RAD;
60
+ heading *= DEG2RAD;
61
+ // return setFromEuler(euler.set(pitch, roll, heading , 'ZXY')).conjugate();
62
+ // Below is optimized version of above line
63
+ return target.setFromEuler(euler.set(-pitch, -roll, -heading, 'YXZ'));
64
+ }
65
+
66
+ /**
67
+ * From
68
+ * [DocMicMac](https://github.com/micmacIGN/Documentation/raw/master/DocMicMac.pdf),
69
+ * the transform from the platform frame to the local East, North, Up (ENU)
70
+ * frame is:
71
+ *
72
+ * ```
73
+ * RotationX(omega).RotationY(phi).RotationZ(kappa).RotationX(PI)
74
+ * Converts between the 2 conventions for the camera local frame:
75
+ * RotationX(PI) <=> Quaternion(1,0,0,0)
76
+ * X right, Y bottom, Z front : convention in photogrammetry and computer vision
77
+ * X right, Y top, Z back : convention in webGL, threejs
78
+ * ```
79
+ *
80
+ * @param omega - angle in degrees. Default is 0.
81
+ * @param phi - angle in degrees. Default is 0.
82
+ * @param kappa - angle in degrees. Default is 0.
83
+ * @param target - output quaternion
84
+ *
85
+ * @returns The target quaternion
86
+ */
87
+ export function quaternionFromOmegaPhiKappa(
88
+ omega = 0,
89
+ phi = 0,
90
+ kappa = 0,
91
+ target = new Quaternion(),
92
+ ) {
93
+ omega *= DEG2RAD;
94
+ phi *= DEG2RAD;
95
+ kappa *= DEG2RAD;
96
+ target.setFromEuler(euler.set(omega, phi, kappa, 'XYZ'));
97
+ target.set(target.w, target.z, -target.y, -target.x);
98
+ // <=> target.multiply(new THREE.Quaternion(1, 0, 0, 0));
99
+ return target;
100
+ }
101
+
102
+ /**
103
+ * Sets the quaternion according to the rotation from the platform frame to the
104
+ * local frame.
105
+ *
106
+ * @param attitude - either euler angles or photogrammetry angles
107
+ * @param target - output Quaternion
108
+ *
109
+ * @returns The target quaternion
110
+ */
111
+ export function quaternionFromAttitude(attitude: Attitude, target = new Quaternion()) {
112
+ if ('roll' in attitude || 'pitch' in attitude || 'heading' in attitude) {
113
+ return quaternionFromRollPitchHeading(
114
+ attitude.roll, attitude.pitch, attitude.heading,
115
+ target,
116
+ );
117
+ }
118
+ if ('omega' in attitude || 'phi' in attitude || 'kappa' in attitude) {
119
+ return quaternionFromOmegaPhiKappa(
120
+ attitude.omega, attitude.phi, attitude.kappa,
121
+ target,
122
+ );
123
+ }
124
+ return target.set(0, 0, 0, 1);
125
+ }
126
+
127
+ export function quaternionFromEnuToGeocent(): QuaternionFunction;
128
+ export function quaternionFromEnuToGeocent(coords: Coordinates, target?: Quaternion): Quaternion;
129
+ /**
130
+ * Sets the quaternion according to the rotation from the local East North Up
131
+ * (ENU) frame to the geocentric frame. The up direction of the ENU frame is
132
+ * provided by the normalized geodetic normal of the provided coordinates
133
+ * (geodeticNormal property).
134
+ *
135
+ * @param coordinates - origin of the local East North Up (ENU) frame
136
+ * @param target - output Quaternion
137
+ * @returns The target quaternion if coordinates is defined. Otherwise, a
138
+ * function to compute it from coordinates.
139
+ */
140
+ export function quaternionFromEnuToGeocent(coordinates?: Coordinates, target = new Quaternion()) {
141
+ if (coordinates) { return quaternionFromEnuToGeocent()(coordinates, target); }
142
+ return (coordinates: Coordinates, target = new Quaternion()) => {
143
+ const up = coordinates.geodesicNormal;
144
+ if (up.x == 0 && up.y == 0) {
145
+ return target.set(0, 0, 0, 1);
146
+ }
147
+ // this is an optimized version of
148
+ // matrix.lookAt(up, new THREE.Vector3(), new THREE.Vector3(0, 0, 1));
149
+ east.set(-up.y, up.x, 0).normalize();
150
+ north.crossVectors(up, east);
151
+ matrix.makeBasis(east, north, up);
152
+ return target.setFromRotationMatrix(matrix);
153
+ };
154
+ }
155
+
156
+ export function quaternionFromGeocentToEnu(): QuaternionFunction;
157
+ export function quaternionFromGeocentToEnu(coords: Coordinates, target?: Quaternion): Quaternion;
158
+ /**
159
+ * Sets the quaternion according to the rotation from a geocentric frame
160
+ * to the local East North Up (ENU) frame. The up direction of the ENU frame is
161
+ * provided by the normalized geodetic normal of the provided coordinates
162
+ * (geodeticNormal property).
163
+ *
164
+ * @param coordinates - origin of the local East North Up (ENU) frame
165
+ * @param target - output Quaternion
166
+ * @returns The target quaternion if coordinates is defined. Otherwise, a
167
+ * function to compute it from coordinates.
168
+ */
169
+ export function quaternionFromGeocentToEnu(coordinates?: Coordinates, target = new Quaternion()) {
170
+ if (coordinates) { return quaternionFromGeocentToEnu()(coordinates, target); }
171
+ const toGeocent = quaternionFromEnuToGeocent();
172
+ return (coordinates: Coordinates, target = new Quaternion()) =>
173
+ toGeocent(coordinates, target).conjugate();
174
+ }
175
+
176
+
177
+ export function quaternionFromLCCToEnu(proj: LCCProjection): QuaternionFunction;
178
+ export function quaternionFromLCCToEnu(
179
+ proj: LCCProjection,
180
+ coords: Coordinates,
181
+ target?: Quaternion,
182
+ ): Quaternion;
183
+ /**
184
+ * Computes the rotation from a Lambert Conformal Conic (LCC) frame to the local
185
+ * East North Up (ENU) frame.
186
+ * The quaternion accounts for the
187
+ * <a href="https://geodesie.ign.fr/contenu/fichiers/documentation/algorithmes/alg0060.pdf">meridian convergence</a>
188
+ * between the ENU and LCC frames.
189
+ * This is a generally small rotation around Z.
190
+ *
191
+ * @param proj - the lcc projection (may be parsed using proj4)
192
+ * @param coordinates - origin of the local East North Up (ENU) frame
193
+ * @param target - output Quaternion
194
+ * @returns The target quaternion if coordinates is defined. Otherwise, a
195
+ * function to compute it from coordinates.
196
+ */
197
+ export function quaternionFromLCCToEnu(
198
+ proj: LCCProjection,
199
+ coordinates?: Coordinates,
200
+ target = new Quaternion(),
201
+ ) {
202
+ if (coordinates) { return quaternionFromLCCToEnu(proj)(coordinates, target); }
203
+ const sinlat0 = Math.sin(proj.lat0);
204
+ return (coordinates: Coordinates, target = new Quaternion()) => {
205
+ const long = coordinates.as(coord.crs, coord).longitude * DEG2RAD;
206
+ return target.setFromAxisAngle(axis, sinlat0 * (proj.long0 - long));
207
+ };
208
+ }
209
+
210
+ export function quaternionFromEnuToLCC(proj: LCCProjection): QuaternionFunction;
211
+ export function quaternionFromEnuToLCC(
212
+ proj: LCCProjection,
213
+ coords: Coordinates,
214
+ target?: Quaternion,
215
+ ): Quaternion;
216
+ /**
217
+ * Computes the rotation from the local East North Up (ENU) frame to a Lambert
218
+ * Conformal Conic (LCC) frame. The quaternion accounts for the
219
+ * <a href="https://geodesie.ign.fr/contenu/fichiers/documentation/algorithmes/alg0060.pdf">meridian convergence</a>
220
+ * between the ENU and LCC frames.
221
+ * This is a generally small rotation around Z.
222
+ *
223
+ * @param proj - the lcc projection (may be parsed using proj4)
224
+ * @param coordinates - origin of the local East North Up (ENU) frame
225
+ * @param target - output Quaternion
226
+ * @returns The target quaternion if coordinates is defined. Otherwise, a
227
+ * function to compute it from coordinates.
228
+ */
229
+ export function quaternionFromEnuToLCC(
230
+ proj: LCCProjection,
231
+ coordinates?: Coordinates,
232
+ target = new Quaternion(),
233
+ ) {
234
+ if (coordinates) { return quaternionFromEnuToLCC(proj)(coordinates, target); }
235
+ const fromLCC = quaternionFromLCCToEnu(proj);
236
+ return (coordinates: Coordinates, target = new Quaternion()) =>
237
+ fromLCC(coordinates, target).conjugate();
238
+ }
239
+
240
+ export function quaternionFromTMercToEnu(proj: TMercProjection): QuaternionFunction;
241
+ export function quaternionFromTMercToEnu(
242
+ proj: TMercProjection,
243
+ coords: Coordinates,
244
+ target?: Quaternion,
245
+ ): Quaternion;
246
+ /**
247
+ * Computes the rotation from a Transverse Mercator frame (TMerc) to the
248
+ * local East North Up (ENU) frame. The quaternion accounts for the
249
+ * <a href="https://geodesie.ign.fr/contenu/fichiers/documentation/algorithmes/alg0061.pdf">meridian convergence</a>
250
+ * between the ENU and TMerc frames.
251
+ * This is a generally small rotation around Z.
252
+ *
253
+ * @param proj - the tmerc projection (may be parsed using proj4)
254
+ * @param coordinates - origin of the local East North Up (ENU) frame
255
+ * @param target - output Quaternion
256
+ * @returns The target quaternion if coordinates is defined. Otherwise, a
257
+ * function to compute it from coordinates.
258
+ */
259
+ export function quaternionFromTMercToEnu(
260
+ proj: TMercProjection,
261
+ coordinates?: Coordinates,
262
+ target = new Quaternion(),
263
+ ) {
264
+ if (coordinates) { return quaternionFromTMercToEnu(proj)(coordinates, target); }
265
+ let eta0;
266
+ if (!proj.e) {
267
+ const a2 = proj.a * proj.a;
268
+ const b2 = proj.b * proj.b;
269
+ eta0 = (a2 / b2 - 1);
270
+ } else {
271
+ const e2 = proj.e * proj.e;
272
+ eta0 = (e2 / (1 - e2));
273
+ }
274
+ return (coordinates: Coordinates, target = new Quaternion()) => {
275
+ coordinates.as(coord.crs, coord);
276
+ const long = coord.longitude * DEG2RAD;
277
+ const lat = coord.latitude * DEG2RAD;
278
+ const dlong = proj.long0 - long;
279
+ const coslat = Math.cos(lat);
280
+ const sinlat = Math.sin(lat);
281
+ const tanlat = sinlat / coslat;
282
+ const coslat2 = coslat * coslat;
283
+ const dl2 = dlong * dlong * coslat2;
284
+ const eta2 = eta0 * coslat2;
285
+ const gamma = dlong * sinlat * (
286
+ 1 + dl2 / 3 * (1 + 3 * eta2 + 2 * eta2 * eta2) + dl2 * dl2 * (2 - tanlat) / 15
287
+ );
288
+ return target.setFromAxisAngle(axis, gamma);
289
+ };
290
+ }
291
+
292
+ export function quaternionFromEnuToTMerc(proj: TMercProjection): QuaternionFunction;
293
+ export function quaternionFromEnuToTMerc(
294
+ proj: TMercProjection,
295
+ coords: Coordinates,
296
+ target?: Quaternion,
297
+ ): Quaternion;
298
+ /**
299
+ * Computes the rotation from the local East North Up (ENU) to a Transverse
300
+ * Mercator frame. The quaternion accounts for the
301
+ * <a href="https://geodesie.ign.fr/contenu/fichiers/documentation/algorithmes/alg0061.pdf">meridian convergence</a>
302
+ * between the ENU and TMerc frames.
303
+ * This is a generally small rotation around Z.
304
+ *
305
+ * @param proj - the tmerc projection (may be parsed using proj4)
306
+ * @param coordinates - origin of the local East North Up (ENU) frame
307
+ * @param target - output Quaternion
308
+ * @returns The target quaternion if coordinates is defined. Otherwise, a
309
+ * function to compute it from coordinates.
310
+ */
311
+ export function quaternionFromEnuToTMerc(
312
+ proj: TMercProjection,
313
+ coordinates?: Coordinates,
314
+ target = new Quaternion(),
315
+ ) {
316
+ if (coordinates) { return quaternionFromEnuToTMerc(proj)(coordinates, target); }
317
+ const fromTMerc = quaternionFromTMercToEnu(proj);
318
+ return (coordinates: Coordinates, target = new Quaternion()) =>
319
+ fromTMerc(coordinates, target).conjugate();
320
+ }
321
+
322
+ export function quaternionFromLongLatToEnu(): QuaternionFunction;
323
+ export function quaternionFromLongLatToEnu(coords: Coordinates, target?: Quaternion): Quaternion;
324
+ /**
325
+ * Computes the rotation from a LongLat frame to the local East North Up
326
+ * (ENU) frame. The identity quaternion (0,0,0,1) is returned, as longlat
327
+ * and ENU frame are assumed to be aligned.
328
+ *
329
+ * @param coordinates - coordinates the origin of the local East North Up
330
+ * (ENU) frame
331
+ * @param target - output Quaternion
332
+ * @returns The target quaternion if coordinates is defined, otherwise, a
333
+ * function to compute it from coordinates.
334
+ */
335
+ export function quaternionFromLongLatToEnu(coordinates?: Coordinates, target = new Quaternion()) {
336
+ return coordinates ? target.set(0, 0, 0, 1) :
337
+ (coordinates: Coordinates, target = new Quaternion()) =>
338
+ quaternionFromLongLatToEnu(coordinates, target);
339
+ }
340
+
341
+ export function quaternionFromEnuToLongLat(): QuaternionFunction;
342
+ export function quaternionFromEnuToLongLat(coords: Coordinates, target?: Quaternion): Quaternion;
343
+ /**
344
+ * Computes the rotation from the local East North Up (ENU) frame to a
345
+ * LongLat frame. The identity quaternion (0,0,0,1) is returned, as longlat
346
+ * and ENU frame are assumed to be aligned.
347
+ *
348
+ * @param coordinates - the origin of the local East North Up (ENU) frame
349
+ * @param target - output Quaternion
350
+ * @returns The target quaternion if coordinates is defined, otherwise, a
351
+ * function to compute it from coordinates.
352
+ */
353
+ export function quaternionFromEnuToLongLat(coordinates?: Coordinates, target = new Quaternion()) {
354
+ return coordinates ? target.set(0, 0, 0, 1) :
355
+ (coordinates: Coordinates, target = new Quaternion()) =>
356
+ quaternionFromEnuToLongLat(coordinates, target);
357
+ }
358
+
359
+
360
+ export function quaternionUnimplemented(proj: { projName?: string }): QuaternionFunction;
361
+ export function quaternionUnimplemented(
362
+ proj: { projName?: string },
363
+ coords: Coordinates,
364
+ target?: Quaternion,
365
+ ): Quaternion;
366
+ /**
367
+ * Warns for an unimplemented projection, sets the quaternion to the
368
+ * identity (0,0,0,1).
369
+ *
370
+ * @param proj - the unimplemented projection (may be parsed using proj4)
371
+ * @param coordinates - the origin of the local East North Up (ENU) frame
372
+ * @param target - output Quaternion
373
+ * @returns The target quaternion if coordinates is defined, otherwise, a
374
+ * function to compute it from coordinates.
375
+ */
376
+ export function quaternionUnimplemented(
377
+ proj: { projName?: string },
378
+ coordinates?: Coordinates,
379
+ target = new Quaternion(),
380
+ ) {
381
+ console.warn(
382
+ 'This quaternion function is not implemented for projections of type',
383
+ proj.projName,
384
+ );
385
+ return coordinates ? target.set(0, 0, 0, 1) :
386
+ (coordinates: Coordinates, target = new Quaternion()) =>
387
+ quaternionUnimplemented(proj, coordinates, target);
388
+ }
389
+
390
+ export function quaternionFromEnuToCRS(proj: ProjectionLike): QuaternionFunction;
391
+ export function quaternionFromEnuToCRS(
392
+ proj: ProjectionLike,
393
+ coords: Coordinates,
394
+ target?: Quaternion,
395
+ ): Quaternion;
396
+ /**
397
+ * Compute the quaternion that models the rotation from the local East North
398
+ * Up (ENU) frame to the frame of the given crs.
399
+ *
400
+ * @param crsOrProj - the CRS of the target frame or its proj4-compatible
401
+ * object.
402
+ * @param coordinates - the origin of the local East North Up (ENU) frame
403
+ * @param target - output Quaternion
404
+ * @returns The target quaternion if coordinates is defined, otherwise, a
405
+ * function to compute it from coordinates.
406
+ */
407
+ export function quaternionFromEnuToCRS(
408
+ crsOrProj: ProjectionLike,
409
+ coordinates?: Coordinates,
410
+ target = new Quaternion(),
411
+ ) {
412
+ if (coordinates) { return quaternionFromEnuToCRS(crsOrProj)(coordinates, target); }
413
+ const proj = typeof crsOrProj === 'string' ? proj4.defs(crsOrProj) : crsOrProj;
414
+ switch (proj.projName) {
415
+ case 'geocent': return quaternionFromEnuToGeocent();
416
+ case 'lcc': return quaternionFromEnuToLCC(proj as LCCProjection);
417
+ case 'tmerc': return quaternionFromEnuToTMerc(proj as TMercProjection);
418
+ case 'longlat': return quaternionFromEnuToLongLat();
419
+ default: return quaternionUnimplemented(proj);
420
+ }
421
+ }
422
+
423
+ export function quaternionFromCRSToEnu(proj: ProjectionLike): QuaternionFunction;
424
+ export function quaternionFromCRSToEnu(
425
+ proj: ProjectionLike,
426
+ coords: Coordinates,
427
+ target?: Quaternion,
428
+ ): Quaternion;
429
+ /**
430
+ * Compute the quaternion that models the rotation from the frame of the
431
+ * given crs to the local East North Up (ENU) frame.
432
+ *
433
+ * @param crsOrProj - the CRS of the target frame or its proj4-compatible
434
+ * object.
435
+ * @param coordinates - the origin of the local East North Up (ENU) frame
436
+ * @param target - output Quaternion
437
+ * @returns The target quaternion if coordinates is defined, otherwise, a
438
+ * function to compute it from coordinates.
439
+ */
440
+ export function quaternionFromCRSToEnu(
441
+ crsOrProj: ProjectionLike,
442
+ coordinates?: Coordinates,
443
+ target = new Quaternion(),
444
+ ) {
445
+ if (coordinates) { return quaternionFromCRSToEnu(crsOrProj)(coordinates, target); }
446
+ const proj = typeof crsOrProj === 'string' ? proj4.defs(crsOrProj) : crsOrProj;
447
+ switch (proj.projName) {
448
+ case 'geocent': return quaternionFromGeocentToEnu();
449
+ case 'lcc': return quaternionFromLCCToEnu(proj as LCCProjection);
450
+ case 'tmerc': return quaternionFromTMercToEnu(proj as TMercProjection);
451
+ case 'longlat': return quaternionFromLongLatToEnu();
452
+ default: return quaternionUnimplemented(proj);
453
+ }
454
+ }
455
+
456
+ export function quaternionFromCRSToCRS(
457
+ crsIn: ProjectionLike,
458
+ crsOut: ProjectionLike,
459
+ ): QuaternionFunction;
460
+ export function quaternionFromCRSToCRS(
461
+ crsIn: ProjectionLike,
462
+ crsOut: ProjectionLike,
463
+ coords: Coordinates,
464
+ target?: Quaternion,
465
+ ): Quaternion;
466
+ /**
467
+ * Return the function that computes the quaternion that represents a
468
+ * rotation of coordinates between two CRS frames.
469
+ *
470
+ * @param crsIn - the CRS of the input frame.
471
+ * @param crsOut - the CRS of the output frame.
472
+ * @param coordinates - the origin of the local East North Up (ENU) frame
473
+ * @param target - output Quaternion
474
+ * @returns The target quaternion if coordinates is defined, otherwise, a
475
+ * function to compute it from coordinates.
476
+ */
477
+ export function quaternionFromCRSToCRS(
478
+ crsIn: ProjectionLike,
479
+ crsOut: ProjectionLike,
480
+ coordinates?: Coordinates,
481
+ target = new Quaternion(),
482
+ ) {
483
+ if (coordinates) { return quaternionFromCRSToCRS(crsIn, crsOut)(coordinates, target); }
484
+ if (crsIn == crsOut) {
485
+ return (origin: Coordinates, target = new Quaternion()) => target.set(0, 0, 0, 1);
486
+ }
487
+
488
+ // get rotations from the local East/North/Up (ENU) frame to both CRS.
489
+ const fromCrs = quaternionFromCRSToEnu(crsIn);
490
+ const toCrs = quaternionFromEnuToCRS(crsOut);
491
+ return (origin: Coordinates, target = new Quaternion()) =>
492
+ toCrs(origin, target).multiply(fromCrs(origin, quat));
493
+ }
package/src/Main.js DELETED
@@ -1,8 +0,0 @@
1
- // Geodesic tools
2
- export { default as Extent } from 'Extent';
3
- export { default as Coordinates } from 'Coordinates';
4
- export * as CRS from 'Crs';
5
- export { default as CoordStars } from 'CoordStars';
6
- export { default as OrientationUtils } from 'OrientationUtils';
7
- export { default as Ellipsoid, ellipsoidSizes } from 'Ellipsoid';
8
-
@@ -1,410 +0,0 @@
1
- import * as THREE from 'three';
2
- import proj4 from 'proj4';
3
- import Coordinates from 'Coordinates';
4
-
5
- const DEG2RAD = THREE.MathUtils.DEG2RAD;
6
- const matrix = new THREE.Matrix4();
7
- const north = new THREE.Vector3();
8
- const east = new THREE.Vector3();
9
- const axis = new THREE.Vector3().set(0, 0, 1);
10
- const coord = new Coordinates('EPSG:4326', 0, 0, 0);
11
- const euler = new THREE.Euler();
12
- const quat = new THREE.Quaternion();
13
-
14
- function quaternionIdentity(coordinates, target = new THREE.Quaternion()) {
15
- return coordinates ? target.set(0, 0, 0, 1) : quaternionIdentity;
16
- }
17
-
18
- /**
19
- * The OrientationUtils module provides methods to compute the quaternion that
20
- * models a rotation defined with various conventions, including between different
21
- * CRS.
22
- * The local <a href="https://en.wikipedia.org/wiki/Local_tangent_plane_coordinates#Local_east,_north,_up_(ENU)_coordinates">
23
- * East/North/Up frame (ENU)</a> is used as a pivot frame when computing the rotation between two distinct CRS.
24
- * If the origin of the frame is undefined, CRS-related methods precompute and return a function
25
- * that can be applied efficiently to many points of origin.
26
- * Otherwise, the target quaternion is returned at the provided origin coordinates.
27
- *
28
- * @example
29
- * // Compute the rotation around the point of origin from a frame aligned with Lambert93 axes (epsg:2154),
30
- * // to the geocentric frame (epsg:4978)
31
- * quat_crs2crs = OrientationUtils.quaternionFromCRSToCRS("EPSG:2154", "EPSG:4978")(origin);
32
- * // Compute the rotation of a sensor platform defined by its attitude
33
- * quat_attitude = OrientationUtils.quaternionFromAttitude(attitude);
34
- * // Compute the rotation from the sensor platform frame to the geocentric frame
35
- * quat = quat_crs2crs.multiply(quat_attitude);
36
- *
37
- * @module OrientationUtils
38
- */
39
- export default {
40
- /**
41
- * @typedef {Object} Attitude
42
- * Properties are either defined as (omega, phi, kappa) or as (roll, pitch,
43
- * heading) or all `undefined`.
44
- *
45
- * @property {number} omega - angle in degrees
46
- * @property {number} phi - angle in degrees
47
- * @property {number} kappa - angle in degrees
48
- * @property {number} roll - angle in degrees
49
- * @property {number} pitch - angle in degrees
50
- * @property {number} heading - angle in degrees
51
- */
52
-
53
- /**
54
- * The transform from the platform frame to the local East, North, Up (ENU)
55
- * frame is `RotationZ(heading).RotationX(pitch).RotationY(roll)`
56
- *
57
- * @param {number} [roll=0] - angle in degrees
58
- * @param {number} [pitch=0] - angle in degrees
59
- * @param {number} [heading=0] - angle in degrees
60
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] - output Quaternion
61
- *
62
- * @return {THREE.Quaternion} target quaternion
63
- */
64
- quaternionFromRollPitchHeading(roll = 0, pitch = 0, heading = 0, target = new THREE.Quaternion()) {
65
- roll *= DEG2RAD;
66
- pitch *= DEG2RAD;
67
- heading *= DEG2RAD;
68
- // return this.setFromEuler(euler.set(pitch, roll, heading , 'ZXY')).conjugate();
69
- return target.setFromEuler(euler.set(-pitch, -roll, -heading, 'YXZ')); // optimized version of above
70
- },
71
-
72
- /**
73
- * From
74
- * [DocMicMac](https://github.com/micmacIGN/Documentation/raw/master/DocMicMac.pdf),
75
- * the transform from the platform frame to the local East, North, Up (ENU)
76
- * frame is:
77
- *
78
- * ```
79
- * RotationX(omega).RotationY(phi).RotationZ(kappa).RotationX(PI)
80
- * RotationX(PI) <=> Quaternion(1,0,0,0) : converts between the 2 conventions for the camera local frame:
81
- * X right, Y bottom, Z front : convention in photogrammetry and computer vision
82
- * X right, Y top, Z back : convention in webGL, threejs
83
- * ```
84
- *
85
- * @param {number} [omega=0] - angle in degrees
86
- * @param {number} [phi=0] - angle in degrees
87
- * @param {number} [kappa=0] - angle in degrees
88
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
89
- *
90
- * @return {THREE.Quaternion} target quaternion
91
- */
92
- quaternionFromOmegaPhiKappa(omega = 0, phi = 0, kappa = 0, target = new THREE.Quaternion()) {
93
- omega *= DEG2RAD;
94
- phi *= DEG2RAD;
95
- kappa *= DEG2RAD;
96
- target.setFromEuler(euler.set(omega, phi, kappa, 'XYZ'));
97
- target.set(target.w, target.z, -target.y, -target.x); // <=> target.multiply(new THREE.Quaternion(1, 0, 0, 0));
98
- return target;
99
- },
100
-
101
- /**
102
- * Set the quaternion according to the rotation from the platform frame to
103
- * the local frame.
104
- *
105
- * @param {Attitude} attitude - Attitude
106
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
107
- *
108
- * @return {THREE.Quaternion} target quaternion
109
- */
110
- quaternionFromAttitude(attitude, target = new THREE.Quaternion()) {
111
- if ((attitude.roll !== undefined) || (attitude.pitch !== undefined) || (attitude.heading !== undefined)) {
112
- return this.quaternionFromRollPitchHeading(attitude.roll, attitude.pitch, attitude.heading, target);
113
- }
114
- if ((attitude.omega !== undefined) || (attitude.phi !== undefined) || (attitude.kappa !== undefined)) {
115
- return this.quaternionFromOmegaPhiKappa(attitude.omega, attitude.phi, attitude.kappa, target);
116
- }
117
- return target.set(0, 0, 0, 1);
118
- },
119
-
120
- /**
121
- * @typedef {Function|THREE.Quaternion} FunctionOrQuaternion - Either a
122
- * THREE.Quaternion or a function that accepts arguments `(coordinates,
123
- * target)` and returns the quaternion that models a rotation around the
124
- * point of origin. If target is not provided, a new quaternion is created
125
- * and returned instead.
126
- *
127
- * @property {Coordinates} coordinates the origin of the local East North Up
128
- * (ENU) frame
129
- * @property {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion.
130
- */
131
-
132
- /**
133
- * A Projection object models a Coordinate Reference System (CRS).
134
- * Such an object is usually created with proj4 using `proj4.defs(crs);`
135
- *
136
- * @typedef {Object} Projection
137
- *
138
- * @property {string} projName
139
- */
140
-
141
- /**
142
- * Set the quaternion according to the rotation from the local East North Up (ENU)
143
- * frame to the geocentric frame. The up direction of the ENU frame is
144
- * provided by the normalized geodetic normal of the provided coordinates
145
- * (geodeticNormal property).
146
- *
147
- * @param {Coordinates} [coordinates] the origin of the local East North Up
148
- * (ENU) frame
149
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
150
- * @return {FunctionOrQuaternion} The target quaternion if coordinates is defined, otherwise, a function to compute it from coordinates.
151
- */
152
- quaternionFromEnuToGeocent(coordinates, target = new THREE.Quaternion()) {
153
- if (coordinates) { return this.quaternionFromEnuToGeocent()(coordinates, target); }
154
- return (coordinates, target = new THREE.Quaternion()) => {
155
- const up = coordinates.geodesicNormal;
156
- if (up.x == 0 && up.y == 0) {
157
- return target.set(0, 0, 0, 1);
158
- }
159
- // this is an optimized version of matrix.lookAt(up, new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, 1));
160
- east.set(-up.y, up.x, 0).normalize();
161
- north.crossVectors(up, east);
162
- matrix.makeBasis(east, north, up);
163
- return target.setFromRotationMatrix(matrix);
164
- };
165
- },
166
-
167
- /**
168
- * Set the quaternion according to the rotation from a geocentric frame
169
- * to the local East North Up (ENU) frame. The up direction of the ENU frame is
170
- * provided by the normalized geodetic normal of the provided coordinates
171
- * (geodeticNormal property).
172
- *
173
- * @param {Coordinates} [coordinates] the origin of the local East North Up
174
- * (ENU) frame
175
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
176
- * @return {FunctionOrQuaternion} The target quaternion if coordinates is defined, otherwise, a function to compute it from coordinates.
177
- */
178
- quaternionFromGeocentToEnu(coordinates, target = new THREE.Quaternion()) {
179
- if (coordinates) { return this.quaternionFromGeocentToEnu()(coordinates, target); }
180
- const toGeocent = this.quaternionFromEnuToGeocent();
181
- return (coordinates, target = new THREE.Quaternion()) => toGeocent(coordinates, target).conjugate();
182
- },
183
-
184
-
185
- /**
186
- * Computes the rotation from a Lambert Conformal Conic (LCC) frame to the local East North Up (ENU) frame.
187
- * The quaternion accounts for the
188
- * <a href="https://geodesie.ign.fr/contenu/fichiers/documentation/algorithmes/alg0060.pdf">meridian convergence</a>
189
- * between the ENU and LCC frames.
190
- * This is a generally small rotation around Z.
191
- *
192
- * @param {Object} proj the lcc projection (may be parsed using proj4)
193
- * @param {number} proj.lat0 - the latitude of origin
194
- * @param {number} proj.long0 - the longitude of the central meridian
195
- * @param {Coordinates} [coordinates] coordinates the origin of the local East North Up
196
- * (ENU) frame
197
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
198
- * @return {FunctionOrQuaternion} The target quaternion if coordinates is defined, otherwise, a function to compute it from coordinates.
199
- */
200
- quaternionFromLCCToEnu(proj, coordinates, target = new THREE.Quaternion()) {
201
- if (coordinates) { return this.quaternionFromLCCToEnu(proj)(coordinates, target); }
202
- const sinlat0 = Math.sin(proj.lat0);
203
- return (coordinates, target = new THREE.Quaternion()) => {
204
- const long = coordinates.as(coord.crs, coord).longitude * DEG2RAD;
205
- return target.setFromAxisAngle(axis, sinlat0 * (proj.long0 - long));
206
- };
207
- },
208
-
209
- /**
210
- * Computes the rotation from the local East North Up (ENU) frame to a Lambert Conformal Conic (LCC) frame.
211
- * The quaternion accounts for the
212
- * <a href="https://geodesie.ign.fr/contenu/fichiers/documentation/algorithmes/alg0060.pdf">meridian convergence</a>
213
- * between the ENU and LCC frames.
214
- * This is a generally small rotation around Z.
215
- *
216
- * @param {Object} proj the lcc projection (may be parsed using proj4)
217
- * @param {number} proj.lat0 - the latitude of origin
218
- * @param {number} proj.long0 - the longitude of the central meridian
219
- * @param {Coordinates} [coordinates] coordinates the origin of the local East North Up
220
- * (ENU) frame
221
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
222
- * @return {FunctionOrQuaternion} The target quaternion if coordinates is defined, otherwise, a function to compute it from coordinates.
223
- */
224
- quaternionFromEnuToLCC(proj, coordinates, target = new THREE.Quaternion()) {
225
- if (coordinates) { return this.quaternionFromEnuToLCC(proj)(coordinates, target); }
226
- const fromLCC = this.quaternionFromLCCToEnu(proj);
227
- return (coordinates, target = new THREE.Quaternion()) => fromLCC(coordinates, target).conjugate();
228
- },
229
-
230
- /**
231
- * Computes the rotation from a Transverse Mercator frame (TMerc) to the local East North Up (ENU) frame.
232
- * The quaternion accounts for the
233
- * <a href="https://geodesie.ign.fr/contenu/fichiers/documentation/algorithmes/alg0061.pdf">meridian convergence</a>
234
- * between the ENU and TMerc frames.
235
- * This is a generally small rotation around Z.
236
- *
237
- * @param {Object} proj the tmerc projection (may be parsed using proj4)
238
- * @param {number} proj.e - the excentricity of the ellipsoid (supersedes {proj.a} and {proj.b})
239
- * @param {number} proj.a - the semimajor radius of the ellipsoid axis
240
- * @param {number} proj.b - the semiminor radius of the ellipsoid axis
241
- * @param {number} proj.long0 - the longitude of the central meridian
242
- *
243
- * @param {Coordinates} [coordinates] coordinates the origin of the local East North Up
244
- * (ENU) frame
245
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
246
- * @return {FunctionOrQuaternion} The target quaternion if coordinates is defined, otherwise, a function to compute it from coordinates.
247
- */
248
- quaternionFromTMercToEnu(proj, coordinates, target = new THREE.Quaternion()) {
249
- if (coordinates) { return this.quaternionFromTMercToEnu(proj)(coordinates, target); }
250
- const a2 = proj.a * proj.a;
251
- const b2 = proj.b * proj.b;
252
- const e2 = proj.e * proj.e;
253
- const eta0 = proj.e ? (e2 / (1 - e2)) : (a2 / b2 - 1);
254
- return (coordinates, target = new THREE.Quaternion()) => {
255
- coordinates.as(coord.crs, coord);
256
- const long = coord.longitude * DEG2RAD;
257
- const lat = coord.latitude * DEG2RAD;
258
- const dlong = proj.long0 - long;
259
- const coslat = Math.cos(lat);
260
- const sinlat = Math.sin(lat);
261
- const tanlat = sinlat / coslat;
262
- const coslat2 = coslat * coslat;
263
- const dl2 = dlong * dlong * coslat2;
264
- const eta2 = eta0 * coslat2;
265
- const gamma = dlong * sinlat * (1 + dl2 / 3 * (1 + 3 * eta2 + 2 * eta2 * eta2) + dl2 * dl2 * (2 - tanlat) / 15);
266
- return target.setFromAxisAngle(axis, gamma);
267
- };
268
- },
269
-
270
- /**
271
- * Computes the rotation from the local East North Up (ENU) to a Transverse Mercator frame.
272
- * The quaternion accounts for the
273
- * <a href="https://geodesie.ign.fr/contenu/fichiers/documentation/algorithmes/alg0061.pdf">meridian convergence</a>
274
- * between the ENU and TMerc frames.
275
- * This is a generally small rotation around Z.
276
- *
277
- * @param {Object} proj the tmerc projection (may be parsed using proj4)
278
- * @param {number} proj.e - the excentricity of the ellipsoid (supersedes
279
- * {proj.a} and {proj.b})
280
- * @param {number} proj.a - the semimajor radius of the ellipsoid axis
281
- * @param {number} proj.b - the semiminor radius of the ellipsoid axis
282
- * @param {number} proj.long0 - the longitude of the central meridian
283
- *
284
- * @param {Coordinates} [coordinates] coordinates the origin of the local East North Up
285
- * (ENU) frame
286
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
287
- * @return {FunctionOrQuaternion} The target quaternion if coordinates is defined, otherwise, a function to compute it from coordinates.
288
- */
289
- quaternionFromEnuToTMerc(proj, coordinates, target = new THREE.Quaternion()) {
290
- if (coordinates) { return this.quaternionFromEnuToTMerc(proj)(coordinates, target); }
291
- const fromTMerc = this.quaternionFromTMercToEnu(proj);
292
- return (coordinates, target = new THREE.Quaternion()) => fromTMerc(coordinates, target).conjugate();
293
- },
294
-
295
- /**
296
- * Computes the rotation from a LongLat frame to the local East North Up (ENU) frame.
297
- * The identity quaternion (0,0,0,1) is returned, as longlat and ENU frame are assumed to be aligned.
298
- *
299
- * @param {Coordinates} [coordinates] coordinates the origin of the local East North Up
300
- * (ENU) frame
301
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
302
- * @return {FunctionOrQuaternion} The target quaternion if coordinates is defined, otherwise, a function to compute it from coordinates.
303
- */
304
- quaternionFromLongLatToEnu(coordinates, target = new THREE.Quaternion()) {
305
- return quaternionIdentity(coordinates, target);
306
- },
307
-
308
- /**
309
- * Computes the rotation from the local East North Up (ENU) frame to a LongLat frame.
310
- * The identity quaternion (0,0,0,1) is returned, as longlat and ENU frame are assumed to be aligned.
311
- *
312
- * @param {Coordinates} [coordinates] coordinates the origin of the local East North Up
313
- * (ENU) frame
314
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
315
- * @return {FunctionOrQuaternion} The target quaternion if coordinates is defined, otherwise, a function to compute it from coordinates.
316
- */
317
- quaternionFromEnuToLongLat(coordinates, target = new THREE.Quaternion()) {
318
- return quaternionIdentity(coordinates, target);
319
- },
320
-
321
-
322
- /**
323
- * Warns for an unimplemented projection, sets the quaternion to the
324
- * identity (0,0,0,1).
325
- *
326
- * @param {Projection} proj - the unimplemented projection (may be parsed
327
- * using proj4)
328
- *
329
- * @param {Coordinates} [coordinates] coordinates the origin of the local East North Up
330
- * (ENU) frame
331
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
332
- * @return {FunctionOrQuaternion} The target quaternion if coordinates is defined, otherwise, a function to compute it from coordinates.
333
- */
334
- quaternionUnimplemented(proj, coordinates, target = new THREE.Quaternion()) {
335
- console.warn('This quaternion function is not implemented for projections of type', proj.projName);
336
- return quaternionIdentity(coordinates, target);
337
- },
338
-
339
- /**
340
- * Compute the quaternion that models the rotation from the local East North
341
- * Up (ENU) frame to the frame of the given crs.
342
- *
343
- * @param {string|Projection} crsOrProj - the CRS of the target frame or its
344
- * proj4-compatible object.
345
- *
346
- * @param {Coordinates} [coordinates] coordinates the origin of the local East North Up
347
- * (ENU) frame
348
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
349
- * @return {FunctionOrQuaternion} The target quaternion if coordinates is defined, otherwise, a function to compute it from coordinates.
350
- */
351
- quaternionFromEnuToCRS(crsOrProj, coordinates, target = new THREE.Quaternion()) {
352
- if (coordinates) { return this.quaternionFromEnuToCRS(crsOrProj)(coordinates, target); }
353
- const proj = crsOrProj.projName ? crsOrProj : proj4.defs(crsOrProj);
354
- switch (proj.projName) {
355
- case 'geocent': return this.quaternionFromEnuToGeocent();
356
- case 'lcc': return this.quaternionFromEnuToLCC(proj);
357
- case 'tmerc': return this.quaternionFromEnuToTMerc(proj);
358
- case 'longlat': return this.quaternionFromEnuToLongLat();
359
- default: return this.quaternionUnimplemented(proj);
360
- }
361
- },
362
-
363
- /**
364
- * Compute the quaternion that models the rotation from the frame of the
365
- * given crs to the local East North Up (ENU) frame.
366
- *
367
- * @param {string|Projection} crsOrProj - the CRS of the source frame or its
368
- * proj4-compatible object.
369
- *
370
- * @param {Coordinates} [coordinates] coordinates the origin of the local East North Up
371
- * (ENU) frame
372
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
373
- * @return {FunctionOrQuaternion} The target quaternion if coordinates is defined, otherwise, a function to compute it from coordinates.
374
- */
375
- quaternionFromCRSToEnu(crsOrProj, coordinates, target = new THREE.Quaternion()) {
376
- if (coordinates) { return this.quaternionFromCRSToEnu(crsOrProj)(coordinates, target); }
377
- const proj = crsOrProj.projName ? crsOrProj : proj4.defs(crsOrProj);
378
- switch (proj.projName) {
379
- case 'geocent': return this.quaternionFromGeocentToEnu();
380
- case 'lcc': return this.quaternionFromLCCToEnu(proj);
381
- case 'tmerc': return this.quaternionFromTMercToEnu(proj);
382
- case 'longlat': return this.quaternionFromLongLatToEnu();
383
- default: return this.quaternionUnimplemented(proj);
384
- }
385
- },
386
-
387
- /**
388
- * Return the function that computes the quaternion that represents a
389
- * rotation of coordinates between two CRS frames.
390
- *
391
- * @param {string} crsIn - the CRS of the input frame.
392
- * @param {string} crsOut - the CRS of the output frame.
393
- * @param {Coordinates} [coordinates] coordinates - the origin of the local East North Up
394
- * (ENU) frame
395
- * @param {THREE.Quaternion} [target=new THREE.Quaternion()] output Quaternion
396
- * @return {FunctionOrQuaternion} The target quaternion if coordinates is defined, otherwise, a function to compute it from coordinates.
397
- */
398
- quaternionFromCRSToCRS(crsIn, crsOut, coordinates, target = new THREE.Quaternion()) {
399
- if (coordinates) { return this.quaternionFromCRSToCRS(crsIn, crsOut)(coordinates, target); }
400
- if (crsIn == crsOut) {
401
- return (origin, target = new THREE.Quaternion()) => target.set(0, 0, 0, 1);
402
- }
403
-
404
- // get rotations from the local East/North/Up (ENU) frame to both CRS.
405
- const fromCrs = this.quaternionFromCRSToEnu(crsIn);
406
- const toCrs = this.quaternionFromEnuToCRS(crsOut);
407
- return (origin, target = new THREE.Quaternion()) =>
408
- toCrs(origin, target).multiply(fromCrs(origin, quat));
409
- },
410
- };