-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.ts
135 lines (125 loc) · 4.48 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { bboxToMeters, googleToBBox, googleToQuadkey, googleToTile } from "global-mercator";
export type Tile = [number, number, number];
/**
* Substitutes the given tile information [x, y, z] to the URL tile scheme.
*
* @name slippyTile
* @param {Tile} tile Tile [x, y, z]
* @param {string} url URL Tile scheme or provider unique key
* @param {Object} [options] Additional options
* @param {string} [options.layer] Layer
* @param {string} [options.version] Version
* @param {string} [format="image/png"] Image Format
* @returns {string} parsed URL
* @example
* slippyTile([10, 15, 8], "https://{s}.tile.openstreetmap.org/{zoom}/{x}/{y}.png")
* //="https://c.tile.openstreetmap.org/8/10/15.png"
*/
function slippyTile(tile: Tile, url: string, options: {
layer?: string,
version?: string,
format?: string,
[key: string]: any,
} = {}) {
const format = options.format || "image/png";
const x = tile[0];
const y = tile[1];
const zoom = tile[2];
url = wms(tile, url);
url = wmts(url);
url = parseSwitch(url);
url = url.replace(/{(zoom|z|level)}/gi, String(zoom));
url = url.replace(/{(x|col)}/gi, String(x));
url = url.replace(/{(y|row)}/gi, String(y));
url = url.replace(/{format}/gi, format);
// Replace all additional options
Object.keys(options).forEach((key) => {
const pattern = RegExp("{" + key + "}", "ig");
if (url.match(pattern)) {
if (options[key] === undefined) { throw new Error("options." + key + " is required"); }
url = url.replace(pattern, options[key]);
}
});
if (url.match(/{-y}/)) { url = url.replace(/{-y}/gi, String(googleToTile(tile)[1])); }
if (url.match(/{(quadkey|q)}/)) { url = url.replace(/{(quadkey|q)}/gi, googleToQuadkey(tile)); }
return url;
}
/**
* Parse WMS URL to friendly SlippyTile format
*
* @private
* @param {Tile} tile Tile [x, y, z]
* @param {string} url WMTS URL scheme
* @returns {string} parsed URL
* @example
* wms([10, 15, 8], "/?layers=imagery&SRS={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}")
* // => "/?layers=imagery&SRS=EPSG:3857&WIDTH=256&HEIGHT=256&BBOX=-165.9375,82.676285,-164.53125,82.853382"
*/
function wms(tile: Tile, url: string) {
url = url.replace(/{height}/gi, "256");
url = url.replace(/{width}/gi, "256");
url = url.replace(/{size}/gi, "256,256");
url = url.replace(/{(proj|srs|crs)}/gi, "EPSG:3857");
const bbox = googleToBBox(tile);
const bboxMeters = bboxToMeters(bbox);
if (url.match(/EPSG:(3857|900913)/i) && url.match(/{bbox}/i)) { url = url.replace(/{bbox}/gi, bboxMeters.join(",")); }
url = url.replace(/{bbox4326}/gi, bbox.join(","));
url = url.replace(/{bbox3857}/gi, bboxMeters.join(","));
url = url.replace(/{bbox}/gi, bbox.join(","));
return url;
}
/**
* Parse WMTS URL to friendly SlippyTile URL format
*
* @private
* @param {string} url WMTS URL scheme
* @returns {string} parsed URL
* @example
* wmts("https://<Tile Server>/WMTS/tile/1.0.0/Imagery/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.jpg")
* //="https://<Tile Server>/WMTS/tile/1.0.0/Imagery/default/GoogleMapsCompatible/{z}/{y}/{x}.jpg"
*/
function wmts(url: string) {
if (url.match(/{TileCol|TileRow|TileMatrix|TileMatrixSet|Style}/gi)) {
url = url.replace(/{TileCol}/gi, "{x}");
url = url.replace(/{TileRow}/gi, "{y}");
url = url.replace(/{TileMatrix}/gi, "{z}");
url = url.replace(/{TileMatrixSet}/gi, "GoogleMapsCompatible");
url = url.replace(/{Style}/gi, "default");
}
return url;
}
/**
* Replaces {switch:a,b,c} with a random sample.
*
* @private
* @param {string} url - URL Scheme
* @returns {string} Parsed URL with switch replaced
* @example
* parseSwitch("http://tile-{switch:a,b,c}.openstreetmap.fr/hot/{zoom}/{x}/{y}.png")
* //="http://tile-b.openstreetmap.fr/hot/{zoom}/{x}/{y}.png"
*/
function parseSwitch(url: string) {
// Default simple switch
if (url.match(/{s}/gi)) { return url.replace(/{s}/gi, String(sample(["a", "b", "c"]))); }
// Custom switch
const pattern = /{switch:([a-z,\d]*)}/i;
const found = url.match(pattern);
if (found) { return url.replace(pattern, String(sample(found[1].split(",")))); }
return url;
}
/**
* Sample an item from a given list
*
* @private
* @name sample
* @param {Array} array List of items
* @returns {*} Single item from the list
* @example
* sample(["a", "b", "c"])
* //="b"
*/
function sample(array: any[]) {
if (array === null || array === undefined || array.length === 0) { return undefined; }
return array[Math.floor(Math.random() * array.length)];
}
export default slippyTile;