Skip to content

Commit

Permalink
Merge pull request #7510 from openstreetmap/1ec5-custom-wms-template-…
Browse files Browse the repository at this point in the history
…7428

Custom WMS imagery URL templates
  • Loading branch information
quincylvania committed May 18, 2020
2 parents cd9c421 + b5140f2 commit 5071b50
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 44 deletions.
2 changes: 1 addition & 1 deletion data/core.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ en:
custom_background:
tooltip: Edit custom background
header: Custom Background Settings
instructions: "Enter a tile URL template. Valid tokens are:\n {zoom} or {z}, {x}, {y} for Z/X/Y tile scheme\n {-y} or {ty} for flipped TMS-style Y coordinates\n {u} for quadtile scheme\n {switch:a,b,c} for DNS server multiplexing\n\nExample:\n{example}"
instructions: "Enter a tile URL template below.\n\nSupported WMS tokens:\n `{proj}`: requested projection (`EPSG:3857` only)\n `{wkid}`: same as proj, but without the EPSG (`3857` only)\n `{width}`, `{height}`: requested image dimensions (`256` only)\n `{bbox}`: requested bounding box (e.g. `minX,minY,maxX,maxY`)\n\nSupported TMS tokens:\n `{zoom}` or `{z}, `{x}`, `{y}`: Z/X/Y tile coordinates\n `{-y}` or `{ty}`: flipped TMS-style Y coordinates\n `{switch:a,b,c}`: DNS server multiplexing\n `{u}`: quadtile (Bing) scheme\n\nExample:\n{example}"
template:
placeholder: Enter a url template
custom_data:
Expand Down
2 changes: 1 addition & 1 deletion dist/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@
"custom_background": {
"tooltip": "Edit custom background",
"header": "Custom Background Settings",
"instructions": "Enter a tile URL template. Valid tokens are:\n {zoom} or {z}, {x}, {y} for Z/X/Y tile scheme\n {-y} or {ty} for flipped TMS-style Y coordinates\n {u} for quadtile scheme\n {switch:a,b,c} for DNS server multiplexing\n\nExample:\n{example}",
"instructions": "Enter a tile URL template below.\n\nSupported WMS tokens:\n `{proj}`: requested projection (`EPSG:3857` only)\n `{wkid}`: same as proj, but without the EPSG (`3857` only)\n `{width}`, `{height}`: requested image dimensions (`256` only)\n `{bbox}`: requested bounding box (e.g. `minX,minY,maxX,maxY`)\n\nSupported TMS tokens:\n `{zoom}` or `{z}, `{x}`, `{y}`: Z/X/Y tile coordinates\n `{-y}` or `{ty}`: flipped TMS-style Y coordinates\n `{switch:a,b,c}`: DNS server multiplexing\n `{u}`: quadtile (Bing) scheme\n\nExample:\n{example}",
"template": {
"placeholder": "Enter a url template"
}
Expand Down
115 changes: 73 additions & 42 deletions modules/renderer/background_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,44 +29,44 @@ function vintageRange(vintage) {

export function rendererBackgroundSource(data) {
var source = Object.assign({}, data); // shallow copy
var offset = [0, 0];
var name = source.name;
var description = source.description;
var best = !!source.best;
var template = source.encrypted ? utilAesDecrypt(source.template) : source.template;
var _offset = [0, 0];
var _name = source.name;
var _description = source.description;
var _best = !!source.best;
var _template = source.encrypted ? utilAesDecrypt(source.template) : source.template;

source.tileSize = data.tileSize || 256;
source.zoomExtent = data.zoomExtent || [0, 22];
source.overzoom = data.overzoom !== false;

source.offset = function(val) {
if (!arguments.length) return offset;
offset = val;
if (!arguments.length) return _offset;
_offset = val;
return source;
};


source.nudge = function(val, zoomlevel) {
offset[0] += val[0] / Math.pow(2, zoomlevel);
offset[1] += val[1] / Math.pow(2, zoomlevel);
_offset[0] += val[0] / Math.pow(2, zoomlevel);
_offset[1] += val[1] / Math.pow(2, zoomlevel);
return source;
};


source.name = function() {
var id_safe = source.id.replace(/\./g, '<TX_DOT>');
return t('imagery.' + id_safe + '.name', { default: name });
return t('imagery.' + id_safe + '.name', { default: _name });
};


source.description = function() {
var id_safe = source.id.replace(/\./g, '<TX_DOT>');
return t('imagery.' + id_safe + '.description', { default: description });
return t('imagery.' + id_safe + '.description', { default: _description });
};


source.best = function() {
return best;
return _best;
};


Expand All @@ -82,15 +82,35 @@ export function rendererBackgroundSource(data) {
};


source.template = function(_) {
if (!arguments.length) return template;
if (source.id === 'custom') template = _;
source.template = function(val) {
if (!arguments.length) return _template;
if (source.id === 'custom') {
_template = val;
}
return source;
};


source.url = function(coord) {
if (this.type === 'wms') {
var result = _template;
if (result === '') return result; // source 'none'


// Guess a type based on the tokens present in the template
// (This is for 'custom' source, where we don't know)
if (!source.type) {
if (/\{(proj|wkid|bbox)\}/.test(_template)) {
source.type = 'wms';
source.projection = 'EPSG:3857'; // guess
} else if (/\{(x|y)\}/.test(_template)) {
source.type = 'tms';
} else if (/\{u\}/.test(_template)) {
source.type = 'bing';
}
}


if (source.type === 'wms') {
var tileToProjectedCoords = (function(x, y, z) {
//polyfill for IE11, PhantomJS
var sinh = Math.sinh || function(x) {
Expand All @@ -102,7 +122,7 @@ export function rendererBackgroundSource(data) {
var lon = x / zoomSize * Math.PI * 2 - Math.PI;
var lat = Math.atan(sinh(Math.PI * (1 - 2 * y / zoomSize)));

switch (this.projection) {
switch (source.projection) {
case 'EPSG:4326':
return {
x: lon * 180 / Math.PI,
Expand All @@ -115,13 +135,14 @@ export function rendererBackgroundSource(data) {
y: 20037508.34 / Math.PI * mercCoords[1]
};
}
}).bind(this);
});

var tileSize = this.tileSize;
var projection = this.projection;
var tileSize = source.tileSize;
var projection = source.projection;
var minXmaxY = tileToProjectedCoords(coord[0], coord[1], coord[2]);
var maxXminY = tileToProjectedCoords(coord[0]+1, coord[1]+1, coord[2]);
return template.replace(/\{(\w+)\}/g, function (token, key) {

result = result.replace(/\{(\w+)\}/g, function (token, key) {
switch (key) {
case 'width':
case 'height':
Expand All @@ -144,28 +165,38 @@ export function rendererBackgroundSource(data) {
return token;
}
});

} else if (source.type === 'tms') {
result = result
.replace('{x}', coord[0])
.replace('{y}', coord[1])
// TMS-flipped y coordinate
.replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
.replace(/\{z(oom)?\}/, coord[2]);

} else if (source.type === 'bing') {
result = result
.replace('{u}', function() {
var u = '';
for (var zoom = coord[2]; zoom > 0; zoom--) {
var b = 0;
var mask = 1 << (zoom - 1);
if ((coord[0] & mask) !== 0) b++;
if ((coord[1] & mask) !== 0) b += 2;
u += b.toString();
}
return u;
});
}
return template
.replace('{x}', coord[0])
.replace('{y}', coord[1])
// TMS-flipped y coordinate
.replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
.replace(/\{z(oom)?\}/, coord[2])
.replace(/\{switch:([^}]+)\}/, function(s, r) {
var subdomains = r.split(',');
return subdomains[(coord[0] + coord[1]) % subdomains.length];
})
.replace('{u}', function() {
var u = '';
for (var zoom = coord[2]; zoom > 0; zoom--) {
var b = 0;
var mask = 1 << (zoom - 1);
if ((coord[0] & mask) !== 0) b++;
if ((coord[1] & mask) !== 0) b += 2;
u += b.toString();
}
return u;
});

// these apply to any type..
result = result.replace(/\{switch:([^}]+)\}/, function(s, r) {
var subdomains = r.split(',');
return subdomains[(coord[0] + coord[1]) % subdomains.length];
});


return result;
};


Expand Down

0 comments on commit 5071b50

Please sign in to comment.