@itowns/geographic 2.44.3-next.43 → 2.44.3-next.44
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 +4 -5
- package/src/{CoordStars.js → CoordStars.ts} +21 -15
- package/src/Coordinates.ts +1 -1
- package/src/Ellipsoid.ts +1 -1
- package/src/Main.ts +8 -0
- package/src/OrientationUtils.ts +493 -0
- package/src/Main.js +0 -8
- package/src/OrientationUtils.js +0 -410
package/package.json
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itowns/geographic",
|
|
3
|
-
"version": "2.44.3-next.
|
|
3
|
+
"version": "2.44.3-next.44",
|
|
4
4
|
"description": "Geodesy",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/Main.js",
|
|
7
|
-
"exports":
|
|
8
|
-
|
|
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
|
|
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 +
|
|
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
|
|
package/src/Coordinates.ts
CHANGED
package/src/Ellipsoid.ts
CHANGED
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
|
-
|
package/src/OrientationUtils.js
DELETED
|
@@ -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
|
-
};
|