Skip to content

Commit

Permalink
feature(Extent): add methods to calculate extent dimensions.
Browse files Browse the repository at this point in the history
* planarDimensions
* geodesicDimensions
* earthEuclideanDimensions
  • Loading branch information
gchoqueux authored and mgermerie committed Nov 18, 2021
1 parent acdf643 commit ed583d9
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 9 deletions.
69 changes: 64 additions & 5 deletions src/Core/Geographic/Extent.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ const dimensionTile = new THREE.Vector2();
const defaultScheme = new THREE.Vector2(2, 2);
const r = { row: 0, col: 0, invDiff: 0 };

const coord = new Coordinates('EPSG:4326', 0, 0, 0);
const cNorthWest = new Coordinates('EPSG:4326', 0, 0, 0);
const cSouthWest = new Coordinates('EPSG:4326', 0, 0, 0);
const cNorthEast = new Coordinates('EPSG:4326', 0, 0, 0);

const southWest = new THREE.Vector3();
const northEast = new THREE.Vector3();
Expand Down Expand Up @@ -256,11 +258,67 @@ class Extent {
* @return {THREE.Vector2}
*/
dimensions(target = new THREE.Vector2()) {
console.warn('Extent.dimensions is deprecated, use planarDimensions, geodesicDimensions or geodesicChordDimensions');
target.x = Math.abs(this.east - this.west);
target.y = Math.abs(this.north - this.south);
return target;
}

/**
* Planar dimensions are two planar distances west/east and south/north.
* Planar distance straight-line Euclidean distance calculated in a 2D Cartesian coordinate system.
*
* @param {THREE.Vector2} [target=new THREE.Vector2()] The target
* @return {THREE.Vector2} Planar dimensions
*/
planarDimensions(target = new THREE.Vector2()) {
// Calculte the dimensions for x and y
return target.set(Math.abs(this.east - this.west), Math.abs(this.north - this.south));
}

/**
* Geodesic dimensions are two planar distances west/east and south/north.
* Geodesic distance is calculated in an ellispoid space as the distance
* across the curved surface of the world.
*
* @param {THREE.Vector2} [target=new THREE.Vector2()] The target
* @return {THREE.Vector2} Planar dimensions
*/
geodesicDimensions(target = new THREE.Vector2()) {
// set 3 corners extent
cNorthWest.crs = this.crs;
cSouthWest.crs = this.crs;
cNorthEast.crs = this.crs;

cNorthWest.setFromValues(this.west, this.north, 0);
cSouthWest.setFromValues(this.west, this.south, 0);
cNorthEast.setFromValues(this.east, this.north, 0);

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

/**
* Earth euclidean dimensions are two earth euclidean distances between west/east and south/north.
* Earth euclidean distance chord is calculated in a ellispoid space.
*
* @param {THREE.Vector2} [target=new THREE.Vector2()] The target
* @return {THREE.Vector2} Earth euclidean dimensions
*/
earthEuclideanDimensions(target = new THREE.Vector2()) {
// set 3 corners extent
cNorthWest.crs = this.crs;
cSouthWest.crs = this.crs;
cNorthEast.crs = this.crs;

cNorthWest.setFromValues(this.west, this.north, 0);
cSouthWest.setFromValues(this.west, this.south, 0);
cNorthEast.setFromValues(this.east, this.north, 0);

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

/**
* Return true if `coord` is inside the bounding box.
*
Expand Down Expand Up @@ -546,10 +604,11 @@ class Extent {
// if geocentric reproject box on 'EPSG:4326'
crs = 'EPSG:4326';
box = _box.copy(box);
coord.crs = crs;
coord.setFromVector3(box.min).as(crs, coord).toVector3(box.min);
coord.crs = crs;
coord.setFromVector3(box.max).as(crs, coord).toVector3(box.max);

cSouthWest.crs = crs;
cSouthWest.setFromVector3(box.min).as(crs, cSouthWest).toVector3(box.min);
cNorthEast.crs = crs;
cNorthEast.setFromVector3(box.max).as(crs, cNorthEast).toVector3(box.max);
}

return new Extent(crs, {
Expand Down
37 changes: 33 additions & 4 deletions test/unit/extent.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import assert from 'assert';
import { Box3, Vector3, Matrix4, Quaternion } from 'three';
import { Box3, Vector3, Vector2, Matrix4, Quaternion } from 'three';
import Coordinates from 'Core/Geographic/Coordinates';
import Extent from 'Core/Geographic/Extent';
import CRS from 'Core/Geographic/Crs';
import proj4 from 'proj4';

proj4.defs('EPSG:2154', '+proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs');

describe('Extent', function () {
const minX = 0;
Expand Down Expand Up @@ -95,16 +98,42 @@ describe('Extent', function () {
assert.strictEqual(subdivided[3].north, 0);
});

it('should return the correct dimension of the extent', function () {
it('should return the correct planar dimensions', function () {
const extent = new Extent('EPSG:4326', -15, 10, -10, 10);
const dimensions = extent.dimensions();
const dimensions = extent.planarDimensions();

// Width
assert.equal(dimensions.x, 25);
// Height
assert.equal(dimensions.y, 20);
});

it('should return the same planar dimensions with deprecated dimensions method', function () {
const extent = new Extent('EPSG:4326', -15, 10, -10, 10);
const dimensions = extent.planarDimensions();
const dimensions_2 = extent.dimensions();
assert.equal(dimensions.x, dimensions_2.x);
assert.equal(dimensions.y, dimensions_2.y);
});

it('should return the correct earth euclidean dimensions', function () {
const extent = new Extent('EPSG:4326', 3, 3.01, 46, 46.01);
const dimensions = new Vector2();

extent.earthEuclideanDimensions(dimensions);
assert.equal(dimensions.x, 774.4934293643765);
assert.equal(dimensions.y, 1111.5141604285038);
});

it('should return the correct geodesic dimensions', function () {
const extent = new Extent('EPSG:4326', 3, 3.01, 46, 46.01);
const dimensions = new Vector2();

extent.geodesicDimensions(dimensions);
assert.equal(dimensions.x, 773.2375602074535);
assert.equal(dimensions.y, 1113.3197697640906);
});

it('should clone extent like expected', function () {
const withValues = new Extent('EPSG:4326', [minX, maxX, minY, maxY]);
const clonedExtent = withValues.clone();
Expand Down Expand Up @@ -168,7 +197,7 @@ describe('Extent', function () {
});
it('should return dimensions of extent expected', function () {
const withValues = new Extent('EPSG:4326', [minX, maxX, minY, maxY]);
const dimensions = withValues.dimensions();
const dimensions = withValues.planarDimensions();
assert.equal(10, dimensions.x);
assert.equal(4, dimensions.y);
});
Expand Down

0 comments on commit ed583d9

Please sign in to comment.