@india-boundary-corrector/leaflet-layer 0.0.4 → 0.0.5
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/dist/index.cjs +242 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.global.js +245 -80
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +242 -77
- package/dist/index.js.map +1 -1
- package/dist/india_boundary_corrections.pmtiles.gz +0 -0
- package/package.json +4 -4
- package/src/index.js +25 -4
package/dist/index.cjs
CHANGED
|
@@ -151,7 +151,166 @@ function templateToTemplateRegex(template) {
|
|
|
151
151
|
});
|
|
152
152
|
return new RegExp("^" + pattern + "(\\?.*)?$", "i");
|
|
153
153
|
}
|
|
154
|
+
function isValidColor(color) {
|
|
155
|
+
if (typeof color !== "string" || !color.trim()) return false;
|
|
156
|
+
if (typeof CSS !== "undefined" && CSS.supports) {
|
|
157
|
+
return CSS.supports("color", color);
|
|
158
|
+
}
|
|
159
|
+
const trimmed = color.trim().toLowerCase();
|
|
160
|
+
if (/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/.test(trimmed)) return true;
|
|
161
|
+
if (/^(rgb|hsl)a?\(/.test(trimmed)) return true;
|
|
162
|
+
if (/^[a-z]+$/.test(trimmed)) return true;
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
var LineStyle = class _LineStyle {
|
|
166
|
+
/**
|
|
167
|
+
* Validate a LineStyle configuration object.
|
|
168
|
+
* @param {Object} obj - The object to validate
|
|
169
|
+
* @param {number} [index] - Optional index for error messages (when validating in an array)
|
|
170
|
+
* @throws {Error} If validation fails
|
|
171
|
+
*/
|
|
172
|
+
static validateJSON(obj, index) {
|
|
173
|
+
const prefix = index !== void 0 ? `lineStyles[${index}]` : "LineStyle";
|
|
174
|
+
if (!obj || typeof obj !== "object") {
|
|
175
|
+
throw new Error(`${prefix}: must be an object`);
|
|
176
|
+
}
|
|
177
|
+
if (!obj.color || typeof obj.color !== "string") {
|
|
178
|
+
throw new Error(`${prefix}: color must be a non-empty string`);
|
|
179
|
+
}
|
|
180
|
+
if (!isValidColor(obj.color)) {
|
|
181
|
+
throw new Error(`${prefix}: color "${obj.color}" is not a valid CSS color`);
|
|
182
|
+
}
|
|
183
|
+
if (obj.widthFraction !== void 0 && (typeof obj.widthFraction !== "number" || obj.widthFraction <= 0)) {
|
|
184
|
+
throw new Error(`${prefix}: widthFraction must be a positive number`);
|
|
185
|
+
}
|
|
186
|
+
if (obj.dashArray !== void 0 && !Array.isArray(obj.dashArray)) {
|
|
187
|
+
throw new Error(`${prefix}: dashArray must be an array`);
|
|
188
|
+
}
|
|
189
|
+
if (obj.alpha !== void 0 && (typeof obj.alpha !== "number" || obj.alpha < 0 || obj.alpha > 1)) {
|
|
190
|
+
throw new Error(`${prefix}: alpha must be a number between 0 and 1`);
|
|
191
|
+
}
|
|
192
|
+
if (obj.startZoom !== void 0 && (typeof obj.startZoom !== "number" || obj.startZoom < 0)) {
|
|
193
|
+
throw new Error(`${prefix}: startZoom must be a non-negative number`);
|
|
194
|
+
}
|
|
195
|
+
if (obj.endZoom !== void 0 && (typeof obj.endZoom !== "number" || obj.endZoom < 0)) {
|
|
196
|
+
throw new Error(`${prefix}: endZoom must be a non-negative number`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* @param {Object} options
|
|
201
|
+
* @param {string} options.color - CSS color string
|
|
202
|
+
* @param {number} [options.widthFraction=1.0] - Multiplier for base line width
|
|
203
|
+
* @param {number[]} [options.dashArray] - Dash pattern for dashed lines
|
|
204
|
+
* @param {number} [options.alpha=1.0] - Opacity (0-1)
|
|
205
|
+
* @param {number} [options.startZoom] - Minimum zoom level for this style
|
|
206
|
+
* @param {number} [options.endZoom=Infinity] - Maximum zoom level for this style
|
|
207
|
+
*/
|
|
208
|
+
constructor({ color, widthFraction = 1, dashArray, alpha = 1, startZoom, endZoom = Infinity }) {
|
|
209
|
+
this.color = color;
|
|
210
|
+
this.widthFraction = widthFraction;
|
|
211
|
+
this.dashArray = dashArray;
|
|
212
|
+
this.alpha = alpha;
|
|
213
|
+
this.startZoom = startZoom;
|
|
214
|
+
this.endZoom = endZoom;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Check if this style is active at the given zoom level.
|
|
218
|
+
* @param {number} z - Zoom level
|
|
219
|
+
* @returns {boolean}
|
|
220
|
+
*/
|
|
221
|
+
isActiveAtZoom(z2) {
|
|
222
|
+
return z2 >= this.startZoom && z2 <= this.endZoom;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Serialize to plain object.
|
|
226
|
+
* @returns {Object}
|
|
227
|
+
*/
|
|
228
|
+
toJSON() {
|
|
229
|
+
const obj = { color: this.color };
|
|
230
|
+
if (this.widthFraction !== 1) obj.widthFraction = this.widthFraction;
|
|
231
|
+
if (this.dashArray) obj.dashArray = this.dashArray;
|
|
232
|
+
if (this.alpha !== 1) obj.alpha = this.alpha;
|
|
233
|
+
if (this.startZoom !== void 0) obj.startZoom = this.startZoom;
|
|
234
|
+
if (this.endZoom !== Infinity) obj.endZoom = this.endZoom;
|
|
235
|
+
return obj;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Create from plain object with validation.
|
|
239
|
+
* @param {Object} obj
|
|
240
|
+
* @param {number} [defaultStartZoom=0] - Default startZoom if not specified
|
|
241
|
+
* @param {number} [index] - Optional index for error messages
|
|
242
|
+
* @returns {LineStyle}
|
|
243
|
+
*/
|
|
244
|
+
static fromJSON(obj, defaultStartZoom = 0, index) {
|
|
245
|
+
_LineStyle.validateJSON(obj, index);
|
|
246
|
+
return new _LineStyle({
|
|
247
|
+
...obj,
|
|
248
|
+
startZoom: obj.startZoom ?? defaultStartZoom
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
};
|
|
154
252
|
var LayerConfig = class _LayerConfig {
|
|
253
|
+
/**
|
|
254
|
+
* Validate a LayerConfig configuration object.
|
|
255
|
+
* Also validates all lineStyles within the config.
|
|
256
|
+
* @param {Object} obj - The object to validate
|
|
257
|
+
* @throws {Error} If validation fails
|
|
258
|
+
*/
|
|
259
|
+
static validateJSON(obj) {
|
|
260
|
+
if (!obj || typeof obj !== "object") {
|
|
261
|
+
throw new Error("LayerConfig: must be an object");
|
|
262
|
+
}
|
|
263
|
+
if (!obj.id || typeof obj.id !== "string") {
|
|
264
|
+
throw new Error("LayerConfig: id must be a non-empty string");
|
|
265
|
+
}
|
|
266
|
+
if (obj.id.includes("/")) {
|
|
267
|
+
throw new Error(`LayerConfig: id cannot contain slashes: "${obj.id}"`);
|
|
268
|
+
}
|
|
269
|
+
const id = obj.id;
|
|
270
|
+
if (obj.startZoom !== void 0 && (typeof obj.startZoom !== "number" || obj.startZoom < 0)) {
|
|
271
|
+
throw new Error(`LayerConfig "${id}": startZoom must be a non-negative number`);
|
|
272
|
+
}
|
|
273
|
+
if (obj.zoomThreshold !== void 0 && (typeof obj.zoomThreshold !== "number" || obj.zoomThreshold < 0)) {
|
|
274
|
+
throw new Error(`LayerConfig "${id}": zoomThreshold must be a non-negative number`);
|
|
275
|
+
}
|
|
276
|
+
const startZoom = obj.startZoom ?? 0;
|
|
277
|
+
const zoomThreshold = obj.zoomThreshold ?? 5;
|
|
278
|
+
if (startZoom > zoomThreshold) {
|
|
279
|
+
throw new Error(`LayerConfig "${id}": startZoom (${startZoom}) must be <= zoomThreshold (${zoomThreshold})`);
|
|
280
|
+
}
|
|
281
|
+
if (obj.lineWidthStops !== void 0) {
|
|
282
|
+
if (!obj.lineWidthStops || typeof obj.lineWidthStops !== "object" || Array.isArray(obj.lineWidthStops)) {
|
|
283
|
+
throw new Error(`LayerConfig "${id}": lineWidthStops must be an object`);
|
|
284
|
+
}
|
|
285
|
+
const stopKeys = Object.keys(obj.lineWidthStops);
|
|
286
|
+
if (stopKeys.length < 2) {
|
|
287
|
+
throw new Error(`LayerConfig "${id}": lineWidthStops must have at least 2 entries`);
|
|
288
|
+
}
|
|
289
|
+
for (const key of stopKeys) {
|
|
290
|
+
const zoom = Number(key);
|
|
291
|
+
if (!Number.isInteger(zoom) || zoom < 0) {
|
|
292
|
+
throw new Error(`LayerConfig "${id}": lineWidthStops keys must be non-negative integers, got "${key}"`);
|
|
293
|
+
}
|
|
294
|
+
if (typeof obj.lineWidthStops[key] !== "number" || obj.lineWidthStops[key] <= 0) {
|
|
295
|
+
throw new Error(`LayerConfig "${id}": lineWidthStops values must be positive numbers`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (obj.lineStyles !== void 0) {
|
|
300
|
+
if (!Array.isArray(obj.lineStyles) || obj.lineStyles.length === 0) {
|
|
301
|
+
throw new Error(`LayerConfig "${id}": lineStyles must be a non-empty array`);
|
|
302
|
+
}
|
|
303
|
+
for (let i2 = 0; i2 < obj.lineStyles.length; i2++) {
|
|
304
|
+
LineStyle.validateJSON(obj.lineStyles[i2], i2);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (obj.delWidthFactor !== void 0 && (typeof obj.delWidthFactor !== "number" || obj.delWidthFactor <= 0)) {
|
|
308
|
+
throw new Error(`LayerConfig "${id}": delWidthFactor must be a positive number`);
|
|
309
|
+
}
|
|
310
|
+
if (obj.lineExtensionFactor !== void 0 && (typeof obj.lineExtensionFactor !== "number" || obj.lineExtensionFactor < 0)) {
|
|
311
|
+
throw new Error(`LayerConfig "${id}": lineExtensionFactor must be a non-negative number`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
155
314
|
constructor({
|
|
156
315
|
id,
|
|
157
316
|
startZoom = 0,
|
|
@@ -174,66 +333,30 @@ var LayerConfig = class _LayerConfig {
|
|
|
174
333
|
// Set to 0 to disable extension
|
|
175
334
|
lineExtensionFactor = 0.5
|
|
176
335
|
}) {
|
|
177
|
-
if (!id || typeof id !== "string") {
|
|
178
|
-
throw new Error("LayerConfig requires a non-empty string id");
|
|
179
|
-
}
|
|
180
|
-
if (id.includes("/")) {
|
|
181
|
-
throw new Error(`LayerConfig id cannot contain slashes: "${id}"`);
|
|
182
|
-
}
|
|
183
336
|
this.id = id;
|
|
184
337
|
this.startZoom = startZoom;
|
|
185
338
|
this.zoomThreshold = zoomThreshold;
|
|
186
|
-
if (startZoom > zoomThreshold) {
|
|
187
|
-
throw new Error(`LayerConfig "${id}": startZoom (${startZoom}) must be <= zoomThreshold (${zoomThreshold})`);
|
|
188
|
-
}
|
|
189
339
|
const templates = Array.isArray(tileUrlTemplates) ? tileUrlTemplates : tileUrlTemplates ? [tileUrlTemplates] : [];
|
|
190
340
|
this.tileUrlTemplates = templates;
|
|
191
341
|
this._compiledPatterns = templates.map((t) => templateToRegex(t));
|
|
192
342
|
this._templatePatterns = templates.map((t) => templateToTemplateRegex(t));
|
|
193
|
-
if (!lineWidthStops || typeof lineWidthStops !== "object" || Array.isArray(lineWidthStops)) {
|
|
194
|
-
throw new Error(`LayerConfig "${id}": lineWidthStops must be an object`);
|
|
195
|
-
}
|
|
196
|
-
const stopKeys = Object.keys(lineWidthStops);
|
|
197
|
-
if (stopKeys.length < 2) {
|
|
198
|
-
throw new Error(`LayerConfig "${id}": lineWidthStops must have at least 2 entries`);
|
|
199
|
-
}
|
|
200
|
-
for (const key of stopKeys) {
|
|
201
|
-
const zoom = Number(key);
|
|
202
|
-
if (!Number.isInteger(zoom) || zoom < 0) {
|
|
203
|
-
throw new Error(`LayerConfig "${id}": lineWidthStops keys must be non-negative integers, got "${key}"`);
|
|
204
|
-
}
|
|
205
|
-
if (typeof lineWidthStops[key] !== "number" || lineWidthStops[key] <= 0) {
|
|
206
|
-
throw new Error(`LayerConfig "${id}": lineWidthStops values must be positive numbers`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
343
|
this.lineWidthStops = lineWidthStops;
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
throw new Error(`LayerConfig "${id}": lineStyles[${i2}] must be an object`);
|
|
217
|
-
}
|
|
218
|
-
if (!style.color || typeof style.color !== "string") {
|
|
219
|
-
throw new Error(`LayerConfig "${id}": lineStyles[${i2}].color must be a non-empty string`);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
this.lineStyles = lineStyles.map((style) => ({
|
|
223
|
-
...style,
|
|
224
|
-
startZoom: style.startZoom ?? startZoom,
|
|
225
|
-
endZoom: style.endZoom ?? Infinity
|
|
226
|
-
}));
|
|
344
|
+
this.lineStyles = lineStyles.map(
|
|
345
|
+
(style) => style instanceof LineStyle ? style : new LineStyle({
|
|
346
|
+
...style,
|
|
347
|
+
startZoom: style.startZoom ?? startZoom
|
|
348
|
+
})
|
|
349
|
+
);
|
|
227
350
|
this.delWidthFactor = delWidthFactor;
|
|
228
351
|
this.lineExtensionFactor = lineExtensionFactor;
|
|
229
352
|
}
|
|
230
353
|
/**
|
|
231
354
|
* Get line styles active at a given zoom level
|
|
232
355
|
* @param {number} z - Zoom level
|
|
233
|
-
* @returns {
|
|
356
|
+
* @returns {LineStyle[]}
|
|
234
357
|
*/
|
|
235
358
|
getLineStylesForZoom(z2) {
|
|
236
|
-
return this.lineStyles.filter((style) =>
|
|
359
|
+
return this.lineStyles.filter((style) => style.isActiveAtZoom(z2));
|
|
237
360
|
}
|
|
238
361
|
/**
|
|
239
362
|
* Check if this config matches the given template URLs (with {z}/{x}/{y} placeholders)
|
|
@@ -296,17 +419,19 @@ var LayerConfig = class _LayerConfig {
|
|
|
296
419
|
zoomThreshold: this.zoomThreshold,
|
|
297
420
|
tileUrlTemplates: this.tileUrlTemplates,
|
|
298
421
|
lineWidthStops: this.lineWidthStops,
|
|
299
|
-
lineStyles: this.lineStyles,
|
|
422
|
+
lineStyles: this.lineStyles.map((s) => s.toJSON()),
|
|
300
423
|
delWidthFactor: this.delWidthFactor,
|
|
301
424
|
lineExtensionFactor: this.lineExtensionFactor
|
|
302
425
|
};
|
|
303
426
|
}
|
|
304
427
|
/**
|
|
305
|
-
* Create a LayerConfig from a plain object
|
|
428
|
+
* Create a LayerConfig from a plain object with validation.
|
|
306
429
|
* @param {Object} obj
|
|
307
430
|
* @returns {LayerConfig}
|
|
431
|
+
* @throws {Error} If validation fails
|
|
308
432
|
*/
|
|
309
433
|
static fromJSON(obj) {
|
|
434
|
+
_LayerConfig.validateJSON(obj);
|
|
310
435
|
return new _LayerConfig(obj);
|
|
311
436
|
}
|
|
312
437
|
};
|
|
@@ -2554,10 +2679,11 @@ var CorrectionsSource = class {
|
|
|
2554
2679
|
* @param {number} z
|
|
2555
2680
|
* @param {number} x
|
|
2556
2681
|
* @param {number} y
|
|
2682
|
+
* @param {AbortSignal} [signal] - Optional abort signal
|
|
2557
2683
|
* @returns {Promise<Object<string, Array>>}
|
|
2558
2684
|
* @private
|
|
2559
2685
|
*/
|
|
2560
|
-
async _fetchTile(z2, x22, y) {
|
|
2686
|
+
async _fetchTile(z2, x22, y, signal) {
|
|
2561
2687
|
const idx = toIndex(z2, x22, y);
|
|
2562
2688
|
return new Promise((resolve, reject) => {
|
|
2563
2689
|
const entry = this.cache.get(idx);
|
|
@@ -2572,7 +2698,7 @@ var CorrectionsSource = class {
|
|
|
2572
2698
|
return;
|
|
2573
2699
|
}
|
|
2574
2700
|
this.inflight.set(idx, []);
|
|
2575
|
-
this.pmtiles.getZxy(z2, x22, y).then((result) => {
|
|
2701
|
+
this.pmtiles.getZxy(z2, x22, y, signal).then((result) => {
|
|
2576
2702
|
let data;
|
|
2577
2703
|
if (result) {
|
|
2578
2704
|
data = parseTile(result.data);
|
|
@@ -2611,9 +2737,10 @@ var CorrectionsSource = class {
|
|
|
2611
2737
|
* @param {number} z - Zoom level
|
|
2612
2738
|
* @param {number} x - Tile X coordinate
|
|
2613
2739
|
* @param {number} y - Tile Y coordinate
|
|
2740
|
+
* @param {AbortSignal} [signal] - Optional abort signal
|
|
2614
2741
|
* @returns {Promise<Object<string, Array>>} Map of layer name to array of features
|
|
2615
2742
|
*/
|
|
2616
|
-
async get(z2, x22, y) {
|
|
2743
|
+
async get(z2, x22, y, signal) {
|
|
2617
2744
|
const maxDataZoom = await this._getMaxDataZoom();
|
|
2618
2745
|
if (z2 > maxDataZoom) {
|
|
2619
2746
|
const zoomDiff = z2 - maxDataZoom;
|
|
@@ -2622,13 +2749,13 @@ var CorrectionsSource = class {
|
|
|
2622
2749
|
const parentY = Math.floor(y / scale);
|
|
2623
2750
|
const offsetX = x22 % scale;
|
|
2624
2751
|
const offsetY = y % scale;
|
|
2625
|
-
const corrections = await this._fetchTile(maxDataZoom, parentX, parentY);
|
|
2752
|
+
const corrections = await this._fetchTile(maxDataZoom, parentX, parentY, signal);
|
|
2626
2753
|
if (Object.keys(corrections).length > 0) {
|
|
2627
2754
|
return transformForOverzoom(corrections, scale, offsetX, offsetY);
|
|
2628
2755
|
}
|
|
2629
2756
|
return {};
|
|
2630
2757
|
}
|
|
2631
|
-
return await this._fetchTile(z2, x22, y);
|
|
2758
|
+
return await this._fetchTile(z2, x22, y, signal);
|
|
2632
2759
|
}
|
|
2633
2760
|
};
|
|
2634
2761
|
var TileFetchError = class _TileFetchError extends Error {
|
|
@@ -2659,6 +2786,25 @@ var TileFetchError = class _TileFetchError extends Error {
|
|
|
2659
2786
|
}
|
|
2660
2787
|
};
|
|
2661
2788
|
var MIN_LINE_WIDTH = 0.5;
|
|
2789
|
+
var DEFAULT_TILE_EXTENT = 4096;
|
|
2790
|
+
var DEFAULT_LINE_WIDTH = 1;
|
|
2791
|
+
function buildFetchOptions(crossOrigin, referrerPolicy) {
|
|
2792
|
+
const options = {};
|
|
2793
|
+
if (crossOrigin === "use-credentials") {
|
|
2794
|
+
options.mode = "cors";
|
|
2795
|
+
options.credentials = "include";
|
|
2796
|
+
} else if (crossOrigin === "anonymous" || crossOrigin === "" || crossOrigin === true) {
|
|
2797
|
+
options.mode = "cors";
|
|
2798
|
+
options.credentials = "omit";
|
|
2799
|
+
} else {
|
|
2800
|
+
options.mode = "cors";
|
|
2801
|
+
options.credentials = "same-origin";
|
|
2802
|
+
}
|
|
2803
|
+
if (referrerPolicy) {
|
|
2804
|
+
options.referrerPolicy = referrerPolicy;
|
|
2805
|
+
}
|
|
2806
|
+
return options;
|
|
2807
|
+
}
|
|
2662
2808
|
function getLineWidth(zoom, lineWidthStops) {
|
|
2663
2809
|
const zooms = Object.keys(lineWidthStops).map(Number).sort((a, b2) => a - b2);
|
|
2664
2810
|
if (lineWidthStops[zoom] !== void 0) {
|
|
@@ -2690,7 +2836,7 @@ function getLineWidth(zoom, lineWidthStops) {
|
|
|
2690
2836
|
return w1 + t * (w2 - w1);
|
|
2691
2837
|
}
|
|
2692
2838
|
}
|
|
2693
|
-
return
|
|
2839
|
+
return DEFAULT_LINE_WIDTH;
|
|
2694
2840
|
}
|
|
2695
2841
|
function getFeaturesBoundingBox(features, tileSize, padding = 0) {
|
|
2696
2842
|
let minX = Infinity, minY = Infinity;
|
|
@@ -2844,6 +2990,14 @@ function extendFeaturesEnds(features, extensionLength) {
|
|
|
2844
2990
|
return { ...feature, geometry: newGeometry };
|
|
2845
2991
|
});
|
|
2846
2992
|
}
|
|
2993
|
+
function extendFeaturesByFactor(features, extensionFactor, delLineWidth, tileSize) {
|
|
2994
|
+
if (!features || features.length === 0 || extensionFactor <= 0) {
|
|
2995
|
+
return features;
|
|
2996
|
+
}
|
|
2997
|
+
const extent = features[0]?.extent || DEFAULT_TILE_EXTENT;
|
|
2998
|
+
const extensionLength = delLineWidth * extensionFactor / tileSize * extent;
|
|
2999
|
+
return extendFeaturesEnds(features, extensionLength);
|
|
3000
|
+
}
|
|
2847
3001
|
function drawFeatures(ctx, features, color, lineWidth, tileSize, dashArray, alpha) {
|
|
2848
3002
|
const prevAlpha = ctx.globalAlpha;
|
|
2849
3003
|
if (alpha !== void 0) {
|
|
@@ -2907,6 +3061,7 @@ var _TileFixer = class _TileFixer2 {
|
|
|
2907
3061
|
*/
|
|
2908
3062
|
constructor(pmtilesUrl, options = {}) {
|
|
2909
3063
|
this.correctionsSource = new CorrectionsSource(pmtilesUrl, options);
|
|
3064
|
+
this._canvas = null;
|
|
2910
3065
|
this._maskCanvas = null;
|
|
2911
3066
|
}
|
|
2912
3067
|
/**
|
|
@@ -2928,10 +3083,11 @@ var _TileFixer = class _TileFixer2 {
|
|
|
2928
3083
|
* @param {number} z - Zoom level
|
|
2929
3084
|
* @param {number} x - Tile X coordinate
|
|
2930
3085
|
* @param {number} y - Tile Y coordinate
|
|
3086
|
+
* @param {AbortSignal} [signal] - Optional abort signal
|
|
2931
3087
|
* @returns {Promise<Object<string, Array>>} Map of layer name to array of features
|
|
2932
3088
|
*/
|
|
2933
|
-
async getCorrections(z2, x22, y) {
|
|
2934
|
-
return await this.correctionsSource.get(z2, x22, y);
|
|
3089
|
+
async getCorrections(z2, x22, y, signal) {
|
|
3090
|
+
return await this.correctionsSource.get(z2, x22, y, signal);
|
|
2935
3091
|
}
|
|
2936
3092
|
/**
|
|
2937
3093
|
* Apply corrections to a raster tile.
|
|
@@ -2975,7 +3131,7 @@ var _TileFixer = class _TileFixer2 {
|
|
|
2975
3131
|
const ctx = canvas.getContext("2d", { willReadFrequently: true });
|
|
2976
3132
|
ctx.drawImage(imageBitmap, 0, 0, tileSize, tileSize);
|
|
2977
3133
|
const baseLineWidth = getLineWidth(zoom, lineWidthStops);
|
|
2978
|
-
const maxWidthFraction = activeLineStyles.length > 0 ? Math.max(...activeLineStyles.map((s) => s.widthFraction
|
|
3134
|
+
const maxWidthFraction = activeLineStyles.length > 0 ? Math.max(...activeLineStyles.map((s) => s.widthFraction)) : 1;
|
|
2979
3135
|
const delLineWidth = baseLineWidth * maxWidthFraction * delWidthFactor;
|
|
2980
3136
|
const delFeatures = corrections[delLayerName] || [];
|
|
2981
3137
|
if (delFeatures.length > 0) {
|
|
@@ -2986,14 +3142,11 @@ var _TileFixer = class _TileFixer2 {
|
|
|
2986
3142
|
}
|
|
2987
3143
|
let addFeatures = corrections[addLayerName] || [];
|
|
2988
3144
|
if (addFeatures.length > 0 && activeLineStyles.length > 0) {
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
const extent = addFeatures[0]?.extent || 4096;
|
|
2992
|
-
const extensionLength = delLineWidth * extensionFactor / tileSize * extent;
|
|
2993
|
-
addFeatures = extendFeaturesEnds(addFeatures, extensionLength);
|
|
3145
|
+
if (delFeatures.length > 0) {
|
|
3146
|
+
addFeatures = extendFeaturesByFactor(addFeatures, layerConfig.lineExtensionFactor, delLineWidth, tileSize);
|
|
2994
3147
|
}
|
|
2995
3148
|
for (const style of activeLineStyles) {
|
|
2996
|
-
const { color, widthFraction
|
|
3149
|
+
const { color, widthFraction, dashArray, alpha } = style;
|
|
2997
3150
|
const lineWidth = baseLineWidth * widthFraction;
|
|
2998
3151
|
drawFeatures(ctx, addFeatures, color, lineWidth, tileSize, dashArray, alpha);
|
|
2999
3152
|
}
|
|
@@ -3008,17 +3161,17 @@ var _TileFixer = class _TileFixer2 {
|
|
|
3008
3161
|
* @param {number} x - Tile X coordinate
|
|
3009
3162
|
* @param {number} y - Tile Y coordinate
|
|
3010
3163
|
* @param {Object} layerConfig - Layer configuration with colors and styles
|
|
3011
|
-
* @param {Object} [
|
|
3012
|
-
* @param {AbortSignal} [
|
|
3013
|
-
* @param {RequestMode} [
|
|
3014
|
-
* @param {
|
|
3164
|
+
* @param {Object} [fetchOptions] - Fetch options passed to fetch()
|
|
3165
|
+
* @param {AbortSignal} [fetchOptions.signal] - Abort signal for fetch
|
|
3166
|
+
* @param {RequestMode} [fetchOptions.mode] - Fetch mode (e.g., 'cors')
|
|
3167
|
+
* @param {RequestCredentials} [fetchOptions.credentials] - Fetch credentials (e.g., 'omit', 'include')
|
|
3168
|
+
* @param {string} [fetchOptions.referrer] - Referrer URL or empty string for none
|
|
3169
|
+
* @param {ReferrerPolicy} [fetchOptions.referrerPolicy] - Referrer policy (e.g., 'no-referrer', 'origin')
|
|
3170
|
+
* @param {boolean} [fallbackOnCorrectionFailure=true] - Return original tile if corrections fail
|
|
3015
3171
|
* @returns {Promise<{data: ArrayBuffer, wasFixed: boolean}>}
|
|
3016
3172
|
*/
|
|
3017
|
-
async fetchAndFixTile(tileUrl, z2, x22, y, layerConfig,
|
|
3018
|
-
const { signal
|
|
3019
|
-
const fetchOptions = {};
|
|
3020
|
-
if (signal) fetchOptions.signal = signal;
|
|
3021
|
-
if (mode) fetchOptions.mode = mode;
|
|
3173
|
+
async fetchAndFixTile(tileUrl, z2, x22, y, layerConfig, fetchOptions = {}, fallbackOnCorrectionFailure = true) {
|
|
3174
|
+
const { signal } = fetchOptions;
|
|
3022
3175
|
if (!layerConfig) {
|
|
3023
3176
|
const response = await fetch(tileUrl, fetchOptions);
|
|
3024
3177
|
if (!response.ok) throw await TileFetchError.fromResponse(response);
|
|
@@ -3029,11 +3182,9 @@ var _TileFixer = class _TileFixer2 {
|
|
|
3029
3182
|
if (!r.ok) throw await TileFetchError.fromResponse(r);
|
|
3030
3183
|
return r.arrayBuffer();
|
|
3031
3184
|
}),
|
|
3032
|
-
this.getCorrections(z2, x22, y)
|
|
3185
|
+
this.getCorrections(z2, x22, y, signal)
|
|
3033
3186
|
]);
|
|
3034
|
-
|
|
3035
|
-
throw new DOMException("Aborted", "AbortError");
|
|
3036
|
-
}
|
|
3187
|
+
signal?.throwIfAborted();
|
|
3037
3188
|
if (tileResult.status === "rejected") {
|
|
3038
3189
|
throw tileResult.reason;
|
|
3039
3190
|
}
|
|
@@ -3087,6 +3238,9 @@ function extendLeaflet(L2) {
|
|
|
3087
3238
|
},
|
|
3088
3239
|
createTile: function(coords, done) {
|
|
3089
3240
|
const tile = document.createElement("img");
|
|
3241
|
+
const controller = new AbortController();
|
|
3242
|
+
const signal = controller.signal;
|
|
3243
|
+
tile.cancel = () => controller.abort();
|
|
3090
3244
|
tile.alt = "";
|
|
3091
3245
|
if (this.options.crossOrigin || this.options.crossOrigin === "") {
|
|
3092
3246
|
tile.crossOrigin = this.options.crossOrigin === true ? "" : this.options.crossOrigin;
|
|
@@ -3105,13 +3259,16 @@ function extendLeaflet(L2) {
|
|
|
3105
3259
|
const x3 = coords.x;
|
|
3106
3260
|
const y = coords.y;
|
|
3107
3261
|
const fallbackOnCorrectionFailure = this.options.fallbackOnCorrectionFailure;
|
|
3108
|
-
|
|
3262
|
+
const fetchOptions = buildFetchOptions(this.options.crossOrigin, this.options.referrerPolicy);
|
|
3263
|
+
fetchOptions.signal = signal;
|
|
3264
|
+
this._tileFixer.fetchAndFixTile(tileUrl, z2, x3, y, this._layerConfig, fetchOptions, fallbackOnCorrectionFailure).then(({ data, correctionsFailed, correctionsError }) => {
|
|
3109
3265
|
if (correctionsFailed) {
|
|
3110
3266
|
console.warn("[L.TileLayer.IndiaBoundaryCorrected] Corrections fetch failed:", correctionsError);
|
|
3111
3267
|
this.fire("correctionerror", { error: correctionsError, coords: { z: z2, x: x3, y }, tileUrl });
|
|
3112
3268
|
}
|
|
3113
3269
|
const blob = new Blob([data]);
|
|
3114
3270
|
tile.src = URL.createObjectURL(blob);
|
|
3271
|
+
tile.cancel = void 0;
|
|
3115
3272
|
tile.onload = () => {
|
|
3116
3273
|
URL.revokeObjectURL(tile.src);
|
|
3117
3274
|
done(null, tile);
|
|
@@ -3121,11 +3278,19 @@ function extendLeaflet(L2) {
|
|
|
3121
3278
|
done(e, tile);
|
|
3122
3279
|
};
|
|
3123
3280
|
}).catch((err2) => {
|
|
3124
|
-
|
|
3125
|
-
|
|
3281
|
+
if (err2.name !== "AbortError") {
|
|
3282
|
+
console.warn("[L.TileLayer.IndiaBoundaryCorrected] Tile fetch failed:", err2);
|
|
3283
|
+
done(err2, tile);
|
|
3284
|
+
}
|
|
3126
3285
|
});
|
|
3127
3286
|
return tile;
|
|
3128
3287
|
},
|
|
3288
|
+
_removeTile: function(key) {
|
|
3289
|
+
const tile = this._tiles[key];
|
|
3290
|
+
if (!tile) return;
|
|
3291
|
+
if (tile.el.cancel) tile.el.cancel();
|
|
3292
|
+
L2.TileLayer.prototype._removeTile.call(this, key);
|
|
3293
|
+
},
|
|
3129
3294
|
getTileFixer: function() {
|
|
3130
3295
|
return this._tileFixer;
|
|
3131
3296
|
},
|