Skip to content

Commit fcf9540

Browse files
committed
Merge pull request openlayers#1060 from georchestra/wmts/createlayer-improvements
WMTS createLayer method improved
2 parents a1953ab + 237b2ce commit fcf9540

File tree

2 files changed

+112
-34
lines changed

2 files changed

+112
-34
lines changed

lib/OpenLayers/Format/WMTSCapabilities.js

Lines changed: 83 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ OpenLayers.Format.WMTSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.Vers
7272
* Optional config properties:
7373
* matrixSet - {String} The matrix set identifier, required if there is
7474
* more than one matrix set in the layer capabilities.
75+
* projection - {String} The desired CRS when no matrixSet is specified.
76+
* eg: "EPSG:3857". If the desired projection is not available,
77+
* an error is thrown.
7578
* style - {String} The name of the style
7679
* format - {String} Image format for the layer. Default is the first
7780
* format returned in the GetCapabilities response.
@@ -114,6 +117,19 @@ OpenLayers.Format.WMTSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.Vers
114117
var matrixSet;
115118
if (config.matrixSet) {
116119
matrixSet = contents.tileMatrixSets[config.matrixSet];
120+
} else if (config.projection) {
121+
for (var i=0,l=layerDef.tileMatrixSetLinks.length;i<l;i++) {
122+
if (contents.tileMatrixSets[
123+
layerDef.tileMatrixSetLinks[i].tileMatrixSet
124+
].supportedCRS.replace(
125+
/urn:ogc:def:crs:(\w+):(.*:)?(\w+)$/, "$1:$3"
126+
) === config.projection) {
127+
128+
matrixSet = contents.tileMatrixSets[
129+
layerDef.tileMatrixSetLinks[i].tileMatrixSet];
130+
break;
131+
}
132+
}
117133
} else if (layerDef.tileMatrixSetLinks.length >= 1) {
118134
matrixSet = contents.tileMatrixSets[
119135
layerDef.tileMatrixSetLinks[0].tileMatrixSet];
@@ -140,7 +156,6 @@ OpenLayers.Format.WMTSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.Vers
140156
if (http.get[0].constraints) {
141157
var constraints = http.get[0].constraints;
142158
var allowedValues = constraints.GetEncoding.allowedValues;
143-
144159
// The OGC documentation is not clear if we should use
145160
// REST or RESTful, ArcGis use RESTful,
146161
// and OpenLayers use REST.
@@ -167,15 +182,47 @@ OpenLayers.Format.WMTSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.Vers
167182
var projection = config.projection || matrixSet.supportedCRS.replace(
168183
/urn:ogc:def:crs:(\w+):(.*:)?(\w+)$/, "$1:$3");
169184
var units = config.units ||
170-
(projection === "EPSG:4326" ? "degrees" : "m");
171-
172-
var resolutions = [];
173-
for (var mid in matrixSet.matrixIds) {
174-
if (matrixSet.matrixIds.hasOwnProperty(mid)) {
175-
resolutions.push(
176-
matrixSet.matrixIds[mid].scaleDenominator * 0.28E-3 /
177-
OpenLayers.METERS_PER_INCH /
178-
OpenLayers.INCHES_PER_UNIT[units]);
185+
(projection === ("EPSG:4326" || "OGC:CRS84") ? "degrees" : "m");
186+
187+
// compute server-supported resolutions array
188+
var resolutions = [], minScaleDenominator, maxScaleDenominator,
189+
reducedMatrixIds = [], tileMatrixSetLink,
190+
tileMatrixSetLinks = layerDef.tileMatrixSetLinks;
191+
var buildResolutionsArray = function(scaleDenominator) {
192+
resolutions.push(
193+
scaleDenominator * 0.28E-3 / OpenLayers.METERS_PER_INCH /
194+
OpenLayers.INCHES_PER_UNIT[units]
195+
);
196+
if (!minScaleDenominator || minScaleDenominator > scaleDenominator) {
197+
minScaleDenominator = scaleDenominator;
198+
}
199+
if (!maxScaleDenominator || maxScaleDenominator < scaleDenominator) {
200+
maxScaleDenominator = scaleDenominator;
201+
}
202+
};
203+
for (var j=0, l=tileMatrixSetLinks.length; j<l; j++) {
204+
tileMatrixSetLink = tileMatrixSetLinks[j];
205+
if (tileMatrixSetLink.tileMatrixSet === matrixSet.identifier) {
206+
if (tileMatrixSetLink.tileMatrixSetLimits) {
207+
// reformat matrixSet.matrixIds so that identifiers become keys
208+
var tmpMatrixIds = {}, mid;
209+
for (var k=0, ll=matrixSet.matrixIds.length; k<ll; k++) {
210+
tmpMatrixIds[matrixSet.matrixIds[k].identifier] = matrixSet.matrixIds[k];
211+
}
212+
// compute resolutions array + scale limits
213+
for (var k=0, ll=tileMatrixSetLink.tileMatrixSetLimits.length; k<ll; k++) {
214+
mid = tmpMatrixIds[tileMatrixSetLink.tileMatrixSetLimits[k].tileMatrix];
215+
reducedMatrixIds.push(mid);
216+
buildResolutionsArray(mid.scaleDenominator);
217+
}
218+
} else {
219+
// if there are no limits in the tileMatrixSetLink,
220+
// use the resolutions from the full tile matrix set
221+
for (var k=0, ll=matrixSet.matrixIds.length; k<ll; k++) {
222+
buildResolutionsArray(matrixSet.matrixIds[k].scaleDenominator);
223+
};
224+
}
225+
break;
179226
}
180227
}
181228

@@ -190,8 +237,7 @@ OpenLayers.Format.WMTSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.Vers
190237
url.push(resourceUrl.template);
191238
}
192239
}
193-
}
194-
else {
240+
} else {
195241
var httpGet = capabilities.operationsMetadata.GetTile.dcp.http.get;
196242
url = [];
197243
var constraint;
@@ -203,28 +249,32 @@ OpenLayers.Format.WMTSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.Vers
203249
}
204250
}
205251
}
206-
207-
return new OpenLayers.Layer.WMTS(
208-
OpenLayers.Util.applyDefaults(config, {
209-
url: url,
210-
requestEncoding: requestEncoding,
211-
name: layerDef.title,
212-
style: style.identifier,
213-
format: format,
214-
matrixIds: matrixSet.matrixIds,
215-
matrixSet: matrixSet.identifier,
216-
projection: projection,
217-
units: units,
218-
resolutions: config.isBaseLayer === false ? undefined :
219-
resolutions,
220-
serverResolutions: resolutions,
221-
tileFullExtent: matrixSet.bounds,
222-
dimensions: dimensions,
223-
params: params
224-
})
225-
);
252+
253+
resolutions.sort(function(a,b){
254+
return b-a;
255+
});
256+
var options = OpenLayers.Util.applyDefaults(config, {
257+
url: url,
258+
requestEncoding: requestEncoding,
259+
name: layerDef.title,
260+
style: style && style.identifier || "",
261+
format: format,
262+
matrixIds: reducedMatrixIds.length ?
263+
reducedMatrixIds : matrixSet.matrixIds,
264+
matrixSet: matrixSet.identifier,
265+
projection: projection,
266+
units: units,
267+
tileFullExtent: matrixSet.bounds,
268+
dimensions: dimensions,
269+
params: params,
270+
resolutions: config.isBaseLayer === false ? undefined :
271+
resolutions,
272+
serverResolutions: resolutions,
273+
minScale: 1/Math.ceil(maxScaleDenominator),
274+
maxScale: 1/Math.floor(minScaleDenominator)
275+
});
276+
return new OpenLayers.Layer.WMTS(options);
226277
},
227278

228279
CLASS_NAME: "OpenLayers.Format.WMTSCapabilities"
229-
230280
});

tests/Format/WMTSCapabilities/v1_0_0.html

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@
197197
}
198198

199199
function test_createLayer(t) {
200-
t.plan(43);
200+
t.plan(48);
201201

202202
var format = new OpenLayers.Format.WMTSCapabilities();
203203

@@ -239,12 +239,29 @@
239239
}
240240
t.ok(!success, "createLayer returns undefined given bad matrixSet identifier");
241241

242+
// bogus projection
243+
try {
244+
layer = format.createLayer(caps, {
245+
layer: "coastlines",
246+
projection: "EPSG:3857"
247+
});
248+
} catch (err) {
249+
success = false;
250+
}
251+
t.ok(!success, "createLayer returns undefined given unsupported projection");
252+
242253
layer = format.createLayer(caps, {
243254
layer: "coastlines",
244255
matrixSet: "BigWorld"
245256
});
246257
t.ok(layer instanceof OpenLayers.Layer.WMTS, "correct instance");
247258

259+
layer = format.createLayer(caps, {
260+
layer: "coastlines",
261+
projection: "OGC:CRS84"
262+
});
263+
t.ok(layer instanceof OpenLayers.Layer.WMTS, "correct instance with CRS84 tile matrix set");
264+
248265
// autodetect matrixSet
249266
layer = format.createLayer(caps, {
250267
layer: "coastlines"
@@ -364,6 +381,17 @@
364381
layer: "WorldTimeZones"
365382
});
366383
t.eq(layer.requestEncoding, "REST", "correct requestEncoding (in RESTfull)");
384+
385+
// test serverresolutions and min/maxScaleDenominator
386+
xml = document.getElementById("French-IGN-GeoPortal").firstChild.nodeValue;
387+
doc = new OpenLayers.Format.XML().read(xml);
388+
caps = format.read(doc);
389+
layer = format.createLayer(caps, {
390+
layer: "ADMINISTRATIVEUNITS.BOUNDARIES"
391+
});
392+
t.eq(layer.serverResolutions.length, 13, "correct number of server resolutions");
393+
t.eq(layer.maxScale, 1/2132, "correct maxScale");
394+
t.eq(layer.minScale, 1/8735661, "correct minScale");
367395
}
368396

369397
function test_parse_projection(t) {

0 commit comments

Comments
 (0)