• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

iTowns / itowns / 12394983982

18 Dec 2024 02:25PM UTC coverage: 87.055% (-0.002%) from 87.057%
12394983982

push

github

Desplandis
feat(wms): use proj4 crs axis param

2782 of 3696 branches covered (75.27%)

Branch coverage included in aggregate %.

51 of 52 new or added lines in 2 files covered. (98.08%)

3 existing lines in 1 file now uncovered.

25013 of 28232 relevant lines covered (88.6%)

991.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.36
/src/Source/WMSSource.js
1
import Source from 'Source/Source';
1✔
2
import URLBuilder from 'Provider/URLBuilder';
1✔
3
import Extent from 'Core/Geographic/Extent';
1✔
4
import * as CRS from 'Core/Geographic/Crs';
1✔
5

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

1✔
8
/**
1✔
9
 * Proj provides an optional param to define axis order and orientation for a
1✔
10
 * given projection. 'enu' for instance stands for east, north, up.
1✔
11
 * Elevation is not needed here. The two first characters are sufficient to map
1✔
12
 * proj axis to iTowns bbox order formalism.
1✔
13
 * 'enu' corresponds to 'wsen' because bbox starts by lower value coordinates
1✔
14
 * and preserves axis ordering, here long/lat.
1✔
15
 */
1✔
16
const projAxisToBboxMappings = {
1✔
17
    en: 'wsen',
1✔
18
    es: 'wnes',
1✔
19
    wn: 'eswn',
1✔
20
    ws: 'enws',
1✔
21
    ne: 'swne',
1✔
22
    se: 'nwse',
1✔
23
    nw: 'senw',
1✔
24
    sw: 'nesw',
1✔
25
};
1✔
26

1✔
27
/**
1✔
28
 * Provides the bbox axis order matching provided proj4 axis
1✔
29
 * @param {string} projAxis the CRS axis order as defined in proj4
1✔
30
 * @returns {string} the corresponding bbox axis order to use for WMS 1.3.0
1✔
31
 */
1✔
32
function projAxisToWmsBbox(projAxis) {
4✔
33
    return projAxis && projAxisToBboxMappings[projAxis.slice(0, 2)] || 'wsen';
4!
34
}
4✔
35

1✔
36
/**
1✔
37
 * An object defining the source of images to get from a
1✔
38
 * [WMS](http://www.opengeospatial.org/standards/wms) server. It inherits
1✔
39
 * from {@link Source}.
1✔
40
 *
1✔
41
 * @extends Source
1✔
42
 *
1✔
43
 * @property {boolean} isWMSSource - Used to checkout whether this source is a
1✔
44
 * WMSSource. Default is true. You should not change this, as it is used
1✔
45
 * internally for optimisation.
1✔
46
 * @property {string} name - The name of the layer, used in the generation of
1✔
47
 * the url.
1✔
48
 * @property {string} version - The version of the WMS server to request on.
1✔
49
 * Default value is '1.3.0'.
1✔
50
 * @property {string} style - The style to query on the WMS server. Default
1✔
51
 * value is 'normal'.
1✔
52
 * @property {number} width - The width of the image to fetch, in pixel.
1✔
53
 * Default value is the height if set or 256.
1✔
54
 * @property {number} height - The height of the image to fetch, in pixel.
1✔
55
 * Default value is the width if set or 256.
1✔
56
 * @property {string} axisOrder - The order of the axis, that helps building the
1✔
57
 * BBOX to put in the url requesting a resource. Default value is 'wsen', other
1✔
58
 * value can be 'swne'.
1✔
59
 * @property {boolean} transparent - Tells if the image to fetch needs
1✔
60
 * transparency support. Default value is false.
1✔
61
 * @property {Object} zoom - Object containing the minimum and maximum values of
1✔
62
 * the level, to zoom in the source.
1✔
63
 * @property {number} zoom.min - The minimum level of the source. Default value
1✔
64
 * is 0.
1✔
65
 * @property {number} zoom.max - The maximum level of the source. Default value
1✔
66
 * is 21.
1✔
67
 * @property {string} bboxDigits - The bbox digits precision used in URL
1✔
68
 * @property {Object} vendorSpecific - An object containing vendor specific
1✔
69
 * parameters. See for example a [list of these parameters for GeoServer](
1✔
70
 * https://docs.geoserver.org/latest/en/user/services/wms/vendor.html). This
1✔
71
 * object is read simply with the `key` being the name of the parameter and
1✔
72
 * `value` being the value of the parameter. If used, this property should be
1✔
73
 * set in the constructor parameters.
1✔
74
 *
1✔
75
 * @example
1✔
76
 * // Create the source
1✔
77
 * const wmsSource = new itowns.WMSSource({
1✔
78
 *     url: 'https://server.geo/wms',
1✔
79
 *     version: '1.3.0',
1✔
80
 *     name: 'REGION.2016',
1✔
81
 *     style: '',
1✔
82
 *     crs: 'EPSG:3857',
1✔
83
 *     extent: {
1✔
84
 *         west: '-6880639.13557728',
1✔
85
 *         east: '6215707.87974825',
1✔
86
 *         south: '-2438399.00148845',
1✔
87
 *         north: '7637050.03850605',
1✔
88
 *     },
1✔
89
 *     transparent: true,
1✔
90
 * });
1✔
91
 *
1✔
92
 * // Create the layer
1✔
93
 * const colorlayer = new itowns.ColorLayer('Region', {
1✔
94
 *     source: wmsSource,
1✔
95
 * });
1✔
96
 *
1✔
97
 * // Add the layer
1✔
98
 * view.addLayer(colorlayer);
1✔
99
 */
1✔
100
class WMSSource extends Source {
1✔
101
    /**
1✔
102
     * @param {Object} source - An object that can contain all properties of
1✔
103
     * WMSSource and {@link Source}. `url`, `name`, `extent` and `crs`
1✔
104
     * are mandatory.
1✔
105
     */
1✔
106
    constructor(source) {
1✔
107
        if (!source.name) {
4!
108
            throw new Error('source.name is required.');
×
109
        }
×
110

4✔
111
        if (!source.extent) {
4!
112
            throw new Error('source.extent is required');
×
113
        }
×
114

4✔
115
        if (!source.crs && !source.projection) {
4!
116
            throw new Error('source.crs is required');
×
117
        }
×
118

4✔
119
        source.format = source.format || 'image/png';
4✔
120

4✔
121
        super(source);
4✔
122

4✔
123
        this.isWMSSource = true;
4✔
124
        this.name = source.name;
4✔
125
        this.zoom = { min: 0, max: Infinity };
4✔
126
        this.style = source.style || '';
4✔
127

4✔
128
        this.width = source.width || source.height || 256;
4✔
129
        this.height = source.height || source.width || 256;
4✔
130
        this.version = source.version || '1.3.0';
4✔
131
        this.transparent = source.transparent || false;
4✔
132
        this.bboxDigits = source.bboxDigits;
4✔
133

4✔
134
        if (source.axisOrder) {
4!
UNCOV
135
            this.axisOrder = source.axisOrder;
×
136
        } else if (this.version === '1.3.0') { // If not set, axis order depends on WMS version
4✔
137
            // Version 1.3.0 depends on CRS axis order as defined in epsg.org database
4✔
138
            this.axisOrder = projAxisToWmsBbox(CRS.axisOrder(this.crs));
4✔
139
        } else {
4!
NEW
140
            // Versions 1.X.X mandate long/lat order, east-north orientation
×
UNCOV
141
            this.axisOrder = 'wsen';
×
UNCOV
142
        }
×
143

4✔
144
        const crsPropName = (this.version === '1.3.0') ? 'CRS' : 'SRS';
4!
145

4✔
146
        const urlObj = new URL(this.url);
4✔
147
        urlObj.searchParams.set('SERVICE', 'WMS');
4✔
148
        urlObj.searchParams.set('REQUEST', 'GetMap');
4✔
149
        urlObj.searchParams.set('LAYERS', this.name);
4✔
150
        urlObj.searchParams.set('VERSION', this.version);
4✔
151
        urlObj.searchParams.set('STYLES', this.style);
4✔
152
        urlObj.searchParams.set('FORMAT', this.format);
4✔
153
        urlObj.searchParams.set('TRANSPARENT', this.transparent);
4✔
154
        urlObj.searchParams.set('BBOX', '%bbox');
4✔
155
        urlObj.searchParams.set(crsPropName, this.crs);
4✔
156
        urlObj.searchParams.set('WIDTH', this.width);
4✔
157
        urlObj.searchParams.set('HEIGHT', this.height);
4✔
158

4✔
159
        this.vendorSpecific = source.vendorSpecific;
4✔
160
        for (const name in this.vendorSpecific) {
4✔
161
            if (Object.prototype.hasOwnProperty.call(this.vendorSpecific, name)) {
3✔
162
                urlObj.searchParams.set(name, this.vendorSpecific[name]);
3✔
163
            }
3✔
164
        }
3✔
165

1✔
166
        this.url = decodeURIComponent(urlObj.toString());
1✔
167
    }
1✔
168

1✔
169
    urlFromExtent(extentOrTile) {
1✔
170
        const extent = extentOrTile.isExtent ?
2✔
171
            extentOrTile.as(this.crs, _extent) :
2!
172
            extentOrTile.toExtent(this.crs, _extent);
2✔
173
        return URLBuilder.bbox(extent, this);
2✔
174
    }
2✔
175

1✔
176
    extentInsideLimit(extent) {
1✔
177
        return this.extent.intersectsExtent(extent);
3✔
178
    }
3✔
179
}
1✔
180

1✔
181
export default WMSSource;
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc