@itowns/geographic 2.46.1-next.6 → 2.46.1-next.60
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/lib/CoordStars.d.ts +13 -0
- package/lib/Coordinates.d.ts +208 -0
- package/lib/Coordinates.js +21 -34
- package/lib/Crs.d.ts +111 -0
- package/lib/Crs.js +67 -11
- package/lib/Ellipsoid.d.ts +77 -0
- package/lib/Ellipsoid.js +9 -11
- package/lib/Extent.d.ts +287 -0
- package/lib/Extent.js +68 -46
- package/lib/OrientationUtils.d.ts +105 -0
- package/lib/OrientationUtils.js +42 -74
- package/lib/index.d.ts +7 -0
- package/package.json +7 -8
- package/src/Coordinates.ts +19 -24
- package/src/Crs.ts +82 -12
- package/src/Ellipsoid.ts +6 -3
- package/src/Extent.ts +62 -21
- package/src/OrientationUtils.ts +29 -10
package/src/Ellipsoid.ts
CHANGED
|
@@ -47,6 +47,7 @@ class Ellipsoid {
|
|
|
47
47
|
* @param cartesian - The given cartesian coordinate.
|
|
48
48
|
* @param target - An object to store this vector to. If this is not
|
|
49
49
|
* specified, a new vector will be created.
|
|
50
|
+
* @returns
|
|
50
51
|
*/
|
|
51
52
|
geodeticSurfaceNormal(
|
|
52
53
|
cartesian: Coordinates,
|
|
@@ -62,6 +63,7 @@ class Ellipsoid {
|
|
|
62
63
|
* @param coordCarto - The given geographic coordinate.
|
|
63
64
|
* @param target - An object to store this vector to. If this is not
|
|
64
65
|
* specified, a new vector will be created.
|
|
66
|
+
* @returns
|
|
65
67
|
*/
|
|
66
68
|
geodeticSurfaceNormalCartographic(
|
|
67
69
|
coordCarto: Coordinates,
|
|
@@ -82,6 +84,7 @@ class Ellipsoid {
|
|
|
82
84
|
* properties.
|
|
83
85
|
*
|
|
84
86
|
* @param size - The source vector.
|
|
87
|
+
* @returns
|
|
85
88
|
*/
|
|
86
89
|
setSize(size: Vector3Like): this {
|
|
87
90
|
this.size.set(size.x, size.y, size.z);
|
|
@@ -146,7 +149,7 @@ class Ellipsoid {
|
|
|
146
149
|
|
|
147
150
|
const phi = Math.atan(
|
|
148
151
|
(position.z * (1 - f) + e * a * sinu * sinu * sinu) /
|
|
149
|
-
|
|
152
|
+
((1 - f) * (rsqXY - e * a * cosu * cosu * cosu)));
|
|
150
153
|
|
|
151
154
|
const h = (rsqXY * Math.cos(phi)) +
|
|
152
155
|
position.z * Math.sin(phi) -
|
|
@@ -202,7 +205,7 @@ class Ellipsoid {
|
|
|
202
205
|
return false;
|
|
203
206
|
}
|
|
204
207
|
|
|
205
|
-
let t
|
|
208
|
+
let t;
|
|
206
209
|
if (t1 <= EPSILON) { t = t2; } else
|
|
207
210
|
if (t2 <= EPSILON) { t = t1; } else { t = (t1 < t2) ? t1 : t2; }
|
|
208
211
|
|
|
@@ -236,7 +239,7 @@ class Ellipsoid {
|
|
|
236
239
|
|
|
237
240
|
const distRad = Math.acos(
|
|
238
241
|
Math.sin(latitude1) * Math.sin(latitude2) +
|
|
239
|
-
|
|
242
|
+
Math.cos(latitude1) * Math.cos(latitude2) * Math.cos(longitude2 - longitude1));
|
|
240
243
|
|
|
241
244
|
const e = this.eccentricity;
|
|
242
245
|
const latMoy = (latitude1 + latitude2) * 0.5;
|
package/src/Extent.ts
CHANGED
|
@@ -16,8 +16,6 @@ const cNorthEast = /* @__PURE__ */ new Coordinates('EPSG:4326', 0, 0, 0);
|
|
|
16
16
|
const southWest = /* @__PURE__ */ new Vector3();
|
|
17
17
|
const northEast = /* @__PURE__ */ new Vector3();
|
|
18
18
|
|
|
19
|
-
let _extent: Extent;
|
|
20
|
-
|
|
21
19
|
const cardinals = [
|
|
22
20
|
/* @__PURE__ */ new Coordinates('EPSG:4326', 0, 0, 0),
|
|
23
21
|
/* @__PURE__ */ new Coordinates('EPSG:4326', 0, 0, 0),
|
|
@@ -100,6 +98,7 @@ class Extent {
|
|
|
100
98
|
|
|
101
99
|
/**
|
|
102
100
|
* Returns a new extent with the same bounds and crs as this one.
|
|
101
|
+
* @returns
|
|
103
102
|
*/
|
|
104
103
|
clone() {
|
|
105
104
|
return new Extent(this.crs, this.west, this.east, this.south, this.north);
|
|
@@ -111,6 +110,7 @@ class Extent {
|
|
|
111
110
|
* @param crs - target's projection.
|
|
112
111
|
* @param target - The target to store the projected extent. If this not
|
|
113
112
|
* provided a new extent will be created.
|
|
113
|
+
* @returns
|
|
114
114
|
*/
|
|
115
115
|
as(crs: string, target: Extent = new Extent('EPSG:4326')) {
|
|
116
116
|
CRS.isValid(crs);
|
|
@@ -155,6 +155,7 @@ class Extent {
|
|
|
155
155
|
*
|
|
156
156
|
* @param target - The target to store the center coordinate. If this not
|
|
157
157
|
* provided a new coordinate will be created.
|
|
158
|
+
* @returns
|
|
158
159
|
*/
|
|
159
160
|
center(target = new Coordinates(this.crs)) {
|
|
160
161
|
this.planarDimensions(_dim);
|
|
@@ -172,6 +173,7 @@ class Extent {
|
|
|
172
173
|
* 2D Cartesian coordinate system.
|
|
173
174
|
*
|
|
174
175
|
* @param target - optional target
|
|
176
|
+
* @returns
|
|
175
177
|
*/
|
|
176
178
|
planarDimensions(target = new Vector2()) {
|
|
177
179
|
// Calculte the dimensions for x and y
|
|
@@ -185,6 +187,7 @@ class Extent {
|
|
|
185
187
|
* across the curved surface of the ellipsoid.
|
|
186
188
|
*
|
|
187
189
|
* @param target - optional target
|
|
190
|
+
* @returns
|
|
188
191
|
*/
|
|
189
192
|
geodeticDimensions(target = new Vector2()) {
|
|
190
193
|
// set 3 corners extent
|
|
@@ -209,6 +212,7 @@ class Extent {
|
|
|
209
212
|
* Spatial euclidean distance chord is calculated in an ellispoid space.
|
|
210
213
|
*
|
|
211
214
|
* @param target - optional target
|
|
215
|
+
* @returns
|
|
212
216
|
*/
|
|
213
217
|
spatialEuclideanDimensions(target = new Vector2()) {
|
|
214
218
|
// set 3 corners extent
|
|
@@ -233,6 +237,7 @@ class Extent {
|
|
|
233
237
|
* @param coord - the given coordinates.
|
|
234
238
|
* @param epsilon - error margin when comparing to the coordinates.
|
|
235
239
|
* Default is 0.
|
|
240
|
+
* @returns
|
|
236
241
|
*/
|
|
237
242
|
isPointInside(coord: Coordinates, epsilon = 0) {
|
|
238
243
|
if (this.crs == coord.crs) {
|
|
@@ -243,9 +248,9 @@ class Extent {
|
|
|
243
248
|
|
|
244
249
|
// TODO this ignores altitude
|
|
245
250
|
return _c.x <= this.east + epsilon &&
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
251
|
+
_c.x >= this.west - epsilon &&
|
|
252
|
+
_c.y <= this.north + epsilon &&
|
|
253
|
+
_c.y >= this.south - epsilon;
|
|
249
254
|
}
|
|
250
255
|
|
|
251
256
|
/**
|
|
@@ -253,13 +258,14 @@ class Extent {
|
|
|
253
258
|
*
|
|
254
259
|
* @param extent - the extent to check
|
|
255
260
|
* @param epsilon - error margin when comparing the extent bounds.
|
|
261
|
+
* @returns
|
|
256
262
|
*/
|
|
257
263
|
isInside(extent: Extent, epsilon = CRS.reasonableEpsilon(this.crs)) {
|
|
258
264
|
extent.as(this.crs, _extent);
|
|
259
265
|
return this.east - _extent.east <= epsilon &&
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
266
|
+
_extent.west - this.west <= epsilon &&
|
|
267
|
+
this.north - _extent.north <= epsilon &&
|
|
268
|
+
_extent.south - this.south <= epsilon;
|
|
263
269
|
}
|
|
264
270
|
|
|
265
271
|
/**
|
|
@@ -294,13 +300,27 @@ class Extent {
|
|
|
294
300
|
* Checks wheter this bounding box intersects with the given extent
|
|
295
301
|
* parameter.
|
|
296
302
|
* @param extent - the provided extent
|
|
303
|
+
* @returns
|
|
297
304
|
*/
|
|
298
305
|
intersectsExtent(extent: Extent) {
|
|
299
306
|
return Extent.intersectsExtent(this, extent);
|
|
300
307
|
}
|
|
301
308
|
|
|
309
|
+
/**
|
|
310
|
+
* Tests whether two extents intersect.
|
|
311
|
+
*
|
|
312
|
+
* This method checks if the geographic extents `extentA` and `extentB`
|
|
313
|
+
* overlap. If their coordinate reference systems (CRS) differ, `extentB`
|
|
314
|
+
* is reprojected into the CRS of `extentA` before performing the test.
|
|
315
|
+
*
|
|
316
|
+
* Extents that touch at an edge or a corner aren't treated as intersecting.
|
|
317
|
+
*
|
|
318
|
+
* @param extentA - The reference extent.
|
|
319
|
+
* @param extentB - The extent to test against.
|
|
320
|
+
*
|
|
321
|
+
* @returns `true` if the extents intersect, `false` otherwise.
|
|
322
|
+
*/
|
|
302
323
|
static intersectsExtent(extentA: Extent, extentB: Extent) {
|
|
303
|
-
// TODO don't work when is on limit
|
|
304
324
|
const other = extentB.crs == extentA.crs ? extentB : extentB.as(extentA.crs, _extent);
|
|
305
325
|
return !(extentA.west >= other.east ||
|
|
306
326
|
extentA.east <= other.west ||
|
|
@@ -310,16 +330,29 @@ class Extent {
|
|
|
310
330
|
|
|
311
331
|
/**
|
|
312
332
|
* Returns the intersection of this extent with another one.
|
|
313
|
-
*
|
|
333
|
+
*
|
|
334
|
+
* This method computes the overlapping region between this extent and
|
|
335
|
+
* another extent. If their coordinate reference systems (CRS) differ,
|
|
336
|
+
* the other extent is reprojected into the CRS of this extent before
|
|
337
|
+
* performing the intersection.
|
|
338
|
+
*
|
|
339
|
+
*
|
|
340
|
+
* @param extent - The extent to intersect with this one.
|
|
341
|
+
* @param target - The target extent to store the result. If not provided,
|
|
342
|
+
* a new extent will be created.
|
|
343
|
+
*
|
|
344
|
+
* @returns The intersection extent
|
|
345
|
+
* (may be empty if extents do not intersect).
|
|
314
346
|
*/
|
|
315
|
-
intersect(extent: Extent) {
|
|
347
|
+
intersect(extent: Extent, target = new Extent(this.crs)) {
|
|
316
348
|
if (!this.intersectsExtent(extent)) {
|
|
317
|
-
return
|
|
349
|
+
return target;
|
|
318
350
|
}
|
|
319
351
|
if (extent.crs != this.crs) {
|
|
320
352
|
extent = extent.as(this.crs, _extent);
|
|
321
353
|
}
|
|
322
|
-
|
|
354
|
+
|
|
355
|
+
return target.set(
|
|
323
356
|
Math.max(this.west, extent.west),
|
|
324
357
|
Math.min(this.east, extent.east),
|
|
325
358
|
Math.max(this.south, extent.south),
|
|
@@ -333,6 +366,7 @@ class Extent {
|
|
|
333
366
|
* @param v1 - the `east` value of this extent. Default is 0.
|
|
334
367
|
* @param v2 - the `south` value of this extent. Default is 0.
|
|
335
368
|
* @param v3 - the `north` value of this extent. Default is 0.
|
|
369
|
+
* @returns
|
|
336
370
|
*/
|
|
337
371
|
set(v0: number, v1: number, v2: number, v3: number): this {
|
|
338
372
|
if (v0 == undefined) {
|
|
@@ -370,8 +404,9 @@ class Extent {
|
|
|
370
404
|
* `north` property to `array[offset + 3]`.
|
|
371
405
|
* @param array - the source array
|
|
372
406
|
* @param offset - offset into the array. Default is 0.
|
|
407
|
+
* @returns
|
|
373
408
|
*/
|
|
374
|
-
setFromArray(array: ArrayLike<number>, offset
|
|
409
|
+
setFromArray(array: ArrayLike<number>, offset = 0): this {
|
|
375
410
|
this.west = array[offset];
|
|
376
411
|
this.east = array[offset + 1];
|
|
377
412
|
this.south = array[offset + 2];
|
|
@@ -383,6 +418,7 @@ class Extent {
|
|
|
383
418
|
* Sets this extent `west`, `east`, `south` and `north` properties from an
|
|
384
419
|
* `extent` bounds.
|
|
385
420
|
* @param extent - the source extent
|
|
421
|
+
* @returns
|
|
386
422
|
*/
|
|
387
423
|
setFromExtent(extent: ExtentLike): this {
|
|
388
424
|
this.west = extent.west;
|
|
@@ -395,6 +431,7 @@ class Extent {
|
|
|
395
431
|
/**
|
|
396
432
|
* Copies the passed extent to this extent.
|
|
397
433
|
* @param extent - extent to copy.
|
|
434
|
+
* @returns
|
|
398
435
|
*/
|
|
399
436
|
copy(extent: Extent): this {
|
|
400
437
|
this.crs = extent.crs;
|
|
@@ -404,6 +441,7 @@ class Extent {
|
|
|
404
441
|
/**
|
|
405
442
|
* Union this extent with the input extent.
|
|
406
443
|
* @param extent - the extent to union.
|
|
444
|
+
* @returns
|
|
407
445
|
*/
|
|
408
446
|
union(extent: Extent) {
|
|
409
447
|
if (extent.crs != this.crs) {
|
|
@@ -432,6 +470,8 @@ class Extent {
|
|
|
432
470
|
this.north = north;
|
|
433
471
|
}
|
|
434
472
|
}
|
|
473
|
+
|
|
474
|
+
return this;
|
|
435
475
|
}
|
|
436
476
|
|
|
437
477
|
/**
|
|
@@ -445,12 +485,11 @@ class Extent {
|
|
|
445
485
|
}
|
|
446
486
|
|
|
447
487
|
/**
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
*/
|
|
488
|
+
* expandByValuesCoordinates perfoms the minimal extension
|
|
489
|
+
* for the coordinates values to belong to this Extent object
|
|
490
|
+
* @param we - The coordinate on west-east
|
|
491
|
+
* @param sn - The coordinate on south-north
|
|
492
|
+
*/
|
|
454
493
|
expandByValuesCoordinates(we: number, sn: number) {
|
|
455
494
|
if (we < this.west) {
|
|
456
495
|
this.west = we;
|
|
@@ -475,6 +514,7 @@ class Extent {
|
|
|
475
514
|
*
|
|
476
515
|
* @param crs - Projection of extent to instancied.
|
|
477
516
|
* @param box - Bounding-box
|
|
517
|
+
* @returns
|
|
478
518
|
*/
|
|
479
519
|
static fromBox3(crs: ProjectionLike, box: Box3) {
|
|
480
520
|
if (CRS.isGeocentric(crs)) {
|
|
@@ -499,6 +539,7 @@ class Extent {
|
|
|
499
539
|
/**
|
|
500
540
|
* Return values of extent in string, separated by the separator input.
|
|
501
541
|
* @param sep - string separator
|
|
542
|
+
* @returns
|
|
502
543
|
*/
|
|
503
544
|
toString(sep = '') {
|
|
504
545
|
return `${this.east}${sep}${this.north}${sep}${this.west}${sep}${this.south}`;
|
|
@@ -603,6 +644,6 @@ class Extent {
|
|
|
603
644
|
}
|
|
604
645
|
}
|
|
605
646
|
|
|
606
|
-
_extent = /* @__PURE__ */ new Extent('EPSG:4326');
|
|
647
|
+
const _extent = /* @__PURE__ */ new Extent('EPSG:4326');
|
|
607
648
|
|
|
608
649
|
export default Extent;
|
package/src/OrientationUtils.ts
CHANGED
|
@@ -32,9 +32,10 @@ type Attitude = Partial<EulerAngles> | Partial<PhotogrammetryAngles>;
|
|
|
32
32
|
|
|
33
33
|
type QuaternionFunction = (coords: Coordinates, target?: Quaternion) => Quaternion;
|
|
34
34
|
|
|
35
|
+
// To unify with Crs.js ProjectionLike type ?
|
|
35
36
|
type ProjectionLike = ProjectionDefinition | string;
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
interface LCCProjection { long0: number; lat0: number }
|
|
38
|
+
interface TMercProjection { a: number; b: number; e?: number; long0: number }
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
41
|
* The transform from the platform frame to the local East, North, Up (ENU)
|
|
@@ -366,6 +367,7 @@ export function quaternionUnimplemented(
|
|
|
366
367
|
* identity (0,0,0,1).
|
|
367
368
|
*
|
|
368
369
|
* @param proj - the unimplemented projection (may be parsed using proj4)
|
|
370
|
+
* @param proj.projName - the name of the projection
|
|
369
371
|
* @param coordinates - the origin of the local East North Up (ENU) frame
|
|
370
372
|
* @param target - output Quaternion
|
|
371
373
|
* @returns The target quaternion if coordinates is defined, otherwise, a
|
|
@@ -416,6 +418,7 @@ export function quaternionFromEnuToCRS(
|
|
|
416
418
|
case 'Geocentric': return quaternionFromEnuToGeocent();
|
|
417
419
|
case 'Lambert Tangential Conformal Conic Projection':
|
|
418
420
|
return quaternionFromEnuToLCC(proj as LCCProjection);
|
|
421
|
+
case 'Universal Transverse Mercator System':
|
|
419
422
|
case 'Fast_Transverse_Mercator': return quaternionFromEnuToTMerc(proj as TMercProjection);
|
|
420
423
|
case 'longlat': return quaternionFromEnuToLongLat();
|
|
421
424
|
default: return quaternionUnimplemented(proj);
|
|
@@ -453,19 +456,21 @@ export function quaternionFromCRSToEnu(
|
|
|
453
456
|
case 'Geocentric': return quaternionFromGeocentToEnu();
|
|
454
457
|
case 'Lambert Tangential Conformal Conic Projection':
|
|
455
458
|
return quaternionFromLCCToEnu(proj as LCCProjection);
|
|
459
|
+
case 'Universal Transverse Mercator System':
|
|
456
460
|
case 'Fast_Transverse_Mercator': return quaternionFromTMercToEnu(proj as TMercProjection);
|
|
457
461
|
case 'longlat': return quaternionFromLongLatToEnu();
|
|
458
462
|
default: return quaternionUnimplemented(proj);
|
|
459
463
|
}
|
|
460
464
|
}
|
|
461
465
|
|
|
466
|
+
const quaternionCrs2CrsCache: Record<string, Record<string, QuaternionFunction>> = {};
|
|
462
467
|
export function quaternionFromCRSToCRS(
|
|
463
|
-
crsIn:
|
|
464
|
-
crsOut:
|
|
468
|
+
crsIn: string,
|
|
469
|
+
crsOut: string,
|
|
465
470
|
): QuaternionFunction;
|
|
466
471
|
export function quaternionFromCRSToCRS(
|
|
467
|
-
crsIn:
|
|
468
|
-
crsOut:
|
|
472
|
+
crsIn: string,
|
|
473
|
+
crsOut: string,
|
|
469
474
|
coords: Coordinates,
|
|
470
475
|
target?: Quaternion,
|
|
471
476
|
): Quaternion;
|
|
@@ -481,8 +486,8 @@ export function quaternionFromCRSToCRS(
|
|
|
481
486
|
* function to compute it from coordinates.
|
|
482
487
|
*/
|
|
483
488
|
export function quaternionFromCRSToCRS(
|
|
484
|
-
crsIn:
|
|
485
|
-
crsOut:
|
|
489
|
+
crsIn: string,
|
|
490
|
+
crsOut: string,
|
|
486
491
|
coordinates?: Coordinates,
|
|
487
492
|
target = new Quaternion(),
|
|
488
493
|
) {
|
|
@@ -491,9 +496,23 @@ export function quaternionFromCRSToCRS(
|
|
|
491
496
|
return (origin: Coordinates, target = new Quaternion()) => target.set(0, 0, 0, 1);
|
|
492
497
|
}
|
|
493
498
|
|
|
499
|
+
if (quaternionCrs2CrsCache[crsIn] && quaternionCrs2CrsCache[crsIn][crsOut]) {
|
|
500
|
+
return quaternionCrs2CrsCache[crsIn][crsOut];
|
|
501
|
+
}
|
|
502
|
+
|
|
494
503
|
// get rotations from the local East/North/Up (ENU) frame to both CRS.
|
|
495
504
|
const fromCrs = quaternionFromCRSToEnu(crsIn);
|
|
496
505
|
const toCrs = quaternionFromEnuToCRS(crsOut);
|
|
497
|
-
|
|
498
|
-
|
|
506
|
+
|
|
507
|
+
if (!quaternionCrs2CrsCache[crsIn]) {
|
|
508
|
+
quaternionCrs2CrsCache[crsIn] = {};
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
if (!quaternionCrs2CrsCache[crsIn][crsOut]) {
|
|
512
|
+
quaternionCrs2CrsCache[crsIn][crsOut] =
|
|
513
|
+
(origin: Coordinates, target = new Quaternion()) =>
|
|
514
|
+
toCrs(origin, target).multiply(fromCrs(origin, quat));
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return quaternionCrs2CrsCache[crsIn][crsOut];
|
|
499
518
|
}
|