Skip to content

Commit

Permalink
feat(wms): use proj4 crs axis param
Browse files Browse the repository at this point in the history
  • Loading branch information
airnez authored and Desplandis committed Dec 18, 2024
1 parent aec3ebf commit 7d67ec4
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 6 deletions.
19 changes: 19 additions & 0 deletions src/Core/Geographic/Crs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import type { ProjectionDefinition } from 'proj4';

proj4.defs('EPSG:4978', '+proj=geocent +datum=WGS84 +units=m +no_defs');

// Redefining proj4 global projections to match epsg.org database axis order.
// See https://github.com/iTowns/itowns/pull/2465#issuecomment-2517024859
proj4.defs('EPSG:4326').axis = 'neu';
proj4.defs('EPSG:4269').axis = 'neu';
proj4.defs('WGS84').axis = 'neu';

/**
* A projection as a CRS identifier string. This identifier references a
* projection definition previously defined with
Expand Down Expand Up @@ -139,6 +145,19 @@ export function reasonableEpsilon(crs: ProjectionLike) {
}
}

/**
* Returns the axis parameter defined in proj4 for the provided crs.
* Might be undefined depending on crs definition.
*
* @param crs - The CRS to get axis from.
* @returns the matching proj4 axis string, 'enu' for instance (east, north, up)
*/
export function axisOrder(crs: ProjectionLike) {
mustBeString(crs);
const projection = proj4.defs(crs);
return !projection ? undefined : projection.axis;
}

/**
* Defines a proj4 projection as a named alias.
* This function is a specialized wrapper over the
Expand Down
39 changes: 33 additions & 6 deletions src/Source/WMSSource.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,38 @@
import Source from 'Source/Source';
import URLBuilder from 'Provider/URLBuilder';
import Extent from 'Core/Geographic/Extent';
import * as CRS from 'Core/Geographic/Crs';

const _extent = new Extent('EPSG:4326', [0, 0, 0, 0]);

/**
* Proj provides an optional param to define axis order and orientation for a
* given projection. 'enu' for instance stands for east, north, up.
* Elevation is not needed here. The two first characters are sufficient to map
* proj axis to iTowns bbox order formalism.
* 'enu' corresponds to 'wsen' because bbox starts by lower value coordinates
* and preserves axis ordering, here long/lat.
*/
const projAxisToBboxMappings = {
en: 'wsen',
es: 'wnes',
wn: 'eswn',
ws: 'enws',
ne: 'swne',
se: 'nwse',
nw: 'senw',
sw: 'nesw',
};

/**
* Provides the bbox axis order matching provided proj4 axis
* @param {string} projAxis the CRS axis order as defined in proj4
* @returns {string} the corresponding bbox axis order to use for WMS 1.3.0
*/
function projAxisToWmsBbox(projAxis) {
return projAxis && projAxisToBboxMappings[projAxis.slice(0, 2)] || 'wsen';
}

/**
* An object defining the source of images to get from a
* [WMS](http://www.opengeospatial.org/standards/wms) server. It inherits
Expand Down Expand Up @@ -104,13 +133,11 @@ class WMSSource extends Source {

if (source.axisOrder) {
this.axisOrder = source.axisOrder;
} else if (this.crs == 'EPSG:4326') {
// 4326 (lat/long) axis order depends on the WMS version used
// EPSG 4326 x = lat, long = y
// version 1.X.X long/lat while version 1.3.0 mandates xy (so lat,long)
this.axisOrder = this.version === '1.3.0' ? 'swne' : 'wsen';
} else if (this.version === '1.3.0') { // If not set, axis order depends on WMS version
// Version 1.3.0 depends on CRS axis order as defined in epsg.org database
this.axisOrder = projAxisToWmsBbox(CRS.axisOrder(this.crs));
} else {
// xy,xy order
// Versions 1.X.X mandate long/lat order, east-north orientation
this.axisOrder = 'wsen';
}

Expand Down
6 changes: 6 additions & 0 deletions test/unit/crs.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,10 @@ describe('CRS assertions', function () {
assert.strictEqual(CRS.reasonableEpsilon('EPSG:4326'), 0.01);
assert.strictEqual(CRS.reasonableEpsilon('EPSG:3857'), 0.001);
});

it('should return neu axis order', function () {
assert.equal(CRS.axisOrder('WGS84'), 'neu');
assert.equal(CRS.axisOrder('WGS84'), 'neu');
assert.equal(CRS.axisOrder('EPSG:4269'), 'neu');
});
});

0 comments on commit 7d67ec4

Please sign in to comment.