@india-boundary-corrector/leaflet-layer 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -0
- package/dist/index.cjs +3065 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.global.js +3091 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +3044 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
- package/src/index.d.ts +50 -0
- package/src/index.js +134 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,3065 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.js
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
LayerConfig: () => LayerConfig,
|
|
24
|
+
extendLeaflet: () => extendLeaflet,
|
|
25
|
+
getPmtilesUrl: () => import_data2.getPmtilesUrl,
|
|
26
|
+
layerConfigs: () => layerConfigs
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
var import_data = require("@india-boundary-corrector/data");
|
|
30
|
+
|
|
31
|
+
// ../layer-configs/dist/index.js
|
|
32
|
+
var configs_default = [
|
|
33
|
+
{
|
|
34
|
+
id: "cartodb-dark",
|
|
35
|
+
zoomThreshold: 5,
|
|
36
|
+
tileUrlTemplates: [
|
|
37
|
+
"https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",
|
|
38
|
+
"https://basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",
|
|
39
|
+
"https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}{r}.png",
|
|
40
|
+
"https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png",
|
|
41
|
+
"https://basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png",
|
|
42
|
+
"https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_nolabels/{z}/{x}/{y}{r}.png"
|
|
43
|
+
],
|
|
44
|
+
lineWidthStops: { "1": 0.5, "10": 2.5 },
|
|
45
|
+
lineStyles: [
|
|
46
|
+
{ color: "rgb(40, 40, 40)" }
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "cartodb-light",
|
|
51
|
+
startZoom: 0,
|
|
52
|
+
zoomThreshold: 5,
|
|
53
|
+
tileUrlTemplates: [
|
|
54
|
+
"https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
|
|
55
|
+
"https://basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
|
|
56
|
+
"https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}{r}.png",
|
|
57
|
+
"https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png",
|
|
58
|
+
"https://basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png",
|
|
59
|
+
"https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_nolabels/{z}/{x}/{y}{r}.png",
|
|
60
|
+
"https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png",
|
|
61
|
+
"https://basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png",
|
|
62
|
+
"https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}{r}.png",
|
|
63
|
+
"https://basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}{r}.png",
|
|
64
|
+
"https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png",
|
|
65
|
+
"https://basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png"
|
|
66
|
+
],
|
|
67
|
+
lineWidthStops: { "1": 0.25, "2": 0.25, "3": 0.5, "4": 0.75, "5": 1 },
|
|
68
|
+
lineStyles: [
|
|
69
|
+
{ color: "rgb(235, 214, 214)", alpha: 0.2, startZoom: 6, widthFraction: 5 },
|
|
70
|
+
{ color: "rgb(235, 214, 214)" }
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: "open-topo",
|
|
75
|
+
startZoom: 4,
|
|
76
|
+
zoomThreshold: 4,
|
|
77
|
+
tileUrlTemplates: [
|
|
78
|
+
"https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",
|
|
79
|
+
"https://tile.opentopomap.org/{z}/{x}/{y}.png"
|
|
80
|
+
],
|
|
81
|
+
lineWidthStops: { "4": 0.75, "5": 1, "6": 1.25, "7": 1.5, "8": 1.75, "9": 1.25, "10": 1.25, "13": 1.5 },
|
|
82
|
+
lineStyles: [
|
|
83
|
+
{ color: "rgb(83, 83, 83)", startZoom: 7, endZoom: 8, alpha: 0.4, widthFraction: 4 },
|
|
84
|
+
{ color: "rgb(83, 83, 83)", endZoom: 8 },
|
|
85
|
+
{ color: "rgb(140, 20, 180)", startZoom: 9, widthFraction: 9, alpha: 0.2 },
|
|
86
|
+
{ color: "rgb(140, 20, 180)", startZoom: 9 }
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: "osm-carto",
|
|
91
|
+
startZoom: 1,
|
|
92
|
+
zoomThreshold: 1,
|
|
93
|
+
tileUrlTemplates: [
|
|
94
|
+
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
|
95
|
+
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
|
96
|
+
],
|
|
97
|
+
lineWidthStops: { "1": 0.5, "2": 0.6, "3": 0.7, "4": 1, "10": 3.75 },
|
|
98
|
+
lineStyles: [
|
|
99
|
+
{ color: "rgb(200, 180, 200)" },
|
|
100
|
+
{ color: "rgb(160, 120, 160)", widthFraction: 0.333, dashArray: [30, 2, 8, 2] }
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
id: "osm-hot",
|
|
105
|
+
startZoom: 2,
|
|
106
|
+
zoomThreshold: 2,
|
|
107
|
+
tileUrlTemplates: [
|
|
108
|
+
"https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png"
|
|
109
|
+
],
|
|
110
|
+
lineWidthStops: { "2": 3, "3": 3, "7": 3, "8": 3.5, "9": 3.5 },
|
|
111
|
+
lineStyles: [
|
|
112
|
+
{ color: "rgb(149, 175, 180)" },
|
|
113
|
+
{ color: "rgb(89, 117, 123)", widthFraction: 0.33 }
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
];
|
|
117
|
+
function templateToRegex(template) {
|
|
118
|
+
const groups = [];
|
|
119
|
+
let pattern = template.replace(/[.*+?^${}()|[\]\\]/g, (char) => {
|
|
120
|
+
if (char === "{" || char === "}") return char;
|
|
121
|
+
return "\\" + char;
|
|
122
|
+
}).replace(/^https:\/\//, "https?://").replace(/^http:\/\//, "https?://").replace(/\{[a-z0-9]-[a-z0-9]\}/gi, () => {
|
|
123
|
+
groups.push("s");
|
|
124
|
+
return "([a-z0-9]+)";
|
|
125
|
+
}).replace(/\{(z|x|y|s|r)\}/gi, (_2, name) => {
|
|
126
|
+
const lowerName = name.toLowerCase();
|
|
127
|
+
groups.push(lowerName);
|
|
128
|
+
if (lowerName === "s") {
|
|
129
|
+
return "([a-z0-9]+)";
|
|
130
|
+
}
|
|
131
|
+
if (lowerName === "r") {
|
|
132
|
+
return "(@\\d+x)?";
|
|
133
|
+
}
|
|
134
|
+
return "(\\d+)";
|
|
135
|
+
});
|
|
136
|
+
return { pattern: new RegExp("^" + pattern + "(\\?.*)?$", "i"), groups };
|
|
137
|
+
}
|
|
138
|
+
function templateToTemplateRegex(template) {
|
|
139
|
+
let pattern = template.replace(/[.*+?^${}()|[\]\\]/g, (char) => {
|
|
140
|
+
if (char === "{" || char === "}") return char;
|
|
141
|
+
return "\\" + char;
|
|
142
|
+
}).replace(/^https:\/\//, "https?://").replace(/^http:\/\//, "https?://").replace(/\{([a-z0-9])-([a-z0-9])\}/gi, (_2, start, end) => `(\\{${start}-${end}\\}|[a-z0-9]+)`).replace(/\{(z|x|y|s|r)\}/gi, (_2, name) => {
|
|
143
|
+
const lowerName = name.toLowerCase();
|
|
144
|
+
if (lowerName === "s") {
|
|
145
|
+
return "(\\{s\\}|[a-z0-9]+)";
|
|
146
|
+
}
|
|
147
|
+
if (lowerName === "r") {
|
|
148
|
+
return "(\\{r\\}|@\\d+x)?";
|
|
149
|
+
}
|
|
150
|
+
return `\\{${lowerName}\\}`;
|
|
151
|
+
});
|
|
152
|
+
return new RegExp("^" + pattern + "(\\?.*)?$", "i");
|
|
153
|
+
}
|
|
154
|
+
var LayerConfig = class _LayerConfig {
|
|
155
|
+
constructor({
|
|
156
|
+
id,
|
|
157
|
+
startZoom = 0,
|
|
158
|
+
zoomThreshold = 5,
|
|
159
|
+
// Tile URL templates for matching (e.g., "https://{s}.tile.example.com/{z}/{x}/{y}.png")
|
|
160
|
+
tileUrlTemplates = [],
|
|
161
|
+
// Line width stops: map of zoom level to line width (at least 2 entries)
|
|
162
|
+
lineWidthStops = { 1: 0.5, 10: 2.5 },
|
|
163
|
+
// Line styles array - each element describes a line to draw
|
|
164
|
+
// { color: string, widthFraction?: number, dashArray?: number[], startZoom?: number, endZoom?: number }
|
|
165
|
+
// Lines are drawn in array order. startZoom defaults to layerConfig startZoom, endZoom defaults to Infinity
|
|
166
|
+
lineStyles = [{ color: "green", widthFraction: 1 }],
|
|
167
|
+
// Factor to multiply line width for deletion blur (default 1.5)
|
|
168
|
+
// Higher values leave gaps where wiped lines meet existing lines
|
|
169
|
+
// Lower values mean wiped lines show through
|
|
170
|
+
delWidthFactor = 1.5,
|
|
171
|
+
// Factor to extend add lines by (multiplied by deletion line width)
|
|
172
|
+
// Helps cover gaps where deleted lines meet the new boundary
|
|
173
|
+
// Set to 0 to disable extension
|
|
174
|
+
lineExtensionFactor = 0.5
|
|
175
|
+
}) {
|
|
176
|
+
if (!id || typeof id !== "string") {
|
|
177
|
+
throw new Error("LayerConfig requires a non-empty string id");
|
|
178
|
+
}
|
|
179
|
+
this.id = id;
|
|
180
|
+
this.startZoom = startZoom;
|
|
181
|
+
this.zoomThreshold = zoomThreshold;
|
|
182
|
+
if (startZoom > zoomThreshold) {
|
|
183
|
+
throw new Error(`LayerConfig "${id}": startZoom (${startZoom}) must be <= zoomThreshold (${zoomThreshold})`);
|
|
184
|
+
}
|
|
185
|
+
const templates = Array.isArray(tileUrlTemplates) ? tileUrlTemplates : tileUrlTemplates ? [tileUrlTemplates] : [];
|
|
186
|
+
this.tileUrlTemplates = templates;
|
|
187
|
+
this._compiledPatterns = templates.map((t) => templateToRegex(t));
|
|
188
|
+
this._templatePatterns = templates.map((t) => templateToTemplateRegex(t));
|
|
189
|
+
if (!lineWidthStops || typeof lineWidthStops !== "object" || Array.isArray(lineWidthStops)) {
|
|
190
|
+
throw new Error(`LayerConfig "${id}": lineWidthStops must be an object`);
|
|
191
|
+
}
|
|
192
|
+
const stopKeys = Object.keys(lineWidthStops);
|
|
193
|
+
if (stopKeys.length < 2) {
|
|
194
|
+
throw new Error(`LayerConfig "${id}": lineWidthStops must have at least 2 entries`);
|
|
195
|
+
}
|
|
196
|
+
for (const key of stopKeys) {
|
|
197
|
+
const zoom = Number(key);
|
|
198
|
+
if (!Number.isInteger(zoom) || zoom < 0) {
|
|
199
|
+
throw new Error(`LayerConfig "${id}": lineWidthStops keys must be non-negative integers, got "${key}"`);
|
|
200
|
+
}
|
|
201
|
+
if (typeof lineWidthStops[key] !== "number" || lineWidthStops[key] <= 0) {
|
|
202
|
+
throw new Error(`LayerConfig "${id}": lineWidthStops values must be positive numbers`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
this.lineWidthStops = lineWidthStops;
|
|
206
|
+
if (!Array.isArray(lineStyles) || lineStyles.length === 0) {
|
|
207
|
+
throw new Error(`LayerConfig "${id}": lineStyles must be a non-empty array`);
|
|
208
|
+
}
|
|
209
|
+
for (let i2 = 0; i2 < lineStyles.length; i2++) {
|
|
210
|
+
const style = lineStyles[i2];
|
|
211
|
+
if (!style || typeof style !== "object") {
|
|
212
|
+
throw new Error(`LayerConfig "${id}": lineStyles[${i2}] must be an object`);
|
|
213
|
+
}
|
|
214
|
+
if (!style.color || typeof style.color !== "string") {
|
|
215
|
+
throw new Error(`LayerConfig "${id}": lineStyles[${i2}].color must be a non-empty string`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
this.lineStyles = lineStyles.map((style) => ({
|
|
219
|
+
...style,
|
|
220
|
+
startZoom: style.startZoom ?? startZoom,
|
|
221
|
+
endZoom: style.endZoom ?? Infinity
|
|
222
|
+
}));
|
|
223
|
+
this.delWidthFactor = delWidthFactor;
|
|
224
|
+
this.lineExtensionFactor = lineExtensionFactor;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Get line styles active at a given zoom level
|
|
228
|
+
* @param {number} z - Zoom level
|
|
229
|
+
* @returns {Array<{color: string, widthFraction?: number, dashArray?: number[]}>}
|
|
230
|
+
*/
|
|
231
|
+
getLineStylesForZoom(z2) {
|
|
232
|
+
return this.lineStyles.filter((style) => z2 >= style.startZoom && z2 <= style.endZoom);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Check if this config matches the given template URLs (with {z}/{x}/{y} placeholders)
|
|
236
|
+
* @param {string | string[]} templates - Single template URL or array of template URLs
|
|
237
|
+
* @returns {boolean}
|
|
238
|
+
*/
|
|
239
|
+
matchTemplate(templates) {
|
|
240
|
+
if (this._templatePatterns.length === 0) return false;
|
|
241
|
+
const urls = Array.isArray(templates) ? templates : [templates];
|
|
242
|
+
if (urls.length === 0) return false;
|
|
243
|
+
return urls.some(
|
|
244
|
+
(url) => this._templatePatterns.some((pattern) => pattern.test(url))
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Check if this config matches the given tile URLs (with actual coordinates)
|
|
249
|
+
* @param {string | string[]} tiles - Single tile URL or array of tile URLs
|
|
250
|
+
* @returns {boolean}
|
|
251
|
+
*/
|
|
252
|
+
matchTileUrl(tiles) {
|
|
253
|
+
if (this._compiledPatterns.length === 0) return false;
|
|
254
|
+
const urls = Array.isArray(tiles) ? tiles : [tiles];
|
|
255
|
+
if (urls.length === 0) return false;
|
|
256
|
+
return urls.some(
|
|
257
|
+
(url) => this._compiledPatterns.some(({ pattern }) => pattern.test(url))
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Extract tile coordinates (z, x, y) from a URL using this config's templates
|
|
262
|
+
* @param {string} url - Tile URL to extract coordinates from
|
|
263
|
+
* @returns {{ z: number, x: number, y: number } | null}
|
|
264
|
+
*/
|
|
265
|
+
extractCoords(url) {
|
|
266
|
+
for (const { pattern, groups } of this._compiledPatterns) {
|
|
267
|
+
const match = url.match(pattern);
|
|
268
|
+
if (match) {
|
|
269
|
+
const result = {};
|
|
270
|
+
for (let i2 = 0; i2 < groups.length; i2++) {
|
|
271
|
+
const name = groups[i2];
|
|
272
|
+
const value = match[i2 + 1];
|
|
273
|
+
if (name === "z" || name === "x" || name === "y") {
|
|
274
|
+
result[name] = parseInt(value, 10);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if ("z" in result && "x" in result && "y" in result) {
|
|
278
|
+
return { z: result.z, x: result.x, y: result.y };
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Serialize the config to a plain object for postMessage
|
|
286
|
+
* @returns {Object}
|
|
287
|
+
*/
|
|
288
|
+
toJSON() {
|
|
289
|
+
return {
|
|
290
|
+
id: this.id,
|
|
291
|
+
startZoom: this.startZoom,
|
|
292
|
+
zoomThreshold: this.zoomThreshold,
|
|
293
|
+
tileUrlTemplates: this.tileUrlTemplates,
|
|
294
|
+
lineWidthStops: this.lineWidthStops,
|
|
295
|
+
lineStyles: this.lineStyles,
|
|
296
|
+
delWidthFactor: this.delWidthFactor,
|
|
297
|
+
lineExtensionFactor: this.lineExtensionFactor
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Create a LayerConfig from a plain object (e.g., from postMessage)
|
|
302
|
+
* @param {Object} obj
|
|
303
|
+
* @returns {LayerConfig}
|
|
304
|
+
*/
|
|
305
|
+
static fromJSON(obj) {
|
|
306
|
+
return new _LayerConfig(obj);
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
var LayerConfigRegistry = class _LayerConfigRegistry {
|
|
310
|
+
constructor() {
|
|
311
|
+
this.registry = {};
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Get a layer config by id
|
|
315
|
+
*/
|
|
316
|
+
get(id) {
|
|
317
|
+
return this.registry[id];
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Register a new layer config
|
|
321
|
+
*/
|
|
322
|
+
register(config) {
|
|
323
|
+
this.registry[config.id] = config;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Remove a layer config by id
|
|
327
|
+
*/
|
|
328
|
+
remove(id) {
|
|
329
|
+
if (!this.registry[id]) return false;
|
|
330
|
+
delete this.registry[id];
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Detect layer config from tile URL templates (with {z}/{x}/{y} placeholders)
|
|
335
|
+
* @param {string | string[]} templates - Single template URL or array of template URLs
|
|
336
|
+
*/
|
|
337
|
+
detectFromTemplates(templates) {
|
|
338
|
+
if (!templates || Array.isArray(templates) && templates.length === 0) return void 0;
|
|
339
|
+
for (const config of Object.values(this.registry)) {
|
|
340
|
+
if (config.matchTemplate(templates)) {
|
|
341
|
+
return config;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return void 0;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Detect layer config from actual tile URLs (with numeric coordinates)
|
|
348
|
+
* @param {string | string[]} urls - Single tile URL or array of tile URLs
|
|
349
|
+
*/
|
|
350
|
+
detectFromTileUrls(urls) {
|
|
351
|
+
if (!urls || Array.isArray(urls) && urls.length === 0) return void 0;
|
|
352
|
+
for (const config of Object.values(this.registry)) {
|
|
353
|
+
if (config.matchTileUrl(urls)) {
|
|
354
|
+
return config;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return void 0;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Get all available layer config ids
|
|
361
|
+
*/
|
|
362
|
+
getAvailableIds() {
|
|
363
|
+
return Object.keys(this.registry);
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Create a new registry with all configs from this registry plus extra configs.
|
|
367
|
+
* @param {LayerConfig[]} extraLayerConfigs - Additional configs to add
|
|
368
|
+
* @returns {LayerConfigRegistry} A new registry with merged configs
|
|
369
|
+
*/
|
|
370
|
+
createMergedRegistry(extraLayerConfigs) {
|
|
371
|
+
const registry = new _LayerConfigRegistry();
|
|
372
|
+
for (const id of this.getAvailableIds()) {
|
|
373
|
+
registry.register(this.get(id));
|
|
374
|
+
}
|
|
375
|
+
if (extraLayerConfigs && extraLayerConfigs.length > 0) {
|
|
376
|
+
for (const config of extraLayerConfigs) {
|
|
377
|
+
registry.register(config);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return registry;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Parse a tile URL into its components: layer config and coordinates
|
|
384
|
+
* @param {string} url - Tile URL to parse
|
|
385
|
+
* @returns {{ layerConfig: LayerConfig, coords: { z: number, x: number, y: number } } | null}
|
|
386
|
+
*/
|
|
387
|
+
parseTileUrl(url) {
|
|
388
|
+
const layerConfig = this.detectFromTileUrls([url]);
|
|
389
|
+
if (!layerConfig) return null;
|
|
390
|
+
const coords = layerConfig.extractCoords(url);
|
|
391
|
+
if (!coords) return null;
|
|
392
|
+
return { layerConfig, coords };
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
var layerConfigs = new LayerConfigRegistry();
|
|
396
|
+
for (const configData of configs_default) {
|
|
397
|
+
layerConfigs.register(new LayerConfig(configData));
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// ../tilefixer/dist/index.js
|
|
401
|
+
var u8 = Uint8Array;
|
|
402
|
+
var u16 = Uint16Array;
|
|
403
|
+
var i32 = Int32Array;
|
|
404
|
+
var fleb = new u8([
|
|
405
|
+
0,
|
|
406
|
+
0,
|
|
407
|
+
0,
|
|
408
|
+
0,
|
|
409
|
+
0,
|
|
410
|
+
0,
|
|
411
|
+
0,
|
|
412
|
+
0,
|
|
413
|
+
1,
|
|
414
|
+
1,
|
|
415
|
+
1,
|
|
416
|
+
1,
|
|
417
|
+
2,
|
|
418
|
+
2,
|
|
419
|
+
2,
|
|
420
|
+
2,
|
|
421
|
+
3,
|
|
422
|
+
3,
|
|
423
|
+
3,
|
|
424
|
+
3,
|
|
425
|
+
4,
|
|
426
|
+
4,
|
|
427
|
+
4,
|
|
428
|
+
4,
|
|
429
|
+
5,
|
|
430
|
+
5,
|
|
431
|
+
5,
|
|
432
|
+
5,
|
|
433
|
+
0,
|
|
434
|
+
/* unused */
|
|
435
|
+
0,
|
|
436
|
+
0,
|
|
437
|
+
/* impossible */
|
|
438
|
+
0
|
|
439
|
+
]);
|
|
440
|
+
var fdeb = new u8([
|
|
441
|
+
0,
|
|
442
|
+
0,
|
|
443
|
+
0,
|
|
444
|
+
0,
|
|
445
|
+
1,
|
|
446
|
+
1,
|
|
447
|
+
2,
|
|
448
|
+
2,
|
|
449
|
+
3,
|
|
450
|
+
3,
|
|
451
|
+
4,
|
|
452
|
+
4,
|
|
453
|
+
5,
|
|
454
|
+
5,
|
|
455
|
+
6,
|
|
456
|
+
6,
|
|
457
|
+
7,
|
|
458
|
+
7,
|
|
459
|
+
8,
|
|
460
|
+
8,
|
|
461
|
+
9,
|
|
462
|
+
9,
|
|
463
|
+
10,
|
|
464
|
+
10,
|
|
465
|
+
11,
|
|
466
|
+
11,
|
|
467
|
+
12,
|
|
468
|
+
12,
|
|
469
|
+
13,
|
|
470
|
+
13,
|
|
471
|
+
/* unused */
|
|
472
|
+
0,
|
|
473
|
+
0
|
|
474
|
+
]);
|
|
475
|
+
var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
|
|
476
|
+
var freb = function(eb, start) {
|
|
477
|
+
var b2 = new u16(31);
|
|
478
|
+
for (var i2 = 0; i2 < 31; ++i2) {
|
|
479
|
+
b2[i2] = start += 1 << eb[i2 - 1];
|
|
480
|
+
}
|
|
481
|
+
var r = new i32(b2[30]);
|
|
482
|
+
for (var i2 = 1; i2 < 30; ++i2) {
|
|
483
|
+
for (var j2 = b2[i2]; j2 < b2[i2 + 1]; ++j2) {
|
|
484
|
+
r[j2] = j2 - b2[i2] << 5 | i2;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return { b: b2, r };
|
|
488
|
+
};
|
|
489
|
+
var _a = freb(fleb, 2);
|
|
490
|
+
var fl = _a.b;
|
|
491
|
+
var revfl = _a.r;
|
|
492
|
+
fl[28] = 258, revfl[258] = 28;
|
|
493
|
+
var _b = freb(fdeb, 0);
|
|
494
|
+
var fd = _b.b;
|
|
495
|
+
var revfd = _b.r;
|
|
496
|
+
var rev = new u16(32768);
|
|
497
|
+
for (i = 0; i < 32768; ++i) {
|
|
498
|
+
x2 = (i & 43690) >> 1 | (i & 21845) << 1;
|
|
499
|
+
x2 = (x2 & 52428) >> 2 | (x2 & 13107) << 2;
|
|
500
|
+
x2 = (x2 & 61680) >> 4 | (x2 & 3855) << 4;
|
|
501
|
+
rev[i] = ((x2 & 65280) >> 8 | (x2 & 255) << 8) >> 1;
|
|
502
|
+
}
|
|
503
|
+
var x2;
|
|
504
|
+
var i;
|
|
505
|
+
var hMap = (function(cd, mb, r) {
|
|
506
|
+
var s = cd.length;
|
|
507
|
+
var i2 = 0;
|
|
508
|
+
var l2 = new u16(mb);
|
|
509
|
+
for (; i2 < s; ++i2) {
|
|
510
|
+
if (cd[i2])
|
|
511
|
+
++l2[cd[i2] - 1];
|
|
512
|
+
}
|
|
513
|
+
var le = new u16(mb);
|
|
514
|
+
for (i2 = 1; i2 < mb; ++i2) {
|
|
515
|
+
le[i2] = le[i2 - 1] + l2[i2 - 1] << 1;
|
|
516
|
+
}
|
|
517
|
+
var co;
|
|
518
|
+
if (r) {
|
|
519
|
+
co = new u16(1 << mb);
|
|
520
|
+
var rvb = 15 - mb;
|
|
521
|
+
for (i2 = 0; i2 < s; ++i2) {
|
|
522
|
+
if (cd[i2]) {
|
|
523
|
+
var sv = i2 << 4 | cd[i2];
|
|
524
|
+
var r_1 = mb - cd[i2];
|
|
525
|
+
var v2 = le[cd[i2] - 1]++ << r_1;
|
|
526
|
+
for (var m2 = v2 | (1 << r_1) - 1; v2 <= m2; ++v2) {
|
|
527
|
+
co[rev[v2] >> rvb] = sv;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
} else {
|
|
532
|
+
co = new u16(s);
|
|
533
|
+
for (i2 = 0; i2 < s; ++i2) {
|
|
534
|
+
if (cd[i2]) {
|
|
535
|
+
co[i2] = rev[le[cd[i2] - 1]++] >> 15 - cd[i2];
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return co;
|
|
540
|
+
});
|
|
541
|
+
var flt = new u8(288);
|
|
542
|
+
for (i = 0; i < 144; ++i)
|
|
543
|
+
flt[i] = 8;
|
|
544
|
+
var i;
|
|
545
|
+
for (i = 144; i < 256; ++i)
|
|
546
|
+
flt[i] = 9;
|
|
547
|
+
var i;
|
|
548
|
+
for (i = 256; i < 280; ++i)
|
|
549
|
+
flt[i] = 7;
|
|
550
|
+
var i;
|
|
551
|
+
for (i = 280; i < 288; ++i)
|
|
552
|
+
flt[i] = 8;
|
|
553
|
+
var i;
|
|
554
|
+
var fdt = new u8(32);
|
|
555
|
+
for (i = 0; i < 32; ++i)
|
|
556
|
+
fdt[i] = 5;
|
|
557
|
+
var i;
|
|
558
|
+
var flrm = /* @__PURE__ */ hMap(flt, 9, 1);
|
|
559
|
+
var fdrm = /* @__PURE__ */ hMap(fdt, 5, 1);
|
|
560
|
+
var max = function(a) {
|
|
561
|
+
var m2 = a[0];
|
|
562
|
+
for (var i2 = 1; i2 < a.length; ++i2) {
|
|
563
|
+
if (a[i2] > m2)
|
|
564
|
+
m2 = a[i2];
|
|
565
|
+
}
|
|
566
|
+
return m2;
|
|
567
|
+
};
|
|
568
|
+
var bits = function(d, p, m2) {
|
|
569
|
+
var o = p / 8 | 0;
|
|
570
|
+
return (d[o] | d[o + 1] << 8) >> (p & 7) & m2;
|
|
571
|
+
};
|
|
572
|
+
var bits16 = function(d, p) {
|
|
573
|
+
var o = p / 8 | 0;
|
|
574
|
+
return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);
|
|
575
|
+
};
|
|
576
|
+
var shft = function(p) {
|
|
577
|
+
return (p + 7) / 8 | 0;
|
|
578
|
+
};
|
|
579
|
+
var slc = function(v2, s, e) {
|
|
580
|
+
if (s == null || s < 0)
|
|
581
|
+
s = 0;
|
|
582
|
+
if (e == null || e > v2.length)
|
|
583
|
+
e = v2.length;
|
|
584
|
+
return new u8(v2.subarray(s, e));
|
|
585
|
+
};
|
|
586
|
+
var ec = [
|
|
587
|
+
"unexpected EOF",
|
|
588
|
+
"invalid block type",
|
|
589
|
+
"invalid length/literal",
|
|
590
|
+
"invalid distance",
|
|
591
|
+
"stream finished",
|
|
592
|
+
"no stream handler",
|
|
593
|
+
,
|
|
594
|
+
"no callback",
|
|
595
|
+
"invalid UTF-8 data",
|
|
596
|
+
"extra field too long",
|
|
597
|
+
"date not in range 1980-2099",
|
|
598
|
+
"filename too long",
|
|
599
|
+
"stream finishing",
|
|
600
|
+
"invalid zip data"
|
|
601
|
+
// determined by unknown compression method
|
|
602
|
+
];
|
|
603
|
+
var err = function(ind, msg, nt) {
|
|
604
|
+
var e = new Error(msg || ec[ind]);
|
|
605
|
+
e.code = ind;
|
|
606
|
+
if (Error.captureStackTrace)
|
|
607
|
+
Error.captureStackTrace(e, err);
|
|
608
|
+
if (!nt)
|
|
609
|
+
throw e;
|
|
610
|
+
return e;
|
|
611
|
+
};
|
|
612
|
+
var inflt = function(dat, st, buf, dict) {
|
|
613
|
+
var sl = dat.length, dl = dict ? dict.length : 0;
|
|
614
|
+
if (!sl || st.f && !st.l)
|
|
615
|
+
return buf || new u8(0);
|
|
616
|
+
var noBuf = !buf;
|
|
617
|
+
var resize = noBuf || st.i != 2;
|
|
618
|
+
var noSt = st.i;
|
|
619
|
+
if (noBuf)
|
|
620
|
+
buf = new u8(sl * 3);
|
|
621
|
+
var cbuf = function(l3) {
|
|
622
|
+
var bl = buf.length;
|
|
623
|
+
if (l3 > bl) {
|
|
624
|
+
var nbuf = new u8(Math.max(bl * 2, l3));
|
|
625
|
+
nbuf.set(buf);
|
|
626
|
+
buf = nbuf;
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
var final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;
|
|
630
|
+
var tbts = sl * 8;
|
|
631
|
+
do {
|
|
632
|
+
if (!lm) {
|
|
633
|
+
final = bits(dat, pos, 1);
|
|
634
|
+
var type = bits(dat, pos + 1, 3);
|
|
635
|
+
pos += 3;
|
|
636
|
+
if (!type) {
|
|
637
|
+
var s = shft(pos) + 4, l2 = dat[s - 4] | dat[s - 3] << 8, t = s + l2;
|
|
638
|
+
if (t > sl) {
|
|
639
|
+
if (noSt)
|
|
640
|
+
err(0);
|
|
641
|
+
break;
|
|
642
|
+
}
|
|
643
|
+
if (resize)
|
|
644
|
+
cbuf(bt + l2);
|
|
645
|
+
buf.set(dat.subarray(s, t), bt);
|
|
646
|
+
st.b = bt += l2, st.p = pos = t * 8, st.f = final;
|
|
647
|
+
continue;
|
|
648
|
+
} else if (type == 1)
|
|
649
|
+
lm = flrm, dm = fdrm, lbt = 9, dbt = 5;
|
|
650
|
+
else if (type == 2) {
|
|
651
|
+
var hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;
|
|
652
|
+
var tl = hLit + bits(dat, pos + 5, 31) + 1;
|
|
653
|
+
pos += 14;
|
|
654
|
+
var ldt = new u8(tl);
|
|
655
|
+
var clt = new u8(19);
|
|
656
|
+
for (var i2 = 0; i2 < hcLen; ++i2) {
|
|
657
|
+
clt[clim[i2]] = bits(dat, pos + i2 * 3, 7);
|
|
658
|
+
}
|
|
659
|
+
pos += hcLen * 3;
|
|
660
|
+
var clb = max(clt), clbmsk = (1 << clb) - 1;
|
|
661
|
+
var clm = hMap(clt, clb, 1);
|
|
662
|
+
for (var i2 = 0; i2 < tl; ) {
|
|
663
|
+
var r = clm[bits(dat, pos, clbmsk)];
|
|
664
|
+
pos += r & 15;
|
|
665
|
+
var s = r >> 4;
|
|
666
|
+
if (s < 16) {
|
|
667
|
+
ldt[i2++] = s;
|
|
668
|
+
} else {
|
|
669
|
+
var c = 0, n = 0;
|
|
670
|
+
if (s == 16)
|
|
671
|
+
n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i2 - 1];
|
|
672
|
+
else if (s == 17)
|
|
673
|
+
n = 3 + bits(dat, pos, 7), pos += 3;
|
|
674
|
+
else if (s == 18)
|
|
675
|
+
n = 11 + bits(dat, pos, 127), pos += 7;
|
|
676
|
+
while (n--)
|
|
677
|
+
ldt[i2++] = c;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
|
|
681
|
+
lbt = max(lt);
|
|
682
|
+
dbt = max(dt);
|
|
683
|
+
lm = hMap(lt, lbt, 1);
|
|
684
|
+
dm = hMap(dt, dbt, 1);
|
|
685
|
+
} else
|
|
686
|
+
err(1);
|
|
687
|
+
if (pos > tbts) {
|
|
688
|
+
if (noSt)
|
|
689
|
+
err(0);
|
|
690
|
+
break;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
if (resize)
|
|
694
|
+
cbuf(bt + 131072);
|
|
695
|
+
var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;
|
|
696
|
+
var lpos = pos;
|
|
697
|
+
for (; ; lpos = pos) {
|
|
698
|
+
var c = lm[bits16(dat, pos) & lms], sym = c >> 4;
|
|
699
|
+
pos += c & 15;
|
|
700
|
+
if (pos > tbts) {
|
|
701
|
+
if (noSt)
|
|
702
|
+
err(0);
|
|
703
|
+
break;
|
|
704
|
+
}
|
|
705
|
+
if (!c)
|
|
706
|
+
err(2);
|
|
707
|
+
if (sym < 256)
|
|
708
|
+
buf[bt++] = sym;
|
|
709
|
+
else if (sym == 256) {
|
|
710
|
+
lpos = pos, lm = null;
|
|
711
|
+
break;
|
|
712
|
+
} else {
|
|
713
|
+
var add = sym - 254;
|
|
714
|
+
if (sym > 264) {
|
|
715
|
+
var i2 = sym - 257, b2 = fleb[i2];
|
|
716
|
+
add = bits(dat, pos, (1 << b2) - 1) + fl[i2];
|
|
717
|
+
pos += b2;
|
|
718
|
+
}
|
|
719
|
+
var d = dm[bits16(dat, pos) & dms], dsym = d >> 4;
|
|
720
|
+
if (!d)
|
|
721
|
+
err(3);
|
|
722
|
+
pos += d & 15;
|
|
723
|
+
var dt = fd[dsym];
|
|
724
|
+
if (dsym > 3) {
|
|
725
|
+
var b2 = fdeb[dsym];
|
|
726
|
+
dt += bits16(dat, pos) & (1 << b2) - 1, pos += b2;
|
|
727
|
+
}
|
|
728
|
+
if (pos > tbts) {
|
|
729
|
+
if (noSt)
|
|
730
|
+
err(0);
|
|
731
|
+
break;
|
|
732
|
+
}
|
|
733
|
+
if (resize)
|
|
734
|
+
cbuf(bt + 131072);
|
|
735
|
+
var end = bt + add;
|
|
736
|
+
if (bt < dt) {
|
|
737
|
+
var shift = dl - dt, dend = Math.min(dt, end);
|
|
738
|
+
if (shift + bt < 0)
|
|
739
|
+
err(3);
|
|
740
|
+
for (; bt < dend; ++bt)
|
|
741
|
+
buf[bt] = dict[shift + bt];
|
|
742
|
+
}
|
|
743
|
+
for (; bt < end; ++bt)
|
|
744
|
+
buf[bt] = buf[bt - dt];
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
st.l = lm, st.p = lpos, st.b = bt, st.f = final;
|
|
748
|
+
if (lm)
|
|
749
|
+
final = 1, st.m = lbt, st.d = dm, st.n = dbt;
|
|
750
|
+
} while (!final);
|
|
751
|
+
return bt != buf.length && noBuf ? slc(buf, 0, bt) : buf.subarray(0, bt);
|
|
752
|
+
};
|
|
753
|
+
var et = /* @__PURE__ */ new u8(0);
|
|
754
|
+
var gzs = function(d) {
|
|
755
|
+
if (d[0] != 31 || d[1] != 139 || d[2] != 8)
|
|
756
|
+
err(6, "invalid gzip data");
|
|
757
|
+
var flg = d[3];
|
|
758
|
+
var st = 10;
|
|
759
|
+
if (flg & 4)
|
|
760
|
+
st += (d[10] | d[11] << 8) + 2;
|
|
761
|
+
for (var zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= !d[st++])
|
|
762
|
+
;
|
|
763
|
+
return st + (flg & 2);
|
|
764
|
+
};
|
|
765
|
+
var gzl = function(d) {
|
|
766
|
+
var l2 = d.length;
|
|
767
|
+
return (d[l2 - 4] | d[l2 - 3] << 8 | d[l2 - 2] << 16 | d[l2 - 1] << 24) >>> 0;
|
|
768
|
+
};
|
|
769
|
+
var zls = function(d, dict) {
|
|
770
|
+
if ((d[0] & 15) != 8 || d[0] >> 4 > 7 || (d[0] << 8 | d[1]) % 31)
|
|
771
|
+
err(6, "invalid zlib data");
|
|
772
|
+
if ((d[1] >> 5 & 1) == +!dict)
|
|
773
|
+
err(6, "invalid zlib data: " + (d[1] & 32 ? "need" : "unexpected") + " dictionary");
|
|
774
|
+
return (d[1] >> 3 & 4) + 2;
|
|
775
|
+
};
|
|
776
|
+
function inflateSync(data, opts) {
|
|
777
|
+
return inflt(data, { i: 2 }, opts && opts.out, opts && opts.dictionary);
|
|
778
|
+
}
|
|
779
|
+
function gunzipSync(data, opts) {
|
|
780
|
+
var st = gzs(data);
|
|
781
|
+
if (st + 8 > data.length)
|
|
782
|
+
err(6, "invalid gzip data");
|
|
783
|
+
return inflt(data.subarray(st, -8), { i: 2 }, opts && opts.out || new u8(gzl(data)), opts && opts.dictionary);
|
|
784
|
+
}
|
|
785
|
+
function unzlibSync(data, opts) {
|
|
786
|
+
return inflt(data.subarray(zls(data, opts && opts.dictionary), -4), { i: 2 }, opts && opts.out, opts && opts.dictionary);
|
|
787
|
+
}
|
|
788
|
+
function decompressSync(data, opts) {
|
|
789
|
+
return data[0] == 31 && data[1] == 139 && data[2] == 8 ? gunzipSync(data, opts) : (data[0] & 15) != 8 || data[0] >> 4 > 7 || (data[0] << 8 | data[1]) % 31 ? inflateSync(data, opts) : unzlibSync(data, opts);
|
|
790
|
+
}
|
|
791
|
+
var td = typeof TextDecoder != "undefined" && /* @__PURE__ */ new TextDecoder();
|
|
792
|
+
var tds = 0;
|
|
793
|
+
try {
|
|
794
|
+
td.decode(et, { stream: true });
|
|
795
|
+
tds = 1;
|
|
796
|
+
} catch (e) {
|
|
797
|
+
}
|
|
798
|
+
var z = Object.defineProperty;
|
|
799
|
+
var b = Math.pow;
|
|
800
|
+
var l = (i2, e) => z(i2, "name", { value: e, configurable: true });
|
|
801
|
+
var m = (i2, e, t) => new Promise((r, n) => {
|
|
802
|
+
var s = (u) => {
|
|
803
|
+
try {
|
|
804
|
+
a(t.next(u));
|
|
805
|
+
} catch (c) {
|
|
806
|
+
n(c);
|
|
807
|
+
}
|
|
808
|
+
}, o = (u) => {
|
|
809
|
+
try {
|
|
810
|
+
a(t.throw(u));
|
|
811
|
+
} catch (c) {
|
|
812
|
+
n(c);
|
|
813
|
+
}
|
|
814
|
+
}, a = (u) => u.done ? r(u.value) : Promise.resolve(u.value).then(s, o);
|
|
815
|
+
a((t = t.apply(i2, e)).next());
|
|
816
|
+
});
|
|
817
|
+
var re = l((i2, e) => {
|
|
818
|
+
let t = false, r = "", n = L.GridLayer.extend({ createTile: l((s, o) => {
|
|
819
|
+
let a = document.createElement("img"), u = new AbortController(), c = u.signal;
|
|
820
|
+
return a.cancel = () => {
|
|
821
|
+
u.abort();
|
|
822
|
+
}, t || (i2.getHeader().then((d) => {
|
|
823
|
+
d.tileType === 1 ? console.error("Error: archive contains MVT vector tiles, but leafletRasterLayer is for displaying raster tiles. See https://github.com/protomaps/PMTiles/tree/main/js for details.") : d.tileType === 2 ? r = "image/png" : d.tileType === 3 ? r = "image/jpeg" : d.tileType === 4 ? r = "image/webp" : d.tileType === 5 && (r = "image/avif");
|
|
824
|
+
}), t = true), i2.getZxy(s.z, s.x, s.y, c).then((d) => {
|
|
825
|
+
if (d) {
|
|
826
|
+
let h = new Blob([d.data], { type: r }), p = window.URL.createObjectURL(h);
|
|
827
|
+
a.src = p, a.cancel = void 0, o(void 0, a);
|
|
828
|
+
}
|
|
829
|
+
}).catch((d) => {
|
|
830
|
+
if (d.name !== "AbortError") throw d;
|
|
831
|
+
}), a;
|
|
832
|
+
}, "createTile"), _removeTile: l(function(s) {
|
|
833
|
+
let o = this._tiles[s];
|
|
834
|
+
o && (o.el.cancel && o.el.cancel(), o.el.width = 0, o.el.height = 0, o.el.deleted = true, L.DomUtil.remove(o.el), delete this._tiles[s], this.fire("tileunload", { tile: o.el, coords: this._keyToTileCoords(s) }));
|
|
835
|
+
}, "_removeTile") });
|
|
836
|
+
return new n(e);
|
|
837
|
+
}, "leafletRasterLayer");
|
|
838
|
+
var j = l((i2) => (e, t) => {
|
|
839
|
+
if (t instanceof AbortController) return i2(e, t);
|
|
840
|
+
let r = new AbortController();
|
|
841
|
+
return i2(e, r).then((n) => t(void 0, n.data, n.cacheControl || "", n.expires || ""), (n) => t(n)).catch((n) => t(n)), { cancel: l(() => r.abort(), "cancel") };
|
|
842
|
+
}, "v3compat");
|
|
843
|
+
var T = class T2 {
|
|
844
|
+
constructor(e) {
|
|
845
|
+
this.tilev4 = l((e2, t) => m(this, null, function* () {
|
|
846
|
+
if (e2.type === "json") {
|
|
847
|
+
let p = e2.url.substr(10), y = this.tiles.get(p);
|
|
848
|
+
if (y || (y = new x(p), this.tiles.set(p, y)), this.metadata) return { data: yield y.getTileJson(e2.url) };
|
|
849
|
+
let f = yield y.getHeader();
|
|
850
|
+
return (f.minLon >= f.maxLon || f.minLat >= f.maxLat) && console.error(`Bounds of PMTiles archive ${f.minLon},${f.minLat},${f.maxLon},${f.maxLat} are not valid.`), { data: { tiles: [`${e2.url}/{z}/{x}/{y}`], minzoom: f.minZoom, maxzoom: f.maxZoom, bounds: [f.minLon, f.minLat, f.maxLon, f.maxLat] } };
|
|
851
|
+
}
|
|
852
|
+
let r = new RegExp(/pmtiles:\/\/(.+)\/(\d+)\/(\d+)\/(\d+)/), n = e2.url.match(r);
|
|
853
|
+
if (!n) throw new Error("Invalid PMTiles protocol URL");
|
|
854
|
+
let s = n[1], o = this.tiles.get(s);
|
|
855
|
+
o || (o = new x(s), this.tiles.set(s, o));
|
|
856
|
+
let a = n[2], u = n[3], c = n[4], d = yield o.getHeader(), h = yield o == null ? void 0 : o.getZxy(+a, +u, +c, t.signal);
|
|
857
|
+
if (h) return { data: new Uint8Array(h.data), cacheControl: h.cacheControl, expires: h.expires };
|
|
858
|
+
if (d.tileType === 1) {
|
|
859
|
+
if (this.errorOnMissingTile) throw new Error("Tile not found.");
|
|
860
|
+
return { data: new Uint8Array() };
|
|
861
|
+
}
|
|
862
|
+
return { data: null };
|
|
863
|
+
}), "tilev4");
|
|
864
|
+
this.tile = j(this.tilev4);
|
|
865
|
+
this.tiles = /* @__PURE__ */ new Map(), this.metadata = (e == null ? void 0 : e.metadata) || false, this.errorOnMissingTile = (e == null ? void 0 : e.errorOnMissingTile) || false;
|
|
866
|
+
}
|
|
867
|
+
add(e) {
|
|
868
|
+
this.tiles.set(e.source.getKey(), e);
|
|
869
|
+
}
|
|
870
|
+
get(e) {
|
|
871
|
+
return this.tiles.get(e);
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
l(T, "Protocol");
|
|
875
|
+
function w(i2, e) {
|
|
876
|
+
return (e >>> 0) * 4294967296 + (i2 >>> 0);
|
|
877
|
+
}
|
|
878
|
+
l(w, "toNum");
|
|
879
|
+
function F(i2, e) {
|
|
880
|
+
let t = e.buf, r = t[e.pos++], n = (r & 112) >> 4;
|
|
881
|
+
if (r < 128 || (r = t[e.pos++], n |= (r & 127) << 3, r < 128) || (r = t[e.pos++], n |= (r & 127) << 10, r < 128) || (r = t[e.pos++], n |= (r & 127) << 17, r < 128) || (r = t[e.pos++], n |= (r & 127) << 24, r < 128) || (r = t[e.pos++], n |= (r & 1) << 31, r < 128)) return w(i2, n);
|
|
882
|
+
throw new Error("Expected varint not more than 10 bytes");
|
|
883
|
+
}
|
|
884
|
+
l(F, "readVarintRemainder");
|
|
885
|
+
function v(i2) {
|
|
886
|
+
let e = i2.buf, t = e[i2.pos++], r = t & 127;
|
|
887
|
+
return t < 128 || (t = e[i2.pos++], r |= (t & 127) << 7, t < 128) || (t = e[i2.pos++], r |= (t & 127) << 14, t < 128) || (t = e[i2.pos++], r |= (t & 127) << 21, t < 128) ? r : (t = e[i2.pos], r |= (t & 15) << 28, F(r, i2));
|
|
888
|
+
}
|
|
889
|
+
l(v, "readVarint");
|
|
890
|
+
function k(i2, e, t, r) {
|
|
891
|
+
if (r === 0) {
|
|
892
|
+
t === 1 && (e[0] = i2 - 1 - e[0], e[1] = i2 - 1 - e[1]);
|
|
893
|
+
let n = e[0];
|
|
894
|
+
e[0] = e[1], e[1] = n;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
l(k, "rotate");
|
|
898
|
+
function N(i2, e) {
|
|
899
|
+
let t = b(2, i2), r = e, n = e, s = e, o = [0, 0], a = 1;
|
|
900
|
+
for (; a < t; ) r = 1 & s / 2, n = 1 & (s ^ r), k(a, o, r, n), o[0] += a * r, o[1] += a * n, s = s / 4, a *= 2;
|
|
901
|
+
return [i2, o[0], o[1]];
|
|
902
|
+
}
|
|
903
|
+
l(N, "idOnLevel");
|
|
904
|
+
var q = [0, 1, 5, 21, 85, 341, 1365, 5461, 21845, 87381, 349525, 1398101, 5592405, 22369621, 89478485, 357913941, 1431655765, 5726623061, 22906492245, 91625968981, 366503875925, 1466015503701, 5864062014805, 23456248059221, 93824992236885, 375299968947541, 1501199875790165];
|
|
905
|
+
function G(i2, e, t) {
|
|
906
|
+
if (i2 > 26) throw new Error("Tile zoom level exceeds max safe number limit (26)");
|
|
907
|
+
if (e > b(2, i2) - 1 || t > b(2, i2) - 1) throw new Error("tile x/y outside zoom level bounds");
|
|
908
|
+
let r = q[i2], n = b(2, i2), s = 0, o = 0, a = 0, u = [e, t], c = n / 2;
|
|
909
|
+
for (; c > 0; ) s = (u[0] & c) > 0 ? 1 : 0, o = (u[1] & c) > 0 ? 1 : 0, a += c * c * (3 * s ^ o), k(c, u, s, o), c = c / 2;
|
|
910
|
+
return r + a;
|
|
911
|
+
}
|
|
912
|
+
l(G, "zxyToTileId");
|
|
913
|
+
function ie(i2) {
|
|
914
|
+
let e = 0, t = 0;
|
|
915
|
+
for (let r = 0; r < 27; r++) {
|
|
916
|
+
let n = (1 << r) * (1 << r);
|
|
917
|
+
if (e + n > i2) return N(r, i2 - e);
|
|
918
|
+
e += n;
|
|
919
|
+
}
|
|
920
|
+
throw new Error("Tile zoom level exceeds max safe number limit (26)");
|
|
921
|
+
}
|
|
922
|
+
l(ie, "tileIdToZxy");
|
|
923
|
+
var J = ((s) => (s[s.Unknown = 0] = "Unknown", s[s.None = 1] = "None", s[s.Gzip = 2] = "Gzip", s[s.Brotli = 3] = "Brotli", s[s.Zstd = 4] = "Zstd", s))(J || {});
|
|
924
|
+
function D(i2, e) {
|
|
925
|
+
return m(this, null, function* () {
|
|
926
|
+
if (e === 1 || e === 0) return i2;
|
|
927
|
+
if (e === 2) {
|
|
928
|
+
if (typeof globalThis.DecompressionStream == "undefined") return decompressSync(new Uint8Array(i2));
|
|
929
|
+
let t = new Response(i2).body;
|
|
930
|
+
if (!t) throw new Error("Failed to read response stream");
|
|
931
|
+
let r = t.pipeThrough(new globalThis.DecompressionStream("gzip"));
|
|
932
|
+
return new Response(r).arrayBuffer();
|
|
933
|
+
}
|
|
934
|
+
throw new Error("Compression method not supported");
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
l(D, "defaultDecompress");
|
|
938
|
+
var O = ((o) => (o[o.Unknown = 0] = "Unknown", o[o.Mvt = 1] = "Mvt", o[o.Png = 2] = "Png", o[o.Jpeg = 3] = "Jpeg", o[o.Webp = 4] = "Webp", o[o.Avif = 5] = "Avif", o))(O || {});
|
|
939
|
+
function _(i2) {
|
|
940
|
+
return i2 === 1 ? ".mvt" : i2 === 2 ? ".png" : i2 === 3 ? ".jpg" : i2 === 4 ? ".webp" : i2 === 5 ? ".avif" : "";
|
|
941
|
+
}
|
|
942
|
+
l(_, "tileTypeExt");
|
|
943
|
+
var Y = 127;
|
|
944
|
+
function Q(i2, e) {
|
|
945
|
+
let t = 0, r = i2.length - 1;
|
|
946
|
+
for (; t <= r; ) {
|
|
947
|
+
let n = r + t >> 1, s = e - i2[n].tileId;
|
|
948
|
+
if (s > 0) t = n + 1;
|
|
949
|
+
else if (s < 0) r = n - 1;
|
|
950
|
+
else return i2[n];
|
|
951
|
+
}
|
|
952
|
+
return r >= 0 && (i2[r].runLength === 0 || e - i2[r].tileId < i2[r].runLength) ? i2[r] : null;
|
|
953
|
+
}
|
|
954
|
+
l(Q, "findTile");
|
|
955
|
+
var A = class A2 {
|
|
956
|
+
constructor(e) {
|
|
957
|
+
this.file = e;
|
|
958
|
+
}
|
|
959
|
+
getKey() {
|
|
960
|
+
return this.file.name;
|
|
961
|
+
}
|
|
962
|
+
getBytes(e, t) {
|
|
963
|
+
return m(this, null, function* () {
|
|
964
|
+
return { data: yield this.file.slice(e, e + t).arrayBuffer() };
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
};
|
|
968
|
+
l(A, "FileSource");
|
|
969
|
+
var U = class U2 {
|
|
970
|
+
constructor(e, t = new Headers()) {
|
|
971
|
+
this.url = e, this.customHeaders = t, this.mustReload = false;
|
|
972
|
+
let r = "";
|
|
973
|
+
"navigator" in globalThis && (r = globalThis.navigator.userAgent || "");
|
|
974
|
+
let n = r.indexOf("Windows") > -1, s = /Chrome|Chromium|Edg|OPR|Brave/.test(r);
|
|
975
|
+
this.chromeWindowsNoCache = false, n && s && (this.chromeWindowsNoCache = true);
|
|
976
|
+
}
|
|
977
|
+
getKey() {
|
|
978
|
+
return this.url;
|
|
979
|
+
}
|
|
980
|
+
setHeaders(e) {
|
|
981
|
+
this.customHeaders = e;
|
|
982
|
+
}
|
|
983
|
+
getBytes(e, t, r, n) {
|
|
984
|
+
return m(this, null, function* () {
|
|
985
|
+
let s, o;
|
|
986
|
+
r ? o = r : (s = new AbortController(), o = s.signal);
|
|
987
|
+
let a = new Headers(this.customHeaders);
|
|
988
|
+
a.set("range", `bytes=${e}-${e + t - 1}`);
|
|
989
|
+
let u;
|
|
990
|
+
this.mustReload ? u = "reload" : this.chromeWindowsNoCache && (u = "no-store");
|
|
991
|
+
let c = yield fetch(this.url, { signal: o, cache: u, headers: a });
|
|
992
|
+
if (e === 0 && c.status === 416) {
|
|
993
|
+
let y = c.headers.get("Content-Range");
|
|
994
|
+
if (!y || !y.startsWith("bytes */")) throw new Error("Missing content-length on 416 response");
|
|
995
|
+
let f = +y.substr(8);
|
|
996
|
+
c = yield fetch(this.url, { signal: o, cache: "reload", headers: { range: `bytes=0-${f - 1}` } });
|
|
997
|
+
}
|
|
998
|
+
let d = c.headers.get("Etag");
|
|
999
|
+
if (d != null && d.startsWith("W/") && (d = null), c.status === 416 || n && d && d !== n) throw this.mustReload = true, new E(`Server returned non-matching ETag ${n} after one retry. Check browser extensions and servers for issues that may affect correct ETag headers.`);
|
|
1000
|
+
if (c.status >= 300) throw new Error(`Bad response code: ${c.status}`);
|
|
1001
|
+
let h = c.headers.get("Content-Length");
|
|
1002
|
+
if (c.status === 200 && (!h || +h > t)) throw s && s.abort(), new Error("Server returned no content-length header or content-length exceeding request. Check that your storage backend supports HTTP Byte Serving.");
|
|
1003
|
+
return { data: yield c.arrayBuffer(), etag: d || void 0, cacheControl: c.headers.get("Cache-Control") || void 0, expires: c.headers.get("Expires") || void 0 };
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
l(U, "FetchSource");
|
|
1008
|
+
var C = U;
|
|
1009
|
+
function g(i2, e) {
|
|
1010
|
+
let t = i2.getUint32(e + 4, true), r = i2.getUint32(e + 0, true);
|
|
1011
|
+
return t * b(2, 32) + r;
|
|
1012
|
+
}
|
|
1013
|
+
l(g, "getUint64");
|
|
1014
|
+
function X(i2, e) {
|
|
1015
|
+
let t = new DataView(i2), r = t.getUint8(7);
|
|
1016
|
+
if (r > 3) throw new Error(`Archive is spec version ${r} but this library supports up to spec version 3`);
|
|
1017
|
+
return { specVersion: r, rootDirectoryOffset: g(t, 8), rootDirectoryLength: g(t, 16), jsonMetadataOffset: g(t, 24), jsonMetadataLength: g(t, 32), leafDirectoryOffset: g(t, 40), leafDirectoryLength: g(t, 48), tileDataOffset: g(t, 56), tileDataLength: g(t, 64), numAddressedTiles: g(t, 72), numTileEntries: g(t, 80), numTileContents: g(t, 88), clustered: t.getUint8(96) === 1, internalCompression: t.getUint8(97), tileCompression: t.getUint8(98), tileType: t.getUint8(99), minZoom: t.getUint8(100), maxZoom: t.getUint8(101), minLon: t.getInt32(102, true) / 1e7, minLat: t.getInt32(106, true) / 1e7, maxLon: t.getInt32(110, true) / 1e7, maxLat: t.getInt32(114, true) / 1e7, centerZoom: t.getUint8(118), centerLon: t.getInt32(119, true) / 1e7, centerLat: t.getInt32(123, true) / 1e7, etag: e };
|
|
1018
|
+
}
|
|
1019
|
+
l(X, "bytesToHeader");
|
|
1020
|
+
function Z(i2) {
|
|
1021
|
+
let e = { buf: new Uint8Array(i2), pos: 0 }, t = v(e), r = [], n = 0;
|
|
1022
|
+
for (let s = 0; s < t; s++) {
|
|
1023
|
+
let o = v(e);
|
|
1024
|
+
r.push({ tileId: n + o, offset: 0, length: 0, runLength: 1 }), n += o;
|
|
1025
|
+
}
|
|
1026
|
+
for (let s = 0; s < t; s++) r[s].runLength = v(e);
|
|
1027
|
+
for (let s = 0; s < t; s++) r[s].length = v(e);
|
|
1028
|
+
for (let s = 0; s < t; s++) {
|
|
1029
|
+
let o = v(e);
|
|
1030
|
+
o === 0 && s > 0 ? r[s].offset = r[s - 1].offset + r[s - 1].length : r[s].offset = o - 1;
|
|
1031
|
+
}
|
|
1032
|
+
return r;
|
|
1033
|
+
}
|
|
1034
|
+
l(Z, "deserializeIndex");
|
|
1035
|
+
var R = class R2 extends Error {
|
|
1036
|
+
};
|
|
1037
|
+
l(R, "EtagMismatch");
|
|
1038
|
+
var E = R;
|
|
1039
|
+
function K(i2, e) {
|
|
1040
|
+
return m(this, null, function* () {
|
|
1041
|
+
let t = yield i2.getBytes(0, 16384);
|
|
1042
|
+
if (new DataView(t.data).getUint16(0, true) !== 19792) throw new Error("Wrong magic number for PMTiles archive");
|
|
1043
|
+
let n = t.data.slice(0, Y), s = X(n, t.etag), o = t.data.slice(s.rootDirectoryOffset, s.rootDirectoryOffset + s.rootDirectoryLength), a = `${i2.getKey()}|${s.etag || ""}|${s.rootDirectoryOffset}|${s.rootDirectoryLength}`, u = Z(yield e(o, s.internalCompression));
|
|
1044
|
+
return [s, [a, u.length, u]];
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
l(K, "getHeaderAndRoot");
|
|
1048
|
+
function I(i2, e, t, r, n) {
|
|
1049
|
+
return m(this, null, function* () {
|
|
1050
|
+
let s = yield i2.getBytes(t, r, void 0, n.etag), o = yield e(s.data, n.internalCompression), a = Z(o);
|
|
1051
|
+
if (a.length === 0) throw new Error("Empty directory is invalid");
|
|
1052
|
+
return a;
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
l(I, "getDirectory");
|
|
1056
|
+
var H = class H2 {
|
|
1057
|
+
constructor(e = 100, t = true, r = D) {
|
|
1058
|
+
this.cache = /* @__PURE__ */ new Map(), this.maxCacheEntries = e, this.counter = 1, this.decompress = r;
|
|
1059
|
+
}
|
|
1060
|
+
getHeader(e) {
|
|
1061
|
+
return m(this, null, function* () {
|
|
1062
|
+
let t = e.getKey(), r = this.cache.get(t);
|
|
1063
|
+
if (r) return r.lastUsed = this.counter++, r.data;
|
|
1064
|
+
let n = yield K(e, this.decompress);
|
|
1065
|
+
return n[1] && this.cache.set(n[1][0], { lastUsed: this.counter++, data: n[1][2] }), this.cache.set(t, { lastUsed: this.counter++, data: n[0] }), this.prune(), n[0];
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
getDirectory(e, t, r, n) {
|
|
1069
|
+
return m(this, null, function* () {
|
|
1070
|
+
let s = `${e.getKey()}|${n.etag || ""}|${t}|${r}`, o = this.cache.get(s);
|
|
1071
|
+
if (o) return o.lastUsed = this.counter++, o.data;
|
|
1072
|
+
let a = yield I(e, this.decompress, t, r, n);
|
|
1073
|
+
return this.cache.set(s, { lastUsed: this.counter++, data: a }), this.prune(), a;
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
prune() {
|
|
1077
|
+
if (this.cache.size > this.maxCacheEntries) {
|
|
1078
|
+
let e = 1 / 0, t;
|
|
1079
|
+
this.cache.forEach((r, n) => {
|
|
1080
|
+
r.lastUsed < e && (e = r.lastUsed, t = n);
|
|
1081
|
+
}), t && this.cache.delete(t);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
invalidate(e) {
|
|
1085
|
+
return m(this, null, function* () {
|
|
1086
|
+
this.cache.delete(e.getKey());
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1090
|
+
l(H, "ResolvedValueCache");
|
|
1091
|
+
var M = class M2 {
|
|
1092
|
+
constructor(e = 100, t = true, r = D) {
|
|
1093
|
+
this.cache = /* @__PURE__ */ new Map(), this.invalidations = /* @__PURE__ */ new Map(), this.maxCacheEntries = e, this.counter = 1, this.decompress = r;
|
|
1094
|
+
}
|
|
1095
|
+
getHeader(e) {
|
|
1096
|
+
return m(this, null, function* () {
|
|
1097
|
+
let t = e.getKey(), r = this.cache.get(t);
|
|
1098
|
+
if (r) return r.lastUsed = this.counter++, yield r.data;
|
|
1099
|
+
let n = new Promise((s, o) => {
|
|
1100
|
+
K(e, this.decompress).then((a) => {
|
|
1101
|
+
a[1] && this.cache.set(a[1][0], { lastUsed: this.counter++, data: Promise.resolve(a[1][2]) }), s(a[0]), this.prune();
|
|
1102
|
+
}).catch((a) => {
|
|
1103
|
+
o(a);
|
|
1104
|
+
});
|
|
1105
|
+
});
|
|
1106
|
+
return this.cache.set(t, { lastUsed: this.counter++, data: n }), n;
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
getDirectory(e, t, r, n) {
|
|
1110
|
+
return m(this, null, function* () {
|
|
1111
|
+
let s = `${e.getKey()}|${n.etag || ""}|${t}|${r}`, o = this.cache.get(s);
|
|
1112
|
+
if (o) return o.lastUsed = this.counter++, yield o.data;
|
|
1113
|
+
let a = new Promise((u, c) => {
|
|
1114
|
+
I(e, this.decompress, t, r, n).then((d) => {
|
|
1115
|
+
u(d), this.prune();
|
|
1116
|
+
}).catch((d) => {
|
|
1117
|
+
c(d);
|
|
1118
|
+
});
|
|
1119
|
+
});
|
|
1120
|
+
return this.cache.set(s, { lastUsed: this.counter++, data: a }), a;
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
prune() {
|
|
1124
|
+
if (this.cache.size >= this.maxCacheEntries) {
|
|
1125
|
+
let e = 1 / 0, t;
|
|
1126
|
+
this.cache.forEach((r, n) => {
|
|
1127
|
+
r.lastUsed < e && (e = r.lastUsed, t = n);
|
|
1128
|
+
}), t && this.cache.delete(t);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
invalidate(e) {
|
|
1132
|
+
return m(this, null, function* () {
|
|
1133
|
+
let t = e.getKey();
|
|
1134
|
+
if (this.invalidations.get(t)) return yield this.invalidations.get(t);
|
|
1135
|
+
this.cache.delete(e.getKey());
|
|
1136
|
+
let r = new Promise((n, s) => {
|
|
1137
|
+
this.getHeader(e).then((o) => {
|
|
1138
|
+
n(), this.invalidations.delete(t);
|
|
1139
|
+
}).catch((o) => {
|
|
1140
|
+
s(o);
|
|
1141
|
+
});
|
|
1142
|
+
});
|
|
1143
|
+
this.invalidations.set(t, r);
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
};
|
|
1147
|
+
l(M, "SharedPromiseCache");
|
|
1148
|
+
var P = M;
|
|
1149
|
+
var B = class B2 {
|
|
1150
|
+
constructor(e, t, r) {
|
|
1151
|
+
typeof e == "string" ? this.source = new C(e) : this.source = e, r ? this.decompress = r : this.decompress = D, t ? this.cache = t : this.cache = new P();
|
|
1152
|
+
}
|
|
1153
|
+
getHeader() {
|
|
1154
|
+
return m(this, null, function* () {
|
|
1155
|
+
return yield this.cache.getHeader(this.source);
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
getZxyAttempt(e, t, r, n) {
|
|
1159
|
+
return m(this, null, function* () {
|
|
1160
|
+
let s = G(e, t, r), o = yield this.cache.getHeader(this.source);
|
|
1161
|
+
if (e < o.minZoom || e > o.maxZoom) return;
|
|
1162
|
+
let a = o.rootDirectoryOffset, u = o.rootDirectoryLength;
|
|
1163
|
+
for (let c = 0; c <= 3; c++) {
|
|
1164
|
+
let d = yield this.cache.getDirectory(this.source, a, u, o), h = Q(d, s);
|
|
1165
|
+
if (h) {
|
|
1166
|
+
if (h.runLength > 0) {
|
|
1167
|
+
let p = yield this.source.getBytes(o.tileDataOffset + h.offset, h.length, n, o.etag);
|
|
1168
|
+
return { data: yield this.decompress(p.data, o.tileCompression), cacheControl: p.cacheControl, expires: p.expires };
|
|
1169
|
+
}
|
|
1170
|
+
a = o.leafDirectoryOffset + h.offset, u = h.length;
|
|
1171
|
+
} else return;
|
|
1172
|
+
}
|
|
1173
|
+
throw new Error("Maximum directory depth exceeded");
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
getZxy(e, t, r, n) {
|
|
1177
|
+
return m(this, null, function* () {
|
|
1178
|
+
try {
|
|
1179
|
+
return yield this.getZxyAttempt(e, t, r, n);
|
|
1180
|
+
} catch (s) {
|
|
1181
|
+
if (s instanceof E) return this.cache.invalidate(this.source), yield this.getZxyAttempt(e, t, r, n);
|
|
1182
|
+
throw s;
|
|
1183
|
+
}
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
getMetadataAttempt() {
|
|
1187
|
+
return m(this, null, function* () {
|
|
1188
|
+
let e = yield this.cache.getHeader(this.source), t = yield this.source.getBytes(e.jsonMetadataOffset, e.jsonMetadataLength, void 0, e.etag), r = yield this.decompress(t.data, e.internalCompression), n = new TextDecoder("utf-8");
|
|
1189
|
+
return JSON.parse(n.decode(r));
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
getMetadata() {
|
|
1193
|
+
return m(this, null, function* () {
|
|
1194
|
+
try {
|
|
1195
|
+
return yield this.getMetadataAttempt();
|
|
1196
|
+
} catch (e) {
|
|
1197
|
+
if (e instanceof E) return this.cache.invalidate(this.source), yield this.getMetadataAttempt();
|
|
1198
|
+
throw e;
|
|
1199
|
+
}
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
getTileJson(e) {
|
|
1203
|
+
return m(this, null, function* () {
|
|
1204
|
+
let t = yield this.getHeader(), r = yield this.getMetadata(), n = _(t.tileType);
|
|
1205
|
+
return { tilejson: "3.0.0", scheme: "xyz", tiles: [`${e}/{z}/{x}/{y}${n}`], vector_layers: r.vector_layers, attribution: r.attribution, description: r.description, name: r.name, version: r.version, bounds: [t.minLon, t.minLat, t.maxLon, t.maxLat], center: [t.centerLon, t.centerLat, t.centerZoom], minzoom: t.minZoom, maxzoom: t.maxZoom };
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1208
|
+
};
|
|
1209
|
+
l(B, "PMTiles");
|
|
1210
|
+
var x = B;
|
|
1211
|
+
function Point(x22, y) {
|
|
1212
|
+
this.x = x22;
|
|
1213
|
+
this.y = y;
|
|
1214
|
+
}
|
|
1215
|
+
Point.prototype = {
|
|
1216
|
+
/**
|
|
1217
|
+
* Clone this point, returning a new point that can be modified
|
|
1218
|
+
* without affecting the old one.
|
|
1219
|
+
* @return {Point} the clone
|
|
1220
|
+
*/
|
|
1221
|
+
clone() {
|
|
1222
|
+
return new Point(this.x, this.y);
|
|
1223
|
+
},
|
|
1224
|
+
/**
|
|
1225
|
+
* Add this point's x & y coordinates to another point,
|
|
1226
|
+
* yielding a new point.
|
|
1227
|
+
* @param {Point} p the other point
|
|
1228
|
+
* @return {Point} output point
|
|
1229
|
+
*/
|
|
1230
|
+
add(p) {
|
|
1231
|
+
return this.clone()._add(p);
|
|
1232
|
+
},
|
|
1233
|
+
/**
|
|
1234
|
+
* Subtract this point's x & y coordinates to from point,
|
|
1235
|
+
* yielding a new point.
|
|
1236
|
+
* @param {Point} p the other point
|
|
1237
|
+
* @return {Point} output point
|
|
1238
|
+
*/
|
|
1239
|
+
sub(p) {
|
|
1240
|
+
return this.clone()._sub(p);
|
|
1241
|
+
},
|
|
1242
|
+
/**
|
|
1243
|
+
* Multiply this point's x & y coordinates by point,
|
|
1244
|
+
* yielding a new point.
|
|
1245
|
+
* @param {Point} p the other point
|
|
1246
|
+
* @return {Point} output point
|
|
1247
|
+
*/
|
|
1248
|
+
multByPoint(p) {
|
|
1249
|
+
return this.clone()._multByPoint(p);
|
|
1250
|
+
},
|
|
1251
|
+
/**
|
|
1252
|
+
* Divide this point's x & y coordinates by point,
|
|
1253
|
+
* yielding a new point.
|
|
1254
|
+
* @param {Point} p the other point
|
|
1255
|
+
* @return {Point} output point
|
|
1256
|
+
*/
|
|
1257
|
+
divByPoint(p) {
|
|
1258
|
+
return this.clone()._divByPoint(p);
|
|
1259
|
+
},
|
|
1260
|
+
/**
|
|
1261
|
+
* Multiply this point's x & y coordinates by a factor,
|
|
1262
|
+
* yielding a new point.
|
|
1263
|
+
* @param {number} k factor
|
|
1264
|
+
* @return {Point} output point
|
|
1265
|
+
*/
|
|
1266
|
+
mult(k2) {
|
|
1267
|
+
return this.clone()._mult(k2);
|
|
1268
|
+
},
|
|
1269
|
+
/**
|
|
1270
|
+
* Divide this point's x & y coordinates by a factor,
|
|
1271
|
+
* yielding a new point.
|
|
1272
|
+
* @param {number} k factor
|
|
1273
|
+
* @return {Point} output point
|
|
1274
|
+
*/
|
|
1275
|
+
div(k2) {
|
|
1276
|
+
return this.clone()._div(k2);
|
|
1277
|
+
},
|
|
1278
|
+
/**
|
|
1279
|
+
* Rotate this point around the 0, 0 origin by an angle a,
|
|
1280
|
+
* given in radians
|
|
1281
|
+
* @param {number} a angle to rotate around, in radians
|
|
1282
|
+
* @return {Point} output point
|
|
1283
|
+
*/
|
|
1284
|
+
rotate(a) {
|
|
1285
|
+
return this.clone()._rotate(a);
|
|
1286
|
+
},
|
|
1287
|
+
/**
|
|
1288
|
+
* Rotate this point around p point by an angle a,
|
|
1289
|
+
* given in radians
|
|
1290
|
+
* @param {number} a angle to rotate around, in radians
|
|
1291
|
+
* @param {Point} p Point to rotate around
|
|
1292
|
+
* @return {Point} output point
|
|
1293
|
+
*/
|
|
1294
|
+
rotateAround(a, p) {
|
|
1295
|
+
return this.clone()._rotateAround(a, p);
|
|
1296
|
+
},
|
|
1297
|
+
/**
|
|
1298
|
+
* Multiply this point by a 4x1 transformation matrix
|
|
1299
|
+
* @param {[number, number, number, number]} m transformation matrix
|
|
1300
|
+
* @return {Point} output point
|
|
1301
|
+
*/
|
|
1302
|
+
matMult(m2) {
|
|
1303
|
+
return this.clone()._matMult(m2);
|
|
1304
|
+
},
|
|
1305
|
+
/**
|
|
1306
|
+
* Calculate this point but as a unit vector from 0, 0, meaning
|
|
1307
|
+
* that the distance from the resulting point to the 0, 0
|
|
1308
|
+
* coordinate will be equal to 1 and the angle from the resulting
|
|
1309
|
+
* point to the 0, 0 coordinate will be the same as before.
|
|
1310
|
+
* @return {Point} unit vector point
|
|
1311
|
+
*/
|
|
1312
|
+
unit() {
|
|
1313
|
+
return this.clone()._unit();
|
|
1314
|
+
},
|
|
1315
|
+
/**
|
|
1316
|
+
* Compute a perpendicular point, where the new y coordinate
|
|
1317
|
+
* is the old x coordinate and the new x coordinate is the old y
|
|
1318
|
+
* coordinate multiplied by -1
|
|
1319
|
+
* @return {Point} perpendicular point
|
|
1320
|
+
*/
|
|
1321
|
+
perp() {
|
|
1322
|
+
return this.clone()._perp();
|
|
1323
|
+
},
|
|
1324
|
+
/**
|
|
1325
|
+
* Return a version of this point with the x & y coordinates
|
|
1326
|
+
* rounded to integers.
|
|
1327
|
+
* @return {Point} rounded point
|
|
1328
|
+
*/
|
|
1329
|
+
round() {
|
|
1330
|
+
return this.clone()._round();
|
|
1331
|
+
},
|
|
1332
|
+
/**
|
|
1333
|
+
* Return the magnitude of this point: this is the Euclidean
|
|
1334
|
+
* distance from the 0, 0 coordinate to this point's x and y
|
|
1335
|
+
* coordinates.
|
|
1336
|
+
* @return {number} magnitude
|
|
1337
|
+
*/
|
|
1338
|
+
mag() {
|
|
1339
|
+
return Math.sqrt(this.x * this.x + this.y * this.y);
|
|
1340
|
+
},
|
|
1341
|
+
/**
|
|
1342
|
+
* Judge whether this point is equal to another point, returning
|
|
1343
|
+
* true or false.
|
|
1344
|
+
* @param {Point} other the other point
|
|
1345
|
+
* @return {boolean} whether the points are equal
|
|
1346
|
+
*/
|
|
1347
|
+
equals(other) {
|
|
1348
|
+
return this.x === other.x && this.y === other.y;
|
|
1349
|
+
},
|
|
1350
|
+
/**
|
|
1351
|
+
* Calculate the distance from this point to another point
|
|
1352
|
+
* @param {Point} p the other point
|
|
1353
|
+
* @return {number} distance
|
|
1354
|
+
*/
|
|
1355
|
+
dist(p) {
|
|
1356
|
+
return Math.sqrt(this.distSqr(p));
|
|
1357
|
+
},
|
|
1358
|
+
/**
|
|
1359
|
+
* Calculate the distance from this point to another point,
|
|
1360
|
+
* without the square root step. Useful if you're comparing
|
|
1361
|
+
* relative distances.
|
|
1362
|
+
* @param {Point} p the other point
|
|
1363
|
+
* @return {number} distance
|
|
1364
|
+
*/
|
|
1365
|
+
distSqr(p) {
|
|
1366
|
+
const dx = p.x - this.x, dy = p.y - this.y;
|
|
1367
|
+
return dx * dx + dy * dy;
|
|
1368
|
+
},
|
|
1369
|
+
/**
|
|
1370
|
+
* Get the angle from the 0, 0 coordinate to this point, in radians
|
|
1371
|
+
* coordinates.
|
|
1372
|
+
* @return {number} angle
|
|
1373
|
+
*/
|
|
1374
|
+
angle() {
|
|
1375
|
+
return Math.atan2(this.y, this.x);
|
|
1376
|
+
},
|
|
1377
|
+
/**
|
|
1378
|
+
* Get the angle from this point to another point, in radians
|
|
1379
|
+
* @param {Point} b the other point
|
|
1380
|
+
* @return {number} angle
|
|
1381
|
+
*/
|
|
1382
|
+
angleTo(b2) {
|
|
1383
|
+
return Math.atan2(this.y - b2.y, this.x - b2.x);
|
|
1384
|
+
},
|
|
1385
|
+
/**
|
|
1386
|
+
* Get the angle between this point and another point, in radians
|
|
1387
|
+
* @param {Point} b the other point
|
|
1388
|
+
* @return {number} angle
|
|
1389
|
+
*/
|
|
1390
|
+
angleWith(b2) {
|
|
1391
|
+
return this.angleWithSep(b2.x, b2.y);
|
|
1392
|
+
},
|
|
1393
|
+
/**
|
|
1394
|
+
* Find the angle of the two vectors, solving the formula for
|
|
1395
|
+
* the cross product a x b = |a||b|sin(θ) for θ.
|
|
1396
|
+
* @param {number} x the x-coordinate
|
|
1397
|
+
* @param {number} y the y-coordinate
|
|
1398
|
+
* @return {number} the angle in radians
|
|
1399
|
+
*/
|
|
1400
|
+
angleWithSep(x22, y) {
|
|
1401
|
+
return Math.atan2(
|
|
1402
|
+
this.x * y - this.y * x22,
|
|
1403
|
+
this.x * x22 + this.y * y
|
|
1404
|
+
);
|
|
1405
|
+
},
|
|
1406
|
+
/** @param {[number, number, number, number]} m */
|
|
1407
|
+
_matMult(m2) {
|
|
1408
|
+
const x22 = m2[0] * this.x + m2[1] * this.y, y = m2[2] * this.x + m2[3] * this.y;
|
|
1409
|
+
this.x = x22;
|
|
1410
|
+
this.y = y;
|
|
1411
|
+
return this;
|
|
1412
|
+
},
|
|
1413
|
+
/** @param {Point} p */
|
|
1414
|
+
_add(p) {
|
|
1415
|
+
this.x += p.x;
|
|
1416
|
+
this.y += p.y;
|
|
1417
|
+
return this;
|
|
1418
|
+
},
|
|
1419
|
+
/** @param {Point} p */
|
|
1420
|
+
_sub(p) {
|
|
1421
|
+
this.x -= p.x;
|
|
1422
|
+
this.y -= p.y;
|
|
1423
|
+
return this;
|
|
1424
|
+
},
|
|
1425
|
+
/** @param {number} k */
|
|
1426
|
+
_mult(k2) {
|
|
1427
|
+
this.x *= k2;
|
|
1428
|
+
this.y *= k2;
|
|
1429
|
+
return this;
|
|
1430
|
+
},
|
|
1431
|
+
/** @param {number} k */
|
|
1432
|
+
_div(k2) {
|
|
1433
|
+
this.x /= k2;
|
|
1434
|
+
this.y /= k2;
|
|
1435
|
+
return this;
|
|
1436
|
+
},
|
|
1437
|
+
/** @param {Point} p */
|
|
1438
|
+
_multByPoint(p) {
|
|
1439
|
+
this.x *= p.x;
|
|
1440
|
+
this.y *= p.y;
|
|
1441
|
+
return this;
|
|
1442
|
+
},
|
|
1443
|
+
/** @param {Point} p */
|
|
1444
|
+
_divByPoint(p) {
|
|
1445
|
+
this.x /= p.x;
|
|
1446
|
+
this.y /= p.y;
|
|
1447
|
+
return this;
|
|
1448
|
+
},
|
|
1449
|
+
_unit() {
|
|
1450
|
+
this._div(this.mag());
|
|
1451
|
+
return this;
|
|
1452
|
+
},
|
|
1453
|
+
_perp() {
|
|
1454
|
+
const y = this.y;
|
|
1455
|
+
this.y = this.x;
|
|
1456
|
+
this.x = -y;
|
|
1457
|
+
return this;
|
|
1458
|
+
},
|
|
1459
|
+
/** @param {number} angle */
|
|
1460
|
+
_rotate(angle) {
|
|
1461
|
+
const cos = Math.cos(angle), sin = Math.sin(angle), x22 = cos * this.x - sin * this.y, y = sin * this.x + cos * this.y;
|
|
1462
|
+
this.x = x22;
|
|
1463
|
+
this.y = y;
|
|
1464
|
+
return this;
|
|
1465
|
+
},
|
|
1466
|
+
/**
|
|
1467
|
+
* @param {number} angle
|
|
1468
|
+
* @param {Point} p
|
|
1469
|
+
*/
|
|
1470
|
+
_rotateAround(angle, p) {
|
|
1471
|
+
const cos = Math.cos(angle), sin = Math.sin(angle), x22 = p.x + cos * (this.x - p.x) - sin * (this.y - p.y), y = p.y + sin * (this.x - p.x) + cos * (this.y - p.y);
|
|
1472
|
+
this.x = x22;
|
|
1473
|
+
this.y = y;
|
|
1474
|
+
return this;
|
|
1475
|
+
},
|
|
1476
|
+
_round() {
|
|
1477
|
+
this.x = Math.round(this.x);
|
|
1478
|
+
this.y = Math.round(this.y);
|
|
1479
|
+
return this;
|
|
1480
|
+
},
|
|
1481
|
+
constructor: Point
|
|
1482
|
+
};
|
|
1483
|
+
Point.convert = function(p) {
|
|
1484
|
+
if (p instanceof Point) {
|
|
1485
|
+
return (
|
|
1486
|
+
/** @type {Point} */
|
|
1487
|
+
p
|
|
1488
|
+
);
|
|
1489
|
+
}
|
|
1490
|
+
if (Array.isArray(p)) {
|
|
1491
|
+
return new Point(+p[0], +p[1]);
|
|
1492
|
+
}
|
|
1493
|
+
if (p.x !== void 0 && p.y !== void 0) {
|
|
1494
|
+
return new Point(+p.x, +p.y);
|
|
1495
|
+
}
|
|
1496
|
+
throw new Error("Expected [x, y] or {x, y} point format");
|
|
1497
|
+
};
|
|
1498
|
+
var VectorTileFeature = class {
|
|
1499
|
+
/**
|
|
1500
|
+
* @param {Pbf} pbf
|
|
1501
|
+
* @param {number} end
|
|
1502
|
+
* @param {number} extent
|
|
1503
|
+
* @param {string[]} keys
|
|
1504
|
+
* @param {(number | string | boolean)[]} values
|
|
1505
|
+
*/
|
|
1506
|
+
constructor(pbf, end, extent, keys, values) {
|
|
1507
|
+
this.properties = {};
|
|
1508
|
+
this.extent = extent;
|
|
1509
|
+
this.type = 0;
|
|
1510
|
+
this.id = void 0;
|
|
1511
|
+
this._pbf = pbf;
|
|
1512
|
+
this._geometry = -1;
|
|
1513
|
+
this._keys = keys;
|
|
1514
|
+
this._values = values;
|
|
1515
|
+
pbf.readFields(readFeature, this, end);
|
|
1516
|
+
}
|
|
1517
|
+
loadGeometry() {
|
|
1518
|
+
const pbf = this._pbf;
|
|
1519
|
+
pbf.pos = this._geometry;
|
|
1520
|
+
const end = pbf.readVarint() + pbf.pos;
|
|
1521
|
+
const lines = [];
|
|
1522
|
+
let line;
|
|
1523
|
+
let cmd = 1;
|
|
1524
|
+
let length = 0;
|
|
1525
|
+
let x22 = 0;
|
|
1526
|
+
let y = 0;
|
|
1527
|
+
while (pbf.pos < end) {
|
|
1528
|
+
if (length <= 0) {
|
|
1529
|
+
const cmdLen = pbf.readVarint();
|
|
1530
|
+
cmd = cmdLen & 7;
|
|
1531
|
+
length = cmdLen >> 3;
|
|
1532
|
+
}
|
|
1533
|
+
length--;
|
|
1534
|
+
if (cmd === 1 || cmd === 2) {
|
|
1535
|
+
x22 += pbf.readSVarint();
|
|
1536
|
+
y += pbf.readSVarint();
|
|
1537
|
+
if (cmd === 1) {
|
|
1538
|
+
if (line) lines.push(line);
|
|
1539
|
+
line = [];
|
|
1540
|
+
}
|
|
1541
|
+
if (line) line.push(new Point(x22, y));
|
|
1542
|
+
} else if (cmd === 7) {
|
|
1543
|
+
if (line) {
|
|
1544
|
+
line.push(line[0].clone());
|
|
1545
|
+
}
|
|
1546
|
+
} else {
|
|
1547
|
+
throw new Error(`unknown command ${cmd}`);
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
if (line) lines.push(line);
|
|
1551
|
+
return lines;
|
|
1552
|
+
}
|
|
1553
|
+
bbox() {
|
|
1554
|
+
const pbf = this._pbf;
|
|
1555
|
+
pbf.pos = this._geometry;
|
|
1556
|
+
const end = pbf.readVarint() + pbf.pos;
|
|
1557
|
+
let cmd = 1, length = 0, x22 = 0, y = 0, x1 = Infinity, x222 = -Infinity, y1 = Infinity, y2 = -Infinity;
|
|
1558
|
+
while (pbf.pos < end) {
|
|
1559
|
+
if (length <= 0) {
|
|
1560
|
+
const cmdLen = pbf.readVarint();
|
|
1561
|
+
cmd = cmdLen & 7;
|
|
1562
|
+
length = cmdLen >> 3;
|
|
1563
|
+
}
|
|
1564
|
+
length--;
|
|
1565
|
+
if (cmd === 1 || cmd === 2) {
|
|
1566
|
+
x22 += pbf.readSVarint();
|
|
1567
|
+
y += pbf.readSVarint();
|
|
1568
|
+
if (x22 < x1) x1 = x22;
|
|
1569
|
+
if (x22 > x222) x222 = x22;
|
|
1570
|
+
if (y < y1) y1 = y;
|
|
1571
|
+
if (y > y2) y2 = y;
|
|
1572
|
+
} else if (cmd !== 7) {
|
|
1573
|
+
throw new Error(`unknown command ${cmd}`);
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
return [x1, y1, x222, y2];
|
|
1577
|
+
}
|
|
1578
|
+
/**
|
|
1579
|
+
* @param {number} x
|
|
1580
|
+
* @param {number} y
|
|
1581
|
+
* @param {number} z
|
|
1582
|
+
* @return {Feature}
|
|
1583
|
+
*/
|
|
1584
|
+
toGeoJSON(x22, y, z2) {
|
|
1585
|
+
const size = this.extent * Math.pow(2, z2), x0 = this.extent * x22, y0 = this.extent * y, vtCoords = this.loadGeometry();
|
|
1586
|
+
function projectPoint(p) {
|
|
1587
|
+
return [
|
|
1588
|
+
(p.x + x0) * 360 / size - 180,
|
|
1589
|
+
360 / Math.PI * Math.atan(Math.exp((1 - (p.y + y0) * 2 / size) * Math.PI)) - 90
|
|
1590
|
+
];
|
|
1591
|
+
}
|
|
1592
|
+
function projectLine(line) {
|
|
1593
|
+
return line.map(projectPoint);
|
|
1594
|
+
}
|
|
1595
|
+
let geometry;
|
|
1596
|
+
if (this.type === 1) {
|
|
1597
|
+
const points = [];
|
|
1598
|
+
for (const line of vtCoords) {
|
|
1599
|
+
points.push(line[0]);
|
|
1600
|
+
}
|
|
1601
|
+
const coordinates = projectLine(points);
|
|
1602
|
+
geometry = points.length === 1 ? { type: "Point", coordinates: coordinates[0] } : { type: "MultiPoint", coordinates };
|
|
1603
|
+
} else if (this.type === 2) {
|
|
1604
|
+
const coordinates = vtCoords.map(projectLine);
|
|
1605
|
+
geometry = coordinates.length === 1 ? { type: "LineString", coordinates: coordinates[0] } : { type: "MultiLineString", coordinates };
|
|
1606
|
+
} else if (this.type === 3) {
|
|
1607
|
+
const polygons = classifyRings(vtCoords);
|
|
1608
|
+
const coordinates = [];
|
|
1609
|
+
for (const polygon of polygons) {
|
|
1610
|
+
coordinates.push(polygon.map(projectLine));
|
|
1611
|
+
}
|
|
1612
|
+
geometry = coordinates.length === 1 ? { type: "Polygon", coordinates: coordinates[0] } : { type: "MultiPolygon", coordinates };
|
|
1613
|
+
} else {
|
|
1614
|
+
throw new Error("unknown feature type");
|
|
1615
|
+
}
|
|
1616
|
+
const result = {
|
|
1617
|
+
type: "Feature",
|
|
1618
|
+
geometry,
|
|
1619
|
+
properties: this.properties
|
|
1620
|
+
};
|
|
1621
|
+
if (this.id != null) {
|
|
1622
|
+
result.id = this.id;
|
|
1623
|
+
}
|
|
1624
|
+
return result;
|
|
1625
|
+
}
|
|
1626
|
+
};
|
|
1627
|
+
VectorTileFeature.types = ["Unknown", "Point", "LineString", "Polygon"];
|
|
1628
|
+
function readFeature(tag, feature, pbf) {
|
|
1629
|
+
if (tag === 1) feature.id = pbf.readVarint();
|
|
1630
|
+
else if (tag === 2) readTag(pbf, feature);
|
|
1631
|
+
else if (tag === 3) feature.type = /** @type {0 | 1 | 2 | 3} */
|
|
1632
|
+
pbf.readVarint();
|
|
1633
|
+
else if (tag === 4) feature._geometry = pbf.pos;
|
|
1634
|
+
}
|
|
1635
|
+
function readTag(pbf, feature) {
|
|
1636
|
+
const end = pbf.readVarint() + pbf.pos;
|
|
1637
|
+
while (pbf.pos < end) {
|
|
1638
|
+
const key = feature._keys[pbf.readVarint()];
|
|
1639
|
+
const value = feature._values[pbf.readVarint()];
|
|
1640
|
+
feature.properties[key] = value;
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
function classifyRings(rings) {
|
|
1644
|
+
const len = rings.length;
|
|
1645
|
+
if (len <= 1) return [rings];
|
|
1646
|
+
const polygons = [];
|
|
1647
|
+
let polygon, ccw;
|
|
1648
|
+
for (let i2 = 0; i2 < len; i2++) {
|
|
1649
|
+
const area = signedArea(rings[i2]);
|
|
1650
|
+
if (area === 0) continue;
|
|
1651
|
+
if (ccw === void 0) ccw = area < 0;
|
|
1652
|
+
if (ccw === area < 0) {
|
|
1653
|
+
if (polygon) polygons.push(polygon);
|
|
1654
|
+
polygon = [rings[i2]];
|
|
1655
|
+
} else if (polygon) {
|
|
1656
|
+
polygon.push(rings[i2]);
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
if (polygon) polygons.push(polygon);
|
|
1660
|
+
return polygons;
|
|
1661
|
+
}
|
|
1662
|
+
function signedArea(ring) {
|
|
1663
|
+
let sum = 0;
|
|
1664
|
+
for (let i2 = 0, len = ring.length, j2 = len - 1, p1, p2; i2 < len; j2 = i2++) {
|
|
1665
|
+
p1 = ring[i2];
|
|
1666
|
+
p2 = ring[j2];
|
|
1667
|
+
sum += (p2.x - p1.x) * (p1.y + p2.y);
|
|
1668
|
+
}
|
|
1669
|
+
return sum;
|
|
1670
|
+
}
|
|
1671
|
+
var VectorTileLayer = class {
|
|
1672
|
+
/**
|
|
1673
|
+
* @param {Pbf} pbf
|
|
1674
|
+
* @param {number} [end]
|
|
1675
|
+
*/
|
|
1676
|
+
constructor(pbf, end) {
|
|
1677
|
+
this.version = 1;
|
|
1678
|
+
this.name = "";
|
|
1679
|
+
this.extent = 4096;
|
|
1680
|
+
this.length = 0;
|
|
1681
|
+
this._pbf = pbf;
|
|
1682
|
+
this._keys = [];
|
|
1683
|
+
this._values = [];
|
|
1684
|
+
this._features = [];
|
|
1685
|
+
pbf.readFields(readLayer, this, end);
|
|
1686
|
+
this.length = this._features.length;
|
|
1687
|
+
}
|
|
1688
|
+
/** return feature `i` from this layer as a `VectorTileFeature`
|
|
1689
|
+
* @param {number} i
|
|
1690
|
+
*/
|
|
1691
|
+
feature(i2) {
|
|
1692
|
+
if (i2 < 0 || i2 >= this._features.length) throw new Error("feature index out of bounds");
|
|
1693
|
+
this._pbf.pos = this._features[i2];
|
|
1694
|
+
const end = this._pbf.readVarint() + this._pbf.pos;
|
|
1695
|
+
return new VectorTileFeature(this._pbf, end, this.extent, this._keys, this._values);
|
|
1696
|
+
}
|
|
1697
|
+
};
|
|
1698
|
+
function readLayer(tag, layer, pbf) {
|
|
1699
|
+
if (tag === 15) layer.version = pbf.readVarint();
|
|
1700
|
+
else if (tag === 1) layer.name = pbf.readString();
|
|
1701
|
+
else if (tag === 5) layer.extent = pbf.readVarint();
|
|
1702
|
+
else if (tag === 2) layer._features.push(pbf.pos);
|
|
1703
|
+
else if (tag === 3) layer._keys.push(pbf.readString());
|
|
1704
|
+
else if (tag === 4) layer._values.push(readValueMessage(pbf));
|
|
1705
|
+
}
|
|
1706
|
+
function readValueMessage(pbf) {
|
|
1707
|
+
let value = null;
|
|
1708
|
+
const end = pbf.readVarint() + pbf.pos;
|
|
1709
|
+
while (pbf.pos < end) {
|
|
1710
|
+
const tag = pbf.readVarint() >> 3;
|
|
1711
|
+
value = tag === 1 ? pbf.readString() : tag === 2 ? pbf.readFloat() : tag === 3 ? pbf.readDouble() : tag === 4 ? pbf.readVarint64() : tag === 5 ? pbf.readVarint() : tag === 6 ? pbf.readSVarint() : tag === 7 ? pbf.readBoolean() : null;
|
|
1712
|
+
}
|
|
1713
|
+
if (value == null) {
|
|
1714
|
+
throw new Error("unknown feature value");
|
|
1715
|
+
}
|
|
1716
|
+
return value;
|
|
1717
|
+
}
|
|
1718
|
+
var VectorTile = class {
|
|
1719
|
+
/**
|
|
1720
|
+
* @param {Pbf} pbf
|
|
1721
|
+
* @param {number} [end]
|
|
1722
|
+
*/
|
|
1723
|
+
constructor(pbf, end) {
|
|
1724
|
+
this.layers = pbf.readFields(readTile, {}, end);
|
|
1725
|
+
}
|
|
1726
|
+
};
|
|
1727
|
+
function readTile(tag, layers, pbf) {
|
|
1728
|
+
if (tag === 3) {
|
|
1729
|
+
const layer = new VectorTileLayer(pbf, pbf.readVarint() + pbf.pos);
|
|
1730
|
+
if (layer.length) layers[layer.name] = layer;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
var SHIFT_LEFT_32 = (1 << 16) * (1 << 16);
|
|
1734
|
+
var SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32;
|
|
1735
|
+
var TEXT_DECODER_MIN_LENGTH = 12;
|
|
1736
|
+
var utf8TextDecoder = typeof TextDecoder === "undefined" ? null : new TextDecoder("utf-8");
|
|
1737
|
+
var PBF_VARINT = 0;
|
|
1738
|
+
var PBF_FIXED64 = 1;
|
|
1739
|
+
var PBF_BYTES = 2;
|
|
1740
|
+
var PBF_FIXED32 = 5;
|
|
1741
|
+
var Pbf = class {
|
|
1742
|
+
/**
|
|
1743
|
+
* @param {Uint8Array | ArrayBuffer} [buf]
|
|
1744
|
+
*/
|
|
1745
|
+
constructor(buf = new Uint8Array(16)) {
|
|
1746
|
+
this.buf = ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf);
|
|
1747
|
+
this.dataView = new DataView(this.buf.buffer);
|
|
1748
|
+
this.pos = 0;
|
|
1749
|
+
this.type = 0;
|
|
1750
|
+
this.length = this.buf.length;
|
|
1751
|
+
}
|
|
1752
|
+
// === READING =================================================================
|
|
1753
|
+
/**
|
|
1754
|
+
* @template T
|
|
1755
|
+
* @param {(tag: number, result: T, pbf: Pbf) => void} readField
|
|
1756
|
+
* @param {T} result
|
|
1757
|
+
* @param {number} [end]
|
|
1758
|
+
*/
|
|
1759
|
+
readFields(readField, result, end = this.length) {
|
|
1760
|
+
while (this.pos < end) {
|
|
1761
|
+
const val = this.readVarint(), tag = val >> 3, startPos = this.pos;
|
|
1762
|
+
this.type = val & 7;
|
|
1763
|
+
readField(tag, result, this);
|
|
1764
|
+
if (this.pos === startPos) this.skip(val);
|
|
1765
|
+
}
|
|
1766
|
+
return result;
|
|
1767
|
+
}
|
|
1768
|
+
/**
|
|
1769
|
+
* @template T
|
|
1770
|
+
* @param {(tag: number, result: T, pbf: Pbf) => void} readField
|
|
1771
|
+
* @param {T} result
|
|
1772
|
+
*/
|
|
1773
|
+
readMessage(readField, result) {
|
|
1774
|
+
return this.readFields(readField, result, this.readVarint() + this.pos);
|
|
1775
|
+
}
|
|
1776
|
+
readFixed32() {
|
|
1777
|
+
const val = this.dataView.getUint32(this.pos, true);
|
|
1778
|
+
this.pos += 4;
|
|
1779
|
+
return val;
|
|
1780
|
+
}
|
|
1781
|
+
readSFixed32() {
|
|
1782
|
+
const val = this.dataView.getInt32(this.pos, true);
|
|
1783
|
+
this.pos += 4;
|
|
1784
|
+
return val;
|
|
1785
|
+
}
|
|
1786
|
+
// 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)
|
|
1787
|
+
readFixed64() {
|
|
1788
|
+
const val = this.dataView.getUint32(this.pos, true) + this.dataView.getUint32(this.pos + 4, true) * SHIFT_LEFT_32;
|
|
1789
|
+
this.pos += 8;
|
|
1790
|
+
return val;
|
|
1791
|
+
}
|
|
1792
|
+
readSFixed64() {
|
|
1793
|
+
const val = this.dataView.getUint32(this.pos, true) + this.dataView.getInt32(this.pos + 4, true) * SHIFT_LEFT_32;
|
|
1794
|
+
this.pos += 8;
|
|
1795
|
+
return val;
|
|
1796
|
+
}
|
|
1797
|
+
readFloat() {
|
|
1798
|
+
const val = this.dataView.getFloat32(this.pos, true);
|
|
1799
|
+
this.pos += 4;
|
|
1800
|
+
return val;
|
|
1801
|
+
}
|
|
1802
|
+
readDouble() {
|
|
1803
|
+
const val = this.dataView.getFloat64(this.pos, true);
|
|
1804
|
+
this.pos += 8;
|
|
1805
|
+
return val;
|
|
1806
|
+
}
|
|
1807
|
+
/**
|
|
1808
|
+
* @param {boolean} [isSigned]
|
|
1809
|
+
*/
|
|
1810
|
+
readVarint(isSigned) {
|
|
1811
|
+
const buf = this.buf;
|
|
1812
|
+
let val, b2;
|
|
1813
|
+
b2 = buf[this.pos++];
|
|
1814
|
+
val = b2 & 127;
|
|
1815
|
+
if (b2 < 128) return val;
|
|
1816
|
+
b2 = buf[this.pos++];
|
|
1817
|
+
val |= (b2 & 127) << 7;
|
|
1818
|
+
if (b2 < 128) return val;
|
|
1819
|
+
b2 = buf[this.pos++];
|
|
1820
|
+
val |= (b2 & 127) << 14;
|
|
1821
|
+
if (b2 < 128) return val;
|
|
1822
|
+
b2 = buf[this.pos++];
|
|
1823
|
+
val |= (b2 & 127) << 21;
|
|
1824
|
+
if (b2 < 128) return val;
|
|
1825
|
+
b2 = buf[this.pos];
|
|
1826
|
+
val |= (b2 & 15) << 28;
|
|
1827
|
+
return readVarintRemainder(val, isSigned, this);
|
|
1828
|
+
}
|
|
1829
|
+
readVarint64() {
|
|
1830
|
+
return this.readVarint(true);
|
|
1831
|
+
}
|
|
1832
|
+
readSVarint() {
|
|
1833
|
+
const num = this.readVarint();
|
|
1834
|
+
return num % 2 === 1 ? (num + 1) / -2 : num / 2;
|
|
1835
|
+
}
|
|
1836
|
+
readBoolean() {
|
|
1837
|
+
return Boolean(this.readVarint());
|
|
1838
|
+
}
|
|
1839
|
+
readString() {
|
|
1840
|
+
const end = this.readVarint() + this.pos;
|
|
1841
|
+
const pos = this.pos;
|
|
1842
|
+
this.pos = end;
|
|
1843
|
+
if (end - pos >= TEXT_DECODER_MIN_LENGTH && utf8TextDecoder) {
|
|
1844
|
+
return utf8TextDecoder.decode(this.buf.subarray(pos, end));
|
|
1845
|
+
}
|
|
1846
|
+
return readUtf8(this.buf, pos, end);
|
|
1847
|
+
}
|
|
1848
|
+
readBytes() {
|
|
1849
|
+
const end = this.readVarint() + this.pos, buffer = this.buf.subarray(this.pos, end);
|
|
1850
|
+
this.pos = end;
|
|
1851
|
+
return buffer;
|
|
1852
|
+
}
|
|
1853
|
+
// verbose for performance reasons; doesn't affect gzipped size
|
|
1854
|
+
/**
|
|
1855
|
+
* @param {number[]} [arr]
|
|
1856
|
+
* @param {boolean} [isSigned]
|
|
1857
|
+
*/
|
|
1858
|
+
readPackedVarint(arr = [], isSigned) {
|
|
1859
|
+
const end = this.readPackedEnd();
|
|
1860
|
+
while (this.pos < end) arr.push(this.readVarint(isSigned));
|
|
1861
|
+
return arr;
|
|
1862
|
+
}
|
|
1863
|
+
/** @param {number[]} [arr] */
|
|
1864
|
+
readPackedSVarint(arr = []) {
|
|
1865
|
+
const end = this.readPackedEnd();
|
|
1866
|
+
while (this.pos < end) arr.push(this.readSVarint());
|
|
1867
|
+
return arr;
|
|
1868
|
+
}
|
|
1869
|
+
/** @param {boolean[]} [arr] */
|
|
1870
|
+
readPackedBoolean(arr = []) {
|
|
1871
|
+
const end = this.readPackedEnd();
|
|
1872
|
+
while (this.pos < end) arr.push(this.readBoolean());
|
|
1873
|
+
return arr;
|
|
1874
|
+
}
|
|
1875
|
+
/** @param {number[]} [arr] */
|
|
1876
|
+
readPackedFloat(arr = []) {
|
|
1877
|
+
const end = this.readPackedEnd();
|
|
1878
|
+
while (this.pos < end) arr.push(this.readFloat());
|
|
1879
|
+
return arr;
|
|
1880
|
+
}
|
|
1881
|
+
/** @param {number[]} [arr] */
|
|
1882
|
+
readPackedDouble(arr = []) {
|
|
1883
|
+
const end = this.readPackedEnd();
|
|
1884
|
+
while (this.pos < end) arr.push(this.readDouble());
|
|
1885
|
+
return arr;
|
|
1886
|
+
}
|
|
1887
|
+
/** @param {number[]} [arr] */
|
|
1888
|
+
readPackedFixed32(arr = []) {
|
|
1889
|
+
const end = this.readPackedEnd();
|
|
1890
|
+
while (this.pos < end) arr.push(this.readFixed32());
|
|
1891
|
+
return arr;
|
|
1892
|
+
}
|
|
1893
|
+
/** @param {number[]} [arr] */
|
|
1894
|
+
readPackedSFixed32(arr = []) {
|
|
1895
|
+
const end = this.readPackedEnd();
|
|
1896
|
+
while (this.pos < end) arr.push(this.readSFixed32());
|
|
1897
|
+
return arr;
|
|
1898
|
+
}
|
|
1899
|
+
/** @param {number[]} [arr] */
|
|
1900
|
+
readPackedFixed64(arr = []) {
|
|
1901
|
+
const end = this.readPackedEnd();
|
|
1902
|
+
while (this.pos < end) arr.push(this.readFixed64());
|
|
1903
|
+
return arr;
|
|
1904
|
+
}
|
|
1905
|
+
/** @param {number[]} [arr] */
|
|
1906
|
+
readPackedSFixed64(arr = []) {
|
|
1907
|
+
const end = this.readPackedEnd();
|
|
1908
|
+
while (this.pos < end) arr.push(this.readSFixed64());
|
|
1909
|
+
return arr;
|
|
1910
|
+
}
|
|
1911
|
+
readPackedEnd() {
|
|
1912
|
+
return this.type === PBF_BYTES ? this.readVarint() + this.pos : this.pos + 1;
|
|
1913
|
+
}
|
|
1914
|
+
/** @param {number} val */
|
|
1915
|
+
skip(val) {
|
|
1916
|
+
const type = val & 7;
|
|
1917
|
+
if (type === PBF_VARINT) while (this.buf[this.pos++] > 127) {
|
|
1918
|
+
}
|
|
1919
|
+
else if (type === PBF_BYTES) this.pos = this.readVarint() + this.pos;
|
|
1920
|
+
else if (type === PBF_FIXED32) this.pos += 4;
|
|
1921
|
+
else if (type === PBF_FIXED64) this.pos += 8;
|
|
1922
|
+
else throw new Error(`Unimplemented type: ${type}`);
|
|
1923
|
+
}
|
|
1924
|
+
// === WRITING =================================================================
|
|
1925
|
+
/**
|
|
1926
|
+
* @param {number} tag
|
|
1927
|
+
* @param {number} type
|
|
1928
|
+
*/
|
|
1929
|
+
writeTag(tag, type) {
|
|
1930
|
+
this.writeVarint(tag << 3 | type);
|
|
1931
|
+
}
|
|
1932
|
+
/** @param {number} min */
|
|
1933
|
+
realloc(min) {
|
|
1934
|
+
let length = this.length || 16;
|
|
1935
|
+
while (length < this.pos + min) length *= 2;
|
|
1936
|
+
if (length !== this.length) {
|
|
1937
|
+
const buf = new Uint8Array(length);
|
|
1938
|
+
buf.set(this.buf);
|
|
1939
|
+
this.buf = buf;
|
|
1940
|
+
this.dataView = new DataView(buf.buffer);
|
|
1941
|
+
this.length = length;
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
finish() {
|
|
1945
|
+
this.length = this.pos;
|
|
1946
|
+
this.pos = 0;
|
|
1947
|
+
return this.buf.subarray(0, this.length);
|
|
1948
|
+
}
|
|
1949
|
+
/** @param {number} val */
|
|
1950
|
+
writeFixed32(val) {
|
|
1951
|
+
this.realloc(4);
|
|
1952
|
+
this.dataView.setInt32(this.pos, val, true);
|
|
1953
|
+
this.pos += 4;
|
|
1954
|
+
}
|
|
1955
|
+
/** @param {number} val */
|
|
1956
|
+
writeSFixed32(val) {
|
|
1957
|
+
this.realloc(4);
|
|
1958
|
+
this.dataView.setInt32(this.pos, val, true);
|
|
1959
|
+
this.pos += 4;
|
|
1960
|
+
}
|
|
1961
|
+
/** @param {number} val */
|
|
1962
|
+
writeFixed64(val) {
|
|
1963
|
+
this.realloc(8);
|
|
1964
|
+
this.dataView.setInt32(this.pos, val & -1, true);
|
|
1965
|
+
this.dataView.setInt32(this.pos + 4, Math.floor(val * SHIFT_RIGHT_32), true);
|
|
1966
|
+
this.pos += 8;
|
|
1967
|
+
}
|
|
1968
|
+
/** @param {number} val */
|
|
1969
|
+
writeSFixed64(val) {
|
|
1970
|
+
this.realloc(8);
|
|
1971
|
+
this.dataView.setInt32(this.pos, val & -1, true);
|
|
1972
|
+
this.dataView.setInt32(this.pos + 4, Math.floor(val * SHIFT_RIGHT_32), true);
|
|
1973
|
+
this.pos += 8;
|
|
1974
|
+
}
|
|
1975
|
+
/** @param {number} val */
|
|
1976
|
+
writeVarint(val) {
|
|
1977
|
+
val = +val || 0;
|
|
1978
|
+
if (val > 268435455 || val < 0) {
|
|
1979
|
+
writeBigVarint(val, this);
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1982
|
+
this.realloc(4);
|
|
1983
|
+
this.buf[this.pos++] = val & 127 | (val > 127 ? 128 : 0);
|
|
1984
|
+
if (val <= 127) return;
|
|
1985
|
+
this.buf[this.pos++] = (val >>>= 7) & 127 | (val > 127 ? 128 : 0);
|
|
1986
|
+
if (val <= 127) return;
|
|
1987
|
+
this.buf[this.pos++] = (val >>>= 7) & 127 | (val > 127 ? 128 : 0);
|
|
1988
|
+
if (val <= 127) return;
|
|
1989
|
+
this.buf[this.pos++] = val >>> 7 & 127;
|
|
1990
|
+
}
|
|
1991
|
+
/** @param {number} val */
|
|
1992
|
+
writeSVarint(val) {
|
|
1993
|
+
this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
|
|
1994
|
+
}
|
|
1995
|
+
/** @param {boolean} val */
|
|
1996
|
+
writeBoolean(val) {
|
|
1997
|
+
this.writeVarint(+val);
|
|
1998
|
+
}
|
|
1999
|
+
/** @param {string} str */
|
|
2000
|
+
writeString(str) {
|
|
2001
|
+
str = String(str);
|
|
2002
|
+
this.realloc(str.length * 4);
|
|
2003
|
+
this.pos++;
|
|
2004
|
+
const startPos = this.pos;
|
|
2005
|
+
this.pos = writeUtf8(this.buf, str, this.pos);
|
|
2006
|
+
const len = this.pos - startPos;
|
|
2007
|
+
if (len >= 128) makeRoomForExtraLength(startPos, len, this);
|
|
2008
|
+
this.pos = startPos - 1;
|
|
2009
|
+
this.writeVarint(len);
|
|
2010
|
+
this.pos += len;
|
|
2011
|
+
}
|
|
2012
|
+
/** @param {number} val */
|
|
2013
|
+
writeFloat(val) {
|
|
2014
|
+
this.realloc(4);
|
|
2015
|
+
this.dataView.setFloat32(this.pos, val, true);
|
|
2016
|
+
this.pos += 4;
|
|
2017
|
+
}
|
|
2018
|
+
/** @param {number} val */
|
|
2019
|
+
writeDouble(val) {
|
|
2020
|
+
this.realloc(8);
|
|
2021
|
+
this.dataView.setFloat64(this.pos, val, true);
|
|
2022
|
+
this.pos += 8;
|
|
2023
|
+
}
|
|
2024
|
+
/** @param {Uint8Array} buffer */
|
|
2025
|
+
writeBytes(buffer) {
|
|
2026
|
+
const len = buffer.length;
|
|
2027
|
+
this.writeVarint(len);
|
|
2028
|
+
this.realloc(len);
|
|
2029
|
+
for (let i2 = 0; i2 < len; i2++) this.buf[this.pos++] = buffer[i2];
|
|
2030
|
+
}
|
|
2031
|
+
/**
|
|
2032
|
+
* @template T
|
|
2033
|
+
* @param {(obj: T, pbf: Pbf) => void} fn
|
|
2034
|
+
* @param {T} obj
|
|
2035
|
+
*/
|
|
2036
|
+
writeRawMessage(fn, obj) {
|
|
2037
|
+
this.pos++;
|
|
2038
|
+
const startPos = this.pos;
|
|
2039
|
+
fn(obj, this);
|
|
2040
|
+
const len = this.pos - startPos;
|
|
2041
|
+
if (len >= 128) makeRoomForExtraLength(startPos, len, this);
|
|
2042
|
+
this.pos = startPos - 1;
|
|
2043
|
+
this.writeVarint(len);
|
|
2044
|
+
this.pos += len;
|
|
2045
|
+
}
|
|
2046
|
+
/**
|
|
2047
|
+
* @template T
|
|
2048
|
+
* @param {number} tag
|
|
2049
|
+
* @param {(obj: T, pbf: Pbf) => void} fn
|
|
2050
|
+
* @param {T} obj
|
|
2051
|
+
*/
|
|
2052
|
+
writeMessage(tag, fn, obj) {
|
|
2053
|
+
this.writeTag(tag, PBF_BYTES);
|
|
2054
|
+
this.writeRawMessage(fn, obj);
|
|
2055
|
+
}
|
|
2056
|
+
/**
|
|
2057
|
+
* @param {number} tag
|
|
2058
|
+
* @param {number[]} arr
|
|
2059
|
+
*/
|
|
2060
|
+
writePackedVarint(tag, arr) {
|
|
2061
|
+
if (arr.length) this.writeMessage(tag, writePackedVarint, arr);
|
|
2062
|
+
}
|
|
2063
|
+
/**
|
|
2064
|
+
* @param {number} tag
|
|
2065
|
+
* @param {number[]} arr
|
|
2066
|
+
*/
|
|
2067
|
+
writePackedSVarint(tag, arr) {
|
|
2068
|
+
if (arr.length) this.writeMessage(tag, writePackedSVarint, arr);
|
|
2069
|
+
}
|
|
2070
|
+
/**
|
|
2071
|
+
* @param {number} tag
|
|
2072
|
+
* @param {boolean[]} arr
|
|
2073
|
+
*/
|
|
2074
|
+
writePackedBoolean(tag, arr) {
|
|
2075
|
+
if (arr.length) this.writeMessage(tag, writePackedBoolean, arr);
|
|
2076
|
+
}
|
|
2077
|
+
/**
|
|
2078
|
+
* @param {number} tag
|
|
2079
|
+
* @param {number[]} arr
|
|
2080
|
+
*/
|
|
2081
|
+
writePackedFloat(tag, arr) {
|
|
2082
|
+
if (arr.length) this.writeMessage(tag, writePackedFloat, arr);
|
|
2083
|
+
}
|
|
2084
|
+
/**
|
|
2085
|
+
* @param {number} tag
|
|
2086
|
+
* @param {number[]} arr
|
|
2087
|
+
*/
|
|
2088
|
+
writePackedDouble(tag, arr) {
|
|
2089
|
+
if (arr.length) this.writeMessage(tag, writePackedDouble, arr);
|
|
2090
|
+
}
|
|
2091
|
+
/**
|
|
2092
|
+
* @param {number} tag
|
|
2093
|
+
* @param {number[]} arr
|
|
2094
|
+
*/
|
|
2095
|
+
writePackedFixed32(tag, arr) {
|
|
2096
|
+
if (arr.length) this.writeMessage(tag, writePackedFixed32, arr);
|
|
2097
|
+
}
|
|
2098
|
+
/**
|
|
2099
|
+
* @param {number} tag
|
|
2100
|
+
* @param {number[]} arr
|
|
2101
|
+
*/
|
|
2102
|
+
writePackedSFixed32(tag, arr) {
|
|
2103
|
+
if (arr.length) this.writeMessage(tag, writePackedSFixed32, arr);
|
|
2104
|
+
}
|
|
2105
|
+
/**
|
|
2106
|
+
* @param {number} tag
|
|
2107
|
+
* @param {number[]} arr
|
|
2108
|
+
*/
|
|
2109
|
+
writePackedFixed64(tag, arr) {
|
|
2110
|
+
if (arr.length) this.writeMessage(tag, writePackedFixed64, arr);
|
|
2111
|
+
}
|
|
2112
|
+
/**
|
|
2113
|
+
* @param {number} tag
|
|
2114
|
+
* @param {number[]} arr
|
|
2115
|
+
*/
|
|
2116
|
+
writePackedSFixed64(tag, arr) {
|
|
2117
|
+
if (arr.length) this.writeMessage(tag, writePackedSFixed64, arr);
|
|
2118
|
+
}
|
|
2119
|
+
/**
|
|
2120
|
+
* @param {number} tag
|
|
2121
|
+
* @param {Uint8Array} buffer
|
|
2122
|
+
*/
|
|
2123
|
+
writeBytesField(tag, buffer) {
|
|
2124
|
+
this.writeTag(tag, PBF_BYTES);
|
|
2125
|
+
this.writeBytes(buffer);
|
|
2126
|
+
}
|
|
2127
|
+
/**
|
|
2128
|
+
* @param {number} tag
|
|
2129
|
+
* @param {number} val
|
|
2130
|
+
*/
|
|
2131
|
+
writeFixed32Field(tag, val) {
|
|
2132
|
+
this.writeTag(tag, PBF_FIXED32);
|
|
2133
|
+
this.writeFixed32(val);
|
|
2134
|
+
}
|
|
2135
|
+
/**
|
|
2136
|
+
* @param {number} tag
|
|
2137
|
+
* @param {number} val
|
|
2138
|
+
*/
|
|
2139
|
+
writeSFixed32Field(tag, val) {
|
|
2140
|
+
this.writeTag(tag, PBF_FIXED32);
|
|
2141
|
+
this.writeSFixed32(val);
|
|
2142
|
+
}
|
|
2143
|
+
/**
|
|
2144
|
+
* @param {number} tag
|
|
2145
|
+
* @param {number} val
|
|
2146
|
+
*/
|
|
2147
|
+
writeFixed64Field(tag, val) {
|
|
2148
|
+
this.writeTag(tag, PBF_FIXED64);
|
|
2149
|
+
this.writeFixed64(val);
|
|
2150
|
+
}
|
|
2151
|
+
/**
|
|
2152
|
+
* @param {number} tag
|
|
2153
|
+
* @param {number} val
|
|
2154
|
+
*/
|
|
2155
|
+
writeSFixed64Field(tag, val) {
|
|
2156
|
+
this.writeTag(tag, PBF_FIXED64);
|
|
2157
|
+
this.writeSFixed64(val);
|
|
2158
|
+
}
|
|
2159
|
+
/**
|
|
2160
|
+
* @param {number} tag
|
|
2161
|
+
* @param {number} val
|
|
2162
|
+
*/
|
|
2163
|
+
writeVarintField(tag, val) {
|
|
2164
|
+
this.writeTag(tag, PBF_VARINT);
|
|
2165
|
+
this.writeVarint(val);
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* @param {number} tag
|
|
2169
|
+
* @param {number} val
|
|
2170
|
+
*/
|
|
2171
|
+
writeSVarintField(tag, val) {
|
|
2172
|
+
this.writeTag(tag, PBF_VARINT);
|
|
2173
|
+
this.writeSVarint(val);
|
|
2174
|
+
}
|
|
2175
|
+
/**
|
|
2176
|
+
* @param {number} tag
|
|
2177
|
+
* @param {string} str
|
|
2178
|
+
*/
|
|
2179
|
+
writeStringField(tag, str) {
|
|
2180
|
+
this.writeTag(tag, PBF_BYTES);
|
|
2181
|
+
this.writeString(str);
|
|
2182
|
+
}
|
|
2183
|
+
/**
|
|
2184
|
+
* @param {number} tag
|
|
2185
|
+
* @param {number} val
|
|
2186
|
+
*/
|
|
2187
|
+
writeFloatField(tag, val) {
|
|
2188
|
+
this.writeTag(tag, PBF_FIXED32);
|
|
2189
|
+
this.writeFloat(val);
|
|
2190
|
+
}
|
|
2191
|
+
/**
|
|
2192
|
+
* @param {number} tag
|
|
2193
|
+
* @param {number} val
|
|
2194
|
+
*/
|
|
2195
|
+
writeDoubleField(tag, val) {
|
|
2196
|
+
this.writeTag(tag, PBF_FIXED64);
|
|
2197
|
+
this.writeDouble(val);
|
|
2198
|
+
}
|
|
2199
|
+
/**
|
|
2200
|
+
* @param {number} tag
|
|
2201
|
+
* @param {boolean} val
|
|
2202
|
+
*/
|
|
2203
|
+
writeBooleanField(tag, val) {
|
|
2204
|
+
this.writeVarintField(tag, +val);
|
|
2205
|
+
}
|
|
2206
|
+
};
|
|
2207
|
+
function readVarintRemainder(l2, s, p) {
|
|
2208
|
+
const buf = p.buf;
|
|
2209
|
+
let h, b2;
|
|
2210
|
+
b2 = buf[p.pos++];
|
|
2211
|
+
h = (b2 & 112) >> 4;
|
|
2212
|
+
if (b2 < 128) return toNum(l2, h, s);
|
|
2213
|
+
b2 = buf[p.pos++];
|
|
2214
|
+
h |= (b2 & 127) << 3;
|
|
2215
|
+
if (b2 < 128) return toNum(l2, h, s);
|
|
2216
|
+
b2 = buf[p.pos++];
|
|
2217
|
+
h |= (b2 & 127) << 10;
|
|
2218
|
+
if (b2 < 128) return toNum(l2, h, s);
|
|
2219
|
+
b2 = buf[p.pos++];
|
|
2220
|
+
h |= (b2 & 127) << 17;
|
|
2221
|
+
if (b2 < 128) return toNum(l2, h, s);
|
|
2222
|
+
b2 = buf[p.pos++];
|
|
2223
|
+
h |= (b2 & 127) << 24;
|
|
2224
|
+
if (b2 < 128) return toNum(l2, h, s);
|
|
2225
|
+
b2 = buf[p.pos++];
|
|
2226
|
+
h |= (b2 & 1) << 31;
|
|
2227
|
+
if (b2 < 128) return toNum(l2, h, s);
|
|
2228
|
+
throw new Error("Expected varint not more than 10 bytes");
|
|
2229
|
+
}
|
|
2230
|
+
function toNum(low, high, isSigned) {
|
|
2231
|
+
return isSigned ? high * 4294967296 + (low >>> 0) : (high >>> 0) * 4294967296 + (low >>> 0);
|
|
2232
|
+
}
|
|
2233
|
+
function writeBigVarint(val, pbf) {
|
|
2234
|
+
let low, high;
|
|
2235
|
+
if (val >= 0) {
|
|
2236
|
+
low = val % 4294967296 | 0;
|
|
2237
|
+
high = val / 4294967296 | 0;
|
|
2238
|
+
} else {
|
|
2239
|
+
low = ~(-val % 4294967296);
|
|
2240
|
+
high = ~(-val / 4294967296);
|
|
2241
|
+
if (low ^ 4294967295) {
|
|
2242
|
+
low = low + 1 | 0;
|
|
2243
|
+
} else {
|
|
2244
|
+
low = 0;
|
|
2245
|
+
high = high + 1 | 0;
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
if (val >= 18446744073709552e3 || val < -18446744073709552e3) {
|
|
2249
|
+
throw new Error("Given varint doesn't fit into 10 bytes");
|
|
2250
|
+
}
|
|
2251
|
+
pbf.realloc(10);
|
|
2252
|
+
writeBigVarintLow(low, high, pbf);
|
|
2253
|
+
writeBigVarintHigh(high, pbf);
|
|
2254
|
+
}
|
|
2255
|
+
function writeBigVarintLow(low, high, pbf) {
|
|
2256
|
+
pbf.buf[pbf.pos++] = low & 127 | 128;
|
|
2257
|
+
low >>>= 7;
|
|
2258
|
+
pbf.buf[pbf.pos++] = low & 127 | 128;
|
|
2259
|
+
low >>>= 7;
|
|
2260
|
+
pbf.buf[pbf.pos++] = low & 127 | 128;
|
|
2261
|
+
low >>>= 7;
|
|
2262
|
+
pbf.buf[pbf.pos++] = low & 127 | 128;
|
|
2263
|
+
low >>>= 7;
|
|
2264
|
+
pbf.buf[pbf.pos] = low & 127;
|
|
2265
|
+
}
|
|
2266
|
+
function writeBigVarintHigh(high, pbf) {
|
|
2267
|
+
const lsb = (high & 7) << 4;
|
|
2268
|
+
pbf.buf[pbf.pos++] |= lsb | ((high >>>= 3) ? 128 : 0);
|
|
2269
|
+
if (!high) return;
|
|
2270
|
+
pbf.buf[pbf.pos++] = high & 127 | ((high >>>= 7) ? 128 : 0);
|
|
2271
|
+
if (!high) return;
|
|
2272
|
+
pbf.buf[pbf.pos++] = high & 127 | ((high >>>= 7) ? 128 : 0);
|
|
2273
|
+
if (!high) return;
|
|
2274
|
+
pbf.buf[pbf.pos++] = high & 127 | ((high >>>= 7) ? 128 : 0);
|
|
2275
|
+
if (!high) return;
|
|
2276
|
+
pbf.buf[pbf.pos++] = high & 127 | ((high >>>= 7) ? 128 : 0);
|
|
2277
|
+
if (!high) return;
|
|
2278
|
+
pbf.buf[pbf.pos++] = high & 127;
|
|
2279
|
+
}
|
|
2280
|
+
function makeRoomForExtraLength(startPos, len, pbf) {
|
|
2281
|
+
const extraLen = len <= 16383 ? 1 : len <= 2097151 ? 2 : len <= 268435455 ? 3 : Math.floor(Math.log(len) / (Math.LN2 * 7));
|
|
2282
|
+
pbf.realloc(extraLen);
|
|
2283
|
+
for (let i2 = pbf.pos - 1; i2 >= startPos; i2--) pbf.buf[i2 + extraLen] = pbf.buf[i2];
|
|
2284
|
+
}
|
|
2285
|
+
function writePackedVarint(arr, pbf) {
|
|
2286
|
+
for (let i2 = 0; i2 < arr.length; i2++) pbf.writeVarint(arr[i2]);
|
|
2287
|
+
}
|
|
2288
|
+
function writePackedSVarint(arr, pbf) {
|
|
2289
|
+
for (let i2 = 0; i2 < arr.length; i2++) pbf.writeSVarint(arr[i2]);
|
|
2290
|
+
}
|
|
2291
|
+
function writePackedFloat(arr, pbf) {
|
|
2292
|
+
for (let i2 = 0; i2 < arr.length; i2++) pbf.writeFloat(arr[i2]);
|
|
2293
|
+
}
|
|
2294
|
+
function writePackedDouble(arr, pbf) {
|
|
2295
|
+
for (let i2 = 0; i2 < arr.length; i2++) pbf.writeDouble(arr[i2]);
|
|
2296
|
+
}
|
|
2297
|
+
function writePackedBoolean(arr, pbf) {
|
|
2298
|
+
for (let i2 = 0; i2 < arr.length; i2++) pbf.writeBoolean(arr[i2]);
|
|
2299
|
+
}
|
|
2300
|
+
function writePackedFixed32(arr, pbf) {
|
|
2301
|
+
for (let i2 = 0; i2 < arr.length; i2++) pbf.writeFixed32(arr[i2]);
|
|
2302
|
+
}
|
|
2303
|
+
function writePackedSFixed32(arr, pbf) {
|
|
2304
|
+
for (let i2 = 0; i2 < arr.length; i2++) pbf.writeSFixed32(arr[i2]);
|
|
2305
|
+
}
|
|
2306
|
+
function writePackedFixed64(arr, pbf) {
|
|
2307
|
+
for (let i2 = 0; i2 < arr.length; i2++) pbf.writeFixed64(arr[i2]);
|
|
2308
|
+
}
|
|
2309
|
+
function writePackedSFixed64(arr, pbf) {
|
|
2310
|
+
for (let i2 = 0; i2 < arr.length; i2++) pbf.writeSFixed64(arr[i2]);
|
|
2311
|
+
}
|
|
2312
|
+
function readUtf8(buf, pos, end) {
|
|
2313
|
+
let str = "";
|
|
2314
|
+
let i2 = pos;
|
|
2315
|
+
while (i2 < end) {
|
|
2316
|
+
const b0 = buf[i2];
|
|
2317
|
+
let c = null;
|
|
2318
|
+
let bytesPerSequence = b0 > 239 ? 4 : b0 > 223 ? 3 : b0 > 191 ? 2 : 1;
|
|
2319
|
+
if (i2 + bytesPerSequence > end) break;
|
|
2320
|
+
let b1, b2, b3;
|
|
2321
|
+
if (bytesPerSequence === 1) {
|
|
2322
|
+
if (b0 < 128) {
|
|
2323
|
+
c = b0;
|
|
2324
|
+
}
|
|
2325
|
+
} else if (bytesPerSequence === 2) {
|
|
2326
|
+
b1 = buf[i2 + 1];
|
|
2327
|
+
if ((b1 & 192) === 128) {
|
|
2328
|
+
c = (b0 & 31) << 6 | b1 & 63;
|
|
2329
|
+
if (c <= 127) {
|
|
2330
|
+
c = null;
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
} else if (bytesPerSequence === 3) {
|
|
2334
|
+
b1 = buf[i2 + 1];
|
|
2335
|
+
b2 = buf[i2 + 2];
|
|
2336
|
+
if ((b1 & 192) === 128 && (b2 & 192) === 128) {
|
|
2337
|
+
c = (b0 & 15) << 12 | (b1 & 63) << 6 | b2 & 63;
|
|
2338
|
+
if (c <= 2047 || c >= 55296 && c <= 57343) {
|
|
2339
|
+
c = null;
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
} else if (bytesPerSequence === 4) {
|
|
2343
|
+
b1 = buf[i2 + 1];
|
|
2344
|
+
b2 = buf[i2 + 2];
|
|
2345
|
+
b3 = buf[i2 + 3];
|
|
2346
|
+
if ((b1 & 192) === 128 && (b2 & 192) === 128 && (b3 & 192) === 128) {
|
|
2347
|
+
c = (b0 & 15) << 18 | (b1 & 63) << 12 | (b2 & 63) << 6 | b3 & 63;
|
|
2348
|
+
if (c <= 65535 || c >= 1114112) {
|
|
2349
|
+
c = null;
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
if (c === null) {
|
|
2354
|
+
c = 65533;
|
|
2355
|
+
bytesPerSequence = 1;
|
|
2356
|
+
} else if (c > 65535) {
|
|
2357
|
+
c -= 65536;
|
|
2358
|
+
str += String.fromCharCode(c >>> 10 & 1023 | 55296);
|
|
2359
|
+
c = 56320 | c & 1023;
|
|
2360
|
+
}
|
|
2361
|
+
str += String.fromCharCode(c);
|
|
2362
|
+
i2 += bytesPerSequence;
|
|
2363
|
+
}
|
|
2364
|
+
return str;
|
|
2365
|
+
}
|
|
2366
|
+
function writeUtf8(buf, str, pos) {
|
|
2367
|
+
for (let i2 = 0, c, lead; i2 < str.length; i2++) {
|
|
2368
|
+
c = str.charCodeAt(i2);
|
|
2369
|
+
if (c > 55295 && c < 57344) {
|
|
2370
|
+
if (lead) {
|
|
2371
|
+
if (c < 56320) {
|
|
2372
|
+
buf[pos++] = 239;
|
|
2373
|
+
buf[pos++] = 191;
|
|
2374
|
+
buf[pos++] = 189;
|
|
2375
|
+
lead = c;
|
|
2376
|
+
continue;
|
|
2377
|
+
} else {
|
|
2378
|
+
c = lead - 55296 << 10 | c - 56320 | 65536;
|
|
2379
|
+
lead = null;
|
|
2380
|
+
}
|
|
2381
|
+
} else {
|
|
2382
|
+
if (c > 56319 || i2 + 1 === str.length) {
|
|
2383
|
+
buf[pos++] = 239;
|
|
2384
|
+
buf[pos++] = 191;
|
|
2385
|
+
buf[pos++] = 189;
|
|
2386
|
+
} else {
|
|
2387
|
+
lead = c;
|
|
2388
|
+
}
|
|
2389
|
+
continue;
|
|
2390
|
+
}
|
|
2391
|
+
} else if (lead) {
|
|
2392
|
+
buf[pos++] = 239;
|
|
2393
|
+
buf[pos++] = 191;
|
|
2394
|
+
buf[pos++] = 189;
|
|
2395
|
+
lead = null;
|
|
2396
|
+
}
|
|
2397
|
+
if (c < 128) {
|
|
2398
|
+
buf[pos++] = c;
|
|
2399
|
+
} else {
|
|
2400
|
+
if (c < 2048) {
|
|
2401
|
+
buf[pos++] = c >> 6 | 192;
|
|
2402
|
+
} else {
|
|
2403
|
+
if (c < 65536) {
|
|
2404
|
+
buf[pos++] = c >> 12 | 224;
|
|
2405
|
+
} else {
|
|
2406
|
+
buf[pos++] = c >> 18 | 240;
|
|
2407
|
+
buf[pos++] = c >> 12 & 63 | 128;
|
|
2408
|
+
}
|
|
2409
|
+
buf[pos++] = c >> 6 & 63 | 128;
|
|
2410
|
+
}
|
|
2411
|
+
buf[pos++] = c & 63 | 128;
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
return pos;
|
|
2415
|
+
}
|
|
2416
|
+
var DEFAULT_CACHE_SIZE = 64;
|
|
2417
|
+
function toIndex(z2, x22, y) {
|
|
2418
|
+
return `${x22}:${y}:${z2}`;
|
|
2419
|
+
}
|
|
2420
|
+
function parseTile(buffer) {
|
|
2421
|
+
const tile = new VectorTile(new Pbf(buffer));
|
|
2422
|
+
const result = {};
|
|
2423
|
+
for (const [layerName, layer] of Object.entries(tile.layers)) {
|
|
2424
|
+
const features = [];
|
|
2425
|
+
for (let i2 = 0; i2 < layer.length; i2++) {
|
|
2426
|
+
const feature = layer.feature(i2);
|
|
2427
|
+
features.push({
|
|
2428
|
+
id: feature.id,
|
|
2429
|
+
type: feature.type,
|
|
2430
|
+
properties: feature.properties,
|
|
2431
|
+
geometry: feature.loadGeometry(),
|
|
2432
|
+
extent: layer.extent
|
|
2433
|
+
});
|
|
2434
|
+
}
|
|
2435
|
+
result[layerName] = features;
|
|
2436
|
+
}
|
|
2437
|
+
return result;
|
|
2438
|
+
}
|
|
2439
|
+
function transformForOverzoom(corrections, scale, offsetX, offsetY) {
|
|
2440
|
+
const result = {};
|
|
2441
|
+
for (const [layerName, features] of Object.entries(corrections)) {
|
|
2442
|
+
result[layerName] = features.map((feature) => {
|
|
2443
|
+
const extent = feature.extent;
|
|
2444
|
+
const childExtent = extent / scale;
|
|
2445
|
+
const startX = offsetX * childExtent;
|
|
2446
|
+
const startY = offsetY * childExtent;
|
|
2447
|
+
const newGeometry = feature.geometry.map((ring) => {
|
|
2448
|
+
return ring.map((point) => {
|
|
2449
|
+
const x22 = (point.x - startX) * scale;
|
|
2450
|
+
const y = (point.y - startY) * scale;
|
|
2451
|
+
return { x: x22, y };
|
|
2452
|
+
});
|
|
2453
|
+
});
|
|
2454
|
+
return {
|
|
2455
|
+
...feature,
|
|
2456
|
+
geometry: newGeometry,
|
|
2457
|
+
// Keep original extent since we scaled coordinates to match
|
|
2458
|
+
extent
|
|
2459
|
+
};
|
|
2460
|
+
});
|
|
2461
|
+
}
|
|
2462
|
+
return result;
|
|
2463
|
+
}
|
|
2464
|
+
var CorrectionsSource = class {
|
|
2465
|
+
/**
|
|
2466
|
+
* @param {string} pmtilesUrl - URL to the PMTiles file
|
|
2467
|
+
* @param {Object} [options] - Options
|
|
2468
|
+
* @param {number} [options.cacheSize=64] - Maximum number of tiles to cache
|
|
2469
|
+
* @param {number} [options.maxDataZoom] - Maximum zoom level in PMTiles (auto-detected if not provided)
|
|
2470
|
+
*/
|
|
2471
|
+
constructor(pmtilesUrl, options = {}) {
|
|
2472
|
+
this.pmtilesUrl = pmtilesUrl;
|
|
2473
|
+
this.pmtiles = new x(pmtilesUrl);
|
|
2474
|
+
this.cacheSize = options.cacheSize ?? DEFAULT_CACHE_SIZE;
|
|
2475
|
+
this.maxDataZoom = options.maxDataZoom;
|
|
2476
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
2477
|
+
this.inflight = /* @__PURE__ */ new Map();
|
|
2478
|
+
}
|
|
2479
|
+
/**
|
|
2480
|
+
* Get the PMTiles source object.
|
|
2481
|
+
* @returns {PMTiles}
|
|
2482
|
+
*/
|
|
2483
|
+
getSource() {
|
|
2484
|
+
return this.pmtiles;
|
|
2485
|
+
}
|
|
2486
|
+
/**
|
|
2487
|
+
* Clear the tile cache.
|
|
2488
|
+
*/
|
|
2489
|
+
clearCache() {
|
|
2490
|
+
this.cache.clear();
|
|
2491
|
+
this.inflight.clear();
|
|
2492
|
+
}
|
|
2493
|
+
/**
|
|
2494
|
+
* Auto-detect max zoom from PMTiles metadata.
|
|
2495
|
+
* @returns {Promise<number>}
|
|
2496
|
+
* @private
|
|
2497
|
+
*/
|
|
2498
|
+
async _getMaxDataZoom() {
|
|
2499
|
+
if (this.maxDataZoom !== void 0) {
|
|
2500
|
+
return this.maxDataZoom;
|
|
2501
|
+
}
|
|
2502
|
+
const header = await this.pmtiles.getHeader();
|
|
2503
|
+
this.maxDataZoom = header.maxZoom;
|
|
2504
|
+
return this.maxDataZoom;
|
|
2505
|
+
}
|
|
2506
|
+
/**
|
|
2507
|
+
* Fetch and parse a tile from PMTiles.
|
|
2508
|
+
* Implements in-flight request deduplication from protomaps-leaflet.
|
|
2509
|
+
* @param {number} z
|
|
2510
|
+
* @param {number} x
|
|
2511
|
+
* @param {number} y
|
|
2512
|
+
* @returns {Promise<Object<string, Array>>}
|
|
2513
|
+
* @private
|
|
2514
|
+
*/
|
|
2515
|
+
async _fetchTile(z2, x22, y) {
|
|
2516
|
+
const idx = toIndex(z2, x22, y);
|
|
2517
|
+
return new Promise((resolve, reject) => {
|
|
2518
|
+
const entry = this.cache.get(idx);
|
|
2519
|
+
if (entry) {
|
|
2520
|
+
entry.used = performance.now();
|
|
2521
|
+
resolve(entry.data);
|
|
2522
|
+
return;
|
|
2523
|
+
}
|
|
2524
|
+
const ifentry = this.inflight.get(idx);
|
|
2525
|
+
if (ifentry) {
|
|
2526
|
+
ifentry.push({ resolve, reject });
|
|
2527
|
+
return;
|
|
2528
|
+
}
|
|
2529
|
+
this.inflight.set(idx, []);
|
|
2530
|
+
this.pmtiles.getZxy(z2, x22, y).then((result) => {
|
|
2531
|
+
let data;
|
|
2532
|
+
if (result) {
|
|
2533
|
+
data = parseTile(result.data);
|
|
2534
|
+
} else {
|
|
2535
|
+
data = {};
|
|
2536
|
+
}
|
|
2537
|
+
this.cache.set(idx, { used: performance.now(), data });
|
|
2538
|
+
const ifentry2 = this.inflight.get(idx);
|
|
2539
|
+
if (ifentry2) {
|
|
2540
|
+
for (const waiter of ifentry2) {
|
|
2541
|
+
waiter.resolve(data);
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2544
|
+
this.inflight.delete(idx);
|
|
2545
|
+
resolve(data);
|
|
2546
|
+
if (this.cache.size > this.cacheSize) {
|
|
2547
|
+
let minUsed = Infinity;
|
|
2548
|
+
let minKey = void 0;
|
|
2549
|
+
this.cache.forEach((value, key) => {
|
|
2550
|
+
if (value.used < minUsed) {
|
|
2551
|
+
minUsed = value.used;
|
|
2552
|
+
minKey = key;
|
|
2553
|
+
}
|
|
2554
|
+
});
|
|
2555
|
+
if (minKey) {
|
|
2556
|
+
this.cache.delete(minKey);
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
}).catch((e) => {
|
|
2560
|
+
const ifentry2 = this.inflight.get(idx);
|
|
2561
|
+
if (ifentry2) {
|
|
2562
|
+
for (const waiter of ifentry2) {
|
|
2563
|
+
waiter.reject(e);
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
this.inflight.delete(idx);
|
|
2567
|
+
reject(e);
|
|
2568
|
+
});
|
|
2569
|
+
});
|
|
2570
|
+
}
|
|
2571
|
+
/**
|
|
2572
|
+
* Get corrections for a tile as a dict of layer name to features.
|
|
2573
|
+
* Supports overzoom beyond maxDataZoom by scaling parent tile data.
|
|
2574
|
+
* @param {number} z - Zoom level
|
|
2575
|
+
* @param {number} x - Tile X coordinate
|
|
2576
|
+
* @param {number} y - Tile Y coordinate
|
|
2577
|
+
* @returns {Promise<Object<string, Array>>} Map of layer name to array of features
|
|
2578
|
+
*/
|
|
2579
|
+
async get(z2, x22, y) {
|
|
2580
|
+
const maxDataZoom = await this._getMaxDataZoom();
|
|
2581
|
+
if (z2 > maxDataZoom) {
|
|
2582
|
+
const zoomDiff = z2 - maxDataZoom;
|
|
2583
|
+
const scale = 1 << zoomDiff;
|
|
2584
|
+
const parentX = Math.floor(x22 / scale);
|
|
2585
|
+
const parentY = Math.floor(y / scale);
|
|
2586
|
+
const offsetX = x22 % scale;
|
|
2587
|
+
const offsetY = y % scale;
|
|
2588
|
+
const corrections = await this._fetchTile(maxDataZoom, parentX, parentY);
|
|
2589
|
+
if (Object.keys(corrections).length > 0) {
|
|
2590
|
+
return transformForOverzoom(corrections, scale, offsetX, offsetY);
|
|
2591
|
+
}
|
|
2592
|
+
return {};
|
|
2593
|
+
}
|
|
2594
|
+
return await this._fetchTile(z2, x22, y);
|
|
2595
|
+
}
|
|
2596
|
+
};
|
|
2597
|
+
var MIN_LINE_WIDTH = 0.5;
|
|
2598
|
+
function getLineWidth(zoom, lineWidthStops) {
|
|
2599
|
+
const zooms = Object.keys(lineWidthStops).map(Number).sort((a, b2) => a - b2);
|
|
2600
|
+
if (lineWidthStops[zoom] !== void 0) {
|
|
2601
|
+
return lineWidthStops[zoom];
|
|
2602
|
+
}
|
|
2603
|
+
if (zoom < zooms[0]) {
|
|
2604
|
+
const z1 = zooms[0];
|
|
2605
|
+
const z2 = zooms[1];
|
|
2606
|
+
const w1 = lineWidthStops[z1];
|
|
2607
|
+
const w2 = lineWidthStops[z2];
|
|
2608
|
+
const slope = (w2 - w1) / (z2 - z1);
|
|
2609
|
+
return Math.max(MIN_LINE_WIDTH, w1 + slope * (zoom - z1));
|
|
2610
|
+
}
|
|
2611
|
+
if (zoom > zooms[zooms.length - 1]) {
|
|
2612
|
+
const z1 = zooms[zooms.length - 2];
|
|
2613
|
+
const z2 = zooms[zooms.length - 1];
|
|
2614
|
+
const w1 = lineWidthStops[z1];
|
|
2615
|
+
const w2 = lineWidthStops[z2];
|
|
2616
|
+
const slope = (w2 - w1) / (z2 - z1);
|
|
2617
|
+
return Math.max(MIN_LINE_WIDTH, w2 + slope * (zoom - z2));
|
|
2618
|
+
}
|
|
2619
|
+
for (let i2 = 0; i2 < zooms.length - 1; i2++) {
|
|
2620
|
+
if (zoom > zooms[i2] && zoom < zooms[i2 + 1]) {
|
|
2621
|
+
const z1 = zooms[i2];
|
|
2622
|
+
const z2 = zooms[i2 + 1];
|
|
2623
|
+
const w1 = lineWidthStops[z1];
|
|
2624
|
+
const w2 = lineWidthStops[z2];
|
|
2625
|
+
const t = (zoom - z1) / (z2 - z1);
|
|
2626
|
+
return w1 + t * (w2 - w1);
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
return 1;
|
|
2630
|
+
}
|
|
2631
|
+
function getFeaturesBoundingBox(features, tileSize, padding = 0) {
|
|
2632
|
+
let minX = Infinity, minY = Infinity;
|
|
2633
|
+
let maxX = -Infinity, maxY = -Infinity;
|
|
2634
|
+
for (const feature of features) {
|
|
2635
|
+
const scale = tileSize / feature.extent;
|
|
2636
|
+
for (const ring of feature.geometry) {
|
|
2637
|
+
for (const point of ring) {
|
|
2638
|
+
const px = point.x * scale;
|
|
2639
|
+
const py = point.y * scale;
|
|
2640
|
+
if (px < minX) minX = px;
|
|
2641
|
+
if (py < minY) minY = py;
|
|
2642
|
+
if (px > maxX) maxX = px;
|
|
2643
|
+
if (py > maxY) maxY = py;
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
return {
|
|
2648
|
+
minX: Math.max(0, Math.floor(minX - padding)),
|
|
2649
|
+
minY: Math.max(0, Math.floor(minY - padding)),
|
|
2650
|
+
maxX: Math.min(tileSize, Math.ceil(maxX + padding)),
|
|
2651
|
+
maxY: Math.min(tileSize, Math.ceil(maxY + padding))
|
|
2652
|
+
};
|
|
2653
|
+
}
|
|
2654
|
+
function medianFromHistogram(histogram, values) {
|
|
2655
|
+
const count = values.length;
|
|
2656
|
+
if (count === 0) return 0;
|
|
2657
|
+
histogram.fill(0);
|
|
2658
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
2659
|
+
histogram[values[i2]]++;
|
|
2660
|
+
}
|
|
2661
|
+
const medianPos = count >> 1;
|
|
2662
|
+
let cumulative = 0;
|
|
2663
|
+
for (let v2 = 0; v2 < 256; v2++) {
|
|
2664
|
+
cumulative += histogram[v2];
|
|
2665
|
+
if (cumulative > medianPos) {
|
|
2666
|
+
return v2;
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
return 0;
|
|
2670
|
+
}
|
|
2671
|
+
function applyMedianBlurAlongPath(ctx, features, lineWidth, tileSize, maskCanvas) {
|
|
2672
|
+
if (features.length === 0) return;
|
|
2673
|
+
const imageData = ctx.getImageData(0, 0, tileSize, tileSize);
|
|
2674
|
+
const data = imageData.data;
|
|
2675
|
+
const width = tileSize;
|
|
2676
|
+
const height = tileSize;
|
|
2677
|
+
if (!maskCanvas || maskCanvas.width !== tileSize || maskCanvas.height !== tileSize) {
|
|
2678
|
+
maskCanvas = new OffscreenCanvas(tileSize, tileSize);
|
|
2679
|
+
}
|
|
2680
|
+
const maskCtx = maskCanvas.getContext("2d");
|
|
2681
|
+
maskCtx.fillStyle = "black";
|
|
2682
|
+
maskCtx.fillRect(0, 0, tileSize, tileSize);
|
|
2683
|
+
maskCtx.strokeStyle = "white";
|
|
2684
|
+
maskCtx.lineWidth = lineWidth;
|
|
2685
|
+
maskCtx.lineCap = "round";
|
|
2686
|
+
maskCtx.lineJoin = "round";
|
|
2687
|
+
for (const feature of features) {
|
|
2688
|
+
const scale = tileSize / feature.extent;
|
|
2689
|
+
for (const ring of feature.geometry) {
|
|
2690
|
+
if (ring.length === 0) continue;
|
|
2691
|
+
maskCtx.beginPath();
|
|
2692
|
+
maskCtx.moveTo(ring[0].x * scale, ring[0].y * scale);
|
|
2693
|
+
for (let i2 = 1; i2 < ring.length; i2++) {
|
|
2694
|
+
maskCtx.lineTo(ring[i2].x * scale, ring[i2].y * scale);
|
|
2695
|
+
}
|
|
2696
|
+
maskCtx.stroke();
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2699
|
+
const maskData = maskCtx.getImageData(0, 0, tileSize, tileSize).data;
|
|
2700
|
+
const radius = Math.max(2, Math.ceil(lineWidth / 2) + 1);
|
|
2701
|
+
const output = new Uint8ClampedArray(data);
|
|
2702
|
+
const bbox = getFeaturesBoundingBox(features, tileSize, radius);
|
|
2703
|
+
const histogram = new Uint16Array(256);
|
|
2704
|
+
const rValues = [];
|
|
2705
|
+
const gValues = [];
|
|
2706
|
+
const bValues = [];
|
|
2707
|
+
for (let y = bbox.minY; y < bbox.maxY; y++) {
|
|
2708
|
+
for (let x22 = bbox.minX; x22 < bbox.maxX; x22++) {
|
|
2709
|
+
const maskIdx = (y * width + x22) * 4;
|
|
2710
|
+
if (maskData[maskIdx] < 128) continue;
|
|
2711
|
+
rValues.length = 0;
|
|
2712
|
+
gValues.length = 0;
|
|
2713
|
+
bValues.length = 0;
|
|
2714
|
+
for (let dy = -radius; dy <= radius; dy++) {
|
|
2715
|
+
for (let dx = -radius; dx <= radius; dx++) {
|
|
2716
|
+
const nx = x22 + dx;
|
|
2717
|
+
const ny = y + dy;
|
|
2718
|
+
if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;
|
|
2719
|
+
const nMaskIdx = (ny * width + nx) * 4;
|
|
2720
|
+
if (maskData[nMaskIdx] >= 128) continue;
|
|
2721
|
+
const nIdx = nMaskIdx;
|
|
2722
|
+
rValues.push(data[nIdx]);
|
|
2723
|
+
gValues.push(data[nIdx + 1]);
|
|
2724
|
+
bValues.push(data[nIdx + 2]);
|
|
2725
|
+
}
|
|
2726
|
+
}
|
|
2727
|
+
if (rValues.length >= 3) {
|
|
2728
|
+
const idx = maskIdx;
|
|
2729
|
+
output[idx] = medianFromHistogram(histogram, rValues);
|
|
2730
|
+
output[idx + 1] = medianFromHistogram(histogram, gValues);
|
|
2731
|
+
output[idx + 2] = medianFromHistogram(histogram, bValues);
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
ctx.putImageData(new ImageData(output, width, height), 0, 0);
|
|
2736
|
+
}
|
|
2737
|
+
function isAtExtentEdge(coord, extent, tolerance = 0.01) {
|
|
2738
|
+
const tol = extent * tolerance;
|
|
2739
|
+
return coord <= tol || coord >= extent - tol;
|
|
2740
|
+
}
|
|
2741
|
+
function extendFeaturesEnds(features, extensionLength) {
|
|
2742
|
+
return features.map((feature) => {
|
|
2743
|
+
const extent = feature.extent;
|
|
2744
|
+
const newGeometry = feature.geometry.map((ring) => {
|
|
2745
|
+
if (ring.length < 2) return ring;
|
|
2746
|
+
const newRing = [...ring];
|
|
2747
|
+
const start = ring[0];
|
|
2748
|
+
const second = ring[1];
|
|
2749
|
+
if (!isAtExtentEdge(start.x, extent) && !isAtExtentEdge(start.y, extent)) {
|
|
2750
|
+
const dx = start.x - second.x;
|
|
2751
|
+
const dy = start.y - second.y;
|
|
2752
|
+
const len = Math.sqrt(dx * dx + dy * dy);
|
|
2753
|
+
if (len > 0) {
|
|
2754
|
+
const ux = dx / len;
|
|
2755
|
+
const uy = dy / len;
|
|
2756
|
+
newRing[0] = {
|
|
2757
|
+
x: start.x + ux * extensionLength,
|
|
2758
|
+
y: start.y + uy * extensionLength
|
|
2759
|
+
};
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
const lastIdx = ring.length - 1;
|
|
2763
|
+
const end = ring[lastIdx];
|
|
2764
|
+
const prev = ring[lastIdx - 1];
|
|
2765
|
+
if (!isAtExtentEdge(end.x, extent) && !isAtExtentEdge(end.y, extent)) {
|
|
2766
|
+
const dx = end.x - prev.x;
|
|
2767
|
+
const dy = end.y - prev.y;
|
|
2768
|
+
const len = Math.sqrt(dx * dx + dy * dy);
|
|
2769
|
+
if (len > 0) {
|
|
2770
|
+
const ux = dx / len;
|
|
2771
|
+
const uy = dy / len;
|
|
2772
|
+
newRing[lastIdx] = {
|
|
2773
|
+
x: end.x + ux * extensionLength,
|
|
2774
|
+
y: end.y + uy * extensionLength
|
|
2775
|
+
};
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
return newRing;
|
|
2779
|
+
});
|
|
2780
|
+
return { ...feature, geometry: newGeometry };
|
|
2781
|
+
});
|
|
2782
|
+
}
|
|
2783
|
+
function drawFeatures(ctx, features, color, lineWidth, tileSize, dashArray, alpha) {
|
|
2784
|
+
const prevAlpha = ctx.globalAlpha;
|
|
2785
|
+
if (alpha !== void 0) {
|
|
2786
|
+
ctx.globalAlpha = alpha;
|
|
2787
|
+
}
|
|
2788
|
+
ctx.strokeStyle = color;
|
|
2789
|
+
ctx.lineWidth = lineWidth;
|
|
2790
|
+
ctx.lineJoin = "round";
|
|
2791
|
+
if (dashArray && dashArray.length > 0) {
|
|
2792
|
+
ctx.setLineDash(dashArray);
|
|
2793
|
+
ctx.lineCap = "butt";
|
|
2794
|
+
} else {
|
|
2795
|
+
ctx.setLineDash([]);
|
|
2796
|
+
ctx.lineCap = "round";
|
|
2797
|
+
}
|
|
2798
|
+
for (const feature of features) {
|
|
2799
|
+
const scale = tileSize / feature.extent;
|
|
2800
|
+
for (const ring of feature.geometry) {
|
|
2801
|
+
if (ring.length === 0) continue;
|
|
2802
|
+
ctx.beginPath();
|
|
2803
|
+
ctx.moveTo(ring[0].x * scale, ring[0].y * scale);
|
|
2804
|
+
for (let i2 = 1; i2 < ring.length; i2++) {
|
|
2805
|
+
ctx.lineTo(ring[i2].x * scale, ring[i2].y * scale);
|
|
2806
|
+
}
|
|
2807
|
+
ctx.stroke();
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
if (alpha !== void 0) {
|
|
2811
|
+
ctx.globalAlpha = prevAlpha;
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
var BoundaryCorrector = class {
|
|
2815
|
+
/**
|
|
2816
|
+
* @param {string} pmtilesUrl - URL to the PMTiles file
|
|
2817
|
+
* @param {Object} [options] - Options
|
|
2818
|
+
* @param {number} [options.cacheSize=64] - Maximum number of tiles to cache
|
|
2819
|
+
* @param {number} [options.maxDataZoom] - Maximum zoom level in PMTiles (auto-detected if not provided)
|
|
2820
|
+
*/
|
|
2821
|
+
constructor(pmtilesUrl, options = {}) {
|
|
2822
|
+
this.correctionsSource = new CorrectionsSource(pmtilesUrl, options);
|
|
2823
|
+
this._maskCanvas = null;
|
|
2824
|
+
}
|
|
2825
|
+
/**
|
|
2826
|
+
* Get the PMTiles source object.
|
|
2827
|
+
* @returns {PMTiles}
|
|
2828
|
+
*/
|
|
2829
|
+
getSource() {
|
|
2830
|
+
return this.correctionsSource.getSource();
|
|
2831
|
+
}
|
|
2832
|
+
/**
|
|
2833
|
+
* Clear the tile cache.
|
|
2834
|
+
*/
|
|
2835
|
+
clearCache() {
|
|
2836
|
+
this.correctionsSource.clearCache();
|
|
2837
|
+
}
|
|
2838
|
+
/**
|
|
2839
|
+
* Get corrections for a tile as a dict of layer name to features.
|
|
2840
|
+
* Supports overzoom beyond maxDataZoom by scaling parent tile data.
|
|
2841
|
+
* @param {number} z - Zoom level
|
|
2842
|
+
* @param {number} x - Tile X coordinate
|
|
2843
|
+
* @param {number} y - Tile Y coordinate
|
|
2844
|
+
* @returns {Promise<Object<string, Array>>} Map of layer name to array of features
|
|
2845
|
+
*/
|
|
2846
|
+
async getCorrections(z2, x22, y) {
|
|
2847
|
+
return await this.correctionsSource.get(z2, x22, y);
|
|
2848
|
+
}
|
|
2849
|
+
/**
|
|
2850
|
+
* Apply corrections to a raster tile.
|
|
2851
|
+
* @param {Object<string, Array>} corrections - Feature map from getCorrections
|
|
2852
|
+
* @param {ArrayBuffer} rasterTile - The original raster tile as ArrayBuffer
|
|
2853
|
+
* @param {Object} layerConfig - Layer configuration with colors and styles
|
|
2854
|
+
* @param {number} zoom - Current zoom level
|
|
2855
|
+
* @param {number} [tileSize=256] - Size of the tile in pixels
|
|
2856
|
+
* @returns {Promise<ArrayBuffer>} The corrected tile as ArrayBuffer (PNG)
|
|
2857
|
+
*/
|
|
2858
|
+
async fixTile(corrections, rasterTile, layerConfig, zoom, tileSize = 256) {
|
|
2859
|
+
const {
|
|
2860
|
+
startZoom = 0,
|
|
2861
|
+
zoomThreshold,
|
|
2862
|
+
lineWidthStops,
|
|
2863
|
+
delWidthFactor
|
|
2864
|
+
} = layerConfig;
|
|
2865
|
+
if (zoom < startZoom) {
|
|
2866
|
+
return rasterTile;
|
|
2867
|
+
}
|
|
2868
|
+
let activeLineStyles;
|
|
2869
|
+
if (layerConfig.getLineStylesForZoom) {
|
|
2870
|
+
activeLineStyles = layerConfig.getLineStylesForZoom(zoom);
|
|
2871
|
+
} else {
|
|
2872
|
+
const allStyles = layerConfig.lineStyles || [];
|
|
2873
|
+
activeLineStyles = allStyles.filter((style) => {
|
|
2874
|
+
const styleStart = style.startZoom ?? startZoom;
|
|
2875
|
+
const styleEnd = style.endZoom ?? Infinity;
|
|
2876
|
+
return zoom >= styleStart && zoom <= styleEnd;
|
|
2877
|
+
});
|
|
2878
|
+
}
|
|
2879
|
+
const useOsm = zoom >= zoomThreshold;
|
|
2880
|
+
const addLayerName = useOsm ? "to-add-osm" : "to-add-ne";
|
|
2881
|
+
const delLayerName = useOsm ? "to-del-osm" : "to-del-ne";
|
|
2882
|
+
const canvas = new OffscreenCanvas(tileSize, tileSize);
|
|
2883
|
+
const ctx = canvas.getContext("2d");
|
|
2884
|
+
const blob = new Blob([rasterTile]);
|
|
2885
|
+
const imageBitmap = await createImageBitmap(blob);
|
|
2886
|
+
ctx.drawImage(imageBitmap, 0, 0, tileSize, tileSize);
|
|
2887
|
+
const baseLineWidth = getLineWidth(zoom, lineWidthStops);
|
|
2888
|
+
const maxWidthFraction = activeLineStyles.length > 0 ? Math.max(...activeLineStyles.map((s) => s.widthFraction ?? 1)) : 1;
|
|
2889
|
+
const delLineWidth = baseLineWidth * maxWidthFraction * delWidthFactor;
|
|
2890
|
+
const delFeatures = corrections[delLayerName] || [];
|
|
2891
|
+
if (delFeatures.length > 0) {
|
|
2892
|
+
if (!this._maskCanvas || this._maskCanvas.width !== tileSize) {
|
|
2893
|
+
this._maskCanvas = new OffscreenCanvas(tileSize, tileSize);
|
|
2894
|
+
}
|
|
2895
|
+
applyMedianBlurAlongPath(ctx, delFeatures, delLineWidth, tileSize, this._maskCanvas);
|
|
2896
|
+
}
|
|
2897
|
+
let addFeatures = corrections[addLayerName] || [];
|
|
2898
|
+
if (addFeatures.length > 0 && activeLineStyles.length > 0) {
|
|
2899
|
+
const extensionFactor = layerConfig.lineExtensionFactor ?? 0.5;
|
|
2900
|
+
if (extensionFactor > 0 && delFeatures.length > 0) {
|
|
2901
|
+
const extent = addFeatures[0]?.extent || 4096;
|
|
2902
|
+
const extensionLength = delLineWidth * extensionFactor / tileSize * extent;
|
|
2903
|
+
addFeatures = extendFeaturesEnds(addFeatures, extensionLength);
|
|
2904
|
+
}
|
|
2905
|
+
for (const style of activeLineStyles) {
|
|
2906
|
+
const { color, widthFraction = 1, dashArray, alpha = 1 } = style;
|
|
2907
|
+
const lineWidth = baseLineWidth * widthFraction;
|
|
2908
|
+
drawFeatures(ctx, addFeatures, color, lineWidth, tileSize, dashArray, alpha);
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
const outputBlob = await canvas.convertToBlob({ type: "image/png" });
|
|
2912
|
+
return outputBlob.arrayBuffer();
|
|
2913
|
+
}
|
|
2914
|
+
/**
|
|
2915
|
+
* Fetch a tile, apply corrections, and return the result.
|
|
2916
|
+
* @param {string} tileUrl - URL of the raster tile
|
|
2917
|
+
* @param {number} z - Zoom level
|
|
2918
|
+
* @param {number} x - Tile X coordinate
|
|
2919
|
+
* @param {number} y - Tile Y coordinate
|
|
2920
|
+
* @param {Object} layerConfig - Layer configuration with colors and styles
|
|
2921
|
+
* @param {Object} [options] - Fetch options
|
|
2922
|
+
* @param {number} [options.tileSize=256] - Tile size in pixels
|
|
2923
|
+
* @param {AbortSignal} [options.signal] - Abort signal for fetch
|
|
2924
|
+
* @param {RequestMode} [options.mode] - Fetch mode (e.g., 'cors')
|
|
2925
|
+
* @returns {Promise<{data: ArrayBuffer, wasFixed: boolean}>}
|
|
2926
|
+
*/
|
|
2927
|
+
async fetchAndFixTile(tileUrl, z2, x22, y, layerConfig, options = {}) {
|
|
2928
|
+
const { tileSize = 256, signal, mode } = options;
|
|
2929
|
+
const fetchOptions = {};
|
|
2930
|
+
if (signal) fetchOptions.signal = signal;
|
|
2931
|
+
if (mode) fetchOptions.mode = mode;
|
|
2932
|
+
if (!layerConfig) {
|
|
2933
|
+
const response = await fetch(tileUrl, fetchOptions);
|
|
2934
|
+
if (!response.ok) throw new Error(`Tile fetch failed: ${response.status}`);
|
|
2935
|
+
return { data: await response.arrayBuffer(), wasFixed: false };
|
|
2936
|
+
}
|
|
2937
|
+
const [tileResult, correctionsResult] = await Promise.allSettled([
|
|
2938
|
+
fetch(tileUrl, fetchOptions).then((r) => {
|
|
2939
|
+
if (!r.ok) throw new Error(`Tile fetch failed: ${r.status}`);
|
|
2940
|
+
return r.arrayBuffer();
|
|
2941
|
+
}),
|
|
2942
|
+
this.getCorrections(z2, x22, y)
|
|
2943
|
+
]);
|
|
2944
|
+
if (signal?.aborted) {
|
|
2945
|
+
throw new DOMException("Aborted", "AbortError");
|
|
2946
|
+
}
|
|
2947
|
+
if (tileResult.status === "rejected") {
|
|
2948
|
+
throw tileResult.reason;
|
|
2949
|
+
}
|
|
2950
|
+
const tileData = tileResult.value;
|
|
2951
|
+
const correctionsFailed = correctionsResult.status === "rejected";
|
|
2952
|
+
const correctionsError = correctionsFailed ? correctionsResult.reason : null;
|
|
2953
|
+
const corrections = correctionsResult.status === "fulfilled" ? correctionsResult.value : {};
|
|
2954
|
+
const hasCorrections = Object.values(corrections).some((arr) => arr && arr.length > 0);
|
|
2955
|
+
if (!hasCorrections) {
|
|
2956
|
+
return { data: tileData, wasFixed: false, correctionsFailed, correctionsError };
|
|
2957
|
+
}
|
|
2958
|
+
const fixedData = await this.fixTile(corrections, tileData, layerConfig, z2, tileSize);
|
|
2959
|
+
return { data: fixedData, wasFixed: true, correctionsFailed: false, correctionsError: null };
|
|
2960
|
+
}
|
|
2961
|
+
};
|
|
2962
|
+
|
|
2963
|
+
// src/index.js
|
|
2964
|
+
var import_data2 = require("@india-boundary-corrector/data");
|
|
2965
|
+
function extendLeaflet(L2) {
|
|
2966
|
+
if (L2.TileLayer.IndiaBoundaryCorrected) {
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2969
|
+
L2.TileLayer.IndiaBoundaryCorrected = L2.TileLayer.extend({
|
|
2970
|
+
options: {
|
|
2971
|
+
pmtilesUrl: null,
|
|
2972
|
+
layerConfig: null,
|
|
2973
|
+
extraLayerConfigs: null
|
|
2974
|
+
},
|
|
2975
|
+
initialize: function(url, options) {
|
|
2976
|
+
L2.TileLayer.prototype.initialize.call(this, url, options);
|
|
2977
|
+
this._pmtilesUrl = this.options.pmtilesUrl ?? (0, import_data.getPmtilesUrl)();
|
|
2978
|
+
this._tileFixer = new BoundaryCorrector(this._pmtilesUrl);
|
|
2979
|
+
this._registry = layerConfigs.createMergedRegistry(this.options.extraLayerConfigs);
|
|
2980
|
+
if (typeof this.options.layerConfig === "string") {
|
|
2981
|
+
this._layerConfig = this._registry.get(this.options.layerConfig);
|
|
2982
|
+
} else if (this.options.layerConfig) {
|
|
2983
|
+
this._layerConfig = this.options.layerConfig;
|
|
2984
|
+
} else {
|
|
2985
|
+
this._layerConfig = this._registry.detectFromTemplates([url]);
|
|
2986
|
+
}
|
|
2987
|
+
if (!this._layerConfig) {
|
|
2988
|
+
console.warn("[L.TileLayer.IndiaBoundaryCorrected] Could not detect layer config from URL. Corrections will not be applied.");
|
|
2989
|
+
}
|
|
2990
|
+
},
|
|
2991
|
+
/**
|
|
2992
|
+
* Handle tile fetching and correction application logic.
|
|
2993
|
+
* This method is extracted for testability.
|
|
2994
|
+
* @param {string} tileUrl - URL of the raster tile
|
|
2995
|
+
* @param {number} z - Zoom level
|
|
2996
|
+
* @param {number} x - Tile X coordinate
|
|
2997
|
+
* @param {number} y - Tile Y coordinate
|
|
2998
|
+
* @param {number} tileSize - Tile size in pixels
|
|
2999
|
+
* @returns {Promise<{blob: Blob, wasFixed: boolean, correctionsFailed: boolean, correctionsError: Error|null}>}
|
|
3000
|
+
* @private
|
|
3001
|
+
*/
|
|
3002
|
+
_fetchAndFixTile: async function(tileUrl, z2, x3, y, tileSize) {
|
|
3003
|
+
const { data, wasFixed, correctionsFailed, correctionsError } = await this._tileFixer.fetchAndFixTile(
|
|
3004
|
+
tileUrl,
|
|
3005
|
+
z2,
|
|
3006
|
+
x3,
|
|
3007
|
+
y,
|
|
3008
|
+
this._layerConfig,
|
|
3009
|
+
{ tileSize }
|
|
3010
|
+
);
|
|
3011
|
+
const blob = new Blob([data], { type: wasFixed ? "image/png" : void 0 });
|
|
3012
|
+
return { blob, wasFixed, correctionsFailed, correctionsError };
|
|
3013
|
+
},
|
|
3014
|
+
createTile: function(coords, done) {
|
|
3015
|
+
const tile = document.createElement("img");
|
|
3016
|
+
tile.alt = "";
|
|
3017
|
+
if (this.options.crossOrigin || this.options.crossOrigin === "") {
|
|
3018
|
+
tile.crossOrigin = this.options.crossOrigin === true ? "" : this.options.crossOrigin;
|
|
3019
|
+
}
|
|
3020
|
+
if (typeof this.options.referrerPolicy === "string") {
|
|
3021
|
+
tile.referrerPolicy = this.options.referrerPolicy;
|
|
3022
|
+
}
|
|
3023
|
+
if (!this._layerConfig) {
|
|
3024
|
+
tile.onload = () => done(null, tile);
|
|
3025
|
+
tile.onerror = (e) => done(e, tile);
|
|
3026
|
+
tile.src = this.getTileUrl(coords);
|
|
3027
|
+
return tile;
|
|
3028
|
+
}
|
|
3029
|
+
const tileUrl = this.getTileUrl(coords);
|
|
3030
|
+
const z2 = coords.z;
|
|
3031
|
+
const x3 = coords.x;
|
|
3032
|
+
const y = coords.y;
|
|
3033
|
+
const tileSize = this.options.tileSize || 256;
|
|
3034
|
+
this._fetchAndFixTile(tileUrl, z2, x3, y, tileSize).then(({ blob, wasFixed, correctionsFailed, correctionsError }) => {
|
|
3035
|
+
if (correctionsFailed) {
|
|
3036
|
+
console.warn("[L.TileLayer.IndiaBoundaryCorrected] Corrections fetch failed:", correctionsError);
|
|
3037
|
+
this.fire("correctionerror", { error: correctionsError, coords: { z: z2, x: x3, y }, tileUrl });
|
|
3038
|
+
}
|
|
3039
|
+
tile.src = URL.createObjectURL(blob);
|
|
3040
|
+
tile.onload = () => {
|
|
3041
|
+
URL.revokeObjectURL(tile.src);
|
|
3042
|
+
done(null, tile);
|
|
3043
|
+
};
|
|
3044
|
+
tile.onerror = (e) => {
|
|
3045
|
+
URL.revokeObjectURL(tile.src);
|
|
3046
|
+
done(e, tile);
|
|
3047
|
+
};
|
|
3048
|
+
}).catch((err2) => {
|
|
3049
|
+
console.warn("[L.TileLayer.IndiaBoundaryCorrected] Tile fetch failed:", err2);
|
|
3050
|
+
done(err2, tile);
|
|
3051
|
+
});
|
|
3052
|
+
return tile;
|
|
3053
|
+
},
|
|
3054
|
+
getTileFixer: function() {
|
|
3055
|
+
return this._tileFixer;
|
|
3056
|
+
},
|
|
3057
|
+
getLayerConfig: function() {
|
|
3058
|
+
return this._layerConfig;
|
|
3059
|
+
}
|
|
3060
|
+
});
|
|
3061
|
+
L2.tileLayer.indiaBoundaryCorrected = function(url, options) {
|
|
3062
|
+
return new L2.TileLayer.IndiaBoundaryCorrected(url, options);
|
|
3063
|
+
};
|
|
3064
|
+
}
|
|
3065
|
+
//# sourceMappingURL=index.cjs.map
|