"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; // dist/index.js var dist_exports = {}; __export(dist_exports, { MVTLoader: () => MVTLoader, MVTSource: () => MVTSource, MVTWorkerLoader: () => MVTWorkerLoader, TableTileSource: () => TableTileSource, TileJSONLoader: () => TileJSONLoader }); module.exports = __toCommonJS(dist_exports); // dist/lib/get-schemas-from-tilejson.js function getSchemaFromTileJSONLayer(layer) { const fields = []; if (layer.fields) { for (const field of layer.fields) { fields.push({ name: field.name, type: getDataTypeFromTileJSONField(field), metadata: getMetadataFromTileJSONField(field) }); } } return { metadata: getMetadataFromTileJSONLayer(layer), fields }; } function getMetadataFromTileJSONLayer(layer) { const metadata = {}; for (const [key, value] of Object.entries(layer)) { if (key !== "fields" && value) { metadata[key] = JSON.stringify(value); } } return metadata; } function getDataTypeFromTileJSONField(field) { switch (field.type.toLowerCase()) { case "float32": return "float32"; case "number": case "float64": return "float64"; case "string": case "utf8": return "utf8"; case "boolean": return "bool"; default: return "null"; } } function getMetadataFromTileJSONField(field) { const metadata = {}; for (const [key, value] of Object.entries(field)) { if (key !== "name" && value) { metadata[key] = JSON.stringify(value); } } return metadata; } // dist/lib/parse-tilejson.js var isObject = (x) => x !== null && typeof x === "object"; function parseTileJSON(jsonMetadata, options) { var _a; if (!jsonMetadata || !isObject(jsonMetadata)) { return null; } let tileJSON = { name: jsonMetadata.name || "", description: jsonMetadata.description || "" }; if (typeof jsonMetadata.generator === "string") { tileJSON.generator = jsonMetadata.generator; } if (typeof jsonMetadata.generator_options === "string") { tileJSON.generatorOptions = jsonMetadata.generator_options; } tileJSON.boundingBox = parseBounds(jsonMetadata.bounds) || parseBounds(jsonMetadata.antimeridian_adjusted_bounds); tileJSON.center = parseCenter(jsonMetadata.center); tileJSON.maxZoom = safeParseFloat(jsonMetadata.maxzoom); tileJSON.minZoom = safeParseFloat(jsonMetadata.minzoom); if (typeof (jsonMetadata == null ? void 0 : jsonMetadata.json) === "string") { try { tileJSON.metaJson = JSON.parse(jsonMetadata.json); } catch (error) { console.warn("Failed to parse tilejson.json field", error); } } const tilestats = jsonMetadata.tilestats || ((_a = tileJSON.metaJson) == null ? void 0 : _a.tilestats); const tileStatsLayers = parseTilestatsLayers(tilestats, options); const tileJSONlayers = parseTileJSONLayers(jsonMetadata.vector_layers); const layers = mergeLayers(tileJSONlayers, tileStatsLayers); tileJSON = { ...tileJSON, layers }; if (tileJSON.maxZoom === null && layers.length > 0) { tileJSON.maxZoom = layers[0].maxZoom || null; } if (tileJSON.minZoom === null && layers.length > 0) { tileJSON.minZoom = layers[0].minZoom || null; } return tileJSON; } function parseTileJSONLayers(layers) { if (!Array.isArray(layers)) { return []; } return layers.map((layer) => parseTileJSONLayer(layer)); } function parseTileJSONLayer(layer) { const fields = Object.entries(layer.fields || []).map(([key, datatype]) => ({ name: key, ...attributeTypeToFieldType(String(datatype)) })); const layer2 = { ...layer }; delete layer2.fields; return { name: layer.id || "", ...layer2, fields }; } function parseTilestatsLayers(tilestats, options) { if (isObject(tilestats) && Array.isArray(tilestats.layers)) { return tilestats.layers.map((layer) => parseTilestatsForLayer(layer, options)); } return []; } function parseTilestatsForLayer(layer, options) { const fields = []; const indexedAttributes = {}; const attributes = layer.attributes || []; for (const attribute of attributes) { const name = attribute.attribute; if (typeof name === "string") { if (name.split("|").length > 1) { const fname = name.split("|")[0]; indexedAttributes[fname] = indexedAttributes[fname] || []; indexedAttributes[fname].push(attribute); console.warn("ignoring tilestats indexed field", fname); } else if (!fields[name]) { fields.push(attributeToField(attribute, options)); } else { } } } return { name: layer.layer || "", dominantGeometry: layer.geometry, fields }; } function mergeLayers(layers, tilestatsLayers) { return layers.map((layer) => { const tilestatsLayer = tilestatsLayers.find((tsLayer) => tsLayer.name === layer.name); const fields = (tilestatsLayer == null ? void 0 : tilestatsLayer.fields) || layer.fields || []; const mergedLayer = { ...layer, ...tilestatsLayer, fields }; mergedLayer.schema = getSchemaFromTileJSONLayer(mergedLayer); return mergedLayer; }); } function parseBounds(bounds) { const result = fromArrayOrString(bounds); if (Array.isArray(result) && result.length === 4 && [result[0], result[2]].every(isLng) && [result[1], result[3]].every(isLat)) { return [ [result[0], result[1]], [result[2], result[3]] ]; } return void 0; } function parseCenter(center) { const result = fromArrayOrString(center); if (Array.isArray(result) && result.length === 3 && isLng(result[0]) && isLat(result[1]) && isZoom(result[2])) { return result; } return null; } function safeParseFloat(input) { const result = typeof input === "string" ? parseFloat(input) : typeof input === "number" ? input : null; return result === null || isNaN(result) ? null : result; } function isLat(num) { return Number.isFinite(num) && num <= 90 && num >= -90; } function isLng(num) { return Number.isFinite(num) && num <= 180 && num >= -180; } function isZoom(num) { return Number.isFinite(num) && num >= 0 && num <= 22; } function fromArrayOrString(data) { if (typeof data === "string") { return data.split(",").map(parseFloat); } else if (Array.isArray(data)) { return data; } return null; } var attrTypeMap = { number: { type: "float32" }, numeric: { type: "float32" }, string: { type: "utf8" }, vachar: { type: "utf8" }, float: { type: "float32" }, int: { type: "int32" }, int4: { type: "int32" }, boolean: { type: "boolean" }, bool: { type: "boolean" } }; function attributeToField(attribute = {}, options) { var _a; const fieldTypes = attributeTypeToFieldType(attribute.type); const field = { name: attribute.attribute, // what happens if attribute type is string... // filterProps: getFilterProps(fieldTypes.type, attribute), ...fieldTypes }; if (typeof attribute.min === "number") { field.min = attribute.min; } if (typeof attribute.max === "number") { field.max = attribute.max; } if (typeof attribute.count === "number") { field.uniqueValueCount = attribute.count; } if (attribute.values) { field.values = attribute.values; } if (field.values && typeof options.maxValues === "number") { field.values = (_a = field.values) == null ? void 0 : _a.slice(0, options.maxValues); } return field; } function attributeTypeToFieldType(aType) { const type = aType.toLowerCase(); if (!type || !attrTypeMap[type]) { } return attrTypeMap[type] || { type: "string" }; } // dist/tilejson-loader.js var VERSION = true ? "4.3.1" : "latest"; var TileJSONLoader = { dataType: null, batchType: null, name: "TileJSON", id: "tilejson", module: "pmtiles", version: VERSION, worker: true, extensions: ["json"], mimeTypes: ["application/json"], text: true, options: { tilejson: { maxValues: void 0 } }, parse: async (arrayBuffer, options) => { const jsonString = new TextDecoder().decode(arrayBuffer); const json = JSON.parse(jsonString); const tilejsonOptions = { ...TileJSONLoader.options.tilejson, ...options == null ? void 0 : options.tilejson }; return parseTileJSON(json, tilejsonOptions); }, parseTextSync: (text, options) => { const json = JSON.parse(text); const tilejsonOptions = { ...TileJSONLoader.options.tilejson, ...options == null ? void 0 : options.tilejson }; return parseTileJSON(json, tilejsonOptions); } }; // dist/lib/parse-mvt.js var import_gis = require("@loaders.gl/gis"); var import_loader_utils = require("@loaders.gl/loader-utils"); var import_pbf = __toESM(require("pbf"), 1); // dist/lib/utils/geometry-utils.js var import_polygon = require("@math.gl/polygon"); function signedArea(ring) { let sum = 0; for (let i = 0, j = ring.length - 1, p1, p2; i < ring.length; j = i++) { p1 = ring[i]; p2 = ring[j]; sum += (p2[0] - p1[0]) * (p1[1] + p2[1]); } return sum; } function convertToLocalCoordinates(coordinates, extent) { if (Array.isArray(coordinates[0])) { for (const subcoords of coordinates) { convertToLocalCoordinates(subcoords, extent); } return; } const p = coordinates; p[0] /= extent; p[1] /= extent; } function convertToLocalCoordinatesFlat(data, extent) { for (let i = 0; i < data.length; ++i) { data[i] /= extent; } } function projectToLngLat(line, tileIndex, extent) { if (typeof line[0][0] !== "number") { for (const point of line) { projectToLngLat(point, tileIndex, extent); } return; } const size = extent * Math.pow(2, tileIndex.z); const x0 = extent * tileIndex.x; const y0 = extent * tileIndex.y; for (let j = 0; j < line.length; j++) { const p = line[j]; p[0] = (p[0] + x0) * 360 / size - 180; const y2 = 180 - (p[1] + y0) * 360 / size; p[1] = 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90; } } function projectToLngLatFlat(data, tileIndex, extent) { const { x, y, z } = tileIndex; const size = extent * Math.pow(2, z); const x0 = extent * x; const y0 = extent * y; for (let j = 0, jl = data.length; j < jl; j += 2) { data[j] = (data[j] + x0) * 360 / size - 180; const y2 = 180 - (data[j + 1] + y0) * 360 / size; data[j + 1] = 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90; } } function classifyRings(rings) { const len = rings.length; if (len <= 1) return [rings]; const polygons = []; let polygon; let ccw; for (let i = 0; i < len; i++) { const area = signedArea(rings[i]); if (area === 0) continue; if (ccw === void 0) ccw = area < 0; if (ccw === area < 0) { if (polygon) polygons.push(polygon); polygon = [rings[i]]; } else if (polygon) polygon.push(rings[i]); } if (polygon) polygons.push(polygon); return polygons; } function classifyRingsFlat(geom) { const len = geom.indices.length; const type = "Polygon"; if (len <= 1) { return { type, data: geom.data, areas: [[(0, import_polygon.getPolygonSignedArea)(geom.data)]], indices: [geom.indices] }; } const areas = []; const polygons = []; let ringAreas = []; let polygon = []; let ccw; let offset = 0; for (let endIndex, i = 0, startIndex; i < len; i++) { startIndex = geom.indices[i] - offset; endIndex = geom.indices[i + 1] - offset || geom.data.length; const shape = geom.data.slice(startIndex, endIndex); const area = (0, import_polygon.getPolygonSignedArea)(shape); if (area === 0) { const before = geom.data.slice(0, startIndex); const after = geom.data.slice(endIndex); geom.data = before.concat(after); offset += endIndex - startIndex; continue; } if (ccw === void 0) ccw = area < 0; if (ccw === area < 0) { if (polygon.length) { areas.push(ringAreas); polygons.push(polygon); } polygon = [startIndex]; ringAreas = [area]; } else { ringAreas.push(area); polygon.push(startIndex); } } if (ringAreas) areas.push(ringAreas); if (polygon.length) polygons.push(polygon); return { type, areas, indices: polygons, data: geom.data }; } // dist/lib/vector-tile/vector-tile-feature.js var VectorTileFeature = class { properties; extent; type; id; _pbf; _geometry; _keys; _values; _geometryInfo; // eslint-disable-next-line max-params constructor(pbf, end, extent, keys, values, geometryInfo) { this.properties = {}; this.extent = extent; this.type = 0; this.id = null; this._pbf = pbf; this._geometry = -1; this._keys = keys; this._values = values; this._geometryInfo = geometryInfo; pbf.readFields(readFeature, this, end); } toGeoJSONFeature(coordinates, tileIndex) { const coords = this.loadGeometry(); switch (coordinates) { case "wgs84": return _toGeoJSONFeature(this, coords, (line) => projectToLngLat(line, tileIndex, this.extent)); default: return _toGeoJSONFeature(this, coords, convertToLocalCoordinates); } } /** * * @param options * @returns */ toBinaryFeature(coordinates, tileIndex) { const geom = this.loadFlatGeometry(); switch (coordinates) { case "wgs84": return this._toBinaryCoordinates(geom, (coords) => projectToLngLatFlat(coords, tileIndex, this.extent)); default: return this._toBinaryCoordinates(geom, convertToLocalCoordinatesFlat); } } /** Read a bounding box from the feature */ // eslint-disable-next-line max-statements bbox() { const pbf = this._pbf; pbf.pos = this._geometry; const end = pbf.readVarint() + pbf.pos; let cmd = 1; let length = 0; let x = 0; let y = 0; let x1 = Infinity; let x2 = -Infinity; let y1 = Infinity; let y2 = -Infinity; while (pbf.pos < end) { if (length <= 0) { const cmdLen = pbf.readVarint(); cmd = cmdLen & 7; length = cmdLen >> 3; } length--; if (cmd === 1 || cmd === 2) { x += pbf.readSVarint(); y += pbf.readSVarint(); if (x < x1) x1 = x; if (x > x2) x2 = x; if (y < y1) y1 = y; if (y > y2) y2 = y; } else if (cmd !== 7) { throw new Error(`unknown command ${cmd}`); } } return [x1, y1, x2, y2]; } // BINARY HELPERS /** * * @param transform * @returns result */ _toBinaryCoordinates(geom, transform) { let geometry; transform(geom.data, this.extent); const coordLength = 2; switch (this.type) { case 1: this._geometryInfo.pointFeaturesCount++; this._geometryInfo.pointPositionsCount += geom.indices.length; geometry = { type: "Point", ...geom }; break; case 2: this._geometryInfo.lineFeaturesCount++; this._geometryInfo.linePathsCount += geom.indices.length; this._geometryInfo.linePositionsCount += geom.data.length / coordLength; geometry = { type: "LineString", ...geom }; break; case 3: geometry = classifyRingsFlat(geom); this._geometryInfo.polygonFeaturesCount++; this._geometryInfo.polygonObjectsCount += geometry.indices.length; for (const indices of geometry.indices) { this._geometryInfo.polygonRingsCount += indices.length; } this._geometryInfo.polygonPositionsCount += geometry.data.length / coordLength; break; default: throw new Error(`Invalid geometry type: ${this.type}`); } const result = { type: "Feature", geometry, properties: this.properties }; if (this.id !== null) { result.id = this.id; } return result; } // GEOJSON HELPER // eslint-disable-next-line complexity, max-statements loadGeometry() { const pbf = this._pbf; pbf.pos = this._geometry; const end = pbf.readVarint() + pbf.pos; let cmd = 1; let length = 0; let x = 0; let y = 0; const lines = []; let line; while (pbf.pos < end) { if (length <= 0) { const cmdLen = pbf.readVarint(); cmd = cmdLen & 7; length = cmdLen >> 3; } length--; switch (cmd) { case 1: case 2: x += pbf.readSVarint(); y += pbf.readSVarint(); if (cmd === 1) { if (line) lines.push(line); line = []; } if (line) line.push([x, y]); break; case 7: if (line) { line.push(line[0].slice()); } break; default: throw new Error(`unknown command ${cmd}`); } } if (line) lines.push(line); return lines; } /** * Expands the protobuf data to an intermediate Flat GeoJSON * data format, which maps closely to the binary data buffers. * It is similar to GeoJSON, but rather than storing the coordinates * in multidimensional arrays, we have a 1D `data` with all the * coordinates, and then index into this using the `indices` * parameter, e.g. * * geometry: { * type: 'Point', data: [1,2], indices: [0] * } * geometry: { * type: 'LineString', data: [1,2,3,4,...], indices: [0] * } * geometry: { * type: 'Polygon', data: [1,2,3,4,...], indices: [[0, 2]] * } * Thus the indices member lets us look up the relevant range * from the data array. * The Multi* versions of the above types share the same data * structure, just with multiple elements in the indices array */ // eslint-disable-next-line complexity, max-statements loadFlatGeometry() { const pbf = this._pbf; pbf.pos = this._geometry; const endPos = pbf.readVarint() + pbf.pos; let cmd = 1; let cmdLen; let length = 0; let x = 0; let y = 0; let i = 0; const indices = []; const data = []; while (pbf.pos < endPos) { if (length <= 0) { cmdLen = pbf.readVarint(); cmd = cmdLen & 7; length = cmdLen >> 3; } length--; if (cmd === 1 || cmd === 2) { x += pbf.readSVarint(); y += pbf.readSVarint(); if (cmd === 1) { indices.push(i); } data.push(x, y); i += 2; } else if (cmd === 7) { if (i > 0) { const start = indices[indices.length - 1]; data.push(data[start], data[start + 1]); i += 2; } } else { throw new Error(`unknown command ${cmd}`); } } return { data, indices }; } }; __publicField(VectorTileFeature, "types", ["Unknown", "Point", "LineString", "Polygon"]); function _toGeoJSONFeature(vtFeature, coords, transform) { let type = VectorTileFeature.types[vtFeature.type]; let i; let j; let coordinates; switch (vtFeature.type) { case 1: const points = []; for (i = 0; i < coords.length; i++) { points[i] = coords[i][0]; } coordinates = points; transform(coordinates, vtFeature.extent); break; case 2: coordinates = coords; for (i = 0; i < coordinates.length; i++) { transform(coordinates[i], vtFeature.extent); } break; case 3: coordinates = classifyRings(coords); for (i = 0; i < coordinates.length; i++) { for (j = 0; j < coordinates[i].length; j++) { transform(coordinates[i][j], vtFeature.extent); } } break; default: throw new Error("illegal vector tile type"); } if (coordinates.length === 1) { coordinates = coordinates[0]; } else { type = `Multi${type}`; } const result = { type: "Feature", geometry: { type, coordinates }, properties: vtFeature.properties }; if (vtFeature.id !== null) { result.properties ||= {}; result.properties.id = vtFeature.id; } return result; } function readFeature(tag, feature, pbf) { if (feature && pbf) { if (tag === 1) feature.id = pbf.readVarint(); else if (tag === 2) readTag(pbf, feature); else if (tag === 3) feature.type = pbf.readVarint(); else if (tag === 4) feature._geometry = pbf.pos; } } function readTag(pbf, feature) { const end = pbf.readVarint() + pbf.pos; while (pbf.pos < end) { const key = feature._keys[pbf.readVarint()]; const value = feature._values[pbf.readVarint()]; feature.properties[key] = value; } } // dist/lib/vector-tile/vector-tile-layer.js var VectorTileLayer = class { version; name; extent; length; _pbf; _keys; _values; _features; constructor(pbf, end) { this.version = 1; this.name = ""; this.extent = 4096; this.length = 0; this._pbf = pbf; this._keys = []; this._values = []; this._features = []; pbf.readFields(readLayer, this, end); this.length = this._features.length; } /** * return feature `i` from this layer as a `VectorTileFeature` * @param index * @returns feature */ getGeoJSONFeature(i) { if (i < 0 || i >= this._features.length) { throw new Error("feature index out of bounds"); } this._pbf.pos = this._features[i]; const end = this._pbf.readVarint() + this._pbf.pos; return new VectorTileFeature(this._pbf, end, this.extent, this._keys, this._values); } /** * return binary feature `i` from this layer as a `VectorTileFeature` * * @param index * @param geometryInfo * @returns binary feature */ getBinaryFeature(i, geometryInfo) { if (i < 0 || i >= this._features.length) { throw new Error("feature index out of bounds"); } this._pbf.pos = this._features[i]; const end = this._pbf.readVarint() + this._pbf.pos; return new VectorTileFeature(this._pbf, end, this.extent, this._keys, this._values, geometryInfo); } }; function readLayer(tag, layer, pbf) { if (layer && pbf) { if (tag === 15) layer.version = pbf.readVarint(); else if (tag === 1) layer.name = pbf.readString(); else if (tag === 5) layer.extent = pbf.readVarint(); else if (tag === 2) layer._features.push(pbf.pos); else if (tag === 3) layer._keys.push(pbf.readString()); else if (tag === 4) layer._values.push(readValueMessage(pbf)); } } function readValueMessage(pbf) { let value = null; const end = pbf.readVarint() + pbf.pos; while (pbf.pos < end) { const tag = pbf.readVarint() >> 3; 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; } return value; } // dist/lib/vector-tile/vector-tile.js var VectorTile = class { layers; constructor(pbf, end) { this.layers = pbf.readFields(readTile, {}, end); } }; function readTile(tag, layers, pbf) { if (tag === 3) { if (pbf) { const layer = new VectorTileLayer(pbf, pbf.readVarint() + pbf.pos); if (layer.length && layers) { layers[layer.name] = layer; } } } } // dist/lib/parse-mvt.js function parseMVT(arrayBuffer, options) { var _a, _b; const mvtOptions = checkOptions(options); const shape = ((_a = options == null ? void 0 : options.gis) == null ? void 0 : _a.format) || ((_b = options == null ? void 0 : options.mvt) == null ? void 0 : _b.shape) || (options == null ? void 0 : options.shape); switch (shape) { case "columnar-table": return { shape: "columnar-table", data: parseToBinary(arrayBuffer, mvtOptions) }; case "geojson-table": { const table = { shape: "geojson-table", type: "FeatureCollection", features: parseToGeojsonFeatures(arrayBuffer, mvtOptions) }; return table; } case "geojson": return parseToGeojsonFeatures(arrayBuffer, mvtOptions); case "binary-geometry": return parseToBinary(arrayBuffer, mvtOptions); case "binary": return parseToBinary(arrayBuffer, mvtOptions); default: throw new Error(shape || "undefined shape"); } } function parseToBinary(arrayBuffer, options) { const [flatGeoJsonFeatures, geometryInfo] = parseToFlatGeoJson(arrayBuffer, options); const binaryData = (0, import_gis.flatGeojsonToBinary)(flatGeoJsonFeatures, geometryInfo); binaryData.byteLength = arrayBuffer.byteLength; return binaryData; } function parseToFlatGeoJson(arrayBuffer, options) { const features2 = []; const geometryInfo = { coordLength: 2, pointPositionsCount: 0, pointFeaturesCount: 0, linePositionsCount: 0, linePathsCount: 0, lineFeaturesCount: 0, polygonPositionsCount: 0, polygonObjectsCount: 0, polygonRingsCount: 0, polygonFeaturesCount: 0 }; if (arrayBuffer.byteLength <= 0) { return [features2, geometryInfo]; } const tile = new VectorTile(new import_pbf.default(arrayBuffer)); const selectedLayers = options && Array.isArray(options.layers) ? options.layers : Object.keys(tile.layers); selectedLayers.forEach((layerName) => { const vectorTileLayer = tile.layers[layerName]; if (!vectorTileLayer) { return; } for (let i = 0; i < vectorTileLayer.length; i++) { const vectorTileFeature = vectorTileLayer.getBinaryFeature(i, geometryInfo); const decodedFeature = getDecodedFeatureBinary(vectorTileFeature, options, layerName); features2.push(decodedFeature); } }); return [features2, geometryInfo]; } function parseToGeojsonFeatures(arrayBuffer, options) { if (arrayBuffer.byteLength <= 0) { return []; } const features2 = []; const tile = new VectorTile(new import_pbf.default(arrayBuffer)); const selectedLayers = Array.isArray(options.layers) ? options.layers : Object.keys(tile.layers); selectedLayers.forEach((layerName) => { const vectorTileLayer = tile.layers[layerName]; if (!vectorTileLayer) { return; } for (let i = 0; i < vectorTileLayer.length; i++) { const vectorTileFeature = vectorTileLayer.getGeoJSONFeature(i); const decodedFeature = getDecodedFeature(vectorTileFeature, options, layerName); features2.push(decodedFeature); } }); return features2; } function checkOptions(options) { var _a; if (!(options == null ? void 0 : options.mvt)) { throw new Error("mvt options required"); } if (((_a = options.mvt) == null ? void 0 : _a.coordinates) === "wgs84" && !options.mvt.tileIndex) { throw new Error("MVT Loader: WGS84 coordinates need tileIndex property"); } if (options.gis) { import_loader_utils.log.warn('MVTLoader: "options.gis" is deprecated, use "options.mvt.shape" instead')(); } return options.mvt; } function getDecodedFeature(feature, options, layerName) { const decodedFeature = feature.toGeoJSONFeature(options.coordinates || "local", options.tileIndex); if (options.layerProperty) { decodedFeature.properties ||= {}; decodedFeature.properties[options.layerProperty] = layerName; } return decodedFeature; } function getDecodedFeatureBinary(feature, options, layerName) { const decodedFeature = feature.toBinaryFeature(options.coordinates || "local", options.tileIndex); if (options.layerProperty && decodedFeature.properties) { decodedFeature.properties[options.layerProperty] = layerName; } return decodedFeature; } // dist/mvt-loader.js var VERSION2 = true ? "4.3.1" : "latest"; var MVTWorkerLoader = { dataType: null, batchType: null, name: "Mapbox Vector Tile", id: "mvt", module: "mvt", version: VERSION2, // Note: ArcGIS uses '.pbf' extension and 'application/octet-stream' extensions: ["mvt", "pbf"], mimeTypes: [ // https://www.iana.org/assignments/media-types/application/vnd.mapbox-vector-tile "application/vnd.mapbox-vector-tile", "application/x-protobuf" // 'application/octet-stream' ], worker: true, category: "geometry", options: { mvt: { shape: "geojson", coordinates: "local", layerProperty: "layerName", layers: void 0, tileIndex: void 0 } } }; var MVTLoader = { ...MVTWorkerLoader, parse: async (arrayBuffer, options) => parseMVT(arrayBuffer, options), parseSync: parseMVT, binary: true }; // dist/mvt-source.js var import_loader_utils2 = require("@loaders.gl/loader-utils"); var import_images = require("@loaders.gl/images"); var import_mvt = require("@loaders.gl/mvt"); var MVTSource = { name: "MVT", id: "mvt", module: "mvt", version: "0.0.0", extensions: ["mvt"], mimeTypes: ["application/octet-stream"], options: { mvt: { // TODO - add options here } }, type: "mvt", fromUrl: true, fromBlob: false, testURL: (url) => true, createDataSource(url, props) { return new MVTTileSource(url, props); } }; var MVTTileSource = class extends import_loader_utils2.DataSource { props; url; metadataUrl = null; data; schema = "tms"; metadata; extension; mimeType = null; constructor(url, props) { var _a, _b; super(props); this.props = props; this.url = (0, import_loader_utils2.resolvePath)(url); this.metadataUrl = ((_a = props.mvt) == null ? void 0 : _a.metadataUrl) || `${this.url}/tilejson.json`; this.extension = ((_b = props.mvt) == null ? void 0 : _b.extension) || ".png"; this.data = this.url; this.getTileData = this.getTileData.bind(this); this.metadata = this.getMetadata(); if (isURLTemplate(this.url)) { this.schema = "template"; } } // @ts-ignore - Metadata type misalignment async getMetadata() { var _a, _b; if (!this.metadataUrl) { return null; } let response; try { response = await this.fetch(this.metadataUrl); } catch (error) { console.error(error.message); return null; } if (!response.ok) { console.error(response.statusText); return null; } const tileJSON = await response.text(); const metadata = ((_b = (_a = import_mvt.TileJSONLoader).parseTextSync) == null ? void 0 : _b.call(_a, tileJSON)) || null; return metadata; } getTileMIMEType() { return this.mimeType; } async getTile(parameters) { const { x, y, z } = parameters; const tileUrl = this.getTileURL(x, y, z); const response = await this.fetch(tileUrl); if (!response.ok) { return null; } const arrayBuffer = await response.arrayBuffer(); return arrayBuffer; } // Tile Source interface implementation: deck.gl compatible API // TODO - currently only handles image tiles, not vector tiles async getTileData(parameters) { const { x, y, z } = parameters.index; const arrayBuffer = await this.getTile({ x, y, z, layers: [] }); if (arrayBuffer === null) { return null; } const imageMetadata = (0, import_images.getBinaryImageMetadata)(arrayBuffer); this.mimeType = this.mimeType || (imageMetadata == null ? void 0 : imageMetadata.mimeType) || "application/vnd.mapbox-vector-tile"; switch (this.mimeType) { case "application/vnd.mapbox-vector-tile": return await this._parseVectorTile(arrayBuffer, { x, y, z, layers: [] }); default: return await this._parseImageTile(arrayBuffer); } } // ImageTileSource interface implementation async getImageTile(tileParams) { const arrayBuffer = await this.getTile(tileParams); return arrayBuffer ? this._parseImageTile(arrayBuffer) : null; } async _parseImageTile(arrayBuffer) { return await import_images.ImageLoader.parse(arrayBuffer, this.loadOptions); } // VectorTileSource interface implementation async getVectorTile(tileParams) { const arrayBuffer = await this.getTile(tileParams); return arrayBuffer ? this._parseVectorTile(arrayBuffer, tileParams) : null; } async _parseVectorTile(arrayBuffer, tileParams) { var _a; const loadOptions = { shape: "geojson-table", mvt: { coordinates: "wgs84", tileIndex: { x: tileParams.x, y: tileParams.y, z: tileParams.z }, ...(_a = this.loadOptions) == null ? void 0 : _a.mvt }, ...this.loadOptions }; return await import_mvt.MVTLoader.parse(arrayBuffer, loadOptions); } getMetadataUrl() { return this.metadataUrl; } getTileURL(x, y, z) { switch (this.schema) { case "xyz": return `${this.url}/${x}/${y}/${z}${this.extension}`; case "tms": return `${this.url}/${z}/${x}/${y}${this.extension}`; case "template": return getURLFromTemplate(this.url, x, y, z, "0"); default: throw new Error(this.schema); } } }; function isURLTemplate(s) { return /(?=.*{z})(?=.*{x})(?=.*({y}|{-y}))|(?=.*{x})(?=.*({y}|{-y})(?=.*{z}))/.test(s); } var xRegex = new RegExp("{x}", "g"); var yRegex = new RegExp("{y}", "g"); var zRegex = new RegExp("{z}", "g"); function getURLFromTemplate(template, x, y, z, id = "0") { if (Array.isArray(template)) { const i = stringHash(id) % template.length; template = template[i]; } let url = template; url = url.replace(xRegex, String(x)); url = url.replace(yRegex, String(y)); url = url.replace(zRegex, String(z)); if (Number.isInteger(y) && Number.isInteger(z)) { url = url.replace(/\{-y\}/g, String(Math.pow(2, z) - y - 1)); } return url; } function stringHash(s) { return Math.abs(s.split("").reduce((a, b) => (a << 5) - a + b.charCodeAt(0) | 0, 0)); } // dist/table-tile-source.js var import_loader_utils3 = require("@loaders.gl/loader-utils"); var import_schema = require("@loaders.gl/schema"); var import_stats = require("@probe.gl/stats"); // dist/lib/vector-tiler/proto-tile.js function createProtoTile(features2, z, tx, ty, options) { const tolerance = z === options.maxZoom ? 0 : options.tolerance / ((1 << z) * options.extent); const tile = { protoFeatures: [], sourceFeatures: null, numPoints: 0, numSimplified: 0, numFeatures: features2.length, x: tx, y: ty, z, transformed: false, minX: 2, minY: 1, maxX: -1, maxY: 0 }; for (const feature of features2) { addProtoFeature(tile, feature, tolerance, options); } return tile; } function addProtoFeature(tile, feature, tolerance, options) { const geometry = feature.geometry; const type = feature.type; const simplifiedGeometry = []; tile.minX = Math.min(tile.minX, feature.minX); tile.minY = Math.min(tile.minY, feature.minY); tile.maxX = Math.max(tile.maxX, feature.maxX); tile.maxY = Math.max(tile.maxY, feature.maxY); let simplifiedType; switch (type) { case "Point": case "MultiPoint": simplifiedType = 1; for (let i = 0; i < geometry.length; i += 3) { simplifiedGeometry.push(geometry[i], geometry[i + 1]); tile.numPoints++; tile.numSimplified++; } break; case "LineString": simplifiedType = 2; addProtoLine(simplifiedGeometry, geometry, tile, tolerance, false, false); break; case "MultiLineString": simplifiedType = 2; for (let i = 0; i < geometry.length; i++) { addProtoLine(simplifiedGeometry, geometry[i], tile, tolerance, false, i === 0); } break; case "Polygon": simplifiedType = 3; for (let i = 0; i < geometry.length; i++) { addProtoLine(simplifiedGeometry, geometry[i], tile, tolerance, true, i === 0); } break; case "MultiPolygon": simplifiedType = 3; for (let k = 0; k < geometry.length; k++) { const polygon = geometry[k]; for (let i = 0; i < polygon.length; i++) { addProtoLine(simplifiedGeometry, polygon[i], tile, tolerance, true, i === 0); } } break; default: throw new Error(`Unknown geometry type: ${type}`); } if (simplifiedGeometry.length) { let tags = feature.tags || null; if (type === "LineString" && options.lineMetrics) { tags = {}; for (const key in feature.tags) { tags[key] = feature.tags[key]; } tags.mapbox_clip_start = geometry.start / geometry.size; tags.mapbox_clip_end = geometry.end / geometry.size; } const tileFeature = { geometry: simplifiedGeometry, simplifiedType, // @ts-expect-error tags }; if (feature.id !== null) { tileFeature.id = feature.id; } tile.protoFeatures.push(tileFeature); } } function addProtoLine(result, geometry, tile, tolerance, isPolygon, isOuter) { const sqTolerance = tolerance * tolerance; if (tolerance > 0 && geometry.size < (isPolygon ? sqTolerance : tolerance)) { tile.numPoints += geometry.length / 3; return; } const ring = []; for (let i = 0; i < geometry.length; i += 3) { if (tolerance === 0 || geometry[i + 2] > sqTolerance) { tile.numSimplified++; ring.push(geometry[i], geometry[i + 1]); } tile.numPoints++; } if (isPolygon) rewind(ring, isOuter); result.push(ring); } function rewind(ring, clockwise) { let area = 0; for (let i = 0, j = ring.length - 2; i < ring.length; j = i, i += 2) { area += (ring[i] - ring[j]) * (ring[i + 1] + ring[j + 1]); } if (area > 0 === clockwise) { for (let i = 0, len = ring.length; i < len / 2; i += 2) { const x = ring[i]; const y = ring[i + 1]; ring[i] = ring[len - 2 - i]; ring[i + 1] = ring[len - 1 - i]; ring[len - 2 - i] = x; ring[len - 1 - i] = y; } } } // dist/lib/vector-tiler/transform-tile.js function transformTile(protoTile, extent) { if (protoTile.transformed) { return protoTile; } const z2 = 1 << protoTile.z; const tx = protoTile.x; const ty = protoTile.y; for (const protoFeature of protoTile.protoFeatures) { const geom = protoFeature.geometry; const simplifiedType = protoFeature.simplifiedType; protoFeature.geometry = []; if (simplifiedType === 1) { for (let j = 0; j < geom.length; j += 2) { protoFeature.geometry.push(transformPoint(geom[j], geom[j + 1], extent, z2, tx, ty)); } } else { for (let j = 0; j < geom.length; j++) { const ring = []; for (let k = 0; k < geom[j].length; k += 2) { ring.push(transformPoint(geom[j][k], geom[j][k + 1], extent, z2, tx, ty)); } protoFeature.geometry.push(ring); } } } protoTile.transformed = true; return protoTile; } function transformPoint(x, y, extent, z2, tx, ty) { return [Math.round(extent * (x * z2 - tx)), Math.round(extent * (y * z2 - ty))]; } // dist/lib/vector-tiler/tile-to-geojson.js function convertTileToGeoJSON(protoTile, props) { const features2 = []; for (const rawFeature of protoTile.protoFeatures) { if (!rawFeature || !rawFeature.geometry) { continue; } let type; let coordinates; switch (rawFeature.simplifiedType) { case 1: if (rawFeature.geometry.length === 1) { type = "Point"; coordinates = rawFeature.geometry[0]; } else { type = "MultiPoint"; coordinates = rawFeature.geometry; } break; case 2: if (rawFeature.geometry.length === 1) { type = "LineString"; coordinates = rawFeature.geometry[0]; } else { type = "MultiLineString"; coordinates = rawFeature.geometry; } break; case 3: if (rawFeature.geometry.length > 1) { type = "MultiPolygon"; coordinates = [rawFeature.geometry]; } else { type = "Polygon"; coordinates = rawFeature.geometry; } break; default: throw new Error(`${rawFeature.simplifiedType}is not a valid simplified type`); } switch (props.coordinates) { case "EPSG:4326": case "wgs84": projectToLngLat(coordinates, props.tileIndex, props.extent); break; default: convertToLocalCoordinates(coordinates, props.extent); break; } const feature = { type: "Feature", geometry: { type, coordinates }, properties: rawFeature.tags || {}, id: rawFeature.id }; features2.push(feature); } if (features2.length === 0) { return null; } const table = { shape: "geojson-table", type: "FeatureCollection", features: features2 }; return table; } // dist/lib/vector-tiler/features/proto-feature.js function createProtoFeature(id, type, geometry, tags) { const feature = { // eslint-disable-next-line id: id == null ? null : id, type, simplifiedType: void 0, // TODO geometry, tags, minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity }; switch (type) { case "Point": case "MultiPoint": case "LineString": calcLineBBox(feature, geometry); break; case "MultiLineString": for (const line of geometry) { calcLineBBox(feature, line); } break; case "Polygon": calcLineBBox(feature, geometry[0]); break; case "MultiPolygon": for (const polygon of geometry) { calcLineBBox(feature, polygon[0]); } break; default: throw new Error(String(type)); } return feature; } function calcLineBBox(feature, geometry) { for (let i = 0; i < geometry.length; i += 3) { feature.minX = Math.min(feature.minX, geometry[i]); feature.minY = Math.min(feature.minY, geometry[i + 1]); feature.maxX = Math.max(feature.maxX, geometry[i]); feature.maxY = Math.max(feature.maxY, geometry[i + 1]); } } // dist/lib/vector-tiler/features/simplify-path.js function simplifyPath(coords, first, last, sqTolerance) { let maxSqDist = sqTolerance; const mid = last - first >> 1; let minPosToMid = last - first; let index; const ax = coords[first]; const ay = coords[first + 1]; const bx = coords[last]; const by = coords[last + 1]; for (let i = first + 3; i < last; i += 3) { const d = getSqSegDist(coords[i], coords[i + 1], ax, ay, bx, by); if (d > maxSqDist) { index = i; maxSqDist = d; } else if (d === maxSqDist) { const posToMid = Math.abs(i - mid); if (posToMid < minPosToMid) { index = i; minPosToMid = posToMid; } } } if (maxSqDist > sqTolerance) { if (index - first > 3) simplifyPath(coords, first, index, sqTolerance); coords[index + 2] = maxSqDist; if (last - index > 3) simplifyPath(coords, index, last, sqTolerance); } } function getSqSegDist(px, py, x, y, bx, by) { let dx = bx - x; let dy = by - y; if (dx !== 0 || dy !== 0) { const t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy); if (t > 1) { x = bx; y = by; } else if (t > 0) { x += dx * t; y += dy * t; } } dx = px - x; dy = py - y; return dx * dx + dy * dy; } // dist/lib/vector-tiler/features/convert-feature.js function convertFeaturesToProtoFeature(data, options) { const protoFeatures = []; switch (data.type) { case "FeatureCollection": let i = 0; for (const feature of data.features) { protoFeatures.push(convertFeature(feature, options, i++)); } break; case "Feature": protoFeatures.push(convertFeature(data, options)); break; default: protoFeatures.push(convertFeature({ geometry: data }, options)); } return protoFeatures; } function convertFeature(geojson, options, index) { if (!geojson.geometry) { return; } const coords = geojson.geometry.coordinates; const type = geojson.geometry.type; const tolerance = Math.pow(options.tolerance / ((1 << options.maxZoom) * options.extent), 2); let geometry = []; let id = geojson.id; if (options.promoteId) { id = geojson.properties[options.promoteId]; } else if (options.generateId) { id = index || 0; } switch (type) { case "Point": convertPoint(coords, geometry); break; case "MultiPoint": for (const p of coords) { convertPoint(p, geometry); } break; case "LineString": convertLine(coords, geometry, tolerance, false); break; case "MultiLineString": if (options.lineMetrics) { for (const line of coords) { geometry = []; convertLine(line, geometry, tolerance, false); features.push(createProtoFeature(id, "LineString", geometry, geojson.properties)); } return; convertLines(coords, geometry, tolerance, false); } break; case "Polygon": convertLines(coords, geometry, tolerance, true); break; case "MultiPolygon": for (const polygon of coords) { const newPolygon = []; convertLines(polygon, newPolygon, tolerance, true); geometry.push(newPolygon); } break; case "GeometryCollection": for (const singleGeometry of geojson.geometry.geometries) { convertFeature(features, { id, geometry: singleGeometry, properties: geojson.properties }, options, index); } break; default: throw new Error("Input data is not a valid GeoJSON object."); } return createProtoFeature(id, type, geometry, geojson.properties); } function convertPoint(coords, out) { out.push(projectX(coords[0]), projectY(coords[1]), 0); } function convertLine(ring, out, tolerance, isPolygon) { let x0, y0; let size = 0; for (let j = 0; j < ring.length; j++) { const x = projectX(ring[j][0]); const y = projectY(ring[j][1]); out.push(x, y, 0); if (j > 0) { if (isPolygon) { size += (x0 * y - x * y0) / 2; } else { size += Math.sqrt(Math.pow(x - x0, 2) + Math.pow(y - y0, 2)); } } x0 = x; y0 = y; } const last = out.length - 3; out[2] = 1; simplifyPath(out, 0, last, tolerance); out[last + 2] = 1; out.size = Math.abs(size); out.start = 0; out.end = out.size; } function convertLines(rings, out, tolerance, isPolygon) { for (let i = 0; i < rings.length; i++) { const geom = []; convertLine(rings[i], geom, tolerance, isPolygon); out.push(geom); } } function projectX(x) { return x / 360 + 0.5; } function projectY(y) { const sin = Math.sin(y * Math.PI / 180); const y2 = 0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI; return y2 < 0 ? 0 : y2 > 1 ? 1 : y2; } // dist/lib/vector-tiler/features/clip-features.js function clipFeatures(features2, scale, k1, k2, axis, minAll, maxAll, options) { k1 /= scale; k2 /= scale; if (minAll >= k1 && maxAll < k2) { return features2; } else if (maxAll < k1 || minAll >= k2) { return null; } const clipped = []; for (const feature of features2) { const geometry = feature.geometry; let type = feature.type; const min = axis === 0 ? feature.minX : feature.minY; const max = axis === 0 ? feature.maxX : feature.maxY; if (min >= k1 && max < k2) { clipped.push(feature); continue; } else if (max < k1 || min >= k2) { continue; } let newGeometry = []; if (type === "Point" || type === "MultiPoint") { clipPoints(geometry, newGeometry, k1, k2, axis); } else if (type === "LineString") { clipLine(geometry, newGeometry, k1, k2, axis, false, options.lineMetrics); } else if (type === "MultiLineString") { clipLines(geometry, newGeometry, k1, k2, axis, false); } else if (type === "Polygon") { clipLines(geometry, newGeometry, k1, k2, axis, true); } else if (type === "MultiPolygon") { for (const polygon of geometry) { const newPolygon = []; clipLines(polygon, newPolygon, k1, k2, axis, true); if (newPolygon.length) { newGeometry.push(newPolygon); } } } if (newGeometry.length) { if (options.lineMetrics && type === "LineString") { for (const line of newGeometry) { clipped.push(createProtoFeature(feature.id, type, line, feature.tags)); } continue; } if (type === "LineString" || type === "MultiLineString") { if (newGeometry.length === 1) { type = "LineString"; newGeometry = newGeometry[0]; } else { type = "MultiLineString"; } } if (type === "Point" || type === "MultiPoint") { type = newGeometry.length === 3 ? "Point" : "MultiPoint"; } clipped.push(createProtoFeature(feature.id, type, newGeometry, feature.tags)); } } return clipped.length ? clipped : null; } function clipPoints(geom, newGeom, k1, k2, axis) { for (let i = 0; i < geom.length; i += 3) { const a = geom[i + axis]; if (a >= k1 && a <= k2) { addPoint(newGeom, geom[i], geom[i + 1], geom[i + 2]); } } } function clipLine(geom, newGeom, k1, k2, axis, isPolygon, trackMetrics) { let slice = newSlice(geom); const intersect = axis === 0 ? intersectX : intersectY; let len = geom.start; let segLen; let t; for (let i = 0; i < geom.length - 3; i += 3) { const ax2 = geom[i]; const ay2 = geom[i + 1]; const az2 = geom[i + 2]; const bx = geom[i + 3]; const by = geom[i + 4]; const a2 = axis === 0 ? ax2 : ay2; const b = axis === 0 ? bx : by; let exited = false; if (trackMetrics) { segLen = Math.sqrt(Math.pow(ax2 - bx, 2) + Math.pow(ay2 - by, 2)); } if (a2 < k1) { if (b > k1) { t = intersect(slice, ax2, ay2, bx, by, k1); if (trackMetrics) { slice.start = len + segLen * t; } } } else if (a2 > k2) { if (b < k2) { t = intersect(slice, ax2, ay2, bx, by, k2); if (trackMetrics) { slice.start = len + segLen * t; } } } else { addPoint(slice, ax2, ay2, az2); } if (b < k1 && a2 >= k1) { t = intersect(slice, ax2, ay2, bx, by, k1); exited = true; } if (b > k2 && a2 <= k2) { t = intersect(slice, ax2, ay2, bx, by, k2); exited = true; } if (!isPolygon && exited) { if (trackMetrics) { slice.end = len + segLen * t; } newGeom.push(slice); slice = newSlice(geom); } if (trackMetrics) { len += segLen; } } let last = geom.length - 3; const ax = geom[last]; const ay = geom[last + 1]; const az = geom[last + 2]; const a = axis === 0 ? ax : ay; if (a >= k1 && a <= k2) addPoint(slice, ax, ay, az); last = slice.length - 3; if (isPolygon && last >= 3 && (slice[last] !== slice[0] || slice[last + 1] !== slice[1])) { addPoint(slice, slice[0], slice[1], slice[2]); } if (slice.length) { newGeom.push(slice); } } function newSlice(line) { const slice = []; slice.size = line.size; slice.start = line.start; slice.end = line.end; return slice; } function clipLines(geom, newGeom, k1, k2, axis, isPolygon) { for (const line of geom) { clipLine(line, newGeom, k1, k2, axis, isPolygon, false); } } function addPoint(out, x, y, z) { out.push(x, y, z); } function intersectX(out, ax, ay, bx, by, x) { const t = (x - ax) / (bx - ax); addPoint(out, x, ay + (by - ay) * t, 1); return t; } function intersectY(out, ax, ay, bx, by, y) { const t = (y - ay) / (by - ay); addPoint(out, ax + (bx - ax) * t, y, 1); return t; } // dist/lib/vector-tiler/features/wrap-features.js function wrapFeatures(features2, options) { const buffer = options.buffer / options.extent; let merged = features2; const left = clipFeatures(features2, 1, -1 - buffer, buffer, 0, -1, 2, options); const right = clipFeatures(features2, 1, 1 - buffer, 2 + buffer, 0, -1, 2, options); if (left || right) { merged = clipFeatures(features2, 1, -buffer, 1 + buffer, 0, -1, 2, options) || []; if (left) { merged = shiftFeatureCoords(left, 1).concat(merged); } if (right) { merged = merged.concat(shiftFeatureCoords(right, -1)); } } return merged; } function shiftFeatureCoords(features2, offset) { const newFeatures = []; for (let i = 0; i < features2.length; i++) { const feature = features2[i]; const type = feature.type; let newGeometry; switch (type) { case "Point": case "MultiPoint": case "LineString": newGeometry = shiftCoords(feature.geometry, offset); break; case "MultiLineString": case "Polygon": newGeometry = []; for (const line of feature.geometry) { newGeometry.push(shiftCoords(line, offset)); } break; case "MultiPolygon": newGeometry = []; for (const polygon of feature.geometry) { const newPolygon = []; for (const line of polygon) { newPolygon.push(shiftCoords(line, offset)); } newGeometry.push(newPolygon); } break; default: throw new Error(String(type)); } newFeatures.push(createProtoFeature(feature.id, type, newGeometry, feature.tags)); } return newFeatures; } function shiftCoords(points, offset) { const newPoints = []; newPoints.size = points.size; if (points.start !== void 0) { newPoints.start = points.start; newPoints.end = points.end; } for (let i = 0; i < points.length; i += 3) { newPoints.push(points[i] + offset, points[i + 1], points[i + 2]); } return newPoints; } // dist/table-tile-source.js var TableTileSource = { name: "TableTiler", id: "table-tiler", version: "0.0.0", extensions: ["mvt"], mimeTypes: ["application/octet-stream"], options: { table: { coordinates: "local", promoteId: void 0, maxZoom: 14, indexMaxZoom: 5, maxPointsPerTile: 1e4, tolerance: 3, extent: 4096, buffer: 64, generateId: void 0 } }, type: "table", testURL: (url) => url.endsWith(".geojson"), createDataSource(url, options) { var _a, _b; const needsLoading = typeof url === "string" || url instanceof Blob; const loader = (_b = (_a = options == null ? void 0 : options.table) == null ? void 0 : _a.loaders) == null ? void 0 : _b[0]; const tablePromise = needsLoading ? loadTable(url, loader) : url; return new DynamicVectorTileSource(tablePromise, options); } // @ts-expect-error }; async function loadTable(url, loader) { if (typeof url === "string") { const response = await fetch(url); const data2 = await response.arrayBuffer(); return await loader.parse(data2); } const data = await url.arrayBuffer(); return await loader.parse(data); } var _DynamicVectorTileSource = class { /** Stats for this DynamicVectorTileSource */ stats = new import_stats.Stats({ id: "table-tile-source", stats: [new import_stats.Stat("tiles", "count"), new import_stats.Stat("features", "count")] }); /** MIME type of the tiles emitted by this tile source */ mimeType = "application/vnd.mapbox-vector-tile"; localCoordinates = true; /** The props that this tile source was created with */ // @ts-expect-error props; /* Schema of the data */ schema = null; /** Map of generated tiles, indexed by stringified tile coordinates */ tiles = {}; /** Array of tile coordinates */ tileCoords = []; /** Input data has loaded, initial top-level tiling is done, sync methods can now be called */ ready; /** Metadata for the tile source (generated TileJSON/tilestats */ metadata; constructor(table, props) { this.props = { ...TableTileSource.options.table, ...props == null ? void 0 : props.table }; this.getTileData = this.getTileData.bind(this); this.ready = this.initializeTilesAsync(table); this.metadata = this.getMetadata(); } async initializeTilesAsync(tablePromise) { const table = await tablePromise; this.schema = (0, import_schema.deduceTableSchema)(table); this.createRootTiles(table); } async getMetadata() { await this.ready; return { schema: this.schema, minZoom: 0, maxZoom: this.props.maxZoom }; } async getSchema() { await this.ready; return this.schema; } /** * Get a tile at the specified index * @param tileIndex z, x, y of tile * @returns */ async getVectorTile(tileIndex) { await this.ready; const table = this.getTileSync(tileIndex); import_loader_utils3.log.info(2, "getVectorTile", tileIndex, table)(); return table; } async getTile(tileIndex) { await this.ready; return this.getTileSync(tileIndex); } async getTileData(tileParams) { const { x, y, z } = tileParams.index; const tile = await this.getVectorTile({ x, y, z }); return (tile == null ? void 0 : tile.features) || []; } // Implementation /** * Synchronously request a tile * @note Application must await `source.ready` before calling sync methods. */ getTileSync(tileIndex) { const protoTile = this.getProtoTile(tileIndex); if (!protoTile) { return null; } return convertTileToGeoJSON(protoTile, { coordinates: this.props.coordinates, tileIndex, extent: this.props.extent }); } /** * Create the initial tiles * @note the tiles stores all the features together with additional data */ createRootTiles(table) { if (this.props.maxZoom < 0 || this.props.maxZoom > 24) { throw new Error("maxZoom should be in the 0-24 range"); } if (this.props.promoteId && this.props.generateId) { throw new Error("promoteId and generateId cannot be used together."); } import_loader_utils3.log.log(1, "DynamicVectorTileSource creating root tiles", this.props)(); import_loader_utils3.log.time(1, "preprocess table")(); let features2 = convertFeaturesToProtoFeature(table, this.props); import_loader_utils3.log.timeEnd(1, "preprocess table")(); import_loader_utils3.log.time(1, "generate tiles")(); features2 = wrapFeatures(features2, this.props); if (features2.length === 0) { import_loader_utils3.log.log(1, "DynamicVectorTileSource: no features generated")(); return; } this.splitTile(features2, 0, 0, 0); const rootTile = this.tiles[0]; import_loader_utils3.log.log(1, `root tile features: ${rootTile.numFeatures}, points: ${rootTile.numPoints}`)(); import_loader_utils3.log.timeEnd(1, "generate tiles")(); import_loader_utils3.log.log(1, `DynamicVectorTileSource: tiles generated: ${this.stats.get("total").count}`, this.stats)(); } /** * Return geojsonvt-style "half formed" vector tile * @note Application must await `source.ready` before calling sync methods. */ // eslint-disable-next-line complexity, max-statements getProtoTile(tileIndex) { const { z, y } = tileIndex; let { x } = tileIndex; const { extent } = this.props; if (z < 0 || z > 24) { return null; } const z2 = 1 << z; x = x + z2 & z2 - 1; const id = toID(z, x, y); if (this.tiles[id]) { return transformTile(this.tiles[id], extent); } import_loader_utils3.log.log(import_loader_utils3.log, "drilling down to z%d-%d-%d", z, x, y)(); let z0 = z; let x0 = x; let y0 = y; let parent; while (!parent && z0 > 0) { z0--; x0 = x0 >> 1; y0 = y0 >> 1; parent = this.tiles[toID(z0, x0, y0)]; } if (!parent || !parent.sourceFeatures) { return null; } import_loader_utils3.log.log(1, "found parent tile z%d-%d-%d", z0, x0, y0)(); import_loader_utils3.log.time(1, "drilling down")(); this.splitTile(parent.sourceFeatures, z0, x0, y0, z, x, y); import_loader_utils3.log.timeEnd(1, "drilling down")(); return this.tiles[id] ? transformTile(this.tiles[id], extent) : null; } /** * splits features from a parent tile to sub-tiles. * @param z, x, and y are the coordinates of the parent tile * @param cz, cx, and cy are the coordinates of the target tile * * If no target tile is specified, splitting stops when we reach the maximum * zoom or the number of points is low as specified in the props. */ // eslint-disable-next-line max-params, max-statements, complexity splitTile(features2, z, x, y, cz, cx, cy) { const stack = [features2, z, x, y]; while (stack.length) { y = stack.pop(); x = stack.pop(); z = stack.pop(); features2 = stack.pop(); const z2 = 1 << z; const id = toID(z, x, y); let tile = this.tiles[id]; if (!tile) { import_loader_utils3.log.time(2, "tile creation")(); tile = this.tiles[id] = createProtoTile(features2, z, x, y, this.props); this.tileCoords.push({ z, x, y }); const key = `z${z}`; let stat = this.stats.get(key, "count"); stat.incrementCount(); stat = this.stats.get("total"); stat.incrementCount(); stat = _DynamicVectorTileSource.stats.get(key, "count"); stat.incrementCount(); stat = _DynamicVectorTileSource.stats.get("total"); stat.incrementCount(); import_loader_utils3.log.log(2, "tile z%d-%d-%d (features: %d, points: %d, simplified: %d)", z, x, y, tile.numFeatures, tile.numPoints, tile.numSimplified)(); import_loader_utils3.log.timeEnd(2, "tile creation")(); } tile.sourceFeatures = features2; if (cz === void 0) { if (z === this.props.indexMaxZoom || tile.numPoints <= this.props.maxPointsPerTile) { continue; } } else if (z === this.props.maxZoom || z === cz) { continue; } else if (cz !== void 0) { const zoomSteps = cz - z; if (x !== cx >> zoomSteps || y !== cy >> zoomSteps) { continue; } } tile.sourceFeatures = null; if (features2.length === 0) continue; import_loader_utils3.log.time(2, "clipping tile")(); const k1 = 0.5 * this.props.buffer / this.props.extent; const k2 = 0.5 - k1; const k3 = 0.5 + k1; const k4 = 1 + k1; let tl = null; let bl = null; let tr = null; let br = null; let left = clipFeatures(features2, z2, x - k1, x + k3, 0, tile.minX, tile.maxX, this.props); let right = clipFeatures(features2, z2, x + k2, x + k4, 0, tile.minX, tile.maxX, this.props); features2 = null; if (left) { tl = clipFeatures(left, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, this.props); bl = clipFeatures(left, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, this.props); left = null; } if (right) { tr = clipFeatures(right, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, this.props); br = clipFeatures(right, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, this.props); right = null; } import_loader_utils3.log.timeEnd(2, "clipping tile")(); stack.push(tl || [], z + 1, x * 2, y * 2); stack.push(bl || [], z + 1, x * 2, y * 2 + 1); stack.push(tr || [], z + 1, x * 2 + 1, y * 2); stack.push(br || [], z + 1, x * 2 + 1, y * 2 + 1); } } }; var DynamicVectorTileSource = _DynamicVectorTileSource; /** Global stats for all DynamicVectorTileSources */ __publicField(DynamicVectorTileSource, "stats", new import_stats.Stats({ id: "table-tile-source-all", stats: [new import_stats.Stat("count", "tiles"), new import_stats.Stat("count", "features")] })); function toID(z, x, y) { return ((1 << z) * y + x) * 32 + z; } //# sourceMappingURL=index.cjs.map