Skip to content

Commit 7d67ec4

Browse files
airnezDesplandis
authored andcommitted
feat(wms): use proj4 crs axis param
1 parent aec3ebf commit 7d67ec4

File tree

3 files changed

+58
-6
lines changed

3 files changed

+58
-6
lines changed

src/Core/Geographic/Crs.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ import type { ProjectionDefinition } from 'proj4';
44

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

7+
// Redefining proj4 global projections to match epsg.org database axis order.
8+
// See https://github.com/iTowns/itowns/pull/2465#issuecomment-2517024859
9+
proj4.defs('EPSG:4326').axis = 'neu';
10+
proj4.defs('EPSG:4269').axis = 'neu';
11+
proj4.defs('WGS84').axis = 'neu';
12+
713
/**
814
* A projection as a CRS identifier string. This identifier references a
915
* projection definition previously defined with
@@ -139,6 +145,19 @@ export function reasonableEpsilon(crs: ProjectionLike) {
139145
}
140146
}
141147

148+
/**
149+
* Returns the axis parameter defined in proj4 for the provided crs.
150+
* Might be undefined depending on crs definition.
151+
*
152+
* @param crs - The CRS to get axis from.
153+
* @returns the matching proj4 axis string, 'enu' for instance (east, north, up)
154+
*/
155+
export function axisOrder(crs: ProjectionLike) {
156+
mustBeString(crs);
157+
const projection = proj4.defs(crs);
158+
return !projection ? undefined : projection.axis;
159+
}
160+
142161
/**
143162
* Defines a proj4 projection as a named alias.
144163
* This function is a specialized wrapper over the

src/Source/WMSSource.js

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,38 @@
11
import Source from 'Source/Source';
22
import URLBuilder from 'Provider/URLBuilder';
33
import Extent from 'Core/Geographic/Extent';
4+
import * as CRS from 'Core/Geographic/Crs';
45

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

8+
/**
9+
* Proj provides an optional param to define axis order and orientation for a
10+
* given projection. 'enu' for instance stands for east, north, up.
11+
* Elevation is not needed here. The two first characters are sufficient to map
12+
* proj axis to iTowns bbox order formalism.
13+
* 'enu' corresponds to 'wsen' because bbox starts by lower value coordinates
14+
* and preserves axis ordering, here long/lat.
15+
*/
16+
const projAxisToBboxMappings = {
17+
en: 'wsen',
18+
es: 'wnes',
19+
wn: 'eswn',
20+
ws: 'enws',
21+
ne: 'swne',
22+
se: 'nwse',
23+
nw: 'senw',
24+
sw: 'nesw',
25+
};
26+
27+
/**
28+
* Provides the bbox axis order matching provided proj4 axis
29+
* @param {string} projAxis the CRS axis order as defined in proj4
30+
* @returns {string} the corresponding bbox axis order to use for WMS 1.3.0
31+
*/
32+
function projAxisToWmsBbox(projAxis) {
33+
return projAxis && projAxisToBboxMappings[projAxis.slice(0, 2)] || 'wsen';
34+
}
35+
736
/**
837
* An object defining the source of images to get from a
938
* [WMS](http://www.opengeospatial.org/standards/wms) server. It inherits
@@ -104,13 +133,11 @@ class WMSSource extends Source {
104133

105134
if (source.axisOrder) {
106135
this.axisOrder = source.axisOrder;
107-
} else if (this.crs == 'EPSG:4326') {
108-
// 4326 (lat/long) axis order depends on the WMS version used
109-
// EPSG 4326 x = lat, long = y
110-
// version 1.X.X long/lat while version 1.3.0 mandates xy (so lat,long)
111-
this.axisOrder = this.version === '1.3.0' ? 'swne' : 'wsen';
136+
} else if (this.version === '1.3.0') { // If not set, axis order depends on WMS version
137+
// Version 1.3.0 depends on CRS axis order as defined in epsg.org database
138+
this.axisOrder = projAxisToWmsBbox(CRS.axisOrder(this.crs));
112139
} else {
113-
// xy,xy order
140+
// Versions 1.X.X mandate long/lat order, east-north orientation
114141
this.axisOrder = 'wsen';
115142
}
116143

test/unit/crs.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,10 @@ describe('CRS assertions', function () {
5353
assert.strictEqual(CRS.reasonableEpsilon('EPSG:4326'), 0.01);
5454
assert.strictEqual(CRS.reasonableEpsilon('EPSG:3857'), 0.001);
5555
});
56+
57+
it('should return neu axis order', function () {
58+
assert.equal(CRS.axisOrder('WGS84'), 'neu');
59+
assert.equal(CRS.axisOrder('WGS84'), 'neu');
60+
assert.equal(CRS.axisOrder('EPSG:4269'), 'neu');
61+
});
5662
});

0 commit comments

Comments
 (0)