Skip to content

Commit

Permalink
refacto: migrate Extent to typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
Desplandis committed Nov 27, 2024
1 parent 8e6f479 commit e0066db
Showing 1 changed file with 57 additions and 32 deletions.
89 changes: 57 additions & 32 deletions src/Core/Geographic/Extent.js → src/Core/Geographic/Extent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import * as THREE from 'three';
import * as CRS from './Crs';
import Coordinates from './Coordinates';

import type { ProjectionLike } from './Crs';

/**
* Extent is a SIG-area (so 2D)
* It can use explicit coordinates (e.g: lon/lat) or implicit (WMTS coordinates)
Expand All @@ -19,8 +21,7 @@ const cNorthEast = new Coordinates('EPSG:4326', 0, 0, 0);
const southWest = new THREE.Vector3();
const northEast = new THREE.Vector3();

/** @type {Extent} */
let _extent;
let _extent: Extent;

const cardinals = new Array(8);
for (let i = cardinals.length - 1; i >= 0; i--) {
Expand All @@ -29,7 +30,21 @@ for (let i = cardinals.length - 1; i >= 0; i--) {

const _c = new Coordinates('EPSG:4326', 0, 0);

export interface ExtentLike {
readonly west: number;
readonly east: number;
readonly south: number;
readonly north: number;
}

class Extent {
readonly isExtent: true;
crs: ProjectionLike;
west: number;
east: number;
south: number;
north: number;

/**
* Extent is geographical bounding rectangle defined by 4 limits: west, east, south and north.
*
Expand All @@ -44,9 +59,11 @@ class Extent {
* @param {number} [v2] south value
* @param {number} [v3] north value
*/
constructor(crs, v0 = 0, v1 = 0, v2 = 0, v3 = 0) {
constructor(crs: ProjectionLike, v0 = 0, v1 = 0, v2 = 0, v3 = 0) {
if (CRS.isGeocentric(crs)) {
throw new Error(`${crs} is a geocentric projection, it doesn't make sense with a geographical extent`);
throw new Error(
`Non-compatible geocentric projection ${crs} to build a geographical extent`,
);
}

this.isExtent = true;
Expand Down Expand Up @@ -74,9 +91,8 @@ class Extent {
* @param {Extent} [target] copy the destination to target.
* @return {Extent}
*/
as(crs, target) {
as(crs: string, target: Extent = new Extent('EPSG:4326')) {
CRS.isValid(crs);
target = target || new Extent('EPSG:4326');
if (this.crs != crs) {
// Compute min/max in x/y by projecting 8 cardinal points,
// and then taking the min/max of each coordinates.
Expand Down Expand Up @@ -158,7 +174,10 @@ class Extent {
cNorthEast.setFromValues(this.east, this.north, 0);

// calcul geodetic distance northWest/northEast and northWest/southWest
return target.set(cNorthWest.geodeticDistanceTo(cNorthEast), cNorthWest.geodeticDistanceTo(cSouthWest));
return target.set(
cNorthWest.geodeticDistanceTo(cNorthEast),
cNorthWest.geodeticDistanceTo(cSouthWest),
);
}

/**
Expand All @@ -179,7 +198,10 @@ class Extent {
cNorthEast.setFromValues(this.east, this.north, 0);

// calcul chord distance northWest/northEast and northWest/southWest
return target.set(cNorthWest.spatialEuclideanDistanceTo(cNorthEast), cNorthWest.spatialEuclideanDistanceTo(cSouthWest));
return target.set(
cNorthWest.spatialEuclideanDistanceTo(cNorthEast),
cNorthWest.spatialEuclideanDistanceTo(cSouthWest),
);
}

/**
Expand All @@ -191,7 +213,7 @@ class Extent {
*
* @return {boolean}
*/
isPointInside(coord, epsilon = 0) {
isPointInside(coord: Coordinates, epsilon = 0) {
if (this.crs == coord.crs) {
_c.copy(coord);
} else {
Expand All @@ -214,9 +236,8 @@ class Extent {
*
* @return {boolean}
*/
isInside(extent, epsilon) {
isInside(extent: Extent, epsilon = CRS.reasonableEpsilon(this.crs)) {
extent.as(this.crs, _extent);
epsilon = epsilon ?? CRS.reasonableEpsilon(this.crs);
return this.east - _extent.east <= epsilon &&
_extent.west - this.west <= epsilon &&
this.north - _extent.north <= epsilon &&
Expand All @@ -230,7 +251,7 @@ class Extent {
* @param {THREE.Vector4} target copy the result to target.
* @return {THREE.Vector4} {x: translation on west-east, y: translation on south-north, z: scale on west-east, w: scale on south-north}
*/
offsetToParent(extent, target = new THREE.Vector4()) {
offsetToParent(extent: Extent, target = new THREE.Vector4()) {
if (this.crs != extent.crs) {
throw new Error('unsupported mix');
}
Expand All @@ -252,11 +273,11 @@ class Extent {
* @param {Extent} extent
* @returns {Boolean}
*/
intersectsExtent(extent) {
intersectsExtent(extent: Extent) {
return Extent.intersectsExtent(this, extent);
}

static intersectsExtent(/** @type {Extent} */extentA, /** @type {Extent} */ extentB) {
static intersectsExtent(extentA: Extent, extentB: Extent) {
// TODO don't work when is on limit
const other = extentB.crs == extentA.crs ? extentB : extentB.as(extentA.crs, _extent);
return !(extentA.west >= other.east ||
Expand All @@ -270,7 +291,7 @@ class Extent {
* @param {Extent} extent
* @returns {Extent}
*/
intersect(extent) {
intersect(extent: Extent) {
if (!this.intersectsExtent(extent)) {
return new Extent(this.crs);
}
Expand Down Expand Up @@ -298,22 +319,26 @@ class Extent {
*
* @return {Extent}
*/
set(v0, v1, v2, v3) {
set(v0: number, v1: number, v2: number, v3: number): this {
if (v0 == undefined) {
throw new Error('No values to set in the extent');
}
if (v0.isExtent) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((v0 as any).isExtent) {
console.warn(
'Deprecated Extent#constructor(string, Extent) and Extent#set(Extent),',
'use new Extent(string).setFromExtent(Extent) instead.',
);
this.setFromExtent(v0);
} else if (v0.length == 4) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.setFromExtent(v0 as any);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} else if ((v0 as any).length == 4) { // deepscan-disable-line
console.warn(
'Deprecated Extent#constructor(string, number[]) and Extent#set(number[]),',
'use new Extent(string).setFromArray(number[]) instead.',
);
this.setFromArray(v0);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.setFromArray(v0 as any);
} else if (v3 !== undefined) {
this.west = v0;
this.east = v1;
Expand All @@ -332,7 +357,7 @@ class Extent {
* @param {number} [offset=0] - offset into the array. Default is 0.
* @returns {this}
*/
setFromArray(array, offset = 0) {
setFromArray(array: ArrayLike<number>, offset: number = 0): this {
this.west = array[offset];
this.east = array[offset + 1];
this.south = array[offset + 2];
Expand All @@ -346,7 +371,7 @@ class Extent {
* @param {Object} extent - the source extent
* @returns {this}
*/
setFromExtent(extent) {
setFromExtent(extent: ExtentLike): this {
this.west = extent.west;
this.east = extent.east;
this.south = extent.south;
Expand All @@ -359,7 +384,7 @@ class Extent {
* @param {Extent} extent
* @return {Extent} copied extent
*/
copy(extent) {
copy(extent: Extent): this {
this.crs = extent.crs;
return this.setFromExtent(extent);
}
Expand All @@ -368,7 +393,7 @@ class Extent {
* Union this extent with the input extent.
* @param {Extent} extent the extent to union.
*/
union(extent) {
union(extent: Extent) {
if (extent.crs != this.crs) {
throw new Error('unsupported union between 2 diff crs');
}
Expand Down Expand Up @@ -402,7 +427,7 @@ class Extent {
* for the coordinates to belong to this Extent object
* @param {Coordinates} coordinates The coordinates to belong
*/
expandByCoordinates(coordinates) {
expandByCoordinates(coordinates: Coordinates) {
const coords = coordinates.crs == this.crs ? coordinates : coordinates.as(this.crs, _c);
this.expandByValuesCoordinates(coords.x, coords.y);
}
Expand All @@ -414,7 +439,7 @@ class Extent {
* @param {number} sn The coordinate on south-north
*
*/
expandByValuesCoordinates(we, sn) {
expandByValuesCoordinates(we: number, sn: number) {
if (we < this.west) {
this.west = we;
}
Expand All @@ -440,7 +465,7 @@ class Extent {
* @param {THREE.Box3} box
* @return {Extent}
*/
static fromBox3(crs, box) {
static fromBox3(crs: ProjectionLike, box: THREE.Box3) {
if (CRS.isGeocentric(crs)) {
// if geocentric reproject box on 'EPSG:4326'
crs = 'EPSG:4326';
Expand Down Expand Up @@ -485,7 +510,7 @@ class Extent {
* @param {THREE.Vector2} [scheme=Vector2(2,2)] The scheme to subdivise.
* @return {Array<Extent>} subdivised extents.
*/
subdivisionByScheme(scheme = defaultScheme) {
subdivisionByScheme(scheme = defaultScheme): Extent[] {
const subdivisedExtents = [];
const dimSub = this.planarDimensions(_dim).divide(scheme);
for (let x = scheme.x - 1; x >= 0; x--) {
Expand All @@ -508,7 +533,7 @@ class Extent {
* @param {THREE.Matrix4} matrix The matrix
* @return {Extent} return this extent instance.
*/
applyMatrix4(matrix) {
applyMatrix4(matrix: THREE.Matrix4): this {
southWest.set(this.west, this.south, 0).applyMatrix4(matrix);
northEast.set(this.east, this.north, 0).applyMatrix4(matrix);
this.west = southWest.x;
Expand All @@ -535,7 +560,7 @@ class Extent {
* @param {number} [north=this.north] The max north
* @return {Extent} this extent
*/
clampSouthNorth(south = this.south, north = this.north) {
clampSouthNorth(south = this.south, north = this.north): this {
this.south = Math.max(this.south, south);
this.north = Math.min(this.north, north);
return this;
Expand All @@ -548,7 +573,7 @@ class Extent {
* @param {number} [east=this.east] The max east
* @return {Extent} this extent
*/
clampWestEast(west = this.west, east = this.east) {
clampWestEast(west = this.west, east = this.east): this {
this.west = Math.max(this.west, west);
this.east = Math.min(this.east, east);
return this;
Expand All @@ -559,7 +584,7 @@ class Extent {
* @param {Extent} extent The maximum extent.
* @return {Extent} this extent.
*/
clampByExtent(extent) {
clampByExtent(extent: ExtentLike): this {
this.clampSouthNorth(extent.south, extent.north);
return this.clampWestEast(extent.west, extent.east);
}
Expand Down

0 comments on commit e0066db

Please sign in to comment.