@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/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
- ((1 - f) * (rsqXY - e * a * cosu * cosu * cosu)));
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 = 0;
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
- Math.cos(latitude1) * Math.cos(latitude2) * Math.cos(longitude2 - longitude1));
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
- _c.x >= this.west - epsilon &&
247
- _c.y <= this.north + epsilon &&
248
- _c.y >= this.south - epsilon;
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
- _extent.west - this.west <= epsilon &&
261
- this.north - _extent.north <= epsilon &&
262
- _extent.south - this.south <= epsilon;
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
- * @param extent - extent to intersect
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 new Extent(this.crs);
349
+ return target;
318
350
  }
319
351
  if (extent.crs != this.crs) {
320
352
  extent = extent.as(this.crs, _extent);
321
353
  }
322
- return new Extent(this.crs,
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: number = 0): this {
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
- * expandByValuesCoordinates perfoms the minimal extension
449
- * for the coordinates values to belong to this Extent object
450
- * @param we - The coordinate on west-east
451
- * @param sn - The coordinate on south-north
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;
@@ -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
- type LCCProjection = { long0: number, lat0: number };
37
- type TMercProjection = { a: number, b: number, e?: number, long0: number };
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: ProjectionLike,
464
- crsOut: ProjectionLike,
468
+ crsIn: string,
469
+ crsOut: string,
465
470
  ): QuaternionFunction;
466
471
  export function quaternionFromCRSToCRS(
467
- crsIn: ProjectionLike,
468
- crsOut: ProjectionLike,
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: ProjectionLike,
485
- crsOut: ProjectionLike,
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
- return (origin: Coordinates, target = new Quaternion()) =>
498
- toCrs(origin, target).multiply(fromCrs(origin, quat));
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
  }