@india-boundary-corrector/leaflet-layer 0.2.0 → 0.2.2
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 +1 -1
- package/dist/index.cjs +190 -117
- package/dist/index.cjs.map +1 -1
- package/dist/index.global.js +191 -118
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +190 -117
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -59,12 +59,11 @@ var configs_default = [
|
|
|
59
59
|
"https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png",
|
|
60
60
|
"https://basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png"
|
|
61
61
|
],
|
|
62
|
-
lineWidthStops: { "1": 0.5, "2": 0.75, "3": 0.75, "4": 1, "5": 1, "7": 1.
|
|
62
|
+
lineWidthStops: { "1": 0.5, "2": 0.75, "3": 0.75, "4": 1, "5": 1, "7": 1.75, "16": 2.5 },
|
|
63
63
|
lineStyles: [
|
|
64
64
|
{ color: "rgb(235, 214, 214)", layerSuffix: "ne", endZoom: 4, lineExtensionFactor: 0.1, delWidthFactor: 2.5 },
|
|
65
65
|
{ color: "rgb(235, 214, 214)", layerSuffix: "ne-disp", endZoom: 4, delWidthFactor: 0 },
|
|
66
|
-
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.
|
|
67
|
-
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.2, startZoom: 12, widthFraction: 4, lineExtensionFactor: 0.1 },
|
|
66
|
+
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 6, lineWidthStops: { "6": 9, "10": 8, "14": 8 }, lineExtensionFactor: 0.1 },
|
|
68
67
|
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", startZoom: 5, lineExtensionFactor: 0.1 },
|
|
69
68
|
{ color: "rgb(235, 214, 214)", layerSuffix: "osm-disp", startZoom: 5, delWidthFactor: 0 },
|
|
70
69
|
{ color: "rgb(235, 214, 214)", layerSuffix: "osm-internal", startZoom: 5, widthFraction: 0.5, dashArray: [2, 2], delWidthFactor: 2 },
|
|
@@ -87,12 +86,11 @@ var configs_default = [
|
|
|
87
86
|
"https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png",
|
|
88
87
|
"https://basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png"
|
|
89
88
|
],
|
|
90
|
-
lineWidthStops: { "1":
|
|
89
|
+
lineWidthStops: { "1": 1, "3": 1, "4": 2, "5": 2, "6": 2.5, "7": 3, "8": 3, "10": 4, "11": 4, "12": 4 },
|
|
91
90
|
lineStyles: [
|
|
92
91
|
{ color: "rgb(235, 214, 214)", layerSuffix: "ne", endZoom: 4, lineExtensionFactor: 0.1, delWidthFactor: 2.5 },
|
|
93
92
|
{ color: "rgb(235, 214, 214)", layerSuffix: "ne-disp", endZoom: 4, delWidthFactor: 0 },
|
|
94
|
-
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 6,
|
|
95
|
-
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 12, widthFraction: 4, lineExtensionFactor: 0.1 },
|
|
93
|
+
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 6, lineWidthStops: { "6": 20, "8": 19, "10": 18, "12": 17 }, lineExtensionFactor: 0.1 },
|
|
96
94
|
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", startZoom: 5, lineExtensionFactor: 0.1 },
|
|
97
95
|
{ color: "rgb(235, 214, 214)", layerSuffix: "osm-disp", startZoom: 5, delWidthFactor: 0 },
|
|
98
96
|
{ color: "rgb(235, 214, 214)", layerSuffix: "osm-internal", startZoom: 5, widthFraction: 0.5, dashArray: [4, 4], delWidthFactor: 2 },
|
|
@@ -103,15 +101,20 @@ var configs_default = [
|
|
|
103
101
|
id: "open-topo",
|
|
104
102
|
tileUrlTemplates: [
|
|
105
103
|
"https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",
|
|
106
|
-
"https://tile.opentopomap.org/{z}/{x}/{y}.png"
|
|
104
|
+
"https://tile.opentopomap.org/{z}/{x}/{y}.png",
|
|
105
|
+
"https://{s}.tile.top-o-map.de/{z}/{x}/{y}.png",
|
|
106
|
+
"https://tile.top-o-map.de/{z}/{x}/{y}.png"
|
|
107
107
|
],
|
|
108
108
|
lineWidthStops: { "4": 0.75, "5": 1, "6": 1.25, "7": 1.5, "8": 1.75, "9": 1.25, "10": 1.25, "13": 1.5 },
|
|
109
109
|
lineStyles: [
|
|
110
110
|
{ color: "rgb(83, 83, 83)", layerSuffix: "ne", startZoom: 4, endZoom: 6 },
|
|
111
111
|
{ color: "rgb(173, 173, 173)", layerSuffix: "osm", startZoom: 7, endZoom: 8, alpha: 0.5, widthFraction: 4 },
|
|
112
112
|
{ color: "rgb(83, 83, 83)", layerSuffix: "osm", startZoom: 7, endZoom: 8 },
|
|
113
|
+
{ color: "rgb(83, 83, 83)", layerSuffix: "osm-internal", widthFraction: 0.75, startZoom: 7, endZoom: 8 },
|
|
113
114
|
{ color: "rgb(199, 158, 204)", layerSuffix: "osm", startZoom: 9, widthFraction: 7, alpha: 0.6, lineExtensionFactor: 0.2 },
|
|
114
|
-
{ color: "rgb(175, 41, 203)", layerSuffix: "osm", startZoom: 9, lineExtensionFactor: 0.2 }
|
|
115
|
+
{ color: "rgb(175, 41, 203)", layerSuffix: "osm", startZoom: 9, lineExtensionFactor: 0.2 },
|
|
116
|
+
{ color: "rgb(199, 158, 204)", layerSuffix: "osm-internal", startZoom: 9, widthFraction: 2.25, alpha: 0.6, lineExtensionFactor: 0.2 },
|
|
117
|
+
{ color: "rgb(175, 41, 203)", layerSuffix: "osm-internal", startZoom: 9, widthFactor: 0.75, lineExtensionFactor: 0.2 }
|
|
115
118
|
]
|
|
116
119
|
},
|
|
117
120
|
{
|
|
@@ -120,9 +123,8 @@ var configs_default = [
|
|
|
120
123
|
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
|
121
124
|
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
|
122
125
|
],
|
|
123
|
-
lineWidthStops: { "
|
|
126
|
+
lineWidthStops: { "3": 0.7, "4": 1, "10": 3.75 },
|
|
124
127
|
lineStyles: [
|
|
125
|
-
{ color: "rgb(200, 180, 200)", layerSuffix: "osm", startZoom: 1, endZoom: 3, delWidthFactor: 2.5, widthFraction: 1.5 },
|
|
126
128
|
{ color: "rgb(200, 180, 200)", layerSuffix: "osm", startZoom: 4, delWidthFactor: 1.5 },
|
|
127
129
|
{ color: "rgb(160, 120, 160)", layerSuffix: "osm", startZoom: 4, widthFraction: 0.333, dashArray: [30, 2, 8, 2], delWidthFactor: 0 },
|
|
128
130
|
{ color: "rgb(200, 180, 200)", layerSuffix: "osm-internal", startZoom: 4, widthFraction: 0.45 },
|
|
@@ -146,6 +148,39 @@ var configs_default = [
|
|
|
146
148
|
var INFINITY = -1;
|
|
147
149
|
var MIN_LINE_WIDTH = 0.1;
|
|
148
150
|
var DEFAULT_LINE_WIDTH = 1;
|
|
151
|
+
function interpolateLineWidth(zoom, lineWidthStops) {
|
|
152
|
+
const zooms = Object.keys(lineWidthStops).map(Number).sort((a, b2) => a - b2);
|
|
153
|
+
if (lineWidthStops[zoom] !== void 0) {
|
|
154
|
+
return lineWidthStops[zoom];
|
|
155
|
+
}
|
|
156
|
+
if (zoom < zooms[0]) {
|
|
157
|
+
const z1 = zooms[0];
|
|
158
|
+
const z2 = zooms[1];
|
|
159
|
+
const w1 = lineWidthStops[z1];
|
|
160
|
+
const w2 = lineWidthStops[z2];
|
|
161
|
+
const slope = (w2 - w1) / (z2 - z1);
|
|
162
|
+
return Math.max(MIN_LINE_WIDTH, w1 + slope * (zoom - z1));
|
|
163
|
+
}
|
|
164
|
+
if (zoom > zooms[zooms.length - 1]) {
|
|
165
|
+
const z1 = zooms[zooms.length - 2];
|
|
166
|
+
const z2 = zooms[zooms.length - 1];
|
|
167
|
+
const w1 = lineWidthStops[z1];
|
|
168
|
+
const w2 = lineWidthStops[z2];
|
|
169
|
+
const slope = (w2 - w1) / (z2 - z1);
|
|
170
|
+
return Math.max(MIN_LINE_WIDTH, w2 + slope * (zoom - z2));
|
|
171
|
+
}
|
|
172
|
+
for (let i2 = 0; i2 < zooms.length - 1; i2++) {
|
|
173
|
+
if (zoom > zooms[i2] && zoom < zooms[i2 + 1]) {
|
|
174
|
+
const z1 = zooms[i2];
|
|
175
|
+
const z2 = zooms[i2 + 1];
|
|
176
|
+
const w1 = lineWidthStops[z1];
|
|
177
|
+
const w2 = lineWidthStops[z2];
|
|
178
|
+
const t = (zoom - z1) / (z2 - z1);
|
|
179
|
+
return w1 + t * (w2 - w1);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return DEFAULT_LINE_WIDTH;
|
|
183
|
+
}
|
|
149
184
|
function templateToRegex(template) {
|
|
150
185
|
const groups = [];
|
|
151
186
|
const hasRetina = template.includes("{r}");
|
|
@@ -212,14 +247,33 @@ function isValidColor(color) {
|
|
|
212
247
|
if (/^[a-z]+$/.test(trimmed)) return true;
|
|
213
248
|
return false;
|
|
214
249
|
}
|
|
250
|
+
function validateLineWidthStops(lineWidthStops, prefix) {
|
|
251
|
+
if (!lineWidthStops || typeof lineWidthStops !== "object" || Array.isArray(lineWidthStops)) {
|
|
252
|
+
throw new Error(`${prefix}: lineWidthStops must be an object`);
|
|
253
|
+
}
|
|
254
|
+
const stopKeys = Object.keys(lineWidthStops);
|
|
255
|
+
if (stopKeys.length < 2) {
|
|
256
|
+
throw new Error(`${prefix}: lineWidthStops must have at least 2 entries`);
|
|
257
|
+
}
|
|
258
|
+
for (const key of stopKeys) {
|
|
259
|
+
const zoom = Number(key);
|
|
260
|
+
if (!Number.isInteger(zoom) || zoom < 0) {
|
|
261
|
+
throw new Error(`${prefix}: lineWidthStops keys must be non-negative integers, got "${key}"`);
|
|
262
|
+
}
|
|
263
|
+
if (typeof lineWidthStops[key] !== "number" || lineWidthStops[key] <= 0) {
|
|
264
|
+
throw new Error(`${prefix}: lineWidthStops values must be positive numbers`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
215
268
|
var LineStyle = class _LineStyle {
|
|
216
269
|
/**
|
|
217
270
|
* Validate a LineStyle configuration object.
|
|
218
271
|
* @param {Object} obj - The object to validate
|
|
219
272
|
* @param {number} [index] - Optional index for error messages (when validating in an array)
|
|
273
|
+
* @param {boolean} [requireLineWidthStops=false] - Whether lineWidthStops is required
|
|
220
274
|
* @throws {Error} If validation fails
|
|
221
275
|
*/
|
|
222
|
-
static validateJSON(obj, index) {
|
|
276
|
+
static validateJSON(obj, index, requireLineWidthStops = false) {
|
|
223
277
|
const prefix = index !== void 0 ? `lineStyles[${index}]` : "LineStyle";
|
|
224
278
|
if (!obj || typeof obj !== "object") {
|
|
225
279
|
throw new Error(`${prefix}: must be an object`);
|
|
@@ -254,22 +308,30 @@ var LineStyle = class _LineStyle {
|
|
|
254
308
|
if (obj.delWidthFactor !== void 0 && (typeof obj.delWidthFactor !== "number" || obj.delWidthFactor < 0)) {
|
|
255
309
|
throw new Error(`${prefix}: delWidthFactor must be a non-negative number`);
|
|
256
310
|
}
|
|
311
|
+
if (requireLineWidthStops && obj.lineWidthStops === void 0) {
|
|
312
|
+
throw new Error(`${prefix}: lineWidthStops is required`);
|
|
313
|
+
}
|
|
314
|
+
if (obj.lineWidthStops !== void 0) {
|
|
315
|
+
validateLineWidthStops(obj.lineWidthStops, prefix);
|
|
316
|
+
}
|
|
257
317
|
}
|
|
258
318
|
/**
|
|
259
319
|
* @param {Object} options
|
|
260
320
|
* @param {string} options.color - CSS color string
|
|
261
321
|
* @param {string} options.layerSuffix - Layer suffix (e.g., 'osm', 'ne', 'osm-disp')
|
|
322
|
+
* @param {Object<number, number>} options.lineWidthStops - Line width stops for this style
|
|
262
323
|
* @param {number} [options.widthFraction=1.0] - Multiplier for base line width
|
|
263
324
|
* @param {number[]} [options.dashArray] - Dash pattern for dashed lines
|
|
264
325
|
* @param {number} [options.alpha=1.0] - Opacity (0-1)
|
|
265
326
|
* @param {number} [options.startZoom=0] - Minimum zoom level for this style
|
|
266
327
|
* @param {number} [options.endZoom=INFINITY] - Maximum zoom level for this style (INFINITY means no limit)
|
|
267
|
-
* @param {number} [options.lineExtensionFactor=0.
|
|
328
|
+
* @param {number} [options.lineExtensionFactor=0.0] - Factor to extend lines by (multiplied by deletion line width)
|
|
268
329
|
* @param {number} [options.delWidthFactor=1.5] - Factor to multiply line width for deletion blur
|
|
269
330
|
*/
|
|
270
|
-
constructor({ color, layerSuffix, widthFraction = 1, dashArray, alpha = 1, startZoom = 0, endZoom = INFINITY, lineExtensionFactor = 0, delWidthFactor = 1.5 }) {
|
|
331
|
+
constructor({ color, layerSuffix, lineWidthStops, widthFraction = 1, dashArray, alpha = 1, startZoom = 0, endZoom = INFINITY, lineExtensionFactor = 0, delWidthFactor = 1.5 }) {
|
|
271
332
|
this.color = color;
|
|
272
333
|
this.layerSuffix = layerSuffix;
|
|
334
|
+
this.lineWidthStops = lineWidthStops;
|
|
273
335
|
this.widthFraction = widthFraction;
|
|
274
336
|
this.dashArray = dashArray;
|
|
275
337
|
this.alpha = alpha;
|
|
@@ -278,6 +340,14 @@ var LineStyle = class _LineStyle {
|
|
|
278
340
|
this.lineExtensionFactor = lineExtensionFactor;
|
|
279
341
|
this.delWidthFactor = delWidthFactor;
|
|
280
342
|
}
|
|
343
|
+
/**
|
|
344
|
+
* Get base line width for this style at a given zoom level.
|
|
345
|
+
* @param {number} zoom - Zoom level
|
|
346
|
+
* @returns {number}
|
|
347
|
+
*/
|
|
348
|
+
getLineWidth(zoom) {
|
|
349
|
+
return interpolateLineWidth(zoom, this.lineWidthStops);
|
|
350
|
+
}
|
|
281
351
|
/**
|
|
282
352
|
* Check if this style is active at the given zoom level.
|
|
283
353
|
* @param {number} z - Zoom level
|
|
@@ -294,6 +364,7 @@ var LineStyle = class _LineStyle {
|
|
|
294
364
|
return {
|
|
295
365
|
color: this.color,
|
|
296
366
|
layerSuffix: this.layerSuffix,
|
|
367
|
+
lineWidthStops: this.lineWidthStops,
|
|
297
368
|
widthFraction: this.widthFraction,
|
|
298
369
|
dashArray: this.dashArray,
|
|
299
370
|
alpha: this.alpha,
|
|
@@ -310,7 +381,7 @@ var LineStyle = class _LineStyle {
|
|
|
310
381
|
* @returns {LineStyle}
|
|
311
382
|
*/
|
|
312
383
|
static fromJSON(obj, index) {
|
|
313
|
-
_LineStyle.validateJSON(obj, index);
|
|
384
|
+
_LineStyle.validateJSON(obj, index, true);
|
|
314
385
|
return new _LineStyle(obj);
|
|
315
386
|
}
|
|
316
387
|
};
|
|
@@ -376,9 +447,13 @@ var LayerConfig = class _LayerConfig {
|
|
|
376
447
|
this._compiledPatterns = templates.map((t) => templateToRegex(t));
|
|
377
448
|
this._templatePatterns = templates.map((t) => templateToTemplateRegex(t));
|
|
378
449
|
this.lineWidthStops = lineWidthStops;
|
|
379
|
-
this.lineStyles = lineStyles.map(
|
|
380
|
-
(style
|
|
381
|
-
|
|
450
|
+
this.lineStyles = lineStyles.map((style) => {
|
|
451
|
+
if (style instanceof LineStyle) {
|
|
452
|
+
return style;
|
|
453
|
+
}
|
|
454
|
+
const styleWithStops = style.lineWidthStops ? style : { ...style, lineWidthStops };
|
|
455
|
+
return new LineStyle(styleWithStops);
|
|
456
|
+
});
|
|
382
457
|
}
|
|
383
458
|
/**
|
|
384
459
|
* Get line styles active at a given zoom level
|
|
@@ -397,45 +472,6 @@ var LayerConfig = class _LayerConfig {
|
|
|
397
472
|
const activeStyles = this.getLineStylesForZoom(z2);
|
|
398
473
|
return [...new Set(activeStyles.map((s) => s.layerSuffix))];
|
|
399
474
|
}
|
|
400
|
-
/**
|
|
401
|
-
* Interpolate or extrapolate line width for a given zoom level.
|
|
402
|
-
* Uses the lineWidthStops map to calculate the appropriate width.
|
|
403
|
-
* @param {number} zoom - Zoom level
|
|
404
|
-
* @returns {number}
|
|
405
|
-
*/
|
|
406
|
-
getLineWidth(zoom) {
|
|
407
|
-
const zooms = Object.keys(this.lineWidthStops).map(Number).sort((a, b2) => a - b2);
|
|
408
|
-
if (this.lineWidthStops[zoom] !== void 0) {
|
|
409
|
-
return this.lineWidthStops[zoom];
|
|
410
|
-
}
|
|
411
|
-
if (zoom < zooms[0]) {
|
|
412
|
-
const z1 = zooms[0];
|
|
413
|
-
const z2 = zooms[1];
|
|
414
|
-
const w1 = this.lineWidthStops[z1];
|
|
415
|
-
const w2 = this.lineWidthStops[z2];
|
|
416
|
-
const slope = (w2 - w1) / (z2 - z1);
|
|
417
|
-
return Math.max(MIN_LINE_WIDTH, w1 + slope * (zoom - z1));
|
|
418
|
-
}
|
|
419
|
-
if (zoom > zooms[zooms.length - 1]) {
|
|
420
|
-
const z1 = zooms[zooms.length - 2];
|
|
421
|
-
const z2 = zooms[zooms.length - 1];
|
|
422
|
-
const w1 = this.lineWidthStops[z1];
|
|
423
|
-
const w2 = this.lineWidthStops[z2];
|
|
424
|
-
const slope = (w2 - w1) / (z2 - z1);
|
|
425
|
-
return Math.max(MIN_LINE_WIDTH, w2 + slope * (zoom - z2));
|
|
426
|
-
}
|
|
427
|
-
for (let i2 = 0; i2 < zooms.length - 1; i2++) {
|
|
428
|
-
if (zoom > zooms[i2] && zoom < zooms[i2 + 1]) {
|
|
429
|
-
const z1 = zooms[i2];
|
|
430
|
-
const z2 = zooms[i2 + 1];
|
|
431
|
-
const w1 = this.lineWidthStops[z1];
|
|
432
|
-
const w2 = this.lineWidthStops[z2];
|
|
433
|
-
const t = (zoom - z1) / (z2 - z1);
|
|
434
|
-
return w1 + t * (w2 - w1);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
return DEFAULT_LINE_WIDTH;
|
|
438
|
-
}
|
|
439
475
|
/**
|
|
440
476
|
* Check if this config matches the given template URLs (with {z}/{x}/{y} placeholders)
|
|
441
477
|
* @param {string | string[]} templates - Single template URL or array of template URLs
|
|
@@ -2889,12 +2925,11 @@ var configs_default2 = [
|
|
|
2889
2925
|
"https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png",
|
|
2890
2926
|
"https://basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png"
|
|
2891
2927
|
],
|
|
2892
|
-
lineWidthStops: { "1": 0.5, "2": 0.75, "3": 0.75, "4": 1, "5": 1, "7": 1.
|
|
2928
|
+
lineWidthStops: { "1": 0.5, "2": 0.75, "3": 0.75, "4": 1, "5": 1, "7": 1.75, "16": 2.5 },
|
|
2893
2929
|
lineStyles: [
|
|
2894
2930
|
{ color: "rgb(235, 214, 214)", layerSuffix: "ne", endZoom: 4, lineExtensionFactor: 0.1, delWidthFactor: 2.5 },
|
|
2895
2931
|
{ color: "rgb(235, 214, 214)", layerSuffix: "ne-disp", endZoom: 4, delWidthFactor: 0 },
|
|
2896
|
-
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.
|
|
2897
|
-
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.2, startZoom: 12, widthFraction: 4, lineExtensionFactor: 0.1 },
|
|
2932
|
+
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 6, lineWidthStops: { "6": 9, "10": 8, "14": 8 }, lineExtensionFactor: 0.1 },
|
|
2898
2933
|
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", startZoom: 5, lineExtensionFactor: 0.1 },
|
|
2899
2934
|
{ color: "rgb(235, 214, 214)", layerSuffix: "osm-disp", startZoom: 5, delWidthFactor: 0 },
|
|
2900
2935
|
{ color: "rgb(235, 214, 214)", layerSuffix: "osm-internal", startZoom: 5, widthFraction: 0.5, dashArray: [2, 2], delWidthFactor: 2 },
|
|
@@ -2917,12 +2952,11 @@ var configs_default2 = [
|
|
|
2917
2952
|
"https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png",
|
|
2918
2953
|
"https://basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png"
|
|
2919
2954
|
],
|
|
2920
|
-
lineWidthStops: { "1":
|
|
2955
|
+
lineWidthStops: { "1": 1, "3": 1, "4": 2, "5": 2, "6": 2.5, "7": 3, "8": 3, "10": 4, "11": 4, "12": 4 },
|
|
2921
2956
|
lineStyles: [
|
|
2922
2957
|
{ color: "rgb(235, 214, 214)", layerSuffix: "ne", endZoom: 4, lineExtensionFactor: 0.1, delWidthFactor: 2.5 },
|
|
2923
2958
|
{ color: "rgb(235, 214, 214)", layerSuffix: "ne-disp", endZoom: 4, delWidthFactor: 0 },
|
|
2924
|
-
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 6,
|
|
2925
|
-
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 12, widthFraction: 4, lineExtensionFactor: 0.1 },
|
|
2959
|
+
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 6, lineWidthStops: { "6": 20, "8": 19, "10": 18, "12": 17 }, lineExtensionFactor: 0.1 },
|
|
2926
2960
|
{ color: "rgb(235, 214, 214)", layerSuffix: "osm", startZoom: 5, lineExtensionFactor: 0.1 },
|
|
2927
2961
|
{ color: "rgb(235, 214, 214)", layerSuffix: "osm-disp", startZoom: 5, delWidthFactor: 0 },
|
|
2928
2962
|
{ color: "rgb(235, 214, 214)", layerSuffix: "osm-internal", startZoom: 5, widthFraction: 0.5, dashArray: [4, 4], delWidthFactor: 2 },
|
|
@@ -2933,15 +2967,20 @@ var configs_default2 = [
|
|
|
2933
2967
|
id: "open-topo",
|
|
2934
2968
|
tileUrlTemplates: [
|
|
2935
2969
|
"https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",
|
|
2936
|
-
"https://tile.opentopomap.org/{z}/{x}/{y}.png"
|
|
2970
|
+
"https://tile.opentopomap.org/{z}/{x}/{y}.png",
|
|
2971
|
+
"https://{s}.tile.top-o-map.de/{z}/{x}/{y}.png",
|
|
2972
|
+
"https://tile.top-o-map.de/{z}/{x}/{y}.png"
|
|
2937
2973
|
],
|
|
2938
2974
|
lineWidthStops: { "4": 0.75, "5": 1, "6": 1.25, "7": 1.5, "8": 1.75, "9": 1.25, "10": 1.25, "13": 1.5 },
|
|
2939
2975
|
lineStyles: [
|
|
2940
2976
|
{ color: "rgb(83, 83, 83)", layerSuffix: "ne", startZoom: 4, endZoom: 6 },
|
|
2941
2977
|
{ color: "rgb(173, 173, 173)", layerSuffix: "osm", startZoom: 7, endZoom: 8, alpha: 0.5, widthFraction: 4 },
|
|
2942
2978
|
{ color: "rgb(83, 83, 83)", layerSuffix: "osm", startZoom: 7, endZoom: 8 },
|
|
2979
|
+
{ color: "rgb(83, 83, 83)", layerSuffix: "osm-internal", widthFraction: 0.75, startZoom: 7, endZoom: 8 },
|
|
2943
2980
|
{ color: "rgb(199, 158, 204)", layerSuffix: "osm", startZoom: 9, widthFraction: 7, alpha: 0.6, lineExtensionFactor: 0.2 },
|
|
2944
|
-
{ color: "rgb(175, 41, 203)", layerSuffix: "osm", startZoom: 9, lineExtensionFactor: 0.2 }
|
|
2981
|
+
{ color: "rgb(175, 41, 203)", layerSuffix: "osm", startZoom: 9, lineExtensionFactor: 0.2 },
|
|
2982
|
+
{ color: "rgb(199, 158, 204)", layerSuffix: "osm-internal", startZoom: 9, widthFraction: 2.25, alpha: 0.6, lineExtensionFactor: 0.2 },
|
|
2983
|
+
{ color: "rgb(175, 41, 203)", layerSuffix: "osm-internal", startZoom: 9, widthFactor: 0.75, lineExtensionFactor: 0.2 }
|
|
2945
2984
|
]
|
|
2946
2985
|
},
|
|
2947
2986
|
{
|
|
@@ -2950,9 +2989,8 @@ var configs_default2 = [
|
|
|
2950
2989
|
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
|
2951
2990
|
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
|
2952
2991
|
],
|
|
2953
|
-
lineWidthStops: { "
|
|
2992
|
+
lineWidthStops: { "3": 0.7, "4": 1, "10": 3.75 },
|
|
2954
2993
|
lineStyles: [
|
|
2955
|
-
{ color: "rgb(200, 180, 200)", layerSuffix: "osm", startZoom: 1, endZoom: 3, delWidthFactor: 2.5, widthFraction: 1.5 },
|
|
2956
2994
|
{ color: "rgb(200, 180, 200)", layerSuffix: "osm", startZoom: 4, delWidthFactor: 1.5 },
|
|
2957
2995
|
{ color: "rgb(160, 120, 160)", layerSuffix: "osm", startZoom: 4, widthFraction: 0.333, dashArray: [30, 2, 8, 2], delWidthFactor: 0 },
|
|
2958
2996
|
{ color: "rgb(200, 180, 200)", layerSuffix: "osm-internal", startZoom: 4, widthFraction: 0.45 },
|
|
@@ -2976,6 +3014,39 @@ var configs_default2 = [
|
|
|
2976
3014
|
var INFINITY2 = -1;
|
|
2977
3015
|
var MIN_LINE_WIDTH2 = 0.1;
|
|
2978
3016
|
var DEFAULT_LINE_WIDTH2 = 1;
|
|
3017
|
+
function interpolateLineWidth2(zoom, lineWidthStops) {
|
|
3018
|
+
const zooms = Object.keys(lineWidthStops).map(Number).sort((a, b2) => a - b2);
|
|
3019
|
+
if (lineWidthStops[zoom] !== void 0) {
|
|
3020
|
+
return lineWidthStops[zoom];
|
|
3021
|
+
}
|
|
3022
|
+
if (zoom < zooms[0]) {
|
|
3023
|
+
const z1 = zooms[0];
|
|
3024
|
+
const z2 = zooms[1];
|
|
3025
|
+
const w1 = lineWidthStops[z1];
|
|
3026
|
+
const w2 = lineWidthStops[z2];
|
|
3027
|
+
const slope = (w2 - w1) / (z2 - z1);
|
|
3028
|
+
return Math.max(MIN_LINE_WIDTH2, w1 + slope * (zoom - z1));
|
|
3029
|
+
}
|
|
3030
|
+
if (zoom > zooms[zooms.length - 1]) {
|
|
3031
|
+
const z1 = zooms[zooms.length - 2];
|
|
3032
|
+
const z2 = zooms[zooms.length - 1];
|
|
3033
|
+
const w1 = lineWidthStops[z1];
|
|
3034
|
+
const w2 = lineWidthStops[z2];
|
|
3035
|
+
const slope = (w2 - w1) / (z2 - z1);
|
|
3036
|
+
return Math.max(MIN_LINE_WIDTH2, w2 + slope * (zoom - z2));
|
|
3037
|
+
}
|
|
3038
|
+
for (let i2 = 0; i2 < zooms.length - 1; i2++) {
|
|
3039
|
+
if (zoom > zooms[i2] && zoom < zooms[i2 + 1]) {
|
|
3040
|
+
const z1 = zooms[i2];
|
|
3041
|
+
const z2 = zooms[i2 + 1];
|
|
3042
|
+
const w1 = lineWidthStops[z1];
|
|
3043
|
+
const w2 = lineWidthStops[z2];
|
|
3044
|
+
const t = (zoom - z1) / (z2 - z1);
|
|
3045
|
+
return w1 + t * (w2 - w1);
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
return DEFAULT_LINE_WIDTH2;
|
|
3049
|
+
}
|
|
2979
3050
|
function templateToRegex2(template) {
|
|
2980
3051
|
const groups = [];
|
|
2981
3052
|
const hasRetina = template.includes("{r}");
|
|
@@ -3042,14 +3113,33 @@ function isValidColor2(color) {
|
|
|
3042
3113
|
if (/^[a-z]+$/.test(trimmed)) return true;
|
|
3043
3114
|
return false;
|
|
3044
3115
|
}
|
|
3116
|
+
function validateLineWidthStops2(lineWidthStops, prefix) {
|
|
3117
|
+
if (!lineWidthStops || typeof lineWidthStops !== "object" || Array.isArray(lineWidthStops)) {
|
|
3118
|
+
throw new Error(`${prefix}: lineWidthStops must be an object`);
|
|
3119
|
+
}
|
|
3120
|
+
const stopKeys = Object.keys(lineWidthStops);
|
|
3121
|
+
if (stopKeys.length < 2) {
|
|
3122
|
+
throw new Error(`${prefix}: lineWidthStops must have at least 2 entries`);
|
|
3123
|
+
}
|
|
3124
|
+
for (const key of stopKeys) {
|
|
3125
|
+
const zoom = Number(key);
|
|
3126
|
+
if (!Number.isInteger(zoom) || zoom < 0) {
|
|
3127
|
+
throw new Error(`${prefix}: lineWidthStops keys must be non-negative integers, got "${key}"`);
|
|
3128
|
+
}
|
|
3129
|
+
if (typeof lineWidthStops[key] !== "number" || lineWidthStops[key] <= 0) {
|
|
3130
|
+
throw new Error(`${prefix}: lineWidthStops values must be positive numbers`);
|
|
3131
|
+
}
|
|
3132
|
+
}
|
|
3133
|
+
}
|
|
3045
3134
|
var LineStyle2 = class _LineStyle2 {
|
|
3046
3135
|
/**
|
|
3047
3136
|
* Validate a LineStyle configuration object.
|
|
3048
3137
|
* @param {Object} obj - The object to validate
|
|
3049
3138
|
* @param {number} [index] - Optional index for error messages (when validating in an array)
|
|
3139
|
+
* @param {boolean} [requireLineWidthStops=false] - Whether lineWidthStops is required
|
|
3050
3140
|
* @throws {Error} If validation fails
|
|
3051
3141
|
*/
|
|
3052
|
-
static validateJSON(obj, index) {
|
|
3142
|
+
static validateJSON(obj, index, requireLineWidthStops = false) {
|
|
3053
3143
|
const prefix = index !== void 0 ? `lineStyles[${index}]` : "LineStyle";
|
|
3054
3144
|
if (!obj || typeof obj !== "object") {
|
|
3055
3145
|
throw new Error(`${prefix}: must be an object`);
|
|
@@ -3084,22 +3174,30 @@ var LineStyle2 = class _LineStyle2 {
|
|
|
3084
3174
|
if (obj.delWidthFactor !== void 0 && (typeof obj.delWidthFactor !== "number" || obj.delWidthFactor < 0)) {
|
|
3085
3175
|
throw new Error(`${prefix}: delWidthFactor must be a non-negative number`);
|
|
3086
3176
|
}
|
|
3177
|
+
if (requireLineWidthStops && obj.lineWidthStops === void 0) {
|
|
3178
|
+
throw new Error(`${prefix}: lineWidthStops is required`);
|
|
3179
|
+
}
|
|
3180
|
+
if (obj.lineWidthStops !== void 0) {
|
|
3181
|
+
validateLineWidthStops2(obj.lineWidthStops, prefix);
|
|
3182
|
+
}
|
|
3087
3183
|
}
|
|
3088
3184
|
/**
|
|
3089
3185
|
* @param {Object} options
|
|
3090
3186
|
* @param {string} options.color - CSS color string
|
|
3091
3187
|
* @param {string} options.layerSuffix - Layer suffix (e.g., 'osm', 'ne', 'osm-disp')
|
|
3188
|
+
* @param {Object<number, number>} options.lineWidthStops - Line width stops for this style
|
|
3092
3189
|
* @param {number} [options.widthFraction=1.0] - Multiplier for base line width
|
|
3093
3190
|
* @param {number[]} [options.dashArray] - Dash pattern for dashed lines
|
|
3094
3191
|
* @param {number} [options.alpha=1.0] - Opacity (0-1)
|
|
3095
3192
|
* @param {number} [options.startZoom=0] - Minimum zoom level for this style
|
|
3096
3193
|
* @param {number} [options.endZoom=INFINITY] - Maximum zoom level for this style (INFINITY means no limit)
|
|
3097
|
-
* @param {number} [options.lineExtensionFactor=0.
|
|
3194
|
+
* @param {number} [options.lineExtensionFactor=0.0] - Factor to extend lines by (multiplied by deletion line width)
|
|
3098
3195
|
* @param {number} [options.delWidthFactor=1.5] - Factor to multiply line width for deletion blur
|
|
3099
3196
|
*/
|
|
3100
|
-
constructor({ color, layerSuffix, widthFraction = 1, dashArray, alpha = 1, startZoom = 0, endZoom = INFINITY2, lineExtensionFactor = 0, delWidthFactor = 1.5 }) {
|
|
3197
|
+
constructor({ color, layerSuffix, lineWidthStops, widthFraction = 1, dashArray, alpha = 1, startZoom = 0, endZoom = INFINITY2, lineExtensionFactor = 0, delWidthFactor = 1.5 }) {
|
|
3101
3198
|
this.color = color;
|
|
3102
3199
|
this.layerSuffix = layerSuffix;
|
|
3200
|
+
this.lineWidthStops = lineWidthStops;
|
|
3103
3201
|
this.widthFraction = widthFraction;
|
|
3104
3202
|
this.dashArray = dashArray;
|
|
3105
3203
|
this.alpha = alpha;
|
|
@@ -3108,6 +3206,14 @@ var LineStyle2 = class _LineStyle2 {
|
|
|
3108
3206
|
this.lineExtensionFactor = lineExtensionFactor;
|
|
3109
3207
|
this.delWidthFactor = delWidthFactor;
|
|
3110
3208
|
}
|
|
3209
|
+
/**
|
|
3210
|
+
* Get base line width for this style at a given zoom level.
|
|
3211
|
+
* @param {number} zoom - Zoom level
|
|
3212
|
+
* @returns {number}
|
|
3213
|
+
*/
|
|
3214
|
+
getLineWidth(zoom) {
|
|
3215
|
+
return interpolateLineWidth2(zoom, this.lineWidthStops);
|
|
3216
|
+
}
|
|
3111
3217
|
/**
|
|
3112
3218
|
* Check if this style is active at the given zoom level.
|
|
3113
3219
|
* @param {number} z - Zoom level
|
|
@@ -3124,6 +3230,7 @@ var LineStyle2 = class _LineStyle2 {
|
|
|
3124
3230
|
return {
|
|
3125
3231
|
color: this.color,
|
|
3126
3232
|
layerSuffix: this.layerSuffix,
|
|
3233
|
+
lineWidthStops: this.lineWidthStops,
|
|
3127
3234
|
widthFraction: this.widthFraction,
|
|
3128
3235
|
dashArray: this.dashArray,
|
|
3129
3236
|
alpha: this.alpha,
|
|
@@ -3140,7 +3247,7 @@ var LineStyle2 = class _LineStyle2 {
|
|
|
3140
3247
|
* @returns {LineStyle}
|
|
3141
3248
|
*/
|
|
3142
3249
|
static fromJSON(obj, index) {
|
|
3143
|
-
_LineStyle2.validateJSON(obj, index);
|
|
3250
|
+
_LineStyle2.validateJSON(obj, index, true);
|
|
3144
3251
|
return new _LineStyle2(obj);
|
|
3145
3252
|
}
|
|
3146
3253
|
};
|
|
@@ -3206,9 +3313,13 @@ var LayerConfig2 = class _LayerConfig2 {
|
|
|
3206
3313
|
this._compiledPatterns = templates.map((t) => templateToRegex2(t));
|
|
3207
3314
|
this._templatePatterns = templates.map((t) => templateToTemplateRegex2(t));
|
|
3208
3315
|
this.lineWidthStops = lineWidthStops;
|
|
3209
|
-
this.lineStyles = lineStyles.map(
|
|
3210
|
-
(style
|
|
3211
|
-
|
|
3316
|
+
this.lineStyles = lineStyles.map((style) => {
|
|
3317
|
+
if (style instanceof LineStyle2) {
|
|
3318
|
+
return style;
|
|
3319
|
+
}
|
|
3320
|
+
const styleWithStops = style.lineWidthStops ? style : { ...style, lineWidthStops };
|
|
3321
|
+
return new LineStyle2(styleWithStops);
|
|
3322
|
+
});
|
|
3212
3323
|
}
|
|
3213
3324
|
/**
|
|
3214
3325
|
* Get line styles active at a given zoom level
|
|
@@ -3227,45 +3338,6 @@ var LayerConfig2 = class _LayerConfig2 {
|
|
|
3227
3338
|
const activeStyles = this.getLineStylesForZoom(z2);
|
|
3228
3339
|
return [...new Set(activeStyles.map((s) => s.layerSuffix))];
|
|
3229
3340
|
}
|
|
3230
|
-
/**
|
|
3231
|
-
* Interpolate or extrapolate line width for a given zoom level.
|
|
3232
|
-
* Uses the lineWidthStops map to calculate the appropriate width.
|
|
3233
|
-
* @param {number} zoom - Zoom level
|
|
3234
|
-
* @returns {number}
|
|
3235
|
-
*/
|
|
3236
|
-
getLineWidth(zoom) {
|
|
3237
|
-
const zooms = Object.keys(this.lineWidthStops).map(Number).sort((a, b2) => a - b2);
|
|
3238
|
-
if (this.lineWidthStops[zoom] !== void 0) {
|
|
3239
|
-
return this.lineWidthStops[zoom];
|
|
3240
|
-
}
|
|
3241
|
-
if (zoom < zooms[0]) {
|
|
3242
|
-
const z1 = zooms[0];
|
|
3243
|
-
const z2 = zooms[1];
|
|
3244
|
-
const w1 = this.lineWidthStops[z1];
|
|
3245
|
-
const w2 = this.lineWidthStops[z2];
|
|
3246
|
-
const slope = (w2 - w1) / (z2 - z1);
|
|
3247
|
-
return Math.max(MIN_LINE_WIDTH2, w1 + slope * (zoom - z1));
|
|
3248
|
-
}
|
|
3249
|
-
if (zoom > zooms[zooms.length - 1]) {
|
|
3250
|
-
const z1 = zooms[zooms.length - 2];
|
|
3251
|
-
const z2 = zooms[zooms.length - 1];
|
|
3252
|
-
const w1 = this.lineWidthStops[z1];
|
|
3253
|
-
const w2 = this.lineWidthStops[z2];
|
|
3254
|
-
const slope = (w2 - w1) / (z2 - z1);
|
|
3255
|
-
return Math.max(MIN_LINE_WIDTH2, w2 + slope * (zoom - z2));
|
|
3256
|
-
}
|
|
3257
|
-
for (let i2 = 0; i2 < zooms.length - 1; i2++) {
|
|
3258
|
-
if (zoom > zooms[i2] && zoom < zooms[i2 + 1]) {
|
|
3259
|
-
const z1 = zooms[i2];
|
|
3260
|
-
const z2 = zooms[i2 + 1];
|
|
3261
|
-
const w1 = this.lineWidthStops[z1];
|
|
3262
|
-
const w2 = this.lineWidthStops[z2];
|
|
3263
|
-
const t = (zoom - z1) / (z2 - z1);
|
|
3264
|
-
return w1 + t * (w2 - w1);
|
|
3265
|
-
}
|
|
3266
|
-
}
|
|
3267
|
-
return DEFAULT_LINE_WIDTH2;
|
|
3268
|
-
}
|
|
3269
3341
|
/**
|
|
3270
3342
|
* Check if this config matches the given template URLs (with {z}/{x}/{y} placeholders)
|
|
3271
3343
|
* @param {string | string[]} templates - Single template URL or array of template URLs
|
|
@@ -3758,12 +3830,13 @@ var _TileFixer = class _TileFixer2 {
|
|
|
3758
3830
|
const canvas = this._canvas;
|
|
3759
3831
|
const ctx = canvas.getContext("2d", { willReadFrequently: true });
|
|
3760
3832
|
ctx.drawImage(imageBitmap, 0, 0, tileSize, tileSize);
|
|
3761
|
-
const baseLineWidth = layerConfig.getLineWidth(zoom);
|
|
3762
3833
|
const delLineWidthBySuffix = {};
|
|
3763
3834
|
for (const suffix of layerSuffixes) {
|
|
3764
3835
|
const stylesForSuffix = activeLineStyles.filter((s) => s.layerSuffix === suffix);
|
|
3765
|
-
const
|
|
3766
|
-
|
|
3836
|
+
const maxDelWidth = Math.max(...stylesForSuffix.map(
|
|
3837
|
+
(s) => s.getLineWidth(zoom) * s.widthFraction * s.delWidthFactor
|
|
3838
|
+
));
|
|
3839
|
+
delLineWidthBySuffix[suffix] = maxDelWidth;
|
|
3767
3840
|
}
|
|
3768
3841
|
for (const suffix of layerSuffixes) {
|
|
3769
3842
|
const delLineWidth = delLineWidthBySuffix[suffix];
|
|
@@ -3778,7 +3851,7 @@ var _TileFixer = class _TileFixer2 {
|
|
|
3778
3851
|
}
|
|
3779
3852
|
}
|
|
3780
3853
|
for (const style of activeLineStyles) {
|
|
3781
|
-
const { color,
|
|
3854
|
+
const { color, widthFraction, dashArray, alpha, lineExtensionFactor, layerSuffix } = style;
|
|
3782
3855
|
const addLayerName = `to-add-${layerSuffix}`;
|
|
3783
3856
|
let addFeatures = corrections[addLayerName] || [];
|
|
3784
3857
|
if (addFeatures.length > 0) {
|
|
@@ -3786,7 +3859,7 @@ var _TileFixer = class _TileFixer2 {
|
|
|
3786
3859
|
if (lineExtensionFactor > 0) {
|
|
3787
3860
|
addFeatures = extendFeaturesByFactor(addFeatures, lineExtensionFactor, delLineWidth, tileSize);
|
|
3788
3861
|
}
|
|
3789
|
-
const lineWidth =
|
|
3862
|
+
const lineWidth = style.getLineWidth(zoom) * widthFraction;
|
|
3790
3863
|
drawFeatures(ctx, addFeatures, color, lineWidth, tileSize, dashArray, alpha);
|
|
3791
3864
|
}
|
|
3792
3865
|
}
|