@urban-toolkit/autk-db 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/autk-db.js +25 -25
  2. package/dist/autk-db.js.map +1 -1
  3. package/dist/{basedecoder-DaTXO39b.js → basedecoder-B2p-79Pg.js} +3 -3
  4. package/dist/basedecoder-B2p-79Pg.js.map +1 -0
  5. package/dist/deflate-DdI6yhy3.js +12 -0
  6. package/dist/deflate-DdI6yhy3.js.map +1 -0
  7. package/dist/globals-QF85DtAk.js.map +1 -1
  8. package/dist/{jpeg-DckFSoVK.js → jpeg-ClN7e6im.js} +3 -3
  9. package/dist/jpeg-ClN7e6im.js.map +1 -0
  10. package/dist/{lerc-BCdGEeLp.js → lerc-B8cSax8j.js} +4 -4
  11. package/dist/lerc-B8cSax8j.js.map +1 -0
  12. package/dist/{lzw-B3twMQgz.js → lzw-Cr5E_zhd.js} +3 -3
  13. package/dist/lzw-Cr5E_zhd.js.map +1 -0
  14. package/dist/{packbits-pbHfk2l8.js → packbits-sD0-qSEu.js} +3 -3
  15. package/dist/packbits-sD0-qSEu.js.map +1 -0
  16. package/dist/{pako.esm-Crx1NgSq.js → pako.esm-x6ItERqe.js} +2 -2
  17. package/dist/pako.esm-x6ItERqe.js.map +1 -0
  18. package/dist/raw-DuoIrg1T.js +11 -0
  19. package/dist/raw-DuoIrg1T.js.map +1 -0
  20. package/dist/{webimage-OC9EEb5f.js → webimage-CCNehbhp.js} +3 -3
  21. package/dist/webimage-CCNehbhp.js.map +1 -0
  22. package/dist/{zstd-rpfNjbfx.js → zstd-CWaVrHII.js} +3 -3
  23. package/dist/zstd-CWaVrHII.js.map +1 -0
  24. package/package.json +1 -1
  25. package/dist/basedecoder-DaTXO39b.js.map +0 -1
  26. package/dist/deflate-DT_oTgqy.js +0 -12
  27. package/dist/deflate-DT_oTgqy.js.map +0 -1
  28. package/dist/jpeg-DckFSoVK.js.map +0 -1
  29. package/dist/lerc-BCdGEeLp.js.map +0 -1
  30. package/dist/lzw-B3twMQgz.js.map +0 -1
  31. package/dist/packbits-pbHfk2l8.js.map +0 -1
  32. package/dist/pako.esm-Crx1NgSq.js.map +0 -1
  33. package/dist/raw-BpEIWqGM.js +0 -11
  34. package/dist/raw-BpEIWqGM.js.map +0 -1
  35. package/dist/webimage-OC9EEb5f.js.map +0 -1
  36. package/dist/zstd-rpfNjbfx.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"autk-db.js","names":["sum","u","sum","bc","ca","ab","bct","cat","abt","u","_8","_8b","_16","fin","fin2","bc","ab","_8","_16","_48","fin","pip","defaultCompare","sweeplineIntersections","lib","point2","booleanPointInPolygon2","intersects","createNode","EPSILON","create","glMatrix.ARRAY_TYPE","glMatrix.ARRAY_TYPE","getValues"],"sources":["../src/shared/osm-tag-definitions.ts","../src/config/duckdb.ts","../src/spatial/use-cases/load-layer/queries.ts","../src/spatial/shared/utils.ts","../src/shared/consts.ts","../../node_modules/@turf/helpers/dist/esm/index.js","../../node_modules/@turf/invariant/dist/esm/index.js","../../node_modules/@turf/meta/dist/esm/index.js","../../node_modules/@turf/bbox/dist/esm/index.js","../../node_modules/@turf/bbox-polygon/dist/esm/index.js","../../node_modules/point-in-polygon-hao/node_modules/robust-predicates/esm/util.js","../../node_modules/point-in-polygon-hao/node_modules/robust-predicates/esm/orient2d.js","../../node_modules/point-in-polygon-hao/node_modules/robust-predicates/esm/orient3d.js","../../node_modules/point-in-polygon-hao/node_modules/robust-predicates/esm/incircle.js","../../node_modules/point-in-polygon-hao/node_modules/robust-predicates/esm/insphere.js","../../node_modules/point-in-polygon-hao/dist/esm/index.js","../../node_modules/@turf/boolean-point-in-polygon/dist/esm/index.js","../../node_modules/sweepline-intersections/dist/sweeplineIntersections.esm.js","../../node_modules/@turf/line-intersect/dist/esm/index.js","../../node_modules/@turf/polygon-to-line/dist/esm/index.js","../../node_modules/@turf/boolean-disjoint/dist/esm/index.js","../../node_modules/@turf/boolean-intersects/dist/esm/index.js","../../node_modules/@turf/envelope/dist/esm/index.js","../../node_modules/@turf/polygonize/dist/esm/index.js","../node_modules/quickselect/index.js","../node_modules/rbush/index.js","../src/shared/clusterIntersectingFeatures.ts","../src/spatial/use-cases/assign-building-ids/AssignBuildingIdsUseCase.ts","../src/spatial/use-cases/aggregate-building-layer/AggregateBuildingLayerUseCase.ts","../src/spatial/use-cases/load-layer/osm-processing-config.ts","../src/spatial/use-cases/load-layer/LoadLayerUseCase.ts","../src/spatial/use-cases/load-csv/queries.ts","../src/spatial/use-cases/load-csv/LoadCsvUseCase.ts","../src/spatial/use-cases/load-json/queries.ts","../src/spatial/use-cases/load-json/LoadJsonUseCase.ts","../src/spatial/use-cases/get-layer-geojson/queries.ts","../src/spatial/use-cases/get-layer-geojson/GetLayerGeojsonUseCase.ts","../../autk-core/src/types-colormap.ts","../../autk-core/src/colormap.ts","../../autk-core/src/utils-geometry.ts","../../node_modules/earcut/src/earcut.js","../../autk-core/src/triangulator-polylines.ts","../../node_modules/gl-matrix/esm/common.js","../../node_modules/gl-matrix/esm/mat4.js","../../node_modules/gl-matrix/esm/vec3.js","../../autk-core/src/camera.ts","../../autk-core/src/utils-layer.ts","../src/spatial/use-cases/load-custom-layer/queries.ts","../src/spatial/use-cases/load-custom-layer/LoadCustomLayerUseCase.ts","../src/spatial/use-cases/spatial-join/errors.ts","../src/spatial/use-cases/spatial-join/queries.ts","../src/spatial/use-cases/spatial-join/SpatialJoinUseCase.ts","../src/spatial/shared/use-cases/drop-table/DropTableUseCase.ts","../src/spatial/shared/use-cases/transform-bounding-box-coordinates/queries.ts","../src/spatial/shared/use-cases/transform-bounding-box-coordinates/TransformBoundingBoxCoordinatesUseCase.ts","../src/spatial/shared/use-cases/get-bounding-box-from-layer/queries.ts","../src/spatial/shared/use-cases/get-bounding-box-from-layer/GetBoundingBoxFromLayerUseCase.ts","../src/shared/HttpCache.ts","../src/spatial/use-cases/load-osm-from-overpass-api/LoadOsmFromOverpassApiUseCase.ts","../../node_modules/pbf/index.js","../../node_modules/@osmix/pbf/dist/proto/osmformat.js","../../node_modules/@osmix/shared/dist/bytes-to-stream.js","../../node_modules/@osmix/shared/dist/concat-bytes.js","../../node_modules/@osmix/shared/dist/stream-to-bytes.js","../../node_modules/@osmix/shared/dist/transform-bytes.js","../../node_modules/@osmix/pbf/dist/utils.js","../../node_modules/@osmix/pbf/dist/blobs-to-blocks.js","../../node_modules/@osmix/pbf/dist/proto/fileformat.js","../../node_modules/@osmix/pbf/dist/spec.js","../../node_modules/@osmix/pbf/dist/blocks-to-pbf.js","../../node_modules/@osmix/pbf/dist/pbf-to-blocks.js","../../node_modules/@osmix/pbf/dist/pbf-to-blobs.js","../src/spatial/use-cases/load-osm-from-pbf/osm-pbf-parser.ts","../src/spatial/use-cases/load-osm-from-pbf/LoadOsmFromPbfUseCase.ts","../src/spatial/use-cases/load-osm-from-overpass-api/queries.ts","../src/spatial/use-cases/osm-processing-pipeline/OsmProcessingPipeline.ts","../src/spatial/use-cases/load-grid-layer/LoadGridLayerUseCase.ts","../node_modules/@petamoriken/float16/src/_util/messages.mjs","../node_modules/@petamoriken/float16/src/_util/primordials.mjs","../node_modules/@petamoriken/float16/src/_util/arrayIterator.mjs","../node_modules/@petamoriken/float16/src/_util/converter.mjs","../node_modules/@petamoriken/float16/src/DataView.mjs","../node_modules/xml-utils/get-attribute.mjs","../node_modules/xml-utils/index-of-match.mjs","../node_modules/xml-utils/index-of-match-end.mjs","../node_modules/xml-utils/count-substring.mjs","../node_modules/xml-utils/find-tag-by-name.mjs","../node_modules/xml-utils/find-tags-by-name.mjs","../node_modules/geotiff/dist-module/rgb.js","../node_modules/geotiff/dist-module/compression/index.js","../node_modules/geotiff/dist-module/resample.js","../node_modules/geotiff/dist-module/geotiffimage.js","../node_modules/geotiff/dist-module/dataview64.js","../node_modules/geotiff/dist-module/dataslice.js","../node_modules/geotiff/dist-module/source/basesource.js","../node_modules/geotiff/dist-module/utils.js","../node_modules/geotiff/dist-module/source/arraybuffer.js","../node_modules/geotiff/dist-module/imagefiledirectory.js","../node_modules/geotiff/dist-module/geotiff.js","../src/spatial/use-cases/load-geotiff/LoadGeoTiffUseCase.ts","../src/spatial/use-cases/raw-query/errors.ts","../src/spatial/use-cases/raw-query/RawQueryUseCase.ts","../src/spatial/shared/use-cases/get-bounding-box-from-osm/queries.ts","../src/spatial/shared/use-cases/get-bounding-box-from-osm/GetBoundingBoxFromOsmUseCase.ts","../src/spatial/use-cases/polygonize-surface-layer/queries.ts","../src/spatial/use-cases/polygonize-surface-layer/PolygonizeSurfaceLayerUseCase.ts","../src/spatial/use-cases/build-heatmap/BuildHeatmapUseCase.ts","../src/spatial/use-cases/get-table-data/GetTableDataUseCase.ts","../src/spatial/use-cases/update-table/interfaces.ts","../src/spatial/use-cases/update-table/queries.ts","../src/spatial/use-cases/update-table/UpdateTableUseCase.ts","../src/spatial/SpatialDb.ts"],"sourcesContent":["/**\n * OSM tag value definitions used across Overpass queries and layer classification.\n *\n * Centralized here so both the Overpass query builder and the SQL layer filters\n * reference the same source of truth.\n */\n\nexport const PARKS_LEISURE_VALUES = ['dog_park', 'park', 'playground', 'recreation_ground'] as const;\nexport const PARKS_LANDUSE_VALUES = ['wood', 'grass', 'forest', 'orchard', 'village_green', 'vineyard', 'cemetery', 'meadow'] as const;\nexport const PARKS_NATURAL_VALUES = ['wood', 'grass', 'grassland', 'forest', 'scrub', 'heath', 'meadow'] as const;\n\nexport const WATER_NATURAL_VALUES = ['water', 'wetland', 'strait', 'spring'] as const;\nexport const WATER_FEATURE_VALUES = ['pond', 'reservoir', 'lagoon', 'stream_pool', 'lake', 'pool', 'canal', 'river'] as const;\n\nexport const EXCLUDED_HIGHWAY_VALUES = ['cycleway', 'elevator', 'footway', 'steps', 'pedestrian', 'proposed', 'construction', 'abandoned', 'platform', 'raceway'] as const;\nexport const EXCLUDED_BUILDING_VALUES = ['shed', 'garage', 'garages', 'carport', 'hut', 'kiosk', 'toilets', 'service', 'transformer_tower', 'sty', 'container'] as const;\n","import * as duckdb from '@duckdb/duckdb-wasm';\n\nconst BROWSER_BUNDLES: duckdb.DuckDBBundles = {\n mvp: {\n mainModule: new URL(/* @vite-ignore */ './duckdb-mvp.wasm', import.meta.url).href,\n mainWorker: new URL(/* @vite-ignore */ './duckdb-browser-mvp.worker.js', import.meta.url).href,\n },\n eh: {\n mainModule: new URL(/* @vite-ignore */ './duckdb-eh.wasm', import.meta.url).href,\n mainWorker: new URL(/* @vite-ignore */ './duckdb-browser-eh.worker.js', import.meta.url).href,\n },\n};\n\n/**\n * Loads and instantiates a DuckDB database, with Node.js and browser support.\n *\n * @returns An instantiated `AsyncDuckDB` instance ready for connections.\n * @throws If DuckDB WebAssembly fails to load or instantiate.\n */\nexport async function loadDb() {\n if (typeof process !== 'undefined' && process.versions?.node) {\n const path = await import(/* @vite-ignore */ 'node:path');\n const { Worker: NodeWorker } = await import(/* @vite-ignore */ 'node:worker_threads');\n const { createRequire } = await import(/* @vite-ignore */ 'node:module');\n const require = createRequire(import.meta.url);\n const dist = path.dirname(require.resolve('@duckdb/duckdb-wasm'));\n const workerPath = path.join(dist, 'duckdb-node-eh.worker.cjs');\n\n // Stub: polyfill the Web Worker globals the duckdb worker expects,\n // then require() it so it loads with proper CJS scope.\n const stub =\n `const { parentPort } = require('node:worker_threads');` +\n `globalThis.postMessage = (msg, transfer) => parentPort.postMessage(msg, transfer);` +\n `parentPort.on('message', (data) => { if (typeof globalThis.onmessage === 'function') globalThis.onmessage({ data }); });` +\n `require(${JSON.stringify(workerPath)});`;\n const nodeWorker = new NodeWorker(stub, { eval: true });\n\n const listeners = new Map<(event: any) => void, [string, (...args: any[]) => void]>();\n const adapter = {\n addEventListener(event: string, handler: (e: any) => void) {\n const wrapped =\n event === 'error'\n ? (err: any) =>\n handler({\n error: err,\n message: err?.message ?? String(err),\n target: adapter,\n })\n : (data: any) => handler({ data, target: adapter });\n listeners.set(handler, [event, wrapped]);\n nodeWorker.on(event, wrapped);\n },\n removeEventListener(_event: string, handler: (e: any) => void) {\n const r = listeners.get(handler);\n if (r) {\n nodeWorker.off(r[0], r[1]);\n listeners.delete(handler);\n }\n },\n postMessage(data: any, transfer?: any[]) {\n nodeWorker.postMessage(data, transfer);\n },\n terminate() {\n return nodeWorker.terminate();\n },\n };\n\n const db = new duckdb.AsyncDuckDB(new duckdb.VoidLogger(), adapter as unknown as Worker);\n await db.instantiate(path.join(dist, 'duckdb-eh.wasm'));\n return db;\n }\n\n const bundle = await duckdb.selectBundle(BROWSER_BUNDLES);\n const worker = new Worker(bundle.mainWorker!);\n const db = new duckdb.AsyncDuckDB(new duckdb.VoidLogger(), worker);\n await db.instantiate(bundle.mainModule);\n return db;\n}\n","import { LayerType } from './interfaces';\nimport { BoundingBox } from '../../../shared/interfaces';\n\ntype Params = {\n tableName: string;\n layer: LayerType;\n outputFormat: string;\n outputTableName: string;\n boundingBox?: BoundingBox;\n workspace?: string;\n};\n\nconst AREA_LAYERS: LayerType[] = ['buildings', 'parks', 'water'];\n\nexport const LOAD_LAYER_QUERY = ({ tableName, layer, outputFormat, outputTableName, boundingBox, workspace = 'main' }: Params) => {\n const query = getLayerQuery(layer);\n \n const qualifiedInputTableName = `${workspace}.${tableName}`;\n const qualifiedOutputTableName = `${workspace}.${outputTableName}`;\n \n let actualTableName = qualifiedInputTableName;\n if (layer === 'surface') {\n const baseTableName = tableName.replace(new RegExp(`^${workspace}\\\\.`), '');\n actualTableName = `${workspace}.${baseTableName}_boundaries`;\n }\n\n return `\n ${query(actualTableName)}\n CREATE OR REPLACE TEMP TABLE ${layer}_with_nodes_refs AS\n SELECT id, UNNEST(refs) as ref, UNNEST(range(length(refs))) as ref_idx\n FROM ${actualTableName}\n SEMI JOIN ${layer} USING (id)\n WHERE kind IN ('way', 'relation');\n\n CREATE OR REPLACE TEMP TABLE ${layer}_required_nodes_with_geometries AS\n SELECT id, ST_POINT(lon, lat) geometry\n FROM ${actualTableName} nodes\n SEMI JOIN ${layer}_with_nodes_refs\n ON nodes.id = ${layer}_with_nodes_refs.ref\n WHERE kind = 'node';\n\n CREATE OR REPLACE TABLE ${qualifiedOutputTableName} AS\n SELECT\n ${layer}.id,\n ${layer}.tags properties,\n ${layer}.refs,\n ${buildGeometrySelect({ outputFormat, boundingBox, layer })} geometry\n FROM ${layer}\n JOIN ${layer}_with_nodes_refs\n ON ${layer}.id = ${layer}_with_nodes_refs.id\n JOIN ${layer}_required_nodes_with_geometries nodes\n ON ${layer}_with_nodes_refs.ref = nodes.id\n GROUP BY 1, 2, 3\n ${buildHavingClause({ outputFormat, boundingBox, layer })};\n\n DESCRIBE ${qualifiedOutputTableName};\n `;\n};\n\nfunction buildAreaGeometryExpression(outputFormat: string, boundingBox?: BoundingBox) {\n const baseGeometry = `\n CASE \n WHEN refs[1] = refs[array_length(refs)] AND array_length(refs) > 3 THEN\n ST_Transform(\n ST_MakePolygon(\n ST_MakeLine(\n list(nodes.geometry ORDER BY ref_idx ASC)\n )\n ),\n 'EPSG:4326',\n '${outputFormat}',\n always_xy := true\n )\n ELSE\n ST_Transform(\n ST_MakeLine(\n list(nodes.geometry ORDER BY ref_idx ASC)\n ),\n 'EPSG:4326',\n '${outputFormat}',\n always_xy := true\n )\n END`;\n\n if (!boundingBox) return baseGeometry;\n\n const clippingGeometry = `ST_MakeEnvelope(${boundingBox.minLon}, ${boundingBox.minLat}, ${boundingBox.maxLon}, ${boundingBox.maxLat})`;\n return `ST_Intersection(${baseGeometry}, ${clippingGeometry})`;\n}\n\nfunction buildGeometrySelect({\n outputFormat,\n boundingBox,\n layer,\n}: {\n outputFormat: string;\n boundingBox?: BoundingBox;\n layer: LayerType;\n}) {\n return AREA_LAYERS.includes(layer)\n ? buildAreaGeometryExpression(outputFormat, boundingBox)\n : `ST_Transform(\n ST_MakeLine(\n list(nodes.geometry ORDER BY ref_idx ASC)\n ),\n 'EPSG:4326',\n '${outputFormat}',\n always_xy := true\n )`;\n}\n\nfunction buildHavingClause({\n outputFormat,\n boundingBox,\n layer,\n}: {\n outputFormat: string;\n boundingBox?: BoundingBox;\n layer: LayerType;\n}) {\n if (!boundingBox || !AREA_LAYERS.includes(layer)) return '';\n\n const geometry = buildAreaGeometryExpression(outputFormat, boundingBox);\n const clippingGeometry = `ST_MakeEnvelope(${boundingBox.minLon}, ${boundingBox.minLat}, ${boundingBox.maxLon}, ${boundingBox.maxLat})`;\n return `HAVING ST_Intersects(${geometry}, ${clippingGeometry})`;\n}\n\nfunction getLayerQuery(layer: string): (t: string) => string {\n switch (layer) {\n case 'parks':\n return GET_PARKS;\n case 'water':\n return GET_WATER;\n case 'buildings':\n return GET_BUILDINGS;\n case 'roads':\n return GET_ROADS;\n case 'surface':\n return GET_SURFACE;\n default:\n return () => '';\n }\n}\n\nconst GET_PARKS = (tableName: string) => `\n CREATE OR REPLACE TEMP TABLE parks AS\n SELECT id, tags, refs FROM ${tableName}\n WHERE kind = 'way' AND map_extract(tags, '__autk_layer')[1] = 'parks';\n`;\n\nconst GET_WATER = (tableName: string) => `\n CREATE OR REPLACE TEMP TABLE water AS\n SELECT id, tags, refs FROM ${tableName}\n WHERE kind = 'way' AND map_extract(tags, '__autk_layer')[1] = 'water';\n`;\n\nconst GET_BUILDINGS = (tableName: string) => `\n CREATE OR REPLACE TEMP TABLE buildings AS\n SELECT id, tags, refs FROM ${tableName}\n WHERE kind = 'way' AND map_extract(tags, '__autk_layer')[1] = 'buildings';\n`;\n\nconst GET_ROADS = (tableName: string) => `\n CREATE OR REPLACE TEMP TABLE roads AS\n SELECT id, tags, refs FROM ${tableName}\n WHERE kind = 'way' AND map_extract(tags, '__autk_layer')[1] = 'roads' AND array_length(refs) > 1;\n`;\n\nconst GET_SURFACE = (tableName: string) => `\n CREATE OR REPLACE TEMP TABLE surface AS\n SELECT id, tags, refs FROM ${tableName}\n WHERE kind IN ('way');\n`;\n","import { Column } from '../../shared/interfaces';\n\ntype DuckDbTableDescriptionColumn = {\n column_name: string;\n column_type: string;\n};\n\n/**\n * Converts DuckDB `DESCRIBE` output rows into `Column` metadata objects.\n *\n * @param tableDescribeResponse Array of `{ column_name, column_type }` rows from DuckDB.\n * @returns Array of `{ name, type }` column descriptors.\n * @throws Never throws.\n */\nexport function getColumnsFromDuckDbTableDescribe(\n tableDescribeResponse: Array<DuckDbTableDescriptionColumn>,\n): Array<Column> {\n return tableDescribeResponse.map((column: DuckDbTableDescriptionColumn) => {\n return {\n name: column.column_name,\n type: column.column_type,\n };\n });\n}\n\n/**\n * Recursively converts values returned by DuckDB-Wasm / Apache Arrow into\n * plain JavaScript values so they can be safely logged or serialised. It\n * handles nested arrays, structs and any object exposing a `toJSON()` method.\n */\nexport function toPlain<T = unknown>(value: T): T {\n // Primitives (string, number, boolean, undefined, null, bigint, symbol)\n if (value === null || typeof value !== 'object') {\n // Arrow sometimes encodes primitive strings as a JSON string literal, e.g.\n // value === '\"secondary\"'\n // Detect that pattern and decode it.\n if (typeof value === 'string') {\n const trimmed = value.trim();\n if (trimmed.length >= 2 && trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n try {\n return JSON.parse(trimmed) as unknown as T;\n } catch {\n /* ignore parse errors and fall through */\n }\n }\n }\n return value;\n }\n\n // Arrow/DuckDB objects usually implement toJSON() to expose their contents.\n const maybeJsonifiable = value as unknown as { toJSON?: () => unknown };\n if (typeof maybeJsonifiable.toJSON === 'function') {\n // Recurse after conversion to remove any nested wrappers.\n return toPlain(maybeJsonifiable.toJSON()) as T;\n }\n\n // Arrays – normalise every element.\n if (Array.isArray(value)) {\n return value.map((v) => toPlain(v)) as unknown as T;\n }\n\n // Generic object – normalise each property.\n const plainObj = Object.fromEntries(\n Object.entries(value as Record<string, unknown>).map(([k, v]) => [k, toPlain(v)]),\n );\n return plainObj as T;\n}\n","/** Default coordinate reference system used for spatial operations. */\nexport const DEFALT_COORDINATE_FORMAT = 'EPSG:4326';\n/** Default geometry column name for point-based tables. */\nexport const DEFAULT_GEO_COLUMN_NAME = 'geoPoint';\n","// index.ts\nvar earthRadius = 63710088e-1;\nvar factors = {\n centimeters: earthRadius * 100,\n centimetres: earthRadius * 100,\n degrees: 360 / (2 * Math.PI),\n feet: earthRadius * 3.28084,\n inches: earthRadius * 39.37,\n kilometers: earthRadius / 1e3,\n kilometres: earthRadius / 1e3,\n meters: earthRadius,\n metres: earthRadius,\n miles: earthRadius / 1609.344,\n millimeters: earthRadius * 1e3,\n millimetres: earthRadius * 1e3,\n nauticalmiles: earthRadius / 1852,\n radians: 1,\n yards: earthRadius * 1.0936\n};\nvar areaFactors = {\n acres: 247105e-9,\n centimeters: 1e4,\n centimetres: 1e4,\n feet: 10.763910417,\n hectares: 1e-4,\n inches: 1550.003100006,\n kilometers: 1e-6,\n kilometres: 1e-6,\n meters: 1,\n metres: 1,\n miles: 386e-9,\n nauticalmiles: 29155334959812285e-23,\n millimeters: 1e6,\n millimetres: 1e6,\n yards: 1.195990046\n};\nfunction feature(geom, properties, options = {}) {\n const feat = { type: \"Feature\" };\n if (options.id === 0 || options.id) {\n feat.id = options.id;\n }\n if (options.bbox) {\n feat.bbox = options.bbox;\n }\n feat.properties = properties || {};\n feat.geometry = geom;\n return feat;\n}\nfunction geometry(type, coordinates, _options = {}) {\n switch (type) {\n case \"Point\":\n return point(coordinates).geometry;\n case \"LineString\":\n return lineString(coordinates).geometry;\n case \"Polygon\":\n return polygon(coordinates).geometry;\n case \"MultiPoint\":\n return multiPoint(coordinates).geometry;\n case \"MultiLineString\":\n return multiLineString(coordinates).geometry;\n case \"MultiPolygon\":\n return multiPolygon(coordinates).geometry;\n default:\n throw new Error(type + \" is invalid\");\n }\n}\nfunction point(coordinates, properties, options = {}) {\n if (!coordinates) {\n throw new Error(\"coordinates is required\");\n }\n if (!Array.isArray(coordinates)) {\n throw new Error(\"coordinates must be an Array\");\n }\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be at least 2 numbers long\");\n }\n if (!isNumber(coordinates[0]) || !isNumber(coordinates[1])) {\n throw new Error(\"coordinates must contain numbers\");\n }\n const geom = {\n type: \"Point\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction points(coordinates, properties, options = {}) {\n return featureCollection(\n coordinates.map((coords) => {\n return point(coords, properties);\n }),\n options\n );\n}\nfunction polygon(coordinates, properties, options = {}) {\n for (const ring of coordinates) {\n if (ring.length < 4) {\n throw new Error(\n \"Each LinearRing of a Polygon must have 4 or more Positions.\"\n );\n }\n if (ring[ring.length - 1].length !== ring[0].length) {\n throw new Error(\"First and last Position are not equivalent.\");\n }\n for (let j = 0; j < ring[ring.length - 1].length; j++) {\n if (ring[ring.length - 1][j] !== ring[0][j]) {\n throw new Error(\"First and last Position are not equivalent.\");\n }\n }\n }\n const geom = {\n type: \"Polygon\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction polygons(coordinates, properties, options = {}) {\n return featureCollection(\n coordinates.map((coords) => {\n return polygon(coords, properties);\n }),\n options\n );\n}\nfunction lineString(coordinates, properties, options = {}) {\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be an array of two or more positions\");\n }\n const geom = {\n type: \"LineString\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction lineStrings(coordinates, properties, options = {}) {\n return featureCollection(\n coordinates.map((coords) => {\n return lineString(coords, properties);\n }),\n options\n );\n}\nfunction featureCollection(features, options = {}) {\n const fc = { type: \"FeatureCollection\" };\n if (options.id) {\n fc.id = options.id;\n }\n if (options.bbox) {\n fc.bbox = options.bbox;\n }\n fc.features = features;\n return fc;\n}\nfunction multiLineString(coordinates, properties, options = {}) {\n const geom = {\n type: \"MultiLineString\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction multiPoint(coordinates, properties, options = {}) {\n const geom = {\n type: \"MultiPoint\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction multiPolygon(coordinates, properties, options = {}) {\n const geom = {\n type: \"MultiPolygon\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction geometryCollection(geometries, properties, options = {}) {\n const geom = {\n type: \"GeometryCollection\",\n geometries\n };\n return feature(geom, properties, options);\n}\nfunction round(num, precision = 0) {\n if (precision && !(precision >= 0)) {\n throw new Error(\"precision must be a positive number\");\n }\n const multiplier = Math.pow(10, precision || 0);\n return Math.round(num * multiplier) / multiplier;\n}\nfunction radiansToLength(radians, units = \"kilometers\") {\n const factor = factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return radians * factor;\n}\nfunction lengthToRadians(distance, units = \"kilometers\") {\n const factor = factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return distance / factor;\n}\nfunction lengthToDegrees(distance, units) {\n return radiansToDegrees(lengthToRadians(distance, units));\n}\nfunction bearingToAzimuth(bearing) {\n let angle = bearing % 360;\n if (angle < 0) {\n angle += 360;\n }\n return angle;\n}\nfunction azimuthToBearing(angle) {\n angle = angle % 360;\n if (angle > 180) {\n return angle - 360;\n } else if (angle < -180) {\n return angle + 360;\n }\n return angle;\n}\nfunction radiansToDegrees(radians) {\n const normalisedRadians = radians % (2 * Math.PI);\n return normalisedRadians * 180 / Math.PI;\n}\nfunction degreesToRadians(degrees) {\n const normalisedDegrees = degrees % 360;\n return normalisedDegrees * Math.PI / 180;\n}\nfunction convertLength(length, originalUnit = \"kilometers\", finalUnit = \"kilometers\") {\n if (!(length >= 0)) {\n throw new Error(\"length must be a positive number\");\n }\n return radiansToLength(lengthToRadians(length, originalUnit), finalUnit);\n}\nfunction convertArea(area, originalUnit = \"meters\", finalUnit = \"kilometers\") {\n if (!(area >= 0)) {\n throw new Error(\"area must be a positive number\");\n }\n const startFactor = areaFactors[originalUnit];\n if (!startFactor) {\n throw new Error(\"invalid original units\");\n }\n const finalFactor = areaFactors[finalUnit];\n if (!finalFactor) {\n throw new Error(\"invalid final units\");\n }\n return area / startFactor * finalFactor;\n}\nfunction isNumber(num) {\n return !isNaN(num) && num !== null && !Array.isArray(num);\n}\nfunction isObject(input) {\n return input !== null && typeof input === \"object\" && !Array.isArray(input);\n}\nfunction validateBBox(bbox) {\n if (!bbox) {\n throw new Error(\"bbox is required\");\n }\n if (!Array.isArray(bbox)) {\n throw new Error(\"bbox must be an Array\");\n }\n if (bbox.length !== 4 && bbox.length !== 6) {\n throw new Error(\"bbox must be an Array of 4 or 6 numbers\");\n }\n bbox.forEach((num) => {\n if (!isNumber(num)) {\n throw new Error(\"bbox must only contain numbers\");\n }\n });\n}\nfunction validateId(id) {\n if (!id) {\n throw new Error(\"id is required\");\n }\n if ([\"string\", \"number\"].indexOf(typeof id) === -1) {\n throw new Error(\"id must be a number or a string\");\n }\n}\nexport {\n areaFactors,\n azimuthToBearing,\n bearingToAzimuth,\n convertArea,\n convertLength,\n degreesToRadians,\n earthRadius,\n factors,\n feature,\n featureCollection,\n geometry,\n geometryCollection,\n isNumber,\n isObject,\n lengthToDegrees,\n lengthToRadians,\n lineString,\n lineStrings,\n multiLineString,\n multiPoint,\n multiPolygon,\n point,\n points,\n polygon,\n polygons,\n radiansToDegrees,\n radiansToLength,\n round,\n validateBBox,\n validateId\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { isNumber } from \"@turf/helpers\";\nfunction getCoord(coord) {\n if (!coord) {\n throw new Error(\"coord is required\");\n }\n if (!Array.isArray(coord)) {\n if (coord.type === \"Feature\" && coord.geometry !== null && coord.geometry.type === \"Point\") {\n return [...coord.geometry.coordinates];\n }\n if (coord.type === \"Point\") {\n return [...coord.coordinates];\n }\n }\n if (Array.isArray(coord) && coord.length >= 2 && !Array.isArray(coord[0]) && !Array.isArray(coord[1])) {\n return [...coord];\n }\n throw new Error(\"coord must be GeoJSON Point or an Array of numbers\");\n}\nfunction getCoords(coords) {\n if (Array.isArray(coords)) {\n return coords;\n }\n if (coords.type === \"Feature\") {\n if (coords.geometry !== null) {\n return coords.geometry.coordinates;\n }\n } else {\n if (coords.coordinates) {\n return coords.coordinates;\n }\n }\n throw new Error(\n \"coords must be GeoJSON Feature, Geometry Object or an Array\"\n );\n}\nfunction containsNumber(coordinates) {\n if (coordinates.length > 1 && isNumber(coordinates[0]) && isNumber(coordinates[1])) {\n return true;\n }\n if (Array.isArray(coordinates[0]) && coordinates[0].length) {\n return containsNumber(coordinates[0]);\n }\n throw new Error(\"coordinates must only contain numbers\");\n}\nfunction geojsonType(value, type, name) {\n if (!type || !name) {\n throw new Error(\"type and name required\");\n }\n if (!value || value.type !== type) {\n throw new Error(\n \"Invalid input to \" + name + \": must be a \" + type + \", given \" + value.type\n );\n }\n}\nfunction featureOf(feature, type, name) {\n if (!feature) {\n throw new Error(\"No feature passed\");\n }\n if (!name) {\n throw new Error(\".featureOf() requires a name\");\n }\n if (!feature || feature.type !== \"Feature\" || !feature.geometry) {\n throw new Error(\n \"Invalid input to \" + name + \", Feature with geometry required\"\n );\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error(\n \"Invalid input to \" + name + \": must be a \" + type + \", given \" + feature.geometry.type\n );\n }\n}\nfunction collectionOf(featureCollection, type, name) {\n if (!featureCollection) {\n throw new Error(\"No featureCollection passed\");\n }\n if (!name) {\n throw new Error(\".collectionOf() requires a name\");\n }\n if (!featureCollection || featureCollection.type !== \"FeatureCollection\") {\n throw new Error(\n \"Invalid input to \" + name + \", FeatureCollection required\"\n );\n }\n for (const feature of featureCollection.features) {\n if (!feature || feature.type !== \"Feature\" || !feature.geometry) {\n throw new Error(\n \"Invalid input to \" + name + \", Feature with geometry required\"\n );\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error(\n \"Invalid input to \" + name + \": must be a \" + type + \", given \" + feature.geometry.type\n );\n }\n }\n}\nfunction getGeom(geojson) {\n if (geojson.type === \"Feature\") {\n return geojson.geometry;\n }\n return geojson;\n}\nfunction getType(geojson, _name) {\n if (geojson.type === \"FeatureCollection\") {\n return \"FeatureCollection\";\n }\n if (geojson.type === \"GeometryCollection\") {\n return \"GeometryCollection\";\n }\n if (geojson.type === \"Feature\" && geojson.geometry !== null) {\n return geojson.geometry.type;\n }\n return geojson.type;\n}\nexport {\n collectionOf,\n containsNumber,\n featureOf,\n geojsonType,\n getCoord,\n getCoords,\n getGeom,\n getType\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { feature, point, lineString, isObject } from \"@turf/helpers\";\nfunction coordEach(geojson, callback, excludeWrapCoord) {\n if (geojson === null) return;\n var j, k, l, geometry, stopG, coords, geometryMaybeCollection, wrapShrink = 0, coordIndex = 0, isGeometryCollection, type = geojson.type, isFeatureCollection = type === \"FeatureCollection\", isFeature = type === \"Feature\", stop = isFeatureCollection ? geojson.features.length : 1;\n for (var featureIndex = 0; featureIndex < stop; featureIndex++) {\n geometryMaybeCollection = isFeatureCollection ? (\n // @ts-expect-error: Known type conflict\n geojson.features[featureIndex].geometry\n ) : isFeature ? (\n // @ts-expect-error: Known type conflict\n geojson.geometry\n ) : geojson;\n isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === \"GeometryCollection\" : false;\n stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;\n for (var geomIndex = 0; geomIndex < stopG; geomIndex++) {\n var multiFeatureIndex = 0;\n var geometryIndex = 0;\n geometry = isGeometryCollection ? geometryMaybeCollection.geometries[geomIndex] : geometryMaybeCollection;\n if (geometry === null) continue;\n coords = geometry.coordinates;\n var geomType = geometry.type;\n wrapShrink = excludeWrapCoord && (geomType === \"Polygon\" || geomType === \"MultiPolygon\") ? 1 : 0;\n switch (geomType) {\n case null:\n break;\n case \"Point\":\n if (\n // @ts-expect-error: Known type conflict\n callback(\n coords,\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n multiFeatureIndex++;\n break;\n case \"LineString\":\n case \"MultiPoint\":\n for (j = 0; j < coords.length; j++) {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n coords[j],\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n if (geomType === \"MultiPoint\") multiFeatureIndex++;\n }\n if (geomType === \"LineString\") multiFeatureIndex++;\n break;\n case \"Polygon\":\n case \"MultiLineString\":\n for (j = 0; j < coords.length; j++) {\n for (k = 0; k < coords[j].length - wrapShrink; k++) {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n coords[j][k],\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n }\n if (geomType === \"MultiLineString\") multiFeatureIndex++;\n if (geomType === \"Polygon\") geometryIndex++;\n }\n if (geomType === \"Polygon\") multiFeatureIndex++;\n break;\n case \"MultiPolygon\":\n for (j = 0; j < coords.length; j++) {\n geometryIndex = 0;\n for (k = 0; k < coords[j].length; k++) {\n for (l = 0; l < coords[j][k].length - wrapShrink; l++) {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n coords[j][k][l],\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n }\n geometryIndex++;\n }\n multiFeatureIndex++;\n }\n break;\n case \"GeometryCollection\":\n for (j = 0; j < geometry.geometries.length; j++)\n if (\n // @ts-expect-error: Known type conflict\n coordEach(geometry.geometries[j], callback, excludeWrapCoord) === false\n )\n return false;\n break;\n default:\n throw new Error(\"Unknown Geometry Type\");\n }\n }\n }\n}\nfunction coordReduce(geojson, callback, initialValue, excludeWrapCoord) {\n var previousValue = initialValue;\n coordEach(\n geojson,\n function(currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {\n if (coordIndex === 0 && initialValue === void 0)\n previousValue = currentCoord;\n else\n previousValue = callback(\n // @ts-expect-error: Known type conflict\n previousValue,\n currentCoord,\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n );\n },\n excludeWrapCoord\n );\n return previousValue;\n}\nfunction propEach(geojson, callback) {\n var i;\n switch (geojson.type) {\n case \"FeatureCollection\":\n for (i = 0; i < geojson.features.length; i++) {\n if (callback(geojson.features[i].properties, i) === false) break;\n }\n break;\n case \"Feature\":\n callback(geojson.properties, 0);\n break;\n }\n}\nfunction propReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n propEach(geojson, function(currentProperties, featureIndex) {\n if (featureIndex === 0 && initialValue === void 0)\n previousValue = currentProperties;\n else\n previousValue = callback(previousValue, currentProperties, featureIndex);\n });\n return previousValue;\n}\nfunction featureEach(geojson, callback) {\n if (geojson.type === \"Feature\") {\n callback(geojson, 0);\n } else if (geojson.type === \"FeatureCollection\") {\n for (var i = 0; i < geojson.features.length; i++) {\n if (callback(geojson.features[i], i) === false) break;\n }\n }\n}\nfunction featureReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n featureEach(geojson, function(currentFeature, featureIndex) {\n if (featureIndex === 0 && initialValue === void 0)\n previousValue = currentFeature;\n else previousValue = callback(previousValue, currentFeature, featureIndex);\n });\n return previousValue;\n}\nfunction coordAll(geojson) {\n var coords = [];\n coordEach(geojson, function(coord) {\n coords.push(coord);\n });\n return coords;\n}\nfunction geomEach(geojson, callback) {\n var i, j, g, geometry, stopG, geometryMaybeCollection, isGeometryCollection, featureProperties, featureBBox, featureId, featureIndex = 0, isFeatureCollection = geojson.type === \"FeatureCollection\", isFeature = geojson.type === \"Feature\", stop = isFeatureCollection ? geojson.features.length : 1;\n for (i = 0; i < stop; i++) {\n geometryMaybeCollection = isFeatureCollection ? (\n // @ts-expect-error: Known type conflict\n geojson.features[i].geometry\n ) : isFeature ? (\n // @ts-expect-error: Known type conflict\n geojson.geometry\n ) : geojson;\n featureProperties = isFeatureCollection ? (\n // @ts-expect-error: Known type conflict\n geojson.features[i].properties\n ) : isFeature ? (\n // @ts-expect-error: Known type conflict\n geojson.properties\n ) : {};\n featureBBox = isFeatureCollection ? (\n // @ts-expect-error: Known type conflict\n geojson.features[i].bbox\n ) : isFeature ? (\n // @ts-expect-error: Known type conflict\n geojson.bbox\n ) : void 0;\n featureId = isFeatureCollection ? (\n // @ts-expect-error: Known type conflict\n geojson.features[i].id\n ) : isFeature ? (\n // @ts-expect-error: Known type conflict\n geojson.id\n ) : void 0;\n isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === \"GeometryCollection\" : false;\n stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;\n for (g = 0; g < stopG; g++) {\n geometry = isGeometryCollection ? geometryMaybeCollection.geometries[g] : geometryMaybeCollection;\n if (geometry === null) {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n // @ts-expect-error: Known type conflict\n null,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) === false\n )\n return false;\n continue;\n }\n switch (geometry.type) {\n case \"Point\":\n case \"LineString\":\n case \"MultiPoint\":\n case \"Polygon\":\n case \"MultiLineString\":\n case \"MultiPolygon\": {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n geometry,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) === false\n )\n return false;\n break;\n }\n case \"GeometryCollection\": {\n for (j = 0; j < geometry.geometries.length; j++) {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n geometry.geometries[j],\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) === false\n )\n return false;\n }\n break;\n }\n default:\n throw new Error(\"Unknown Geometry Type\");\n }\n }\n featureIndex++;\n }\n}\nfunction geomReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n geomEach(\n geojson,\n function(currentGeometry, featureIndex, featureProperties, featureBBox, featureId) {\n if (featureIndex === 0 && initialValue === void 0)\n previousValue = currentGeometry;\n else\n previousValue = callback(\n // @ts-expect-error: Known type conflict\n previousValue,\n currentGeometry,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n );\n }\n );\n return previousValue;\n}\nfunction flattenEach(geojson, callback) {\n geomEach(geojson, function(geometry, featureIndex, properties, bbox, id) {\n var type = geometry === null ? null : geometry.type;\n switch (type) {\n case null:\n case \"Point\":\n case \"LineString\":\n case \"Polygon\":\n if (\n // @ts-expect-error: Known type conflict\n callback(\n feature(geometry, properties, { bbox, id }),\n featureIndex,\n 0\n ) === false\n )\n return false;\n return;\n }\n var geomType;\n switch (type) {\n case \"MultiPoint\":\n geomType = \"Point\";\n break;\n case \"MultiLineString\":\n geomType = \"LineString\";\n break;\n case \"MultiPolygon\":\n geomType = \"Polygon\";\n break;\n }\n for (\n var multiFeatureIndex = 0;\n // @ts-expect-error: Known type conflict\n multiFeatureIndex < geometry.coordinates.length;\n multiFeatureIndex++\n ) {\n var coordinate = geometry.coordinates[multiFeatureIndex];\n var geom = {\n type: geomType,\n coordinates: coordinate\n };\n if (\n // @ts-expect-error: Known type conflict\n callback(feature(geom, properties), featureIndex, multiFeatureIndex) === false\n )\n return false;\n }\n });\n}\nfunction flattenReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n flattenEach(\n geojson,\n function(currentFeature, featureIndex, multiFeatureIndex) {\n if (featureIndex === 0 && multiFeatureIndex === 0 && initialValue === void 0)\n previousValue = currentFeature;\n else\n previousValue = callback(\n // @ts-expect-error: Known type conflict\n previousValue,\n currentFeature,\n featureIndex,\n multiFeatureIndex\n );\n }\n );\n return previousValue;\n}\nfunction segmentEach(geojson, callback) {\n flattenEach(geojson, function(feature2, featureIndex, multiFeatureIndex) {\n var segmentIndex = 0;\n if (!feature2.geometry) return;\n var type = feature2.geometry.type;\n if (type === \"Point\" || type === \"MultiPoint\") return;\n var previousCoords;\n var previousFeatureIndex = 0;\n var previousMultiIndex = 0;\n var prevGeomIndex = 0;\n if (\n // @ts-expect-error: Known type conflict\n coordEach(\n feature2,\n function(currentCoord, coordIndex, featureIndexCoord, multiPartIndexCoord, geometryIndex) {\n if (\n // @ts-expect-error: Known type conflict\n previousCoords === void 0 || featureIndex > previousFeatureIndex || multiPartIndexCoord > previousMultiIndex || geometryIndex > prevGeomIndex\n ) {\n previousCoords = currentCoord;\n previousFeatureIndex = featureIndex;\n previousMultiIndex = multiPartIndexCoord;\n prevGeomIndex = geometryIndex;\n segmentIndex = 0;\n return;\n }\n var currentSegment = lineString(\n // @ts-expect-error: Known type conflict\n [previousCoords, currentCoord],\n feature2.properties\n );\n if (\n // @ts-expect-error: Known type conflict\n callback(\n // @ts-expect-error: Known type conflict\n currentSegment,\n featureIndex,\n multiFeatureIndex,\n geometryIndex,\n segmentIndex\n ) === false\n )\n return false;\n segmentIndex++;\n previousCoords = currentCoord;\n }\n ) === false\n )\n return false;\n });\n}\nfunction segmentReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n var started = false;\n segmentEach(\n geojson,\n function(currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) {\n if (started === false && initialValue === void 0)\n previousValue = currentSegment;\n else\n previousValue = callback(\n previousValue,\n // @ts-expect-error: Known type conflict\n currentSegment,\n featureIndex,\n multiFeatureIndex,\n geometryIndex,\n segmentIndex\n );\n started = true;\n }\n );\n return previousValue;\n}\nfunction lineEach(geojson, callback) {\n if (!geojson) throw new Error(\"geojson is required\");\n flattenEach(geojson, function(feature2, featureIndex, multiFeatureIndex) {\n if (feature2.geometry === null) return;\n var type = feature2.geometry.type;\n var coords = feature2.geometry.coordinates;\n switch (type) {\n case \"LineString\":\n if (callback(feature2, featureIndex, multiFeatureIndex, 0, 0) === false)\n return false;\n break;\n case \"Polygon\":\n for (var geometryIndex = 0; geometryIndex < coords.length; geometryIndex++) {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n // @ts-expect-error: Known type conflict\n lineString(coords[geometryIndex], feature2.properties),\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n }\n break;\n }\n });\n}\nfunction lineReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n lineEach(\n geojson,\n function(currentLine, featureIndex, multiFeatureIndex, geometryIndex) {\n if (featureIndex === 0 && initialValue === void 0)\n previousValue = currentLine;\n else\n previousValue = callback(\n previousValue,\n currentLine,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n );\n }\n );\n return previousValue;\n}\nfunction findSegment(geojson, options) {\n options = options || {};\n if (!isObject(options)) throw new Error(\"options is invalid\");\n var featureIndex = options.featureIndex || 0;\n var multiFeatureIndex = options.multiFeatureIndex || 0;\n var geometryIndex = options.geometryIndex || 0;\n var segmentIndex = options.segmentIndex || 0;\n var properties = options.properties;\n var geometry;\n switch (geojson.type) {\n case \"FeatureCollection\":\n if (featureIndex < 0)\n featureIndex = geojson.features.length + featureIndex;\n properties = properties || geojson.features[featureIndex].properties;\n geometry = geojson.features[featureIndex].geometry;\n break;\n case \"Feature\":\n properties = properties || geojson.properties;\n geometry = geojson.geometry;\n break;\n case \"Point\":\n case \"MultiPoint\":\n return null;\n case \"LineString\":\n case \"Polygon\":\n case \"MultiLineString\":\n case \"MultiPolygon\":\n geometry = geojson;\n break;\n default:\n throw new Error(\"geojson is invalid\");\n }\n if (geometry === null) return null;\n var coords = geometry.coordinates;\n switch (geometry.type) {\n case \"Point\":\n case \"MultiPoint\":\n return null;\n case \"LineString\":\n if (segmentIndex < 0) segmentIndex = coords.length + segmentIndex - 1;\n return lineString(\n // @ts-expect-error: Known type conflict\n [coords[segmentIndex], coords[segmentIndex + 1]],\n properties,\n options\n );\n case \"Polygon\":\n if (geometryIndex < 0) geometryIndex = coords.length + geometryIndex;\n if (segmentIndex < 0)\n segmentIndex = coords[geometryIndex].length + segmentIndex - 1;\n return lineString(\n [\n // @ts-expect-error: Known type conflict\n coords[geometryIndex][segmentIndex],\n // @ts-expect-error: Known type conflict\n coords[geometryIndex][segmentIndex + 1]\n ],\n properties,\n options\n );\n case \"MultiLineString\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (segmentIndex < 0)\n segmentIndex = coords[multiFeatureIndex].length + segmentIndex - 1;\n return lineString(\n [\n // @ts-expect-error: Known type conflict\n coords[multiFeatureIndex][segmentIndex],\n // @ts-expect-error: Known type conflict\n coords[multiFeatureIndex][segmentIndex + 1]\n ],\n properties,\n options\n );\n case \"MultiPolygon\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (geometryIndex < 0)\n geometryIndex = coords[multiFeatureIndex].length + geometryIndex;\n if (segmentIndex < 0)\n segmentIndex = // @ts-expect-error: Known type conflict\n coords[multiFeatureIndex][geometryIndex].length - segmentIndex - 1;\n return lineString(\n [\n // @ts-expect-error: Known type conflict\n coords[multiFeatureIndex][geometryIndex][segmentIndex],\n // @ts-expect-error: Known type conflict\n coords[multiFeatureIndex][geometryIndex][segmentIndex + 1]\n ],\n properties,\n options\n );\n }\n throw new Error(\"geojson is invalid\");\n}\nfunction findPoint(geojson, options) {\n options = options || {};\n if (!isObject(options)) throw new Error(\"options is invalid\");\n var featureIndex = options.featureIndex || 0;\n var multiFeatureIndex = options.multiFeatureIndex || 0;\n var geometryIndex = options.geometryIndex || 0;\n var coordIndex = options.coordIndex || 0;\n var properties = options.properties;\n var geometry;\n switch (geojson.type) {\n case \"FeatureCollection\":\n if (featureIndex < 0)\n featureIndex = geojson.features.length + featureIndex;\n properties = properties || geojson.features[featureIndex].properties;\n geometry = geojson.features[featureIndex].geometry;\n break;\n case \"Feature\":\n properties = properties || geojson.properties;\n geometry = geojson.geometry;\n break;\n case \"Point\":\n case \"MultiPoint\":\n return null;\n case \"LineString\":\n case \"Polygon\":\n case \"MultiLineString\":\n case \"MultiPolygon\":\n geometry = geojson;\n break;\n default:\n throw new Error(\"geojson is invalid\");\n }\n if (geometry === null) return null;\n var coords = geometry.coordinates;\n switch (geometry.type) {\n case \"Point\":\n return point(coords, properties, options);\n case \"MultiPoint\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n return point(coords[multiFeatureIndex], properties, options);\n case \"LineString\":\n if (coordIndex < 0) coordIndex = coords.length + coordIndex;\n return point(coords[coordIndex], properties, options);\n case \"Polygon\":\n if (geometryIndex < 0) geometryIndex = coords.length + geometryIndex;\n if (coordIndex < 0)\n coordIndex = coords[geometryIndex].length + coordIndex;\n return point(coords[geometryIndex][coordIndex], properties, options);\n case \"MultiLineString\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (coordIndex < 0)\n coordIndex = coords[multiFeatureIndex].length + coordIndex;\n return point(coords[multiFeatureIndex][coordIndex], properties, options);\n case \"MultiPolygon\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (geometryIndex < 0)\n geometryIndex = coords[multiFeatureIndex].length + geometryIndex;\n if (coordIndex < 0)\n coordIndex = coords[multiFeatureIndex][geometryIndex].length - coordIndex;\n return point(\n coords[multiFeatureIndex][geometryIndex][coordIndex],\n properties,\n options\n );\n }\n throw new Error(\"geojson is invalid\");\n}\nexport {\n coordAll,\n coordEach,\n coordReduce,\n featureEach,\n featureReduce,\n findPoint,\n findSegment,\n flattenEach,\n flattenReduce,\n geomEach,\n geomReduce,\n lineEach,\n lineReduce,\n propEach,\n propReduce,\n segmentEach,\n segmentReduce\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { coordEach } from \"@turf/meta\";\nfunction bbox(geojson, options = {}) {\n if (geojson.bbox != null && true !== options.recompute) {\n return geojson.bbox;\n }\n const result = [Infinity, Infinity, -Infinity, -Infinity];\n coordEach(geojson, (coord) => {\n if (result[0] > coord[0]) {\n result[0] = coord[0];\n }\n if (result[1] > coord[1]) {\n result[1] = coord[1];\n }\n if (result[2] < coord[0]) {\n result[2] = coord[0];\n }\n if (result[3] < coord[1]) {\n result[3] = coord[1];\n }\n });\n return result;\n}\nvar index_default = bbox;\nexport {\n bbox,\n index_default as default\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { polygon } from \"@turf/helpers\";\nfunction bboxPolygon(bbox, options = {}) {\n const west = Number(bbox[0]);\n const south = Number(bbox[1]);\n const east = Number(bbox[2]);\n const north = Number(bbox[3]);\n if (bbox.length === 6) {\n throw new Error(\n \"@turf/bbox-polygon does not support BBox with 6 positions\"\n );\n }\n const lowLeft = [west, south];\n const topLeft = [west, north];\n const topRight = [east, north];\n const lowRight = [east, south];\n return polygon(\n [[lowLeft, lowRight, topRight, topLeft, lowLeft]],\n options.properties,\n { bbox, id: options.id }\n );\n}\nvar index_default = bboxPolygon;\nexport {\n bboxPolygon,\n index_default as default\n};\n//# sourceMappingURL=index.js.map","export const epsilon = 1.1102230246251565e-16;\nexport const splitter = 134217729;\nexport const resulterrbound = (3 + 8 * epsilon) * epsilon;\n\n// fast_expansion_sum_zeroelim routine from original code\nexport function sum(elen, e, flen, f, h) {\n let Q, Qnew, hh, bvirt;\n let enow = e[0];\n let fnow = f[0];\n let eindex = 0;\n let findex = 0;\n if ((fnow > enow) === (fnow > -enow)) {\n Q = enow;\n enow = e[++eindex];\n } else {\n Q = fnow;\n fnow = f[++findex];\n }\n let hindex = 0;\n if (eindex < elen && findex < flen) {\n if ((fnow > enow) === (fnow > -enow)) {\n Qnew = enow + Q;\n hh = Q - (Qnew - enow);\n enow = e[++eindex];\n } else {\n Qnew = fnow + Q;\n hh = Q - (Qnew - fnow);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n while (eindex < elen && findex < flen) {\n if ((fnow > enow) === (fnow > -enow)) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n } else {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n }\n while (eindex < elen) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n while (findex < flen) {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\n\nexport function sum_three(alen, a, blen, b, clen, c, tmp, out) {\n return sum(sum(alen, a, blen, b, tmp), tmp, clen, c, out);\n}\n\n// scale_expansion_zeroelim routine from oritinal code\nexport function scale(elen, e, b, h) {\n let Q, sum, hh, product1, product0;\n let bvirt, c, ahi, alo, bhi, blo;\n\n c = splitter * b;\n bhi = c - (c - b);\n blo = b - bhi;\n let enow = e[0];\n Q = enow * b;\n c = splitter * enow;\n ahi = c - (c - enow);\n alo = enow - ahi;\n hh = alo * blo - (Q - ahi * bhi - alo * bhi - ahi * blo);\n let hindex = 0;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n for (let i = 1; i < elen; i++) {\n enow = e[i];\n product1 = enow * b;\n c = splitter * enow;\n ahi = c - (c - enow);\n alo = enow - ahi;\n product0 = alo * blo - (product1 - ahi * bhi - alo * bhi - ahi * blo);\n sum = Q + product0;\n bvirt = sum - Q;\n hh = Q - (sum - bvirt) + (product0 - bvirt);\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n Q = product1 + sum;\n hh = sum - (Q - product1);\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\n\nexport function negate(elen, e) {\n for (let i = 0; i < elen; i++) e[i] = -e[i];\n return elen;\n}\n\nexport function estimate(elen, e) {\n let Q = e[0];\n for (let i = 1; i < elen; i++) Q += e[i];\n return Q;\n}\n\nexport function vec(n) {\n return new Float64Array(n);\n}\n","import {epsilon, splitter, resulterrbound, estimate, vec, sum} from './util.js';\n\nconst ccwerrboundA = (3 + 16 * epsilon) * epsilon;\nconst ccwerrboundB = (2 + 12 * epsilon) * epsilon;\nconst ccwerrboundC = (9 + 64 * epsilon) * epsilon * epsilon;\n\nconst B = vec(4);\nconst C1 = vec(8);\nconst C2 = vec(12);\nconst D = vec(16);\nconst u = vec(4);\n\nfunction orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {\n let acxtail, acytail, bcxtail, bcytail;\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;\n\n const acx = ax - cx;\n const bcx = bx - cx;\n const acy = ay - cy;\n const bcy = by - cy;\n\n s1 = acx * bcy;\n c = splitter * acx;\n ahi = c - (c - acx);\n alo = acx - ahi;\n c = splitter * bcy;\n bhi = c - (c - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acy * bcx;\n c = splitter * acy;\n ahi = c - (c - acy);\n alo = acy - ahi;\n c = splitter * bcx;\n bhi = c - (c - bcx);\n blo = bcx - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n B[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n B[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n B[2] = _j - (u3 - bvirt) + (_i - bvirt);\n B[3] = u3;\n\n let det = estimate(4, B);\n let errbound = ccwerrboundB * detsum;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n bvirt = ax - acx;\n acxtail = ax - (acx + bvirt) + (bvirt - cx);\n bvirt = bx - bcx;\n bcxtail = bx - (bcx + bvirt) + (bvirt - cx);\n bvirt = ay - acy;\n acytail = ay - (acy + bvirt) + (bvirt - cy);\n bvirt = by - bcy;\n bcytail = by - (bcy + bvirt) + (bvirt - cy);\n\n if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {\n return det;\n }\n\n errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);\n det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);\n if (det >= errbound || -det >= errbound) return det;\n\n s1 = acxtail * bcy;\n c = splitter * acxtail;\n ahi = c - (c - acxtail);\n alo = acxtail - ahi;\n c = splitter * bcy;\n bhi = c - (c - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acytail * bcx;\n c = splitter * acytail;\n ahi = c - (c - acytail);\n alo = acytail - ahi;\n c = splitter * bcx;\n bhi = c - (c - bcx);\n blo = bcx - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const C1len = sum(4, B, 4, u, C1);\n\n s1 = acx * bcytail;\n c = splitter * acx;\n ahi = c - (c - acx);\n alo = acx - ahi;\n c = splitter * bcytail;\n bhi = c - (c - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acy * bcxtail;\n c = splitter * acy;\n ahi = c - (c - acy);\n alo = acy - ahi;\n c = splitter * bcxtail;\n bhi = c - (c - bcxtail);\n blo = bcxtail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const C2len = sum(C1len, C1, 4, u, C2);\n\n s1 = acxtail * bcytail;\n c = splitter * acxtail;\n ahi = c - (c - acxtail);\n alo = acxtail - ahi;\n c = splitter * bcytail;\n bhi = c - (c - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acytail * bcxtail;\n c = splitter * acytail;\n ahi = c - (c - acytail);\n alo = acytail - ahi;\n c = splitter * bcxtail;\n bhi = c - (c - bcxtail);\n blo = bcxtail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const Dlen = sum(C2len, C2, 4, u, D);\n\n return D[Dlen - 1];\n}\n\nexport function orient2d(ax, ay, bx, by, cx, cy) {\n const detleft = (ay - cy) * (bx - cx);\n const detright = (ax - cx) * (by - cy);\n const det = detleft - detright;\n\n const detsum = Math.abs(detleft + detright);\n if (Math.abs(det) >= ccwerrboundA * detsum) return det;\n\n return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);\n}\n\nexport function orient2dfast(ax, ay, bx, by, cx, cy) {\n return (ay - cy) * (bx - cx) - (ax - cx) * (by - cy);\n}\n","import {epsilon, splitter, resulterrbound, estimate, vec, sum, scale} from './util.js';\n\nconst o3derrboundA = (7 + 56 * epsilon) * epsilon;\nconst o3derrboundB = (3 + 28 * epsilon) * epsilon;\nconst o3derrboundC = (26 + 288 * epsilon) * epsilon * epsilon;\n\nconst bc = vec(4);\nconst ca = vec(4);\nconst ab = vec(4);\nconst at_b = vec(4);\nconst at_c = vec(4);\nconst bt_c = vec(4);\nconst bt_a = vec(4);\nconst ct_a = vec(4);\nconst ct_b = vec(4);\nconst bct = vec(8);\nconst cat = vec(8);\nconst abt = vec(8);\nconst u = vec(4);\n\nconst _8 = vec(8);\nconst _8b = vec(8);\nconst _16 = vec(16);\nconst _12 = vec(12);\n\nlet fin = vec(192);\nlet fin2 = vec(192);\n\nfunction finadd(finlen, alen, a) {\n finlen = sum(finlen, fin, alen, a, fin2);\n const tmp = fin; fin = fin2; fin2 = tmp;\n return finlen;\n}\n\nfunction tailinit(xtail, ytail, ax, ay, bx, by, a, b) {\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _k, _0, s1, s0, t1, t0, u3, negate;\n if (xtail === 0) {\n if (ytail === 0) {\n a[0] = 0;\n b[0] = 0;\n return 1;\n }\n negate = -ytail;\n s1 = negate * ax;\n c = splitter * negate;\n ahi = c - (c - negate);\n alo = negate - ahi;\n c = splitter * ax;\n bhi = c - (c - ax);\n blo = ax - bhi;\n a[0] = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n a[1] = s1;\n s1 = ytail * bx;\n c = splitter * ytail;\n ahi = c - (c - ytail);\n alo = ytail - ahi;\n c = splitter * bx;\n bhi = c - (c - bx);\n blo = bx - bhi;\n b[0] = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n b[1] = s1;\n return 2;\n }\n if (ytail === 0) {\n s1 = xtail * ay;\n c = splitter * xtail;\n ahi = c - (c - xtail);\n alo = xtail - ahi;\n c = splitter * ay;\n bhi = c - (c - ay);\n blo = ay - bhi;\n a[0] = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n a[1] = s1;\n negate = -xtail;\n s1 = negate * by;\n c = splitter * negate;\n ahi = c - (c - negate);\n alo = negate - ahi;\n c = splitter * by;\n bhi = c - (c - by);\n blo = by - bhi;\n b[0] = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n b[1] = s1;\n return 2;\n }\n s1 = xtail * ay;\n c = splitter * xtail;\n ahi = c - (c - xtail);\n alo = xtail - ahi;\n c = splitter * ay;\n bhi = c - (c - ay);\n blo = ay - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = ytail * ax;\n c = splitter * ytail;\n ahi = c - (c - ytail);\n alo = ytail - ahi;\n c = splitter * ax;\n bhi = c - (c - ax);\n blo = ax - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n a[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n a[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n a[2] = _j - (u3 - bvirt) + (_i - bvirt);\n a[3] = u3;\n s1 = ytail * bx;\n c = splitter * ytail;\n ahi = c - (c - ytail);\n alo = ytail - ahi;\n c = splitter * bx;\n bhi = c - (c - bx);\n blo = bx - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = xtail * by;\n c = splitter * xtail;\n ahi = c - (c - xtail);\n alo = xtail - ahi;\n c = splitter * by;\n bhi = c - (c - by);\n blo = by - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n b[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n b[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n b[2] = _j - (u3 - bvirt) + (_i - bvirt);\n b[3] = u3;\n return 4;\n}\n\nfunction tailadd(finlen, a, b, k, z) {\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _k, _0, s1, s0, u3;\n s1 = a * b;\n c = splitter * a;\n ahi = c - (c - a);\n alo = a - ahi;\n c = splitter * b;\n bhi = c - (c - b);\n blo = b - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n c = splitter * k;\n bhi = c - (c - k);\n blo = k - bhi;\n _i = s0 * k;\n c = splitter * s0;\n ahi = c - (c - s0);\n alo = s0 - ahi;\n u[0] = alo * blo - (_i - ahi * bhi - alo * bhi - ahi * blo);\n _j = s1 * k;\n c = splitter * s1;\n ahi = c - (c - s1);\n alo = s1 - ahi;\n _0 = alo * blo - (_j - ahi * bhi - alo * bhi - ahi * blo);\n _k = _i + _0;\n bvirt = _k - _i;\n u[1] = _i - (_k - bvirt) + (_0 - bvirt);\n u3 = _j + _k;\n u[2] = _k - (u3 - _j);\n u[3] = u3;\n finlen = finadd(finlen, 4, u);\n if (z !== 0) {\n c = splitter * z;\n bhi = c - (c - z);\n blo = z - bhi;\n _i = s0 * z;\n c = splitter * s0;\n ahi = c - (c - s0);\n alo = s0 - ahi;\n u[0] = alo * blo - (_i - ahi * bhi - alo * bhi - ahi * blo);\n _j = s1 * z;\n c = splitter * s1;\n ahi = c - (c - s1);\n alo = s1 - ahi;\n _0 = alo * blo - (_j - ahi * bhi - alo * bhi - ahi * blo);\n _k = _i + _0;\n bvirt = _k - _i;\n u[1] = _i - (_k - bvirt) + (_0 - bvirt);\n u3 = _j + _k;\n u[2] = _k - (u3 - _j);\n u[3] = u3;\n finlen = finadd(finlen, 4, u);\n }\n return finlen;\n}\n\nfunction orient3dadapt(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, permanent) {\n let finlen;\n let adxtail, bdxtail, cdxtail;\n let adytail, bdytail, cdytail;\n let adztail, bdztail, cdztail;\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _k, _0, s1, s0, t1, t0, u3;\n\n const adx = ax - dx;\n const bdx = bx - dx;\n const cdx = cx - dx;\n const ady = ay - dy;\n const bdy = by - dy;\n const cdy = cy - dy;\n const adz = az - dz;\n const bdz = bz - dz;\n const cdz = cz - dz;\n\n s1 = bdx * cdy;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n c = splitter * cdy;\n bhi = c - (c - cdy);\n blo = cdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cdx * bdy;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n c = splitter * bdy;\n bhi = c - (c - bdy);\n blo = bdy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bc[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bc[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n bc[2] = _j - (u3 - bvirt) + (_i - bvirt);\n bc[3] = u3;\n s1 = cdx * ady;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n c = splitter * ady;\n bhi = c - (c - ady);\n blo = ady - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = adx * cdy;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n c = splitter * cdy;\n bhi = c - (c - cdy);\n blo = cdy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ca[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ca[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ca[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ca[3] = u3;\n s1 = adx * bdy;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n c = splitter * bdy;\n bhi = c - (c - bdy);\n blo = bdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bdx * ady;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n c = splitter * ady;\n bhi = c - (c - ady);\n blo = ady - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ab[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ab[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ab[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ab[3] = u3;\n\n finlen = sum(\n sum(\n scale(4, bc, adz, _8), _8,\n scale(4, ca, bdz, _8b), _8b, _16), _16,\n scale(4, ab, cdz, _8), _8, fin);\n\n let det = estimate(finlen, fin);\n let errbound = o3derrboundB * permanent;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n bvirt = ax - adx;\n adxtail = ax - (adx + bvirt) + (bvirt - dx);\n bvirt = bx - bdx;\n bdxtail = bx - (bdx + bvirt) + (bvirt - dx);\n bvirt = cx - cdx;\n cdxtail = cx - (cdx + bvirt) + (bvirt - dx);\n bvirt = ay - ady;\n adytail = ay - (ady + bvirt) + (bvirt - dy);\n bvirt = by - bdy;\n bdytail = by - (bdy + bvirt) + (bvirt - dy);\n bvirt = cy - cdy;\n cdytail = cy - (cdy + bvirt) + (bvirt - dy);\n bvirt = az - adz;\n adztail = az - (adz + bvirt) + (bvirt - dz);\n bvirt = bz - bdz;\n bdztail = bz - (bdz + bvirt) + (bvirt - dz);\n bvirt = cz - cdz;\n cdztail = cz - (cdz + bvirt) + (bvirt - dz);\n\n if (adxtail === 0 && bdxtail === 0 && cdxtail === 0 &&\n adytail === 0 && bdytail === 0 && cdytail === 0 &&\n adztail === 0 && bdztail === 0 && cdztail === 0) {\n return det;\n }\n\n errbound = o3derrboundC * permanent + resulterrbound * Math.abs(det);\n det +=\n adz * (bdx * cdytail + cdy * bdxtail - (bdy * cdxtail + cdx * bdytail)) + adztail * (bdx * cdy - bdy * cdx) +\n bdz * (cdx * adytail + ady * cdxtail - (cdy * adxtail + adx * cdytail)) + bdztail * (cdx * ady - cdy * adx) +\n cdz * (adx * bdytail + bdy * adxtail - (ady * bdxtail + bdx * adytail)) + cdztail * (adx * bdy - ady * bdx);\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n const at_len = tailinit(adxtail, adytail, bdx, bdy, cdx, cdy, at_b, at_c);\n const bt_len = tailinit(bdxtail, bdytail, cdx, cdy, adx, ady, bt_c, bt_a);\n const ct_len = tailinit(cdxtail, cdytail, adx, ady, bdx, bdy, ct_a, ct_b);\n\n const bctlen = sum(bt_len, bt_c, ct_len, ct_b, bct);\n finlen = finadd(finlen, scale(bctlen, bct, adz, _16), _16);\n\n const catlen = sum(ct_len, ct_a, at_len, at_c, cat);\n finlen = finadd(finlen, scale(catlen, cat, bdz, _16), _16);\n\n const abtlen = sum(at_len, at_b, bt_len, bt_a, abt);\n finlen = finadd(finlen, scale(abtlen, abt, cdz, _16), _16);\n\n if (adztail !== 0) {\n finlen = finadd(finlen, scale(4, bc, adztail, _12), _12);\n finlen = finadd(finlen, scale(bctlen, bct, adztail, _16), _16);\n }\n if (bdztail !== 0) {\n finlen = finadd(finlen, scale(4, ca, bdztail, _12), _12);\n finlen = finadd(finlen, scale(catlen, cat, bdztail, _16), _16);\n }\n if (cdztail !== 0) {\n finlen = finadd(finlen, scale(4, ab, cdztail, _12), _12);\n finlen = finadd(finlen, scale(abtlen, abt, cdztail, _16), _16);\n }\n\n if (adxtail !== 0) {\n if (bdytail !== 0) {\n finlen = tailadd(finlen, adxtail, bdytail, cdz, cdztail);\n }\n if (cdytail !== 0) {\n finlen = tailadd(finlen, -adxtail, cdytail, bdz, bdztail);\n }\n }\n if (bdxtail !== 0) {\n if (cdytail !== 0) {\n finlen = tailadd(finlen, bdxtail, cdytail, adz, adztail);\n }\n if (adytail !== 0) {\n finlen = tailadd(finlen, -bdxtail, adytail, cdz, cdztail);\n }\n }\n if (cdxtail !== 0) {\n if (adytail !== 0) {\n finlen = tailadd(finlen, cdxtail, adytail, bdz, bdztail);\n }\n if (bdytail !== 0) {\n finlen = tailadd(finlen, -cdxtail, bdytail, adz, adztail);\n }\n }\n\n return fin[finlen - 1];\n}\n\nexport function orient3d(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz) {\n const adx = ax - dx;\n const bdx = bx - dx;\n const cdx = cx - dx;\n const ady = ay - dy;\n const bdy = by - dy;\n const cdy = cy - dy;\n const adz = az - dz;\n const bdz = bz - dz;\n const cdz = cz - dz;\n\n const bdxcdy = bdx * cdy;\n const cdxbdy = cdx * bdy;\n\n const cdxady = cdx * ady;\n const adxcdy = adx * cdy;\n\n const adxbdy = adx * bdy;\n const bdxady = bdx * ady;\n\n const det =\n adz * (bdxcdy - cdxbdy) +\n bdz * (cdxady - adxcdy) +\n cdz * (adxbdy - bdxady);\n\n const permanent =\n (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * Math.abs(adz) +\n (Math.abs(cdxady) + Math.abs(adxcdy)) * Math.abs(bdz) +\n (Math.abs(adxbdy) + Math.abs(bdxady)) * Math.abs(cdz);\n\n const errbound = o3derrboundA * permanent;\n if (det > errbound || -det > errbound) {\n return det;\n }\n\n return orient3dadapt(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, permanent);\n}\n\nexport function orient3dfast(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz) {\n const adx = ax - dx;\n const bdx = bx - dx;\n const cdx = cx - dx;\n const ady = ay - dy;\n const bdy = by - dy;\n const cdy = cy - dy;\n const adz = az - dz;\n const bdz = bz - dz;\n const cdz = cz - dz;\n\n return adx * (bdy * cdz - bdz * cdy) +\n bdx * (cdy * adz - cdz * ady) +\n cdx * (ady * bdz - adz * bdy);\n}\n","import {epsilon, splitter, resulterrbound, estimate, vec, sum, sum_three, scale} from './util.js';\n\nconst iccerrboundA = (10 + 96 * epsilon) * epsilon;\nconst iccerrboundB = (4 + 48 * epsilon) * epsilon;\nconst iccerrboundC = (44 + 576 * epsilon) * epsilon * epsilon;\n\nconst bc = vec(4);\nconst ca = vec(4);\nconst ab = vec(4);\nconst aa = vec(4);\nconst bb = vec(4);\nconst cc = vec(4);\nconst u = vec(4);\nconst v = vec(4);\nconst axtbc = vec(8);\nconst aytbc = vec(8);\nconst bxtca = vec(8);\nconst bytca = vec(8);\nconst cxtab = vec(8);\nconst cytab = vec(8);\nconst abt = vec(8);\nconst bct = vec(8);\nconst cat = vec(8);\nconst abtt = vec(4);\nconst bctt = vec(4);\nconst catt = vec(4);\n\nconst _8 = vec(8);\nconst _16 = vec(16);\nconst _16b = vec(16);\nconst _16c = vec(16);\nconst _32 = vec(32);\nconst _32b = vec(32);\nconst _48 = vec(48);\nconst _64 = vec(64);\n\nlet fin = vec(1152);\nlet fin2 = vec(1152);\n\nfunction finadd(finlen, a, alen) {\n finlen = sum(finlen, fin, a, alen, fin2);\n const tmp = fin; fin = fin2; fin2 = tmp;\n return finlen;\n}\n\nfunction incircleadapt(ax, ay, bx, by, cx, cy, dx, dy, permanent) {\n let finlen;\n let adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;\n let axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;\n let abtlen, bctlen, catlen;\n let abttlen, bcttlen, cattlen;\n let n1, n0;\n\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;\n\n const adx = ax - dx;\n const bdx = bx - dx;\n const cdx = cx - dx;\n const ady = ay - dy;\n const bdy = by - dy;\n const cdy = cy - dy;\n\n s1 = bdx * cdy;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n c = splitter * cdy;\n bhi = c - (c - cdy);\n blo = cdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cdx * bdy;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n c = splitter * bdy;\n bhi = c - (c - bdy);\n blo = bdy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bc[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bc[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n bc[2] = _j - (u3 - bvirt) + (_i - bvirt);\n bc[3] = u3;\n s1 = cdx * ady;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n c = splitter * ady;\n bhi = c - (c - ady);\n blo = ady - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = adx * cdy;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n c = splitter * cdy;\n bhi = c - (c - cdy);\n blo = cdy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ca[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ca[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ca[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ca[3] = u3;\n s1 = adx * bdy;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n c = splitter * bdy;\n bhi = c - (c - bdy);\n blo = bdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bdx * ady;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n c = splitter * ady;\n bhi = c - (c - ady);\n blo = ady - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ab[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ab[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ab[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ab[3] = u3;\n\n finlen = sum(\n sum(\n sum(\n scale(scale(4, bc, adx, _8), _8, adx, _16), _16,\n scale(scale(4, bc, ady, _8), _8, ady, _16b), _16b, _32), _32,\n sum(\n scale(scale(4, ca, bdx, _8), _8, bdx, _16), _16,\n scale(scale(4, ca, bdy, _8), _8, bdy, _16b), _16b, _32b), _32b, _64), _64,\n sum(\n scale(scale(4, ab, cdx, _8), _8, cdx, _16), _16,\n scale(scale(4, ab, cdy, _8), _8, cdy, _16b), _16b, _32), _32, fin);\n\n let det = estimate(finlen, fin);\n let errbound = iccerrboundB * permanent;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n bvirt = ax - adx;\n adxtail = ax - (adx + bvirt) + (bvirt - dx);\n bvirt = ay - ady;\n adytail = ay - (ady + bvirt) + (bvirt - dy);\n bvirt = bx - bdx;\n bdxtail = bx - (bdx + bvirt) + (bvirt - dx);\n bvirt = by - bdy;\n bdytail = by - (bdy + bvirt) + (bvirt - dy);\n bvirt = cx - cdx;\n cdxtail = cx - (cdx + bvirt) + (bvirt - dx);\n bvirt = cy - cdy;\n cdytail = cy - (cdy + bvirt) + (bvirt - dy);\n if (adxtail === 0 && bdxtail === 0 && cdxtail === 0 && adytail === 0 && bdytail === 0 && cdytail === 0) {\n return det;\n }\n\n errbound = iccerrboundC * permanent + resulterrbound * Math.abs(det);\n det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail) - (bdy * cdxtail + cdx * bdytail)) +\n 2 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx)) +\n ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail) - (cdy * adxtail + adx * cdytail)) +\n 2 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx)) +\n ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail) - (ady * bdxtail + bdx * adytail)) +\n 2 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));\n\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n if (bdxtail !== 0 || bdytail !== 0 || cdxtail !== 0 || cdytail !== 0) {\n s1 = adx * adx;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n s0 = alo * alo - (s1 - ahi * ahi - (ahi + ahi) * alo);\n t1 = ady * ady;\n c = splitter * ady;\n ahi = c - (c - ady);\n alo = ady - ahi;\n t0 = alo * alo - (t1 - ahi * ahi - (ahi + ahi) * alo);\n _i = s0 + t0;\n bvirt = _i - s0;\n aa[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n aa[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n aa[2] = _j - (u3 - bvirt) + (_i - bvirt);\n aa[3] = u3;\n }\n if (cdxtail !== 0 || cdytail !== 0 || adxtail !== 0 || adytail !== 0) {\n s1 = bdx * bdx;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n s0 = alo * alo - (s1 - ahi * ahi - (ahi + ahi) * alo);\n t1 = bdy * bdy;\n c = splitter * bdy;\n ahi = c - (c - bdy);\n alo = bdy - ahi;\n t0 = alo * alo - (t1 - ahi * ahi - (ahi + ahi) * alo);\n _i = s0 + t0;\n bvirt = _i - s0;\n bb[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n bb[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n bb[2] = _j - (u3 - bvirt) + (_i - bvirt);\n bb[3] = u3;\n }\n if (adxtail !== 0 || adytail !== 0 || bdxtail !== 0 || bdytail !== 0) {\n s1 = cdx * cdx;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n s0 = alo * alo - (s1 - ahi * ahi - (ahi + ahi) * alo);\n t1 = cdy * cdy;\n c = splitter * cdy;\n ahi = c - (c - cdy);\n alo = cdy - ahi;\n t0 = alo * alo - (t1 - ahi * ahi - (ahi + ahi) * alo);\n _i = s0 + t0;\n bvirt = _i - s0;\n cc[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n cc[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n cc[2] = _j - (u3 - bvirt) + (_i - bvirt);\n cc[3] = u3;\n }\n\n if (adxtail !== 0) {\n axtbclen = scale(4, bc, adxtail, axtbc);\n finlen = finadd(finlen, sum_three(\n scale(axtbclen, axtbc, 2 * adx, _16), _16,\n scale(scale(4, cc, adxtail, _8), _8, bdy, _16b), _16b,\n scale(scale(4, bb, adxtail, _8), _8, -cdy, _16c), _16c, _32, _48), _48);\n }\n if (adytail !== 0) {\n aytbclen = scale(4, bc, adytail, aytbc);\n finlen = finadd(finlen, sum_three(\n scale(aytbclen, aytbc, 2 * ady, _16), _16,\n scale(scale(4, bb, adytail, _8), _8, cdx, _16b), _16b,\n scale(scale(4, cc, adytail, _8), _8, -bdx, _16c), _16c, _32, _48), _48);\n }\n if (bdxtail !== 0) {\n bxtcalen = scale(4, ca, bdxtail, bxtca);\n finlen = finadd(finlen, sum_three(\n scale(bxtcalen, bxtca, 2 * bdx, _16), _16,\n scale(scale(4, aa, bdxtail, _8), _8, cdy, _16b), _16b,\n scale(scale(4, cc, bdxtail, _8), _8, -ady, _16c), _16c, _32, _48), _48);\n }\n if (bdytail !== 0) {\n bytcalen = scale(4, ca, bdytail, bytca);\n finlen = finadd(finlen, sum_three(\n scale(bytcalen, bytca, 2 * bdy, _16), _16,\n scale(scale(4, cc, bdytail, _8), _8, adx, _16b), _16b,\n scale(scale(4, aa, bdytail, _8), _8, -cdx, _16c), _16c, _32, _48), _48);\n }\n if (cdxtail !== 0) {\n cxtablen = scale(4, ab, cdxtail, cxtab);\n finlen = finadd(finlen, sum_three(\n scale(cxtablen, cxtab, 2 * cdx, _16), _16,\n scale(scale(4, bb, cdxtail, _8), _8, ady, _16b), _16b,\n scale(scale(4, aa, cdxtail, _8), _8, -bdy, _16c), _16c, _32, _48), _48);\n }\n if (cdytail !== 0) {\n cytablen = scale(4, ab, cdytail, cytab);\n finlen = finadd(finlen, sum_three(\n scale(cytablen, cytab, 2 * cdy, _16), _16,\n scale(scale(4, aa, cdytail, _8), _8, bdx, _16b), _16b,\n scale(scale(4, bb, cdytail, _8), _8, -adx, _16c), _16c, _32, _48), _48);\n }\n\n if (adxtail !== 0 || adytail !== 0) {\n if (bdxtail !== 0 || bdytail !== 0 || cdxtail !== 0 || cdytail !== 0) {\n s1 = bdxtail * cdy;\n c = splitter * bdxtail;\n ahi = c - (c - bdxtail);\n alo = bdxtail - ahi;\n c = splitter * cdy;\n bhi = c - (c - cdy);\n blo = cdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bdx * cdytail;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n c = splitter * cdytail;\n bhi = c - (c - cdytail);\n blo = cdytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 + t0;\n bvirt = _i - s0;\n u[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n u[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n s1 = cdxtail * -bdy;\n c = splitter * cdxtail;\n ahi = c - (c - cdxtail);\n alo = cdxtail - ahi;\n c = splitter * -bdy;\n bhi = c - (c - -bdy);\n blo = -bdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cdx * -bdytail;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n c = splitter * -bdytail;\n bhi = c - (c - -bdytail);\n blo = -bdytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 + t0;\n bvirt = _i - s0;\n v[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n v[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n v[2] = _j - (u3 - bvirt) + (_i - bvirt);\n v[3] = u3;\n bctlen = sum(4, u, 4, v, bct);\n s1 = bdxtail * cdytail;\n c = splitter * bdxtail;\n ahi = c - (c - bdxtail);\n alo = bdxtail - ahi;\n c = splitter * cdytail;\n bhi = c - (c - cdytail);\n blo = cdytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cdxtail * bdytail;\n c = splitter * cdxtail;\n ahi = c - (c - cdxtail);\n alo = cdxtail - ahi;\n c = splitter * bdytail;\n bhi = c - (c - bdytail);\n blo = bdytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bctt[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bctt[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n bctt[2] = _j - (u3 - bvirt) + (_i - bvirt);\n bctt[3] = u3;\n bcttlen = 4;\n } else {\n bct[0] = 0;\n bctlen = 1;\n bctt[0] = 0;\n bcttlen = 1;\n }\n if (adxtail !== 0) {\n const len = scale(bctlen, bct, adxtail, _16c);\n finlen = finadd(finlen, sum(\n scale(axtbclen, axtbc, adxtail, _16), _16,\n scale(len, _16c, 2 * adx, _32), _32, _48), _48);\n\n const len2 = scale(bcttlen, bctt, adxtail, _8);\n finlen = finadd(finlen, sum_three(\n scale(len2, _8, 2 * adx, _16), _16,\n scale(len2, _8, adxtail, _16b), _16b,\n scale(len, _16c, adxtail, _32), _32, _32b, _64), _64);\n\n if (bdytail !== 0) {\n finlen = finadd(finlen, scale(scale(4, cc, adxtail, _8), _8, bdytail, _16), _16);\n }\n if (cdytail !== 0) {\n finlen = finadd(finlen, scale(scale(4, bb, -adxtail, _8), _8, cdytail, _16), _16);\n }\n }\n if (adytail !== 0) {\n const len = scale(bctlen, bct, adytail, _16c);\n finlen = finadd(finlen, sum(\n scale(aytbclen, aytbc, adytail, _16), _16,\n scale(len, _16c, 2 * ady, _32), _32, _48), _48);\n\n const len2 = scale(bcttlen, bctt, adytail, _8);\n finlen = finadd(finlen, sum_three(\n scale(len2, _8, 2 * ady, _16), _16,\n scale(len2, _8, adytail, _16b), _16b,\n scale(len, _16c, adytail, _32), _32, _32b, _64), _64);\n }\n }\n if (bdxtail !== 0 || bdytail !== 0) {\n if (cdxtail !== 0 || cdytail !== 0 || adxtail !== 0 || adytail !== 0) {\n s1 = cdxtail * ady;\n c = splitter * cdxtail;\n ahi = c - (c - cdxtail);\n alo = cdxtail - ahi;\n c = splitter * ady;\n bhi = c - (c - ady);\n blo = ady - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cdx * adytail;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n c = splitter * adytail;\n bhi = c - (c - adytail);\n blo = adytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 + t0;\n bvirt = _i - s0;\n u[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n u[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n n1 = -cdy;\n n0 = -cdytail;\n s1 = adxtail * n1;\n c = splitter * adxtail;\n ahi = c - (c - adxtail);\n alo = adxtail - ahi;\n c = splitter * n1;\n bhi = c - (c - n1);\n blo = n1 - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = adx * n0;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n c = splitter * n0;\n bhi = c - (c - n0);\n blo = n0 - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 + t0;\n bvirt = _i - s0;\n v[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n v[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n v[2] = _j - (u3 - bvirt) + (_i - bvirt);\n v[3] = u3;\n catlen = sum(4, u, 4, v, cat);\n s1 = cdxtail * adytail;\n c = splitter * cdxtail;\n ahi = c - (c - cdxtail);\n alo = cdxtail - ahi;\n c = splitter * adytail;\n bhi = c - (c - adytail);\n blo = adytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = adxtail * cdytail;\n c = splitter * adxtail;\n ahi = c - (c - adxtail);\n alo = adxtail - ahi;\n c = splitter * cdytail;\n bhi = c - (c - cdytail);\n blo = cdytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n catt[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n catt[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n catt[2] = _j - (u3 - bvirt) + (_i - bvirt);\n catt[3] = u3;\n cattlen = 4;\n } else {\n cat[0] = 0;\n catlen = 1;\n catt[0] = 0;\n cattlen = 1;\n }\n if (bdxtail !== 0) {\n const len = scale(catlen, cat, bdxtail, _16c);\n finlen = finadd(finlen, sum(\n scale(bxtcalen, bxtca, bdxtail, _16), _16,\n scale(len, _16c, 2 * bdx, _32), _32, _48), _48);\n\n const len2 = scale(cattlen, catt, bdxtail, _8);\n finlen = finadd(finlen, sum_three(\n scale(len2, _8, 2 * bdx, _16), _16,\n scale(len2, _8, bdxtail, _16b), _16b,\n scale(len, _16c, bdxtail, _32), _32, _32b, _64), _64);\n\n if (cdytail !== 0) {\n finlen = finadd(finlen, scale(scale(4, aa, bdxtail, _8), _8, cdytail, _16), _16);\n }\n if (adytail !== 0) {\n finlen = finadd(finlen, scale(scale(4, cc, -bdxtail, _8), _8, adytail, _16), _16);\n }\n }\n if (bdytail !== 0) {\n const len = scale(catlen, cat, bdytail, _16c);\n finlen = finadd(finlen, sum(\n scale(bytcalen, bytca, bdytail, _16), _16,\n scale(len, _16c, 2 * bdy, _32), _32, _48), _48);\n\n const len2 = scale(cattlen, catt, bdytail, _8);\n finlen = finadd(finlen, sum_three(\n scale(len2, _8, 2 * bdy, _16), _16,\n scale(len2, _8, bdytail, _16b), _16b,\n scale(len, _16c, bdytail, _32), _32, _32b, _64), _64);\n }\n }\n if (cdxtail !== 0 || cdytail !== 0) {\n if (adxtail !== 0 || adytail !== 0 || bdxtail !== 0 || bdytail !== 0) {\n s1 = adxtail * bdy;\n c = splitter * adxtail;\n ahi = c - (c - adxtail);\n alo = adxtail - ahi;\n c = splitter * bdy;\n bhi = c - (c - bdy);\n blo = bdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = adx * bdytail;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n c = splitter * bdytail;\n bhi = c - (c - bdytail);\n blo = bdytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 + t0;\n bvirt = _i - s0;\n u[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n u[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n n1 = -ady;\n n0 = -adytail;\n s1 = bdxtail * n1;\n c = splitter * bdxtail;\n ahi = c - (c - bdxtail);\n alo = bdxtail - ahi;\n c = splitter * n1;\n bhi = c - (c - n1);\n blo = n1 - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bdx * n0;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n c = splitter * n0;\n bhi = c - (c - n0);\n blo = n0 - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 + t0;\n bvirt = _i - s0;\n v[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n v[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n v[2] = _j - (u3 - bvirt) + (_i - bvirt);\n v[3] = u3;\n abtlen = sum(4, u, 4, v, abt);\n s1 = adxtail * bdytail;\n c = splitter * adxtail;\n ahi = c - (c - adxtail);\n alo = adxtail - ahi;\n c = splitter * bdytail;\n bhi = c - (c - bdytail);\n blo = bdytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bdxtail * adytail;\n c = splitter * bdxtail;\n ahi = c - (c - bdxtail);\n alo = bdxtail - ahi;\n c = splitter * adytail;\n bhi = c - (c - adytail);\n blo = adytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n abtt[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n abtt[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n abtt[2] = _j - (u3 - bvirt) + (_i - bvirt);\n abtt[3] = u3;\n abttlen = 4;\n } else {\n abt[0] = 0;\n abtlen = 1;\n abtt[0] = 0;\n abttlen = 1;\n }\n if (cdxtail !== 0) {\n const len = scale(abtlen, abt, cdxtail, _16c);\n finlen = finadd(finlen, sum(\n scale(cxtablen, cxtab, cdxtail, _16), _16,\n scale(len, _16c, 2 * cdx, _32), _32, _48), _48);\n\n const len2 = scale(abttlen, abtt, cdxtail, _8);\n finlen = finadd(finlen, sum_three(\n scale(len2, _8, 2 * cdx, _16), _16,\n scale(len2, _8, cdxtail, _16b), _16b,\n scale(len, _16c, cdxtail, _32), _32, _32b, _64), _64);\n\n if (adytail !== 0) {\n finlen = finadd(finlen, scale(scale(4, bb, cdxtail, _8), _8, adytail, _16), _16);\n }\n if (bdytail !== 0) {\n finlen = finadd(finlen, scale(scale(4, aa, -cdxtail, _8), _8, bdytail, _16), _16);\n }\n }\n if (cdytail !== 0) {\n const len = scale(abtlen, abt, cdytail, _16c);\n finlen = finadd(finlen, sum(\n scale(cytablen, cytab, cdytail, _16), _16,\n scale(len, _16c, 2 * cdy, _32), _32, _48), _48);\n\n const len2 = scale(abttlen, abtt, cdytail, _8);\n finlen = finadd(finlen, sum_three(\n scale(len2, _8, 2 * cdy, _16), _16,\n scale(len2, _8, cdytail, _16b), _16b,\n scale(len, _16c, cdytail, _32), _32, _32b, _64), _64);\n }\n }\n\n return fin[finlen - 1];\n}\n\nexport function incircle(ax, ay, bx, by, cx, cy, dx, dy) {\n const adx = ax - dx;\n const bdx = bx - dx;\n const cdx = cx - dx;\n const ady = ay - dy;\n const bdy = by - dy;\n const cdy = cy - dy;\n\n const bdxcdy = bdx * cdy;\n const cdxbdy = cdx * bdy;\n const alift = adx * adx + ady * ady;\n\n const cdxady = cdx * ady;\n const adxcdy = adx * cdy;\n const blift = bdx * bdx + bdy * bdy;\n\n const adxbdy = adx * bdy;\n const bdxady = bdx * ady;\n const clift = cdx * cdx + cdy * cdy;\n\n const det =\n alift * (bdxcdy - cdxbdy) +\n blift * (cdxady - adxcdy) +\n clift * (adxbdy - bdxady);\n\n const permanent =\n (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * alift +\n (Math.abs(cdxady) + Math.abs(adxcdy)) * blift +\n (Math.abs(adxbdy) + Math.abs(bdxady)) * clift;\n\n const errbound = iccerrboundA * permanent;\n\n if (det > errbound || -det > errbound) {\n return det;\n }\n return incircleadapt(ax, ay, bx, by, cx, cy, dx, dy, permanent);\n}\n\nexport function incirclefast(ax, ay, bx, by, cx, cy, dx, dy) {\n const adx = ax - dx;\n const ady = ay - dy;\n const bdx = bx - dx;\n const bdy = by - dy;\n const cdx = cx - dx;\n const cdy = cy - dy;\n\n const abdet = adx * bdy - bdx * ady;\n const bcdet = bdx * cdy - cdx * bdy;\n const cadet = cdx * ady - adx * cdy;\n const alift = adx * adx + ady * ady;\n const blift = bdx * bdx + bdy * bdy;\n const clift = cdx * cdx + cdy * cdy;\n\n return alift * bcdet + blift * cadet + clift * abdet;\n}\n","import {epsilon, splitter, resulterrbound, estimate, vec, sum, sum_three, scale, negate} from './util.js';\n\nconst isperrboundA = (16 + 224 * epsilon) * epsilon;\nconst isperrboundB = (5 + 72 * epsilon) * epsilon;\nconst isperrboundC = (71 + 1408 * epsilon) * epsilon * epsilon;\n\nconst ab = vec(4);\nconst bc = vec(4);\nconst cd = vec(4);\nconst de = vec(4);\nconst ea = vec(4);\nconst ac = vec(4);\nconst bd = vec(4);\nconst ce = vec(4);\nconst da = vec(4);\nconst eb = vec(4);\n\nconst abc = vec(24);\nconst bcd = vec(24);\nconst cde = vec(24);\nconst dea = vec(24);\nconst eab = vec(24);\nconst abd = vec(24);\nconst bce = vec(24);\nconst cda = vec(24);\nconst deb = vec(24);\nconst eac = vec(24);\n\nconst adet = vec(1152);\nconst bdet = vec(1152);\nconst cdet = vec(1152);\nconst ddet = vec(1152);\nconst edet = vec(1152);\nconst abdet = vec(2304);\nconst cddet = vec(2304);\nconst cdedet = vec(3456);\nconst deter = vec(5760);\n\nconst _8 = vec(8);\nconst _8b = vec(8);\nconst _8c = vec(8);\nconst _16 = vec(16);\nconst _24 = vec(24);\nconst _48 = vec(48);\nconst _48b = vec(48);\nconst _96 = vec(96);\nconst _192 = vec(192);\nconst _384x = vec(384);\nconst _384y = vec(384);\nconst _384z = vec(384);\nconst _768 = vec(768);\n\nfunction sum_three_scale(a, b, c, az, bz, cz, out) {\n return sum_three(\n scale(4, a, az, _8), _8,\n scale(4, b, bz, _8b), _8b,\n scale(4, c, cz, _8c), _8c, _16, out);\n}\n\nfunction liftexact(alen, a, blen, b, clen, c, dlen, d, x, y, z, out) {\n const len = sum(\n sum(alen, a, blen, b, _48), _48,\n negate(sum(clen, c, dlen, d, _48b), _48b), _48b, _96);\n\n return sum_three(\n scale(scale(len, _96, x, _192), _192, x, _384x), _384x,\n scale(scale(len, _96, y, _192), _192, y, _384y), _384y,\n scale(scale(len, _96, z, _192), _192, z, _384z), _384z, _768, out);\n}\n\nfunction insphereexact(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez) {\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;\n\n s1 = ax * by;\n c = splitter * ax;\n ahi = c - (c - ax);\n alo = ax - ahi;\n c = splitter * by;\n bhi = c - (c - by);\n blo = by - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bx * ay;\n c = splitter * bx;\n ahi = c - (c - bx);\n alo = bx - ahi;\n c = splitter * ay;\n bhi = c - (c - ay);\n blo = ay - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ab[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ab[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ab[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ab[3] = u3;\n s1 = bx * cy;\n c = splitter * bx;\n ahi = c - (c - bx);\n alo = bx - ahi;\n c = splitter * cy;\n bhi = c - (c - cy);\n blo = cy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cx * by;\n c = splitter * cx;\n ahi = c - (c - cx);\n alo = cx - ahi;\n c = splitter * by;\n bhi = c - (c - by);\n blo = by - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bc[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bc[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n bc[2] = _j - (u3 - bvirt) + (_i - bvirt);\n bc[3] = u3;\n s1 = cx * dy;\n c = splitter * cx;\n ahi = c - (c - cx);\n alo = cx - ahi;\n c = splitter * dy;\n bhi = c - (c - dy);\n blo = dy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = dx * cy;\n c = splitter * dx;\n ahi = c - (c - dx);\n alo = dx - ahi;\n c = splitter * cy;\n bhi = c - (c - cy);\n blo = cy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n cd[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n cd[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n cd[2] = _j - (u3 - bvirt) + (_i - bvirt);\n cd[3] = u3;\n s1 = dx * ey;\n c = splitter * dx;\n ahi = c - (c - dx);\n alo = dx - ahi;\n c = splitter * ey;\n bhi = c - (c - ey);\n blo = ey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = ex * dy;\n c = splitter * ex;\n ahi = c - (c - ex);\n alo = ex - ahi;\n c = splitter * dy;\n bhi = c - (c - dy);\n blo = dy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n de[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n de[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n de[2] = _j - (u3 - bvirt) + (_i - bvirt);\n de[3] = u3;\n s1 = ex * ay;\n c = splitter * ex;\n ahi = c - (c - ex);\n alo = ex - ahi;\n c = splitter * ay;\n bhi = c - (c - ay);\n blo = ay - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = ax * ey;\n c = splitter * ax;\n ahi = c - (c - ax);\n alo = ax - ahi;\n c = splitter * ey;\n bhi = c - (c - ey);\n blo = ey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ea[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ea[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ea[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ea[3] = u3;\n s1 = ax * cy;\n c = splitter * ax;\n ahi = c - (c - ax);\n alo = ax - ahi;\n c = splitter * cy;\n bhi = c - (c - cy);\n blo = cy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cx * ay;\n c = splitter * cx;\n ahi = c - (c - cx);\n alo = cx - ahi;\n c = splitter * ay;\n bhi = c - (c - ay);\n blo = ay - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ac[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ac[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ac[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ac[3] = u3;\n s1 = bx * dy;\n c = splitter * bx;\n ahi = c - (c - bx);\n alo = bx - ahi;\n c = splitter * dy;\n bhi = c - (c - dy);\n blo = dy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = dx * by;\n c = splitter * dx;\n ahi = c - (c - dx);\n alo = dx - ahi;\n c = splitter * by;\n bhi = c - (c - by);\n blo = by - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bd[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bd[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n bd[2] = _j - (u3 - bvirt) + (_i - bvirt);\n bd[3] = u3;\n s1 = cx * ey;\n c = splitter * cx;\n ahi = c - (c - cx);\n alo = cx - ahi;\n c = splitter * ey;\n bhi = c - (c - ey);\n blo = ey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = ex * cy;\n c = splitter * ex;\n ahi = c - (c - ex);\n alo = ex - ahi;\n c = splitter * cy;\n bhi = c - (c - cy);\n blo = cy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ce[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ce[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ce[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ce[3] = u3;\n s1 = dx * ay;\n c = splitter * dx;\n ahi = c - (c - dx);\n alo = dx - ahi;\n c = splitter * ay;\n bhi = c - (c - ay);\n blo = ay - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = ax * dy;\n c = splitter * ax;\n ahi = c - (c - ax);\n alo = ax - ahi;\n c = splitter * dy;\n bhi = c - (c - dy);\n blo = dy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n da[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n da[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n da[2] = _j - (u3 - bvirt) + (_i - bvirt);\n da[3] = u3;\n s1 = ex * by;\n c = splitter * ex;\n ahi = c - (c - ex);\n alo = ex - ahi;\n c = splitter * by;\n bhi = c - (c - by);\n blo = by - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bx * ey;\n c = splitter * bx;\n ahi = c - (c - bx);\n alo = bx - ahi;\n c = splitter * ey;\n bhi = c - (c - ey);\n blo = ey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n eb[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n eb[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n eb[2] = _j - (u3 - bvirt) + (_i - bvirt);\n eb[3] = u3;\n\n const abclen = sum_three_scale(ab, bc, ac, cz, az, -bz, abc);\n const bcdlen = sum_three_scale(bc, cd, bd, dz, bz, -cz, bcd);\n const cdelen = sum_three_scale(cd, de, ce, ez, cz, -dz, cde);\n const dealen = sum_three_scale(de, ea, da, az, dz, -ez, dea);\n const eablen = sum_three_scale(ea, ab, eb, bz, ez, -az, eab);\n const abdlen = sum_three_scale(ab, bd, da, dz, az, bz, abd);\n const bcelen = sum_three_scale(bc, ce, eb, ez, bz, cz, bce);\n const cdalen = sum_three_scale(cd, da, ac, az, cz, dz, cda);\n const deblen = sum_three_scale(de, eb, bd, bz, dz, ez, deb);\n const eaclen = sum_three_scale(ea, ac, ce, cz, ez, az, eac);\n\n const deterlen = sum_three(\n liftexact(cdelen, cde, bcelen, bce, deblen, deb, bcdlen, bcd, ax, ay, az, adet), adet,\n liftexact(dealen, dea, cdalen, cda, eaclen, eac, cdelen, cde, bx, by, bz, bdet), bdet,\n sum_three(\n liftexact(eablen, eab, deblen, deb, abdlen, abd, dealen, dea, cx, cy, cz, cdet), cdet,\n liftexact(abclen, abc, eaclen, eac, bcelen, bce, eablen, eab, dx, dy, dz, ddet), ddet,\n liftexact(bcdlen, bcd, abdlen, abd, cdalen, cda, abclen, abc, ex, ey, ez, edet), edet, cddet, cdedet), cdedet, abdet, deter);\n\n return deter[deterlen - 1];\n}\n\nconst xdet = vec(96);\nconst ydet = vec(96);\nconst zdet = vec(96);\nconst fin = vec(1152);\n\nfunction liftadapt(a, b, c, az, bz, cz, x, y, z, out) {\n const len = sum_three_scale(a, b, c, az, bz, cz, _24);\n return sum_three(\n scale(scale(len, _24, x, _48), _48, x, xdet), xdet,\n scale(scale(len, _24, y, _48), _48, y, ydet), ydet,\n scale(scale(len, _24, z, _48), _48, z, zdet), zdet, _192, out);\n}\n\nfunction insphereadapt(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez, permanent) {\n let ab3, bc3, cd3, da3, ac3, bd3;\n\n let aextail, bextail, cextail, dextail;\n let aeytail, beytail, ceytail, deytail;\n let aeztail, beztail, ceztail, deztail;\n\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0;\n\n const aex = ax - ex;\n const bex = bx - ex;\n const cex = cx - ex;\n const dex = dx - ex;\n const aey = ay - ey;\n const bey = by - ey;\n const cey = cy - ey;\n const dey = dy - ey;\n const aez = az - ez;\n const bez = bz - ez;\n const cez = cz - ez;\n const dez = dz - ez;\n\n s1 = aex * bey;\n c = splitter * aex;\n ahi = c - (c - aex);\n alo = aex - ahi;\n c = splitter * bey;\n bhi = c - (c - bey);\n blo = bey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bex * aey;\n c = splitter * bex;\n ahi = c - (c - bex);\n alo = bex - ahi;\n c = splitter * aey;\n bhi = c - (c - aey);\n blo = aey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ab[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ab[1] = _0 - (_i + bvirt) + (bvirt - t1);\n ab3 = _j + _i;\n bvirt = ab3 - _j;\n ab[2] = _j - (ab3 - bvirt) + (_i - bvirt);\n ab[3] = ab3;\n s1 = bex * cey;\n c = splitter * bex;\n ahi = c - (c - bex);\n alo = bex - ahi;\n c = splitter * cey;\n bhi = c - (c - cey);\n blo = cey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cex * bey;\n c = splitter * cex;\n ahi = c - (c - cex);\n alo = cex - ahi;\n c = splitter * bey;\n bhi = c - (c - bey);\n blo = bey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bc[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bc[1] = _0 - (_i + bvirt) + (bvirt - t1);\n bc3 = _j + _i;\n bvirt = bc3 - _j;\n bc[2] = _j - (bc3 - bvirt) + (_i - bvirt);\n bc[3] = bc3;\n s1 = cex * dey;\n c = splitter * cex;\n ahi = c - (c - cex);\n alo = cex - ahi;\n c = splitter * dey;\n bhi = c - (c - dey);\n blo = dey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = dex * cey;\n c = splitter * dex;\n ahi = c - (c - dex);\n alo = dex - ahi;\n c = splitter * cey;\n bhi = c - (c - cey);\n blo = cey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n cd[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n cd[1] = _0 - (_i + bvirt) + (bvirt - t1);\n cd3 = _j + _i;\n bvirt = cd3 - _j;\n cd[2] = _j - (cd3 - bvirt) + (_i - bvirt);\n cd[3] = cd3;\n s1 = dex * aey;\n c = splitter * dex;\n ahi = c - (c - dex);\n alo = dex - ahi;\n c = splitter * aey;\n bhi = c - (c - aey);\n blo = aey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = aex * dey;\n c = splitter * aex;\n ahi = c - (c - aex);\n alo = aex - ahi;\n c = splitter * dey;\n bhi = c - (c - dey);\n blo = dey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n da[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n da[1] = _0 - (_i + bvirt) + (bvirt - t1);\n da3 = _j + _i;\n bvirt = da3 - _j;\n da[2] = _j - (da3 - bvirt) + (_i - bvirt);\n da[3] = da3;\n s1 = aex * cey;\n c = splitter * aex;\n ahi = c - (c - aex);\n alo = aex - ahi;\n c = splitter * cey;\n bhi = c - (c - cey);\n blo = cey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cex * aey;\n c = splitter * cex;\n ahi = c - (c - cex);\n alo = cex - ahi;\n c = splitter * aey;\n bhi = c - (c - aey);\n blo = aey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ac[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ac[1] = _0 - (_i + bvirt) + (bvirt - t1);\n ac3 = _j + _i;\n bvirt = ac3 - _j;\n ac[2] = _j - (ac3 - bvirt) + (_i - bvirt);\n ac[3] = ac3;\n s1 = bex * dey;\n c = splitter * bex;\n ahi = c - (c - bex);\n alo = bex - ahi;\n c = splitter * dey;\n bhi = c - (c - dey);\n blo = dey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = dex * bey;\n c = splitter * dex;\n ahi = c - (c - dex);\n alo = dex - ahi;\n c = splitter * bey;\n bhi = c - (c - bey);\n blo = bey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bd[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bd[1] = _0 - (_i + bvirt) + (bvirt - t1);\n bd3 = _j + _i;\n bvirt = bd3 - _j;\n bd[2] = _j - (bd3 - bvirt) + (_i - bvirt);\n bd[3] = bd3;\n\n const finlen = sum(\n sum(\n negate(liftadapt(bc, cd, bd, dez, bez, -cez, aex, aey, aez, adet), adet), adet,\n liftadapt(cd, da, ac, aez, cez, dez, bex, bey, bez, bdet), bdet, abdet), abdet,\n sum(\n negate(liftadapt(da, ab, bd, bez, dez, aez, cex, cey, cez, cdet), cdet), cdet,\n liftadapt(ab, bc, ac, cez, aez, -bez, dex, dey, dez, ddet), ddet, cddet), cddet, fin);\n\n let det = estimate(finlen, fin);\n let errbound = isperrboundB * permanent;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n bvirt = ax - aex;\n aextail = ax - (aex + bvirt) + (bvirt - ex);\n bvirt = ay - aey;\n aeytail = ay - (aey + bvirt) + (bvirt - ey);\n bvirt = az - aez;\n aeztail = az - (aez + bvirt) + (bvirt - ez);\n bvirt = bx - bex;\n bextail = bx - (bex + bvirt) + (bvirt - ex);\n bvirt = by - bey;\n beytail = by - (bey + bvirt) + (bvirt - ey);\n bvirt = bz - bez;\n beztail = bz - (bez + bvirt) + (bvirt - ez);\n bvirt = cx - cex;\n cextail = cx - (cex + bvirt) + (bvirt - ex);\n bvirt = cy - cey;\n ceytail = cy - (cey + bvirt) + (bvirt - ey);\n bvirt = cz - cez;\n ceztail = cz - (cez + bvirt) + (bvirt - ez);\n bvirt = dx - dex;\n dextail = dx - (dex + bvirt) + (bvirt - ex);\n bvirt = dy - dey;\n deytail = dy - (dey + bvirt) + (bvirt - ey);\n bvirt = dz - dez;\n deztail = dz - (dez + bvirt) + (bvirt - ez);\n if (aextail === 0 && aeytail === 0 && aeztail === 0 &&\n bextail === 0 && beytail === 0 && beztail === 0 &&\n cextail === 0 && ceytail === 0 && ceztail === 0 &&\n dextail === 0 && deytail === 0 && deztail === 0) {\n return det;\n }\n\n errbound = isperrboundC * permanent + resulterrbound * Math.abs(det);\n\n const abeps = (aex * beytail + bey * aextail) - (aey * bextail + bex * aeytail);\n const bceps = (bex * ceytail + cey * bextail) - (bey * cextail + cex * beytail);\n const cdeps = (cex * deytail + dey * cextail) - (cey * dextail + dex * ceytail);\n const daeps = (dex * aeytail + aey * dextail) - (dey * aextail + aex * deytail);\n const aceps = (aex * ceytail + cey * aextail) - (aey * cextail + cex * aeytail);\n const bdeps = (bex * deytail + dey * bextail) - (bey * dextail + dex * beytail);\n det +=\n (((bex * bex + bey * bey + bez * bez) * ((cez * daeps + dez * aceps + aez * cdeps) +\n (ceztail * da3 + deztail * ac3 + aeztail * cd3)) + (dex * dex + dey * dey + dez * dez) *\n ((aez * bceps - bez * aceps + cez * abeps) + (aeztail * bc3 - beztail * ac3 + ceztail * ab3))) -\n ((aex * aex + aey * aey + aez * aez) * ((bez * cdeps - cez * bdeps + dez * bceps) +\n (beztail * cd3 - ceztail * bd3 + deztail * bc3)) + (cex * cex + cey * cey + cez * cez) *\n ((dez * abeps + aez * bdeps + bez * daeps) + (deztail * ab3 + aeztail * bd3 + beztail * da3)))) +\n 2 * (((bex * bextail + bey * beytail + bez * beztail) * (cez * da3 + dez * ac3 + aez * cd3) +\n (dex * dextail + dey * deytail + dez * deztail) * (aez * bc3 - bez * ac3 + cez * ab3)) -\n ((aex * aextail + aey * aeytail + aez * aeztail) * (bez * cd3 - cez * bd3 + dez * bc3) +\n (cex * cextail + cey * ceytail + cez * ceztail) * (dez * ab3 + aez * bd3 + bez * da3)));\n\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n return insphereexact(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez);\n}\n\nexport function insphere(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez) {\n const aex = ax - ex;\n const bex = bx - ex;\n const cex = cx - ex;\n const dex = dx - ex;\n const aey = ay - ey;\n const bey = by - ey;\n const cey = cy - ey;\n const dey = dy - ey;\n const aez = az - ez;\n const bez = bz - ez;\n const cez = cz - ez;\n const dez = dz - ez;\n\n const aexbey = aex * bey;\n const bexaey = bex * aey;\n const ab = aexbey - bexaey;\n const bexcey = bex * cey;\n const cexbey = cex * bey;\n const bc = bexcey - cexbey;\n const cexdey = cex * dey;\n const dexcey = dex * cey;\n const cd = cexdey - dexcey;\n const dexaey = dex * aey;\n const aexdey = aex * dey;\n const da = dexaey - aexdey;\n const aexcey = aex * cey;\n const cexaey = cex * aey;\n const ac = aexcey - cexaey;\n const bexdey = bex * dey;\n const dexbey = dex * bey;\n const bd = bexdey - dexbey;\n\n const alift = aex * aex + aey * aey + aez * aez;\n const blift = bex * bex + bey * bey + bez * bez;\n const clift = cex * cex + cey * cey + cez * cez;\n const dlift = dex * dex + dey * dey + dez * dez;\n\n const det =\n (clift * (dez * ab + aez * bd + bez * da) - dlift * (aez * bc - bez * ac + cez * ab)) +\n (alift * (bez * cd - cez * bd + dez * bc) - blift * (cez * da + dez * ac + aez * cd));\n\n const aezplus = Math.abs(aez);\n const bezplus = Math.abs(bez);\n const cezplus = Math.abs(cez);\n const dezplus = Math.abs(dez);\n const aexbeyplus = Math.abs(aexbey) + Math.abs(bexaey);\n const bexceyplus = Math.abs(bexcey) + Math.abs(cexbey);\n const cexdeyplus = Math.abs(cexdey) + Math.abs(dexcey);\n const dexaeyplus = Math.abs(dexaey) + Math.abs(aexdey);\n const aexceyplus = Math.abs(aexcey) + Math.abs(cexaey);\n const bexdeyplus = Math.abs(bexdey) + Math.abs(dexbey);\n const permanent =\n (cexdeyplus * bezplus + bexdeyplus * cezplus + bexceyplus * dezplus) * alift +\n (dexaeyplus * cezplus + aexceyplus * dezplus + cexdeyplus * aezplus) * blift +\n (aexbeyplus * dezplus + bexdeyplus * aezplus + dexaeyplus * bezplus) * clift +\n (bexceyplus * aezplus + aexceyplus * bezplus + aexbeyplus * cezplus) * dlift;\n\n const errbound = isperrboundA * permanent;\n if (det > errbound || -det > errbound) {\n return det;\n }\n return -insphereadapt(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez, permanent);\n}\n\nexport function inspherefast(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez) {\n const aex = ax - ex;\n const bex = bx - ex;\n const cex = cx - ex;\n const dex = dx - ex;\n const aey = ay - ey;\n const bey = by - ey;\n const cey = cy - ey;\n const dey = dy - ey;\n const aez = az - ez;\n const bez = bz - ez;\n const cez = cz - ez;\n const dez = dz - ez;\n\n const ab = aex * bey - bex * aey;\n const bc = bex * cey - cex * bey;\n const cd = cex * dey - dex * cey;\n const da = dex * aey - aex * dey;\n const ac = aex * cey - cex * aey;\n const bd = bex * dey - dex * bey;\n\n const abc = aez * bc - bez * ac + cez * ab;\n const bcd = bez * cd - cez * bd + dez * bc;\n const cda = cez * da + dez * ac + aez * cd;\n const dab = dez * ab + aez * bd + bez * da;\n\n const alift = aex * aex + aey * aey + aez * aez;\n const blift = bex * bex + bey * bey + bez * bez;\n const clift = cex * cex + cey * cey + cez * cez;\n const dlift = dex * dex + dey * dey + dez * dez;\n\n return (clift * dab - dlift * abc) + (alift * bcd - blift * cda);\n}\n","import { orient2d } from 'robust-predicates';\n\nfunction pointInPolygon(p, polygon) {\n var i;\n var ii;\n var k = 0;\n var f;\n var u1;\n var v1;\n var u2;\n var v2;\n var currentP;\n var nextP;\n\n var x = p[0];\n var y = p[1];\n\n var numContours = polygon.length;\n for (i = 0; i < numContours; i++) {\n ii = 0;\n var contour = polygon[i];\n var contourLen = contour.length - 1;\n\n currentP = contour[0];\n if (currentP[0] !== contour[contourLen][0] &&\n currentP[1] !== contour[contourLen][1]) {\n throw new Error('First and last coordinates in a ring must be the same')\n }\n\n u1 = currentP[0] - x;\n v1 = currentP[1] - y;\n\n for (ii; ii < contourLen; ii++) {\n nextP = contour[ii + 1];\n\n u2 = nextP[0] - x;\n v2 = nextP[1] - y;\n\n if (v1 === 0 && v2 === 0) {\n if ((u2 <= 0 && u1 >= 0) || (u1 <= 0 && u2 >= 0)) { return 0 }\n } else if ((v2 >= 0 && v1 <= 0) || (v2 <= 0 && v1 >= 0)) {\n f = orient2d(u1, u2, v1, v2, 0, 0);\n if (f === 0) { return 0 }\n if ((f > 0 && v2 > 0 && v1 <= 0) || (f < 0 && v2 <= 0 && v1 > 0)) { k++; }\n }\n currentP = nextP;\n v1 = v2;\n u1 = u2;\n }\n }\n\n if (k % 2 === 0) { return false }\n return true\n}\n\nexport { pointInPolygon as default };\n","// index.ts\nimport pip from \"point-in-polygon-hao\";\nimport { getCoord, getGeom } from \"@turf/invariant\";\nfunction booleanPointInPolygon(point, polygon, options = {}) {\n if (!point) {\n throw new Error(\"point is required\");\n }\n if (!polygon) {\n throw new Error(\"polygon is required\");\n }\n const pt = getCoord(point);\n const geom = getGeom(polygon);\n const type = geom.type;\n const bbox = polygon.bbox;\n let polys = geom.coordinates;\n if (bbox && inBBox(pt, bbox) === false) {\n return false;\n }\n if (type === \"Polygon\") {\n polys = [polys];\n }\n let result = false;\n for (var i = 0; i < polys.length; ++i) {\n const polyResult = pip(pt, polys[i]);\n if (polyResult === 0) return options.ignoreBoundary ? false : true;\n else if (polyResult) result = true;\n }\n return result;\n}\nfunction inBBox(pt, bbox) {\n return bbox[0] <= pt[0] && bbox[1] <= pt[1] && bbox[2] >= pt[0] && bbox[3] >= pt[1];\n}\nvar index_default = booleanPointInPolygon;\nexport {\n booleanPointInPolygon,\n index_default as default\n};\n//# sourceMappingURL=index.js.map","class TinyQueue {\n constructor(data = [], compare = defaultCompare) {\n this.data = data;\n this.length = this.data.length;\n this.compare = compare;\n\n if (this.length > 0) {\n for (let i = (this.length >> 1) - 1; i >= 0; i--) this._down(i);\n }\n }\n\n push(item) {\n this.data.push(item);\n this.length++;\n this._up(this.length - 1);\n }\n\n pop() {\n if (this.length === 0) return undefined;\n\n const top = this.data[0];\n const bottom = this.data.pop();\n this.length--;\n\n if (this.length > 0) {\n this.data[0] = bottom;\n this._down(0);\n }\n\n return top;\n }\n\n peek() {\n return this.data[0];\n }\n\n _up(pos) {\n const {data, compare} = this;\n const item = data[pos];\n\n while (pos > 0) {\n const parent = (pos - 1) >> 1;\n const current = data[parent];\n if (compare(item, current) >= 0) break;\n data[pos] = current;\n pos = parent;\n }\n\n data[pos] = item;\n }\n\n _down(pos) {\n const {data, compare} = this;\n const halfLength = this.length >> 1;\n const item = data[pos];\n\n while (pos < halfLength) {\n let left = (pos << 1) + 1;\n let best = data[left];\n const right = left + 1;\n\n if (right < this.length && compare(data[right], best) < 0) {\n left = right;\n best = data[right];\n }\n if (compare(best, item) >= 0) break;\n\n data[pos] = best;\n pos = left;\n }\n\n data[pos] = item;\n }\n}\n\nfunction defaultCompare(a, b) {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\nfunction checkWhichEventIsLeft (e1, e2) {\n if (e1.p.x > e2.p.x) return 1\n if (e1.p.x < e2.p.x) return -1\n\n if (e1.p.y !== e2.p.y) return e1.p.y > e2.p.y ? 1 : -1\n return 1\n}\n\nfunction checkWhichSegmentHasRightEndpointFirst (seg1, seg2) {\n if (seg1.rightSweepEvent.p.x > seg2.rightSweepEvent.p.x) return 1\n if (seg1.rightSweepEvent.p.x < seg2.rightSweepEvent.p.x) return -1\n\n if (seg1.rightSweepEvent.p.y !== seg2.rightSweepEvent.p.y) return seg1.rightSweepEvent.p.y < seg2.rightSweepEvent.p.y ? 1 : -1\n return 1\n}\n\nclass Event {\n\n constructor (p, featureId, ringId, eventId) {\n this.p = {\n x: p[0],\n y: p[1]\n };\n this.featureId = featureId;\n this.ringId = ringId;\n this.eventId = eventId;\n\n this.otherEvent = null;\n this.isLeftEndpoint = null;\n }\n\n isSamePoint (eventToCheck) {\n return this.p.x === eventToCheck.p.x && this.p.y === eventToCheck.p.y\n }\n}\n\nfunction fillEventQueue (geojson, eventQueue) {\n if (geojson.type === 'FeatureCollection') {\n const features = geojson.features;\n for (let i = 0; i < features.length; i++) {\n processFeature(features[i], eventQueue);\n }\n } else {\n processFeature(geojson, eventQueue);\n }\n}\n\nlet featureId = 0;\nlet ringId = 0;\nlet eventId = 0;\nfunction processFeature (featureOrGeometry, eventQueue) {\n const geom = featureOrGeometry.type === 'Feature' ? featureOrGeometry.geometry : featureOrGeometry;\n let coords = geom.coordinates;\n // standardise the input\n if (geom.type === 'Polygon' || geom.type === 'MultiLineString') coords = [coords];\n if (geom.type === 'LineString') coords = [[coords]];\n\n for (let i = 0; i < coords.length; i++) {\n for (let ii = 0; ii < coords[i].length; ii++) {\n let currentP = coords[i][ii][0];\n let nextP = null;\n ringId = ringId + 1;\n for (let iii = 0; iii < coords[i][ii].length - 1; iii++) {\n nextP = coords[i][ii][iii + 1];\n\n const e1 = new Event(currentP, featureId, ringId, eventId);\n const e2 = new Event(nextP, featureId, ringId, eventId + 1);\n\n e1.otherEvent = e2;\n e2.otherEvent = e1;\n\n if (checkWhichEventIsLeft(e1, e2) > 0) {\n e2.isLeftEndpoint = true;\n e1.isLeftEndpoint = false;\n } else {\n e1.isLeftEndpoint = true;\n e2.isLeftEndpoint = false;\n }\n eventQueue.push(e1);\n eventQueue.push(e2);\n\n currentP = nextP;\n eventId = eventId + 1;\n }\n }\n }\n featureId = featureId + 1;\n}\n\nclass Segment {\n\n constructor (event) {\n this.leftSweepEvent = event;\n this.rightSweepEvent = event.otherEvent;\n }\n}\n\nfunction testSegmentIntersect (seg1, seg2) {\n if (seg1 === null || seg2 === null) return false\n\n if (seg1.leftSweepEvent.ringId === seg2.leftSweepEvent.ringId &&\n (seg1.rightSweepEvent.isSamePoint(seg2.leftSweepEvent) ||\n seg1.rightSweepEvent.isSamePoint(seg2.leftSweepEvent) ||\n seg1.rightSweepEvent.isSamePoint(seg2.rightSweepEvent) ||\n seg1.leftSweepEvent.isSamePoint(seg2.leftSweepEvent) ||\n seg1.leftSweepEvent.isSamePoint(seg2.rightSweepEvent))) return false\n\n const x1 = seg1.leftSweepEvent.p.x;\n const y1 = seg1.leftSweepEvent.p.y;\n const x2 = seg1.rightSweepEvent.p.x;\n const y2 = seg1.rightSweepEvent.p.y;\n const x3 = seg2.leftSweepEvent.p.x;\n const y3 = seg2.leftSweepEvent.p.y;\n const x4 = seg2.rightSweepEvent.p.x;\n const y4 = seg2.rightSweepEvent.p.y;\n\n const denom = ((y4 - y3) * (x2 - x1)) - ((x4 - x3) * (y2 - y1));\n const numeA = ((x4 - x3) * (y1 - y3)) - ((y4 - y3) * (x1 - x3));\n const numeB = ((x2 - x1) * (y1 - y3)) - ((y2 - y1) * (x1 - x3));\n\n if (denom === 0) {\n if (numeA === 0 && numeB === 0) return false\n return false\n }\n\n const uA = numeA / denom;\n const uB = numeB / denom;\n\n if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {\n const x = x1 + (uA * (x2 - x1));\n const y = y1 + (uA * (y2 - y1));\n return [x, y]\n }\n return false\n}\n\n// import {debugEventAndSegments, debugRemovingSegment} from './debug'\n\nfunction runCheck (eventQueue, ignoreSelfIntersections) {\n ignoreSelfIntersections = ignoreSelfIntersections ? ignoreSelfIntersections : false;\n\n const intersectionPoints = [];\n const outQueue = new TinyQueue([], checkWhichSegmentHasRightEndpointFirst);\n\n while (eventQueue.length) {\n const event = eventQueue.pop();\n if (event.isLeftEndpoint) {\n // debugEventAndSegments(event.p, outQueue.data)\n const segment = new Segment(event);\n for (let i = 0; i < outQueue.data.length; i++) {\n const otherSeg = outQueue.data[i];\n if (ignoreSelfIntersections) {\n if (otherSeg.leftSweepEvent.featureId === event.featureId) continue\n }\n const intersection = testSegmentIntersect(segment, otherSeg);\n if (intersection !== false) intersectionPoints.push(intersection);\n }\n outQueue.push(segment);\n } else if (event.isLeftEndpoint === false) {\n outQueue.pop();\n // const seg = outQueue.pop()\n // debugRemovingSegment(event.p, seg)\n }\n }\n return intersectionPoints\n}\n\nfunction sweeplineIntersections (geojson, ignoreSelfIntersections) {\n const eventQueue = new TinyQueue([], checkWhichEventIsLeft);\n fillEventQueue(geojson, eventQueue);\n return runCheck(eventQueue, ignoreSelfIntersections)\n}\n\nexport default sweeplineIntersections;\n","// index.ts\nimport { feature, featureCollection, point } from \"@turf/helpers\";\n\n// lib/sweepline-intersections-export.ts\nimport lib from \"sweepline-intersections\";\nvar sweeplineIntersections = lib;\n\n// index.ts\nfunction lineIntersect(line1, line2, options = {}) {\n const { removeDuplicates = true, ignoreSelfIntersections = true } = options;\n let features = [];\n if (line1.type === \"FeatureCollection\")\n features = features.concat(line1.features);\n else if (line1.type === \"Feature\") features.push(line1);\n else if (line1.type === \"LineString\" || line1.type === \"Polygon\" || line1.type === \"MultiLineString\" || line1.type === \"MultiPolygon\") {\n features.push(feature(line1));\n }\n if (line2.type === \"FeatureCollection\")\n features = features.concat(line2.features);\n else if (line2.type === \"Feature\") features.push(line2);\n else if (line2.type === \"LineString\" || line2.type === \"Polygon\" || line2.type === \"MultiLineString\" || line2.type === \"MultiPolygon\") {\n features.push(feature(line2));\n }\n const intersections = sweeplineIntersections(\n featureCollection(features),\n ignoreSelfIntersections\n );\n let results = [];\n if (removeDuplicates) {\n const unique = {};\n intersections.forEach((intersection) => {\n const key = intersection.join(\",\");\n if (!unique[key]) {\n unique[key] = true;\n results.push(intersection);\n }\n });\n } else {\n results = intersections;\n }\n return featureCollection(results.map((r) => point(r)));\n}\nvar index_default = lineIntersect;\nexport {\n index_default as default,\n lineIntersect\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { featureCollection, lineString, multiLineString } from \"@turf/helpers\";\nimport { getGeom } from \"@turf/invariant\";\nfunction polygonToLine(poly, options = {}) {\n const geom = getGeom(poly);\n if (!options.properties && poly.type === \"Feature\") {\n options.properties = poly.properties;\n }\n switch (geom.type) {\n case \"Polygon\":\n return singlePolygonToLine(geom, options);\n case \"MultiPolygon\":\n return multiPolygonToLine(geom, options);\n default:\n throw new Error(\"invalid poly\");\n }\n}\nfunction singlePolygonToLine(poly, options = {}) {\n const geom = getGeom(poly);\n const coords = geom.coordinates;\n const properties = options.properties ? options.properties : poly.type === \"Feature\" ? poly.properties : {};\n return coordsToLine(coords, properties);\n}\nfunction multiPolygonToLine(multiPoly, options = {}) {\n const geom = getGeom(multiPoly);\n const coords = geom.coordinates;\n const properties = options.properties ? options.properties : multiPoly.type === \"Feature\" ? multiPoly.properties : {};\n const lines = [];\n coords.forEach((coord) => {\n lines.push(coordsToLine(coord, properties));\n });\n return featureCollection(lines);\n}\nfunction coordsToLine(coords, properties) {\n if (coords.length > 1) {\n return multiLineString(coords, properties);\n }\n return lineString(coords[0], properties);\n}\nvar index_default = polygonToLine;\nexport {\n coordsToLine,\n index_default as default,\n multiPolygonToLine,\n polygonToLine,\n singlePolygonToLine\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { booleanPointInPolygon } from \"@turf/boolean-point-in-polygon\";\nimport { lineIntersect } from \"@turf/line-intersect\";\nimport { flattenEach } from \"@turf/meta\";\nimport { polygonToLine } from \"@turf/polygon-to-line\";\nfunction booleanDisjoint(feature1, feature2, {\n ignoreSelfIntersections = true\n} = { ignoreSelfIntersections: true }) {\n let bool = true;\n flattenEach(feature1, (flatten1) => {\n flattenEach(feature2, (flatten2) => {\n if (bool === false) {\n return false;\n }\n bool = disjoint(\n flatten1.geometry,\n flatten2.geometry,\n ignoreSelfIntersections\n );\n });\n });\n return bool;\n}\nfunction disjoint(geom1, geom2, ignoreSelfIntersections) {\n switch (geom1.type) {\n case \"Point\":\n switch (geom2.type) {\n case \"Point\":\n return !compareCoords(geom1.coordinates, geom2.coordinates);\n case \"LineString\":\n return !isPointOnLine(geom2, geom1);\n case \"Polygon\":\n return !booleanPointInPolygon(geom1, geom2);\n }\n break;\n case \"LineString\":\n switch (geom2.type) {\n case \"Point\":\n return !isPointOnLine(geom1, geom2);\n case \"LineString\":\n return !isLineOnLine(geom1, geom2, ignoreSelfIntersections);\n case \"Polygon\":\n return !isLineInPoly(geom2, geom1, ignoreSelfIntersections);\n }\n break;\n case \"Polygon\":\n switch (geom2.type) {\n case \"Point\":\n return !booleanPointInPolygon(geom2, geom1);\n case \"LineString\":\n return !isLineInPoly(geom1, geom2, ignoreSelfIntersections);\n case \"Polygon\":\n return !isPolyInPoly(geom2, geom1, ignoreSelfIntersections);\n }\n }\n return false;\n}\nfunction isPointOnLine(lineString, pt) {\n for (let i = 0; i < lineString.coordinates.length - 1; i++) {\n if (isPointOnLineSegment(\n lineString.coordinates[i],\n lineString.coordinates[i + 1],\n pt.coordinates\n )) {\n return true;\n }\n }\n return false;\n}\nfunction isLineOnLine(lineString1, lineString2, ignoreSelfIntersections) {\n const doLinesIntersect = lineIntersect(lineString1, lineString2, {\n ignoreSelfIntersections\n });\n if (doLinesIntersect.features.length > 0) {\n return true;\n }\n return false;\n}\nfunction isLineInPoly(polygon, lineString, ignoreSelfIntersections) {\n for (const coord of lineString.coordinates) {\n if (booleanPointInPolygon(coord, polygon)) {\n return true;\n }\n }\n const doLinesIntersect = lineIntersect(lineString, polygonToLine(polygon), {\n ignoreSelfIntersections\n });\n if (doLinesIntersect.features.length > 0) {\n return true;\n }\n return false;\n}\nfunction isPolyInPoly(feature1, feature2, ignoreSelfIntersections) {\n for (const coord1 of feature1.coordinates[0]) {\n if (booleanPointInPolygon(coord1, feature2)) {\n return true;\n }\n }\n for (const coord2 of feature2.coordinates[0]) {\n if (booleanPointInPolygon(coord2, feature1)) {\n return true;\n }\n }\n const doLinesIntersect = lineIntersect(\n polygonToLine(feature1),\n polygonToLine(feature2),\n { ignoreSelfIntersections }\n );\n if (doLinesIntersect.features.length > 0) {\n return true;\n }\n return false;\n}\nfunction isPointOnLineSegment(lineSegmentStart, lineSegmentEnd, pt) {\n const dxc = pt[0] - lineSegmentStart[0];\n const dyc = pt[1] - lineSegmentStart[1];\n const dxl = lineSegmentEnd[0] - lineSegmentStart[0];\n const dyl = lineSegmentEnd[1] - lineSegmentStart[1];\n const cross = dxc * dyl - dyc * dxl;\n if (cross !== 0) {\n return false;\n }\n if (Math.abs(dxl) >= Math.abs(dyl)) {\n if (dxl > 0) {\n return lineSegmentStart[0] <= pt[0] && pt[0] <= lineSegmentEnd[0];\n } else {\n return lineSegmentEnd[0] <= pt[0] && pt[0] <= lineSegmentStart[0];\n }\n } else if (dyl > 0) {\n return lineSegmentStart[1] <= pt[1] && pt[1] <= lineSegmentEnd[1];\n } else {\n return lineSegmentEnd[1] <= pt[1] && pt[1] <= lineSegmentStart[1];\n }\n}\nfunction compareCoords(pair1, pair2) {\n return pair1[0] === pair2[0] && pair1[1] === pair2[1];\n}\nvar index_default = booleanDisjoint;\nexport {\n booleanDisjoint,\n index_default as default\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { booleanDisjoint } from \"@turf/boolean-disjoint\";\nimport { flattenEach } from \"@turf/meta\";\nfunction booleanIntersects(feature1, feature2, {\n ignoreSelfIntersections = true\n} = {}) {\n let bool = false;\n flattenEach(feature1, (flatten1) => {\n flattenEach(feature2, (flatten2) => {\n if (bool === true) {\n return true;\n }\n bool = !booleanDisjoint(flatten1.geometry, flatten2.geometry, {\n ignoreSelfIntersections\n });\n });\n });\n return bool;\n}\nvar index_default = booleanIntersects;\nexport {\n booleanIntersects,\n index_default as default\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { bbox } from \"@turf/bbox\";\nimport { bboxPolygon } from \"@turf/bbox-polygon\";\nfunction envelope(geojson) {\n return bboxPolygon(bbox(geojson));\n}\nvar index_default = envelope;\nexport {\n index_default as default,\n envelope\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { featureCollection } from \"@turf/helpers\";\n\n// lib/util.ts\nimport { booleanPointInPolygon } from \"@turf/boolean-point-in-polygon\";\nimport { point } from \"@turf/helpers\";\nfunction mathSign(x) {\n return (x > 0) - (x < 0) || +x;\n}\nfunction orientationIndex(p1, p2, q) {\n const dx1 = p2[0] - p1[0], dy1 = p2[1] - p1[1], dx2 = q[0] - p2[0], dy2 = q[1] - p2[1];\n return mathSign(dx1 * dy2 - dx2 * dy1);\n}\nfunction envelopeIsEqual(env1, env2) {\n const envX1 = env1.geometry.coordinates[0].map((c) => c[0]), envY1 = env1.geometry.coordinates[0].map((c) => c[1]), envX2 = env2.geometry.coordinates[0].map((c) => c[0]), envY2 = env2.geometry.coordinates[0].map((c) => c[1]);\n return Math.max.apply(null, envX1) === Math.max.apply(null, envX2) && Math.max.apply(null, envY1) === Math.max.apply(null, envY2) && Math.min.apply(null, envX1) === Math.min.apply(null, envX2) && Math.min.apply(null, envY1) === Math.min.apply(null, envY2);\n}\nfunction envelopeContains(self, env) {\n return env.geometry.coordinates[0].every(\n (c) => booleanPointInPolygon(point(c), self)\n );\n}\nfunction coordinatesEqual(coord1, coord2) {\n return coord1[0] === coord2[0] && coord1[1] === coord2[1];\n}\n\n// lib/Node.ts\nvar Node = class _Node {\n static buildId(coordinates) {\n return coordinates.join(\",\");\n }\n constructor(coordinates) {\n this.id = _Node.buildId(coordinates);\n this.coordinates = coordinates;\n this.innerEdges = [];\n this.outerEdges = [];\n this.outerEdgesSorted = false;\n }\n removeInnerEdge(edge) {\n this.innerEdges = this.innerEdges.filter((e) => e.from.id !== edge.from.id);\n }\n removeOuterEdge(edge) {\n this.outerEdges = this.outerEdges.filter((e) => e.to.id !== edge.to.id);\n }\n /**\n * Outer edges are stored CCW order.\n *\n * @memberof Node\n * @param {Edge} edge - Edge to add as an outerEdge.\n */\n addOuterEdge(edge) {\n this.outerEdges.push(edge);\n this.outerEdgesSorted = false;\n }\n /**\n * Sorts outer edges in CCW way.\n *\n * @memberof Node\n * @private\n */\n sortOuterEdges() {\n if (!this.outerEdgesSorted) {\n this.outerEdges.sort((a, b) => {\n const aNode = a.to, bNode = b.to;\n if (aNode.coordinates[0] - this.coordinates[0] >= 0 && bNode.coordinates[0] - this.coordinates[0] < 0)\n return 1;\n if (aNode.coordinates[0] - this.coordinates[0] < 0 && bNode.coordinates[0] - this.coordinates[0] >= 0)\n return -1;\n if (aNode.coordinates[0] - this.coordinates[0] === 0 && bNode.coordinates[0] - this.coordinates[0] === 0) {\n if (aNode.coordinates[1] - this.coordinates[1] >= 0 || bNode.coordinates[1] - this.coordinates[1] >= 0)\n return aNode.coordinates[1] - bNode.coordinates[1];\n return bNode.coordinates[1] - aNode.coordinates[1];\n }\n const det = orientationIndex(\n this.coordinates,\n aNode.coordinates,\n bNode.coordinates\n );\n if (det < 0) return 1;\n if (det > 0) return -1;\n const d1 = Math.pow(aNode.coordinates[0] - this.coordinates[0], 2) + Math.pow(aNode.coordinates[1] - this.coordinates[1], 2), d2 = Math.pow(bNode.coordinates[0] - this.coordinates[0], 2) + Math.pow(bNode.coordinates[1] - this.coordinates[1], 2);\n return d1 - d2;\n });\n this.outerEdgesSorted = true;\n }\n }\n /**\n * Retrieves outer edges.\n *\n * They are sorted if they aren't in the CCW order.\n *\n * @memberof Node\n * @returns {Edge[]} - List of outer edges sorted in a CCW order.\n */\n getOuterEdges() {\n this.sortOuterEdges();\n return this.outerEdges;\n }\n getOuterEdge(i) {\n this.sortOuterEdges();\n return this.outerEdges[i];\n }\n addInnerEdge(edge) {\n this.innerEdges.push(edge);\n }\n};\n\n// lib/Edge.ts\nimport { lineString } from \"@turf/helpers\";\nvar Edge = class _Edge {\n /**\n * Creates or get the symetric Edge.\n *\n * @returns {Edge} - Symetric Edge.\n */\n getSymetric() {\n if (!this.symetric) {\n this.symetric = new _Edge(this.to, this.from);\n this.symetric.symetric = this;\n }\n return this.symetric;\n }\n /**\n * @param {Node} from - start node of the Edge\n * @param {Node} to - end node of the edge\n */\n constructor(from, to) {\n this.from = from;\n this.to = to;\n this.next = void 0;\n this.label = void 0;\n this.symetric = void 0;\n this.ring = void 0;\n this.from.addOuterEdge(this);\n this.to.addInnerEdge(this);\n }\n /**\n * Removes edge from from and to nodes.\n */\n deleteEdge() {\n this.from.removeOuterEdge(this);\n this.to.removeInnerEdge(this);\n }\n /**\n * Compares Edge equallity.\n *\n * An edge is equal to another, if the from and to nodes are the same.\n *\n * @param {Edge} edge - Another Edge\n * @returns {boolean} - True if Edges are equal, False otherwise\n */\n isEqual(edge) {\n return this.from.id === edge.from.id && this.to.id === edge.to.id;\n }\n toString() {\n return `Edge { ${this.from.id} -> ${this.to.id} }`;\n }\n /**\n * Returns a LineString representation of the Edge\n *\n * @returns {Feature<LineString>} - LineString representation of the Edge\n */\n toLineString() {\n return lineString([this.from.coordinates, this.to.coordinates]);\n }\n /**\n * Comparator of two edges.\n *\n * Implementation of geos::planargraph::DirectedEdge::compareTo.\n *\n * @param {Edge} edge - Another edge to compare with this one\n * @returns {number} -1 if this Edge has a greater angle with the positive x-axis than b,\n * 0 if the Edges are colinear,\n * 1 otherwise\n */\n compareTo(edge) {\n return orientationIndex(\n edge.from.coordinates,\n edge.to.coordinates,\n this.to.coordinates\n );\n }\n};\n\n// lib/EdgeRing.ts\nimport { multiPoint, polygon, point as point2 } from \"@turf/helpers\";\nimport { envelope } from \"@turf/envelope\";\nimport { booleanPointInPolygon as booleanPointInPolygon2 } from \"@turf/boolean-point-in-polygon\";\nvar EdgeRing = class {\n constructor() {\n this.edges = [];\n this.polygon = void 0;\n this.envelope = void 0;\n }\n /**\n * Add an edge to the ring, inserting it in the last position.\n *\n * @memberof EdgeRing\n * @param {Edge} edge - Edge to be inserted\n */\n push(edge) {\n this.edges.push(edge);\n this.polygon = this.envelope = void 0;\n }\n /**\n * Get Edge.\n *\n * @memberof EdgeRing\n * @param {number} i - Index\n * @returns {Edge} - Edge in the i position\n */\n get(i) {\n return this.edges[i];\n }\n /**\n * Getter of length property.\n *\n * @memberof EdgeRing\n * @returns {number} - Length of the edge ring.\n */\n get length() {\n return this.edges.length;\n }\n /**\n * Similar to Array.prototype.forEach for the list of Edges in the EdgeRing.\n *\n * @memberof EdgeRing\n * @param {Function} f - The same function to be passed to Array.prototype.forEach\n */\n forEach(f) {\n this.edges.forEach(f);\n }\n /**\n * Similar to Array.prototype.map for the list of Edges in the EdgeRing.\n *\n * @memberof EdgeRing\n * @param {Function} f - The same function to be passed to Array.prototype.map\n * @returns {Array} - The mapped values in the function\n */\n map(f) {\n return this.edges.map(f);\n }\n /**\n * Similar to Array.prototype.some for the list of Edges in the EdgeRing.\n *\n * @memberof EdgeRing\n * @param {Function} f - The same function to be passed to Array.prototype.some\n * @returns {boolean} - True if an Edge check the condition\n */\n some(f) {\n return this.edges.some(f);\n }\n /**\n * Check if the ring is valid in geomtry terms.\n *\n * A ring must have either 0 or 4 or more points. The first and the last must be\n * equal (in 2D)\n * geos::geom::LinearRing::validateConstruction\n *\n * @memberof EdgeRing\n * @returns {boolean} - Validity of the EdgeRing\n */\n isValid() {\n return true;\n }\n /**\n * Tests whether this ring is a hole.\n *\n * A ring is a hole if it is oriented counter-clockwise.\n * Similar implementation of geos::algorithm::CGAlgorithms::isCCW\n *\n * @memberof EdgeRing\n * @returns {boolean} - true: if it is a hole\n */\n isHole() {\n const hiIndex = this.edges.reduce((high, edge, i) => {\n if (edge.from.coordinates[1] > this.edges[high].from.coordinates[1])\n high = i;\n return high;\n }, 0), iPrev = (hiIndex === 0 ? this.length : hiIndex) - 1, iNext = (hiIndex + 1) % this.length, disc = orientationIndex(\n this.edges[iPrev].from.coordinates,\n this.edges[hiIndex].from.coordinates,\n this.edges[iNext].from.coordinates\n );\n if (disc === 0)\n return this.edges[iPrev].from.coordinates[0] > this.edges[iNext].from.coordinates[0];\n return disc > 0;\n }\n /**\n * Creates a MultiPoint representing the EdgeRing (discarts edges directions).\n *\n * @memberof EdgeRing\n * @returns {Feature<MultiPoint>} - Multipoint representation of the EdgeRing\n */\n toMultiPoint() {\n return multiPoint(this.edges.map((edge) => edge.from.coordinates));\n }\n /**\n * Creates a Polygon representing the EdgeRing.\n *\n * @memberof EdgeRing\n * @returns {Feature<Polygon>} - Polygon representation of the Edge Ring\n */\n toPolygon() {\n if (this.polygon) return this.polygon;\n const coordinates = this.edges.map((edge) => edge.from.coordinates);\n coordinates.push(this.edges[0].from.coordinates);\n return this.polygon = polygon([coordinates]);\n }\n /**\n * Calculates the envelope of the EdgeRing.\n *\n * @memberof EdgeRing\n * @returns {Feature<Polygon>} - envelope\n */\n getEnvelope() {\n if (this.envelope) return this.envelope;\n return this.envelope = envelope(this.toPolygon());\n }\n /**\n * `geos::operation::polygonize::EdgeRing::findEdgeRingContaining`\n *\n * @param {EdgeRing} testEdgeRing - EdgeRing to look in the list\n * @param {EdgeRing[]} shellList - List of EdgeRing in which to search\n *\n * @returns {EdgeRing} - EdgeRing which contains the testEdgeRing\n */\n static findEdgeRingContaining(testEdgeRing, shellList) {\n const testEnvelope = testEdgeRing.getEnvelope();\n let minEnvelope, minShell;\n shellList.forEach((shell) => {\n const tryEnvelope = shell.getEnvelope();\n if (minShell) minEnvelope = minShell.getEnvelope();\n if (envelopeIsEqual(tryEnvelope, testEnvelope)) return;\n if (envelopeContains(tryEnvelope, testEnvelope)) {\n const testEdgeRingCoordinates = testEdgeRing.map(\n (edge) => edge.from.coordinates\n );\n let testPoint;\n for (const pt of testEdgeRingCoordinates) {\n if (!shell.some((edge) => coordinatesEqual(pt, edge.from.coordinates))) {\n testPoint = pt;\n }\n }\n if (testPoint && shell.inside(point2(testPoint))) {\n if (!minShell || envelopeContains(minEnvelope, tryEnvelope))\n minShell = shell;\n }\n }\n });\n return minShell;\n }\n /**\n * Checks if the point is inside the edgeRing\n *\n * @param {Feature<Point>} pt - Point to check if it is inside the edgeRing\n * @returns {boolean} - True if it is inside, False otherwise\n */\n inside(pt) {\n return booleanPointInPolygon2(pt, this.toPolygon());\n }\n};\n\n// lib/Graph.ts\nimport { flattenEach, coordReduce } from \"@turf/meta\";\nimport { featureOf } from \"@turf/invariant\";\nfunction validateGeoJson(geoJson) {\n if (!geoJson) throw new Error(\"No geojson passed\");\n if (geoJson.type !== \"FeatureCollection\" && geoJson.type !== \"GeometryCollection\" && geoJson.type !== \"MultiLineString\" && geoJson.type !== \"LineString\" && geoJson.type !== \"Feature\")\n throw new Error(\n `Invalid input type '${geoJson.type}'. Geojson must be FeatureCollection, GeometryCollection, LineString, MultiLineString or Feature`\n );\n}\nvar Graph = class _Graph {\n /**\n * Creates a graph from a GeoJSON.\n *\n * @param {FeatureCollection<LineString>} geoJson - it must comply with the restrictions detailed in the index\n * @returns {Graph} - The newly created graph\n * @throws {Error} if geoJson is invalid.\n */\n static fromGeoJson(geoJson) {\n validateGeoJson(geoJson);\n const graph = new _Graph();\n flattenEach(geoJson, (feature) => {\n featureOf(feature, \"LineString\", \"Graph::fromGeoJson\");\n coordReduce(feature, (prev, cur) => {\n if (prev) {\n const start = graph.getNode(prev), end = graph.getNode(cur);\n graph.addEdge(start, end);\n }\n return cur;\n });\n });\n return graph;\n }\n /**\n * Creates or get a Node.\n *\n * @param {number[]} coordinates - Coordinates of the node\n * @returns {Node} - The created or stored node\n */\n getNode(coordinates) {\n const id = Node.buildId(coordinates);\n let node = this.nodes[id];\n if (!node) node = this.nodes[id] = new Node(coordinates);\n return node;\n }\n /**\n * Adds an Edge and its symetricall.\n *\n * Edges are added symetrically, i.e.: we also add its symetric\n *\n * @param {Node} from - Node which starts the Edge\n * @param {Node} to - Node which ends the Edge\n */\n addEdge(from, to) {\n const edge = new Edge(from, to), symetricEdge = edge.getSymetric();\n this.edges.push(edge);\n this.edges.push(symetricEdge);\n }\n constructor() {\n this.edges = [];\n this.nodes = {};\n }\n /**\n * Removes Dangle Nodes (nodes with grade 1).\n */\n deleteDangles() {\n Object.keys(this.nodes).map((id) => this.nodes[id]).forEach((node) => this._removeIfDangle(node));\n }\n /**\n * Check if node is dangle, if so, remove it.\n *\n * It calls itself recursively, removing a dangling node might cause another dangling node\n *\n * @param {Node} node - Node to check if it's a dangle\n */\n _removeIfDangle(node) {\n if (node.innerEdges.length <= 1) {\n const outerNodes = node.getOuterEdges().map((e) => e.to);\n this.removeNode(node);\n outerNodes.forEach((n) => this._removeIfDangle(n));\n }\n }\n /**\n * Delete cut-edges (bridge edges).\n *\n * The graph will be traversed, all the edges will be labeled according the ring\n * in which they are. (The label is a number incremented by 1). Edges with the same\n * label are cut-edges.\n */\n deleteCutEdges() {\n this._computeNextCWEdges();\n this._findLabeledEdgeRings();\n this.edges.forEach((edge) => {\n if (edge.label === edge.symetric.label) {\n this.removeEdge(edge.symetric);\n this.removeEdge(edge);\n }\n });\n }\n /**\n * Set the `next` property of each Edge.\n *\n * The graph will be transversed in a CW form, so, we set the next of the symetrical edge as the previous one.\n * OuterEdges are sorted CCW.\n *\n * @param {Node} [node] - If no node is passed, the function calls itself for every node in the Graph\n */\n _computeNextCWEdges(node) {\n if (typeof node === \"undefined\") {\n Object.keys(this.nodes).forEach(\n (id) => this._computeNextCWEdges(this.nodes[id])\n );\n } else {\n node.getOuterEdges().forEach((edge, i) => {\n node.getOuterEdge(\n (i === 0 ? node.getOuterEdges().length : i) - 1\n ).symetric.next = edge;\n });\n }\n }\n /**\n * Computes the next edge pointers going CCW around the given node, for the given edgering label.\n *\n * This algorithm has the effect of converting maximal edgerings into minimal edgerings\n *\n * XXX: method literally transcribed from `geos::operation::polygonize::PolygonizeGraph::computeNextCCWEdges`,\n * could be written in a more javascript way.\n *\n * @param {Node} node - Node\n * @param {number} label - Ring's label\n */\n _computeNextCCWEdges(node, label) {\n const edges = node.getOuterEdges();\n let firstOutDE, prevInDE;\n for (let i = edges.length - 1; i >= 0; --i) {\n let de = edges[i], sym = de.symetric, outDE, inDE;\n if (de.label === label) outDE = de;\n if (sym.label === label) inDE = sym;\n if (!outDE || !inDE)\n continue;\n if (inDE) prevInDE = inDE;\n if (outDE) {\n if (prevInDE) {\n prevInDE.next = outDE;\n prevInDE = void 0;\n }\n if (!firstOutDE) firstOutDE = outDE;\n }\n }\n if (prevInDE) prevInDE.next = firstOutDE;\n }\n /**\n * Finds rings and labels edges according to which rings are.\n *\n * The label is a number which is increased for each ring.\n *\n * @returns {Edge[]} edges that start rings\n */\n _findLabeledEdgeRings() {\n const edgeRingStarts = [];\n let label = 0;\n this.edges.forEach((edge) => {\n if (edge.label >= 0) return;\n edgeRingStarts.push(edge);\n let e = edge;\n do {\n e.label = label;\n e = e.next;\n } while (!edge.isEqual(e));\n label++;\n });\n return edgeRingStarts;\n }\n /**\n * Computes the EdgeRings formed by the edges in this graph.\n *\n * @returns {EdgeRing[]} - A list of all the EdgeRings in the graph.\n */\n getEdgeRings() {\n this._computeNextCWEdges();\n this.edges.forEach((edge) => {\n edge.label = void 0;\n });\n this._findLabeledEdgeRings().forEach((edge) => {\n this._findIntersectionNodes(edge).forEach((node) => {\n this._computeNextCCWEdges(node, edge.label);\n });\n });\n const edgeRingList = [];\n this.edges.forEach((edge) => {\n if (edge.ring) return;\n edgeRingList.push(this._findEdgeRing(edge));\n });\n return edgeRingList;\n }\n /**\n * Find all nodes in a Maxima EdgeRing which are self-intersection nodes.\n *\n * @param {Node} startEdge - Start Edge of the Ring\n * @returns {Node[]} - intersection nodes\n */\n _findIntersectionNodes(startEdge) {\n const intersectionNodes = [];\n let edge = startEdge;\n do {\n let degree = 0;\n edge.from.getOuterEdges().forEach((e) => {\n if (e.label === startEdge.label) ++degree;\n });\n if (degree > 1) intersectionNodes.push(edge.from);\n edge = edge.next;\n } while (!startEdge.isEqual(edge));\n return intersectionNodes;\n }\n /**\n * Get the edge-ring which starts from the provided Edge.\n *\n * @param {Edge} startEdge - starting edge of the edge ring\n * @returns {EdgeRing} - EdgeRing which start Edge is the provided one.\n */\n _findEdgeRing(startEdge) {\n let edge = startEdge;\n const edgeRing = new EdgeRing();\n do {\n edgeRing.push(edge);\n edge.ring = edgeRing;\n edge = edge.next;\n } while (!startEdge.isEqual(edge));\n return edgeRing;\n }\n /**\n * Removes a node from the Graph.\n *\n * It also removes edges asociated to that node\n * @param {Node} node - Node to be removed\n */\n removeNode(node) {\n node.getOuterEdges().forEach((edge) => this.removeEdge(edge));\n node.innerEdges.forEach((edge) => this.removeEdge(edge));\n delete this.nodes[node.id];\n }\n /**\n * Remove edge from the graph and deletes the edge.\n *\n * @param {Edge} edge - Edge to be removed\n */\n removeEdge(edge) {\n this.edges = this.edges.filter((e) => !e.isEqual(edge));\n edge.deleteEdge();\n }\n};\n\n// index.ts\nfunction polygonize(geoJson) {\n const graph = Graph.fromGeoJson(geoJson);\n graph.deleteDangles();\n graph.deleteCutEdges();\n const holes = [], shells = [];\n graph.getEdgeRings().filter((edgeRing) => edgeRing.isValid()).forEach((edgeRing) => {\n if (edgeRing.isHole()) holes.push(edgeRing);\n else shells.push(edgeRing);\n });\n holes.forEach((hole) => {\n if (EdgeRing.findEdgeRingContaining(hole, shells)) shells.push(hole);\n });\n return featureCollection(shells.map((shell) => shell.toPolygon()));\n}\nvar index_default = polygonize;\nexport {\n index_default as default,\n polygonize\n};\n//# sourceMappingURL=index.js.map","\n/**\n * Rearranges items so that all items in the [left, k] are the smallest.\n * The k-th element will have the (k - left + 1)-th smallest value in [left, right].\n *\n * @template T\n * @param {T[]} arr the array to partially sort (in place)\n * @param {number} k middle index for partial sorting (as defined above)\n * @param {number} [left=0] left index of the range to sort\n * @param {number} [right=arr.length-1] right index\n * @param {(a: T, b: T) => number} [compare = (a, b) => a - b] compare function\n */\nexport default function quickselect(arr, k, left = 0, right = arr.length - 1, compare = defaultCompare) {\n\n while (right > left) {\n if (right - left > 600) {\n const n = right - left + 1;\n const m = k - left + 1;\n const z = Math.log(n);\n const s = 0.5 * Math.exp(2 * z / 3);\n const sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);\n const newLeft = Math.max(left, Math.floor(k - m * s / n + sd));\n const newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));\n quickselect(arr, k, newLeft, newRight, compare);\n }\n\n const t = arr[k];\n let i = left;\n /** @type {number} */\n let j = right;\n\n swap(arr, left, k);\n if (compare(arr[right], t) > 0) swap(arr, left, right);\n\n while (i < j) {\n swap(arr, i, j);\n i++;\n j--;\n while (compare(arr[i], t) < 0) i++;\n while (compare(arr[j], t) > 0) j--;\n }\n\n if (compare(arr[left], t) === 0) swap(arr, left, j);\n else {\n j++;\n swap(arr, j, right);\n }\n\n if (j <= k) left = j + 1;\n if (k <= j) right = j - 1;\n }\n}\n\n/**\n * @template T\n * @param {T[]} arr\n * @param {number} i\n * @param {number} j\n */\nfunction swap(arr, i, j) {\n const tmp = arr[i];\n arr[i] = arr[j];\n arr[j] = tmp;\n}\n\n/**\n * @template T\n * @param {T} a\n * @param {T} b\n * @returns {number}\n */\nfunction defaultCompare(a, b) {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n","import quickselect from 'quickselect';\n\nexport default class RBush {\n constructor(maxEntries = 9) {\n // max entries in a node is 9 by default; min node fill is 40% for best performance\n this._maxEntries = Math.max(4, maxEntries);\n this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));\n this.clear();\n }\n\n all() {\n return this._all(this.data, []);\n }\n\n search(bbox) {\n let node = this.data;\n const result = [];\n\n if (!intersects(bbox, node)) return result;\n\n const toBBox = this.toBBox;\n const nodesToSearch = [];\n\n while (node) {\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n const childBBox = node.leaf ? toBBox(child) : child;\n\n if (intersects(bbox, childBBox)) {\n if (node.leaf) result.push(child);\n else if (contains(bbox, childBBox)) this._all(child, result);\n else nodesToSearch.push(child);\n }\n }\n node = nodesToSearch.pop();\n }\n\n return result;\n }\n\n collides(bbox) {\n let node = this.data;\n\n if (!intersects(bbox, node)) return false;\n\n const nodesToSearch = [];\n while (node) {\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n const childBBox = node.leaf ? this.toBBox(child) : child;\n\n if (intersects(bbox, childBBox)) {\n if (node.leaf || contains(bbox, childBBox)) return true;\n nodesToSearch.push(child);\n }\n }\n node = nodesToSearch.pop();\n }\n\n return false;\n }\n\n load(data) {\n if (!(data && data.length)) return this;\n\n if (data.length < this._minEntries) {\n for (let i = 0; i < data.length; i++) {\n this.insert(data[i]);\n }\n return this;\n }\n\n // recursively build the tree with the given data from scratch using OMT algorithm\n let node = this._build(data.slice(), 0, data.length - 1, 0);\n\n if (!this.data.children.length) {\n // save as is if tree is empty\n this.data = node;\n\n } else if (this.data.height === node.height) {\n // split root if trees have the same height\n this._splitRoot(this.data, node);\n\n } else {\n if (this.data.height < node.height) {\n // swap trees if inserted one is bigger\n const tmpNode = this.data;\n this.data = node;\n node = tmpNode;\n }\n\n // insert the small tree into the large tree at appropriate level\n this._insert(node, this.data.height - node.height - 1, true);\n }\n\n return this;\n }\n\n insert(item) {\n if (item) this._insert(item, this.data.height - 1);\n return this;\n }\n\n clear() {\n this.data = createNode([]);\n return this;\n }\n\n remove(item, equalsFn) {\n if (!item) return this;\n\n let node = this.data;\n const bbox = this.toBBox(item);\n const path = [];\n const indexes = [];\n let i, parent, goingUp;\n\n // depth-first iterative tree traversal\n while (node || path.length) {\n\n if (!node) { // go up\n node = path.pop();\n parent = path[path.length - 1];\n i = indexes.pop();\n goingUp = true;\n }\n\n if (node.leaf) { // check current node\n const index = findItem(item, node.children, equalsFn);\n\n if (index !== -1) {\n // item found, remove the item and condense tree upwards\n node.children.splice(index, 1);\n path.push(node);\n this._condense(path);\n return this;\n }\n }\n\n if (!goingUp && !node.leaf && contains(node, bbox)) { // go down\n path.push(node);\n indexes.push(i);\n i = 0;\n parent = node;\n node = node.children[0];\n\n } else if (parent) { // go right\n i++;\n node = parent.children[i];\n goingUp = false;\n\n } else node = null; // nothing found\n }\n\n return this;\n }\n\n toBBox(item) { return item; }\n\n compareMinX(a, b) { return a.minX - b.minX; }\n compareMinY(a, b) { return a.minY - b.minY; }\n\n toJSON() { return this.data; }\n\n fromJSON(data) {\n this.data = data;\n return this;\n }\n\n _all(node, result) {\n const nodesToSearch = [];\n while (node) {\n if (node.leaf) result.push(...node.children);\n else nodesToSearch.push(...node.children);\n\n node = nodesToSearch.pop();\n }\n return result;\n }\n\n _build(items, left, right, height) {\n\n const N = right - left + 1;\n let M = this._maxEntries;\n let node;\n\n if (N <= M) {\n // reached leaf level; return leaf\n node = createNode(items.slice(left, right + 1));\n calcBBox(node, this.toBBox);\n return node;\n }\n\n if (!height) {\n // target height of the bulk-loaded tree\n height = Math.ceil(Math.log(N) / Math.log(M));\n\n // target number of root entries to maximize storage utilization\n M = Math.ceil(N / Math.pow(M, height - 1));\n }\n\n node = createNode([]);\n node.leaf = false;\n node.height = height;\n\n // split the items into M mostly square tiles\n\n const N2 = Math.ceil(N / M);\n const N1 = N2 * Math.ceil(Math.sqrt(M));\n\n multiSelect(items, left, right, N1, this.compareMinX);\n\n for (let i = left; i <= right; i += N1) {\n\n const right2 = Math.min(i + N1 - 1, right);\n\n multiSelect(items, i, right2, N2, this.compareMinY);\n\n for (let j = i; j <= right2; j += N2) {\n\n const right3 = Math.min(j + N2 - 1, right2);\n\n // pack each entry recursively\n node.children.push(this._build(items, j, right3, height - 1));\n }\n }\n\n calcBBox(node, this.toBBox);\n\n return node;\n }\n\n _chooseSubtree(bbox, node, level, path) {\n while (true) {\n path.push(node);\n\n if (node.leaf || path.length - 1 === level) break;\n\n let minArea = Infinity;\n let minEnlargement = Infinity;\n let targetNode;\n\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n const area = bboxArea(child);\n const enlargement = enlargedArea(bbox, child) - area;\n\n // choose entry with the least area enlargement\n if (enlargement < minEnlargement) {\n minEnlargement = enlargement;\n minArea = area < minArea ? area : minArea;\n targetNode = child;\n\n } else if (enlargement === minEnlargement) {\n // otherwise choose one with the smallest area\n if (area < minArea) {\n minArea = area;\n targetNode = child;\n }\n }\n }\n\n node = targetNode || node.children[0];\n }\n\n return node;\n }\n\n _insert(item, level, isNode) {\n const bbox = isNode ? item : this.toBBox(item);\n const insertPath = [];\n\n // find the best node for accommodating the item, saving all nodes along the path too\n const node = this._chooseSubtree(bbox, this.data, level, insertPath);\n\n // put the item into the node\n node.children.push(item);\n extend(node, bbox);\n\n // split on node overflow; propagate upwards if necessary\n while (level >= 0) {\n if (insertPath[level].children.length > this._maxEntries) {\n this._split(insertPath, level);\n level--;\n } else break;\n }\n\n // adjust bboxes along the insertion path\n this._adjustParentBBoxes(bbox, insertPath, level);\n }\n\n // split overflowed node into two\n _split(insertPath, level) {\n const node = insertPath[level];\n const M = node.children.length;\n const m = this._minEntries;\n\n this._chooseSplitAxis(node, m, M);\n\n const splitIndex = this._chooseSplitIndex(node, m, M);\n\n const newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));\n newNode.height = node.height;\n newNode.leaf = node.leaf;\n\n calcBBox(node, this.toBBox);\n calcBBox(newNode, this.toBBox);\n\n if (level) insertPath[level - 1].children.push(newNode);\n else this._splitRoot(node, newNode);\n }\n\n _splitRoot(node, newNode) {\n // split root node\n this.data = createNode([node, newNode]);\n this.data.height = node.height + 1;\n this.data.leaf = false;\n calcBBox(this.data, this.toBBox);\n }\n\n _chooseSplitIndex(node, m, M) {\n let index;\n let minOverlap = Infinity;\n let minArea = Infinity;\n\n for (let i = m; i <= M - m; i++) {\n const bbox1 = distBBox(node, 0, i, this.toBBox);\n const bbox2 = distBBox(node, i, M, this.toBBox);\n\n const overlap = intersectionArea(bbox1, bbox2);\n const area = bboxArea(bbox1) + bboxArea(bbox2);\n\n // choose distribution with minimum overlap\n if (overlap < minOverlap) {\n minOverlap = overlap;\n index = i;\n\n minArea = area < minArea ? area : minArea;\n\n } else if (overlap === minOverlap) {\n // otherwise choose distribution with minimum area\n if (area < minArea) {\n minArea = area;\n index = i;\n }\n }\n }\n\n return index || M - m;\n }\n\n // sorts node children by the best axis for split\n _chooseSplitAxis(node, m, M) {\n const compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;\n const compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;\n const xMargin = this._allDistMargin(node, m, M, compareMinX);\n const yMargin = this._allDistMargin(node, m, M, compareMinY);\n\n // if total distributions margin value is minimal for x, sort by minX,\n // otherwise it's already sorted by minY\n if (xMargin < yMargin) node.children.sort(compareMinX);\n }\n\n // total margin of all possible split distributions where each node is at least m full\n _allDistMargin(node, m, M, compare) {\n node.children.sort(compare);\n\n const toBBox = this.toBBox;\n const leftBBox = distBBox(node, 0, m, toBBox);\n const rightBBox = distBBox(node, M - m, M, toBBox);\n let margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);\n\n for (let i = m; i < M - m; i++) {\n const child = node.children[i];\n extend(leftBBox, node.leaf ? toBBox(child) : child);\n margin += bboxMargin(leftBBox);\n }\n\n for (let i = M - m - 1; i >= m; i--) {\n const child = node.children[i];\n extend(rightBBox, node.leaf ? toBBox(child) : child);\n margin += bboxMargin(rightBBox);\n }\n\n return margin;\n }\n\n _adjustParentBBoxes(bbox, path, level) {\n // adjust bboxes along the given tree path\n for (let i = level; i >= 0; i--) {\n extend(path[i], bbox);\n }\n }\n\n _condense(path) {\n // go through the path, removing empty nodes and updating bboxes\n for (let i = path.length - 1, siblings; i >= 0; i--) {\n if (path[i].children.length === 0) {\n if (i > 0) {\n siblings = path[i - 1].children;\n siblings.splice(siblings.indexOf(path[i]), 1);\n\n } else this.clear();\n\n } else calcBBox(path[i], this.toBBox);\n }\n }\n}\n\nfunction findItem(item, items, equalsFn) {\n if (!equalsFn) return items.indexOf(item);\n\n for (let i = 0; i < items.length; i++) {\n if (equalsFn(item, items[i])) return i;\n }\n return -1;\n}\n\n// calculate node's bbox from bboxes of its children\nfunction calcBBox(node, toBBox) {\n distBBox(node, 0, node.children.length, toBBox, node);\n}\n\n// min bounding rectangle of node children from k to p-1\nfunction distBBox(node, k, p, toBBox, destNode) {\n if (!destNode) destNode = createNode(null);\n destNode.minX = Infinity;\n destNode.minY = Infinity;\n destNode.maxX = -Infinity;\n destNode.maxY = -Infinity;\n\n for (let i = k; i < p; i++) {\n const child = node.children[i];\n extend(destNode, node.leaf ? toBBox(child) : child);\n }\n\n return destNode;\n}\n\nfunction extend(a, b) {\n a.minX = Math.min(a.minX, b.minX);\n a.minY = Math.min(a.minY, b.minY);\n a.maxX = Math.max(a.maxX, b.maxX);\n a.maxY = Math.max(a.maxY, b.maxY);\n return a;\n}\n\nfunction compareNodeMinX(a, b) { return a.minX - b.minX; }\nfunction compareNodeMinY(a, b) { return a.minY - b.minY; }\n\nfunction bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }\nfunction bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }\n\nfunction enlargedArea(a, b) {\n return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *\n (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));\n}\n\nfunction intersectionArea(a, b) {\n const minX = Math.max(a.minX, b.minX);\n const minY = Math.max(a.minY, b.minY);\n const maxX = Math.min(a.maxX, b.maxX);\n const maxY = Math.min(a.maxY, b.maxY);\n\n return Math.max(0, maxX - minX) *\n Math.max(0, maxY - minY);\n}\n\nfunction contains(a, b) {\n return a.minX <= b.minX &&\n a.minY <= b.minY &&\n b.maxX <= a.maxX &&\n b.maxY <= a.maxY;\n}\n\nfunction intersects(a, b) {\n return b.minX <= a.maxX &&\n b.minY <= a.maxY &&\n b.maxX >= a.minX &&\n b.maxY >= a.minY;\n}\n\nfunction createNode(children) {\n return {\n children,\n height: 1,\n leaf: true,\n minX: Infinity,\n minY: Infinity,\n maxX: -Infinity,\n maxY: -Infinity\n };\n}\n\n// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;\n// combines selection algorithm with binary divide & conquer approach\n\nfunction multiSelect(arr, left, right, n, compare) {\n const stack = [left, right];\n\n while (stack.length) {\n right = stack.pop();\n left = stack.pop();\n\n if (right - left <= n) continue;\n\n const mid = left + Math.ceil((right - left) / n / 2) * n;\n quickselect(arr, mid, left, right, compare);\n\n stack.push(left, mid, mid, right);\n }\n}\n","import { booleanIntersects, bbox as turfBbox } from '@turf/turf';\nimport RBush from 'rbush';\nimport { Geometry } from 'geojson';\n\n/**\n * Computes connected components (clusters) of intersecting geometries and returns\n * a mapping from feature id to cluster id. The input array must contain an\n * application-level identifier for each geometry. Cluster ids are stable only\n * within a single invocation and start at 0.\n */\nexport function computeIntersectingClusterIds(\n items: Array<{ id: number | string; geometry: Geometry | null | undefined }>,\n): Map<string, number> {\n const validItems = items.map((it, idx) => ({ ...it, __idx: idx })).filter((it) => it.geometry != null) as Array<{\n id: number | string;\n geometry: Geometry;\n __idx: number;\n }>;\n\n const n = validItems.length;\n if (n === 0) return new Map();\n\n // Union-find structure\n const parent = new Array(n).fill(0).map((_, i) => i);\n const find = (i: number): number => (parent[i] === i ? i : (parent[i] = find(parent[i])));\n const union = (a: number, b: number) => {\n const ra = find(a);\n const rb = find(b);\n if (ra !== rb) parent[rb] = ra;\n };\n\n // Build R-tree of bboxes\n interface RTreeItem {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n idx: number; // index within validItems\n }\n const rtree = new RBush<RTreeItem>();\n const itemsForTree: RTreeItem[] = new Array(n);\n for (let i = 0; i < n; i++) {\n const [minX, minY, maxX, maxY] = turfBbox(validItems[i].geometry as any);\n itemsForTree[i] = { minX, minY, maxX, maxY, idx: i };\n }\n rtree.load(itemsForTree);\n\n // Intersections among nearby candidates\n for (let i = 0; i < n; i++) {\n const aItem = itemsForTree[i];\n const candidates = rtree.search(aItem);\n for (const cand of candidates) {\n const j = cand.idx;\n if (j <= i) continue;\n try {\n if (booleanIntersects(validItems[i].geometry as any, validItems[j].geometry as any)) {\n union(i, j);\n }\n } catch {\n // ignore invalid geometries\n }\n }\n }\n\n // Assign compact cluster ids\n const rootToClusterId = new Map<number, number>();\n let nextClusterId = 0;\n const result = new Map<string, number>();\n for (let i = 0; i < n; i++) {\n const root = find(i);\n if (!rootToClusterId.has(root)) rootToClusterId.set(root, nextClusterId++);\n const clusterId = rootToClusterId.get(root)!;\n const appId = String(validItems[i].id);\n result.set(appId, clusterId);\n }\n\n return result;\n}\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { Column } from '../../../shared/interfaces';\nimport { computeIntersectingClusterIds } from '../../../shared/clusterIntersectingFeatures';\n\n/**\n * Assigns stable `building_id` values by clustering intersecting building geometries.\n */\nexport class AssignBuildingIdsUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n }\n\n /**\n * Reads geometries from the provided building table, computes intersecting\n * clusters in JS, writes a stable building_id per row back to the table, and\n * returns the updated column list for the table.\n */\n async exec(params: { tableName: string; workspace?: string }): Promise<Column[]> {\n const { tableName, workspace = 'main' } = params;\n const qualifiedTableName = `${workspace}.${tableName}`;\n\n // Read id and geometry as GeoJSON for JS processing\n const selectSql = `\n SELECT id, CAST(ST_AsGeoJSON(geometry) AS JSON) AS geometry_json\n FROM ${qualifiedTableName}\n `;\n const res = await this.conn.query(selectSql);\n const rows = res.toArray();\n\n const items = rows.map((r: any) => ({ id: r.id as number, geometry: JSON.parse(r.geometry_json) as any }));\n\n const idToCluster = computeIntersectingClusterIds(items);\n\n // Skip if nothing to assign\n if (idToCluster.size === 0) {\n return await this.describeColumns(qualifiedTableName);\n }\n\n // Ensure building_id column exists\n const hasBuildingId = await this.columnExists(qualifiedTableName, 'building_id');\n if (!hasBuildingId) {\n await this.conn.query(`ALTER TABLE ${qualifiedTableName} ADD COLUMN building_id BIGINT`);\n }\n\n // Bulk insert using an in-memory JSON file (same pattern as custom layer loader)\n const jsonRows = Array.from(idToCluster.entries()).map(([id, building_id]) => ({ id: Number(id), building_id }));\n const vfsPath = `tmp_building_ids_${Date.now()}_${Math.random().toString(36).slice(2, 10)}.json`;\n await this.db.registerFileText(vfsPath, JSON.stringify({ rows: jsonRows }));\n\n await this.conn.query(`CREATE TEMP TABLE __tmp_building_ids_json AS SELECT * FROM '${vfsPath}'`);\n await this.conn.query(`\n CREATE TEMP TABLE __tmp_building_ids AS\n SELECT CAST(row.id AS BIGINT) AS id, CAST(row.building_id AS BIGINT) AS building_id\n FROM (SELECT UNNEST(rows) AS row FROM __tmp_building_ids_json);\n `);\n\n // Update table by joining on id\n await this.conn.query(\n `UPDATE ${qualifiedTableName} AS t SET building_id = b.building_id FROM __tmp_building_ids AS b WHERE t.id = b.id`,\n );\n\n // Cleanup temp table\n await this.conn.query(`DROP TABLE __tmp_building_ids`);\n await this.conn.query(`DROP TABLE __tmp_building_ids_json`);\n await this.db.dropFile(vfsPath);\n\n return await this.describeColumns(qualifiedTableName);\n }\n\n private async columnExists(tableName: string, columnName: string): Promise<boolean> {\n const pragma = await this.conn.query(`PRAGMA table_info('${tableName}')`);\n const arr = pragma?.toArray?.() ?? [];\n return arr.some((r: any) => String(r.name) === columnName);\n }\n\n private async describeColumns(tableName: string): Promise<Column[]> {\n const describe = await this.conn.query(`DESCRIBE ${tableName}`);\n const rows = describe?.toArray?.() ?? [];\n return rows.map((r: any) => ({ name: r[0] ?? r.column_name ?? r.name, type: r[1] ?? r.column_type ?? r.type }));\n }\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nconst BATCH_SIZE = 100;\n\n/**\n * Aggregates building geometries by `building_id` into union geometries.\n */\nexport class AggregateBuildingLayerUseCase {\n private conn: AsyncDuckDBConnection;\n\n constructor(conn: AsyncDuckDBConnection) {\n this.conn = conn;\n }\n\n async exec(params: { inputTableName: string; workspace?: string }): Promise<void> {\n const { inputTableName, workspace = 'main' } = params;\n const qualifiedTableName = `${workspace}.${inputTableName}`;\n const tempTableName = `${inputTableName}_temp_agg`;\n\n const result = await this.conn.query(`\n SELECT building_id\n FROM ${qualifiedTableName}\n WHERE building_id IS NOT NULL\n GROUP BY building_id\n `);\n const buildingIds: bigint[] = result.toArray().map((r: any) => r.building_id as bigint);\n\n await this.conn.query(`CREATE OR REPLACE TEMP TABLE ${tempTableName} (building_id BIGINT, agg_geometry BLOB)`);\n\n for (let i = 0; i < buildingIds.length; i += BATCH_SIZE) {\n const batch = buildingIds.slice(i, i + BATCH_SIZE);\n const ids = batch.map(id => String(id)).join(',');\n\n const query = `\n INSERT INTO ${tempTableName}\n SELECT\n building_id,\n ST_Union_Agg(ST_Buffer(geometry, 0.0)) AS agg_geometry\n FROM ${qualifiedTableName}\n WHERE building_id IN (${ids})\n AND ST_IsValid(geometry)\n GROUP BY building_id;\n `;\n\n try {\n await this.conn.query(query);\n } catch (_error) {\n for (const bid of batch) {\n try {\n await this.conn.query(`\n INSERT INTO ${tempTableName}\n SELECT\n ${String(bid)} AS building_id,\n ST_Union_Agg(ST_Buffer(geometry, 0.0)) AS agg_geometry\n FROM ${qualifiedTableName}\n WHERE building_id = ${String(bid)}\n AND ST_IsValid(geometry)\n GROUP BY building_id;\n `);\n } catch (_e) {\n console.warn(\n `[AggregateBuildingLayer] failed for building_id=${String(bid)}:`,\n (_e as Error).message,\n );\n await this.conn.query(`\n INSERT INTO ${tempTableName} (building_id, agg_geometry)\n VALUES (${String(bid)}, NULL);\n `);\n }\n }\n }\n }\n\n const addColumnQuery = `\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT\n b.*,\n agg.agg_geometry\n FROM ${qualifiedTableName} b\n LEFT JOIN ${tempTableName} agg ON b.building_id = agg.building_id;\n `;\n\n await this.conn.query(addColumnQuery);\n\n const nullCount = (\n await this.conn.query(`\n SELECT COUNT(*) AS cnt\n FROM ${qualifiedTableName}\n WHERE agg_geometry IS NULL\n `)\n ).toArray()[0]?.cnt as number;\n\n if (nullCount > 0) {\n console.warn(`[AggregateBuildingLayer] ${nullCount} rows have no agg_geometry (union failed)`);\n }\n\n await this.conn.query(`DROP TABLE IF EXISTS ${tempTableName};`);\n }\n}","import { LayerType } from 'autk-core';\n\nexport type OsmLayerType = Exclude<LayerType, 'background'>;\n\nexport interface OsmProcessingConfig {\n type: OsmLayerType;\n processesRelations: boolean;\n createsPolygons: boolean;\n postProcessing?: 'building-aggregation' | 'surface-polygonization' | null;\n}\n\nexport const OSM_PROCESSING_CONFIGS: Record<OsmLayerType, OsmProcessingConfig> = {\n surface: { type: 'surface', processesRelations: false, createsPolygons: false, postProcessing: 'surface-polygonization' },\n water: { type: 'water', processesRelations: true, createsPolygons: true, postProcessing: null },\n parks: { type: 'parks', processesRelations: true, createsPolygons: true, postProcessing: null },\n roads: { type: 'roads', processesRelations: false, createsPolygons: false, postProcessing: null },\n buildings: { type: 'buildings', processesRelations: true, createsPolygons: true, postProcessing: 'building-aggregation' },\n points: { type: 'points', processesRelations: false, createsPolygons: false, postProcessing: null },\n polygons: { type: 'polygons', processesRelations: false, createsPolygons: true, postProcessing: null },\n polylines: { type: 'polylines', processesRelations: false, createsPolygons: false, postProcessing: null },\n raster: { type: 'raster', processesRelations: false, createsPolygons: false, postProcessing: null },\n};\n\nexport function getOsmProcessingConfig(layer: LayerType): OsmProcessingConfig | null {\n if (layer === 'background') return null;\n return OSM_PROCESSING_CONFIGS[layer];\n}\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport type { Geometry, MultiPolygon, Polygon, Position } from 'geojson';\n\nimport { LoadLayerParams, LayerType } from './interfaces';\nimport { LOAD_LAYER_QUERY } from './queries';\nimport { BoundingBox, LayerTable } from '../../../shared/interfaces';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport { DEFALT_COORDINATE_FORMAT } from '../../../shared/consts';\nimport { AssignBuildingIdsUseCase } from '../assign-building-ids/AssignBuildingIdsUseCase';\nimport { AggregateBuildingLayerUseCase } from '../aggregate-building-layer/AggregateBuildingLayerUseCase';\nimport { getOsmProcessingConfig } from './osm-processing-config';\n\ntype RelationRow = {\n id: number | bigint;\n refs: unknown;\n ref_roles: unknown;\n ref_types: unknown;\n tags_json: unknown;\n};\n\ntype WayRow = {\n id: number | bigint;\n refs: unknown;\n};\n\ntype NodeRow = {\n id: number | bigint;\n lat: number;\n lon: number;\n};\n\ntype WayRing = {\n refs: number[];\n coordinates: Position[];\n};\n\ntype RelationAreaRecord = {\n id: number;\n tags: Array<{ k: string; v: string }>;\n geometry: Geometry;\n};\n\n/**\n * Extracts a thematic layer (roads, buildings, parks, water, surface) from raw OSM data.\n */\nexport class LoadLayerUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n private assignBuildingIdsUseCase: AssignBuildingIdsUseCase;\n private aggregateBuildingLayerUseCase: AggregateBuildingLayerUseCase;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n this.assignBuildingIdsUseCase = new AssignBuildingIdsUseCase(db, conn);\n this.aggregateBuildingLayerUseCase = new AggregateBuildingLayerUseCase(conn);\n }\n\n async exec(params: LoadLayerParams): Promise<LayerTable> {\n if (!params.coordinateFormat) params.coordinateFormat = DEFALT_COORDINATE_FORMAT;\n const workspace = params.workspace || 'main';\n\n const layerOutputTableName = params.outputTableName || `${params.osmInputTableName}_${params.layer}`;\n const qualifiedOutputTableName = `${workspace}.${layerOutputTableName}`;\n\n const layerQuery = LOAD_LAYER_QUERY({\n layer: params.layer,\n tableName: params.osmInputTableName,\n outputFormat: params.coordinateFormat,\n outputTableName: layerOutputTableName,\n boundingBox: params.boundingBox,\n workspace,\n });\n const describeTableResponse = await this.conn.query(layerQuery);\n let columns = getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray());\n let totalSkippedRelations = 0;\n\n const config = getOsmProcessingConfig(params.layer);\n if (!config) throw new Error(`Unsupported layer type for OSM processing: ${params.layer}`);\n\n if (config.processesRelations) {\n totalSkippedRelations = await this.appendRelationAreaGeometries({\n inputTableName: params.osmInputTableName,\n outputTableName: layerOutputTableName,\n layer: params.layer,\n coordinateFormat: params.coordinateFormat,\n boundingBox: params.boundingBox,\n workspace,\n });\n\n const describeUpdatedTableResponse = await this.conn.query(`DESCRIBE ${qualifiedOutputTableName}`);\n columns = getColumnsFromDuckDbTableDescribe(describeUpdatedTableResponse.toArray());\n }\n\n if (totalSkippedRelations > 0) {\n console.warn(`[LoadLayerUseCase] loaded ${params.layer}: ${totalSkippedRelations} relations skipped.`);\n }\n\n if (config.postProcessing === 'building-aggregation') {\n await this.assignBuildingIdsUseCase.exec({ tableName: layerOutputTableName, workspace });\n\n await this.aggregateBuildingLayerUseCase.exec({\n inputTableName: layerOutputTableName,\n workspace,\n });\n\n const describeUpdatedTableResponse = await this.conn.query(`DESCRIBE ${qualifiedOutputTableName}`);\n columns = getColumnsFromDuckDbTableDescribe(describeUpdatedTableResponse.toArray());\n }\n\n return {\n source: 'osm',\n type: params.layer,\n columns,\n name: layerOutputTableName,\n };\n }\n\n private async appendRelationAreaGeometries(params: {\n inputTableName: string;\n outputTableName: string;\n layer: LayerType;\n coordinateFormat: string;\n boundingBox?: BoundingBox;\n workspace: string;\n }): Promise<number> {\n const { records, skipped } = await this.buildRelationAreaRecords(params.inputTableName, params.layer, params.workspace);\n if (records.length === 0) return skipped;\n\n const fileName = `temp_${params.layer}_relations_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.json`;\n await this.db.registerFileText(fileName, JSON.stringify(records));\n\n const qualifiedOutputTableName = `${params.workspace}.${params.outputTableName}`;\n const geometryWgs84 = 'ST_GeomFromGeoJSON(JSON(geometry))';\n const transformedGeometry = `ST_Transform(${geometryWgs84}, 'EPSG:4326', '${params.coordinateFormat}', always_xy := true)`;\n const clippingGeometry = params.boundingBox\n ? `ST_MakeEnvelope(${params.boundingBox.minLon}, ${params.boundingBox.minLat}, ${params.boundingBox.maxLon}, ${params.boundingBox.maxLat})`\n : null;\n const geometrySelect = clippingGeometry\n ? `ST_Intersection(${transformedGeometry}, ${clippingGeometry})`\n : transformedGeometry;\n const whereClause = clippingGeometry\n ? `WHERE ST_Intersects(${transformedGeometry}, ${clippingGeometry})`\n : '';\n\n try {\n await this.conn.query(`\n INSERT INTO ${qualifiedOutputTableName} (id, properties, refs, geometry)\n SELECT\n id::BIGINT,\n CASE\n WHEN tags IS NULL OR tags = [] THEN NULL\n ELSE map_from_entries(tags)\n END AS properties,\n []::BIGINT[] AS refs,\n ${geometrySelect} AS geometry\n FROM '${fileName}'\n ${whereClause};\n `);\n } finally {\n await this.db.dropFile(fileName);\n }\n\n return skipped;\n }\n\n private async buildRelationAreaRecords(\n inputTableName: string,\n layer: LayerType,\n workspace: string,\n ): Promise<{ records: RelationAreaRecord[]; skipped: number }> {\n const qualifiedInputTableName = `${workspace}.${inputTableName}`;\n const relations = (await this.conn.query(`\n SELECT id, refs, ref_roles, ref_types, CAST(tags AS JSON) AS tags_json\n FROM ${qualifiedInputTableName}\n WHERE kind = 'relation' AND map_extract(tags, '__autk_layer')[1] = '${layer}';\n `)).toArray() as unknown as RelationRow[];\n\n if (relations.length === 0) return { records: [], skipped: 0 };\n\n const ways = (await this.conn.query(`\n SELECT id, refs\n FROM ${qualifiedInputTableName}\n WHERE kind = 'way';\n `)).toArray() as unknown as WayRow[];\n const nodes = (await this.conn.query(`\n SELECT id, lat, lon\n FROM ${qualifiedInputTableName}\n WHERE kind = 'node';\n `)).toArray() as unknown as NodeRow[];\n\n const refsByWayId = new Map<number, number[]>();\n for (const way of ways) {\n refsByWayId.set(this.toNumber(way.id), this.toNumberArray(way.refs));\n }\n\n const coordinateByNodeId = new Map<number, Position>();\n for (const node of nodes) {\n coordinateByNodeId.set(this.toNumber(node.id), [node.lon, node.lat]);\n }\n\n const records: RelationAreaRecord[] = [];\n let skipped = 0;\n for (const relation of relations) {\n const geometry = this.buildRelationGeometry(relation, refsByWayId, coordinateByNodeId);\n if (!geometry) {\n skipped++;\n continue;\n }\n\n const tags = this.parseTags(relation.tags_json);\n records.push({\n id: this.toNumber(relation.id),\n tags: Object.entries(tags).map(([k, v]) => ({ k, v })),\n geometry,\n });\n }\n\n if (skipped > 0) {\n console.warn(`[autk-db] ${layer}: ${skipped} relations skipped (missing member ways or geometry).`);\n }\n\n return { records, skipped };\n }\n\n private buildRelationGeometry(\n relation: RelationRow,\n refsByWayId: Map<number, number[]>,\n coordinateByNodeId: Map<number, Position>,\n ): Polygon | MultiPolygon | null {\n const refs = this.toNumberArray(relation.refs);\n const roles = this.toStringArray(relation.ref_roles);\n const types = this.toStringArray(relation.ref_types);\n\n const outerWayIds: number[] = [];\n const innerWayIds: number[] = [];\n\n refs.forEach((ref, index) => {\n if (types[index] !== 'way') return;\n\n const role = roles[index] ?? '';\n if (role === 'inner') {\n innerWayIds.push(ref);\n } else if (role === 'outer' || role === '') {\n outerWayIds.push(ref);\n }\n });\n\n const outerRings = this.buildClosedRings(outerWayIds, refsByWayId, coordinateByNodeId);\n const innerRings = this.buildClosedRings(innerWayIds, refsByWayId, coordinateByNodeId);\n if (outerRings.length === 0) return null;\n\n const polygons = outerRings.map((outer) => [outer.coordinates] as Position[][]);\n\n for (const inner of innerRings) {\n const matchIndex = outerRings.length === 1\n ? 0\n : outerRings.findIndex((outer) => this.ringContainsPosition(outer.coordinates, inner.coordinates[0]));\n\n if (matchIndex === -1) {\n console.warn(`[autk-db] Skipped unmatched inner ring in relation ${String(relation.id)}.`);\n continue;\n }\n\n polygons[matchIndex].push(inner.coordinates);\n }\n\n if (polygons.length === 1) {\n return {\n type: 'Polygon',\n coordinates: polygons[0],\n };\n }\n\n return {\n type: 'MultiPolygon',\n coordinates: polygons,\n };\n }\n\n private buildClosedRings(\n wayIds: number[],\n refsByWayId: Map<number, number[]>,\n coordinateByNodeId: Map<number, Position>,\n ): WayRing[] {\n const standaloneClosedRings: WayRing[] = [];\n const openSegments: WayRing[] = [];\n\n for (const wayId of wayIds) {\n const refs = refsByWayId.get(wayId);\n if (!refs || refs.length < 2) continue;\n\n const coordinates = refs.map((ref) => coordinateByNodeId.get(ref));\n if (coordinates.some((coordinate) => !coordinate)) continue;\n\n const ring = { refs: [...refs], coordinates: coordinates as Position[] };\n if (refs.length > 3 && refs[0] === refs[refs.length - 1]) {\n standaloneClosedRings.push(ring);\n } else {\n openSegments.push(ring);\n }\n }\n\n return [...standaloneClosedRings, ...this.stitchOpenWaySegmentsIntoRings(openSegments)];\n }\n\n private stitchOpenWaySegmentsIntoRings(segments: WayRing[]): WayRing[] {\n const unusedSegments = [...segments];\n const rings: WayRing[] = [];\n\n while (unusedSegments.length > 0) {\n let current = unusedSegments.shift()!;\n let extended = true;\n\n while (extended) {\n extended = false;\n for (let i = 0; i < unusedSegments.length; i++) {\n const merged = this.tryMergeRings(current, unusedSegments[i]);\n if (!merged) continue;\n\n current = merged;\n unusedSegments.splice(i, 1);\n extended = true;\n break;\n }\n }\n\n if (current.refs.length > 3 && current.refs[0] === current.refs[current.refs.length - 1]) {\n rings.push(current);\n }\n }\n\n return rings;\n }\n\n private tryMergeRings(a: WayRing, b: WayRing): WayRing | null {\n const aStart = a.refs[0];\n const aEnd = a.refs[a.refs.length - 1];\n const bStart = b.refs[0];\n const bEnd = b.refs[b.refs.length - 1];\n\n if (aEnd === bStart) return this.concatRings(a, b);\n if (aEnd === bEnd) return this.concatRings(a, this.reverseRing(b));\n if (aStart === bEnd) return this.concatRings(b, a);\n if (aStart === bStart) return this.concatRings(this.reverseRing(b), a);\n\n return null;\n }\n\n private concatRings(left: WayRing, right: WayRing): WayRing {\n return {\n refs: [...left.refs, ...right.refs.slice(1)],\n coordinates: [...left.coordinates, ...right.coordinates.slice(1)],\n };\n }\n\n private reverseRing(ring: WayRing): WayRing {\n return {\n refs: [...ring.refs].reverse(),\n coordinates: [...ring.coordinates].reverse(),\n };\n }\n\n private ringContainsPosition(ring: Position[], position: Position): boolean {\n const [x, y] = position;\n let inside = false;\n\n for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n const [xi, yi] = ring[i];\n const [xj, yj] = ring[j];\n const intersects = ((yi > y) !== (yj > y))\n && (x < ((xj - xi) * (y - yi)) / (yj - yi) + xi);\n if (intersects) inside = !inside;\n }\n\n return inside;\n }\n\n private parseTags(rawTags: unknown): Record<string, string> {\n const value = typeof rawTags === 'string' ? JSON.parse(rawTags) as unknown : rawTags;\n if (!value) return {};\n\n if (value instanceof Map) {\n return Object.fromEntries([...value.entries()].map(([k, v]) => [String(k), String(v)]));\n }\n\n if (Array.isArray(value)) {\n const entries = value.flatMap((entry): [string, string][] => {\n if (!entry || typeof entry !== 'object') return [];\n const record = entry as Record<string, unknown>;\n if ('k' in record && 'v' in record) return [[String(record.k), String(record.v)]];\n if ('key' in record && 'value' in record) return [[String(record.key), String(record.value)]];\n return [];\n });\n return Object.fromEntries(entries);\n }\n\n if (typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).map(([k, v]) => [k, String(v)]),\n );\n }\n\n return {};\n }\n\n private toNumberArray(value: unknown): number[] {\n if (!value) return [];\n return Array.from(value as Iterable<unknown>).map((item) => this.toNumber(item));\n }\n\n private toStringArray(value: unknown): string[] {\n if (!value) return [];\n return Array.from(value as Iterable<unknown>).map((item) => String(item));\n }\n\n private toNumber(value: unknown): number {\n return typeof value === 'bigint' ? Number(value) : Number(value);\n }\n}\n","import { DEFAULT_GEO_COLUMN_NAME } from '../../../shared/consts';\n\nexport const LOAD_CSV_ON_TABLE_QUERY = (csvFileUrl: string, tableName: string, delimiter: string, workspace: string) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT * FROM READ_CSV(\n '${csvFileUrl}',\n delim='${delimiter}',\n HEADER=TRUE,\n AUTO_DETECT=TRUE\n );\n\n DESCRIBE ${qualifiedTableName};\n `;\n};\n\ninterface LoadCsvOnTableWithCoordinatesParams {\n csvFileUrl: string;\n tableName: string;\n delimiter: string;\n latColumnName: string;\n longColumnName: string;\n coordinateFormat: string;\n workspace: string;\n}\nexport const LOAD_CSV_ON_TABLE_WITH_COORDINATES_QUERY = ({\n csvFileUrl,\n tableName,\n delimiter,\n latColumnName,\n longColumnName,\n coordinateFormat,\n workspace,\n}: LoadCsvOnTableWithCoordinatesParams) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `\n CREATE TABLE ${qualifiedTableName} AS\n SELECT\n *,\n ST_Transform(\n ST_Point(CAST(${longColumnName} AS DOUBLE), CAST(${latColumnName} AS DOUBLE)),\n 'EPSG:4326',\n '${coordinateFormat}',\n always_xy := true\n ) AS ${DEFAULT_GEO_COLUMN_NAME}\n FROM READ_CSV(\n '${csvFileUrl}',\n delim='${delimiter}',\n HEADER=TRUE,\n AUTO_DETECT=TRUE\n );\n\n DESCRIBE ${qualifiedTableName};\n `;\n};\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { LoadCsvParams } from './interfaces';\nimport { CsvTable } from '../../../shared/interfaces';\nimport { LOAD_CSV_ON_TABLE_QUERY, LOAD_CSV_ON_TABLE_WITH_COORDINATES_QUERY } from './queries';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport { DEFALT_COORDINATE_FORMAT, DEFAULT_GEO_COLUMN_NAME } from '../../../shared/consts';\n\n/**\n * Loads CSV data into DuckDB, with optional geometry column creation.\n */\nexport class LoadCsvUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n }\n\n async exec({ csvFileUrl, csvObject, outputTableName, geometryColumns, delimiter = ',', workspace = 'main' }: LoadCsvParams): Promise<CsvTable> {\n if (!csvFileUrl && !csvObject) {\n throw new Error('Either csvFileUrl or csvObject must be provided');\n }\n if (csvFileUrl && csvObject) {\n throw new Error('Cannot provide both csvFileUrl and csvObject. Please provide only one.');\n }\n\n const csvString = csvFileUrl\n ? await fetch(csvFileUrl).then((r) => {\n if (!r.ok) throw new Error(`HTTP error! Error to load ${csvFileUrl}! Status: ${r.status}`);\n return r.text();\n })\n : this.buildCsvString(csvObject!, delimiter);\n\n const csvPath = `temp_csv_${Date.now()}_${Math.random().toString(36).slice(2, 11)}.csv`;\n await this.db.registerFileText(csvPath, csvString);\n\n const qualifiedTableName = `${workspace}.${outputTableName}`;\n \n let loadCsvQuery: string;\n if (geometryColumns) {\n loadCsvQuery = LOAD_CSV_ON_TABLE_WITH_COORDINATES_QUERY({\n csvFileUrl: csvPath,\n tableName: outputTableName,\n delimiter,\n latColumnName: geometryColumns.latColumnName,\n longColumnName: geometryColumns.longColumnName,\n coordinateFormat: geometryColumns.coordinateFormat || DEFALT_COORDINATE_FORMAT,\n workspace,\n });\n } else {\n loadCsvQuery = LOAD_CSV_ON_TABLE_QUERY(csvPath, outputTableName, delimiter, workspace);\n }\n\n const describeTableResponse = await this.conn.query(loadCsvQuery);\n\n // Automatically create spatial index for geometry column\n if (geometryColumns) {\n const indexName = `idx_${outputTableName}_geometry`;\n await this.conn.query(`CREATE INDEX ${indexName} ON ${qualifiedTableName} USING RTREE (${DEFAULT_GEO_COLUMN_NAME});`);\n }\n\n await this.db.dropFile(csvPath);\n\n return {\n source: 'csv',\n type: 'pointset',\n name: outputTableName,\n columns: getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray()),\n };\n }\n\n private buildCsvString(csvObject: unknown[][], delimiter: string): string {\n return csvObject\n .map((row) =>\n row\n .map((value) => {\n const str = String(value ?? '');\n const escaped = str.replace(/\"/g, '\"\"');\n return `\"${escaped}\"`;\n })\n .join(delimiter),\n )\n .join('\\n');\n }\n}\n","import { DEFAULT_GEO_COLUMN_NAME } from '../../../shared/consts';\n\nexport const LOAD_JSON_ON_TABLE_QUERY = (jsonFileUrl: string, tableName: string, workspace: string) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT * FROM read_json_auto('${jsonFileUrl}');\n\n DESCRIBE ${qualifiedTableName};\n `;\n};\n\ninterface LoadJsonOnTableWithCoordinatesParams {\n jsonFileUrl: string;\n tableName: string;\n latColumnName: string;\n longColumnName: string;\n coordinateFormat: string;\n workspace: string;\n}\nexport const LOAD_JSON_ON_TABLE_WITH_COORDINATES_QUERY = ({\n jsonFileUrl,\n tableName,\n latColumnName,\n longColumnName,\n coordinateFormat,\n workspace,\n}: LoadJsonOnTableWithCoordinatesParams) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `\n CREATE TABLE ${qualifiedTableName} AS\n SELECT\n *,\n ST_Transform(\n ST_Point(CAST(${longColumnName} AS DOUBLE), CAST(${latColumnName} AS DOUBLE)),\n 'EPSG:4326',\n '${coordinateFormat}',\n always_xy := true\n ) AS ${DEFAULT_GEO_COLUMN_NAME}\n FROM read_json_auto('${jsonFileUrl}');\n\n DESCRIBE ${qualifiedTableName};\n `;\n};\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { LoadJsonParams } from './interfaces';\nimport { JsonTable } from '../../../shared/interfaces';\nimport { LOAD_JSON_ON_TABLE_QUERY, LOAD_JSON_ON_TABLE_WITH_COORDINATES_QUERY } from './queries';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport { DEFALT_COORDINATE_FORMAT } from '../../../shared/consts';\n\n/**\n * Loads JSON data into DuckDB, with optional geometry column creation.\n */\nexport class LoadJsonUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n }\n\n async exec({ jsonFileUrl, jsonObject, outputTableName, geometryColumns, workspace = 'main' }: LoadJsonParams): Promise<JsonTable> {\n if (!jsonFileUrl && !jsonObject) {\n throw new Error('Either jsonFileUrl or jsonObject must be provided');\n }\n if (jsonFileUrl && jsonObject) {\n throw new Error('Cannot provide both jsonFileUrl and jsonObject. Please provide only one.');\n }\n\n let jsonPath = jsonFileUrl as string;\n let tempFileCreated = false;\n\n if (jsonObject) {\n const jsonString = JSON.stringify(jsonObject);\n jsonPath = `temp_json_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.json`;\n await this.db.registerFileText(jsonPath, jsonString);\n tempFileCreated = true;\n }\n\n let loadJsonQuery: string;\n if (geometryColumns) {\n loadJsonQuery = LOAD_JSON_ON_TABLE_WITH_COORDINATES_QUERY({\n jsonFileUrl: jsonPath,\n tableName: outputTableName,\n latColumnName: geometryColumns.latColumnName,\n longColumnName: geometryColumns.longColumnName,\n coordinateFormat: geometryColumns.coordinateFormat || DEFALT_COORDINATE_FORMAT,\n workspace,\n });\n } else {\n loadJsonQuery = LOAD_JSON_ON_TABLE_QUERY(jsonPath, outputTableName, workspace);\n }\n\n const describeTableResponse = await this.conn.query(loadJsonQuery);\n\n if (tempFileCreated) {\n await this.db.dropFile(jsonPath);\n }\n\n return {\n source: 'json',\n type: 'pointset',\n name: outputTableName,\n columns: getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray()),\n };\n }\n}\n","import { CustomLayerTable, LayerTable } from '../../../shared/interfaces';\n\nexport const GET_LAYER_AS_GEOJSON_QUERY = (layerTable: LayerTable | CustomLayerTable, workspace: string) => {\n const hasBuildingIdColumn = !!layerTable.columns?.some((c) => c.name === 'building_id');\n const qualifiedTableName = `${workspace}.${layerTable.name}`;\n\n if (layerTable.type === 'buildings' && hasBuildingIdColumn) {\n // Aggregate building parts into one feature per building.\n // Geometry becomes a GeometryCollection of all part polygons (one per part).\n // Properties contain a 'parts' array with per-part OSM properties (heights, tags, etc.)\n // aligned by index with geometry.geometries, plus shared/join properties at the top level.\n return `\n SELECT json_object(\n 'type', 'FeatureCollection',\n 'features', json_group_array(feature)\n ) AS geojson\n FROM (\n SELECT json_object(\n 'type', 'Feature',\n 'geometry', json_object('type', 'GeometryCollection', 'geometries', geom_array),\n 'properties', json_merge_patch(rep_props, json_object('building_id', building_id, 'parts', parts_array))\n ) AS feature\n FROM (\n SELECT\n building_id,\n json_group_array(CAST(ST_AsGeoJSON(geometry) AS JSON)) AS geom_array,\n any_value(COALESCE(CAST(properties AS JSON), '{}'::JSON)) AS rep_props,\n json_group_array(COALESCE(CAST(properties AS JSON), '{}'::JSON)) AS parts_array\n FROM ${qualifiedTableName}\n WHERE ST_IsValid(geometry)\n GROUP BY building_id\n ) agg\n ) sub;\n `;\n }\n\n if (layerTable.type === 'buildings') {\n // Fallback for buildings without building_id — wrap each row in a single-part GeometryCollection.\n // This path should rarely be hit since building_id is auto-assigned on load.\n return `\n SELECT json_object(\n 'type', 'FeatureCollection',\n 'features', json_group_array(feature)\n ) AS geojson\n FROM (\n SELECT json_object(\n 'type', 'Feature',\n 'geometry', json_object('type', 'GeometryCollection', 'geometries', json_array(CAST(ST_AsGeoJSON(geometry) AS JSON))),\n 'properties', properties\n ) AS feature\n FROM ${qualifiedTableName}\n ) sub;\n `;\n }\n\n return `\n SELECT json_object(\n 'type', 'FeatureCollection',\n 'features', json_group_array(feature)\n ) AS geojson\n FROM (\n SELECT json_object(\n 'type', 'Feature',\n 'geometry', CAST(ST_AsGeoJSON(geometry) AS JSON),\n 'properties', properties\n ) AS feature\n FROM ${qualifiedTableName}\n ) sub;\n`;\n};\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { FeatureCollection } from 'geojson';\n\nimport { GET_LAYER_AS_GEOJSON_QUERY } from './queries';\nimport { CustomLayerTable, LayerTable } from '../../../shared/interfaces';\n\n/**\n * Exports a layer table as a GeoJSON FeatureCollection.\n */\nexport class GetLayerGeojsonUseCase {\n private conn: AsyncDuckDBConnection;\n\n constructor(conn: AsyncDuckDBConnection) {\n this.conn = conn;\n }\n\n async exec(table: LayerTable | CustomLayerTable, workspace: string = 'main'): Promise<FeatureCollection> {\n const query = GET_LAYER_AS_GEOJSON_QUERY(table, workspace);\n const response = await this.conn.query(query);\n\n const raw: string = response.toArray()[0]?.geojson ?? '{\"type\":\"FeatureCollection\",\"features\":[]}';\n return JSON.parse(raw.replace(/\\bNaN\\b/g, 'null')) as FeatureCollection;\n }\n}\n","/**\n * @module ColorMapTypes\n * Shared enums and types for color mapping, legend generation, and color-buffer\n * exchange across the toolkit.\n *\n * This module defines the contracts used by the shared color-mapping API in\n * `autk-core` and `@urban-toolkit/autk-map`. It describes how a domain is requested and\n * resolved, which d3-backed interpolators can be selected, and how colors are\n * represented when exchanged as hex strings, RGBA objects, or flat texture\n * buffers.\n */\n\n/**\n * Strategies for deriving a colormap domain.\n *\n * The selected strategy determines whether the domain is supplied directly,\n * computed from numeric min/max values, or computed from numeric percentiles.\n */\nexport enum ColorMapDomainStrategy {\n /** Use the caller-provided domain verbatim. */\n USER = 'user',\n /** Derive the domain from the observed minimum and maximum values. */\n MIN_MAX = 'minMax',\n /** Derive the domain from lower and upper percentiles. */\n PERCENTILE = 'percentile',\n}\n\n/**\n * Domain resolved from input data and a colormap configuration.\n *\n * Numeric domains are returned for continuous interpolators, while string\n * domains are returned for categorical schemes and legend labeling.\n */\nexport type ResolvedDomain = number[] | string[];\n\n/**\n * Specification for how a colormap domain should be derived.\n *\n * `USER` supplies an explicit domain, `MIN_MAX` derives a numeric range from\n * the input values, and `PERCENTILE` derives a numeric range from percentile\n * bounds.\n */\nexport type ColorMapDomainSpec =\n /** Explicit domain supplied by the caller. */\n | { type: ColorMapDomainStrategy.USER; params: number[] | string[] }\n /** Domain inferred from the minimum and maximum numeric values. */\n | { type: ColorMapDomainStrategy.MIN_MAX }\n /** Domain inferred from lower and upper numeric percentiles in the 0-100 range. */\n | { type: ColorMapDomainStrategy.PERCENTILE; params?: [number, number] };\n\n/**\n * Identifiers for the supported color schemes and interpolators.\n *\n * Values map to d3-scale-chromatic categorical, sequential, and diverging\n * schemes used by the shared color-mapping engine.\n */\nexport enum ColorMapInterpolator {\n /** Accent categorical scheme. */\n CAT_ACCENT = 'schemeAccent',\n /** Dark2 categorical scheme. */\n CAT_DARK2 = 'schemeDark2',\n /** Category10 categorical scheme. */\n CAT_CATEGORY10 = 'schemeCategory10',\n /** Observable10 categorical scheme. */\n CAT_OBSERVABLE10 = 'schemeObservable10',\n /** Paired categorical scheme. */\n CAT_PAIRED = 'schemePaired',\n /** Pastel1 categorical scheme. */\n CAT_PASTEL1 = 'schemePastel1',\n /** Pastel2 categorical scheme. */\n CAT_PASTEL2 = 'schemePastel2',\n /** Set1 categorical scheme. */\n CAT_SET1 = 'schemeSet1',\n /** Set2 categorical scheme. */\n CAT_SET2 = 'schemeSet2',\n /** Set3 categorical scheme. */\n CAT_SET3 = 'schemeSet3',\n /** Tableau10 categorical scheme. */\n CAT_TABLEAU10 = 'schemeTableau10',\n /** Reds sequential scheme. */\n SEQ_REDS = 'interpolateReds',\n /** Blues sequential scheme. */\n SEQ_BLUES = 'interpolateBlues',\n /** Greens sequential scheme. */\n SEQ_GREENS = 'interpolateGreens',\n /** Greys sequential scheme. */\n SEQ_GREYS = 'interpolateGreys',\n /** Oranges sequential scheme. */\n SEQ_ORANGES = 'interpolateOranges',\n /** Purples sequential scheme. */\n SEQ_PURPLES = 'interpolatePurples',\n /** Turbo sequential scheme. */\n SEQ_TURBO = 'interpolateTurbo',\n /** Viridis sequential scheme. */\n SEQ_VIRIDIS = 'interpolateViridis',\n /** Inferno sequential scheme. */\n SEQ_INFERNO = 'interpolateInferno',\n /** Magma sequential scheme. */\n SEQ_MAGMA = 'interpolateMagma',\n /** Plasma sequential scheme. */\n SEQ_PLASMA = 'interpolatePlasma',\n /** Cividis sequential scheme. */\n SEQ_CIVIDIS = 'interpolateCividis',\n /** Warm sequential scheme. */\n SEQ_WARM = 'interpolateWarm',\n /** Cool sequential scheme. */\n SEQ_COOL = 'interpolateCool',\n /** Default cubehelix sequential scheme. */\n SEQ_CUBEHELIX_DEFAULT = 'interpolateCubehelixDefault',\n /** Blue-Green sequential scheme. */\n SEQ_BU_GN = 'interpolateBuGn',\n /** Blue-Purple sequential scheme. */\n SEQ_BU_PU = 'interpolateBuPu',\n /** Green-Blue sequential scheme. */\n SEQ_GN_BU = 'interpolateGnBu',\n /** Orange-Red sequential scheme. */\n SEQ_OR_RD = 'interpolateOrRd',\n /** Purple-Blue-Green sequential scheme. */\n SEQ_PU_BU_GN = 'interpolatePuBuGn',\n /** Purple-Blue sequential scheme. */\n SEQ_PU_BU = 'interpolatePuBu',\n /** Purple-Red sequential scheme. */\n SEQ_PU_RD = 'interpolatePuRd',\n /** Red-Purple sequential scheme. */\n SEQ_RD_PU = 'interpolateRdPu',\n /** Yellow-Green-Blue sequential scheme. */\n SEQ_YL_GN_BU = 'interpolateYlGnBu',\n /** Yellow-Green sequential scheme. */\n SEQ_YL_GN = 'interpolateYlGn',\n /** Yellow-Orange-Brown sequential scheme. */\n SEQ_YL_OR_BR = 'interpolateYlOrBr',\n /** Yellow-Orange-Red sequential scheme. */\n SEQ_YL_OR_RD = 'interpolateYlOrRd',\n /** Brown-Blue-Green diverging scheme. */\n DIV_BR_BG = 'interpolateBrBG',\n /** Purple-Green diverging scheme. */\n DIV_PR_GN = 'interpolatePRGn',\n /** Pink-Yellow-Green diverging scheme. */\n DIV_PI_YG = 'interpolatePiYG',\n /** Purple-Orange diverging scheme. */\n DIV_PU_OR = 'interpolatePuOr',\n /** Red-Blue diverging scheme. */\n DIV_RED_BLUE = 'interpolateRdBu',\n /** Red-Grey diverging scheme. */\n DIV_RED_GREY = 'interpolateRdGy',\n /** Red-Yellow-Blue diverging scheme. */\n DIV_RED_YELLOW_BLUE = 'interpolateRdYlBu',\n /** Red-Yellow-Green diverging scheme. */\n DIV_RED_YELLOW_GREEN = 'interpolateRdYlGn',\n /** Spectral diverging scheme. */\n DIV_SPECTRAL = 'interpolateSpectral',\n}\n\n/**\n * Unified color-map configuration used by map rendering and legend generation.\n *\n * This config couples the selected interpolator with the domain strategy so\n * both `autk-core` and `@urban-toolkit/autk-map` resolve and display the same scale.\n */\nexport type ColorMapConfig = {\n /** Selected interpolator or color scheme. */\n interpolator: ColorMapInterpolator;\n /** Strategy used to derive the domain passed to the interpolator. */\n domainSpec: ColorMapDomainSpec;\n};\n\n/**\n * Hexadecimal color string used by styling APIs.\n */\nexport type ColorHEX = `#${string}`;\n\n/**\n * RGBA color representation used by sampling and map styling APIs.\n */\nexport type ColorRGB = {\n /** Red channel value. */\n r: number;\n /** Green channel value. */\n g: number;\n /** Blue channel value. */\n b: number;\n /** Alpha channel value, typically normalized to the 0-1 range. */\n alpha: number;\n};\n\n/**\n * Flat RGBA texture buffer laid out as `[r, g, b, a, ...]`.\n */\nexport type ColorTEX = number[];\n","/**\n * @module ColorMap\n * Color-domain resolution, sampling, and legend-label utilities.\n *\n * This module centralizes the logic for turning raw numeric or categorical\n * inputs into resolved color-map domains, d3-backed interpolators, GPU-ready\n * texture data, and human-readable legend labels. It also exposes helpers for\n * converting between RGB and hex representations.\n */\nimport * as d3_color from 'd3-color';\nimport * as d3_format from 'd3-format';\nimport * as d3_scale from 'd3-scale';\nimport * as d3_scheme from 'd3-scale-chromatic';\n\nimport {\n ColorMapDomainStrategy,\n ColorMapConfig,\n ColorHEX,\n ColorMapInterpolator,\n ResolvedDomain,\n ColorRGB,\n ColorTEX,\n} from './types-colormap';\n\nimport type { TypedArray } from './types-buffer';\n\n/** Two-point numeric domain used by sequential color interpolators. */\ntype SequentialDomain = [number, number];\n/** Three-point numeric domain used by diverging color interpolators. */\ntype DivergingDomain = [number, number, number];\n/** Ordered set of category labels used by categorical color schemes. */\ntype CategoricalDomain = string[];\n\n/** Default number of texels used to sample continuous color maps. */\nexport const DEFAULT_COLORMAP_RESOLUTION = 256;\n\n/** Interpolators backed by discrete categorical color schemes. */\nconst CATEGORICAL_INTERPOLATORS = new Set<ColorMapInterpolator>([\n ColorMapInterpolator.CAT_ACCENT,\n ColorMapInterpolator.CAT_DARK2,\n ColorMapInterpolator.CAT_CATEGORY10,\n ColorMapInterpolator.CAT_OBSERVABLE10,\n ColorMapInterpolator.CAT_PAIRED,\n ColorMapInterpolator.CAT_PASTEL1,\n ColorMapInterpolator.CAT_PASTEL2,\n ColorMapInterpolator.CAT_SET1,\n ColorMapInterpolator.CAT_SET2,\n ColorMapInterpolator.CAT_SET3,\n ColorMapInterpolator.CAT_TABLEAU10,\n]);\n\n/** Interpolators backed by diverging continuous color scales. */\nconst DIVERGING_INTERPOLATORS = new Set<ColorMapInterpolator>([\n ColorMapInterpolator.DIV_BR_BG,\n ColorMapInterpolator.DIV_PR_GN,\n ColorMapInterpolator.DIV_PI_YG,\n ColorMapInterpolator.DIV_PU_OR,\n ColorMapInterpolator.DIV_RED_BLUE,\n ColorMapInterpolator.DIV_RED_GREY,\n ColorMapInterpolator.DIV_RED_YELLOW_BLUE,\n ColorMapInterpolator.DIV_RED_YELLOW_GREEN,\n ColorMapInterpolator.DIV_SPECTRAL,\n]);\n\n/**\n * Color utility for resolving domains, sampling color scales, and building\n * legend and texture representations.\n *\n * `ColorMap` decides whether a scheme should be treated as categorical,\n * sequential, or diverging; derives a compatible domain from data and\n * configuration; and exposes helpers for sampling colors or generating flat\n * RGBA textures for GPU upload.\n */\nexport class ColorMap {\n /**\n * Samples a color interpolator at a normalized value, returning RGBA.\n *\n * @param value - Normalized sample position in `[0, 1]`.\n * @param color - Interpolator identifier to sample.\n * @param domain - Optional explicit domain used to parameterize the scale.\n * @returns Sampled color in RGBA object form.\n * @throws Never throws.\n * @example\n * const c = ColorMap.getColor(0.5, ColorMapInterpolator.SEQ_VIRIDIS);\n * // c → { r: 33, g: 144, b: 141, alpha: 1 }\n */\n public static getColor(value: number, color: ColorMapInterpolator, domain?: SequentialDomain | DivergingDomain | CategoricalDomain): ColorRGB {\n const interpolator = ColorMap.buildInterpolator(color, domain);\n const { r, g, b } = d3_color.rgb(interpolator(value));\n return { r, g, b, alpha: 1 };\n }\n\n /**\n * Builds a flat RGBA texture array for GPU upload from a color scheme.\n *\n * @param color - Interpolator identifier to sample.\n * @param res - Number of texels to generate (default `256`).\n * @param domain - Optional explicit domain used to parameterize the scale.\n * @returns Flat RGBA texture values `[r, g, b, a, ...]`.\n * @throws Never throws. Non-positive `res` returns an empty array.\n * @example\n * const tex = ColorMap.getColorMap(ColorMapInterpolator.SEQ_VIRIDIS, 4);\n * // tex → [68, 1, 84, 1, 59, 82, 139, 1, 33, 144, 141, 1, 253, 231, 37, 1]\n */\n public static getColorMap(\n color: ColorMapInterpolator,\n res: number = DEFAULT_COLORMAP_RESOLUTION,\n domain?: SequentialDomain | DivergingDomain | CategoricalDomain,\n ): ColorTEX {\n if (res <= 0) { return []; }\n if (res === 1) {\n const { r, g, b } = d3_color.rgb(ColorMap.buildInterpolator(color, domain)(0.5));\n return [r, g, b, 1];\n }\n\n const interpolator = ColorMap.buildInterpolator(color, domain);\n const tex: number[] = [];\n for (let id = 0; id < res; id++) {\n const { r, g, b } = d3_color.rgb(interpolator(id / (res - 1)));\n tex.push(r, g, b, 1);\n }\n return tex;\n }\n\n /**\n * Builds an array of sampled RGBA color objects from a color scheme.\n *\n * @param color - Interpolator identifier to sample.\n * @param res - Number of samples to generate (default `256`).\n * @param domain - Optional explicit domain used to parameterize the scale.\n * @returns Array of sampled RGBA color objects.\n * @throws Never throws. Non-positive `res` returns an empty array.\n * @example\n * const colors = ColorMap.getColorArray(ColorMapInterpolator.CAT_SET1, 3);\n * // colors → [{ r: 228, g: 26, b: 28, alpha: 1 }, ...]\n */\n public static getColorArray(\n color: ColorMapInterpolator,\n res: number = DEFAULT_COLORMAP_RESOLUTION,\n domain?: SequentialDomain | DivergingDomain | CategoricalDomain,\n ): ColorRGB[] {\n if (res <= 0) { return []; }\n if (res === 1) {\n const { r, g, b } = d3_color.rgb(ColorMap.buildInterpolator(color, domain)(0.5));\n return [{ r, g, b, alpha: 1 }];\n }\n\n const interpolator = ColorMap.buildInterpolator(color, domain);\n const result: ColorRGB[] = [];\n for (let id = 0; id < res; id++) {\n const { r, g, b } = d3_color.rgb(interpolator(id / (res - 1)));\n result.push({ r, g, b, alpha: 1 });\n }\n return result;\n }\n\n /**\n * Converts an RGBA color object into a hex color string.\n *\n * @param color - RGB color to convert.\n * @returns Hexadecimal color string.\n * @throws Never throws.\n * @example\n * ColorMap.rgbToHex({ r: 255, g: 128, b: 0, alpha: 1 }); // '#ff8000'\n */\n public static rgbToHex(color: ColorRGB): ColorHEX {\n const hex = d3_color.rgb(color.r, color.g, color.b, 1).formatHex();\n return <ColorHEX>hex;\n }\n\n /**\n * Converts a hex color string into an RGBA color object.\n *\n * @param color - Hexadecimal color string to convert.\n * @returns RGBA color object with alpha fixed to `1`.\n * @throws Never throws.\n * @example\n * ColorMap.hexToRgb('#ff8000'); // { r: 255, g: 128, b: 0, alpha: 1 }\n */\n public static hexToRgb(color: ColorHEX): ColorRGB {\n const rgb = d3_color.rgb(color);\n return { r: rgb.r, g: rgb.g, b: rgb.b, alpha: 1.0 };\n }\n\n /**\n * Computes the numeric minimum and maximum of a value array.\n *\n * @param values - Numeric values to inspect.\n * @returns Two-element tuple `[min, max]`, or `[0, 0]` when the input is empty.\n * @throws Never throws. Empty input returns `[0, 0]`.\n * @example\n * ColorMap.computeMinMaxRange([3, 7, 2, 9, 4]); // [2, 9]\n */\n public static computeMinMaxRange(values: number[] | TypedArray): [number, number] {\n if (values.length === 0) return [0, 0];\n let min = Infinity;\n let max = -Infinity;\n for (let i = 0; i < values.length; i++) {\n const v = values[i];\n if (v < min) min = v;\n if (v > max) max = v;\n }\n return [min, max];\n }\n\n /**\n * Returns `true` when an interpolator uses a discrete categorical scheme.\n *\n * @param interpolator - Interpolator identifier to classify.\n * @returns `true` for categorical schemes, otherwise `false`.\n * @throws Never throws.\n * @example\n * ColorMap.isCategorical(ColorMapInterpolator.CAT_SET1); // true\n * ColorMap.isCategorical(ColorMapInterpolator.SEQ_VIRIDIS); // false\n */\n public static isCategorical(interpolator: ColorMapInterpolator): boolean {\n return CATEGORICAL_INTERPOLATORS.has(interpolator);\n }\n \n /**\n * Returns `true` when an interpolator uses a diverging continuous scale.\n *\n * @param interpolator - Interpolator identifier to classify.\n * @returns `true` for diverging interpolators, otherwise `false`.\n * @throws Never throws.\n */\n private static isDiverging(interpolator: ColorMapInterpolator): boolean {\n return DIVERGING_INTERPOLATORS.has(interpolator);\n }\n\n /**\n * Returns the number of colors in a categorical color scheme.\n *\n * @param interpolator - Interpolator identifier to inspect.\n * @returns Scheme size for categorical interpolators, or `null` otherwise.\n * @throws Never throws.\n * @example\n * ColorMap.getCategoricalSchemeSize(ColorMapInterpolator.CAT_SET1); // 9\n * ColorMap.getCategoricalSchemeSize(ColorMapInterpolator.SEQ_VIRIDIS); // null\n */\n public static getCategoricalSchemeSize(interpolator: ColorMapInterpolator): number | null {\n if (!ColorMap.isCategorical(interpolator)) return null;\n return (d3_scheme[interpolator] as string[]).length;\n }\n\n\n /**\n * Resolves a numeric domain from data and color-map configuration.\n *\n * USER domains must contain finite numbers and must match the interpolator\n * shape: sequential schemes require at least two values, while diverging\n * schemes accept either two endpoints or an explicit three-point domain.\n * Percentile resolution ignores non-finite values. When no finite values are\n * available, sequential schemes fall back to `[0, 0]` and diverging schemes\n * fall back to `[0, 0, 0]`.\n *\n * @param values - Numeric input values used to derive the domain.\n * @param config - Color-map configuration controlling the domain strategy.\n * @param interpolator - Interpolator used to decide sequential vs diverging behavior.\n * @returns Resolved sequential or diverging numeric domain.\n */\n private static resolveNumericDomainFromConfig(\n values: number[] | TypedArray,\n config: ColorMapConfig,\n interpolator: ColorMapInterpolator,\n ): SequentialDomain | DivergingDomain {\n const mode = config.domainSpec.type;\n\n if (mode === ColorMapDomainStrategy.USER) {\n const params = config.domainSpec.params;\n if (!params.length || params.some(v => typeof v !== 'number' || !Number.isFinite(v))) {\n throw new Error('ColorMap USER domain for numeric interpolators must be number[].');\n }\n const numeric = params as number[];\n if (ColorMap.isDiverging(interpolator)) {\n if (numeric.length === 3) return [numeric[0], numeric[1], numeric[2]];\n if (numeric.length === 2) {\n const center = (numeric[0] + numeric[1]) / 2;\n return [numeric[0], center, numeric[1]];\n }\n throw new Error('Diverging USER domain must have 2 or 3 numeric values.');\n }\n if (numeric.length < 2) {\n throw new Error('Sequential USER domain must have at least 2 numeric values.');\n }\n return [numeric[0], numeric[numeric.length - 1]];\n }\n\n const finiteValues = (ArrayBuffer.isView(values) ? Array.from(values) : values)\n .filter((value) => Number.isFinite(value));\n\n if (finiteValues.length === 0) {\n return ColorMap.isDiverging(interpolator) ? [0, 0, 0] : [0, 0];\n }\n\n if (mode === ColorMapDomainStrategy.PERCENTILE) {\n const [lowerPercentile, upperPercentile] = config.domainSpec.params ?? [2, 98];\n const low = ColorMap.computePercentile(finiteValues, lowerPercentile / 100);\n const high = ColorMap.computePercentile(finiteValues, upperPercentile / 100);\n if (ColorMap.isDiverging(interpolator)) {\n const center = ColorMap.computePercentile(finiteValues, 50 / 100);\n return [low, center, high];\n }\n return [low, high];\n }\n\n const [min, max] = ColorMap.computeMinMaxRange(finiteValues);\n if (ColorMap.isDiverging(interpolator)) {\n const center = (min + max) / 2;\n return [min, center, max];\n }\n return [min, max];\n }\n\n /**\n * Resolves a categorical domain from a color-map configuration.\n *\n * USER domains are used verbatim after string conversion. Data-derived\n * domains preserve first-seen order and remove duplicates.\n *\n * @param values - Input category values.\n * @param config - Color-map configuration controlling the domain strategy.\n * @returns Ordered categorical domain labels.\n */\n private static resolveCategoricalDomainFromConfig(\n values: string[],\n config: ColorMapConfig,\n ): CategoricalDomain {\n if (config.domainSpec.type === ColorMapDomainStrategy.USER) {\n return config.domainSpec.params.map(v => String(v));\n }\n return Array.from(new Set(values.map(v => String(v))));\n }\n\n /**\n * Derives human-readable legend labels from a domain.\n *\n * Categorical domains are returned as-is. Numeric domains are formatted\n * with a magnitude-aware d3 formatter so legend labels remain compact for\n * large values and readable for small decimals.\n *\n * @param domain Any supported color-scale domain.\n * @returns Ordered label strings suitable for a legend.\n * @throws Never throws.\n * @example\n * ColorMap.computeLabels([0, 500000, 1000000]); // ['0', '500,000', '1M']\n * ColorMap.computeLabels(['low', 'mid', 'high']); // ['low', 'mid', 'high']\n */\n public static computeLabels(\n domain: ResolvedDomain,\n ): string[] {\n if (typeof domain[0] === 'string') return domain as string[];\n\n const numeric = domain as number[];\n const maxAbs = numeric.reduce((acc, v) => Math.max(acc, Math.abs(v)), 0);\n const formatter = maxAbs >= 1_000_000\n ? d3_format.format('.3s')\n : maxAbs >= 1\n ? d3_format.format(',.2f')\n : d3_format.format('.3~g');\n\n return numeric.map(v => formatter(v));\n }\n\n /**\n * Resolves a color domain from data and configuration.\n *\n * The method infers categorical handling when the selected interpolator is\n * categorical, when a USER domain contains string values, or when the input\n * array contains non-numeric strings. Numeric-looking strings in normal\n * arrays are still treated as numeric values. Unsupported domain shapes are\n * not coerced beyond this inference.\n *\n * @param values - Source values used to derive the domain.\n * @param config - Color-map configuration controlling the resolution mode.\n * @returns Resolved categorical or numeric domain.\n * @throws {Error} When USER domain has invalid shape for the selected\n * interpolator (e.g. non-numeric values for a sequential interpolator).\n * @example\n * const domain = ColorMap.resolveDomainFromData(\n * [10, 50, 30, 80, 20],\n * { interpolator: ColorMapInterpolator.SEQ_VIRIDIS, domainSpec: { type: ColorMapDomainStrategy.MIN_MAX } }\n * );\n * // domain → [10, 80]\n */\n public static resolveDomainFromData(\n values: number[] | string[] | TypedArray,\n config: ColorMapConfig,\n ): ResolvedDomain {\n const isCategorical = ColorMap.isCategorical(config.interpolator)\n || (config.domainSpec.type === ColorMapDomainStrategy.USER && config.domainSpec.params.some(v => typeof v === 'string'))\n || (!ArrayBuffer.isView(values) && (values as Array<number|string>).some(v => typeof v === 'string' && isNaN(Number(v))));\n\n if (isCategorical) {\n return ColorMap.resolveCategoricalDomainFromConfig(values as string[], config);\n } else {\n return ColorMap.resolveNumericDomainFromConfig(values as number[] | TypedArray, config, config.interpolator);\n }\n }\n\n /**\n * Builds a d3-compatible interpolator function for the requested color scheme.\n *\n * Categorical schemes map values by index into the underlying d3 scheme.\n * When no domain is provided, the full categorical scheme length is used.\n * Diverging scales default to `[0, 0.5, 1]` and sequential scales default to\n * `[0, 1]`.\n *\n * @param color - Interpolator identifier to build.\n * @param domain - Optional explicit domain used to parameterize the scale.\n * @returns Function that maps normalized scalar values to CSS color strings.\n */\n private static buildInterpolator(\n color: ColorMapInterpolator,\n domain?: SequentialDomain | DivergingDomain | CategoricalDomain,\n ): (t: number) => string {\n if (ColorMap.isCategorical(color)) {\n const scheme = d3_scheme[color] as string[];\n const n = domain?.length ?? scheme.length;\n return (t: number) => {\n const idx = Math.min(Math.round(t * (n - 1)), scheme.length - 1);\n return scheme[idx];\n };\n }\n\n if (ColorMap.isDiverging(color)) {\n return d3_scale.scaleDiverging(d3_scheme[color] as (t: number) => string)\n .domain((domain as DivergingDomain) ?? [0, 0.5, 1]);\n }\n\n return d3_scale.scaleSequential(d3_scheme[color] as (t: number) => string)\n .domain((domain as SequentialDomain) ?? [0, 1]);\n }\n\n /**\n * Computes a percentile value from a numeric array.\n *\n * @param values - Numeric values to sample.\n * @param p - Percentile in normalized `[0, 1]` form.\n * @returns Interpolated percentile value, or `0` for empty input.\n */\n private static computePercentile(values: number[] | TypedArray, p: number): number {\n if (values.length === 0) return 0;\n const sorted = (ArrayBuffer.isView(values) ? new Float32Array(values) : [...values]).sort((a, b) => a - b);\n const idx = p * (sorted.length - 1);\n const lo = Math.floor(idx);\n const hi = Math.ceil(idx);\n return sorted[lo] + (sorted[hi] - sorted[lo]) * (idx - lo);\n }\n}\n","/**\n * @module GeometryUtils\n * Planar geometry helpers for triangulation and ring analysis.\n *\n * This module groups small 2D primitives used to offset local-space\n * polylines, normalize polygon rings, measure ring properties, test\n * convexity, and derive convex hulls. The helpers assume coordinates are\n * already expressed in a local planar system.\n */\n\n/**\n * Builds a closed polygon buffer around a polyline for stroke rendering.\n *\n * Input coordinates are expected to already be in a local planar system.\n * Consecutive duplicate points are skipped before the offset is computed.\n * The returned polygon includes a repeated closing vertex and is suitable for\n * triangulation with earcut.\n *\n * @param points - Ordered local-space polyline coordinates.\n * @param distance - Offset distance applied on both sides of the polyline.\n * @returns A closed polygon describing the buffered polyline footprint in\n * local planar coordinates. Returns an empty array when the input contains\n * fewer than two distinct points or when `distance` is `0`.\n * @throws Never throws. Degenerate inputs return an empty array rather than\n * raising an error.\n * @example\n * const poly = offsetPolyline([[0, 0], [10, 0], [10, 10]], 2);\n * // poly is a closed ring e.g. [[-0, 2], [10, -2], [12, 10], …]\n */\nexport function offsetPolyline(points: number[][], distance: number): [number, number][] {\n const clean = points.filter((point, index) => {\n if (index === 0) return true;\n const prev = points[index - 1];\n return point[0] !== prev[0] || point[1] !== prev[1];\n }) as [number, number][];\n\n if (clean.length < 2 || distance === 0) {\n return [];\n }\n\n const left: [number, number][] = [];\n const right: [number, number][] = [];\n\n for (let i = 0; i < clean.length; i++) {\n const prev = i > 0 ? clean[i - 1] : null;\n const curr = clean[i];\n const next = i < clean.length - 1 ? clean[i + 1] : null;\n\n const prevNormal = prev ? getUnitLeftNormal(prev, curr) : null;\n const nextNormal = next ? getUnitLeftNormal(curr, next) : null;\n\n const leftPoint = computeOffsetPoint(prev, curr, next, prevNormal, nextNormal, distance, 1);\n const rightPoint = computeOffsetPoint(prev, curr, next, prevNormal, nextNormal, distance, -1);\n\n left.push(leftPoint);\n right.push(rightPoint);\n }\n\n const polygon = [...left, ...right.reverse()];\n if (polygon.length > 0) {\n polygon.push([polygon[0][0], polygon[0][1]]);\n }\n\n return polygon;\n}\n\n/**\n * Returns a shallow copy of a ring without a duplicated closing vertex.\n *\n * Only the final vertex is removed, and only when it matches the first vertex\n * exactly. Rings that are already open are copied unchanged.\n *\n * @param ring - Polygon ring to normalize.\n * @returns A shallow copy of the ring without a repeated closing point.\n * @throws Never throws. Always returns a shallow copy, even for degenerate inputs.\n * @example\n * const open = normalizeRing([[0, 0], [10, 0], [10, 10], [0, 0]]);\n * // open → [[0, 0], [10, 0], [10, 10]]\n */\nexport function normalizeRing(ring: number[][]): number[][] {\n if (ring.length < 2) return [...ring];\n const normalized = [...ring];\n const first = normalized[0];\n const last = normalized[normalized.length - 1];\n if (first[0] === last[0] && first[1] === last[1]) {\n normalized.pop();\n }\n return normalized;\n}\n\n/**\n * Computes the convex hull of a 2D point set using the monotonic chain algorithm.\n *\n * Duplicate points are removed before hull computation. Collinear interior\n * points are discarded from the outer boundary. Degenerate inputs with\n * three or fewer unique points are returned as shallow copies.\n *\n * @param points - Input points to reduce to a convex hull.\n * @returns Hull points ordered around the outer boundary in CCW order.\n * @throws Never throws. Degenerate inputs are returned verbatim (limited copies).\n * @example\n * const hull = computePointConvexHull([[0, 0], [10, 0], [10, 10], [5, 5], [0, 10]]);\n * // hull → [[0, 0], [10, 0], [10, 10], [0, 10]] (interior point [5,5] discarded)\n */\nexport function computePointConvexHull(points: number[][]): number[][] {\n const unique = Array.from(new Map(\n normalizeRing(points).map((point) => [`${point[0]},${point[1]}`, point as [number, number]])\n ).values());\n\n if (unique.length <= 3) {\n return unique.map(([x, y]) => [x, y]);\n }\n\n unique.sort((a, b) => (a[0] - b[0]) || (a[1] - b[1]));\n\n const lower: Array<[number, number]> = [];\n for (const point of unique) {\n while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], point) <= 0) {\n lower.pop();\n }\n lower.push(point);\n }\n\n const upper: Array<[number, number]> = [];\n for (let i = unique.length - 1; i >= 0; i--) {\n const point = unique[i];\n while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], point) <= 0) {\n upper.pop();\n }\n upper.push(point);\n }\n\n lower.pop();\n upper.pop();\n return [...lower, ...upper].map(([x, y]) => [x, y]);\n}\n\n/**\n * Computes the signed planar area of a polygon ring.\n *\n * Positive area indicates counterclockwise winding; negative area indicates\n * clockwise winding. The ring is automatically closed between the last and\n * first vertex.\n *\n * @param ring - Ring vertices in order around the polygon.\n * @returns Signed area of the ring. Counterclockwise rings produce positive\n * area and clockwise rings produce negative area.\n * @throws Never throws. Degenerate rings return `0`.\n * @example\n * const area = computeRingArea([[0, 0], [10, 0], [10, 10]]);\n * // area → 50 (CCW triangle)\n */\nexport function computeRingArea(ring: number[][]): number {\n let area = 0;\n for (let i = 0; i < ring.length; i++) {\n const [x1, y1] = ring[i];\n const [x2, y2] = ring[(i + 1) % ring.length];\n area += x1 * y2 - x2 * y1;\n }\n return area * 0.5;\n}\n\n/**\n * Computes the total perimeter length of a polygon ring.\n *\n * The ring is traversed in order and closed automatically between the last\n * and first vertex.\n *\n * @param ring - Ring vertices in order around the polygon.\n * @returns Sum of Euclidean edge lengths around the ring.\n * @throws Never throws. Returns `0` for rings with fewer than 2 vertices.\n * @example\n * const len = polygonPerimeter([[0, 0], [10, 0], [10, 10]]);\n * // len → 10 + 10 + 14.14…\n */\nexport function polygonPerimeter(ring: number[][]): number {\n let perimeter = 0;\n const n = ring.length;\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const dx = ring[i][0] - ring[j][0];\n const dy = ring[i][1] - ring[j][1];\n perimeter += Math.sqrt(dx * dx + dy * dy);\n }\n return perimeter;\n}\n\n/**\n * Returns true when a polygon ring is convex.\n *\n * Assumes the ring is already open, with no duplicated closing vertex.\n * Collinear vertices are ignored when testing turn direction consistency.\n *\n * @param ring - Open polygon ring to test.\n * @returns `true` when all non-zero cross products share the same sign,\n * otherwise `false`.\n * @throws Never throws. Rings with fewer than 3 vertices return `true`.\n * @example\n * isConvex([[0, 0], [10, 0], [10, 10], [0, 10]]); // true\n * isConvex([[0, 0], [10, 0], [5, 5], [10, 10], [0, 10]]); // false (concave)\n */\nexport function isConvex(ring: number[][]): boolean {\n const n = ring.length;\n let sign = 0;\n for (let i = 0; i < n; i++) {\n const prev = (i + n - 1) % n;\n const next = (i + 1) % n;\n const e1x = ring[i][0] - ring[prev][0];\n const e1y = ring[i][1] - ring[prev][1];\n const e2x = ring[next][0] - ring[i][0];\n const e2y = ring[next][1] - ring[i][1];\n const turn = e1x * e2y - e1y * e2x;\n if (Math.abs(turn) < 1e-10) continue;\n const currentSign = turn > 0 ? 1 : -1;\n if (sign === 0) sign = currentSign;\n else if (currentSign !== sign) return false;\n }\n return true;\n}\n\n/**\n * Computes the unit left-hand normal for a directed segment.\n *\n * The left-hand normal is the vector perpendicular to the segment direction\n * rotated 90° counterclockwise, used by `offsetPolyline` to push vertices\n * outward.\n *\n * @param a - Start point of the segment.\n * @param b - End point of the segment.\n * @returns A normalized left-hand perpendicular vector, or `null` when the\n * segment has zero length.\n */\nfunction getUnitLeftNormal(a: [number, number], b: [number, number]): [number, number] | null {\n const dx = b[0] - a[0];\n const dy = b[1] - a[1];\n const length = Math.hypot(dx, dy);\n\n if (length === 0) {\n return null;\n }\n\n return [-dy / length, dx / length];\n}\n\n/**\n * Computes the offset vertex for one side of a polyline at a given vertex.\n *\n * Endpoints fall back to a single segment normal. Interior vertices are formed\n * by intersecting the adjacent offset segments when possible; when segments\n * are parallel or nearly so, the averaged normal direction is used instead.\n *\n * @param prev - Previous polyline point, or `null` when `curr` is the first point.\n * @param curr - Current polyline point being offset.\n * @param next - Next polyline point, or `null` when `curr` is the last point.\n * @param prevNormal - Unit left normal of the incoming segment, if available.\n * @param nextNormal - Unit left normal of the outgoing segment, if available.\n * @param distance - Offset distance applied away from the source polyline.\n * @param side - Offset side multiplier: `1` for the left outline, `-1` for the right outline.\n * @returns The offset point for the requested side at `curr`. Falls back to\n * `curr` itself when both normals are unavailable.\n */\nfunction computeOffsetPoint(\n prev: [number, number] | null,\n curr: [number, number],\n next: [number, number] | null,\n prevNormal: [number, number] | null,\n nextNormal: [number, number] | null,\n distance: number,\n side: 1 | -1,\n): [number, number] {\n if (!prevNormal && !nextNormal) {\n return curr;\n }\n\n if (!prev || !prevNormal) {\n return [\n curr[0] + nextNormal![0] * distance * side,\n curr[1] + nextNormal![1] * distance * side,\n ];\n }\n\n if (!next || !nextNormal) {\n return [\n curr[0] + prevNormal[0] * distance * side,\n curr[1] + prevNormal[1] * distance * side,\n ];\n }\n\n const prevOffsetA: [number, number] = [\n prev[0] + prevNormal[0] * distance * side,\n prev[1] + prevNormal[1] * distance * side,\n ];\n const prevOffsetB: [number, number] = [\n curr[0] + prevNormal[0] * distance * side,\n curr[1] + prevNormal[1] * distance * side,\n ];\n const nextOffsetA: [number, number] = [\n curr[0] + nextNormal[0] * distance * side,\n curr[1] + nextNormal[1] * distance * side,\n ];\n const nextOffsetB: [number, number] = [\n next[0] + nextNormal[0] * distance * side,\n next[1] + nextNormal[1] * distance * side,\n ];\n\n const intersection = intersectLines(prevOffsetA, prevOffsetB, nextOffsetA, nextOffsetB);\n if (intersection) {\n return intersection;\n }\n\n const avgX = prevNormal[0] + nextNormal[0];\n const avgY = prevNormal[1] + nextNormal[1];\n const avgLength = Math.hypot(avgX, avgY);\n\n if (avgLength === 0) {\n return [\n curr[0] + nextNormal[0] * distance * side,\n curr[1] + nextNormal[1] * distance * side,\n ];\n }\n\n return [\n curr[0] + (avgX / avgLength) * distance * side,\n curr[1] + (avgY / avgLength) * distance * side,\n ];\n}\n\n/**\n * Computes the intersection point of two infinite 2D lines.\n *\n * The lines are defined by the point pairs `a1`-`a2` and `b1`-`b2`.\n * Parallel or nearly parallel lines (determinant < 1e-9) return `null`.\n * Used by `computeOffsetPoint` to resolve mitered corners.\n *\n * @param a1 - First point on the first line.\n * @param a2 - Second point on the first line.\n * @param b1 - First point on the second line.\n * @param b2 - Second point on the second line.\n * @returns The line intersection point, or `null` when the lines are parallel\n * or nearly so.\n */\nfunction intersectLines(\n a1: [number, number],\n a2: [number, number],\n b1: [number, number],\n b2: [number, number],\n): [number, number] | null {\n const x1 = a1[0];\n const y1 = a1[1];\n const x2 = a2[0];\n const y2 = a2[1];\n const x3 = b1[0];\n const y3 = b1[1];\n const x4 = b2[0];\n const y4 = b2[1];\n\n const denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);\n if (Math.abs(denom) < 1e-9) {\n return null;\n }\n\n const detA = x1 * y2 - y1 * x2;\n const detB = x3 * y4 - y3 * x4;\n\n return [\n (detA * (x3 - x4) - (x1 - x2) * detB) / denom,\n (detA * (y3 - y4) - (y1 - y2) * detB) / denom,\n ];\n}\n\n/**\n * Computes the signed cross product of the turn from `a` → `b` → `c`.\n *\n * Used by `computePointConvexHull` to test point-to-line orientation during\n * monotonic chain construction.\n *\n * @param a - First point.\n * @param b - Second point.\n * @param c - Third point.\n * @returns Positive for counterclockwise turns, negative for clockwise\n * turns, and `0` for collinear points.\n */\nfunction cross(a: [number, number], b: [number, number], c: [number, number]): number {\n return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);\n}\n","\nexport default function earcut(data, holeIndices, dim = 2) {\n\n const hasHoles = holeIndices && holeIndices.length;\n const outerLen = hasHoles ? holeIndices[0] * dim : data.length;\n let outerNode = linkedList(data, 0, outerLen, dim, true);\n const triangles = [];\n\n if (!outerNode || outerNode.next === outerNode.prev) return triangles;\n\n let minX, minY, invSize;\n\n if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);\n\n // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox\n if (data.length > 80 * dim) {\n minX = data[0];\n minY = data[1];\n let maxX = minX;\n let maxY = minY;\n\n for (let i = dim; i < outerLen; i += dim) {\n const x = data[i];\n const y = data[i + 1];\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n }\n\n // minX, minY and invSize are later used to transform coords into integers for z-order calculation\n invSize = Math.max(maxX - minX, maxY - minY);\n invSize = invSize !== 0 ? 32767 / invSize : 0;\n }\n\n earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);\n\n return triangles;\n}\n\n// create a circular doubly linked list from polygon points in the specified winding order\nfunction linkedList(data, start, end, dim, clockwise) {\n let last;\n\n if (clockwise === (signedArea(data, start, end, dim) > 0)) {\n for (let i = start; i < end; i += dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);\n } else {\n for (let i = end - dim; i >= start; i -= dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);\n }\n\n if (last && equals(last, last.next)) {\n removeNode(last);\n last = last.next;\n }\n\n return last;\n}\n\n// eliminate colinear or duplicate points\nfunction filterPoints(start, end) {\n if (!start) return start;\n if (!end) end = start;\n\n let p = start,\n again;\n do {\n again = false;\n\n if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {\n removeNode(p);\n p = end = p.prev;\n if (p === p.next) break;\n again = true;\n\n } else {\n p = p.next;\n }\n } while (again || p !== end);\n\n return end;\n}\n\n// main ear slicing loop which triangulates a polygon (given as a linked list)\nfunction earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {\n if (!ear) return;\n\n // interlink polygon nodes in z-order\n if (!pass && invSize) indexCurve(ear, minX, minY, invSize);\n\n let stop = ear;\n\n // iterate through ears, slicing them one by one\n while (ear.prev !== ear.next) {\n const prev = ear.prev;\n const next = ear.next;\n\n if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {\n triangles.push(prev.i, ear.i, next.i); // cut off the triangle\n\n removeNode(ear);\n\n // skipping the next vertex leads to less sliver triangles\n ear = next.next;\n stop = next.next;\n\n continue;\n }\n\n ear = next;\n\n // if we looped through the whole remaining polygon and can't find any more ears\n if (ear === stop) {\n // try filtering points and slicing again\n if (!pass) {\n earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);\n\n // if this didn't work, try curing all small self-intersections locally\n } else if (pass === 1) {\n ear = cureLocalIntersections(filterPoints(ear), triangles);\n earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);\n\n // as a last resort, try splitting the remaining polygon into two\n } else if (pass === 2) {\n splitEarcut(ear, triangles, dim, minX, minY, invSize);\n }\n\n break;\n }\n }\n}\n\n// check whether a polygon node forms a valid ear with adjacent nodes\nfunction isEar(ear) {\n const a = ear.prev,\n b = ear,\n c = ear.next;\n\n if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\n\n // now make sure we don't have other points inside the potential ear\n const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;\n\n // triangle bbox\n const x0 = Math.min(ax, bx, cx),\n y0 = Math.min(ay, by, cy),\n x1 = Math.max(ax, bx, cx),\n y1 = Math.max(ay, by, cy);\n\n let p = c.next;\n while (p !== a) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&\n pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) &&\n area(p.prev, p, p.next) >= 0) return false;\n p = p.next;\n }\n\n return true;\n}\n\nfunction isEarHashed(ear, minX, minY, invSize) {\n const a = ear.prev,\n b = ear,\n c = ear.next;\n\n if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\n\n const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;\n\n // triangle bbox\n const x0 = Math.min(ax, bx, cx),\n y0 = Math.min(ay, by, cy),\n x1 = Math.max(ax, bx, cx),\n y1 = Math.max(ay, by, cy);\n\n // z-order range for the current triangle bbox;\n const minZ = zOrder(x0, y0, minX, minY, invSize),\n maxZ = zOrder(x1, y1, minX, minY, invSize);\n\n let p = ear.prevZ,\n n = ear.nextZ;\n\n // look for points inside the triangle in both directions\n while (p && p.z >= minZ && n && n.z <= maxZ) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&\n pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.prevZ;\n\n if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&\n pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;\n n = n.nextZ;\n }\n\n // look for remaining points in decreasing z-order\n while (p && p.z >= minZ) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&\n pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.prevZ;\n }\n\n // look for remaining points in increasing z-order\n while (n && n.z <= maxZ) {\n if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&\n pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;\n n = n.nextZ;\n }\n\n return true;\n}\n\n// go through all polygon nodes and cure small local self-intersections\nfunction cureLocalIntersections(start, triangles) {\n let p = start;\n do {\n const a = p.prev,\n b = p.next.next;\n\n if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {\n\n triangles.push(a.i, p.i, b.i);\n\n // remove two nodes involved\n removeNode(p);\n removeNode(p.next);\n\n p = start = b;\n }\n p = p.next;\n } while (p !== start);\n\n return filterPoints(p);\n}\n\n// try splitting polygon into two and triangulate them independently\nfunction splitEarcut(start, triangles, dim, minX, minY, invSize) {\n // look for a valid diagonal that divides the polygon into two\n let a = start;\n do {\n let b = a.next.next;\n while (b !== a.prev) {\n if (a.i !== b.i && isValidDiagonal(a, b)) {\n // split the polygon in two by the diagonal\n let c = splitPolygon(a, b);\n\n // filter colinear points around the cuts\n a = filterPoints(a, a.next);\n c = filterPoints(c, c.next);\n\n // run earcut on each half\n earcutLinked(a, triangles, dim, minX, minY, invSize, 0);\n earcutLinked(c, triangles, dim, minX, minY, invSize, 0);\n return;\n }\n b = b.next;\n }\n a = a.next;\n } while (a !== start);\n}\n\n// link every hole into the outer loop, producing a single-ring polygon without holes\nfunction eliminateHoles(data, holeIndices, outerNode, dim) {\n const queue = [];\n\n for (let i = 0, len = holeIndices.length; i < len; i++) {\n const start = holeIndices[i] * dim;\n const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n const list = linkedList(data, start, end, dim, false);\n if (list === list.next) list.steiner = true;\n queue.push(getLeftmost(list));\n }\n\n queue.sort(compareXYSlope);\n\n // process holes from left to right\n for (let i = 0; i < queue.length; i++) {\n outerNode = eliminateHole(queue[i], outerNode);\n }\n\n return outerNode;\n}\n\nfunction compareXYSlope(a, b) {\n let result = a.x - b.x;\n // when the left-most point of 2 holes meet at a vertex, sort the holes counterclockwise so that when we find\n // the bridge to the outer shell is always the point that they meet at.\n if (result === 0) {\n result = a.y - b.y;\n if (result === 0) {\n const aSlope = (a.next.y - a.y) / (a.next.x - a.x);\n const bSlope = (b.next.y - b.y) / (b.next.x - b.x);\n result = aSlope - bSlope;\n }\n }\n return result;\n}\n\n// find a bridge between vertices that connects hole with an outer ring and link it\nfunction eliminateHole(hole, outerNode) {\n const bridge = findHoleBridge(hole, outerNode);\n if (!bridge) {\n return outerNode;\n }\n\n const bridgeReverse = splitPolygon(bridge, hole);\n\n // filter collinear points around the cuts\n filterPoints(bridgeReverse, bridgeReverse.next);\n return filterPoints(bridge, bridge.next);\n}\n\n// David Eberly's algorithm for finding a bridge between hole and outer polygon\nfunction findHoleBridge(hole, outerNode) {\n let p = outerNode;\n const hx = hole.x;\n const hy = hole.y;\n let qx = -Infinity;\n let m;\n\n // find a segment intersected by a ray from the hole's leftmost point to the left;\n // segment's endpoint with lesser x will be potential connection point\n // unless they intersect at a vertex, then choose the vertex\n if (equals(hole, p)) return p;\n do {\n if (equals(hole, p.next)) return p.next;\n else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {\n const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);\n if (x <= hx && x > qx) {\n qx = x;\n m = p.x < p.next.x ? p : p.next;\n if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint\n }\n }\n p = p.next;\n } while (p !== outerNode);\n\n if (!m) return null;\n\n // look for points inside the triangle of hole point, segment intersection and endpoint;\n // if there are no points found, we have a valid connection;\n // otherwise choose the point of the minimum angle with the ray as connection point\n\n const stop = m;\n const mx = m.x;\n const my = m.y;\n let tanMin = Infinity;\n\n p = m;\n\n do {\n if (hx >= p.x && p.x >= mx && hx !== p.x &&\n pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {\n\n const tan = Math.abs(hy - p.y) / (hx - p.x); // tangential\n\n if (locallyInside(p, hole) &&\n (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {\n m = p;\n tanMin = tan;\n }\n }\n\n p = p.next;\n } while (p !== stop);\n\n return m;\n}\n\n// whether sector in vertex m contains sector in vertex p in the same coordinates\nfunction sectorContainsSector(m, p) {\n return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;\n}\n\n// interlink polygon nodes in z-order\nfunction indexCurve(start, minX, minY, invSize) {\n let p = start;\n do {\n if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);\n p.prevZ = p.prev;\n p.nextZ = p.next;\n p = p.next;\n } while (p !== start);\n\n p.prevZ.nextZ = null;\n p.prevZ = null;\n\n sortLinked(p);\n}\n\n// Simon Tatham's linked list merge sort algorithm\n// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html\nfunction sortLinked(list) {\n let numMerges;\n let inSize = 1;\n\n do {\n let p = list;\n let e;\n list = null;\n let tail = null;\n numMerges = 0;\n\n while (p) {\n numMerges++;\n let q = p;\n let pSize = 0;\n for (let i = 0; i < inSize; i++) {\n pSize++;\n q = q.nextZ;\n if (!q) break;\n }\n let qSize = inSize;\n\n while (pSize > 0 || (qSize > 0 && q)) {\n\n if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {\n e = p;\n p = p.nextZ;\n pSize--;\n } else {\n e = q;\n q = q.nextZ;\n qSize--;\n }\n\n if (tail) tail.nextZ = e;\n else list = e;\n\n e.prevZ = tail;\n tail = e;\n }\n\n p = q;\n }\n\n tail.nextZ = null;\n inSize *= 2;\n\n } while (numMerges > 1);\n\n return list;\n}\n\n// z-order of a point given coords and inverse of the longer side of data bbox\nfunction zOrder(x, y, minX, minY, invSize) {\n // coords are transformed into non-negative 15-bit integer range\n x = (x - minX) * invSize | 0;\n y = (y - minY) * invSize | 0;\n\n x = (x | (x << 8)) & 0x00FF00FF;\n x = (x | (x << 4)) & 0x0F0F0F0F;\n x = (x | (x << 2)) & 0x33333333;\n x = (x | (x << 1)) & 0x55555555;\n\n y = (y | (y << 8)) & 0x00FF00FF;\n y = (y | (y << 4)) & 0x0F0F0F0F;\n y = (y | (y << 2)) & 0x33333333;\n y = (y | (y << 1)) & 0x55555555;\n\n return x | (y << 1);\n}\n\n// find the leftmost node of a polygon ring\nfunction getLeftmost(start) {\n let p = start,\n leftmost = start;\n do {\n if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;\n p = p.next;\n } while (p !== start);\n\n return leftmost;\n}\n\n// check if a point lies within a convex triangle\nfunction pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {\n return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&\n (ax - px) * (by - py) >= (bx - px) * (ay - py) &&\n (bx - px) * (cy - py) >= (cx - px) * (by - py);\n}\n\n// check if a point lies within a convex triangle but false if its equal to the first point of the triangle\nfunction pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, px, py) {\n return !(ax === px && ay === py) && pointInTriangle(ax, ay, bx, by, cx, cy, px, py);\n}\n\n// check if a diagonal between two polygon nodes is valid (lies in polygon interior)\nfunction isValidDiagonal(a, b) {\n return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // doesn't intersect other edges\n (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible\n (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors\n equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case\n}\n\n// signed area of a triangle\nfunction area(p, q, r) {\n return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);\n}\n\n// check if two points are equal\nfunction equals(p1, p2) {\n return p1.x === p2.x && p1.y === p2.y;\n}\n\n// check if two segments intersect\nfunction intersects(p1, q1, p2, q2) {\n const o1 = sign(area(p1, q1, p2));\n const o2 = sign(area(p1, q1, q2));\n const o3 = sign(area(p2, q2, p1));\n const o4 = sign(area(p2, q2, q1));\n\n if (o1 !== o2 && o3 !== o4) return true; // general case\n\n if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1\n if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1\n if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2\n if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2\n\n return false;\n}\n\n// for collinear points p, q, r, check if point q lies on segment pr\nfunction onSegment(p, q, r) {\n return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);\n}\n\nfunction sign(num) {\n return num > 0 ? 1 : num < 0 ? -1 : 0;\n}\n\n// check if a polygon diagonal intersects any polygon segments\nfunction intersectsPolygon(a, b) {\n let p = a;\n do {\n if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&\n intersects(p, p.next, a, b)) return true;\n p = p.next;\n } while (p !== a);\n\n return false;\n}\n\n// check if a polygon diagonal is locally inside the polygon\nfunction locallyInside(a, b) {\n return area(a.prev, a, a.next) < 0 ?\n area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :\n area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;\n}\n\n// check if the middle point of a polygon diagonal is inside the polygon\nfunction middleInside(a, b) {\n let p = a;\n let inside = false;\n const px = (a.x + b.x) / 2;\n const py = (a.y + b.y) / 2;\n do {\n if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&\n (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))\n inside = !inside;\n p = p.next;\n } while (p !== a);\n\n return inside;\n}\n\n// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;\n// if one belongs to the outer ring and another to a hole, it merges it into a single ring\nfunction splitPolygon(a, b) {\n const a2 = createNode(a.i, a.x, a.y),\n b2 = createNode(b.i, b.x, b.y),\n an = a.next,\n bp = b.prev;\n\n a.next = b;\n b.prev = a;\n\n a2.next = an;\n an.prev = a2;\n\n b2.next = a2;\n a2.prev = b2;\n\n bp.next = b2;\n b2.prev = bp;\n\n return b2;\n}\n\n// create a node and optionally link it with previous one (in a circular doubly linked list)\nfunction insertNode(i, x, y, last) {\n const p = createNode(i, x, y);\n\n if (!last) {\n p.prev = p;\n p.next = p;\n\n } else {\n p.next = last.next;\n p.prev = last;\n last.next.prev = p;\n last.next = p;\n }\n return p;\n}\n\nfunction removeNode(p) {\n p.next.prev = p.prev;\n p.prev.next = p.next;\n\n if (p.prevZ) p.prevZ.nextZ = p.nextZ;\n if (p.nextZ) p.nextZ.prevZ = p.prevZ;\n}\n\nfunction createNode(i, x, y) {\n return {\n i, // vertex index in coordinates array\n x, y, // vertex coordinates\n prev: null, // previous and next vertex nodes in a polygon ring\n next: null,\n z: 0, // z-order curve value\n prevZ: null, // previous and next nodes in z-order\n nextZ: null,\n steiner: false // indicates whether this is a steiner point\n };\n}\n\n// return a percentage difference between the polygon area and its triangulation area;\n// used to verify correctness of triangulation\nexport function deviation(data, holeIndices, dim, triangles) {\n const hasHoles = holeIndices && holeIndices.length;\n const outerLen = hasHoles ? holeIndices[0] * dim : data.length;\n\n let polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));\n if (hasHoles) {\n for (let i = 0, len = holeIndices.length; i < len; i++) {\n const start = holeIndices[i] * dim;\n const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n polygonArea -= Math.abs(signedArea(data, start, end, dim));\n }\n }\n\n let trianglesArea = 0;\n for (let i = 0; i < triangles.length; i += 3) {\n const a = triangles[i] * dim;\n const b = triangles[i + 1] * dim;\n const c = triangles[i + 2] * dim;\n trianglesArea += Math.abs(\n (data[a] - data[c]) * (data[b + 1] - data[a + 1]) -\n (data[a] - data[b]) * (data[c + 1] - data[a + 1]));\n }\n\n return polygonArea === 0 && trianglesArea === 0 ? 0 :\n Math.abs((trianglesArea - polygonArea) / polygonArea);\n}\n\nfunction signedArea(data, start, end, dim) {\n let sum = 0;\n for (let i = start, j = end - dim; i < end; i += dim) {\n sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);\n j = i;\n }\n return sum;\n}\n\n// turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts\nexport function flatten(data) {\n const vertices = [];\n const holes = [];\n const dimensions = data[0][0].length;\n let holeIndex = 0;\n let prevLen = 0;\n\n for (const ring of data) {\n for (const p of ring) {\n for (let d = 0; d < dimensions; d++) vertices.push(p[d]);\n }\n if (prevLen) {\n holeIndex += prevLen;\n holes.push(holeIndex);\n }\n prevLen = ring.length;\n }\n return {vertices, holes, dimensions};\n}\n","import { FeatureCollection, Feature, LineString, MultiLineString, GeometryCollection } from 'geojson';\n\nimport { LayerGeometry, LayerComponent } from './types-mesh';\n\nimport { offsetPolyline } from './utils-geometry';\nimport earcut from 'earcut';\n\n/**\n * @module triangulator-polylines\n * Polyline triangulation helpers for GeoJSON line geometries.\n *\n * This module converts `LineString`, `MultiLineString`, and supported\n * `GeometryCollection` children into closed buffered polygons in local planar\n * coordinates, then triangulates the resulting rings with `earcut` for mesh\n * rendering.\n */\nexport class TriangulatorPolylines {\n /** Default half-width, in local planar units, used when buffering source polylines. */\n static offset: number = 5;\n\n /** OSM road half-widths, in local planar units, keyed by normalized `highway` tag value. */\n static readonly ROAD_HALF_WIDTH_BY_HIGHWAY: Record<string, number> = {\n motorway: 10,\n motorway_link: 3.5,\n trunk: 8,\n trunk_link: 3.5,\n primary: 6,\n primary_link: 3,\n secondary: 5,\n secondary_link: 2.5,\n tertiary: 4,\n tertiary_link: 2,\n unclassified: 3.5,\n residential: 3.5,\n service: 2.5,\n living_street: 2.5,\n road: 3.5,\n track: 1.5,\n path: 0.75,\n };\n\n /** Default road half-width used when no known `highway` tag value is available. */\n static readonly DEFAULT_ROAD_HALF_WIDTH: number = 3.5;\n\n /** Optional callback used to resolve a per-feature polyline half-width. */\n static readonly defaultOffsetResolver = (_feature: Feature, _featureIndex: number): number => TriangulatorPolylines.offset;\n\n /**\n * Builds triangulated polyline geometry for a GeoJSON feature collection.\n *\n * @param geojson Source feature collection containing polyline geometries.\n * @param origin World-space origin subtracted before converting to local planar space.\n * @param resolveOffset Optional per-feature half-width resolver.\n * @returns A tuple of triangulated geometry chunks and per-feature component metadata.\n * @throws Never throws. Unsupported or degenerate features are skipped.\n * @example\n * const [meshes, comps] = TriangulatorPolylines.buildMesh(lineFC, origin);\n */\n static buildMesh(\n geojson: FeatureCollection,\n origin: number[],\n resolveOffset: (feature: Feature, featureIndex: number) => number = TriangulatorPolylines.defaultOffsetResolver,\n ): [LayerGeometry[], LayerComponent[]] {\n const mesh: LayerGeometry[] = [];\n const comps: LayerComponent[] = [];\n\n const collection: Feature[] = geojson['features'];\n\n let meshes: { flatCoords: number[], flatIds: number[] }[];\n for (let fId = 0; fId < collection.length; fId++) {\n const feature = collection[fId];\n if (!feature.geometry) {\n TriangulatorPolylines.warnSkippedFeature(fId, null);\n continue;\n }\n\n const resolvedOffset = resolveOffset(feature, fId);\n const offset = Number.isFinite(resolvedOffset) && resolvedOffset > 0\n ? resolvedOffset\n : TriangulatorPolylines.offset;\n\n if (feature.geometry.type === 'LineString') {\n meshes = TriangulatorPolylines.lineStringToPolyline(feature, origin, offset);\n } else if (feature.geometry.type === 'MultiLineString') {\n meshes = TriangulatorPolylines.multiLineStringToPolyline(feature, origin, offset);\n } else if (feature.geometry.type === 'GeometryCollection') {\n meshes = TriangulatorPolylines.geometryCollectionToPolyline(feature, origin, offset, fId);\n } else {\n TriangulatorPolylines.warnSkippedFeature(fId, feature.geometry.type);\n continue;\n }\n\n let nPoints = 0;\n let nTriangles = 0;\n\n for (const triangulation of meshes) {\n mesh.push({ \n position: new Float32Array(triangulation.flatCoords), \n indices: new Uint32Array(triangulation.flatIds),\n featureIndex: fId,\n });\n nPoints += triangulation.flatCoords.length / 2;\n nTriangles += triangulation.flatIds.length / 3;\n }\n comps.push({ nPoints, nTriangles, featureIndex: fId, featureId: feature.id });\n }\n return [mesh, comps];\n }\n\n /**\n * Converts a single `LineString` feature into triangulated polyline mesh data.\n *\n * @param feature Source feature with `LineString` geometry.\n * @param origin World-space origin subtracted before buffering.\n * @param offset Polyline half-width used for planar buffering.\n * @returns One triangulated polygon mesh, or an empty array when buffering fails.\n * @throws Never throws. Degenerate buffers return an empty array.\n * @example\n * const [mesh] = TriangulatorPolylines.lineStringToPolyline(feature, origin, 5);\n */\n static lineStringToPolyline(feature: Feature, origin: number[], offset: number): { flatCoords: number[], flatIds: number[] }[] {\n const base = <LineString>feature.geometry;\n const localCoords = base.coordinates.map((coord: number[]) => [coord[0] - origin[0], coord[1] - origin[1]]);\n const polygon = offsetPolyline(localCoords, offset);\n if (polygon.length < 4) {\n return [];\n }\n\n const flatIds = earcut(polygon.flat());\n const flatCoords = polygon.map((coord: number[]) => [coord[0], coord[1]]).flat();\n\n return [{ flatCoords, flatIds }];\n }\n\n /**\n * Converts a `MultiLineString` feature into triangulated polyline meshes.\n *\n * @param feature Source feature with `MultiLineString` geometry.\n * @param origin World-space origin subtracted before buffering.\n * @param offset Polyline half-width used for planar buffering.\n * @returns Triangulated meshes for each valid buffered line string.\n * @throws Never throws. Invalid buffered lines are silently ignored.\n * @example\n * const meshes = TriangulatorPolylines.multiLineStringToPolyline(feature, origin, 5);\n */\n static multiLineStringToPolyline(feature: Feature, origin: number[], offset: number): { flatCoords: number[], flatIds: number[] }[] {\n const { coordinates } = <MultiLineString>feature.geometry;\n\n const meshes = [];\n for (const ls of coordinates) {\n const localCoords = ls.map((coord: number[]) => [coord[0] - origin[0], coord[1] - origin[1]]);\n const polygon = offsetPolyline(localCoords, offset);\n if (polygon.length < 4) {\n continue;\n }\n\n const flatIds = earcut(polygon.flat());\n const flatCoords = polygon.map((coord: number[]) => [coord[0], coord[1]]).flat();\n\n meshes.push({ flatCoords, flatIds });\n }\n\n return meshes;\n }\n\n /**\n * Flattens supported children of a `GeometryCollection` into polyline meshes.\n *\n * @param feature Source feature with `GeometryCollection` geometry.\n * @param origin World-space origin subtracted before buffering.\n * @param offset Polyline half-width used for planar buffering.\n * @param featureIndex Index of the parent feature in the source collection.\n * @returns Triangulated meshes for all supported child geometries.\n * @throws Never throws. Unsupported children are skipped with a console warning.\n * @example\n * const meshes = TriangulatorPolylines.geometryCollectionToPolyline(feature, origin, 5, 0);\n */\n static geometryCollectionToPolyline(feature: Feature, origin: number[], offset: number, featureIndex: number): { flatCoords: number[], flatIds: number[] }[] {\n const { geometries } = <GeometryCollection>feature.geometry;\n const meshes = [];\n for (const geom of geometries) {\n const syntheticFeature = { ...feature, geometry: geom } as Feature;\n if (geom.type === 'LineString') {\n meshes.push(...TriangulatorPolylines.lineStringToPolyline(syntheticFeature, origin, offset));\n } else if (geom.type === 'MultiLineString') {\n meshes.push(...TriangulatorPolylines.multiLineStringToPolyline(syntheticFeature, origin, offset));\n } else {\n TriangulatorPolylines.warnSkippedGeometryCollectionChild(featureIndex, geom.type);\n }\n }\n return meshes;\n }\n\n /**\n * Resolves a road polyline half-width from OSM `highway` tag semantics.\n *\n * @param feature Source road feature with `highway` property.\n * @returns Polyline half-width in local planar units.\n * @throws Never throws. Falls back to `DEFAULT_ROAD_HALF_WIDTH`.\n * @example\n * const hw = TriangulatorPolylines.resolveRoadHalfWidth(roadFeature);\n * // hw → 10 for motorway, 6 for primary, 3.5 for unknown\n */\n static resolveRoadHalfWidth(feature: Feature): number {\n const highway = TriangulatorPolylines.normalizeRoadHighwayValue(feature.properties?.highway);\n return highway\n ? (TriangulatorPolylines.ROAD_HALF_WIDTH_BY_HIGHWAY[highway] ?? TriangulatorPolylines.DEFAULT_ROAD_HALF_WIDTH)\n : TriangulatorPolylines.DEFAULT_ROAD_HALF_WIDTH;\n }\n\n /**\n * Normalizes an OSM `highway` tag value for road-width lookup.\n *\n * @param highway Raw `highway` property value (string, semicolon-delimited, or array).\n * @returns Normalized highway token, or `null` when unavailable.\n * @throws Never throws.\n * @example\n * TriangulatorPolylines.normalizeRoadHighwayValue('motorway'); // 'motorway'\n * TriangulatorPolylines.normalizeRoadHighwayValue('primary;secondary'); // 'primary'\n */\n static normalizeRoadHighwayValue(highway: unknown): string | null {\n const values = Array.isArray(highway)\n ? highway\n : typeof highway === 'string'\n ? highway.split(';')\n : [];\n\n for (const value of values) {\n if (typeof value !== 'string') {\n continue;\n }\n\n const normalized = value.trim().toLowerCase();\n if (normalized.length > 0) {\n return normalized;\n }\n }\n\n return null;\n }\n\n /**\n * Emits a warning when a feature does not contain a supported polyline geometry.\n *\n * @param featureIndex Index of the skipped feature in the source collection.\n * @param geometryType Encountered geometry type, or `null` when geometry is missing.\n * @returns Nothing. A warning is written to the console.\n */\n private static warnSkippedFeature(featureIndex: number, geometryType: string | null): void {\n console.warn(\n `[autk-core] TriangulatorPolylines skipped feature ${featureIndex}: expected LineString or MultiLineString geometry, got ${geometryType ?? 'null'}.`\n );\n }\n\n /**\n * Emits a warning when a `GeometryCollection` child is not a supported polyline geometry.\n *\n * @param featureIndex Index of the parent feature in the source collection.\n * @param geometryType Encountered unsupported child geometry type.\n * @returns Nothing. A warning is written to the console.\n */\n private static warnSkippedGeometryCollectionChild(featureIndex: number, geometryType: string): void {\n console.warn(\n `[autk-core] TriangulatorPolylines skipped GeometryCollection child in feature ${featureIndex}: expected LineString or MultiLineString geometry, got ${geometryType}.`\n );\n }\n}\n","/**\n * Common utilities\n * @module glMatrix\n */\n\n// Configuration Constants\nexport var EPSILON = 0.000001;\nexport var ARRAY_TYPE = typeof Float32Array !== \"undefined\" ? Float32Array : Array;\nexport var RANDOM = Math.random;\nexport var ANGLE_ORDER = \"zyx\";\n\n/**\n * Symmetric round\n * see https://www.npmjs.com/package/round-half-up-symmetric#user-content-detailed-background\n *\n * @param {Number} a value to round\n */\nexport function round(a) {\n if (a >= 0) return Math.round(a);\n return a % 0.5 === 0 ? Math.floor(a) : Math.round(a);\n}\n\n/**\n * Sets the type of array used when creating new vectors and matrices\n *\n * @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array\n */\nexport function setMatrixArrayType(type) {\n ARRAY_TYPE = type;\n}\nvar degree = Math.PI / 180;\nvar radian = 180 / Math.PI;\n\n/**\n * Convert Degree To Radian\n *\n * @param {Number} a Angle in Degrees\n */\nexport function toRadian(a) {\n return a * degree;\n}\n\n/**\n * Convert Radian To Degree\n *\n * @param {Number} a Angle in Radians\n */\nexport function toDegree(a) {\n return a * radian;\n}\n\n/**\n * Tests whether or not the arguments have approximately the same value, within an absolute\n * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less\n * than or equal to 1.0, and a relative tolerance is used for larger values)\n *\n * @param {Number} a The first number to test.\n * @param {Number} b The second number to test.\n * @param {Number} tolerance Absolute or relative tolerance (default glMatrix.EPSILON)\n * @returns {Boolean} True if the numbers are approximately equal, false otherwise.\n */\nexport function equals(a, b) {\n var tolerance = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : EPSILON;\n return Math.abs(a - b) <= tolerance * Math.max(1, Math.abs(a), Math.abs(b));\n}","import * as glMatrix from \"./common.js\";\n\n/**\n * 4x4 Matrix<br>Format: column-major, when typed out it looks like row-major<br>The matrices are being post multiplied.\n * @module mat4\n */\n\n/**\n * Creates a new identity mat4\n *\n * @returns {mat4} a new 4x4 matrix\n */\nexport function create() {\n var out = new glMatrix.ARRAY_TYPE(16);\n if (glMatrix.ARRAY_TYPE != Float32Array) {\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n }\n out[0] = 1;\n out[5] = 1;\n out[10] = 1;\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a new mat4 initialized with values from an existing matrix\n *\n * @param {ReadonlyMat4} a matrix to clone\n * @returns {mat4} a new 4x4 matrix\n */\nexport function clone(a) {\n var out = new glMatrix.ARRAY_TYPE(16);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n\n/**\n * Copy the values from one mat4 to another\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\nexport function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n\n/**\n * Create a new mat4 with the given values\n *\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\n * @returns {mat4} A new mat4\n */\nexport function fromValues(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\n var out = new glMatrix.ARRAY_TYPE(16);\n out[0] = m00;\n out[1] = m01;\n out[2] = m02;\n out[3] = m03;\n out[4] = m10;\n out[5] = m11;\n out[6] = m12;\n out[7] = m13;\n out[8] = m20;\n out[9] = m21;\n out[10] = m22;\n out[11] = m23;\n out[12] = m30;\n out[13] = m31;\n out[14] = m32;\n out[15] = m33;\n return out;\n}\n\n/**\n * Set the components of a mat4 to the given values\n *\n * @param {mat4} out the receiving matrix\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\n * @returns {mat4} out\n */\nexport function set(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\n out[0] = m00;\n out[1] = m01;\n out[2] = m02;\n out[3] = m03;\n out[4] = m10;\n out[5] = m11;\n out[6] = m12;\n out[7] = m13;\n out[8] = m20;\n out[9] = m21;\n out[10] = m22;\n out[11] = m23;\n out[12] = m30;\n out[13] = m31;\n out[14] = m32;\n out[15] = m33;\n return out;\n}\n\n/**\n * Set a mat4 to the identity matrix\n *\n * @param {mat4} out the receiving matrix\n * @returns {mat4} out\n */\nexport function identity(out) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Transpose the values of a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\nexport function transpose(out, a) {\n // If we are transposing ourselves we can skip a few steps but have to cache some values\n if (out === a) {\n var a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a12 = a[6],\n a13 = a[7];\n var a23 = a[11];\n out[1] = a[4];\n out[2] = a[8];\n out[3] = a[12];\n out[4] = a01;\n out[6] = a[9];\n out[7] = a[13];\n out[8] = a02;\n out[9] = a12;\n out[11] = a[14];\n out[12] = a03;\n out[13] = a13;\n out[14] = a23;\n } else {\n out[0] = a[0];\n out[1] = a[4];\n out[2] = a[8];\n out[3] = a[12];\n out[4] = a[1];\n out[5] = a[5];\n out[6] = a[9];\n out[7] = a[13];\n out[8] = a[2];\n out[9] = a[6];\n out[10] = a[10];\n out[11] = a[14];\n out[12] = a[3];\n out[13] = a[7];\n out[14] = a[11];\n out[15] = a[15];\n }\n return out;\n}\n\n/**\n * Inverts a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4 | null} out, or null if source matrix is not invertible\n */\nexport function invert(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b00 = a00 * a11 - a01 * a10;\n var b01 = a00 * a12 - a02 * a10;\n var b02 = a00 * a13 - a03 * a10;\n var b03 = a01 * a12 - a02 * a11;\n var b04 = a01 * a13 - a03 * a11;\n var b05 = a02 * a13 - a03 * a12;\n var b06 = a20 * a31 - a21 * a30;\n var b07 = a20 * a32 - a22 * a30;\n var b08 = a20 * a33 - a23 * a30;\n var b09 = a21 * a32 - a22 * a31;\n var b10 = a21 * a33 - a23 * a31;\n var b11 = a22 * a33 - a23 * a32;\n\n // Calculate the determinant\n var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n if (!det) {\n return null;\n }\n det = 1.0 / det;\n out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;\n out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;\n out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;\n out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;\n out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;\n out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;\n out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;\n out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;\n out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;\n out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;\n out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;\n out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;\n out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;\n out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;\n out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;\n out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;\n return out;\n}\n\n/**\n * Calculates the adjugate of a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\nexport function adjoint(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b00 = a00 * a11 - a01 * a10;\n var b01 = a00 * a12 - a02 * a10;\n var b02 = a00 * a13 - a03 * a10;\n var b03 = a01 * a12 - a02 * a11;\n var b04 = a01 * a13 - a03 * a11;\n var b05 = a02 * a13 - a03 * a12;\n var b06 = a20 * a31 - a21 * a30;\n var b07 = a20 * a32 - a22 * a30;\n var b08 = a20 * a33 - a23 * a30;\n var b09 = a21 * a32 - a22 * a31;\n var b10 = a21 * a33 - a23 * a31;\n var b11 = a22 * a33 - a23 * a32;\n out[0] = a11 * b11 - a12 * b10 + a13 * b09;\n out[1] = a02 * b10 - a01 * b11 - a03 * b09;\n out[2] = a31 * b05 - a32 * b04 + a33 * b03;\n out[3] = a22 * b04 - a21 * b05 - a23 * b03;\n out[4] = a12 * b08 - a10 * b11 - a13 * b07;\n out[5] = a00 * b11 - a02 * b08 + a03 * b07;\n out[6] = a32 * b02 - a30 * b05 - a33 * b01;\n out[7] = a20 * b05 - a22 * b02 + a23 * b01;\n out[8] = a10 * b10 - a11 * b08 + a13 * b06;\n out[9] = a01 * b08 - a00 * b10 - a03 * b06;\n out[10] = a30 * b04 - a31 * b02 + a33 * b00;\n out[11] = a21 * b02 - a20 * b04 - a23 * b00;\n out[12] = a11 * b07 - a10 * b09 - a12 * b06;\n out[13] = a00 * b09 - a01 * b07 + a02 * b06;\n out[14] = a31 * b01 - a30 * b03 - a32 * b00;\n out[15] = a20 * b03 - a21 * b01 + a22 * b00;\n return out;\n}\n\n/**\n * Calculates the determinant of a mat4\n *\n * @param {ReadonlyMat4} a the source matrix\n * @returns {Number} determinant of a\n */\nexport function determinant(a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b0 = a00 * a11 - a01 * a10;\n var b1 = a00 * a12 - a02 * a10;\n var b2 = a01 * a12 - a02 * a11;\n var b3 = a20 * a31 - a21 * a30;\n var b4 = a20 * a32 - a22 * a30;\n var b5 = a21 * a32 - a22 * a31;\n var b6 = a00 * b5 - a01 * b4 + a02 * b3;\n var b7 = a10 * b5 - a11 * b4 + a12 * b3;\n var b8 = a20 * b2 - a21 * b1 + a22 * b0;\n var b9 = a30 * b2 - a31 * b1 + a32 * b0;\n\n // Calculate the determinant\n return a13 * b6 - a03 * b7 + a33 * b8 - a23 * b9;\n}\n\n/**\n * Multiplies two mat4s\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\nexport function multiply(out, a, b) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n\n // Cache only the current line of the second matrix\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[4];\n b1 = b[5];\n b2 = b[6];\n b3 = b[7];\n out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[8];\n b1 = b[9];\n b2 = b[10];\n b3 = b[11];\n out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[12];\n b1 = b[13];\n b2 = b[14];\n b3 = b[15];\n out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n return out;\n}\n\n/**\n * Translate a mat4 by the given vector\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to translate\n * @param {ReadonlyVec3} v vector to translate by\n * @returns {mat4} out\n */\nexport function translate(out, a, v) {\n var x = v[0],\n y = v[1],\n z = v[2];\n var a00, a01, a02, a03;\n var a10, a11, a12, a13;\n var a20, a21, a22, a23;\n if (a === out) {\n out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];\n out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];\n out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];\n out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];\n } else {\n a00 = a[0];\n a01 = a[1];\n a02 = a[2];\n a03 = a[3];\n a10 = a[4];\n a11 = a[5];\n a12 = a[6];\n a13 = a[7];\n a20 = a[8];\n a21 = a[9];\n a22 = a[10];\n a23 = a[11];\n out[0] = a00;\n out[1] = a01;\n out[2] = a02;\n out[3] = a03;\n out[4] = a10;\n out[5] = a11;\n out[6] = a12;\n out[7] = a13;\n out[8] = a20;\n out[9] = a21;\n out[10] = a22;\n out[11] = a23;\n out[12] = a00 * x + a10 * y + a20 * z + a[12];\n out[13] = a01 * x + a11 * y + a21 * z + a[13];\n out[14] = a02 * x + a12 * y + a22 * z + a[14];\n out[15] = a03 * x + a13 * y + a23 * z + a[15];\n }\n return out;\n}\n\n/**\n * Scales the mat4 by the dimensions in the given vec3 not using vectorization\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to scale\n * @param {ReadonlyVec3} v the vec3 to scale the matrix by\n * @returns {mat4} out\n **/\nexport function scale(out, a, v) {\n var x = v[0],\n y = v[1],\n z = v[2];\n out[0] = a[0] * x;\n out[1] = a[1] * x;\n out[2] = a[2] * x;\n out[3] = a[3] * x;\n out[4] = a[4] * y;\n out[5] = a[5] * y;\n out[6] = a[6] * y;\n out[7] = a[7] * y;\n out[8] = a[8] * z;\n out[9] = a[9] * z;\n out[10] = a[10] * z;\n out[11] = a[11] * z;\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n\n/**\n * Rotates a mat4 by the given angle around the given axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @param {ReadonlyVec3} axis the axis to rotate around\n * @returns {mat4} out\n */\nexport function rotate(out, a, rad, axis) {\n var x = axis[0],\n y = axis[1],\n z = axis[2];\n var len = Math.sqrt(x * x + y * y + z * z);\n var s, c, t;\n var a00, a01, a02, a03;\n var a10, a11, a12, a13;\n var a20, a21, a22, a23;\n var b00, b01, b02;\n var b10, b11, b12;\n var b20, b21, b22;\n if (len < glMatrix.EPSILON) {\n return null;\n }\n len = 1 / len;\n x *= len;\n y *= len;\n z *= len;\n s = Math.sin(rad);\n c = Math.cos(rad);\n t = 1 - c;\n a00 = a[0];\n a01 = a[1];\n a02 = a[2];\n a03 = a[3];\n a10 = a[4];\n a11 = a[5];\n a12 = a[6];\n a13 = a[7];\n a20 = a[8];\n a21 = a[9];\n a22 = a[10];\n a23 = a[11];\n\n // Construct the elements of the rotation matrix\n b00 = x * x * t + c;\n b01 = y * x * t + z * s;\n b02 = z * x * t - y * s;\n b10 = x * y * t - z * s;\n b11 = y * y * t + c;\n b12 = z * y * t + x * s;\n b20 = x * z * t + y * s;\n b21 = y * z * t - x * s;\n b22 = z * z * t + c;\n\n // Perform rotation-specific matrix multiplication\n out[0] = a00 * b00 + a10 * b01 + a20 * b02;\n out[1] = a01 * b00 + a11 * b01 + a21 * b02;\n out[2] = a02 * b00 + a12 * b01 + a22 * b02;\n out[3] = a03 * b00 + a13 * b01 + a23 * b02;\n out[4] = a00 * b10 + a10 * b11 + a20 * b12;\n out[5] = a01 * b10 + a11 * b11 + a21 * b12;\n out[6] = a02 * b10 + a12 * b11 + a22 * b12;\n out[7] = a03 * b10 + a13 * b11 + a23 * b12;\n out[8] = a00 * b20 + a10 * b21 + a20 * b22;\n out[9] = a01 * b20 + a11 * b21 + a21 * b22;\n out[10] = a02 * b20 + a12 * b21 + a22 * b22;\n out[11] = a03 * b20 + a13 * b21 + a23 * b22;\n if (a !== out) {\n // If the source and destination differ, copy the unchanged last row\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n }\n return out;\n}\n\n/**\n * Rotates a matrix by the given angle around the X axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\nexport function rotateX(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a10 = a[4];\n var a11 = a[5];\n var a12 = a[6];\n var a13 = a[7];\n var a20 = a[8];\n var a21 = a[9];\n var a22 = a[10];\n var a23 = a[11];\n if (a !== out) {\n // If the source and destination differ, copy the unchanged rows\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n }\n\n // Perform axis-specific matrix multiplication\n out[4] = a10 * c + a20 * s;\n out[5] = a11 * c + a21 * s;\n out[6] = a12 * c + a22 * s;\n out[7] = a13 * c + a23 * s;\n out[8] = a20 * c - a10 * s;\n out[9] = a21 * c - a11 * s;\n out[10] = a22 * c - a12 * s;\n out[11] = a23 * c - a13 * s;\n return out;\n}\n\n/**\n * Rotates a matrix by the given angle around the Y axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\nexport function rotateY(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a00 = a[0];\n var a01 = a[1];\n var a02 = a[2];\n var a03 = a[3];\n var a20 = a[8];\n var a21 = a[9];\n var a22 = a[10];\n var a23 = a[11];\n if (a !== out) {\n // If the source and destination differ, copy the unchanged rows\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n }\n\n // Perform axis-specific matrix multiplication\n out[0] = a00 * c - a20 * s;\n out[1] = a01 * c - a21 * s;\n out[2] = a02 * c - a22 * s;\n out[3] = a03 * c - a23 * s;\n out[8] = a00 * s + a20 * c;\n out[9] = a01 * s + a21 * c;\n out[10] = a02 * s + a22 * c;\n out[11] = a03 * s + a23 * c;\n return out;\n}\n\n/**\n * Rotates a matrix by the given angle around the Z axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\nexport function rotateZ(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a00 = a[0];\n var a01 = a[1];\n var a02 = a[2];\n var a03 = a[3];\n var a10 = a[4];\n var a11 = a[5];\n var a12 = a[6];\n var a13 = a[7];\n if (a !== out) {\n // If the source and destination differ, copy the unchanged last row\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n }\n\n // Perform axis-specific matrix multiplication\n out[0] = a00 * c + a10 * s;\n out[1] = a01 * c + a11 * s;\n out[2] = a02 * c + a12 * s;\n out[3] = a03 * c + a13 * s;\n out[4] = a10 * c - a00 * s;\n out[5] = a11 * c - a01 * s;\n out[6] = a12 * c - a02 * s;\n out[7] = a13 * c - a03 * s;\n return out;\n}\n\n/**\n * Creates a matrix from a vector translation\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, dest, vec);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyVec3} v Translation vector\n * @returns {mat4} out\n */\nexport function fromTranslation(out, v) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from a vector scaling\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.scale(dest, dest, vec);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyVec3} v Scaling vector\n * @returns {mat4} out\n */\nexport function fromScaling(out, v) {\n out[0] = v[0];\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = v[1];\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = v[2];\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from a given angle around a given axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotate(dest, dest, rad, axis);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @param {ReadonlyVec3} axis the axis to rotate around\n * @returns {mat4} out\n */\nexport function fromRotation(out, rad, axis) {\n var x = axis[0],\n y = axis[1],\n z = axis[2];\n var len = Math.sqrt(x * x + y * y + z * z);\n var s, c, t;\n if (len < glMatrix.EPSILON) {\n return null;\n }\n len = 1 / len;\n x *= len;\n y *= len;\n z *= len;\n s = Math.sin(rad);\n c = Math.cos(rad);\n t = 1 - c;\n\n // Perform rotation-specific matrix multiplication\n out[0] = x * x * t + c;\n out[1] = y * x * t + z * s;\n out[2] = z * x * t - y * s;\n out[3] = 0;\n out[4] = x * y * t - z * s;\n out[5] = y * y * t + c;\n out[6] = z * y * t + x * s;\n out[7] = 0;\n out[8] = x * z * t + y * s;\n out[9] = y * z * t - x * s;\n out[10] = z * z * t + c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from the given angle around the X axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateX(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\nexport function fromXRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n\n // Perform axis-specific matrix multiplication\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = c;\n out[6] = s;\n out[7] = 0;\n out[8] = 0;\n out[9] = -s;\n out[10] = c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from the given angle around the Y axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateY(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\nexport function fromYRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n\n // Perform axis-specific matrix multiplication\n out[0] = c;\n out[1] = 0;\n out[2] = -s;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = s;\n out[9] = 0;\n out[10] = c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from the given angle around the Z axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateZ(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\nexport function fromZRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n\n // Perform axis-specific matrix multiplication\n out[0] = c;\n out[1] = s;\n out[2] = 0;\n out[3] = 0;\n out[4] = -s;\n out[5] = c;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from a quaternion rotation and vector translation\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, dest, vec);\n * let quatMat = mat4.create();\n * mat4.fromQuat(quatMat, quat);\n * mat4.multiply(dest, dest, quatMat);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @returns {mat4} out\n */\nexport function fromRotationTranslation(out, q, v) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n out[0] = 1 - (yy + zz);\n out[1] = xy + wz;\n out[2] = xz - wy;\n out[3] = 0;\n out[4] = xy - wz;\n out[5] = 1 - (xx + zz);\n out[6] = yz + wx;\n out[7] = 0;\n out[8] = xz + wy;\n out[9] = yz - wx;\n out[10] = 1 - (xx + yy);\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a new mat4 from a dual quat.\n *\n * @param {mat4} out Matrix\n * @param {ReadonlyQuat2} a Dual Quaternion\n * @returns {mat4} mat4 receiving operation result\n */\nexport function fromQuat2(out, a) {\n var translation = new glMatrix.ARRAY_TYPE(3);\n var bx = -a[0],\n by = -a[1],\n bz = -a[2],\n bw = a[3],\n ax = a[4],\n ay = a[5],\n az = a[6],\n aw = a[7];\n var magnitude = bx * bx + by * by + bz * bz + bw * bw;\n //Only scale if it makes sense\n if (magnitude > 0) {\n translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;\n translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;\n translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;\n } else {\n translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;\n translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;\n translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;\n }\n fromRotationTranslation(out, a, translation);\n return out;\n}\n\n/**\n * Returns the translation vector component of a transformation\n * matrix. If a matrix is built with fromRotationTranslation,\n * the returned vector will be the same as the translation vector\n * originally supplied.\n * @param {vec3} out Vector to receive translation component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {vec3} out\n */\nexport function getTranslation(out, mat) {\n out[0] = mat[12];\n out[1] = mat[13];\n out[2] = mat[14];\n return out;\n}\n\n/**\n * Returns the scaling factor component of a transformation\n * matrix. If a matrix is built with fromRotationTranslationScale\n * with a normalized Quaternion parameter, the returned vector will be\n * the same as the scaling vector\n * originally supplied.\n * @param {vec3} out Vector to receive scaling factor component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {vec3} out\n */\nexport function getScaling(out, mat) {\n var m11 = mat[0];\n var m12 = mat[1];\n var m13 = mat[2];\n var m21 = mat[4];\n var m22 = mat[5];\n var m23 = mat[6];\n var m31 = mat[8];\n var m32 = mat[9];\n var m33 = mat[10];\n out[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13);\n out[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23);\n out[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33);\n return out;\n}\n\n/**\n * Returns a quaternion representing the rotational component\n * of a transformation matrix. If a matrix is built with\n * fromRotationTranslation, the returned quaternion will be the\n * same as the quaternion originally supplied.\n * @param {quat} out Quaternion to receive the rotation component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {quat} out\n */\nexport function getRotation(out, mat) {\n var scaling = new glMatrix.ARRAY_TYPE(3);\n getScaling(scaling, mat);\n var is1 = 1 / scaling[0];\n var is2 = 1 / scaling[1];\n var is3 = 1 / scaling[2];\n var sm11 = mat[0] * is1;\n var sm12 = mat[1] * is2;\n var sm13 = mat[2] * is3;\n var sm21 = mat[4] * is1;\n var sm22 = mat[5] * is2;\n var sm23 = mat[6] * is3;\n var sm31 = mat[8] * is1;\n var sm32 = mat[9] * is2;\n var sm33 = mat[10] * is3;\n var trace = sm11 + sm22 + sm33;\n var S = 0;\n if (trace > 0) {\n S = Math.sqrt(trace + 1.0) * 2;\n out[3] = 0.25 * S;\n out[0] = (sm23 - sm32) / S;\n out[1] = (sm31 - sm13) / S;\n out[2] = (sm12 - sm21) / S;\n } else if (sm11 > sm22 && sm11 > sm33) {\n S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;\n out[3] = (sm23 - sm32) / S;\n out[0] = 0.25 * S;\n out[1] = (sm12 + sm21) / S;\n out[2] = (sm31 + sm13) / S;\n } else if (sm22 > sm33) {\n S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;\n out[3] = (sm31 - sm13) / S;\n out[0] = (sm12 + sm21) / S;\n out[1] = 0.25 * S;\n out[2] = (sm23 + sm32) / S;\n } else {\n S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;\n out[3] = (sm12 - sm21) / S;\n out[0] = (sm31 + sm13) / S;\n out[1] = (sm23 + sm32) / S;\n out[2] = 0.25 * S;\n }\n return out;\n}\n\n/**\n * Decomposes a transformation matrix into its rotation, translation\n * and scale components. Returns only the rotation component\n * @param {quat} out_r Quaternion to receive the rotation component\n * @param {vec3} out_t Vector to receive the translation vector\n * @param {vec3} out_s Vector to receive the scaling factor\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @returns {quat} out_r\n */\nexport function decompose(out_r, out_t, out_s, mat) {\n out_t[0] = mat[12];\n out_t[1] = mat[13];\n out_t[2] = mat[14];\n var m11 = mat[0];\n var m12 = mat[1];\n var m13 = mat[2];\n var m21 = mat[4];\n var m22 = mat[5];\n var m23 = mat[6];\n var m31 = mat[8];\n var m32 = mat[9];\n var m33 = mat[10];\n out_s[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13);\n out_s[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23);\n out_s[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33);\n var is1 = 1 / out_s[0];\n var is2 = 1 / out_s[1];\n var is3 = 1 / out_s[2];\n var sm11 = m11 * is1;\n var sm12 = m12 * is2;\n var sm13 = m13 * is3;\n var sm21 = m21 * is1;\n var sm22 = m22 * is2;\n var sm23 = m23 * is3;\n var sm31 = m31 * is1;\n var sm32 = m32 * is2;\n var sm33 = m33 * is3;\n var trace = sm11 + sm22 + sm33;\n var S = 0;\n if (trace > 0) {\n S = Math.sqrt(trace + 1.0) * 2;\n out_r[3] = 0.25 * S;\n out_r[0] = (sm23 - sm32) / S;\n out_r[1] = (sm31 - sm13) / S;\n out_r[2] = (sm12 - sm21) / S;\n } else if (sm11 > sm22 && sm11 > sm33) {\n S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;\n out_r[3] = (sm23 - sm32) / S;\n out_r[0] = 0.25 * S;\n out_r[1] = (sm12 + sm21) / S;\n out_r[2] = (sm31 + sm13) / S;\n } else if (sm22 > sm33) {\n S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;\n out_r[3] = (sm31 - sm13) / S;\n out_r[0] = (sm12 + sm21) / S;\n out_r[1] = 0.25 * S;\n out_r[2] = (sm23 + sm32) / S;\n } else {\n S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;\n out_r[3] = (sm12 - sm21) / S;\n out_r[0] = (sm31 + sm13) / S;\n out_r[1] = (sm23 + sm32) / S;\n out_r[2] = 0.25 * S;\n }\n return out_r;\n}\n\n/**\n * Creates a matrix from a quaternion rotation, vector translation and vector scale\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, dest, vec);\n * let quatMat = mat4.create();\n * mat4.fromQuat(quatMat, quat);\n * mat4.multiply(dest, dest, quatMat);\n * mat4.scale(dest, dest, scale)\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @param {ReadonlyVec3} s Scaling vector\n * @returns {mat4} out\n */\nexport function fromRotationTranslationScale(out, q, v, s) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n var sx = s[0];\n var sy = s[1];\n var sz = s[2];\n out[0] = (1 - (yy + zz)) * sx;\n out[1] = (xy + wz) * sx;\n out[2] = (xz - wy) * sx;\n out[3] = 0;\n out[4] = (xy - wz) * sy;\n out[5] = (1 - (xx + zz)) * sy;\n out[6] = (yz + wx) * sy;\n out[7] = 0;\n out[8] = (xz + wy) * sz;\n out[9] = (yz - wx) * sz;\n out[10] = (1 - (xx + yy)) * sz;\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, dest, vec);\n * mat4.translate(dest, dest, origin);\n * let quatMat = mat4.create();\n * mat4.fromQuat(quatMat, quat);\n * mat4.multiply(dest, dest, quatMat);\n * mat4.scale(dest, dest, scale)\n * mat4.translate(dest, dest, negativeOrigin);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @param {ReadonlyVec3} s Scaling vector\n * @param {ReadonlyVec3} o The origin vector around which to scale and rotate\n * @returns {mat4} out\n */\nexport function fromRotationTranslationScaleOrigin(out, q, v, s, o) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n var sx = s[0];\n var sy = s[1];\n var sz = s[2];\n var ox = o[0];\n var oy = o[1];\n var oz = o[2];\n var out0 = (1 - (yy + zz)) * sx;\n var out1 = (xy + wz) * sx;\n var out2 = (xz - wy) * sx;\n var out4 = (xy - wz) * sy;\n var out5 = (1 - (xx + zz)) * sy;\n var out6 = (yz + wx) * sy;\n var out8 = (xz + wy) * sz;\n var out9 = (yz - wx) * sz;\n var out10 = (1 - (xx + yy)) * sz;\n out[0] = out0;\n out[1] = out1;\n out[2] = out2;\n out[3] = 0;\n out[4] = out4;\n out[5] = out5;\n out[6] = out6;\n out[7] = 0;\n out[8] = out8;\n out[9] = out9;\n out[10] = out10;\n out[11] = 0;\n out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);\n out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);\n out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);\n out[15] = 1;\n return out;\n}\n\n/**\n * Calculates a 4x4 matrix from the given quaternion\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyQuat} q Quaternion to create matrix from\n *\n * @returns {mat4} out\n */\nexport function fromQuat(out, q) {\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var yx = y * x2;\n var yy = y * y2;\n var zx = z * x2;\n var zy = z * y2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n out[0] = 1 - yy - zz;\n out[1] = yx + wz;\n out[2] = zx - wy;\n out[3] = 0;\n out[4] = yx - wz;\n out[5] = 1 - xx - zz;\n out[6] = zy + wx;\n out[7] = 0;\n out[8] = zx + wy;\n out[9] = zy - wx;\n out[10] = 1 - xx - yy;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Generates a frustum matrix with the given bounds\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {Number} left Left bound of the frustum\n * @param {Number} right Right bound of the frustum\n * @param {Number} bottom Bottom bound of the frustum\n * @param {Number} top Top bound of the frustum\n * @param {Number} near Near bound of the frustum\n * @param {Number} far Far bound of the frustum\n * @returns {mat4} out\n */\nexport function frustum(out, left, right, bottom, top, near, far) {\n var rl = 1 / (right - left);\n var tb = 1 / (top - bottom);\n var nf = 1 / (near - far);\n out[0] = near * 2 * rl;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = near * 2 * tb;\n out[6] = 0;\n out[7] = 0;\n out[8] = (right + left) * rl;\n out[9] = (top + bottom) * tb;\n out[10] = (far + near) * nf;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[14] = far * near * 2 * nf;\n out[15] = 0;\n return out;\n}\n\n/**\n * Generates a perspective projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],\n * which matches WebGL/OpenGL's clip volume.\n * Passing null/undefined/no value for far will generate infinite projection matrix.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} fovy Vertical field of view in radians\n * @param {number} aspect Aspect ratio. typically viewport width/height\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum, can be null or Infinity\n * @returns {mat4} out\n */\nexport function perspectiveNO(out, fovy, aspect, near, far) {\n var f = 1.0 / Math.tan(fovy / 2);\n out[0] = f / aspect;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = f;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[15] = 0;\n if (far != null && far !== Infinity) {\n var nf = 1 / (near - far);\n out[10] = (far + near) * nf;\n out[14] = 2 * far * near * nf;\n } else {\n out[10] = -1;\n out[14] = -2 * near;\n }\n return out;\n}\n\n/**\n * Alias for {@link mat4.perspectiveNO}\n * @function\n */\nexport var perspective = perspectiveNO;\n\n/**\n * Generates a perspective projection matrix suitable for WebGPU with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],\n * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.\n * Passing null/undefined/no value for far will generate infinite projection matrix.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} fovy Vertical field of view in radians\n * @param {number} aspect Aspect ratio. typically viewport width/height\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum, can be null or Infinity\n * @returns {mat4} out\n */\nexport function perspectiveZO(out, fovy, aspect, near, far) {\n var f = 1.0 / Math.tan(fovy / 2);\n out[0] = f / aspect;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = f;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[15] = 0;\n if (far != null && far !== Infinity) {\n var nf = 1 / (near - far);\n out[10] = far * nf;\n out[14] = far * near * nf;\n } else {\n out[10] = -1;\n out[14] = -near;\n }\n return out;\n}\n\n/**\n * Generates a perspective projection matrix with the given field of view.\n * This is primarily useful for generating projection matrices to be used\n * with the still experiemental WebVR API.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\nexport function perspectiveFromFieldOfView(out, fov, near, far) {\n var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);\n var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);\n var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);\n var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);\n var xScale = 2.0 / (leftTan + rightTan);\n var yScale = 2.0 / (upTan + downTan);\n out[0] = xScale;\n out[1] = 0.0;\n out[2] = 0.0;\n out[3] = 0.0;\n out[4] = 0.0;\n out[5] = yScale;\n out[6] = 0.0;\n out[7] = 0.0;\n out[8] = -((leftTan - rightTan) * xScale * 0.5);\n out[9] = (upTan - downTan) * yScale * 0.5;\n out[10] = far / (near - far);\n out[11] = -1.0;\n out[12] = 0.0;\n out[13] = 0.0;\n out[14] = far * near / (near - far);\n out[15] = 0.0;\n return out;\n}\n\n/**\n * Generates a orthogonal projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],\n * which matches WebGL/OpenGL's clip volume.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} left Left bound of the frustum\n * @param {number} right Right bound of the frustum\n * @param {number} bottom Bottom bound of the frustum\n * @param {number} top Top bound of the frustum\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\nexport function orthoNO(out, left, right, bottom, top, near, far) {\n var lr = 1 / (left - right);\n var bt = 1 / (bottom - top);\n var nf = 1 / (near - far);\n out[0] = -2 * lr;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = -2 * bt;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 2 * nf;\n out[11] = 0;\n out[12] = (left + right) * lr;\n out[13] = (top + bottom) * bt;\n out[14] = (far + near) * nf;\n out[15] = 1;\n return out;\n}\n\n/**\n * Alias for {@link mat4.orthoNO}\n * @function\n */\nexport var ortho = orthoNO;\n\n/**\n * Generates a orthogonal projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],\n * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} left Left bound of the frustum\n * @param {number} right Right bound of the frustum\n * @param {number} bottom Bottom bound of the frustum\n * @param {number} top Top bound of the frustum\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\nexport function orthoZO(out, left, right, bottom, top, near, far) {\n var lr = 1 / (left - right);\n var bt = 1 / (bottom - top);\n var nf = 1 / (near - far);\n out[0] = -2 * lr;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = -2 * bt;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = nf;\n out[11] = 0;\n out[12] = (left + right) * lr;\n out[13] = (top + bottom) * bt;\n out[14] = near * nf;\n out[15] = 1;\n return out;\n}\n\n/**\n * Generates a look-at matrix with the given eye position, focal point, and up axis.\n * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {ReadonlyVec3} eye Position of the viewer\n * @param {ReadonlyVec3} center Point the viewer is looking at\n * @param {ReadonlyVec3} up vec3 pointing up\n * @returns {mat4} out\n */\nexport function lookAt(out, eye, center, up) {\n var x0, x1, x2, y0, y1, y2, z0, z1, z2, len;\n var eyex = eye[0];\n var eyey = eye[1];\n var eyez = eye[2];\n var upx = up[0];\n var upy = up[1];\n var upz = up[2];\n var centerx = center[0];\n var centery = center[1];\n var centerz = center[2];\n if (Math.abs(eyex - centerx) < glMatrix.EPSILON && Math.abs(eyey - centery) < glMatrix.EPSILON && Math.abs(eyez - centerz) < glMatrix.EPSILON) {\n return identity(out);\n }\n z0 = eyex - centerx;\n z1 = eyey - centery;\n z2 = eyez - centerz;\n len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);\n z0 *= len;\n z1 *= len;\n z2 *= len;\n x0 = upy * z2 - upz * z1;\n x1 = upz * z0 - upx * z2;\n x2 = upx * z1 - upy * z0;\n len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);\n if (!len) {\n x0 = 0;\n x1 = 0;\n x2 = 0;\n } else {\n len = 1 / len;\n x0 *= len;\n x1 *= len;\n x2 *= len;\n }\n y0 = z1 * x2 - z2 * x1;\n y1 = z2 * x0 - z0 * x2;\n y2 = z0 * x1 - z1 * x0;\n len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);\n if (!len) {\n y0 = 0;\n y1 = 0;\n y2 = 0;\n } else {\n len = 1 / len;\n y0 *= len;\n y1 *= len;\n y2 *= len;\n }\n out[0] = x0;\n out[1] = y0;\n out[2] = z0;\n out[3] = 0;\n out[4] = x1;\n out[5] = y1;\n out[6] = z1;\n out[7] = 0;\n out[8] = x2;\n out[9] = y2;\n out[10] = z2;\n out[11] = 0;\n out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);\n out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);\n out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);\n out[15] = 1;\n return out;\n}\n\n/**\n * Generates a matrix that makes something look at something else.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {ReadonlyVec3} eye Position of the viewer\n * @param {ReadonlyVec3} target Point the viewer is looking at\n * @param {ReadonlyVec3} up vec3 pointing up\n * @returns {mat4} out\n */\nexport function targetTo(out, eye, target, up) {\n var eyex = eye[0],\n eyey = eye[1],\n eyez = eye[2],\n upx = up[0],\n upy = up[1],\n upz = up[2];\n var z0 = eyex - target[0],\n z1 = eyey - target[1],\n z2 = eyez - target[2];\n var len = z0 * z0 + z1 * z1 + z2 * z2;\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n z0 *= len;\n z1 *= len;\n z2 *= len;\n }\n var x0 = upy * z2 - upz * z1,\n x1 = upz * z0 - upx * z2,\n x2 = upx * z1 - upy * z0;\n len = x0 * x0 + x1 * x1 + x2 * x2;\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n x0 *= len;\n x1 *= len;\n x2 *= len;\n }\n out[0] = x0;\n out[1] = x1;\n out[2] = x2;\n out[3] = 0;\n out[4] = z1 * x2 - z2 * x1;\n out[5] = z2 * x0 - z0 * x2;\n out[6] = z0 * x1 - z1 * x0;\n out[7] = 0;\n out[8] = z0;\n out[9] = z1;\n out[10] = z2;\n out[11] = 0;\n out[12] = eyex;\n out[13] = eyey;\n out[14] = eyez;\n out[15] = 1;\n return out;\n}\n\n/**\n * Returns a string representation of a mat4\n *\n * @param {ReadonlyMat4} a matrix to represent as a string\n * @returns {String} string representation of the matrix\n */\nexport function str(a) {\n return \"mat4(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \", \" + a[4] + \", \" + a[5] + \", \" + a[6] + \", \" + a[7] + \", \" + a[8] + \", \" + a[9] + \", \" + a[10] + \", \" + a[11] + \", \" + a[12] + \", \" + a[13] + \", \" + a[14] + \", \" + a[15] + \")\";\n}\n\n/**\n * Returns Frobenius norm of a mat4\n *\n * @param {ReadonlyMat4} a the matrix to calculate Frobenius norm of\n * @returns {Number} Frobenius norm\n */\nexport function frob(a) {\n return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2] + a[3] * a[3] + a[4] * a[4] + a[5] * a[5] + a[6] * a[6] + a[7] * a[7] + a[8] * a[8] + a[9] * a[9] + a[10] * a[10] + a[11] * a[11] + a[12] * a[12] + a[13] * a[13] + a[14] * a[14] + a[15] * a[15]);\n}\n\n/**\n * Adds two mat4's\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\nexport function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n out[4] = a[4] + b[4];\n out[5] = a[5] + b[5];\n out[6] = a[6] + b[6];\n out[7] = a[7] + b[7];\n out[8] = a[8] + b[8];\n out[9] = a[9] + b[9];\n out[10] = a[10] + b[10];\n out[11] = a[11] + b[11];\n out[12] = a[12] + b[12];\n out[13] = a[13] + b[13];\n out[14] = a[14] + b[14];\n out[15] = a[15] + b[15];\n return out;\n}\n\n/**\n * Subtracts matrix b from matrix a\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\nexport function subtract(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n out[3] = a[3] - b[3];\n out[4] = a[4] - b[4];\n out[5] = a[5] - b[5];\n out[6] = a[6] - b[6];\n out[7] = a[7] - b[7];\n out[8] = a[8] - b[8];\n out[9] = a[9] - b[9];\n out[10] = a[10] - b[10];\n out[11] = a[11] - b[11];\n out[12] = a[12] - b[12];\n out[13] = a[13] - b[13];\n out[14] = a[14] - b[14];\n out[15] = a[15] - b[15];\n return out;\n}\n\n/**\n * Multiply each element of the matrix by a scalar.\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to scale\n * @param {Number} b amount to scale the matrix's elements by\n * @returns {mat4} out\n */\nexport function multiplyScalar(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n out[3] = a[3] * b;\n out[4] = a[4] * b;\n out[5] = a[5] * b;\n out[6] = a[6] * b;\n out[7] = a[7] * b;\n out[8] = a[8] * b;\n out[9] = a[9] * b;\n out[10] = a[10] * b;\n out[11] = a[11] * b;\n out[12] = a[12] * b;\n out[13] = a[13] * b;\n out[14] = a[14] * b;\n out[15] = a[15] * b;\n return out;\n}\n\n/**\n * Adds two mat4's after multiplying each element of the second operand by a scalar value.\n *\n * @param {mat4} out the receiving vector\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @param {Number} scale the amount to scale b's elements by before adding\n * @returns {mat4} out\n */\nexport function multiplyScalarAndAdd(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n out[3] = a[3] + b[3] * scale;\n out[4] = a[4] + b[4] * scale;\n out[5] = a[5] + b[5] * scale;\n out[6] = a[6] + b[6] * scale;\n out[7] = a[7] + b[7] * scale;\n out[8] = a[8] + b[8] * scale;\n out[9] = a[9] + b[9] * scale;\n out[10] = a[10] + b[10] * scale;\n out[11] = a[11] + b[11] * scale;\n out[12] = a[12] + b[12] * scale;\n out[13] = a[13] + b[13] * scale;\n out[14] = a[14] + b[14] * scale;\n out[15] = a[15] + b[15] * scale;\n return out;\n}\n\n/**\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyMat4} a The first matrix.\n * @param {ReadonlyMat4} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\nexport function exactEquals(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];\n}\n\n/**\n * Returns whether or not the matrices have approximately the same elements in the same position.\n *\n * @param {ReadonlyMat4} a The first matrix.\n * @param {ReadonlyMat4} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\nexport function equals(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3];\n var a4 = a[4],\n a5 = a[5],\n a6 = a[6],\n a7 = a[7];\n var a8 = a[8],\n a9 = a[9],\n a10 = a[10],\n a11 = a[11];\n var a12 = a[12],\n a13 = a[13],\n a14 = a[14],\n a15 = a[15];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n var b4 = b[4],\n b5 = b[5],\n b6 = b[6],\n b7 = b[7];\n var b8 = b[8],\n b9 = b[9],\n b10 = b[10],\n b11 = b[11];\n var b12 = b[12],\n b13 = b[13],\n b14 = b[14],\n b15 = b[15];\n return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && Math.abs(a9 - b9) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && Math.abs(a10 - b10) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && Math.abs(a11 - b11) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && Math.abs(a12 - b12) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && Math.abs(a13 - b13) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && Math.abs(a14 - b14) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && Math.abs(a15 - b15) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15));\n}\n\n/**\n * Alias for {@link mat4.multiply}\n * @function\n */\nexport var mul = multiply;\n\n/**\n * Alias for {@link mat4.subtract}\n * @function\n */\nexport var sub = subtract;","import * as glMatrix from \"./common.js\";\n\n/**\n * 3 Dimensional Vector\n * @module vec3\n */\n\n/**\n * Creates a new, empty vec3\n *\n * @returns {vec3} a new 3D vector\n */\nexport function create() {\n var out = new glMatrix.ARRAY_TYPE(3);\n if (glMatrix.ARRAY_TYPE != Float32Array) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n }\n return out;\n}\n\n/**\n * Creates a new vec3 initialized with values from an existing vector\n *\n * @param {ReadonlyVec3} a vector to clone\n * @returns {vec3} a new 3D vector\n */\nexport function clone(a) {\n var out = new glMatrix.ARRAY_TYPE(3);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n return out;\n}\n\n/**\n * Calculates the length of a vec3\n *\n * @param {ReadonlyVec3} a vector to calculate length of\n * @returns {Number} length of a\n */\nexport function length(a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n return Math.sqrt(x * x + y * y + z * z);\n}\n\n/**\n * Creates a new vec3 initialized with the given values\n *\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @returns {vec3} a new 3D vector\n */\nexport function fromValues(x, y, z) {\n var out = new glMatrix.ARRAY_TYPE(3);\n out[0] = x;\n out[1] = y;\n out[2] = z;\n return out;\n}\n\n/**\n * Copy the values from one vec3 to another\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the source vector\n * @returns {vec3} out\n */\nexport function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n return out;\n}\n\n/**\n * Set the components of a vec3 to the given values\n *\n * @param {vec3} out the receiving vector\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @returns {vec3} out\n */\nexport function set(out, x, y, z) {\n out[0] = x;\n out[1] = y;\n out[2] = z;\n return out;\n}\n\n/**\n * Adds two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n return out;\n}\n\n/**\n * Subtracts vector b from vector a\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function subtract(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n return out;\n}\n\n/**\n * Multiplies two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function multiply(out, a, b) {\n out[0] = a[0] * b[0];\n out[1] = a[1] * b[1];\n out[2] = a[2] * b[2];\n return out;\n}\n\n/**\n * Divides two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function divide(out, a, b) {\n out[0] = a[0] / b[0];\n out[1] = a[1] / b[1];\n out[2] = a[2] / b[2];\n return out;\n}\n\n/**\n * Math.ceil the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to ceil\n * @returns {vec3} out\n */\nexport function ceil(out, a) {\n out[0] = Math.ceil(a[0]);\n out[1] = Math.ceil(a[1]);\n out[2] = Math.ceil(a[2]);\n return out;\n}\n\n/**\n * Math.floor the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to floor\n * @returns {vec3} out\n */\nexport function floor(out, a) {\n out[0] = Math.floor(a[0]);\n out[1] = Math.floor(a[1]);\n out[2] = Math.floor(a[2]);\n return out;\n}\n\n/**\n * Returns the minimum of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function min(out, a, b) {\n out[0] = Math.min(a[0], b[0]);\n out[1] = Math.min(a[1], b[1]);\n out[2] = Math.min(a[2], b[2]);\n return out;\n}\n\n/**\n * Returns the maximum of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function max(out, a, b) {\n out[0] = Math.max(a[0], b[0]);\n out[1] = Math.max(a[1], b[1]);\n out[2] = Math.max(a[2], b[2]);\n return out;\n}\n\n/**\n * symmetric round the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to round\n * @returns {vec3} out\n */\nexport function round(out, a) {\n out[0] = glMatrix.round(a[0]);\n out[1] = glMatrix.round(a[1]);\n out[2] = glMatrix.round(a[2]);\n return out;\n}\n\n/**\n * Scales a vec3 by a scalar number\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to scale\n * @param {Number} b amount to scale the vector by\n * @returns {vec3} out\n */\nexport function scale(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n return out;\n}\n\n/**\n * Adds two vec3's after scaling the second operand by a scalar value\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {Number} scale the amount to scale b by before adding\n * @returns {vec3} out\n */\nexport function scaleAndAdd(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n return out;\n}\n\n/**\n * Calculates the euclidian distance between two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} distance between a and b\n */\nexport function distance(a, b) {\n var x = b[0] - a[0];\n var y = b[1] - a[1];\n var z = b[2] - a[2];\n return Math.sqrt(x * x + y * y + z * z);\n}\n\n/**\n * Calculates the squared euclidian distance between two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} squared distance between a and b\n */\nexport function squaredDistance(a, b) {\n var x = b[0] - a[0];\n var y = b[1] - a[1];\n var z = b[2] - a[2];\n return x * x + y * y + z * z;\n}\n\n/**\n * Calculates the squared length of a vec3\n *\n * @param {ReadonlyVec3} a vector to calculate squared length of\n * @returns {Number} squared length of a\n */\nexport function squaredLength(a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n return x * x + y * y + z * z;\n}\n\n/**\n * Negates the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to negate\n * @returns {vec3} out\n */\nexport function negate(out, a) {\n out[0] = -a[0];\n out[1] = -a[1];\n out[2] = -a[2];\n return out;\n}\n\n/**\n * Returns the inverse of the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to invert\n * @returns {vec3} out\n */\nexport function inverse(out, a) {\n out[0] = 1.0 / a[0];\n out[1] = 1.0 / a[1];\n out[2] = 1.0 / a[2];\n return out;\n}\n\n/**\n * Normalize a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to normalize\n * @returns {vec3} out\n */\nexport function normalize(out, a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n var len = x * x + y * y + z * z;\n if (len > 0) {\n //TODO: evaluate use of glm_invsqrt here?\n len = 1 / Math.sqrt(len);\n }\n out[0] = a[0] * len;\n out[1] = a[1] * len;\n out[2] = a[2] * len;\n return out;\n}\n\n/**\n * Calculates the dot product of two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} dot product of a and b\n */\nexport function dot(a, b) {\n return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\n}\n\n/**\n * Computes the cross product of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function cross(out, a, b) {\n var ax = a[0],\n ay = a[1],\n az = a[2];\n var bx = b[0],\n by = b[1],\n bz = b[2];\n out[0] = ay * bz - az * by;\n out[1] = az * bx - ax * bz;\n out[2] = ax * by - ay * bx;\n return out;\n}\n\n/**\n * Performs a linear interpolation between two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\nexport function lerp(out, a, b, t) {\n var ax = a[0];\n var ay = a[1];\n var az = a[2];\n out[0] = ax + t * (b[0] - ax);\n out[1] = ay + t * (b[1] - ay);\n out[2] = az + t * (b[2] - az);\n return out;\n}\n\n/**\n * Performs a spherical linear interpolation between two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\nexport function slerp(out, a, b, t) {\n var angle = Math.acos(Math.min(Math.max(dot(a, b), -1), 1));\n var sinTotal = Math.sin(angle);\n var ratioA = Math.sin((1 - t) * angle) / sinTotal;\n var ratioB = Math.sin(t * angle) / sinTotal;\n out[0] = ratioA * a[0] + ratioB * b[0];\n out[1] = ratioA * a[1] + ratioB * b[1];\n out[2] = ratioA * a[2] + ratioB * b[2];\n return out;\n}\n\n/**\n * Performs a hermite interpolation with two control points\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {ReadonlyVec3} c the third operand\n * @param {ReadonlyVec3} d the fourth operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\nexport function hermite(out, a, b, c, d, t) {\n var factorTimes2 = t * t;\n var factor1 = factorTimes2 * (2 * t - 3) + 1;\n var factor2 = factorTimes2 * (t - 2) + t;\n var factor3 = factorTimes2 * (t - 1);\n var factor4 = factorTimes2 * (3 - 2 * t);\n out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n return out;\n}\n\n/**\n * Performs a bezier interpolation with two control points\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {ReadonlyVec3} c the third operand\n * @param {ReadonlyVec3} d the fourth operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\nexport function bezier(out, a, b, c, d, t) {\n var inverseFactor = 1 - t;\n var inverseFactorTimesTwo = inverseFactor * inverseFactor;\n var factorTimes2 = t * t;\n var factor1 = inverseFactorTimesTwo * inverseFactor;\n var factor2 = 3 * t * inverseFactorTimesTwo;\n var factor3 = 3 * factorTimes2 * inverseFactor;\n var factor4 = factorTimes2 * t;\n out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n return out;\n}\n\n/**\n * Generates a random vector with the given scale\n *\n * @param {vec3} out the receiving vector\n * @param {Number} [scale] Length of the resulting vector. If omitted, a unit vector will be returned\n * @returns {vec3} out\n */\nexport function random(out, scale) {\n scale = scale === undefined ? 1.0 : scale;\n var r = glMatrix.RANDOM() * 2.0 * Math.PI;\n var z = glMatrix.RANDOM() * 2.0 - 1.0;\n var zScale = Math.sqrt(1.0 - z * z) * scale;\n out[0] = Math.cos(r) * zScale;\n out[1] = Math.sin(r) * zScale;\n out[2] = z * scale;\n return out;\n}\n\n/**\n * Transforms the vec3 with a mat4.\n * 4th vector component is implicitly '1'\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyMat4} m matrix to transform with\n * @returns {vec3} out\n */\nexport function transformMat4(out, a, m) {\n var x = a[0],\n y = a[1],\n z = a[2];\n var w = m[3] * x + m[7] * y + m[11] * z + m[15];\n w = w || 1.0;\n out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;\n out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;\n out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;\n return out;\n}\n\n/**\n * Transforms the vec3 with a mat3.\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyMat3} m the 3x3 matrix to transform with\n * @returns {vec3} out\n */\nexport function transformMat3(out, a, m) {\n var x = a[0],\n y = a[1],\n z = a[2];\n out[0] = x * m[0] + y * m[3] + z * m[6];\n out[1] = x * m[1] + y * m[4] + z * m[7];\n out[2] = x * m[2] + y * m[5] + z * m[8];\n return out;\n}\n\n/**\n * Transforms the vec3 with a quat\n * Can also be used for dual quaternions. (Multiply it with the real part)\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyQuat} q normalized quaternion to transform with\n * @returns {vec3} out\n */\nexport function transformQuat(out, a, q) {\n // Fast Vector Rotation using Quaternions by Robert Eisele\n // https://raw.org/proof/vector-rotation-using-quaternions/\n\n var qx = q[0],\n qy = q[1],\n qz = q[2],\n qw = q[3];\n var vx = a[0],\n vy = a[1],\n vz = a[2];\n\n // t = q x v\n var tx = qy * vz - qz * vy;\n var ty = qz * vx - qx * vz;\n var tz = qx * vy - qy * vx;\n\n // t = 2t\n tx = tx + tx;\n ty = ty + ty;\n tz = tz + tz;\n\n // v + w t + q x t\n out[0] = vx + qw * tx + qy * tz - qz * ty;\n out[1] = vy + qw * ty + qz * tx - qx * tz;\n out[2] = vz + qw * tz + qx * ty - qy * tx;\n return out;\n}\n\n/**\n * Rotate a 3D vector around the x-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\nexport function rotateX(out, a, b, rad) {\n var p = [],\n r = [];\n //Translate point to the origin\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2];\n\n //perform rotation\n r[0] = p[0];\n r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);\n r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad);\n\n //translate to correct position\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n\n/**\n * Rotate a 3D vector around the y-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\nexport function rotateY(out, a, b, rad) {\n var p = [],\n r = [];\n //Translate point to the origin\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2];\n\n //perform rotation\n r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);\n r[1] = p[1];\n r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad);\n\n //translate to correct position\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n\n/**\n * Rotate a 3D vector around the z-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\nexport function rotateZ(out, a, b, rad) {\n var p = [],\n r = [];\n //Translate point to the origin\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2];\n\n //perform rotation\n r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);\n r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);\n r[2] = p[2];\n\n //translate to correct position\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n\n/**\n * Get the angle between two 3D vectors\n * @param {ReadonlyVec3} a The first operand\n * @param {ReadonlyVec3} b The second operand\n * @returns {Number} The angle in radians\n */\nexport function angle(a, b) {\n var ax = a[0],\n ay = a[1],\n az = a[2],\n bx = b[0],\n by = b[1],\n bz = b[2],\n mag = Math.sqrt((ax * ax + ay * ay + az * az) * (bx * bx + by * by + bz * bz)),\n cosine = mag && dot(a, b) / mag;\n return Math.acos(Math.min(Math.max(cosine, -1), 1));\n}\n\n/**\n * Set the components of a vec3 to zero\n *\n * @param {vec3} out the receiving vector\n * @returns {vec3} out\n */\nexport function zero(out) {\n out[0] = 0.0;\n out[1] = 0.0;\n out[2] = 0.0;\n return out;\n}\n\n/**\n * Returns a string representation of a vector\n *\n * @param {ReadonlyVec3} a vector to represent as a string\n * @returns {String} string representation of the vector\n */\nexport function str(a) {\n return \"vec3(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \")\";\n}\n\n/**\n * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyVec3} a The first vector.\n * @param {ReadonlyVec3} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\nexport function exactEquals(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];\n}\n\n/**\n * Returns whether or not the vectors have approximately the same elements in the same position.\n *\n * @param {ReadonlyVec3} a The first vector.\n * @param {ReadonlyVec3} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\nexport function equals(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2];\n return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2));\n}\n\n/**\n * Alias for {@link vec3.subtract}\n * @function\n */\nexport var sub = subtract;\n\n/**\n * Alias for {@link vec3.multiply}\n * @function\n */\nexport var mul = multiply;\n\n/**\n * Alias for {@link vec3.divide}\n * @function\n */\nexport var div = divide;\n\n/**\n * Alias for {@link vec3.distance}\n * @function\n */\nexport var dist = distance;\n\n/**\n * Alias for {@link vec3.squaredDistance}\n * @function\n */\nexport var sqrDist = squaredDistance;\n\n/**\n * Alias for {@link vec3.length}\n * @function\n */\nexport var len = length;\n\n/**\n * Alias for {@link vec3.squaredLength}\n * @function\n */\nexport var sqrLen = squaredLength;\n\n/**\n * Perform some operation over an array of vec3s.\n *\n * @param {Array} a the array of vectors to iterate over\n * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed\n * @param {Number} offset Number of elements to skip at the beginning of the array\n * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array\n * @param {Function} fn Function to call for each vector in the array\n * @param {Object} [arg] additional argument to pass to fn\n * @returns {Array} a\n * @function\n */\nexport var forEach = function () {\n var vec = create();\n return function (a, stride, offset, count, fn, arg) {\n var i, l;\n if (!stride) {\n stride = 3;\n }\n if (!offset) {\n offset = 0;\n }\n if (count) {\n l = Math.min(count * stride + offset, a.length);\n } else {\n l = a.length;\n }\n for (i = offset; i < l; i += stride) {\n vec[0] = a[i];\n vec[1] = a[i + 1];\n vec[2] = a[i + 2];\n fn(vec, vec, arg);\n a[i] = vec[0];\n a[i + 1] = vec[1];\n a[i + 2] = vec[2];\n }\n return a;\n };\n}();","/**\n * @module Camera\n * Interactive camera primitives for WebGPU scene navigation.\n *\n * This module defines the `Camera` class, which keeps the current eye,\n * look-at, and up vectors in sync with view and projection matrices. It also\n * exposes a one-shot helper for building view-projection matrices from\n * explicit parameters when a persistent camera instance is not needed.\n */\n\nimport { vec3, mat4 } from 'gl-matrix';\n\n/**\n * Initial camera state used to seed or reset a `Camera` instance.\n */\nexport interface CameraData {\n /** World-space up vector. */\n up: number[];\n /** Initial eye (camera) position in world space. */\n eye: number[];\n /** Point the camera looks at in world space. */\n lookAt: number[];\n}\n\n/**\n * Explicit parameters for building a single view-projection matrix.\n */\nexport interface ViewProjectionParams {\n /** Eye (camera) position in world space. */\n eye: [number, number, number];\n /** Point the camera looks at in world space. */\n lookAt: [number, number, number];\n /** World-space up vector. */\n up: [number, number, number];\n /** Vertical field of view in degrees. */\n fovDeg: number;\n /** Viewport aspect ratio (width / height). */\n aspect: number;\n /** Near clipping plane distance. */\n near: number;\n /** Far clipping plane distance. */\n far: number;\n}\n\n/**\n * Interactive 3-DOF camera for orbit-style navigation.\n *\n * The camera tracks world-space eye, look-at, and up vectors together with the\n * current viewport size. Call the navigation methods to adjust state, then\n * call {@link Camera.update} to rebuild the matrices. Projection uses\n * reversed-Z depth mapping for improved precision at distance.\n *\n * @example\n * const camera = new Camera();\n * camera.resize(width, height);\n * camera.zoom(-1, 0.5, 0.5);\n * camera.update();\n */\nexport class Camera {\n /** Eye (camera) position in world space. */\n protected wEye: vec3 = vec3.create();\n /** Look-at target in world space. */\n protected wLookAt: vec3 = vec3.create();\n /** Normalised direction vector from eye to look-at. */\n protected wEyeDir: vec3 = vec3.create();\n /** World-space up vector. */\n protected wUp: vec3 = vec3.create();\n /** Near clipping plane distance. */\n protected wNear: number = 0;\n /** Far clipping plane distance. */\n protected wFar: number = 0;\n /** Vertical field of view in radians. */\n protected fovy = (45 * Math.PI) / 180.0;\n /** Current projection matrix. */\n protected mProjectionMatrix: mat4 = mat4.create();\n /** Current view matrix. */\n protected mViewMatrix: mat4 = mat4.create();\n private viewportWidth: number = 0;\n private viewportHeight: number = 0;\n\n private static defaultParams: CameraData = {\n up: [0, 1, 0],\n eye: [0, 0, 10000],\n lookAt: [0, 0, 0],\n };\n\n /**\n * Creates a camera with the provided initial state.\n *\n * @param params - Initial camera position and orientation (defaults to `[0, 1, 0]` up, 10k units above origin).\n * @throws Never throws.\n * @example\n * const camera = new Camera();\n * const custom = new Camera({ eye: [0, 0, 500], lookAt: [0, 0, 0], up: [0, 1, 0] });\n */\n constructor(params: CameraData = Camera.defaultParams) {\n this.resetCamera(params.up, params.lookAt, params.eye);\n }\n\n /**\n * Resets the camera to a new position, orientation, and default projection.\n *\n * @param wUp - World-space up vector.\n * @param wLookAt - Point to look at in world space.\n * @param wEye - Eye position in world space.\n * @throws Never throws.\n * @example\n * camera.resetCamera([0, 1, 0], [100, 200, 0], [100, 200, 500]);\n * camera.update();\n */\n public resetCamera(wUp: number[], wLookAt: number[], wEye: number[]): void {\n this.fovy = (45 * Math.PI) / 180.0;\n this.mProjectionMatrix = mat4.create();\n this.mViewMatrix = mat4.create();\n this.wNear = 1;\n this.wFar = 5e5;\n this.wLookAt = vec3.fromValues(wLookAt[0], wLookAt[1], wLookAt[2]);\n this.wEye = vec3.fromValues(wEye[0], wEye[1], wEye[2]);\n this.updateEyeDirAndLen();\n this.wUp = vec3.fromValues(wUp[0], wUp[1], wUp[2]);\n }\n\n /**\n * Returns the current projection matrix.\n *\n * @returns The projection matrix in column-major `mat4`.\n * @throws Never throws.\n * @example\n * camera.update();\n * const proj = camera.getProjectionMatrix();\n */\n public getProjectionMatrix(): mat4 {\n return this.mProjectionMatrix;\n }\n\n /**\n * Returns the current view (model-view) matrix.\n *\n * @returns The view matrix in column-major `mat4`.\n * @throws Never throws.\n * @example\n * camera.update();\n * const view = camera.getModelViewMatrix();\n */\n public getModelViewMatrix(): mat4 {\n return this.mViewMatrix;\n }\n\n /**\n * Updates viewport size and recomputes matrices in one call.\n *\n * Pass drawable canvas pixel size, not CSS size.\n *\n * @param width - Viewport width in pixels.\n * @param height - Viewport height in pixels.\n * @throws Never throws.\n * @example\n * camera.resize(1920, 1080); // calls update() internally\n */\n public resize(width: number, height: number): void {\n this.viewportWidth = width;\n this.viewportHeight = height;\n this.update();\n }\n\n /**\n * Zooms the camera at the cursor position, preserving it in world space.\n *\n * @param delta - Normalized scroll delta (positive = zoom out, negative = zoom in).\n * @param x - Normalized cursor X position (0–1, left to right).\n * @param y - Normalized cursor Y position (0–1, bottom to top).\n * @throws Never throws.\n * @example\n * camera.zoom(-1, 0.5, 0.5); // zoom in at screen center\n * camera.update();\n */\n public zoom(delta: number, x: number, y: number): void {\n const zoomScale = Math.max(Math.abs(this.wEye[2]), 1) * 0.2;\n delta = -delta * zoomScale;\n const dir = this.screenCoordToWorldDir(x, y);\n vec3.scaleAndAdd(this.wEye, this.wEye, dir, delta);\n vec3.scaleAndAdd(this.wLookAt, this.wEye, this.wEyeDir, vec3.length(this.wEyeDir));\n }\n\n /**\n * Pans the camera in screen space, scaled by the current view distance.\n *\n * @param dx - Normalized horizontal drag delta (0–1).\n * @param dy - Normalized vertical drag delta (0–1).\n * @throws Never throws.\n * @example\n * camera.translate(0.1, 0); // pan right\n * camera.update();\n */\n public translate(dx: number, dy: number): void {\n const scale = this.wEye[2];\n const X = vec3.create();\n vec3.normalize(X, vec3.cross(X, this.wEyeDir, this.wUp));\n const D = vec3.add(\n vec3.create(),\n vec3.scale(vec3.create(), X, dx * scale),\n vec3.scale(vec3.create(), this.wUp, dy * scale),\n );\n vec3.add(this.wEye, this.wEye, D);\n vec3.scaleAndAdd(this.wLookAt, this.wEye, this.wEyeDir, vec3.length(this.wEyeDir));\n }\n\n /**\n * Rotates the camera around the world Z-axis (compass bearing).\n *\n * @param delta - Rotation angle in radians.\n * @throws Never throws.\n * @example\n * camera.yaw(Math.PI / 4); // rotate 45° clockwise\n * camera.update();\n */\n public yaw(delta: number): void {\n vec3.rotateZ(this.wEyeDir, this.wEyeDir, vec3.fromValues(0, 0, 0), delta);\n vec3.rotateZ(this.wUp, this.wUp, vec3.fromValues(0, 0, 0), delta);\n vec3.scaleAndAdd(this.wLookAt, this.wEye, this.wEyeDir, vec3.length(this.wEyeDir));\n }\n\n /**\n * Tilts the camera up or down (elevation angle).\n *\n * @param delta - Tilt angle in radians. Positive values tilt upward.\n * @throws Never throws.\n * @example\n * camera.pitch(-0.3); // tilt downward ~17°\n * camera.update();\n */\n public pitch(delta: number): void {\n delta = -delta;\n vec3.add(\n this.wEyeDir,\n vec3.scale(vec3.create(), this.wUp, Math.sin(delta)),\n vec3.scale(vec3.create(), this.wEyeDir, Math.cos(delta)),\n );\n vec3.normalize(this.wEyeDir, this.wEyeDir);\n vec3.scaleAndAdd(this.wLookAt, this.wEye, this.wEyeDir, vec3.length(this.wEyeDir));\n vec3.cross(this.wUp, vec3.cross(vec3.create(), this.wEyeDir, this.wUp), this.wEyeDir);\n vec3.normalize(this.wUp, this.wUp);\n }\n\n /**\n * Rebuilds view and projection matrices from the current camera state.\n *\n * Uses reversed-Z depth for improved precision at long range.\n *\n * @throws Never throws.\n * @example\n * camera.zoom(-1, 0.5, 0.5);\n * camera.update(); // rebuild matrices after navigation change\n */\n public update(): void {\n const aspect = this.viewportWidth / this.viewportHeight;\n mat4.lookAt(this.mViewMatrix, this.wEye, this.wLookAt, this.wUp);\n // Reversed-Z: swap near/far so near→1 and far→0 in NDC.\n // Combined with depthClearValue=0 and depthCompare='greater-equal' this\n // distributes float32 precision logarithmically, eliminating z-fighting\n // at distance without requiring an absurdly large far plane.\n mat4.perspectiveZO(this.mProjectionMatrix, this.fovy, aspect, this.wFar, this.wNear);\n }\n\n /**\n * Builds a stateless view-projection matrix from explicit parameters.\n *\n * @param p - Camera and projection parameters.\n * @returns Column-major `Float32Array` of length 16.\n * @throws Never throws.\n * @example\n * const vp = Camera.buildViewProjection({\n * eye: [0, 0, 500], lookAt: [0, 0, 0], up: [0, 1, 0],\n * fovDeg: 45, aspect: 16/9, near: 0.1, far: 10000,\n * });\n */\n public static buildViewProjection(p: ViewProjectionParams): Float32Array {\n const view = mat4.lookAt(mat4.create(), p.eye, p.lookAt, p.up);\n const proj = mat4.perspectiveZO(mat4.create(), p.fovDeg * (Math.PI / 180), p.aspect, p.near, p.far);\n return new Float32Array(mat4.mul(mat4.create(), proj, view));\n }\n\n /**\n * Converts a normalized screen coordinate to a world-space direction ray.\n *\n * @param x - Normalized screen X (0–1, left to right).\n * @param y - Normalized screen Y (0–1, bottom to top).\n * @returns Normalized direction vector in world space.\n * @throws Never throws.\n */\n protected screenCoordToWorldDir(x: number, y: number): vec3 {\n const wRight = vec3.create();\n vec3.normalize(wRight, vec3.cross(wRight, this.wEyeDir, this.wUp));\n const upOffset = vec3.scale(vec3.create(), this.wUp, Math.tan(this.fovy / 2) * (y - 0.5) * 2);\n const aspect = this.viewportWidth / this.viewportHeight;\n const rightOffset = vec3.scale(vec3.create(), wRight, Math.tan(this.fovy / 2) * (x - 0.5) * 2 * aspect);\n const offset = vec3.add(vec3.create(), upOffset, rightOffset);\n const dir = vec3.add(vec3.create(), this.wEyeDir, offset);\n vec3.normalize(dir, dir);\n return dir;\n }\n\n /**\n * Recomputes the normalized eye direction from current eye and look-at.\n *\n * @throws Never throws.\n */\n protected updateEyeDirAndLen(): void {\n this.wEyeDir = vec3.create();\n vec3.sub(this.wEyeDir, this.wLookAt, this.wEye);\n vec3.normalize(this.wEyeDir, this.wEyeDir);\n }\n}\n","/**\n * @module LayerUtils\n * Shared helpers for the toolkit's layer taxonomy.\n *\n * This module centralizes the canonical `LayerType` guard and the GeoJSON\n * geometry classification used by layer-loading code. It keeps layer identity\n * checks and geometry-to-layer inference consistent across packages that share\n * the same taxonomy.\n */\nimport type { Geometry } from 'geojson';\n\nimport type { LayerType } from './types-layer';\n\n/**\n * Type guard checking whether a string is a supported shared layer type.\n *\n * @param value Candidate layer identifier to validate.\n * @returns `true` when `value` is a recognized `LayerType`, narrowing the type.\n * @throws Never throws.\n * @example\n * if (isLayerType(userInput)) {\n * // userInput is now typed as LayerType\n * }\n */\nexport function isLayerType(value: string): value is LayerType {\n return value === 'surface'\n || value === 'water'\n || value === 'parks'\n || value === 'roads'\n || value === 'buildings'\n || value === 'points'\n || value === 'polygons'\n || value === 'polylines'\n || value === 'raster';\n}\n\n/**\n * Maps a GeoJSON geometry type to the corresponding shared layer family.\n *\n * @param geometryType GeoJSON geometry type to classify.\n * @returns One of `points`, `polylines`, or `polygons`.\n * @throws Never throws.\n * @example\n * mapGeometryTypeToLayerType('Polygon'); // 'polygons'\n * mapGeometryTypeToLayerType('Point'); // 'points'\n */\nexport function mapGeometryTypeToLayerType(\n geometryType: Geometry['type'],\n): Extract<LayerType, 'points' | 'polygons' | 'polylines'> {\n switch (geometryType) {\n case 'Point':\n case 'MultiPoint':\n return 'points';\n case 'LineString':\n case 'MultiLineString':\n return 'polylines';\n case 'Polygon':\n case 'MultiPolygon':\n case 'GeometryCollection':\n return 'polygons';\n }\n}\n","import { BoundingBox } from '../../../shared/interfaces';\n\nexport const LOAD_FEATURE_COLLECTION_QUERY = (geojsonFileUrl: string, featureCollectionTableName: string, workspace: string) => {\n const qualifiedTableName = `${workspace}.${featureCollectionTableName}`;\n return `\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT * FROM read_json('${geojsonFileUrl}', maximum_object_size=104857600);\n `;\n};\n\n// TODO: update this name columns, its not linestring (i just do not want to break pattern right now)\nexport const LOAD_LAYER_FROM_FEATURE_COLLECTION_QUERY = (\n featureCollectionTableName: string,\n outputTableName: string,\n coordinateFormat: string,\n workspace: string,\n boundingBox?: BoundingBox,\n) => {\n const qualifiedFeatureCollectionTableName = `${workspace}.${featureCollectionTableName}`;\n const qualifiedOutputTableName = `${workspace}.${outputTableName}`;\n \n const geometryTransform = `ST_Transform(\n ST_GeomFromGeoJSON(JSON(feature.geometry)),\n 'EPSG:4326',\n '${coordinateFormat}',\n always_xy := true\n )`;\n\n const geometrySelect = boundingBox\n ? `ST_Intersection(\n ${geometryTransform},\n ST_MakeEnvelope(${boundingBox.minLon}, ${boundingBox.minLat}, ${boundingBox.maxLon}, ${boundingBox.maxLat})\n )`\n : geometryTransform;\n\n return `\n CREATE OR REPLACE TABLE ${qualifiedOutputTableName} AS\n SELECT\n row_number() OVER () AS id,\n ${geometrySelect} AS geometry,\n feature.properties AS properties\n FROM (\n SELECT UNNEST(features) AS feature\n FROM ${qualifiedFeatureCollectionTableName}\n )\n ${boundingBox ? 'WHERE ST_Intersects(' + geometryTransform + ', ST_MakeEnvelope(' + boundingBox.minLon + ', ' + boundingBox.minLat + ', ' + boundingBox.maxLon + ', ' + boundingBox.maxLat + '))' : ''};\n\n DROP TABLE ${qualifiedFeatureCollectionTableName};\n\n DESCRIBE ${qualifiedOutputTableName};\n `;\n};\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { CustomLayerTable } from '../../../shared/interfaces';\nimport { LoadCustomLayerParams } from './interfaces';\nimport { DEFALT_COORDINATE_FORMAT } from '../../../shared/consts';\nimport { LOAD_FEATURE_COLLECTION_QUERY, LOAD_LAYER_FROM_FEATURE_COLLECTION_QUERY } from './queries';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport { FeatureCollection } from 'geojson';\nimport { BoundingBox } from '../../../shared/interfaces';\nimport { mapGeometryTypeToLayerType } from 'autk-core';\n\n/**\n * Loads a GeoJSON FeatureCollection as a spatial layer table.\n */\nexport class LoadCustomLayerUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n }\n\n async exec({\n geojsonFileUrl,\n geojsonObject,\n outputTableName,\n coordinateFormat = DEFALT_COORDINATE_FORMAT,\n boundingBox,\n workspace = 'main',\n layerType,\n }: LoadCustomLayerParams): Promise<CustomLayerTable> {\n if (!geojsonFileUrl && !geojsonObject) {\n throw new Error('Either geojsonFileUrl or geojsonObject must be provided');\n }\n if (geojsonFileUrl && geojsonObject) {\n throw new Error('Cannot provide both geojsonFileUrl and geojsonObject. Please provide only one.');\n }\n\n let geojson: FeatureCollection;\n\n if (geojsonFileUrl) {\n const response = await fetch(geojsonFileUrl);\n if (!response.ok) {\n throw new Error(`HTTP error! Error to load ${geojsonFileUrl}! Status: ${response.status}`);\n }\n geojson = await response.json();\n } else {\n geojson = geojsonObject!;\n }\n\n if (geojson.type !== 'FeatureCollection') {\n throw new Error(`Invalid GeoJSON type! Just accepting FeatureCollection for now!`);\n }\n\n // Extract geometry type from the first feature\n if (!geojson.features || geojson.features.length === 0) {\n throw new Error('FeatureCollection is empty - no features found');\n }\n\n const firstFeature = geojson.features[0];\n if (!firstFeature.geometry || !firstFeature.geometry.type) {\n throw new Error('First feature has no geometry or geometry type');\n }\n\n const geometryType = layerType ?? mapGeometryTypeToLayerType(firstFeature.geometry.type);\n\n const describeTableResponse = await this.createTableFromFeatureCollection(\n geojson,\n outputTableName,\n coordinateFormat,\n workspace,\n boundingBox,\n );\n\n return {\n source: 'geojson',\n type: geometryType,\n columns: getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray()),\n name: outputTableName,\n };\n }\n\n private async createTableFromFeatureCollection(\n geojson: FeatureCollection,\n outputTableName: string,\n coordinateFormat: string,\n workspace: string,\n boundingBox?: BoundingBox,\n ) {\n // Create temporary file with GeoJSON data\n const fileName = `temp_geojson_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.json`;\n\n // Register the GeoJSON as a temporary file in DuckDB\n await this.db.registerFileText(fileName, JSON.stringify(geojson));\n\n // Create feature collection table from the temporary file\n const featureCollectionQuery = LOAD_FEATURE_COLLECTION_QUERY(fileName, `${outputTableName}_feature_collection`, workspace);\n await this.conn.query(featureCollectionQuery);\n\n // Create the final layer table\n const queryLayer = LOAD_LAYER_FROM_FEATURE_COLLECTION_QUERY(\n `${outputTableName}_feature_collection`,\n outputTableName,\n coordinateFormat,\n workspace,\n boundingBox,\n );\n\n await this.db.dropFile(fileName);\n\n return await this.conn.query(queryLayer);\n }\n}\n","/** Custom error types for spatial join operations. */\n\nexport class TableNotFoundError extends Error {\n constructor(tableName: string) {\n super(`Table ${tableName} not found`);\n this.name = 'TableNotFoundError';\n }\n}\n\nexport class GeometryColumnNotFoundError extends Error {\n constructor(tableName: string) {\n super(`Table ${tableName} does not have a geometry column`);\n this.name = 'GeometryColumnNotFoundError';\n }\n}\n","import { Table } from '../../../shared/interfaces';\nimport { isLayerType } from 'autk-core';\n\ntype InternalColumn = { table: Table; column: string; aggregateFn?: string; aggregateFnResultColumnName?: string; normalize?: boolean };\n\ninterface Params {\n tableRoot: Table;\n tableJoin: Table;\n geometricColumnRoot: string;\n geometricColumnJoin: string;\n joinType: string;\n spatialPredicate: string;\n nearDistance?: number;\n nearUseCentroid?: boolean;\n groupBy: { selectColumns: Array<InternalColumn> } | null;\n outputTableName: string;\n}\n\n// Alias used for the pre-filtered join table CTE in NEAR queries\nconst NEAR_CTE_ALIAS = 'csv_candidates';\n\nexport const SPATIAL_JOIN_QUERY = (params: Params) => {\n const isNear = params.spatialPredicate === 'NEAR';\n\n // For NEAR queries we reference the CTE alias instead of the real table name\n // in both the SELECT and JOIN clauses, so the optimizer sees a pre-filtered dataset.\n const effectiveJoinTable: Table = isNear\n ? { ...params.tableJoin, name: NEAR_CTE_ALIAS }\n : params.tableJoin;\n\n // Also remap any groupBy column references that point to the join table so that\n // generated expressions like COUNT(noise.\"col\") become COUNT(csv_candidates.\"col\").\n const effectiveGroupBy = isNear && params.groupBy\n ? {\n selectColumns: params.groupBy.selectColumns.map((col) => ({\n ...col,\n // Preserve the original table name as the result column name so the generated\n // JSON key stays e.g. 'noise' instead of falling back to 'csv_candidates'.\n aggregateFnResultColumnName: col.aggregateFnResultColumnName ?? (col.table.name === params.tableJoin.name ? col.table.name : undefined),\n table: col.table.name === params.tableJoin.name ? effectiveJoinTable : col.table,\n })),\n }\n : params.groupBy;\n\n const selectString = getSelectString({\n tableRoot: params.tableRoot,\n tableJoin: effectiveJoinTable,\n geometricColumnRoot: params.geometricColumnRoot,\n geometricColumnJoin: params.geometricColumnJoin,\n nearUseCentroid: params.nearUseCentroid,\n groupBy: effectiveGroupBy,\n });\n\n const joinString = getJoinString({\n spatialPredicate: params.spatialPredicate,\n joinType: params.joinType,\n tableJoin: effectiveJoinTable,\n tableRoot: params.tableRoot,\n geometricColumnRoot: params.geometricColumnRoot,\n geometricColumnJoin: params.geometricColumnJoin,\n nearDistance: params.nearDistance,\n nearUseCentroid: params.nearUseCentroid,\n });\n\n const groupByString = getGroupByString(params.tableRoot);\n\n // For NEAR queries: a CTE that pre-filters the join table using an ST_Intersects\n // WHERE clause so the R-tree index fires. Stored separately so it can be combined\n // with a normalization CTE when needed.\n const rootGeomExpr = (col: string) =>\n params.nearUseCentroid ? `ST_Centroid(\"${col}\")` : `\"${col}\"`;\n\n const nearCtePart = isNear\n ? `${NEAR_CTE_ALIAS} AS (\n SELECT * FROM ${params.tableJoin.name}\n WHERE ST_Intersects(\n (SELECT ST_Union_Agg(ST_Expand(${rootGeomExpr(params.geometricColumnRoot)}, ${params.nearDistance})) FROM ${params.tableRoot.name}),\n ${params.tableJoin.name}.\"${params.geometricColumnJoin}\"\n )\n )`\n : null;\n\n const innerQuery = `\n ${selectString}\n FROM ${params.tableRoot.name}\n ${joinString}\n ${params.groupBy ? groupByString : ''}\n `;\n\n const normalizedColumns = effectiveGroupBy?.selectColumns.filter((col) => col.normalize) ?? [];\n\n if (normalizedColumns.length > 0) {\n const cteParts = [...(nearCtePart ? [nearCtePart] : []), `sjoin_base AS (${innerQuery})`];\n const normPatch = buildNormalizationMergePatch(normalizedColumns);\n return `\n WITH ${cteParts.join(',\\n')}\n SELECT * REPLACE (${normPatch} AS properties)\n FROM sjoin_base;\n `;\n }\n\n return `\n ${nearCtePart ? `WITH ${nearCtePart}` : ''}\n ${innerQuery};\n `;\n};\n\n/* Select Logic */\nfunction getSelectString(params: {\n tableRoot: Table;\n tableJoin: Table;\n geometricColumnRoot: string;\n geometricColumnJoin: string;\n nearUseCentroid?: boolean;\n groupBy: { selectColumns: Array<InternalColumn> } | null;\n}) {\n if (params.groupBy) {\n const { aggregatesByFunction, nonAggregateColumns } = groupColumnsByAggregateFunction(params.groupBy.selectColumns);\n const sjoinObjectSql = buildSjoinObject(aggregatesByFunction, nonAggregateColumns, {\n tableRoot: params.tableRoot,\n tableJoin: params.tableJoin,\n geometricColumnRoot: params.geometricColumnRoot,\n geometricColumnJoin: params.geometricColumnJoin,\n nearUseCentroid: params.nearUseCentroid,\n });\n\n // Get all additional columns from tableRoot (excluding geometry and properties)\n const additionalColumns = params.tableRoot.columns\n .filter((col) => col.name !== 'geometry' && col.name !== 'properties')\n .map((col) => `${params.tableRoot.name}.${col.name}`);\n\n const additionalColumnsStr =\n additionalColumns.length > 0 ? `,\\n ${additionalColumns.join(',\\n ')}` : '';\n\n return `\n SELECT \n ${params.tableRoot.name}.geometry,\n json_merge_patch(\n COALESCE(CAST(\"${params.tableRoot.name}\".properties AS JSON), '{}'::JSON),\n json_object(\n 'sjoin', json_object(\n ${sjoinObjectSql}\n )\n )\n ) AS properties${additionalColumnsStr}\n `;\n }\n\n return buildSimpleJoinSelect(params.tableRoot, params.tableJoin, params.geometricColumnJoin);\n}\n\nfunction groupColumnsByAggregateFunction(selectColumns: Array<InternalColumn>) {\n const aggregatesByFunction: Record<\n string,\n Array<{ table: Table; column: string; aggregateFnResultColumnName?: string }>\n > = {};\n const nonAggregateColumns: Array<{ table: Table; column: string; aggregateFnResultColumnName?: string }> = [];\n\n selectColumns.forEach((column) => {\n if (column.aggregateFn) {\n const funcName = column.aggregateFn.toLowerCase();\n if (!aggregatesByFunction[funcName]) {\n aggregatesByFunction[funcName] = [];\n }\n aggregatesByFunction[funcName].push({\n table: column.table,\n column: column.column,\n aggregateFnResultColumnName: column.aggregateFnResultColumnName,\n });\n } else {\n nonAggregateColumns.push({\n table: column.table,\n column: column.column,\n aggregateFnResultColumnName: column.aggregateFnResultColumnName,\n });\n }\n });\n\n return { aggregatesByFunction, nonAggregateColumns };\n}\n\nfunction buildSjoinObject(\n aggregatesByFunction: Record<string, Array<{ table: Table; column: string; aggregateFnResultColumnName?: string }>>,\n nonAggregateColumns: Array<{ table: Table; column: string; aggregateFnResultColumnName?: string }>,\n geomContext: { tableRoot: Table; tableJoin: Table; geometricColumnRoot: string; geometricColumnJoin: string; nearUseCentroid?: boolean },\n): string {\n const sjoinParts: string[] = [];\n\n // Handle aggregate functions\n Object.entries(aggregatesByFunction).forEach(([funcName, columns]) => {\n if (funcName === 'count') {\n sjoinParts.push(buildCountExpression(columns[0]));\n } else if (funcName === 'weighted') {\n sjoinParts.push(buildWeightedExpression(columns[0], geomContext));\n } else if (funcName === 'collect') {\n sjoinParts.push(buildCollectExpression(columns[0]));\n } else {\n sjoinParts.push(buildNestedFunctionExpression(funcName, columns));\n }\n });\n\n // Handle non-aggregate columns\n if (nonAggregateColumns.length > 0) {\n sjoinParts.push(buildNonAggregateColumns(nonAggregateColumns));\n }\n\n return sjoinParts.join(', ');\n}\n\nfunction buildWeightedExpression(\n column: { table: Table; column: string; aggregateFnResultColumnName?: string },\n geomContext: { tableRoot: Table; tableJoin: Table; geometricColumnRoot: string; geometricColumnJoin: string; nearUseCentroid?: boolean },\n): string {\n const { tableRoot, tableJoin, geometricColumnRoot, geometricColumnJoin, nearUseCentroid } = geomContext;\n const rootGeom = nearUseCentroid\n ? `ST_Centroid(${tableRoot.name}.\"${geometricColumnRoot}\")`\n : `${tableRoot.name}.\"${geometricColumnRoot}\"`;\n const joinGeom = nearUseCentroid\n ? `ST_Centroid(${tableJoin.name}.\"${geometricColumnJoin}\")`\n : `${tableJoin.name}.\"${geometricColumnJoin}\"`;\n const columnName = column.aggregateFnResultColumnName ?? column.table.name;\n return `'weighted', json_object('${columnName}', SUM(1.0 / (ST_Distance(${rootGeom}, ${joinGeom}) + 1.0)))`;\n}\n\nfunction buildCollectExpression(column: { table: Table; column: string; aggregateFnResultColumnName?: string }): string {\n const columnName = column.aggregateFnResultColumnName ?? column.table.name;\n const valueExpression = generateValueExpression(column.table, column.column, 'COLLECT');\n return `'collect', json_object('${columnName}', ${valueExpression})`;\n}\n\nfunction buildCollectColumnExpression(table: Table, columnName: string): string {\n if (table.source === 'geotiff') return `${table.name}.properties.${columnName}`;\n if (isLayerType(table.type)) return buildJsonExtract(table.name, columnName);\n return `${table.name}.\"${columnName}\"`;\n}\n\nfunction buildCountExpression(column: { table: Table; column: string; aggregateFnResultColumnName?: string }): string {\n const valueExpression = generateValueExpression(column.table, column.column, 'COUNT');\n const columnName = column.aggregateFnResultColumnName || column.table.name;\n return `'count', json_object('${columnName}', ${valueExpression})`;\n}\n\nfunction buildNestedFunctionExpression(\n funcName: string,\n columns: Array<{ table: Table; column: string; aggregateFnResultColumnName?: string }>,\n): string {\n const functionAttributes = columns\n .map((column) => {\n const valueExpression = generateValueExpression(column.table, column.column, funcName.toUpperCase());\n const columnName = column.aggregateFnResultColumnName || `${column.table.name}.${column.column}`;\n return `'${columnName}', ${valueExpression}`;\n })\n .join(', ');\n\n return `'${funcName}', json_object(${functionAttributes})`;\n}\n\nfunction buildNonAggregateColumns(\n nonAggregateColumns: Array<{ table: Table; column: string; aggregateFnResultColumnName?: string }>,\n): string {\n return nonAggregateColumns\n .map((column) => {\n const valueExpression = column.table.source === 'geotiff'\n ? `${column.table.name}.properties.${column.column}`\n : isLayerType(column.table.type)\n ? buildJsonExtract(column.table.name, column.column)\n : `${column.table.name}.\"${column.column}\"`;\n const columnName = column.aggregateFnResultColumnName || column.column;\n return `'${columnName}', ${valueExpression}`;\n })\n .join(', ');\n}\n\nfunction generateValueExpression(table: Table, columnName: string, aggregateFunction: string): string {\n if (aggregateFunction === 'COLLECT') {\n // '*' collects the entire properties object of the join row; otherwise collects a specific column.\n if (columnName === '*') {\n if (table.source === 'geotiff') return `json_group_array(${table.name}.properties)`;\n if (isLayerType(table.type)) return `json_group_array(CAST(${table.name}.properties AS JSON))`;\n // CSV/JSON tables: build a json_object from all non-geometry columns\n const cols = table.columns\n .filter(c => c.name !== 'geometry')\n .map(c => `'${c.name}', ${table.name}.\"${c.name}\"`)\n .join(', ');\n return `json_group_array(json_object(${cols}))`;\n }\n // Single-column collect: wrap in json_object so consumers always get an array of objects.\n const colExpr = buildCollectColumnExpression(table, columnName);\n return `json_group_array(json_object('${columnName}', ${colExpr}))`;\n }\n if (table.source === 'geotiff') {\n return `${aggregateFunction}(${table.name}.properties.${columnName})`;\n }\n if (isLayerType(table.type)) {\n const extract = buildJsonExtract(table.name, columnName);\n const castExpr = aggregateFunction === 'COUNT' ? extract : `CAST(${extract} AS DOUBLE)`;\n return `${aggregateFunction}(${castExpr})`;\n }\n return `${aggregateFunction}(${table.name}.\"${columnName}\")`;\n}\n\n/**\n * Builds a DuckDB JSON/STRUCT extraction expression for a (possibly nested) column path.\n * Supports dot-notation paths like 'compute.skyViewFactor'.\n * Uses chained -> / ->> operators which work for both DuckDB STRUCT and JSON column types.\n */\nfunction buildJsonExtract(tableName: string, columnPath: string): string {\n const parts = columnPath.split('.');\n const last = parts.pop()!;\n const chain = parts.reduce((acc, p) => `${acc}->'${p}'`, `${tableName}.properties`);\n return `${chain}->>'${last}'`;\n}\n\nfunction buildNormalizationMergePatch(normalizedColumns: Array<InternalColumn>): string {\n // Group columns by aggregateFn so we can build the nested sjoin JSON structure\n const byAggFn: Record<string, Array<{ colKey: string; jsonPath: string }>> = {};\n\n for (const col of normalizedColumns) {\n const funcName = col.aggregateFn?.toLowerCase() ?? 'value';\n const colKey =\n funcName === 'count'\n ? (col.aggregateFnResultColumnName ?? col.table.name)\n : (col.aggregateFnResultColumnName ?? `${col.table.name}.${col.column}`);\n const jsonPath = `$.sjoin.${funcName}.${colKey}`;\n\n if (!byAggFn[funcName]) byAggFn[funcName] = [];\n byAggFn[funcName].push({ colKey, jsonPath });\n }\n\n const aggFnParts = Object.entries(byAggFn)\n .map(([funcName, cols]) => {\n const colParts = cols\n .map(({ colKey, jsonPath }) => {\n const rawVal = `COALESCE(json_extract(properties, '${jsonPath}')::DOUBLE, 0)`;\n const normExpr =\n `(${rawVal} - MIN(${rawVal}) OVER ()) / ` +\n `NULLIF(MAX(${rawVal}) OVER () - MIN(${rawVal}) OVER (), 0)`;\n return `'${colKey}_norm', ${normExpr}`;\n })\n .join(',\\n ');\n return `'${funcName}', json_object(${colParts})`;\n })\n .join(',\\n ');\n\n return `json_merge_patch(\n properties,\n json_object('sjoin', json_object(\n ${aggFnParts}\n ))\n )`;\n}\n\nfunction buildSimpleJoinSelect(tableRoot: Table, tableJoin: Table, geometricColumnJoin: string): string {\n // Get all additional columns from tableRoot (excluding geometry and properties)\n const additionalColumns = tableRoot.columns\n .filter((col) => col.name !== 'geometry' && col.name !== 'properties')\n .map((col) => `${tableRoot.name}.${col.name}`);\n\n const additionalColumnsStr =\n additionalColumns.length > 0 ? `,\\n ${additionalColumns.join(',\\n ')}` : '';\n\n // When the join table is a layer type (OSM / GeoJSON), its data lives in a 'properties'\n // JSON column. Using json_object(tableJoin.properties) would fail because json_object()\n // requires an even number of key-value pair arguments. Instead, merge the JSON blob directly.\n const joinPropertiesExpr = isLayerType(tableJoin.type)\n ? `COALESCE(CAST(${tableJoin.name}.properties AS JSON), '{}'::JSON)`\n : `json_object(${tableJoin.columns\n .filter((column) => column.name !== geometricColumnJoin)\n .map((column) => `'${column.name}', ${tableJoin.name}.\"${column.name}\"`)\n .join(', ')})`;\n\n return `\n SELECT \n ${tableRoot.name}.geometry,\n json_merge_patch(\n json_object('sjoin', ${joinPropertiesExpr}),\n COALESCE(CAST(\"${tableRoot.name}\".properties AS JSON), '{}'::JSON)\n ) AS properties${additionalColumnsStr}\n `;\n}\n\n\n/* Join Logic */\nfunction getJoinString({\n spatialPredicate,\n joinType,\n tableJoin,\n tableRoot,\n geometricColumnRoot,\n geometricColumnJoin,\n nearDistance,\n nearUseCentroid,\n}: {\n spatialPredicate: string;\n joinType: string;\n tableJoin: Table;\n tableRoot: Table;\n geometricColumnRoot: string;\n geometricColumnJoin: string;\n nearDistance?: number;\n nearUseCentroid?: boolean;\n}) {\n if (spatialPredicate === 'NEAR') {\n const rootExpr = nearUseCentroid\n ? `ST_Centroid(${tableRoot.name}.\"${geometricColumnRoot}\")`\n : `${tableRoot.name}.\"${geometricColumnRoot}\"`;\n const joinExpr = nearUseCentroid\n ? `ST_Centroid(${tableJoin.name}.\"${geometricColumnJoin}\")`\n : `${tableJoin.name}.\"${geometricColumnJoin}\"`;\n return `${joinType || ''} JOIN ${tableJoin.name} ON ST_Distance(${rootExpr}, ${joinExpr}) <= ${nearDistance}`;\n }\n\n return `${joinType || ''} JOIN ${tableJoin.name} ON ST_Intersects( ${tableRoot.name}.\"${geometricColumnRoot}\", ${tableJoin.name}.\"${geometricColumnJoin}\")`;\n}\n\n/* Group By Logic */\nfunction getGroupByString(tableRoot: Table) {\n // Get all additional columns from tableRoot (excluding geometry and properties)\n const additionalColumns = tableRoot.columns\n .filter((col) => col.name !== 'geometry' && col.name !== 'properties')\n .map((col) => `${tableRoot.name}.${col.name}`);\n\n const allGroupByColumns = [`${tableRoot.name}.geometry`, `${tableRoot.name}.properties`, ...additionalColumns];\n\n return `\n GROUP BY ${allGroupByColumns.join(', ')}\n `;\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { SpatialQueryParams } from './interfaces';\nimport { Table } from '../../../shared/interfaces';\nimport { GeometryColumnNotFoundError, TableNotFoundError } from './errors';\nimport { SPATIAL_JOIN_QUERY } from './queries';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\n\n/**\n * Performs a spatial join between two tables, with optional aggregation.\n */\nexport class SpatialJoinUseCase {\n private conn: AsyncDuckDBConnection;\n\n constructor(conn: AsyncDuckDBConnection) {\n this.conn = conn;\n }\n\n async exec(params: SpatialQueryParams, tables: Table[]): Promise<{ created: boolean; table: Table }> {\n const tableRoot = tables.find((table) => table.name === params.tableRootName);\n if (!tableRoot) throw new TableNotFoundError(params.tableRootName);\n\n const tableJoin = tables.find((table) => table.name === params.tableJoinName);\n if (!tableJoin) throw new TableNotFoundError(params.tableJoinName);\n\n const geometricColumnRoot = this.getGeometryColumnName(tableRoot);\n if (!geometricColumnRoot) throw new GeometryColumnNotFoundError(tableRoot.name);\n\n const geometricColumnJoin = this.getGeometryColumnName(tableJoin);\n if (!geometricColumnJoin) throw new GeometryColumnNotFoundError(tableJoin.name);\n\n const joinType = params.joinType || 'INNER';\n const spatialPredicate = params.spatialPredicate || 'INTERSECT';\n\n let nearUseCentroid = params.nearUseCentroid;\n if (nearUseCentroid === undefined && spatialPredicate === 'NEAR') {\n nearUseCentroid = await this.isPolygonTable(tableRoot.name, geometricColumnRoot);\n }\n\n const outputTableName = (params.output.type === 'CREATE_NEW' ? params.output.tableName : tableRoot.name) as string;\n const query = SPATIAL_JOIN_QUERY({\n tableRoot,\n tableJoin,\n geometricColumnRoot,\n geometricColumnJoin,\n joinType,\n spatialPredicate,\n groupBy: this.addTablesToGroupBy(params.groupBy, tables),\n nearDistance: params.nearDistance,\n nearUseCentroid,\n outputTableName,\n });\n\n // console.log({ query });\n const tableDescribeResponse = await this.conn.query(`\n CREATE OR REPLACE TABLE ${outputTableName} AS\n ${query}\n\n DESCRIBE ${outputTableName};\n `);\n\n return {\n table: {\n source: tableRoot.source,\n type: tableRoot.type,\n name: outputTableName,\n columns: getColumnsFromDuckDbTableDescribe(tableDescribeResponse.toArray()),\n } as Table,\n created: params.output.type === 'CREATE_NEW',\n };\n }\n\n /**\n * Gets the appropriate geometry column name for a table.\n * For building tables, prioritizes 'agg_geometry' if available, otherwise falls back to 'geometry'.\n * For other tables, returns the first geometry column found.\n */\n private async isPolygonTable(tableName: string, geomColumn: string): Promise<boolean> {\n const result = await this.conn.query(\n `SELECT ST_GeometryType(\"${geomColumn}\") AS geom_type FROM ${tableName} WHERE \"${geomColumn}\" IS NOT NULL LIMIT 1`\n );\n const rows = result.toArray();\n if (rows.length === 0) return false;\n const geomType = String(rows[0].geom_type).toUpperCase();\n return geomType === 'POLYGON' || geomType === 'MULTIPOLYGON';\n }\n\n private getGeometryColumnName(table: Table): string | undefined {\n if (table.source === 'osm' && table.type === 'buildings') {\n const aggGeometryColumn = table.columns.find(\n (column) => column.name === 'agg_geometry' && column.type === 'GEOMETRY',\n );\n\n if (aggGeometryColumn) return aggGeometryColumn.name;\n }\n\n // Default behavior: return first geometry column found\n return table.columns.find((column) => column.type === 'GEOMETRY')?.name;\n }\n\n private addTablesToGroupBy(\n groupBy: SpatialQueryParams['groupBy'],\n tables: Table[],\n ): {\n selectColumns: Array<{ table: Table; column: string; aggregateFn?: string; aggregateFnResultColumnName?: string; normalize?: boolean }>;\n } | null {\n if (!groupBy) return null;\n\n return {\n selectColumns: groupBy.selectColumns.map((column) => {\n const table = tables.find((table) => table.name === column.tableName);\n if (!table) throw new TableNotFoundError(column.tableName);\n\n return {\n table,\n column: column.column,\n aggregateFn: column.aggregateFn,\n aggregateFnResultColumnName: column.aggregateFnResultColumnName,\n normalize: column.normalize,\n };\n }),\n };\n }\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nexport interface DropTableParams {\n tableName: string;\n workspace?: string;\n}\n\nexport interface DropTableResult {\n success: boolean;\n message: string;\n}\n\n/**\n * Drops a table from the current workspace.\n */\nexport class DropTableUseCase {\n constructor(private conn: AsyncDuckDBConnection) {}\n\n /**\n * Drops the specified table, returning success/failure rather than throwing.\n *\n * @param params.tableName Name of the table to drop.\n * @param params.workspace Optional workspace name (defaults to `main`).\n * @returns Result indicating success or failure with a message.\n * @throws Never throws. Errors are caught and returned in the result.\n */\n async exec(params: DropTableParams): Promise<DropTableResult> {\n try {\n const workspace = params.workspace || 'main';\n const qualifiedTableName = `${workspace}.${params.tableName}`;\n await this.conn.query(`DROP TABLE IF EXISTS ${qualifiedTableName};`);\n return {\n success: true,\n message: `Table ${params.tableName} dropped successfully`,\n };\n } catch (error) {\n return {\n success: false,\n message: `Error dropping table ${params.tableName}: ${error}`,\n };\n }\n }\n}\n","type Params = {\n boundingBox: {\n minLat: number;\n maxLat: number;\n minLon: number;\n maxLon: number;\n };\n coordinateFormat: string;\n};\n\nexport const TRANSFORM_BOUNDING_BOX_COORDINATES_QUERY = ({ boundingBox, coordinateFormat }: Params) => {\n return `\n WITH transformed_bounds AS (\n SELECT\n ST_Transform(ST_Point(${boundingBox.minLon}, ${boundingBox.minLat}), 'EPSG:4326', '${coordinateFormat}', always_xy := true) as min_point,\n ST_Transform(ST_Point(${boundingBox.maxLon}, ${boundingBox.maxLat}), 'EPSG:4326', '${coordinateFormat}', always_xy := true) as max_point\n )\n SELECT \n CAST(ST_X(min_point) AS DOUBLE) as minLon,\n CAST(ST_Y(min_point) AS DOUBLE) as minLat,\n CAST(ST_X(max_point) AS DOUBLE) as maxLon,\n CAST(ST_Y(max_point) AS DOUBLE) as maxLat\n FROM transformed_bounds;\n `;\n};\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { TransformBoundingBoxCoordinatesParams } from './interfaces';\nimport { BoundingBox } from '../../../../shared/interfaces';\nimport { TRANSFORM_BOUNDING_BOX_COORDINATES_QUERY } from './queries';\n\n/**\n * Transforms a bounding box between coordinate reference systems.\n */\nexport class TransformBoundingBoxCoordinatesUseCase {\n constructor(private conn: AsyncDuckDBConnection) {}\n\n /**\n * Transforms bounding box coordinates using DuckDB's `ST_Transform`.\n * EPSG:4326 inputs are returned unchanged.\n *\n * @param params.boundingBox Source bounding box to transform.\n * @param params.coordinateFormat Target CRS (e.g. `EPSG:3857`).\n * @returns Transformed bounding box.\n * @throws If the coordinate transformation fails.\n */\n async exec(params: TransformBoundingBoxCoordinatesParams): Promise<BoundingBox> {\n // If already in EPSG:4326, no conversion needed\n if (params.coordinateFormat === 'EPSG:4326') {\n return {\n minLon: params.boundingBox.minLon,\n minLat: params.boundingBox.minLat,\n maxLon: params.boundingBox.maxLon,\n maxLat: params.boundingBox.maxLat,\n };\n }\n\n // Transform coordinates using DuckDB's ST_Transform function\n const result = await this.conn.query(\n TRANSFORM_BOUNDING_BOX_COORDINATES_QUERY({\n boundingBox: params.boundingBox,\n coordinateFormat: params.coordinateFormat,\n }),\n );\n const rows = result.toArray();\n\n if (rows.length === 0) {\n throw new Error('Could not transform bounding box coordinates');\n }\n\n return {\n minLon: rows[0].minLon,\n minLat: rows[0].minLat,\n maxLon: rows[0].maxLon,\n maxLat: rows[0].maxLat,\n };\n }\n}\n","export const GET_BOUNDING_BOX_FROM_LAYER_QUERY = (layerTableName: string, workspace: string) => {\n const qualifiedTableName = `${workspace}.${layerTableName}`;\n return `\n WITH geometry_bounds AS (\n SELECT \n ST_XMin(geometry) as min_x,\n ST_YMin(geometry) as min_y,\n ST_XMax(geometry) as max_x,\n ST_YMax(geometry) as max_y\n FROM ${qualifiedTableName}\n WHERE geometry IS NOT NULL\n )\n SELECT \n CAST(MIN(min_x) AS DOUBLE) as minLon,\n CAST(MIN(min_y) AS DOUBLE) as minLat,\n CAST(MAX(max_x) AS DOUBLE) as maxLon,\n CAST(MAX(max_y) AS DOUBLE) as maxLat\n FROM geometry_bounds;\n `;\n};\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { GetBoundingBoxFromLayerParams } from './interfaces';\nimport { BoundingBox } from '../../../../shared/interfaces';\nimport { GET_BOUNDING_BOX_FROM_LAYER_QUERY } from './queries';\n\n/**\n * Computes the geographic bounding box of a layer table.\n */\nexport class GetBoundingBoxFromLayerUseCase {\n constructor(private conn: AsyncDuckDBConnection) {}\n\n /**\n * Queries the spatial extent of a layer's geometry column.\n *\n * @param params.layerTableName Name of the layer table.\n * @param params.workspace Optional workspace name (defaults to `main`).\n * @returns Named bounding box with `minLon`, `minLat`, `maxLon`, `maxLat`.\n * @throws If the table has no geometries or invalid coordinates.\n */\n async exec(params: GetBoundingBoxFromLayerParams): Promise<BoundingBox> {\n const workspace = params.workspace || 'main';\n const result = await this.conn.query(GET_BOUNDING_BOX_FROM_LAYER_QUERY(params.layerTableName, workspace));\n const rows = result.toArray();\n\n if (rows.length === 0) {\n throw new Error(`Could not calculate bounding box - no geometries found in table ${params.layerTableName}`);\n }\n\n const row = rows[0];\n\n // Validate that we have valid coordinates\n if (row.minLon == null || row.minLat == null || row.maxLon == null || row.maxLat == null) {\n throw new Error(`Could not calculate bounding box - invalid coordinates found in table ${params.layerTableName}`);\n }\n\n return {\n minLon: row.minLon,\n minLat: row.minLat,\n maxLon: row.maxLon,\n maxLat: row.maxLat,\n };\n }\n}\n","/**\n * Simple HTTP cache using Browser Cache API with TTL support\n */\nexport class HttpCache<T = any> {\n private cache: Cache | null = null;\n private readonly cacheName: string;\n private readonly ttl: number;\n\n /**\n * Creates an HTTP cache with the given name and TTL.\n *\n * @param cacheName Name of the cache storage.\n * @param ttl Time to live in milliseconds (default: 24 hours).\n * @throws Never throws.\n */\n constructor(cacheName: string, ttl: number = 24 * 60 * 60 * 1000) {\n this.cacheName = cacheName;\n this.ttl = ttl;\n }\n\n /**\n * Initializes the Cache API storage if available.\n *\n * @throws Never throws. Failures leave the cache as `null`.\n */\n private async init(): Promise<void> {\n if ('caches' in self && !this.cache) {\n try {\n this.cache = await caches.open(this.cacheName);\n } catch {\n this.cache = null;\n }\n }\n }\n\n /**\n * Returns cached data for a key, or `null` if missing or expired.\n *\n * @param key Cache key to look up.\n * @returns Cached data or `null`.\n * @throws Never throws. Errors are caught and return `null`.\n */\n async get(key: string): Promise<T | null> {\n await this.init();\n if (!this.cache) return null;\n\n try {\n const response = await this.cache.match(this.toRequest(key));\n if (!response) return null;\n\n const cached = await response.json();\n const now = Date.now();\n\n // Check if expired\n if (now - cached.timestamp > this.ttl) {\n await this.cache.delete(this.toRequest(key));\n return null;\n }\n\n return cached.data as T;\n } catch {\n return null;\n }\n }\n\n private toRequest(key: string): Request {\n return new Request(`https://cache.local/${encodeURIComponent(key)}`);\n }\n\n /**\n * Stores data in the cache with a current timestamp.\n *\n * @param key Cache key to store under.\n * @param data Value to cache.\n * @returns Nothing.\n * @throws Never throws. Errors are silently caught.\n */\n async set(key: string, data: T): Promise<void> {\n await this.init();\n if (!this.cache) return;\n\n try {\n const cached = {\n data,\n timestamp: Date.now(),\n };\n\n const response = new Response(JSON.stringify(cached), {\n headers: { 'Content-Type': 'application/json' },\n });\n\n await this.cache.put(this.toRequest(key), response);\n } catch {\n // Ignore cache errors\n }\n }\n\n /**\n * Deletes a specific key from the cache.\n *\n * @param key Cache key to remove.\n * @returns Nothing.\n * @throws Never throws. Errors are silently caught.\n */\n async delete(key: string): Promise<void> {\n await this.init();\n if (!this.cache) return;\n\n try {\n await this.cache.delete(this.toRequest(key));\n } catch {\n // Ignore errors\n }\n }\n\n /**\n * Clears all items from this cache.\n *\n * @returns Nothing.\n * @throws Never throws. Errors are silently caught.\n */\n async clear(): Promise<void> {\n await this.init();\n if (!this.cache) return;\n\n try {\n const keys = await this.cache.keys();\n await Promise.all(keys.map((request) => this.cache!.delete(request)));\n } catch {\n // Ignore errors\n }\n }\n}\n\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { LoadOsmParams, OsmElement, OnLoadingProgress } from './interfaces';\nimport { OsmTable } from '../../../shared/interfaces';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport { HttpCache } from '../../../shared/HttpCache';\nimport {\n PARKS_LEISURE_VALUES,\n PARKS_LANDUSE_VALUES,\n PARKS_NATURAL_VALUES,\n WATER_NATURAL_VALUES,\n WATER_FEATURE_VALUES,\n EXCLUDED_BUILDING_VALUES,\n EXCLUDED_HIGHWAY_VALUES,\n} from '../../../shared/osm-tag-definitions';\n\nimport { OsmProcessingPipeline } from '../osm-processing-pipeline/OsmProcessingPipeline';\n\ninterface OverpassApiResponse {\n elements: OsmElement[];\n}\n\ninterface OsmExecResult {\n tables: OsmTable[];\n osmElementCount: number;\n boundaryElementCount: number;\n osmDataProcessingMs: number;\n boundariesProcessingMs: number;\n}\n\ntype OverpassTagSelectors = {\n way: string[];\n relation: string[];\n};\n\n/**\n * Loads OSM data from the Overpass API with caching, retry, and slot polling.\n */\nexport class LoadOsmFromOverpassApiUseCase {\n private readonly conn: AsyncDuckDBConnection;\n private readonly cache: HttpCache<OverpassApiResponse>;\n private readonly pipeline: OsmProcessingPipeline;\n\n constructor(conn: AsyncDuckDBConnection, pipeline: OsmProcessingPipeline) {\n this.conn = conn;\n this.cache = new HttpCache('overpass-api-cache', 24 * 60 * 60 * 1000); // 24h TTL\n this.pipeline = pipeline;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n async exec(params: LoadOsmParams): Promise<OsmExecResult> {\n const workspace = params.workspace || 'main';\n const onProgress = params.onProgress;\n\n const combined = await this.fetchCombinedOsmData(\n params.queryArea,\n params.autoLoadLayers?.layers,\n onProgress,\n params.forceRefresh,\n );\n\n // Verify every requested area has an admin boundary relation in the response.\n const relationNames = new Set(\n combined.elements\n .filter(e => e.type === 'relation' && e.tags?.name)\n .map(e => e.tags!.name),\n );\n const missingAreas = params.queryArea.areas.filter(area => !relationNames.has(area));\n if (missingAreas.length > 0) {\n throw new Error(\n `No administrative boundary found in OSM for: ${missingAreas.map(a => `\"${a}\"`).join(', ')}. ` +\n `Verify the area names match OSM relation names exactly (check openstreetmap.org).`,\n );\n }\n\n const { osmData, boundariesData } = this.pipeline.splitCombinedResponse(combined, params.queryArea);\n console.log(`[autk-db] Split: ${osmData.elements.length} OSM elements, ${boundariesData.elements.length} boundary elements`);\n\n onProgress?.('processing-osm-data');\n const t0 = performance.now();\n await this.pipeline.insertOsmDataUsingJson(params.outputTableName, osmData, workspace);\n const osmDataProcessingMs = performance.now() - t0;\n console.log(`Successfully inserted ${osmData.elements.length} OSM elements into ${params.outputTableName}`);\n\n onProgress?.('processing-boundaries');\n const t1 = performance.now();\n await this.pipeline.insertOsmDataUsingJson(`${params.outputTableName}_boundaries`, boundariesData, workspace, true);\n const boundariesProcessingMs = performance.now() - t1;\n console.log(`Successfully inserted ${boundariesData.elements.length} boundaries into ${params.outputTableName}_boundaries`);\n\n const qualifiedTableName = `${workspace}.${params.outputTableName}`;\n const tableDescribeResponse = await this.conn.query(`DESCRIBE ${qualifiedTableName}`);\n const columns = getColumnsFromDuckDbTableDescribe(tableDescribeResponse.toArray());\n\n return {\n tables: [\n { source: 'osm', type: 'pointset', name: params.outputTableName, columns },\n { source: 'osm', type: 'pointset', name: `${params.outputTableName}_boundaries`, columns },\n ],\n osmElementCount: osmData.elements.length,\n boundaryElementCount: boundariesData.elements.length,\n osmDataProcessingMs,\n boundariesProcessingMs,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Cache\n // ---------------------------------------------------------------------------\n\n private getCacheKey(queryArea: { geocodeArea: string; areas: string[] }, layers?: string[]): string {\n const areas = [...queryArea.areas].sort().join(',');\n const layerKey = layers && layers.length > 0 ? `-layers:${[...layers].sort().join('+')}` : '';\n return `overpass-combined-${queryArea.geocodeArea}-${areas}${layerKey}`;\n }\n\n private getFullDataCacheKey(queryArea: { geocodeArea: string; areas: string[] }): string {\n const areas = [...queryArea.areas].sort().join(',');\n return `overpass-combined-${queryArea.geocodeArea}-${areas}`;\n }\n\n // ---------------------------------------------------------------------------\n // Overpass fetch orchestration\n // ---------------------------------------------------------------------------\n\n /**\n * Fetches OSM data as four independent requests — boundaries, parks+water,\n * roads, buildings — so each request is smaller and less likely to trigger a\n * 504. A pause between requests avoids immediate rate-limiting. Results are\n * cached for 24h.\n *\n * `geocodeArea` (e.g. \"New York\") is used only as a disambiguation scope.\n * All data is spatially constrained to the entries in `queryArea.areas`.\n */\n private async fetchCombinedOsmData(\n queryArea: { geocodeArea: string; areas: string[] },\n layers: string[] | undefined,\n onProgress?: OnLoadingProgress,\n forceRefresh: boolean = false,\n ): Promise<OverpassApiResponse> {\n const cacheKey = this.getCacheKey(queryArea, layers);\n if (!forceRefresh) {\n const cachedData = await this.cache.get(cacheKey);\n if (cachedData) {\n console.log(`[autk-db] Using cached Overpass data: ${cacheKey}`);\n return cachedData;\n }\n\n // A full-data cache entry (no layer filter) is a valid superset — reuse it.\n const fullDataCacheKey = this.getFullDataCacheKey(queryArea);\n if (fullDataCacheKey !== cacheKey) {\n const fullData = await this.cache.get(fullDataCacheKey);\n if (fullData) {\n console.log(`[autk-db] Using cached Overpass full-data superset: ${fullDataCacheKey}`);\n return fullData;\n }\n }\n } else {\n console.log(`[autk-db] forceRefresh enabled — bypassing Overpass cache for: ${cacheKey}`);\n }\n\n const requestedLayers = layers && layers.length > 0 ? layers : ['roads', 'buildings', 'parks', 'water'];\n const pause = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n const BETWEEN_REQUESTS_MS = 3_000;\n\n onProgress?.('querying-osm-server');\n\n // Request 1: boundaries (always needed, always small)\n console.log('[autk-db] Fetching boundary data from Overpass API…');\n const boundariesResponse = await this.fetchWithRetry(this.buildBoundariesQuery(queryArea));\n onProgress?.('downloading-osm-data');\n const boundariesData: OverpassApiResponse = await boundariesResponse.json();\n console.log(`[autk-db] Boundaries: ${boundariesData.elements?.length ?? 0} elements`);\n let combined: OverpassApiResponse = boundariesData;\n\n // Compute the area bbox once from boundary data only — independent of which\n // layers are requested, so parks/roads/etc. never pollute the extent.\n const boundariesBbox = this.pipeline.computeBboxFromElements(boundariesData.elements ?? []);\n\n // Requests 2–4: one per layer group, skipped when not requested.\n // Buildings are fetched as a 2×2 tiled grid to stay within Overpass maxsize limits.\n const layerGroups: [string, string[]][] = [\n ['parks+water', ['parks', 'water']],\n ['roads', ['roads']],\n ['buildings', ['buildings']],\n ];\n\n let anyGroupEmpty = false;\n\n for (const [label, group] of layerGroups) {\n const activeGroup = group.filter(l => requestedLayers.includes(l));\n if (activeGroup.length === 0) continue;\n\n if (activeGroup.includes('buildings')) {\n const tileQueries = boundariesBbox\n ? this.buildBuildingsTileQueries(queryArea, boundariesBbox)\n : [this.buildLayerGroupQuery(queryArea, activeGroup)!];\n\n let buildingsTotal = 0;\n for (let t = 0; t < tileQueries.length; t++) {\n await pause(BETWEEN_REQUESTS_MS);\n console.log(`[autk-db] Fetching buildings tile ${t + 1}/${tileQueries.length}…`);\n const response = await this.fetchWithRetry(tileQueries[t]);\n const data: OverpassApiResponse = await response.json();\n const count = data.elements?.length ?? 0;\n console.log(`[autk-db] buildings tile ${t + 1}: ${count} elements`);\n buildingsTotal += count;\n combined = this.mergeResponses(combined, data);\n }\n if (buildingsTotal === 0) {\n console.warn('[autk-db] buildings: 0 elements across all tiles — skipping cache.');\n anyGroupEmpty = true;\n }\n continue;\n }\n\n const query = this.buildLayerGroupQuery(queryArea, activeGroup);\n if (!query) continue;\n\n await pause(BETWEEN_REQUESTS_MS);\n console.log(`[autk-db] Fetching ${label} data from Overpass API…`);\n const response = await this.fetchWithRetry(query);\n const data: OverpassApiResponse = await response.json();\n const count = data.elements?.length ?? 0;\n console.log(`[autk-db] ${label}: ${count} elements`);\n if (count === 0) {\n console.warn(`[autk-db] ${label}: 0 elements — skipping cache.`);\n anyGroupEmpty = true;\n }\n combined = this.mergeResponses(combined, data);\n }\n\n if (anyGroupEmpty) {\n return combined;\n }\n\n await this.cache.set(cacheKey, combined);\n return combined;\n }\n\n // ---------------------------------------------------------------------------\n // Overpass HTTP — slot checking and retry\n // ---------------------------------------------------------------------------\n\n private static readonly OVERPASS_ENDPOINT = 'https://overpass-api.de/api/interpreter';\n private static readonly OVERPASS_STATUS_ENDPOINT = 'https://overpass-api.de/api/status';\n\n // Query [timeout] is stepped down on each consecutive 504 / network rejection\n // to make the request look cheaper to the server.\n private static readonly QUERY_TIMEOUTS_S = [60, 45, 30, 20, 15, 10];\n\n private static setQueryTimeout(query: string, timeoutS: number): string {\n return query.replace(/\\[timeout:\\d+\\]/, `[timeout:${timeoutS}]`);\n }\n\n /**\n * Polls the Overpass status endpoint until a slot is free, then returns.\n * Fails silently — a status check error never blocks the actual request.\n */\n private async waitForSlot(): Promise<void> {\n const POLL_INTERVAL_MS = 3_000;\n const MAX_CHECKS = 60; // bail out after ~3 min of polling\n const wait = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n\n for (let check = 0; check < MAX_CHECKS; check++) {\n try {\n const res = await fetch(LoadOsmFromOverpassApiUseCase.OVERPASS_STATUS_ENDPOINT);\n if (!res.ok) return;\n const text = await res.text();\n\n const available = text.match(/(\\d+) slots available now/);\n if (available && parseInt(available[1]) > 0) return;\n\n const waitTimes = [...text.matchAll(/in (\\d+) seconds/g)].map(m => parseInt(m[1]));\n if (waitTimes.length === 0) return;\n\n const nextFreeS = Math.min(...waitTimes);\n console.log(`[autk-db] No Overpass slots available (next free in ${nextFreeS}s). Waiting…`);\n await wait(POLL_INTERVAL_MS);\n } catch {\n return;\n }\n }\n }\n\n /**\n * POSTs a query to the Overpass API with slot checking and automatic retry.\n *\n * POST is used so large queries are never truncated by proxy URL-length limits.\n * Before each top-level call the slot status is checked and waited on.\n *\n * Retryable conditions:\n * - 429 / 503 — server overloaded; backoff: 20s → 45s → 90s → 120s → 180s → 240s\n * - 504 / ERR_EMPTY_RESPONSE / fetch timeout — proxy rejection; backoff:\n * 10s → 20s → 45s → 90s → 120s → 180s, plus [timeout] in the query is\n * stepped down (60s → 45s → 30s → 20s → 15s → 10s) so each retry looks\n * cheaper to the server.\n *\n * All backoff values have ±10% jitter. The fetch-level AbortController\n * deadline is derived from the current query [timeout] + 30s overhead.\n */\n private async fetchWithRetry(query: string): Promise<Response> {\n const MAX_RETRIES = 6;\n const FETCH_OVERHEAD_MS = 30_000;\n const BACKOFF_429_MS = [20_000, 45_000, 90_000, 120_000, 180_000, 240_000];\n const BACKOFF_504_MS = [10_000, 20_000, 45_000, 90_000, 120_000, 180_000];\n\n const endpoint = LoadOsmFromOverpassApiUseCase.OVERPASS_ENDPOINT;\n const jitter = (ms: number) => ms * (0.9 + Math.random() * 0.2);\n const wait = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n const isRetryable = (status: number) => status === 429 || status === 503 || status === 504;\n\n await this.waitForSlot();\n\n let consecutive504s = 0;\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n const queryTimeoutS = LoadOsmFromOverpassApiUseCase.QUERY_TIMEOUTS_S[consecutive504s] ?? 10;\n const fetchTimeoutMs = queryTimeoutS * 1000 + FETCH_OVERHEAD_MS;\n const activeQuery = LoadOsmFromOverpassApiUseCase.setQueryTimeout(query, queryTimeoutS);\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), fetchTimeoutMs);\n let response: Response;\n\n try {\n response = await fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: 'data=' + encodeURIComponent(activeQuery),\n signal: controller.signal,\n });\n } catch (networkErr) {\n clearTimeout(timeoutId);\n if (attempt < MAX_RETRIES) {\n const isTimeout = (networkErr as Error)?.name === 'AbortError';\n consecutive504s++;\n const nextTimeoutS = LoadOsmFromOverpassApiUseCase.QUERY_TIMEOUTS_S[consecutive504s] ?? 10;\n const ms = jitter(BACKOFF_504_MS[attempt] ?? 180_000);\n console.warn(\n `[autk-db] Overpass ${isTimeout ? 'fetch timeout' : 'network error'} ` +\n `(attempt ${attempt + 1}/${MAX_RETRIES + 1}): ${networkErr}. ` +\n `Reducing query timeout ${queryTimeoutS}s → ${nextTimeoutS}s. ` +\n `Retrying in ${(ms / 1000).toFixed(0)}s…`,\n );\n await wait(ms);\n continue;\n }\n throw networkErr;\n }\n\n clearTimeout(timeoutId);\n\n if (response.ok) return response;\n\n if (isRetryable(response.status) && attempt < MAX_RETRIES) {\n const backoff = response.status === 504 ? BACKOFF_504_MS : BACKOFF_429_MS;\n const ms = jitter(backoff[attempt] ?? 240_000);\n if (response.status === 504) {\n consecutive504s++;\n const nextTimeoutS = LoadOsmFromOverpassApiUseCase.QUERY_TIMEOUTS_S[consecutive504s] ?? 10;\n console.warn(\n `[autk-db] Overpass 504 (attempt ${attempt + 1}/${MAX_RETRIES + 1}). ` +\n `Reducing query timeout ${queryTimeoutS}s → ${nextTimeoutS}s. ` +\n `Retrying in ${(ms / 1000).toFixed(0)}s…`,\n );\n } else {\n consecutive504s = 0;\n console.warn(\n `[autk-db] Overpass ${response.status} (attempt ${attempt + 1}/${MAX_RETRIES + 1}). ` +\n `Retrying in ${(ms / 1000).toFixed(0)}s…`,\n );\n }\n await wait(ms);\n continue;\n }\n\n throw new Error(`Overpass API error: ${response.status} ${response.statusText}`);\n }\n\n throw new Error('Overpass API: max retries exceeded');\n }\n\n // ---------------------------------------------------------------------------\n // Query builders\n // ---------------------------------------------------------------------------\n\n /**\n * Builds the boundaries query: admin relations + their member ways.\n * Relations are output with `body` only (tags + member IDs); ways get full\n * inline geometry via `out geom qt`.\n */\n private buildBoundariesQuery(queryArea: { geocodeArea: string; areas: string[] }): string {\n const geocodeLine = `area[\"name\"=\"${queryArea.geocodeArea}\"]->.areaMain;`;\n const areaLines: string[] = [];\n const relSelectors: string[] = [];\n const boundaryWaySelectors: string[] = [];\n\n queryArea.areas.forEach((areaName, idx) => {\n const i = idx + 1;\n areaLines.push(`area[\"name\"=\"${areaName}\"](area.areaMain)->.area${i};`);\n areaLines.push(`relation[\"name\"=\"${areaName}\"](area.areaMain)->.rel${i};`);\n areaLines.push(`way(r.rel${i})->.boundaryWays${i};`);\n relSelectors.push(`.rel${i};`);\n boundaryWaySelectors.push(`.boundaryWays${i};`);\n });\n\n return `\n [out:json][timeout:60][maxsize:134217728];\n\n ${geocodeLine}\n ${areaLines.join('\\n ')}\n\n ( ${relSelectors.join(' ')} );\n out body;\n\n ( ${boundaryWaySelectors.join(' ')} );\n out geom qt;\n `;\n }\n\n /**\n * Builds a query for a specific group of layers.\n * Returns null when no tag selectors apply to the given group (e.g. surface-only).\n */\n private buildLayerGroupQuery(\n queryArea: { geocodeArea: string; areas: string[] },\n layerGroup: string[],\n ): string | null {\n const tagSelectors = this.getTagSelectorsForLayers(layerGroup);\n if (tagSelectors.way.length === 0 && tagSelectors.relation.length === 0) return null;\n\n const geocodeLine = `area[\"name\"=\"${queryArea.geocodeArea}\"]->.areaMain;`;\n const areaLines: string[] = [];\n const dataWaySelectors: string[] = [];\n const dataRelationSelectors: string[] = [];\n const relationWaySelectors: string[] = [];\n\n queryArea.areas.forEach((areaName, idx) => {\n const i = idx + 1;\n areaLines.push(`area[\"name\"=\"${areaName}\"](area.areaMain)->.area${i};`);\n if (tagSelectors.way.length > 0) {\n areaLines.push(`(\n ${tagSelectors.way.map(filter => `way[${filter}](area.area${i});`).join('\\n ')}\n )->.dataWays${i};`);\n dataWaySelectors.push(`.dataWays${i};`);\n }\n if (tagSelectors.relation.length > 0) {\n areaLines.push(`(\n ${tagSelectors.relation.map(filter => `relation[${filter}](area.area${i});`).join('\\n ')}\n )->.dataRelations${i};`);\n areaLines.push(`way(r.dataRelations${i})->.dataRelationWays${i};`);\n dataRelationSelectors.push(`.dataRelations${i};`);\n relationWaySelectors.push(`.dataRelationWays${i};`);\n }\n });\n\n const allWaySelectors = [...dataWaySelectors, ...relationWaySelectors];\n const relationOutput = dataRelationSelectors.length > 0\n ? `\n ( ${dataRelationSelectors.join(' ')} );\n out body;`\n : '';\n const wayOutput = allWaySelectors.length > 0\n ? `\n ( ${allWaySelectors.join(' ')} );\n out geom qt;`\n : '';\n\n return `\n [out:json][timeout:60][maxsize:268435456];\n\n ${geocodeLine}\n ${areaLines.join('\\n ')}\n ${relationOutput}\n ${wayOutput}\n `;\n }\n\n /**\n * Returns Overpass tag filter expressions for the requested layers.\n * Uses value-level specificity for `natural` to avoid fetching unused types\n * (coastline, beach, cliff, etc.). `surface` needs no selectors — its ways\n * come from `way(r.rel)` in the boundaries query.\n */\n private getTagSelectorsForLayers(layers: string[]): OverpassTagSelectors {\n const wayFilters = new Set<string>();\n const relationFilters = new Set<string>();\n\n for (const layer of layers) {\n switch (layer) {\n case 'roads':\n wayFilters.add(`\"highway\"][\"area\"!=\"yes\"][\"highway\"!~\"^(${EXCLUDED_HIGHWAY_VALUES.join('|')})$\"`);\n break;\n case 'buildings':\n wayFilters.add(`\"building\"][${this.buildExcludedValueSelector('building', EXCLUDED_BUILDING_VALUES)}]`);\n wayFilters.add(`\"building:part\"][${this.buildExcludedValueSelector('building:part', EXCLUDED_BUILDING_VALUES)}]`);\n wayFilters.add(`\"type\"=\"building\"`);\n relationFilters.add(`\"building\"][${this.buildExcludedValueSelector('building', EXCLUDED_BUILDING_VALUES)}]`);\n relationFilters.add(`\"building:part\"][${this.buildExcludedValueSelector('building:part', EXCLUDED_BUILDING_VALUES)}]`);\n break;\n case 'parks':\n wayFilters.add(this.buildExactValueSelector('leisure', PARKS_LEISURE_VALUES));\n wayFilters.add(this.buildExactValueSelector('landuse', PARKS_LANDUSE_VALUES));\n wayFilters.add(this.buildExactValueSelector('natural', PARKS_NATURAL_VALUES));\n relationFilters.add(this.buildExactValueSelector('leisure', PARKS_LEISURE_VALUES));\n relationFilters.add(this.buildExactValueSelector('landuse', PARKS_LANDUSE_VALUES));\n relationFilters.add(this.buildExactValueSelector('natural', PARKS_NATURAL_VALUES));\n break;\n case 'water':\n wayFilters.add(this.buildExactValueSelector('natural', WATER_NATURAL_VALUES));\n wayFilters.add(this.buildExactValueSelector('water', WATER_FEATURE_VALUES));\n relationFilters.add(this.buildExactValueSelector('natural', WATER_NATURAL_VALUES));\n relationFilters.add(this.buildExactValueSelector('water', WATER_FEATURE_VALUES));\n break;\n case 'surface':\n break;\n }\n }\n\n return {\n way: [...wayFilters],\n relation: [...relationFilters],\n };\n }\n\n private buildExactValueSelector(key: string, values: readonly string[]): string {\n return `\"${key}\"~\"^(${values.join('|')})$\"`;\n }\n\n private buildExcludedValueSelector(key: string, values: readonly string[]): string {\n return `\"${key}\"!~\"^(${values.join('|')})$\"`;\n }\n\n /**\n * Returns `cols × rows` Overpass queries that together cover `bbox`, each\n * using a combined area + tile-bbox filter so only features inside both the\n * named OSM area and the tile are returned. 256 MB maxsize per tile keeps\n * each response well within Overpass limits.\n */\n private buildBuildingsTileQueries(\n queryArea: { geocodeArea: string; areas: string[] },\n bbox: { south: number; north: number; west: number; east: number },\n cols = 2,\n rows = 2,\n ): string[] {\n const latStep = (bbox.north - bbox.south) / rows;\n const lonStep = (bbox.east - bbox.west) / cols;\n const queries: string[] = [];\n\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < cols; col++) {\n const south = bbox.south + row * latStep;\n const north = south + latStep;\n const west = bbox.west + col * lonStep;\n const east = west + lonStep;\n const tileBbox = `${south},${west},${north},${east}`;\n\n const geocodeLine = `area[\"name\"=\"${queryArea.geocodeArea}\"]->.areaMain;`;\n const areaLines: string[] = [];\n const dataWaySelectors: string[] = [];\n const dataRelationSelectors: string[] = [];\n const relationWaySelectors: string[] = [];\n\n queryArea.areas.forEach((areaName, idx) => {\n const i = idx + 1;\n areaLines.push(`area[\"name\"=\"${areaName}\"](area.areaMain)->.area${i};`);\n areaLines.push(`(\n way[\"building\"][${this.buildExcludedValueSelector('building', EXCLUDED_BUILDING_VALUES)}](area.area${i})(${tileBbox});\n way[\"building:part\"][${this.buildExcludedValueSelector('building:part', EXCLUDED_BUILDING_VALUES)}](area.area${i})(${tileBbox});\n way[\"type\"=\"building\"](area.area${i})(${tileBbox});\n )->.dataWays${i};`);\n dataWaySelectors.push(`.dataWays${i};`);\n areaLines.push(`(\n relation[\"building\"][${this.buildExcludedValueSelector('building', EXCLUDED_BUILDING_VALUES)}](area.area${i})(${tileBbox});\n relation[\"building:part\"][${this.buildExcludedValueSelector('building:part', EXCLUDED_BUILDING_VALUES)}](area.area${i})(${tileBbox});\n )->.dataRelations${i};`);\n areaLines.push(`way(r.dataRelations${i})->.dataRelationWays${i};`);\n dataRelationSelectors.push(`.dataRelations${i};`);\n relationWaySelectors.push(`.dataRelationWays${i};`);\n });\n\n const allWaySelectors = [...dataWaySelectors, ...relationWaySelectors];\n\n queries.push(`\n [out:json][timeout:60][maxsize:268435456];\n\n ${geocodeLine}\n ${areaLines.join('\\n ')}\n\n ( ${dataRelationSelectors.join(' ')} );\n out body;\n\n ( ${allWaySelectors.join(' ')} );\n out geom qt;\n `);\n }\n }\n\n return queries;\n }\n\n /** Merges two Overpass responses, deduplicating all elements by (type, id). */\n private mergeResponses(a: OverpassApiResponse, b: OverpassApiResponse): OverpassApiResponse {\n const existingIds = new Set<string>();\n for (const e of a.elements) {\n existingIds.add(`${e.type}:${e.id}`);\n }\n const dedupedB = b.elements.filter(e => !existingIds.has(`${e.type}:${e.id}`));\n return { elements: [...a.elements, ...dedupedB] };\n }\n\n}\n","\nconst SHIFT_LEFT_32 = (1 << 16) * (1 << 16);\nconst SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32;\n\n// Threshold chosen based on both benchmarking and knowledge about browser string\n// data structures (which currently switch structure types at 12 bytes or more)\nconst TEXT_DECODER_MIN_LENGTH = 12;\nconst utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8');\n\nconst PBF_VARINT = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum\nconst PBF_FIXED64 = 1; // 64-bit: double, fixed64, sfixed64\nconst PBF_BYTES = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields\nconst PBF_FIXED32 = 5; // 32-bit: float, fixed32, sfixed32\n\nexport default class Pbf {\n /**\n * @param {Uint8Array | ArrayBuffer} [buf]\n */\n constructor(buf = new Uint8Array(16)) {\n this.buf = ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf);\n this.dataView = new DataView(this.buf.buffer);\n this.pos = 0;\n this.type = 0;\n this.length = this.buf.length;\n }\n\n // === READING =================================================================\n\n /**\n * @template T\n * @param {(tag: number, result: T, pbf: Pbf) => void} readField\n * @param {T} result\n * @param {number} [end]\n */\n readFields(readField, result, end = this.length) {\n while (this.pos < end) {\n const val = this.readVarint(),\n tag = val >> 3,\n startPos = this.pos;\n\n this.type = val & 0x7;\n readField(tag, result, this);\n\n if (this.pos === startPos) this.skip(val);\n }\n return result;\n }\n\n /**\n * @template T\n * @param {(tag: number, result: T, pbf: Pbf) => void} readField\n * @param {T} result\n */\n readMessage(readField, result) {\n return this.readFields(readField, result, this.readVarint() + this.pos);\n }\n\n readFixed32() {\n const val = this.dataView.getUint32(this.pos, true);\n this.pos += 4;\n return val;\n }\n\n readSFixed32() {\n const val = this.dataView.getInt32(this.pos, true);\n this.pos += 4;\n return val;\n }\n\n // 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)\n\n readFixed64() {\n const val = this.dataView.getUint32(this.pos, true) + this.dataView.getUint32(this.pos + 4, true) * SHIFT_LEFT_32;\n this.pos += 8;\n return val;\n }\n\n readSFixed64() {\n const val = this.dataView.getUint32(this.pos, true) + this.dataView.getInt32(this.pos + 4, true) * SHIFT_LEFT_32;\n this.pos += 8;\n return val;\n }\n\n readFloat() {\n const val = this.dataView.getFloat32(this.pos, true);\n this.pos += 4;\n return val;\n }\n\n readDouble() {\n const val = this.dataView.getFloat64(this.pos, true);\n this.pos += 8;\n return val;\n }\n\n /**\n * @param {boolean} [isSigned]\n */\n readVarint(isSigned) {\n const buf = this.buf;\n let val, b;\n\n b = buf[this.pos++]; val = b & 0x7f; if (b < 0x80) return val;\n b = buf[this.pos++]; val |= (b & 0x7f) << 7; if (b < 0x80) return val;\n b = buf[this.pos++]; val |= (b & 0x7f) << 14; if (b < 0x80) return val;\n b = buf[this.pos++]; val |= (b & 0x7f) << 21; if (b < 0x80) return val;\n b = buf[this.pos]; val |= (b & 0x0f) << 28;\n\n return readVarintRemainder(val, isSigned, this);\n }\n\n readVarint64() { // for compatibility with v2.0.1\n return this.readVarint(true);\n }\n\n readSVarint() {\n const num = this.readVarint();\n return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding\n }\n\n readBoolean() {\n return Boolean(this.readVarint());\n }\n\n readString() {\n const end = this.readVarint() + this.pos;\n const pos = this.pos;\n this.pos = end;\n\n if (end - pos >= TEXT_DECODER_MIN_LENGTH && utf8TextDecoder) {\n // longer strings are fast with the built-in browser TextDecoder API\n return utf8TextDecoder.decode(this.buf.subarray(pos, end));\n }\n // short strings are fast with our custom implementation\n return readUtf8(this.buf, pos, end);\n }\n\n readBytes() {\n const end = this.readVarint() + this.pos,\n buffer = this.buf.subarray(this.pos, end);\n this.pos = end;\n return buffer;\n }\n\n // verbose for performance reasons; doesn't affect gzipped size\n\n /**\n * @param {number[]} [arr]\n * @param {boolean} [isSigned]\n */\n readPackedVarint(arr = [], isSigned) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readVarint(isSigned));\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedSVarint(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readSVarint());\n return arr;\n }\n /** @param {boolean[]} [arr] */\n readPackedBoolean(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readBoolean());\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedFloat(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readFloat());\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedDouble(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readDouble());\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedFixed32(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readFixed32());\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedSFixed32(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readSFixed32());\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedFixed64(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readFixed64());\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedSFixed64(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readSFixed64());\n return arr;\n }\n readPackedEnd() {\n return this.type === PBF_BYTES ? this.readVarint() + this.pos : this.pos + 1;\n }\n\n /** @param {number} val */\n skip(val) {\n const type = val & 0x7;\n if (type === PBF_VARINT) while (this.buf[this.pos++] > 0x7f) {}\n else if (type === PBF_BYTES) this.pos = this.readVarint() + this.pos;\n else if (type === PBF_FIXED32) this.pos += 4;\n else if (type === PBF_FIXED64) this.pos += 8;\n else throw new Error(`Unimplemented type: ${type}`);\n }\n\n // === WRITING =================================================================\n\n /**\n * @param {number} tag\n * @param {number} type\n */\n writeTag(tag, type) {\n this.writeVarint((tag << 3) | type);\n }\n\n /** @param {number} min */\n realloc(min) {\n let length = this.length || 16;\n\n while (length < this.pos + min) length *= 2;\n\n if (length !== this.length) {\n const buf = new Uint8Array(length);\n buf.set(this.buf);\n this.buf = buf;\n this.dataView = new DataView(buf.buffer);\n this.length = length;\n }\n }\n\n finish() {\n this.length = this.pos;\n this.pos = 0;\n return this.buf.subarray(0, this.length);\n }\n\n /** @param {number} val */\n writeFixed32(val) {\n this.realloc(4);\n this.dataView.setInt32(this.pos, val, true);\n this.pos += 4;\n }\n\n /** @param {number} val */\n writeSFixed32(val) {\n this.realloc(4);\n this.dataView.setInt32(this.pos, val, true);\n this.pos += 4;\n }\n\n /** @param {number} val */\n writeFixed64(val) {\n this.realloc(8);\n this.dataView.setInt32(this.pos, val & -1, true);\n this.dataView.setInt32(this.pos + 4, Math.floor(val * SHIFT_RIGHT_32), true);\n this.pos += 8;\n }\n\n /** @param {number} val */\n writeSFixed64(val) {\n this.realloc(8);\n this.dataView.setInt32(this.pos, val & -1, true);\n this.dataView.setInt32(this.pos + 4, Math.floor(val * SHIFT_RIGHT_32), true);\n this.pos += 8;\n }\n\n /** @param {number} val */\n writeVarint(val) {\n val = +val || 0;\n\n if (val > 0xfffffff || val < 0) {\n writeBigVarint(val, this);\n return;\n }\n\n this.realloc(4);\n\n this.buf[this.pos++] = val & 0x7f | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;\n this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;\n this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;\n this.buf[this.pos++] = (val >>> 7) & 0x7f;\n }\n\n /** @param {number} val */\n writeSVarint(val) {\n this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);\n }\n\n /** @param {boolean} val */\n writeBoolean(val) {\n this.writeVarint(+val);\n }\n\n /** @param {string} str */\n writeString(str) {\n str = String(str);\n this.realloc(str.length * 4);\n\n this.pos++; // reserve 1 byte for short string length\n\n const startPos = this.pos;\n // write the string directly to the buffer and see how much was written\n this.pos = writeUtf8(this.buf, str, this.pos);\n const len = this.pos - startPos;\n\n if (len >= 0x80) makeRoomForExtraLength(startPos, len, this);\n\n // finally, write the message length in the reserved place and restore the position\n this.pos = startPos - 1;\n this.writeVarint(len);\n this.pos += len;\n }\n\n /** @param {number} val */\n writeFloat(val) {\n this.realloc(4);\n this.dataView.setFloat32(this.pos, val, true);\n this.pos += 4;\n }\n\n /** @param {number} val */\n writeDouble(val) {\n this.realloc(8);\n this.dataView.setFloat64(this.pos, val, true);\n this.pos += 8;\n }\n\n /** @param {Uint8Array} buffer */\n writeBytes(buffer) {\n const len = buffer.length;\n this.writeVarint(len);\n this.realloc(len);\n for (let i = 0; i < len; i++) this.buf[this.pos++] = buffer[i];\n }\n\n /**\n * @template T\n * @param {(obj: T, pbf: Pbf) => void} fn\n * @param {T} obj\n */\n writeRawMessage(fn, obj) {\n this.pos++; // reserve 1 byte for short message length\n\n // write the message directly to the buffer and see how much was written\n const startPos = this.pos;\n fn(obj, this);\n const len = this.pos - startPos;\n\n if (len >= 0x80) makeRoomForExtraLength(startPos, len, this);\n\n // finally, write the message length in the reserved place and restore the position\n this.pos = startPos - 1;\n this.writeVarint(len);\n this.pos += len;\n }\n\n /**\n * @template T\n * @param {number} tag\n * @param {(obj: T, pbf: Pbf) => void} fn\n * @param {T} obj\n */\n writeMessage(tag, fn, obj) {\n this.writeTag(tag, PBF_BYTES);\n this.writeRawMessage(fn, obj);\n }\n\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedVarint(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedVarint, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedSVarint(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedSVarint, arr);\n }\n /**\n * @param {number} tag\n * @param {boolean[]} arr\n */\n writePackedBoolean(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedBoolean, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedFloat(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedFloat, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedDouble(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedDouble, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedFixed32(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedFixed32, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedSFixed32(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedSFixed32, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedFixed64(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedFixed64, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedSFixed64(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedSFixed64, arr);\n }\n\n /**\n * @param {number} tag\n * @param {Uint8Array} buffer\n */\n writeBytesField(tag, buffer) {\n this.writeTag(tag, PBF_BYTES);\n this.writeBytes(buffer);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeFixed32Field(tag, val) {\n this.writeTag(tag, PBF_FIXED32);\n this.writeFixed32(val);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeSFixed32Field(tag, val) {\n this.writeTag(tag, PBF_FIXED32);\n this.writeSFixed32(val);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeFixed64Field(tag, val) {\n this.writeTag(tag, PBF_FIXED64);\n this.writeFixed64(val);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeSFixed64Field(tag, val) {\n this.writeTag(tag, PBF_FIXED64);\n this.writeSFixed64(val);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeVarintField(tag, val) {\n this.writeTag(tag, PBF_VARINT);\n this.writeVarint(val);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeSVarintField(tag, val) {\n this.writeTag(tag, PBF_VARINT);\n this.writeSVarint(val);\n }\n /**\n * @param {number} tag\n * @param {string} str\n */\n writeStringField(tag, str) {\n this.writeTag(tag, PBF_BYTES);\n this.writeString(str);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeFloatField(tag, val) {\n this.writeTag(tag, PBF_FIXED32);\n this.writeFloat(val);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeDoubleField(tag, val) {\n this.writeTag(tag, PBF_FIXED64);\n this.writeDouble(val);\n }\n /**\n * @param {number} tag\n * @param {boolean} val\n */\n writeBooleanField(tag, val) {\n this.writeVarintField(tag, +val);\n }\n};\n\n/**\n * @param {number} l\n * @param {boolean | undefined} s\n * @param {Pbf} p\n */\nfunction readVarintRemainder(l, s, p) {\n const buf = p.buf;\n let h, b;\n\n b = buf[p.pos++]; h = (b & 0x70) >> 4; if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++]; h |= (b & 0x7f) << 3; if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++]; h |= (b & 0x7f) << 10; if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++]; h |= (b & 0x7f) << 17; if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++]; h |= (b & 0x7f) << 24; if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++]; h |= (b & 0x01) << 31; if (b < 0x80) return toNum(l, h, s);\n\n throw new Error('Expected varint not more than 10 bytes');\n}\n\n/**\n * @param {number} low\n * @param {number} high\n * @param {boolean} [isSigned]\n */\nfunction toNum(low, high, isSigned) {\n return isSigned ? high * 0x100000000 + (low >>> 0) : ((high >>> 0) * 0x100000000) + (low >>> 0);\n}\n\n/**\n * @param {number} val\n * @param {Pbf} pbf\n */\nfunction writeBigVarint(val, pbf) {\n let low, high;\n\n if (val >= 0) {\n low = (val % 0x100000000) | 0;\n high = (val / 0x100000000) | 0;\n } else {\n low = ~(-val % 0x100000000);\n high = ~(-val / 0x100000000);\n\n if (low ^ 0xffffffff) {\n low = (low + 1) | 0;\n } else {\n low = 0;\n high = (high + 1) | 0;\n }\n }\n\n if (val >= 0x10000000000000000 || val < -0x10000000000000000) {\n throw new Error('Given varint doesn\\'t fit into 10 bytes');\n }\n\n pbf.realloc(10);\n\n writeBigVarintLow(low, high, pbf);\n writeBigVarintHigh(high, pbf);\n}\n\n/**\n * @param {number} high\n * @param {number} low\n * @param {Pbf} pbf\n */\nfunction writeBigVarintLow(low, high, pbf) {\n pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;\n pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;\n pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;\n pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;\n pbf.buf[pbf.pos] = low & 0x7f;\n}\n\n/**\n * @param {number} high\n * @param {Pbf} pbf\n */\nfunction writeBigVarintHigh(high, pbf) {\n const lsb = (high & 0x07) << 4;\n\n pbf.buf[pbf.pos++] |= lsb | ((high >>>= 3) ? 0x80 : 0); if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f;\n}\n\n/**\n * @param {number} startPos\n * @param {number} len\n * @param {Pbf} pbf\n */\nfunction makeRoomForExtraLength(startPos, len, pbf) {\n const extraLen =\n len <= 0x3fff ? 1 :\n len <= 0x1fffff ? 2 :\n len <= 0xfffffff ? 3 : Math.floor(Math.log(len) / (Math.LN2 * 7));\n\n // if 1 byte isn't enough for encoding message length, shift the data to the right\n pbf.realloc(extraLen);\n for (let i = pbf.pos - 1; i >= startPos; i--) pbf.buf[i + extraLen] = pbf.buf[i];\n}\n\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedVarint(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeVarint(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedSVarint(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeSVarint(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedFloat(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeFloat(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedDouble(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeDouble(arr[i]);\n}\n/**\n * @param {boolean[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedBoolean(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeBoolean(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedFixed32(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeFixed32(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedSFixed32(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeSFixed32(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedFixed64(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeFixed64(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedSFixed64(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeSFixed64(arr[i]);\n}\n\n// Buffer code below from https://github.com/feross/buffer, MIT-licensed\n\n/**\n * @param {Uint8Array} buf\n * @param {number} pos\n * @param {number} end\n */\nfunction readUtf8(buf, pos, end) {\n let str = '';\n let i = pos;\n\n while (i < end) {\n const b0 = buf[i];\n let c = null; // codepoint\n let bytesPerSequence =\n b0 > 0xEF ? 4 :\n b0 > 0xDF ? 3 :\n b0 > 0xBF ? 2 : 1;\n\n if (i + bytesPerSequence > end) break;\n\n let b1, b2, b3;\n\n if (bytesPerSequence === 1) {\n if (b0 < 0x80) {\n c = b0;\n }\n } else if (bytesPerSequence === 2) {\n b1 = buf[i + 1];\n if ((b1 & 0xC0) === 0x80) {\n c = (b0 & 0x1F) << 0x6 | (b1 & 0x3F);\n if (c <= 0x7F) {\n c = null;\n }\n }\n } else if (bytesPerSequence === 3) {\n b1 = buf[i + 1];\n b2 = buf[i + 2];\n if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80) {\n c = (b0 & 0xF) << 0xC | (b1 & 0x3F) << 0x6 | (b2 & 0x3F);\n if (c <= 0x7FF || (c >= 0xD800 && c <= 0xDFFF)) {\n c = null;\n }\n }\n } else if (bytesPerSequence === 4) {\n b1 = buf[i + 1];\n b2 = buf[i + 2];\n b3 = buf[i + 3];\n if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {\n c = (b0 & 0xF) << 0x12 | (b1 & 0x3F) << 0xC | (b2 & 0x3F) << 0x6 | (b3 & 0x3F);\n if (c <= 0xFFFF || c >= 0x110000) {\n c = null;\n }\n }\n }\n\n if (c === null) {\n c = 0xFFFD;\n bytesPerSequence = 1;\n\n } else if (c > 0xFFFF) {\n c -= 0x10000;\n str += String.fromCharCode(c >>> 10 & 0x3FF | 0xD800);\n c = 0xDC00 | c & 0x3FF;\n }\n\n str += String.fromCharCode(c);\n i += bytesPerSequence;\n }\n\n return str;\n}\n\n/**\n * @param {Uint8Array} buf\n * @param {string} str\n * @param {number} pos\n */\nfunction writeUtf8(buf, str, pos) {\n for (let i = 0, c, lead; i < str.length; i++) {\n c = str.charCodeAt(i); // code point\n\n if (c > 0xD7FF && c < 0xE000) {\n if (lead) {\n if (c < 0xDC00) {\n buf[pos++] = 0xEF;\n buf[pos++] = 0xBF;\n buf[pos++] = 0xBD;\n lead = c;\n continue;\n } else {\n c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000;\n lead = null;\n }\n } else {\n if (c > 0xDBFF || (i + 1 === str.length)) {\n buf[pos++] = 0xEF;\n buf[pos++] = 0xBF;\n buf[pos++] = 0xBD;\n } else {\n lead = c;\n }\n continue;\n }\n } else if (lead) {\n buf[pos++] = 0xEF;\n buf[pos++] = 0xBF;\n buf[pos++] = 0xBD;\n lead = null;\n }\n\n if (c < 0x80) {\n buf[pos++] = c;\n } else {\n if (c < 0x800) {\n buf[pos++] = c >> 0x6 | 0xC0;\n } else {\n if (c < 0x10000) {\n buf[pos++] = c >> 0xC | 0xE0;\n } else {\n buf[pos++] = c >> 0x12 | 0xF0;\n buf[pos++] = c >> 0xC & 0x3F | 0x80;\n }\n buf[pos++] = c >> 0x6 & 0x3F | 0x80;\n }\n buf[pos++] = c & 0x3F | 0x80;\n }\n }\n return pos;\n}\n","/**\n * Reads an `OsmPbfHeaderBlock` message from the provided Pbf reader.\n */\nexport function readHeaderBlock(pbf, end) {\n return pbf.readFields(readHeaderBlockField, {\n required_features: [],\n optional_features: [],\n }, end);\n}\n/**\n * Populates header block fields based on the protobuf tag encountered.\n */\nfunction readHeaderBlockField(tag, obj, pbf) {\n if (tag === 1)\n obj.bbox = readHeaderBBox(pbf, pbf.readVarint() + pbf.pos);\n else if (tag === 4)\n obj.required_features.push(pbf.readString());\n else if (tag === 5)\n obj.optional_features.push(pbf.readString());\n else if (tag === 16)\n obj.writingprogram = pbf.readString();\n else if (tag === 17)\n obj.source = pbf.readString();\n else if (tag === 32)\n obj.osmosis_replication_timestamp = pbf.readVarint(true);\n else if (tag === 33) {\n obj.osmosis_replication_sequence_number = pbf.readVarint(true);\n }\n else if (tag === 34)\n obj.osmosis_replication_base_url = pbf.readString();\n}\n/**\n * Serializes an `OsmPbfHeaderBlock` message into the Pbf writer.\n */\nexport function writeHeaderBlock(obj, pbf) {\n if (obj.bbox)\n pbf.writeMessage(1, writeHeaderBBox, obj.bbox);\n if (obj.required_features) {\n for (const item of obj.required_features)\n pbf.writeStringField(4, item);\n }\n if (obj.optional_features) {\n for (const item of obj.optional_features)\n pbf.writeStringField(5, item);\n }\n if (obj.writingprogram)\n pbf.writeStringField(16, obj.writingprogram);\n if (obj.source)\n pbf.writeStringField(17, obj.source);\n if (obj.osmosis_replication_timestamp) {\n pbf.writeVarintField(32, obj.osmosis_replication_timestamp);\n }\n if (obj.osmosis_replication_sequence_number) {\n pbf.writeVarintField(33, obj.osmosis_replication_sequence_number);\n }\n if (obj.osmosis_replication_base_url) {\n pbf.writeStringField(34, obj.osmosis_replication_base_url);\n }\n}\n/**\n * Reads a header bounding box and converts nanodegrees to degrees.\n */\nfunction readHeaderBBox(pbf, end) {\n return pbf.readFields(readHeaderBBoxField, { left: 0, right: 0, top: 0, bottom: 0 }, end);\n}\n/**\n * Populates bounding box properties while converting from nanodegrees.\n */\nfunction readHeaderBBoxField(tag, obj, pbf) {\n if (tag === 1)\n obj.left = pbf.readSVarint() / 1e9;\n else if (tag === 2)\n obj.right = pbf.readSVarint() / 1e9;\n else if (tag === 3)\n obj.top = pbf.readSVarint() / 1e9;\n else if (tag === 4)\n obj.bottom = pbf.readSVarint() / 1e9;\n}\n/**\n * Serializes a header bounding box, converting degrees back to nanodegrees.\n */\nfunction writeHeaderBBox(obj, pbf) {\n if (obj.left)\n pbf.writeSVarintField(1, obj.left * 1e9);\n if (obj.right)\n pbf.writeSVarintField(2, obj.right * 1e9);\n if (obj.top)\n pbf.writeSVarintField(3, obj.top * 1e9);\n if (obj.bottom)\n pbf.writeSVarintField(4, obj.bottom * 1e9);\n}\n/**\n * Reads a primitive block containing string tables and primitive groups.\n */\nexport function readPrimitiveBlock(pbf, end) {\n return pbf.readFields(readPrimitiveBlockField, {\n stringtable: [],\n primitivegroup: [],\n }, end);\n}\n/**\n * Populates primitive block fields based on protobuf tags.\n */\nfunction readPrimitiveBlockField(tag, obj, pbf) {\n if (tag === 1) {\n obj.stringtable = readStringTable(pbf, pbf.readVarint() + pbf.pos);\n }\n else if (tag === 2) {\n obj.primitivegroup.push(readPrimitiveGroup(pbf, pbf.readVarint() + pbf.pos));\n }\n else if (tag === 17) {\n obj.granularity = pbf.readVarint(true);\n obj.granularity = !obj.granularity ? 1e7 : 1e9 / obj.granularity;\n }\n else if (tag === 19)\n obj.lat_offset = pbf.readVarint(true) * 1e-9;\n else if (tag === 20)\n obj.lon_offset = pbf.readVarint(true) * 1e-9;\n else if (tag === 18)\n obj.date_granularity = pbf.readVarint(true) ?? 1000;\n}\n/**\n * Serializes a primitive block including its string table and primitive groups.\n */\nexport function writePrimitiveBlock(obj, pbf) {\n if (obj.stringtable)\n pbf.writeMessage(1, writeStringTable, obj.stringtable);\n if (obj.primitivegroup) {\n for (const item of obj.primitivegroup) {\n pbf.writeMessage(2, writePrimitiveGroup, item);\n }\n }\n if (obj.granularity != null && obj.granularity !== 1e7) {\n pbf.writeVarintField(17, 1e9 / obj.granularity);\n }\n if (obj.lat_offset)\n pbf.writeVarintField(19, obj.lat_offset / 1e-9);\n if (obj.lon_offset)\n pbf.writeVarintField(20, obj.lon_offset / 1e-9);\n if (obj.date_granularity != null && obj.date_granularity !== 1000) {\n pbf.writeVarintField(18, obj.date_granularity);\n }\n}\n/**\n * Reads a primitive group with collections of primitives.\n */\nfunction readPrimitiveGroup(pbf, end) {\n return pbf.readFields(readPrimitiveGroupField, { nodes: [], ways: [], relations: [] }, end);\n}\n/**\n * Populates primitive group collections from protobuf data.\n */\nfunction readPrimitiveGroupField(tag, obj, pbf) {\n if (tag === 1)\n obj.nodes.push(readNode(pbf, pbf.readVarint() + pbf.pos));\n else if (tag === 2) {\n obj.dense = readDenseNodes(pbf, pbf.readVarint() + pbf.pos);\n }\n else if (tag === 3)\n obj.ways.push(readWay(pbf, pbf.readVarint() + pbf.pos));\n else if (tag === 4) {\n obj.relations.push(readRelation(pbf, pbf.readVarint() + pbf.pos));\n }\n}\n/**\n * Serializes a primitive group to protobuf.\n */\nfunction writePrimitiveGroup(obj, pbf) {\n if (obj.nodes) {\n for (const item of obj.nodes)\n pbf.writeMessage(1, writeNode, item);\n }\n if (obj.dense)\n pbf.writeMessage(2, writeDenseNodes, obj.dense);\n if (obj.ways) {\n for (const item of obj.ways)\n pbf.writeMessage(3, writeWay, item);\n }\n if (obj.relations) {\n for (const item of obj.relations)\n pbf.writeMessage(4, writeRelation, item);\n }\n}\n/**\n * Reads the shared string table for a primitive block.\n */\nfunction readStringTable(pbf, end) {\n return pbf.readFields(readStringTableField, [], end);\n}\n/**\n * Appends string table entries as they are encountered.\n */\nfunction readStringTableField(tag, obj, pbf) {\n if (tag === 1)\n obj.push(pbf.readBytes());\n}\n/**\n * Serializes string table entries.\n */\nfunction writeStringTable(obj, pbf) {\n if (obj) {\n for (const item of obj)\n pbf.writeBytesField(1, item);\n }\n}\n/**\n * Reads metadata describing a single primitive.\n */\nfunction readInfo(pbf, end) {\n return pbf.readFields(readInfoField, {}, end);\n}\n/**\n * Populates primitive metadata fields.\n */\nfunction readInfoField(tag, obj, pbf) {\n if (tag === 1)\n obj.version = pbf.readVarint(true);\n else if (tag === 2)\n obj.timestamp = pbf.readVarint(true);\n else if (tag === 3)\n obj.changeset = pbf.readVarint(true);\n else if (tag === 4)\n obj.uid = pbf.readVarint(true);\n else if (tag === 5)\n obj.user_sid = pbf.readVarint();\n else if (tag === 6)\n obj.visible = pbf.readBoolean();\n}\n/**\n * Serializes primitive metadata fields.\n */\nfunction writeInfo(obj, pbf) {\n if (obj.version != null && obj.version !== -1) {\n pbf.writeVarintField(1, obj.version);\n }\n if (obj.timestamp)\n pbf.writeVarintField(2, obj.timestamp);\n if (obj.changeset)\n pbf.writeVarintField(3, obj.changeset);\n if (obj.uid)\n pbf.writeVarintField(4, obj.uid);\n if (obj.user_sid)\n pbf.writeVarintField(5, obj.user_sid);\n if (obj.visible)\n pbf.writeBooleanField(6, obj.visible);\n}\n/**\n * Reads dense node metadata collections.\n */\nfunction readDenseInfo(pbf, end) {\n return pbf.readFields(readDenseInfoField, {\n version: [],\n timestamp: [],\n changeset: [],\n uid: [],\n user_sid: [],\n visible: [],\n }, end);\n}\n/**\n * Populates dense node metadata arrays from packed fields.\n */\nfunction readDenseInfoField(tag, obj, pbf) {\n if (tag === 1)\n pbf.readPackedVarint(obj.version, true);\n else if (tag === 2)\n pbf.readPackedSVarint(obj.timestamp);\n else if (tag === 3)\n pbf.readPackedSVarint(obj.changeset);\n else if (tag === 4)\n pbf.readPackedSVarint(obj.uid);\n else if (tag === 5)\n pbf.readPackedSVarint(obj.user_sid);\n else if (tag === 6)\n pbf.readPackedBoolean(obj.visible);\n}\n/**\n * Serializes dense node metadata arrays.\n */\nfunction writeDenseInfo(obj, pbf) {\n if (obj.version)\n pbf.writePackedVarint(1, obj.version);\n if (obj.timestamp)\n pbf.writePackedSVarint(2, obj.timestamp);\n if (obj.changeset)\n pbf.writePackedSVarint(3, obj.changeset);\n if (obj.uid)\n pbf.writePackedSVarint(4, obj.uid);\n if (obj.user_sid)\n pbf.writePackedSVarint(5, obj.user_sid);\n if (obj.visible)\n pbf.writePackedBoolean(6, obj.visible);\n}\n/**\n * Reads a node primitive from the protobuf stream.\n */\nfunction readNode(pbf, end) {\n return pbf.readFields(readNodeField, { id: 0, keys: [], vals: [], lat: 0, lon: 0 }, end);\n}\n/**\n * Populates node fields based on protobuf tags.\n */\nfunction readNodeField(tag, obj, pbf) {\n if (tag === 1)\n obj.id = pbf.readSVarint();\n else if (tag === 2)\n pbf.readPackedVarint(obj.keys);\n else if (tag === 3)\n pbf.readPackedVarint(obj.vals);\n else if (tag === 4)\n obj.info = readInfo(pbf, pbf.readVarint() + pbf.pos);\n else if (tag === 8)\n obj.lat = pbf.readSVarint();\n else if (tag === 9)\n obj.lon = pbf.readSVarint();\n}\n/**\n * Serializes a node primitive to protobuf.\n */\nfunction writeNode(obj, pbf) {\n if (obj.id)\n pbf.writeSVarintField(1, obj.id);\n if (obj.keys)\n pbf.writePackedVarint(2, obj.keys);\n if (obj.vals)\n pbf.writePackedVarint(3, obj.vals);\n if (obj.info)\n pbf.writeMessage(4, writeInfo, obj.info);\n if (obj.lat)\n pbf.writeSVarintField(8, obj.lat);\n if (obj.lon)\n pbf.writeSVarintField(9, obj.lon);\n}\n/**\n * Reads dense node collections from the protobuf stream.\n */\nfunction readDenseNodes(pbf, end) {\n return pbf.readFields(readDenseNodesField, { id: [], lat: [], lon: [], keys_vals: [] }, end);\n}\n/**\n * Populates dense node arrays using packed encoding.\n */\nfunction readDenseNodesField(tag, obj, pbf) {\n if (tag === 1)\n pbf.readPackedSVarint(obj.id);\n else if (tag === 5) {\n obj.denseinfo = readDenseInfo(pbf, pbf.readVarint() + pbf.pos);\n }\n else if (tag === 8)\n pbf.readPackedSVarint(obj.lat);\n else if (tag === 9)\n pbf.readPackedSVarint(obj.lon);\n else if (tag === 10)\n pbf.readPackedVarint(obj.keys_vals, true);\n}\n/**\n * Serializes dense node collections back to protobuf.\n */\nfunction writeDenseNodes(obj, pbf) {\n if (obj.id)\n pbf.writePackedSVarint(1, obj.id);\n if (obj.denseinfo)\n pbf.writeMessage(5, writeDenseInfo, obj.denseinfo);\n if (obj.lat)\n pbf.writePackedSVarint(8, obj.lat);\n if (obj.lon)\n pbf.writePackedSVarint(9, obj.lon);\n if (obj.keys_vals)\n pbf.writePackedVarint(10, obj.keys_vals);\n}\n/**\n * Reads a way primitive from the protobuf stream.\n */\nfunction readWay(pbf, end) {\n return pbf.readFields(readWayField, { id: 0, keys: [], vals: [], refs: [], lat: [], lon: [] }, end);\n}\n/**\n * Populates way fields based on protobuf tags.\n */\nfunction readWayField(tag, obj, pbf) {\n if (tag === 1)\n obj.id = pbf.readVarint(true);\n else if (tag === 2)\n pbf.readPackedVarint(obj.keys);\n else if (tag === 3)\n pbf.readPackedVarint(obj.vals);\n else if (tag === 4)\n obj.info = readInfo(pbf, pbf.readVarint() + pbf.pos);\n else if (tag === 8)\n pbf.readPackedSVarint(obj.refs);\n}\n/**\n * Serializes a way primitive to protobuf.\n */\nfunction writeWay(obj, pbf) {\n if (obj.id)\n pbf.writeVarintField(1, obj.id);\n if (obj.keys)\n pbf.writePackedVarint(2, obj.keys);\n if (obj.vals)\n pbf.writePackedVarint(3, obj.vals);\n if (obj.info)\n pbf.writeMessage(4, writeInfo, obj.info);\n if (obj.refs)\n pbf.writePackedSVarint(8, obj.refs);\n}\n/**\n * Reads a relation primitive from the protobuf stream.\n */\nfunction readRelation(pbf, end) {\n return pbf.readFields(readRelationField, {\n id: 0,\n keys: [],\n vals: [],\n roles_sid: [],\n memids: [],\n types: [],\n }, end);\n}\n/**\n * Populates relation fields based on protobuf tags.\n */\nfunction readRelationField(tag, obj, pbf) {\n if (tag === 1)\n obj.id = pbf.readVarint(true);\n else if (tag === 2)\n pbf.readPackedVarint(obj.keys);\n else if (tag === 3)\n pbf.readPackedVarint(obj.vals);\n else if (tag === 4)\n obj.info = readInfo(pbf, pbf.readVarint() + pbf.pos);\n else if (tag === 8)\n pbf.readPackedVarint(obj.roles_sid, true);\n else if (tag === 9)\n pbf.readPackedSVarint(obj.memids);\n else if (tag === 10)\n pbf.readPackedVarint(obj.types);\n}\n/**\n * Serializes a relation primitive to protobuf.\n */\nfunction writeRelation(obj, pbf) {\n if (obj.id)\n pbf.writeVarintField(1, obj.id);\n if (obj.keys)\n pbf.writePackedVarint(2, obj.keys);\n if (obj.vals)\n pbf.writePackedVarint(3, obj.vals);\n if (obj.info)\n pbf.writeMessage(4, writeInfo, obj.info);\n if (obj.roles_sid)\n pbf.writePackedVarint(8, obj.roles_sid);\n if (obj.memids)\n pbf.writePackedSVarint(9, obj.memids);\n if (obj.types)\n pbf.writePackedVarint(10, obj.types);\n}\n//# sourceMappingURL=osmformat.js.map","/**\n * Byte array to stream conversion.\n *\n * Wraps a Uint8Array in a ReadableStream for use with streaming APIs.\n *\n * @module\n */\n/**\n * Create a ReadableStream from a Uint8Array.\n *\n * The stream will emit the entire byte array as a single chunk,\n * then close immediately.\n *\n * @param bytes - The byte array to wrap.\n * @returns A ReadableStream that emits the bytes.\n */\nexport function bytesToStream(bytes) {\n return new ReadableStream({\n start(controller) {\n controller.enqueue(bytes);\n controller.close();\n },\n });\n}\n//# sourceMappingURL=bytes-to-stream.js.map","/**\n * Concatenates multiple `Uint8Array` segments into a contiguous array.\n */\nexport function concatBytes(parts) {\n const total = parts.reduce((n, p) => n + p.length, 0);\n const out = new Uint8Array(new ArrayBuffer(total));\n let offset = 0;\n for (const p of parts) {\n out.set(p, offset);\n offset += p.length;\n }\n return out;\n}\n//# sourceMappingURL=concat-bytes.js.map","/**\n * Stream to byte array conversion.\n *\n * Consumes a ReadableStream and concatenates all chunks into a single Uint8Array.\n *\n * @module\n */\nimport { concatBytes } from \"./concat-bytes.js\";\n/**\n * Consume a ReadableStream and return all data as a single Uint8Array.\n *\n * Reads all chunks from the stream and concatenates them.\n * The stream will be fully consumed after this function returns.\n *\n * @param stream - The stream to consume.\n * @returns A Promise resolving to the concatenated bytes.\n */\nexport async function streamToBytes(stream) {\n const reader = stream.getReader();\n const chunks = [];\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (value !== undefined)\n chunks.push(value);\n }\n return concatBytes(chunks);\n}\n//# sourceMappingURL=stream-to-bytes.js.map","/**\n * Transform stream utilities.\n *\n * Helpers for piping byte arrays through TransformStreams (e.g., compression).\n *\n * @module\n */\nimport { bytesToStream } from \"./bytes-to-stream.js\";\nimport { streamToBytes } from \"./stream-to-bytes.js\";\n/**\n * Pipe a byte array through a TransformStream and return the result.\n *\n * Useful for applying compression/decompression or other transformations\n * to byte data using the Web Streams API.\n *\n * @param bytes - The input bytes.\n * @param transformStream - The transform to apply (e.g., CompressionStream).\n * @returns A Promise resolving to the transformed bytes.\n *\n * @example\n * ```ts\n * const compressed = await transformBytes(data, new CompressionStream('gzip'))\n * ```\n */\nexport async function transformBytes(bytes, transformStream) {\n return streamToBytes(bytesToStream(bytes).pipeThrough(transformStream));\n}\n//# sourceMappingURL=transform-bytes.js.map","import { assertValue as assert } from \"@osmix/shared/assert\";\nimport { transformBytes } from \"@osmix/shared/transform-bytes\";\n/**\n * Normalizes values, streams, and iterables into a unified async generator interface.\n */\nexport async function* toAsyncGenerator(v) {\n if (v instanceof Promise)\n return toAsyncGenerator(await v);\n if (v == null)\n throw Error(\"Value is null\");\n if (v instanceof ReadableStream) {\n const reader = v.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done)\n break;\n yield value;\n }\n reader.releaseLock();\n }\n else if (ArrayBuffer.isView(v) || v instanceof ArrayBuffer) {\n // Treat ArrayBuffer and TypedArrays (like Uint8Array, Buffer) as single values\n yield v;\n }\n else if (typeof v === \"object\" &&\n (Symbol.asyncIterator in v || Symbol.iterator in v)) {\n return v;\n }\n else {\n yield v;\n }\n}\n/**\n * Web decompression stream\n */\nexport async function webDecompress(data) {\n return transformBytes(data, new DecompressionStream(\"deflate\"));\n}\n/**\n * Web compression stream\n */\nexport async function webCompress(data) {\n return transformBytes(data, new CompressionStream(\"deflate\"));\n}\n/**\n * Concatenates multiple `Uint8Array` segments into a contiguous array.\n */\nexport function concatUint8(...parts) {\n const total = parts.reduce((n, p) => n + p.length, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const p of parts) {\n out.set(p, offset);\n offset += p.length;\n }\n return out;\n}\n/**\n * Encodes a 32-bit big-endian unsigned integer as a four-byte buffer.\n */\nexport function uint32BE(n) {\n const out = new Uint8Array(4);\n out[0] = (n >>> 24) & 0xff;\n out[1] = (n >>> 16) & 0xff;\n out[2] = (n >>> 8) & 0xff;\n out[3] = n & 0xff;\n return out;\n}\nexport async function testOsmPbfReader(osm, pbf) {\n assert(JSON.stringify(osm.header.bbox) === JSON.stringify(pbf.bbox), `Header bbox ${JSON.stringify(osm.header.bbox)} != ${JSON.stringify(pbf.bbox)}`);\n const { onGroup, count } = createOsmEntityCounter();\n for await (const block of osm.blocks)\n for (const group of block.primitivegroup)\n onGroup(group);\n assert(count.nodes === pbf.nodes, `Expected nodes: ${pbf.nodes}, got: ${count.nodes}`);\n assert(count.ways === pbf.ways, `Expected ways: ${pbf.ways}, got: ${count.ways}`);\n assert(count.relations === pbf.relations, `Expected relations: ${pbf.relations}, got: ${count.relations}`);\n assert(count.node0 === pbf.node0.id, `Expected node0: ${pbf.node0.id}, got: ${count.node0}`);\n assert(count.way0 === pbf.way0, `Expected way0: ${pbf.way0}, got: ${count.way0}`);\n assert(count.relation0 === pbf.relation0, `Expected relation0: ${pbf.relation0}, got: ${count.relation0}`);\n return count;\n}\nexport function createOsmEntityCounter() {\n const count = {\n nodes: 0,\n ways: 0,\n relations: 0,\n node0: -1,\n way0: -1,\n relation0: -1,\n };\n const onGroup = (group) => {\n if (count.node0 === -1 && group.dense?.id?.[0] != null) {\n count.node0 = group.dense.id[0];\n }\n if (count.way0 === -1 && group.ways?.[0]?.id != null) {\n count.way0 = group.ways[0].id;\n }\n if (count.relation0 === -1 && group.relations?.[0]?.id != null) {\n count.relation0 = group.relations[0].id;\n }\n count.nodes += group.nodes?.length ?? 0;\n if (group.dense) {\n count.nodes += group.dense.id.length;\n }\n count.ways += group.ways?.length ?? 0;\n count.relations += group.relations?.length ?? 0;\n };\n return {\n onGroup,\n count,\n };\n}\n//# sourceMappingURL=utils.js.map","/**\n * Blob-to-block conversion utilities.\n *\n * Handles decompression and protobuf decoding of raw OSM PBF blobs into\n * typed header and primitive block structures.\n *\n * @module\n */\nimport Pbf from \"pbf\";\nimport { readHeaderBlock, readPrimitiveBlock, } from \"./proto/osmformat.js\";\nimport { webDecompress } from \"./utils.js\";\n/**\n * Decompress and decode a stream of raw PBF blobs into typed blocks.\n *\n * This async generator handles the transition from compressed bytes to parsed\n * protobuf structures. The first blob is always decoded as a header block;\n * subsequent blobs are decoded as primitive blocks containing OSM entities.\n *\n * @param blobs - Async or sync generator yielding compressed blob payloads.\n * @param decompress - Optional decompression function (defaults to Web Streams zlib).\n * @yields Header block first, then primitive blocks.\n *\n * @example\n * ```ts\n * import { osmPbfBlobsToBlocksGenerator, createOsmPbfBlobGenerator } from \"@osmix/pbf\"\n *\n * const generateBlobs = createOsmPbfBlobGenerator()\n * const blobsGen = (async function* () {\n * for await (const chunk of stream) {\n * yield* generateBlobs(chunk)\n * }\n * })()\n *\n * for await (const block of osmPbfBlobsToBlocksGenerator(blobsGen)) {\n * // First iteration yields header, rest yield primitive blocks\n * }\n * ```\n */\nexport async function* osmPbfBlobsToBlocksGenerator(blobs, decompress = webDecompress) {\n let headerRead = false;\n for await (const blob of blobs) {\n if (!headerRead) {\n headerRead = true;\n yield readOsmHeaderBlock(blob, decompress);\n }\n else {\n yield readOsmPrimitiveBlock(blob, decompress);\n }\n }\n}\n/**\n * Decompress and parse a header block from a compressed blob.\n *\n * @param compressedBlob - Zlib-compressed protobuf header blob.\n * @param decompress - Optional decompression function.\n * @returns Parsed header block with required/optional features and bbox.\n */\nexport async function readOsmHeaderBlock(compressedBlob, decompress = webDecompress) {\n const decompressedBlob = await decompress(compressedBlob);\n const pbf = new Pbf(decompressedBlob);\n return readHeaderBlock(pbf);\n}\n/**\n * Decompress and parse a primitive block from a compressed blob.\n *\n * @param compressedBlob - Zlib-compressed protobuf primitive blob.\n * @param decompress - Optional decompression function.\n * @returns Parsed primitive block with string table and primitive groups.\n */\nexport async function readOsmPrimitiveBlock(compressedBlob, decompress = webDecompress) {\n const decompressedBlob = await decompress(compressedBlob);\n const pbf = new Pbf(decompressedBlob);\n return readPrimitiveBlock(pbf);\n}\n//# sourceMappingURL=blobs-to-blocks.js.map","/**\n * Reads an `OsmPbfBlob` message from the current position in the Pbf reader.\n */\nexport function readBlob(pbf, end) {\n return pbf.readFields(readBlobField, {\n raw_size: 0,\n }, end);\n}\n/**\n * Dispatches individual Blob fields based on their protobuf tag.\n */\nfunction readBlobField(tag, obj, pbf) {\n if (tag === 2)\n obj.raw_size = pbf.readVarint(true);\n else if (tag === 1) {\n obj.raw = pbf.readBytes();\n }\n else if (tag === 3) {\n obj.zlib_data = pbf.readBytes();\n }\n}\n/**\n * Writes an `OsmPbfBlob` message to the provided Pbf writer.\n */\nexport function writeBlob(obj, pbf) {\n if (obj.raw_size)\n pbf.writeVarintField(2, obj.raw_size);\n if (obj.raw != null)\n pbf.writeBytesField(1, obj.raw);\n if (obj.zlib_data != null)\n pbf.writeBytesField(3, obj.zlib_data);\n}\n/**\n * Reads an `OsmPbfBlobHeader` from the current position in the Pbf reader.\n */\nexport function readBlobHeader(pbf, end) {\n return pbf.readFields(readBlobHeaderField, { type: \"OSMData\", datasize: 0 }, end);\n}\n/**\n * Dispatches individual BlobHeader fields based on their protobuf tag.\n */\nfunction readBlobHeaderField(tag, obj, pbf) {\n if (tag === 1)\n obj.type = pbf.readString();\n else if (tag === 3)\n obj.datasize = pbf.readVarint(true);\n}\n/**\n * Writes an `OsmPbfBlobHeader` message to the provided Pbf writer.\n */\nexport function writeBlobHeader(obj, pbf) {\n if (obj.type)\n pbf.writeStringField(1, obj.type);\n if (obj.datasize)\n pbf.writeVarintField(3, obj.datasize);\n}\n//# sourceMappingURL=fileformat.js.map","// Recommended and maximum header and blob sizes as defined by the OSM PBF specification\n// Header: 32 KiB and 64 KiB\nexport const RECOMMENDED_HEADER_SIZE_BYTES = 32 * 1024;\nexport const MAX_HEADER_SIZE_BYTES = 64 * 1024;\n// Blob: 16 MiB and 32 MiB\nexport const RECOMMENDED_BLOB_SIZE_BYTES = 16 * 1024 * 1024;\nexport const MAX_BLOB_SIZE_BYTES = 32 * 1024 * 1024;\n// Recommended maximum number of entities per block\nexport const MAX_ENTITIES_PER_BLOCK = 8_000;\n//# sourceMappingURL=spec.js.map","/**\n * Block-to-PBF serialization utilities.\n *\n * Converts parsed OSM header and primitive blocks back into spec-compliant\n * PBF byte sequences with proper framing, compression, and size validation.\n *\n * @module\n */\nimport Pbf from \"pbf\";\nimport { writeBlob, writeBlobHeader } from \"./proto/fileformat.js\";\nimport { writeHeaderBlock, writePrimitiveBlock } from \"./proto/osmformat.js\";\nimport { MAX_BLOB_SIZE_BYTES, MAX_HEADER_SIZE_BYTES, RECOMMENDED_BLOB_SIZE_BYTES, RECOMMENDED_HEADER_SIZE_BYTES, } from \"./spec.js\";\nimport { concatUint8, uint32BE, webCompress } from \"./utils.js\";\n/**\n * Serialize a header or primitive block into spec-compliant PBF bytes.\n *\n * Handles protobuf encoding, zlib compression, blob wrapping, and length prefixing.\n * Validates output against OSM PBF specification size limits and logs warnings\n * if recommended sizes are exceeded.\n *\n * @param block - Parsed header or primitive block to encode.\n * @param compress - Optional compression function (defaults to Web Streams zlib).\n * @returns Complete blob bytes: 4-byte length prefix + BlobHeader + Blob.\n * @throws If blob exceeds maximum size limits (64 KiB header, 32 MiB data).\n *\n * @example\n * ```ts\n * import { osmBlockToPbfBlobBytes } from \"@osmix/pbf\"\n *\n * const headerBytes = await osmBlockToPbfBlobBytes({\n * required_features: [\"OsmSchema-V0.6\", \"DenseNodes\"],\n * optional_features: [],\n * })\n * ```\n */\nexport async function osmBlockToPbfBlobBytes(block, compress = webCompress) {\n const contentPbf = new Pbf();\n let type;\n if (\"primitivegroup\" in block) {\n type = \"OSMData\";\n writePrimitiveBlock(block, contentPbf);\n }\n else {\n type = \"OSMHeader\";\n writeHeaderBlock(block, contentPbf);\n }\n const contentData = contentPbf.finish();\n const raw_size = contentData.length;\n const compressedBuffer = await compress(contentData);\n const blobPbf = new Pbf();\n writeBlob({\n raw_size,\n zlib_data: compressedBuffer,\n }, blobPbf);\n const blob = blobPbf.finish();\n const blobHeaderPbf = new Pbf();\n writeBlobHeader({\n type,\n datasize: blob.length,\n }, blobHeaderPbf);\n const blobHeader = blobHeaderPbf.finish();\n const blobHeaderSize = uint32BE(blobHeader.byteLength);\n // Check the BlobHeader and Blob sizes, log error if over the recommended size, throw error if over the maximum size\n if (blobHeader.byteLength > RECOMMENDED_HEADER_SIZE_BYTES) {\n const sizeKiB = (blobHeader.byteLength / 1024).toFixed(2);\n if (blobHeader.byteLength > MAX_HEADER_SIZE_BYTES) {\n throw new Error(`BlobHeader is ${sizeKiB} KiB, the maximum size is 64KiB`);\n }\n console.warn(`BlobHeader is ${sizeKiB} KiB, the recommended size is 32KiB`);\n }\n if (blob.byteLength > RECOMMENDED_BLOB_SIZE_BYTES) {\n const sizeMiB = (blob.byteLength / 1024 / 1024).toFixed(2);\n if (blob.byteLength > MAX_BLOB_SIZE_BYTES) {\n throw new Error(`Blob is ${sizeMiB} MiB, the maximum size is 32MiB`);\n }\n console.warn(`Blob is ${sizeMiB} MiB, the recommended size is 16MiB`);\n }\n return concatUint8(blobHeaderSize, blobHeader, blob);\n}\n/**\n * Web `TransformStream` that encodes OSM blocks into PBF byte chunks.\n *\n * Accepts a stream of header and primitive blocks and outputs spec-compliant\n * PBF bytes. The header block must be the first item in the stream.\n *\n * @throws If a primitive block is received before the header.\n *\n * @example\n * ```ts\n * import { OsmBlocksToPbfBytesTransformStream } from \"@osmix/pbf\"\n *\n * const pbfStream = blocksStream.pipeThrough(new OsmBlocksToPbfBytesTransformStream())\n * await pbfStream.pipeTo(writableFile)\n * ```\n */\nexport class OsmBlocksToPbfBytesTransformStream extends TransformStream {\n headerEnqueued = false;\n constructor() {\n super({\n transform: async (block, controller) => {\n if (\"primitivegroup\" in block && !this.headerEnqueued) {\n throw Error(\"Header first in ReadableStream of blocks.\");\n }\n this.headerEnqueued = true;\n controller.enqueue(await osmBlockToPbfBlobBytes(block));\n },\n });\n }\n}\n//# sourceMappingURL=blocks-to-pbf.js.map","import Pbf from \"pbf\";\nimport { osmPbfBlobsToBlocksGenerator } from \"./blobs-to-blocks.js\";\nimport { createOsmPbfBlobGenerator } from \"./pbf-to-blobs.js\";\nimport { readHeaderBlock, readPrimitiveBlock, } from \"./proto/osmformat.js\";\nimport { toAsyncGenerator, webDecompress, } from \"./utils.js\";\n/** Number of bytes used to encode the BlobHeader length prefix (big-endian uint32). */\nexport const HEADER_LENGTH_BYTES = 4;\n/**\n * Parse an OSM PBF file from various input sources.\n *\n * Accepts `ArrayBuffer`, `Uint8Array`, `ReadableStream<Uint8Array>`, or async generators.\n * Returns the file header and a lazy async generator of primitive blocks for on-demand parsing.\n *\n * @param data - PBF bytes as buffer, stream, or async iterable.\n * @returns Object with `header` (file metadata) and `blocks` (async generator of primitive blocks).\n * @throws If the header block is missing or malformed.\n *\n * @example\n * ```ts\n * import { readOsmPbf } from \"@osmix/pbf\"\n *\n * // From a file stream\n * const { header, blocks } = await readOsmPbf(Bun.file('./monaco.pbf').stream())\n *\n * // From a fetch response\n * const response = await fetch('/data/monaco.pbf')\n * const { header, blocks } = await readOsmPbf(response.body!)\n *\n * // Iterate blocks lazily\n * for await (const block of blocks) {\n * for (const group of block.primitivegroup) {\n * console.log(group.dense?.id.length ?? 0, \"dense nodes\")\n * }\n * }\n * ```\n */\nexport async function readOsmPbf(data) {\n const generateBlobsFromChunk = createOsmPbfBlobGenerator();\n const blocks = osmPbfBlobsToBlocksGenerator((async function* () {\n for await (const chunk of toAsyncGenerator(data)) {\n for await (const blob of generateBlobsFromChunk(chunk)) {\n yield blob;\n }\n }\n })());\n const header = (await blocks.next()).value;\n if (header == null || !(\"required_features\" in header)) {\n throw Error(\"OSM PBF header block not found\");\n }\n return {\n header,\n blocks: blocks,\n };\n}\n/**\n * Web `TransformStream` that decodes raw PBF byte chunks into OSM header and data blocks.\n *\n * The first blob in an OSM PBF file is always the header block; subsequent blobs\n * contain primitive data (nodes, ways, relations). This stream handles the framing,\n * decompression, and protobuf decoding automatically.\n *\n * @example\n * ```ts\n * import { OsmPbfBytesToBlocksTransformStream } from \"@osmix/pbf\"\n *\n * const response = await fetch('/data/monaco.pbf')\n * const blocksStream = response.body!\n * .pipeThrough(new OsmPbfBytesToBlocksTransformStream())\n *\n * const reader = blocksStream.getReader()\n * const { value: header } = await reader.read() // First read yields header\n * // Subsequent reads yield primitive blocks\n * ```\n */\nexport class OsmPbfBytesToBlocksTransformStream extends TransformStream {\n generateBlobsFromChunk = createOsmPbfBlobGenerator();\n header = null;\n constructor(decompress = webDecompress) {\n super({\n transform: async (bytesChunk, controller) => {\n for await (const rawBlobs of this.generateBlobsFromChunk(bytesChunk)) {\n const decompressed = await decompress(rawBlobs);\n const pbf = new Pbf(decompressed);\n if (this.header == null) {\n this.header = readHeaderBlock(pbf);\n controller.enqueue(this.header);\n }\n else {\n controller.enqueue(readPrimitiveBlock(pbf));\n }\n }\n },\n });\n }\n}\n//# sourceMappingURL=pbf-to-blocks.js.map","import Pbf from \"pbf\";\nimport { HEADER_LENGTH_BYTES } from \"./pbf-to-blocks.js\";\nimport { readBlob, readBlobHeader, } from \"./proto/fileformat.js\";\n/**\n * Create a stateful parser that extracts compressed blobs from raw PBF bytes.\n *\n * OSM PBF files consist of length-prefixed blobs. This function returns a generator\n * that accumulates incoming byte chunks and yields complete compressed blobs as they\n * become available. The caller is responsible for decompression.\n *\n * The first yielded blob contains the file header; subsequent blobs contain primitive data.\n *\n * @returns A generator function that accepts byte chunks and yields compressed blob payloads.\n *\n * @example\n * ```ts\n * import { createOsmPbfBlobGenerator } from \"@osmix/pbf\"\n *\n * const generateBlobs = createOsmPbfBlobGenerator()\n *\n * for await (const chunk of stream) {\n * for (const compressedBlob of generateBlobs(chunk)) {\n * // Decompress and parse blob...\n * }\n * }\n * ```\n */\nexport function createOsmPbfBlobGenerator() {\n let pbf = new Pbf(new Uint8Array(0));\n let state = \"header-length\";\n let bytesNeeded = HEADER_LENGTH_BYTES;\n let blobHeader = null;\n /**\n * Feed the parser with the next chunk of bytes and yield any complete compressed blobs.\n * @param chunk - Raw bytes from the PBF file.\n * @yields Compressed blob payloads (zlib-compressed protobuf data).\n */\n return function* nextChunk(chunk) {\n const currentBuffer = pbf.buf.slice(pbf.pos);\n const tmpBuffer = new Uint8Array(currentBuffer.buffer.byteLength + chunk.byteLength);\n tmpBuffer.set(currentBuffer.subarray(0));\n tmpBuffer.set(new Uint8Array(chunk), currentBuffer.byteLength);\n pbf = new Pbf(tmpBuffer);\n while (pbf.pos + bytesNeeded <= pbf.length) {\n if (state === \"header-length\") {\n const dataView = new DataView(pbf.buf.buffer);\n bytesNeeded = dataView.getInt32(pbf.pos, false); // network byte order\n pbf.pos += HEADER_LENGTH_BYTES;\n state = \"header\";\n }\n else if (state === \"header\") {\n blobHeader = readBlobHeader(pbf, pbf.pos + bytesNeeded);\n bytesNeeded = blobHeader.datasize;\n state = \"blob\";\n }\n else if (state === \"blob\") {\n if (blobHeader == null)\n throw Error(\"Blob header has not been read\");\n const blob = readBlob(pbf, pbf.pos + bytesNeeded);\n if (blob.zlib_data === undefined || blob.zlib_data.length === 0)\n throw Error(\"Blob has no zlib data. Format is unsupported.\");\n yield blob.zlib_data;\n state = \"header-length\";\n bytesNeeded = HEADER_LENGTH_BYTES;\n blobHeader = null;\n }\n }\n };\n}\n//# sourceMappingURL=pbf-to-blobs.js.map","import type {\n OsmPbfBlock,\n OsmPbfNode,\n OsmPbfDenseNodes,\n OsmPbfWay,\n OsmPbfRelation,\n} from '@osmix/pbf';\n\nimport type { OsmElement } from '../load-osm-from-overpass-api/interfaces';\n\nconst TEXT_DECODER = new TextDecoder();\n\n/**\n * Converts a `@osmix/pbf` block into an array of `OsmElement` records.\n *\n * Handles all four primitive types:\n * - regular nodes\n * - dense nodes (delta-encoded, compact storage)\n * - ways (with node refs)\n * - relations (with member refs)\n *\n * StringTable indices are resolved to actual tag strings.\n * Way geometry is **not** resolved here — caller must build a node index\n * and call `resolveWayGeometries()` afterwards.\n */\nexport function blockToElements(block: OsmPbfBlock): OsmElement[] {\n const elements: OsmElement[] = [];\n const st = block.stringtable;\n const str = (sid: number) => TEXT_DECODER.decode(st[sid]);\n\n for (const group of block.primitivegroup) {\n // Regular nodes\n for (const node of group.nodes ?? []) {\n elements.push(pbfNodeToElement(node, block, str));\n }\n\n // Dense nodes (compact delta-encoded format)\n if (group.dense) {\n elements.push(...denseNodesToElements(group.dense, block, str));\n }\n\n // Ways\n for (const way of group.ways ?? []) {\n elements.push(pbfWayToElement(way, block, str));\n }\n\n // Relations\n for (const rel of group.relations ?? []) {\n elements.push(pbfRelationToElement(rel, block, str));\n }\n }\n\n return elements;\n}\n\n// ---------------------------------------------------------------------------\n// Internal converters\n// ---------------------------------------------------------------------------\n\nfunction pbfNodeToElement(\n node: OsmPbfNode,\n block: OsmPbfBlock,\n _str: (sid: number) => string,\n): OsmElement {\n return {\n type: 'node',\n id: node.id,\n lat: decodeLat(block, node.lat),\n lon: decodeLon(block, node.lon),\n tags: tagsFromKv(node.keys, node.vals, block, _str),\n };\n}\n\nfunction denseNodesToElements(\n dense: OsmPbfDenseNodes,\n block: OsmPbfBlock,\n str: (sid: number) => string,\n): OsmElement[] {\n const elements: OsmElement[] = [];\n const { id, lat, lon, keys_vals } = dense;\n\n let prevId = 0;\n let prevLat = 0;\n let prevLon = 0;\n let kvIdx = 0;\n\n for (let i = 0; i < id.length; i++) {\n // Delta decoding\n prevId += id[i];\n prevLat += lat[i];\n prevLon += lon[i];\n\n // Decode tags from interleaved keys_vals array\n const tags: Record<string, string> = {};\n while (kvIdx < keys_vals.length) {\n const keySid = keys_vals[kvIdx];\n if (keySid === 0) {\n kvIdx++; // skip sentinel\n break;\n }\n const valSid = keys_vals[kvIdx + 1];\n tags[str(keySid)] = str(valSid);\n kvIdx += 2;\n }\n\n elements.push({\n type: 'node',\n id: prevId,\n lat: decodeLat(block, prevLat),\n lon: decodeLon(block, prevLon),\n tags: Object.keys(tags).length > 0 ? tags : undefined,\n });\n }\n\n return elements;\n}\n\nfunction pbfWayToElement(\n way: OsmPbfWay,\n _block: OsmPbfBlock,\n str: (sid: number) => string,\n): OsmElement {\n // Delta-decode refs\n const refs: number[] = [];\n let prevRef = 0;\n for (const ref of way.refs) {\n prevRef += ref;\n refs.push(prevRef);\n }\n\n return {\n type: 'way',\n id: way.id,\n nodes: refs,\n geometry: undefined, // resolved later by caller\n tags: tagsFromKv(way.keys, way.vals, _block, str),\n };\n}\n\nfunction pbfRelationToElement(\n rel: OsmPbfRelation,\n _block: OsmPbfBlock,\n str: (sid: number) => string,\n): OsmElement {\n // Delta-decode member IDs\n const members: OsmElement['members'] = [];\n let prevMemId = 0;\n for (let i = 0; i < rel.memids.length; i++) {\n prevMemId += rel.memids[i];\n const memberType = rel.types[i];\n const typeMap: Record<number, 'node' | 'way' | 'relation'> = {\n 0: 'node',\n 1: 'way',\n 2: 'relation',\n };\n members.push({\n type: typeMap[memberType] ?? 'node',\n ref: prevMemId,\n role: rel.roles_sid[i] !== undefined ? str(rel.roles_sid[i]) : '',\n });\n }\n\n return {\n type: 'relation',\n id: rel.id,\n members,\n tags: tagsFromKv(rel.keys, rel.vals, _block, str),\n };\n}\n\nfunction tagsFromKv(\n keys: number[],\n vals: number[],\n _block: OsmPbfBlock,\n str: (sid: number) => string,\n): Record<string, string> | undefined {\n if (keys.length === 0) return undefined;\n const tags: Record<string, string> = {};\n for (let i = 0; i < keys.length; i++) {\n tags[str(keys[i])] = str(vals[i]);\n }\n return tags;\n}\n\nfunction decodeLat(block: OsmPbfBlock, value: number): number {\n return value / (block.granularity ?? 1e7) + (block.lat_offset ?? 0);\n}\n\nfunction decodeLon(block: OsmPbfBlock, value: number): number {\n return value / (block.granularity ?? 1e7) + (block.lon_offset ?? 0);\n}\n\n/**\n * Resolves inline `geometry` for every way by looking up node coordinates.\n *\n * Mutates the `elements` array in place — each way that has a non-empty\n * `nodes[]` array gets a matching `geometry[]` array.\n *\n * @returns A `Map<nodeId, {lat, lon}>` for downstream use (e.g. bbox computation).\n */\nexport function resolveWayGeometries(elements: OsmElement[]): Map<number, { lat: number; lon: number }> {\n const nodeIndex = new Map<number, { lat: number; lon: number }>();\n\n // Build node index\n for (const el of elements) {\n if (el.type === 'node' && el.lat !== undefined && el.lon !== undefined) {\n nodeIndex.set(el.id, { lat: el.lat, lon: el.lon });\n }\n }\n\n // Resolve way geometries\n for (const el of elements) {\n if (el.type === 'way' && el.nodes && el.nodes.length > 0) {\n const geometry: { lat: number; lon: number }[] = [];\n for (const nodeId of el.nodes) {\n const coord = nodeIndex.get(nodeId);\n if (coord) {\n geometry.push(coord);\n }\n }\n if (geometry.length > 0) {\n el.geometry = geometry;\n }\n }\n }\n\n return nodeIndex;\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { readOsmPbf } from '@osmix/pbf';\n\nimport { OsmTable } from '../../../shared/interfaces';\nimport {\n EXCLUDED_BUILDING_VALUES,\n EXCLUDED_HIGHWAY_VALUES,\n PARKS_LANDUSE_VALUES,\n PARKS_LEISURE_VALUES,\n PARKS_NATURAL_VALUES,\n WATER_NATURAL_VALUES,\n WATER_FEATURE_VALUES,\n} from '../../../shared/osm-tag-definitions';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport { LoadOsmParams, OsmElement } from '../load-osm-from-overpass-api/interfaces';\nimport { OsmProcessingPipeline } from '../osm-processing-pipeline/OsmProcessingPipeline';\nimport { blockToElements, resolveWayGeometries } from './osm-pbf-parser';\n\ninterface OverpassApiResponse {\n elements: OsmElement[];\n}\n\ninterface OsmExecResult {\n tables: OsmTable[];\n osmElementCount: number;\n boundaryElementCount: number;\n osmDataProcessingMs: number;\n boundariesProcessingMs: number;\n}\n\ntype RequestedLayer = 'roads' | 'buildings' | 'parks' | 'water';\ntype Bbox = { south: number; north: number; west: number; east: number };\n\nclass IdFilter {\n private bits: Uint8Array;\n private bitCount: number;\n\n constructor(bitCount: number = 1 << 27) {\n this.bitCount = bitCount;\n this.bits = new Uint8Array(Math.ceil(bitCount / 8));\n }\n\n add(id: number): void {\n this.setBit(this.hash1(id));\n this.setBit(this.hash2(id));\n this.setBit(this.hash3(id));\n }\n\n has(id: number): boolean {\n return this.getBit(this.hash1(id)) && this.getBit(this.hash2(id)) && this.getBit(this.hash3(id));\n }\n\n private setBit(index: number): void {\n this.bits[index >> 3] |= 1 << (index & 7);\n }\n\n private getBit(index: number): boolean {\n return (this.bits[index >> 3] & (1 << (index & 7))) !== 0;\n }\n\n private hash1(id: number): number {\n return this.mix(id, 0x9e3779b1);\n }\n\n private hash2(id: number): number {\n return this.mix(id, 0x85ebca6b);\n }\n\n private hash3(id: number): number {\n return this.mix(id, 0xc2b2ae35);\n }\n\n private mix(id: number, seed: number): number {\n let x = Math.floor(id) ^ seed;\n x = Math.imul(x ^ (x >>> 16), 0x45d9f3b);\n x = Math.imul(x ^ (x >>> 16), 0x45d9f3b);\n x = x ^ (x >>> 16);\n return (x >>> 0) % this.bitCount;\n }\n}\n\n/**\n * Loads OSM data from a local PBF file with multi-pass streaming.\n */\nexport class LoadOsmFromPbfUseCase {\n private readonly conn: AsyncDuckDBConnection;\n private readonly pipeline: OsmProcessingPipeline;\n\n constructor(conn: AsyncDuckDBConnection, pipeline: OsmProcessingPipeline) {\n this.conn = conn;\n this.pipeline = pipeline;\n }\n\n async exec(params: LoadOsmParams): Promise<OsmExecResult> {\n const pbfFileUrl = params.pbfFileUrl;\n if (!pbfFileUrl) throw new Error('pbfFileUrl must be provided for PBF loading');\n const workspace = params.workspace || 'main';\n const onProgress = params.onProgress;\n const requestedLayers = this.getRequestedLayers(params);\n\n onProgress?.('downloading-osm-data');\n\n const boundaryContext = await this.collectBoundaryContext(pbfFileUrl, params.queryArea.areas);\n const bbox = await this.collectBoundaryBbox(pbfFileUrl, boundaryContext.boundaryWayIds);\n\n onProgress?.('processing-osm-data');\n console.log('[autk-db] PBF pass 3/3: thematic collection started');\n\n const candidates = await this.collectCandidateWaysAndRelations(\n pbfFileUrl,\n boundaryContext.boundaryRelationIds,\n boundaryContext.boundaryWayIds,\n requestedLayers,\n );\n\n await this.collectRequiredNodes(pbfFileUrl, candidates.requiredNodeIds, candidates.elements);\n resolveWayGeometries(candidates.elements);\n\n const filteredElements = this.filterFinalElements(\n candidates.elements,\n bbox,\n boundaryContext.boundaryRelationIds,\n boundaryContext.boundaryWayIds,\n );\n const grouped = this.buildGroupedCollections(\n filteredElements,\n boundaryContext.boundaryRelationIds,\n boundaryContext.boundaryWayIds,\n );\n console.log('[autk-db] PBF pass 3/3: thematic collection finished');\n console.log(\n `[autk-db] PBF filter summary: boundaries=${grouped.boundaries.elements.length}, parks+water=${grouped.parksWater.elements.length}, roads=${grouped.roads.elements.length}, buildings=${grouped.buildings.elements.length}, total=${filteredElements.length}`\n );\n\n const combined = this.mergeResponses(\n this.mergeResponses(grouped.boundaries, grouped.parksWater),\n this.mergeResponses(grouped.roads, grouped.buildings),\n );\n const { osmData, boundariesData } = this.pipeline.splitCombinedResponse(combined, params.queryArea);\n\n const t0 = performance.now();\n await this.pipeline.insertOsmDataUsingJson(params.outputTableName, osmData, workspace);\n const osmDataProcessingMs = performance.now() - t0;\n\n onProgress?.('processing-boundaries');\n const t1 = performance.now();\n await this.pipeline.insertOsmDataUsingJson(`${params.outputTableName}_boundaries`, boundariesData, workspace, true);\n const boundariesProcessingMs = performance.now() - t1;\n\n const qualifiedTableName = `${workspace}.${params.outputTableName}`;\n const tableDescribeResponse = await this.conn.query(`DESCRIBE ${qualifiedTableName}`);\n const columns = getColumnsFromDuckDbTableDescribe(tableDescribeResponse.toArray());\n\n return {\n tables: [\n { source: 'osm', type: 'pointset', name: params.outputTableName, columns },\n { source: 'osm', type: 'pointset', name: `${params.outputTableName}_boundaries`, columns },\n ],\n osmElementCount: osmData.elements.length,\n boundaryElementCount: boundariesData.elements.length,\n osmDataProcessingMs,\n boundariesProcessingMs,\n };\n }\n\n private getRequestedLayers(params: LoadOsmParams): RequestedLayer[] {\n const layers = params.autoLoadLayers?.layers ?? ['roads', 'buildings', 'parks', 'water'];\n return layers.filter((layer): layer is RequestedLayer =>\n layer === 'roads' || layer === 'buildings' || layer === 'parks' || layer === 'water',\n );\n }\n\n // Pass 1: find requested boundary relations and their member ways\n private async collectBoundaryContext(\n pbfFileUrl: string,\n areaNames: string[],\n ): Promise<{\n boundaryRelationIds: Set<number>;\n boundaryWayIds: Set<number>;\n }> {\n console.log('[autk-db] PBF pass 1/3: boundary discovery started');\n const requestedAreaNames = new Set(areaNames);\n const foundAreaNames = new Set<string>();\n const boundaryRelationIds = new Set<number>();\n const boundaryWayIds = new Set<number>();\n\n await this.streamPbfBlocks(pbfFileUrl, async (elements) => {\n for (const element of elements) {\n if (element.type !== 'relation') continue;\n const name = element.tags?.name;\n if (!name || !requestedAreaNames.has(name)) continue;\n\n foundAreaNames.add(name);\n boundaryRelationIds.add(element.id);\n for (const member of element.members ?? []) {\n if (member.type === 'way') boundaryWayIds.add(member.ref);\n }\n }\n });\n\n const missingAreas = areaNames.filter((name) => !foundAreaNames.has(name));\n if (missingAreas.length > 0) {\n throw new Error(\n `No administrative boundary found in PBF for: ${missingAreas.map(a => `\"${a}\"`).join(', ')}. ` +\n `Verify the area names match OSM relation names exactly.`,\n );\n }\n\n console.log(\n `[autk-db] PBF pass 1/3: boundary discovery finished (${boundaryRelationIds.size} relations, ${boundaryWayIds.size} ways)`\n );\n return { boundaryRelationIds, boundaryWayIds };\n }\n\n // Pass 2: collect boundary ways/nodes and compute bbox\n private async collectBoundaryBbox(\n pbfFileUrl: string,\n boundaryWayIds: Set<number>,\n ): Promise<Bbox> {\n console.log('[autk-db] PBF pass 2/3: boundary bbox collection started');\n const elements: OsmElement[] = [];\n const requiredNodeIds = new IdFilter();\n\n await this.streamPbfBlocks(pbfFileUrl, async (blockElements) => {\n for (const element of blockElements) {\n if (element.type !== 'way' || !boundaryWayIds.has(element.id)) continue;\n elements.push(element);\n for (const nodeId of element.nodes ?? []) requiredNodeIds.add(nodeId);\n }\n });\n\n await this.collectRequiredNodes(pbfFileUrl, requiredNodeIds, elements);\n resolveWayGeometries(elements);\n\n const bbox = this.pipeline.computeBboxFromElements(elements);\n if (!bbox) throw new Error('Failed to compute bounding box from boundary elements');\n\n console.log(\n `[autk-db] PBF pass 2/3: boundary bbox collection finished (${bbox.south}, ${bbox.west}) → (${bbox.north}, ${bbox.east})`\n );\n return bbox;\n }\n\n // Pass 3: collect candidate thematic relations + ways and required node ids\n private async collectCandidateWaysAndRelations(\n pbfFileUrl: string,\n boundaryRelationIds: Set<number>,\n boundaryWayIds: Set<number>,\n requestedLayers: RequestedLayer[],\n ): Promise<{\n elements: OsmElement[];\n requiredNodeIds: IdFilter;\n }> {\n const elements: OsmElement[] = [];\n const relationWayIds = new Set<number>();\n\n await this.streamPbfBlocks(pbfFileUrl, async (blockElements) => {\n for (const element of blockElements) {\n if (element.type !== 'relation') continue;\n\n if (boundaryRelationIds.has(element.id) || this.matchesRequestedRelationLayers(element.tags, requestedLayers)) {\n elements.push(element);\n for (const member of element.members ?? []) {\n if (member.type === 'way') relationWayIds.add(member.ref);\n }\n }\n }\n });\n\n const requiredNodeIds = new IdFilter();\n\n await this.streamPbfBlocks(pbfFileUrl, async (blockElements) => {\n for (const element of blockElements) {\n if (element.type !== 'way') continue;\n\n const keep =\n boundaryWayIds.has(element.id) ||\n relationWayIds.has(element.id) ||\n this.matchesRequestedWayLayers(element.tags, requestedLayers);\n\n if (!keep) continue;\n\n elements.push(element);\n for (const nodeId of element.nodes ?? []) {\n requiredNodeIds.add(nodeId);\n }\n }\n });\n\n return { elements, requiredNodeIds };\n }\n\n private async collectRequiredNodes(\n pbfFileUrl: string,\n requiredNodeIds: IdFilter,\n elements: OsmElement[],\n ): Promise<void> {\n await this.streamPbfBlocks(pbfFileUrl, async (blockElements) => {\n for (const element of blockElements) {\n if (element.type !== 'node') continue;\n if (!requiredNodeIds.has(element.id)) continue;\n elements.push(element);\n }\n });\n }\n\n private filterFinalElements(\n elements: OsmElement[],\n bbox: Bbox,\n boundaryRelationIds: Set<number>,\n boundaryWayIds: Set<number>,\n ): OsmElement[] {\n const intersectingWays = new IdFilter();\n\n for (const element of elements) {\n if (element.type !== 'way') continue;\n if (boundaryWayIds.has(element.id) || this.wayIntersectsBbox(element, bbox)) {\n intersectingWays.add(element.id);\n }\n }\n\n const keptRelationIds = new IdFilter();\n const relationMemberWayIds = new IdFilter();\n\n for (const element of elements) {\n if (element.type !== 'relation') continue;\n\n if (boundaryRelationIds.has(element.id)) {\n keptRelationIds.add(element.id);\n for (const member of element.members ?? []) {\n if (member.type === 'way') relationMemberWayIds.add(member.ref);\n }\n continue;\n }\n\n const memberWayRefs = this.getRelationWayRefs(element);\n\n if (memberWayRefs.some((ref) => intersectingWays.has(ref))) {\n keptRelationIds.add(element.id);\n for (const ref of memberWayRefs) relationMemberWayIds.add(ref);\n }\n }\n\n const keptWays = new IdFilter();\n for (const element of elements) {\n if (element.type !== 'way') continue;\n if (intersectingWays.has(element.id) || relationMemberWayIds.has(element.id)) {\n keptWays.add(element.id);\n }\n }\n\n const keptNodeIds = new IdFilter();\n for (const element of elements) {\n if (element.type === 'way' && keptWays.has(element.id)) {\n for (const nodeId of element.nodes ?? []) keptNodeIds.add(nodeId);\n }\n }\n\n return elements.filter((element) => {\n if (element.type === 'way') return keptWays.has(element.id);\n if (element.type === 'node') return keptNodeIds.has(element.id);\n if (element.type === 'relation') return keptRelationIds.has(element.id);\n return false;\n });\n }\n\n private buildGroupedCollections(\n elements: OsmElement[],\n boundaryRelationIds: Set<number>,\n boundaryWayIds: Set<number>,\n ): {\n boundaries: OverpassApiResponse;\n parksWater: OverpassApiResponse;\n roads: OverpassApiResponse;\n buildings: OverpassApiResponse;\n } {\n const boundaryWaySet = new Set<number>();\n const parksWaterWaySet = new Set<number>();\n const roadsWaySet = new Set<number>();\n const buildingsWaySet = new Set<number>();\n\n const boundaryNodeIds = new IdFilter();\n const parksWaterNodeIds = new IdFilter();\n const roadsNodeIds = new IdFilter();\n const buildingsNodeIds = new IdFilter();\n\n const boundaries: OsmElement[] = [];\n const parksWater: OsmElement[] = [];\n const roads: OsmElement[] = [];\n const buildings: OsmElement[] = [];\n\n const addWayNodes = (nodeIds: number[] | undefined, nodeFilter: IdFilter) => {\n for (const nodeId of nodeIds ?? []) nodeFilter.add(nodeId);\n };\n\n for (const element of elements) {\n if (element.type !== 'relation') continue;\n\n if (boundaryRelationIds.has(element.id)) {\n boundaries.push(element);\n for (const member of element.members ?? []) {\n if (member.type === 'way') boundaryWaySet.add(member.ref);\n }\n continue;\n }\n\n if (this.isBuildingTagSet(element.tags ?? {})) {\n buildings.push(element);\n for (const member of element.members ?? []) {\n if (member.type === 'way') buildingsWaySet.add(member.ref);\n }\n continue;\n }\n\n if (this.isRoadTagSet(element.tags ?? {})) {\n roads.push(element);\n for (const member of element.members ?? []) {\n if (member.type === 'way') roadsWaySet.add(member.ref);\n }\n continue;\n }\n\n if (this.isParkTagSet(element.tags ?? {}) || this.isWaterTagSet(element.tags ?? {})) {\n parksWater.push(element);\n for (const member of element.members ?? []) {\n if (member.type === 'way') parksWaterWaySet.add(member.ref);\n }\n }\n }\n\n for (const element of elements) {\n if (element.type !== 'way') continue;\n\n if (boundaryWayIds.has(element.id) || boundaryWaySet.has(element.id)) {\n boundaries.push(element);\n boundaryWaySet.add(element.id);\n addWayNodes(element.nodes, boundaryNodeIds);\n continue;\n }\n if (buildingsWaySet.has(element.id) || this.isBuildingTagSet(element.tags ?? {})) {\n buildings.push(element);\n buildingsWaySet.add(element.id);\n addWayNodes(element.nodes, buildingsNodeIds);\n continue;\n }\n if (roadsWaySet.has(element.id) || this.isRoadTagSet(element.tags ?? {})) {\n roads.push(element);\n roadsWaySet.add(element.id);\n addWayNodes(element.nodes, roadsNodeIds);\n continue;\n }\n if (parksWaterWaySet.has(element.id) || this.isParkTagSet(element.tags ?? {}) || this.isWaterTagSet(element.tags ?? {})) {\n parksWater.push(element);\n parksWaterWaySet.add(element.id);\n addWayNodes(element.nodes, parksWaterNodeIds);\n continue;\n }\n }\n\n for (const element of elements) {\n if (element.type !== 'node') continue;\n if (boundaryNodeIds.has(element.id)) boundaries.push(element);\n if (parksWaterNodeIds.has(element.id)) parksWater.push(element);\n if (roadsNodeIds.has(element.id)) roads.push(element);\n if (buildingsNodeIds.has(element.id)) buildings.push(element);\n }\n\n return {\n boundaries: { elements: boundaries },\n parksWater: { elements: parksWater },\n roads: { elements: roads },\n buildings: { elements: buildings },\n };\n }\n\n private mergeResponses(a: OverpassApiResponse, b: OverpassApiResponse): OverpassApiResponse {\n const existingIds = new Set<string>();\n for (const e of a.elements) existingIds.add(`${e.type}:${e.id}`);\n const dedupedB = b.elements.filter(e => !existingIds.has(`${e.type}:${e.id}`));\n return { elements: [...a.elements, ...dedupedB] };\n }\n\n private getRelationWayRefs(element: OsmElement): number[] {\n return (element.members ?? [])\n .filter((member) => member.type === 'way')\n .map((member) => member.ref);\n }\n\n private wayIntersectsBbox(element: OsmElement, bbox: Bbox): boolean {\n const points = element.geometry;\n if (!points || points.length === 0) return false;\n\n let minLat = Infinity;\n let maxLat = -Infinity;\n let minLon = Infinity;\n let maxLon = -Infinity;\n\n for (const pt of points) {\n if (pt.lat < minLat) minLat = pt.lat;\n if (pt.lat > maxLat) maxLat = pt.lat;\n if (pt.lon < minLon) minLon = pt.lon;\n if (pt.lon > maxLon) maxLon = pt.lon;\n }\n\n return !(maxLat < bbox.south || minLat > bbox.north || maxLon < bbox.west || minLon > bbox.east);\n }\n\n private async streamPbfBlocks(\n pbfFileUrl: string,\n onBlock: (elements: OsmElement[]) => Promise<void> | void,\n ): Promise<void> {\n const response = await fetch(pbfFileUrl);\n if (!response.ok || !response.body) {\n throw new Error(`Failed to fetch PBF file: ${response.status} ${response.statusText}`);\n }\n\n const { blocks } = await readOsmPbf(response.body);\n for await (const block of blocks) {\n await onBlock(blockToElements(block));\n }\n }\n\n private matchesRequestedWayLayers(tags: Record<string, string> | undefined, requestedLayers: RequestedLayer[]): boolean {\n if (!tags) return false;\n for (const layer of requestedLayers) {\n switch (layer) {\n case 'roads':\n if (this.isRoadTagSet(tags)) return true;\n break;\n case 'buildings':\n if (this.isBuildingTagSet(tags)) return true;\n break;\n case 'parks':\n if (this.isParkTagSet(tags)) return true;\n break;\n case 'water':\n if (this.isWaterTagSet(tags)) return true;\n break;\n }\n }\n return false;\n }\n\n private matchesRequestedRelationLayers(tags: Record<string, string> | undefined, requestedLayers: RequestedLayer[]): boolean {\n return this.matchesRequestedWayLayers(tags, requestedLayers);\n }\n\n private isRoadTagSet(tags: Record<string, string>): boolean {\n return (\n tags.highway !== undefined &&\n tags.area !== 'yes' &&\n !this.hasTagValue(tags, 'highway', EXCLUDED_HIGHWAY_VALUES)\n );\n }\n\n private isBuildingTagSet(tags: Record<string, string>): boolean {\n return (\n (tags.building !== undefined && !this.hasTagValue(tags, 'building', EXCLUDED_BUILDING_VALUES)) ||\n (tags['building:part'] !== undefined && !this.hasTagValue(tags, 'building:part', EXCLUDED_BUILDING_VALUES)) ||\n tags.type === 'building' ||\n (tags.type === 'multipolygon' && tags.building !== undefined && !this.hasTagValue(tags, 'building', EXCLUDED_BUILDING_VALUES)) ||\n (tags.type === 'multipolygon' && tags['building:part'] !== undefined && !this.hasTagValue(tags, 'building:part', EXCLUDED_BUILDING_VALUES))\n );\n }\n\n private isParkTagSet(tags: Record<string, string>): boolean {\n return (\n this.hasTagValue(tags, 'leisure', PARKS_LEISURE_VALUES) ||\n this.hasTagValue(tags, 'landuse', PARKS_LANDUSE_VALUES) ||\n this.hasTagValue(tags, 'natural', PARKS_NATURAL_VALUES)\n );\n }\n\n private isWaterTagSet(tags: Record<string, string>): boolean {\n return (\n this.hasTagValue(tags, 'natural', WATER_NATURAL_VALUES) ||\n this.hasTagValue(tags, 'water', WATER_FEATURE_VALUES)\n );\n }\n\n private hasTagValue(tags: Record<string, string>, key: string, values: readonly string[]): boolean {\n const value = tags[key];\n return value !== undefined && values.includes(value);\n }\n}\n","export const CREATE_OSM_TABLE_QUERY = (tableName: string, workspace: string): string => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `\n CREATE OR REPLACE TABLE ${qualifiedTableName} (\n kind VARCHAR,\n id BIGINT,\n tags MAP(VARCHAR, VARCHAR),\n refs BIGINT[],\n lat DOUBLE,\n lon DOUBLE,\n ref_roles VARCHAR[],\n ref_types VARCHAR[]\n );\n`;\n};\n\nexport const INSERT_OSM_DATA_QUERY = (tableName: string, fileName: string, workspace: string, ignoreTags: boolean = false): string => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `\n INSERT INTO ${qualifiedTableName} \n SELECT \n kind::VARCHAR,\n id::BIGINT,\n ${\n ignoreTags\n ? 'NULL'\n : `CASE \n WHEN tags IS NULL OR tags = [] THEN NULL\n ELSE map_from_entries(tags)\n END`\n } AS tags,\n refs::BIGINT[],\n lat::DOUBLE,\n lon::DOUBLE,\n ref_roles::VARCHAR[],\n ref_types::VARCHAR[]\n FROM '${fileName}';\n`;\n};\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { OsmElement } from '../load-osm-from-overpass-api/interfaces';\nimport {\n PARKS_LEISURE_VALUES,\n PARKS_LANDUSE_VALUES,\n PARKS_NATURAL_VALUES,\n WATER_NATURAL_VALUES,\n WATER_FEATURE_VALUES,\n EXCLUDED_HIGHWAY_VALUES,\n EXCLUDED_BUILDING_VALUES,\n} from '../../../shared/osm-tag-definitions';\n\nimport { CREATE_OSM_TABLE_QUERY, INSERT_OSM_DATA_QUERY } from '../load-osm-from-overpass-api/queries';\n\ninterface OverpassApiResponse {\n elements: OsmElement[];\n}\n\n/**\n * Shared OSM processing pipeline for splitting, tagging, and inserting OSM data.\n *\n * Consumed identically by both the Overpass API and PBF loading paths.\n */\nexport class OsmProcessingPipeline {\n constructor(\n private readonly db: AsyncDuckDB,\n private readonly conn: AsyncDuckDBConnection,\n ) {}\n\n // ---------------------------------------------------------------------------\n // Response splitting\n // ---------------------------------------------------------------------------\n\n /**\n * Splits the merged OSM response into two datasets:\n * - `osmData`: all nodes, ways, and non-boundary relations\n * - `boundariesData`: only the ways that form admin boundary rings + their nodes\n */\n splitCombinedResponse(\n combined: OverpassApiResponse,\n queryArea: { geocodeArea: string; areas: string[] },\n ): {\n osmData: OverpassApiResponse;\n boundariesData: OverpassApiResponse;\n } {\n const elements = combined.elements ?? [];\n const boundaryRelationIds = this.getBoundaryRelationIds(elements, queryArea.areas);\n\n const boundaryWayIds = new Set<number>();\n for (const element of elements) {\n if (element.type === 'relation' && boundaryRelationIds.has(element.id) && element.members) {\n for (const member of element.members) {\n if (member.type === 'way') boundaryWayIds.add(member.ref);\n }\n }\n }\n\n const osmData: OverpassApiResponse = {\n elements: elements.filter(e => e.type !== 'relation' || !boundaryRelationIds.has(e.id)),\n };\n\n const boundaryNodeIds = new Set<number>();\n for (const element of elements) {\n if (element.type === 'way' && boundaryWayIds.has(element.id) && element.nodes) {\n element.nodes.forEach(nodeId => boundaryNodeIds.add(nodeId));\n }\n }\n\n const boundariesData: OverpassApiResponse = {\n elements: elements.filter(\n e =>\n (e.type === 'way' && boundaryWayIds.has(e.id)) ||\n (e.type === 'node' && boundaryNodeIds.has(e.id)),\n ),\n };\n\n return { osmData, boundariesData };\n }\n\n // ---------------------------------------------------------------------------\n // Bounding-box computation\n // ---------------------------------------------------------------------------\n\n /**\n * Derives the bounding box from elements already in memory.\n * Uses node lat/lon and way inline geometry produced by `out geom qt`\n * or resolved from a PBF node index.\n */\n computeBboxFromElements(\n elements: OsmElement[],\n ): { south: number; north: number; west: number; east: number } | null {\n let minLat = Infinity, maxLat = -Infinity, minLon = Infinity, maxLon = -Infinity;\n let found = false;\n\n for (const el of elements) {\n if (el.type === 'node' && el.lat !== undefined && el.lon !== undefined) {\n if (el.lat < minLat) minLat = el.lat;\n if (el.lat > maxLat) maxLat = el.lat;\n if (el.lon < minLon) minLon = el.lon;\n if (el.lon > maxLon) maxLon = el.lon;\n found = true;\n }\n if (el.type === 'way' && el.geometry) {\n for (const pt of el.geometry) {\n if (pt.lat < minLat) minLat = pt.lat;\n if (pt.lat > maxLat) maxLat = pt.lat;\n if (pt.lon < minLon) minLon = pt.lon;\n if (pt.lon > maxLon) maxLon = pt.lon;\n found = true;\n }\n }\n }\n\n return found ? { south: minLat, north: maxLat, west: minLon, east: maxLon } : null;\n }\n\n // ---------------------------------------------------------------------------\n // Boundary relation detection\n // ---------------------------------------------------------------------------\n\n getBoundaryRelationIds(elements: OsmElement[], areaNames: string[]): Set<number> {\n const boundaryRelationIds = new Set<number>();\n const requestedAreaNames = new Set(areaNames);\n\n for (const element of elements) {\n if (element.type !== 'relation') continue;\n if (element.tags?.name && requestedAreaNames.has(element.tags.name)) {\n boundaryRelationIds.add(element.id);\n }\n }\n\n if (boundaryRelationIds.size === 0) {\n console.warn(\n `[autk-db] Requested area boundary relations were not found by exact name match: ${areaNames.join(', ')}`,\n );\n }\n\n return boundaryRelationIds;\n }\n\n // ---------------------------------------------------------------------------\n // DuckDB insertion\n // ---------------------------------------------------------------------------\n\n async insertOsmDataUsingJson(\n tableName: string,\n osmData: OverpassApiResponse,\n workspace: string,\n ignoreTags: boolean = false,\n ): Promise<void> {\n if ((osmData.elements?.length ?? 0) === 0) {\n await this.conn.query(CREATE_OSM_TABLE_QUERY(tableName, workspace));\n return;\n }\n\n const formattedElements = this.formatOsmDataForJson(osmData);\n if (formattedElements.length === 0) {\n await this.conn.query(CREATE_OSM_TABLE_QUERY(tableName, workspace));\n return;\n }\n\n const payload = JSON.stringify(formattedElements);\n if (!payload || payload.trim().length === 0) {\n throw new Error(`Failed to serialize OSM JSON payload for table ${tableName}`);\n }\n\n const fileName = `osm_data_${tableName}_${Date.now()}_${Math.random().toString(36).slice(2)}.json`;\n\n await this.db.registerFileText(fileName, payload);\n await this.conn.query(CREATE_OSM_TABLE_QUERY(tableName, workspace));\n await this.conn.query(INSERT_OSM_DATA_QUERY(tableName, fileName, workspace, ignoreTags));\n\n try {\n await this.db.dropFile(fileName);\n } catch (e) {\n console.warn(`Failed to cleanup file ${fileName}:`, e);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Element formatting\n // ---------------------------------------------------------------------------\n\n /**\n * Converts a raw OSM response into the flat record format expected by\n * the DuckDB table schema.\n *\n * Ways with inline `geometry` carry both `nodes` (real OSM node IDs) and\n * `geometry` (lat/lon per node). Synthetic node records are emitted from\n * the inline geometry so the SQL layer queries can join on node ID.\n */\n formatOsmDataForJson(osmData: OverpassApiResponse): Array<{\n kind: 'node' | 'way' | 'relation';\n id: number;\n tags: Array<{ k: string; v: string }>;\n refs: number[];\n lat: number | null;\n lon: number | null;\n ref_roles: string[];\n ref_types: string[];\n }> {\n type FormattedElement = {\n kind: 'node' | 'way' | 'relation';\n id: number;\n tags: Array<{ k: string; v: string }>;\n refs: number[];\n lat: number | null;\n lon: number | null;\n ref_roles: string[];\n ref_types: string[];\n };\n\n const formattedElements: FormattedElement[] = [];\n const emittedNodeIds = new Set<number>();\n\n const emitNode = (id: number, lat: number, lon: number) => {\n if (!emittedNodeIds.has(id)) {\n emittedNodeIds.add(id);\n formattedElements.push({ kind: 'node', id, tags: [], refs: [], lat, lon, ref_roles: [], ref_types: [] });\n }\n };\n\n osmData.elements.forEach((element) => {\n switch (element.type) {\n case 'node':\n if (element.lat !== undefined && element.lon !== undefined) {\n emitNode(element.id, element.lat, element.lon);\n }\n break;\n\n case 'way': {\n const refs: number[] = element.nodes ?? [];\n const tags = this.withDerivedLayerTag(element.tags);\n if (element.geometry && element.geometry.length > 0 && element.nodes) {\n for (let i = 0; i < element.nodes.length; i++) {\n const geo = element.geometry[i];\n if (geo) emitNode(element.nodes[i], geo.lat, geo.lon);\n }\n }\n formattedElements.push({\n kind: 'way',\n id: element.id,\n tags: tags ? Object.entries(tags).map(([k, v]) => ({ k, v })) : [],\n refs,\n lat: null,\n lon: null,\n ref_roles: [],\n ref_types: [],\n });\n break;\n }\n\n case 'relation': {\n const refs: number[] = [];\n const ref_roles: string[] = [];\n const ref_types: ('node' | 'way' | 'relation')[] = [];\n const tags = this.withDerivedLayerTag(element.tags);\n if (element.members) {\n element.members.forEach((member) => {\n refs.push(member.ref);\n ref_roles.push(member.role || '');\n ref_types.push(member.type);\n });\n }\n formattedElements.push({\n kind: 'relation',\n id: element.id,\n tags: tags ? Object.entries(tags).map(([k, v]) => ({ k, v })) : [],\n refs,\n lat: null,\n lon: null,\n ref_roles,\n ref_types,\n });\n break;\n }\n }\n });\n\n return formattedElements;\n }\n\n // ---------------------------------------------------------------------------\n // Derived layer tagging\n // ---------------------------------------------------------------------------\n\n private getDerivedLayerTag(tags?: Record<string, string>): 'parks' | 'water' | 'roads' | 'buildings' | null {\n if (!tags) return null;\n\n if (this.isBuildingTagSet(tags)) {\n return 'buildings';\n }\n\n if (this.isRoadTagSet(tags)) {\n return 'roads';\n }\n\n if (\n this.hasTagValue(tags, 'leisure', PARKS_LEISURE_VALUES) ||\n this.hasTagValue(tags, 'landuse', PARKS_LANDUSE_VALUES) ||\n this.hasTagValue(tags, 'natural', PARKS_NATURAL_VALUES)\n ) {\n return 'parks';\n }\n\n if (\n this.hasTagValue(tags, 'natural', WATER_NATURAL_VALUES) ||\n this.hasTagValue(tags, 'water', WATER_FEATURE_VALUES)\n ) {\n return 'water';\n }\n\n return null;\n }\n\n private isRoadTagSet(tags: Record<string, string>): boolean {\n return (\n tags.highway !== undefined &&\n tags.area !== 'yes' &&\n !this.hasTagValue(tags, 'highway', EXCLUDED_HIGHWAY_VALUES)\n );\n }\n\n private isBuildingTagSet(tags: Record<string, string>): boolean {\n const hasBuildingKind =\n (tags.building !== undefined && !this.hasTagValue(tags, 'building', EXCLUDED_BUILDING_VALUES)) ||\n (tags['building:part'] !== undefined && !this.hasTagValue(tags, 'building:part', EXCLUDED_BUILDING_VALUES)) ||\n tags.type === 'building' ||\n (tags.type === 'multipolygon' && tags.building !== undefined && !this.hasTagValue(tags, 'building', EXCLUDED_BUILDING_VALUES)) ||\n (tags.type === 'multipolygon' && tags['building:part'] !== undefined && !this.hasTagValue(tags, 'building:part', EXCLUDED_BUILDING_VALUES));\n\n return hasBuildingKind;\n }\n\n private hasTagValue(tags: Record<string, string>, key: string, values: readonly string[]): boolean {\n const value = tags[key];\n return value !== undefined && values.includes(value);\n }\n\n private withDerivedLayerTag(tags?: Record<string, string>): Record<string, string> | undefined {\n if (!tags) return tags;\n\n const derivedLayer = this.getDerivedLayerTag(tags);\n if (!derivedLayer) return tags;\n\n return {\n ...tags,\n __autk_layer: derivedLayer,\n };\n }\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { BoundingBox, GridLayerTable } from '../../../shared/interfaces';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\n\nexport interface LoadGridLayerParams {\n boundingBox?: BoundingBox;\n rows: number;\n columns: number;\n outputTableName: string;\n workspace?: string;\n}\n\n/**\n * Creates a grid layer table with evenly spaced cell centroids.\n */\nexport class LoadGridLayerUseCase {\n private conn: AsyncDuckDBConnection;\n\n constructor(conn: AsyncDuckDBConnection) {\n this.conn = conn;\n }\n\n async exec(params: LoadGridLayerParams): Promise<GridLayerTable> {\n const { boundingBox, rows, columns, outputTableName, workspace = 'main' } = params;\n const qualifiedTableName = `${workspace}.${outputTableName}`;\n\n if (!boundingBox) {\n throw new Error('Bounding box is required to load a grid layer.');\n }\n\n if (rows <= 0 || columns <= 0) {\n throw new Error('Rows and columns must be positive integers.');\n }\n\n const { minLon, minLat, maxLon, maxLat } = boundingBox;\n\n // 1. Create (or replace) empty table\n const createTableSql = `CREATE OR REPLACE TABLE ${qualifiedTableName} (\n geometry GEOMETRY,\n properties STRUCT(row INTEGER, \"column\" INTEGER)\n );`;\n\n await this.conn.query(createTableSql);\n\n // 2. Generate grid cell centroids in JS and bulk-insert\n const lonStep = (maxLon - minLon) / columns;\n const latStep = (maxLat - minLat) / rows;\n\n const values: string[] = [];\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < columns; c++) {\n // Calculate the center point of each grid cell\n const centerLon = minLon + (c + 0.5) * lonStep;\n const centerLat = minLat + (r + 0.5) * latStep;\n\n values.push(`(ST_Point(${centerLon}, ${centerLat}), {'row': ${r}, 'column': ${c}})`);\n }\n }\n\n const insertSql = `INSERT INTO ${qualifiedTableName} VALUES ${values.join(',')};`;\n\n await this.conn.query(insertSql);\n\n // 3. Create spatial index on geometry column\n const createIndexSql = `CREATE INDEX idx_${outputTableName}_geometry ON ${qualifiedTableName} USING RTREE (geometry);`;\n await this.conn.query(createIndexSql);\n\n const describeTableResponse = await this.conn.query(`DESCRIBE ${qualifiedTableName}`);\n\n return {\n source: 'user',\n type: 'raster',\n name: outputTableName,\n columns: getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray()),\n };\n }\n}\n","export const THIS_IS_NOT_AN_OBJECT = \"This is not an object\";\nexport const THIS_IS_NOT_A_FLOAT16ARRAY_OBJECT = \"This is not a Float16Array object\";\nexport const THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY =\n \"This constructor is not a subclass of Float16Array\";\nexport const THE_CONSTRUCTOR_PROPERTY_VALUE_IS_NOT_AN_OBJECT =\n \"The constructor property value is not an object\";\nexport const SPECIES_CONSTRUCTOR_DIDNT_RETURN_TYPEDARRAY_OBJECT =\n \"Species constructor didn't return TypedArray object\";\nexport const DERIVED_CONSTRUCTOR_CREATED_TYPEDARRAY_OBJECT_WHICH_WAS_TOO_SMALL_LENGTH =\n \"Derived constructor created TypedArray object which was too small length\";\nexport const ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER =\n \"Attempting to access detached ArrayBuffer\";\nexport const CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT =\n \"Cannot convert undefined or null to object\";\nexport const CANNOT_MIX_BIGINT_AND_OTHER_TYPES =\n \"Cannot mix BigInt and other types, use explicit conversions\";\nexport const ITERATOR_PROPERTY_IS_NOT_CALLABLE = \"@@iterator property is not callable\";\nexport const REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE =\n \"Reduce of empty array with no initial value\";\nexport const THE_COMPARISON_FUNCTION_MUST_BE_EITHER_A_FUNCTION_OR_UNDEFINED =\n \"The comparison function must be either a function or undefined\";\nexport const OFFSET_IS_OUT_OF_BOUNDS = \"Offset is out of bounds\";\n","/* eslint-disable no-restricted-globals, no-restricted-syntax */\n/* global SharedArrayBuffer */\n\nimport { CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT } from \"./messages.mjs\";\n\n/** @type {<T extends (...args: any) => any>(target: T) => (thisArg: ThisType<T>, ...args: any[]) => any} */\nfunction uncurryThis(target) {\n return (thisArg, ...args) => {\n return ReflectApply(target, thisArg, args);\n };\n}\n\n/** @type {(target: any, key: string | symbol) => (thisArg: any, ...args: any[]) => any} */\nfunction uncurryThisGetter(target, key) {\n return uncurryThis(\n ReflectGetOwnPropertyDescriptor(\n target,\n key\n ).get\n );\n}\n\n// Reflect\nexport const {\n apply: ReflectApply,\n construct: ReflectConstruct,\n defineProperty: ReflectDefineProperty,\n get: ReflectGet,\n getOwnPropertyDescriptor: ReflectGetOwnPropertyDescriptor,\n getPrototypeOf: ReflectGetPrototypeOf,\n has: ReflectHas,\n ownKeys: ReflectOwnKeys,\n set: ReflectSet,\n setPrototypeOf: ReflectSetPrototypeOf,\n} = Reflect;\n\n// Proxy\nexport const NativeProxy = Proxy;\n\n// Number\nexport const {\n EPSILON,\n MAX_SAFE_INTEGER,\n isFinite: NumberIsFinite,\n isNaN: NumberIsNaN,\n} = Number;\n\n// Symbol\nexport const {\n iterator: SymbolIterator,\n species: SymbolSpecies,\n toStringTag: SymbolToStringTag,\n for: SymbolFor,\n} = Symbol;\n\n// Object\nexport const NativeObject = Object;\nexport const {\n create: ObjectCreate,\n defineProperty: ObjectDefineProperty,\n freeze: ObjectFreeze,\n is: ObjectIs,\n} = NativeObject;\nconst ObjectPrototype = NativeObject.prototype;\n/** @type {(object: object, key: PropertyKey) => Function | undefined} */\nexport const ObjectPrototype__lookupGetter__ = /** @type {any} */ (ObjectPrototype).__lookupGetter__\n ? uncurryThis(/** @type {any} */ (ObjectPrototype).__lookupGetter__)\n : (object, key) => {\n if (object == null) {\n throw NativeTypeError(\n CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT\n );\n }\n\n let target = NativeObject(object);\n do {\n const descriptor = ReflectGetOwnPropertyDescriptor(target, key);\n if (descriptor !== undefined) {\n if (ObjectHasOwn(descriptor, \"get\")) {\n return descriptor.get;\n }\n\n return;\n }\n } while ((target = ReflectGetPrototypeOf(target)) !== null);\n };\n/** @type {(object: object, key: PropertyKey) => boolean} */\nexport const ObjectHasOwn = /** @type {any} */ (NativeObject).hasOwn ||\n uncurryThis(ObjectPrototype.hasOwnProperty);\n\n// Array\nconst NativeArray = Array;\nexport const ArrayIsArray = NativeArray.isArray;\nconst ArrayPrototype = NativeArray.prototype;\n/** @type {(array: ArrayLike<unknown>, separator?: string) => string} */\nexport const ArrayPrototypeJoin = uncurryThis(ArrayPrototype.join);\n/** @type {<T>(array: T[], ...items: T[]) => number} */\nexport const ArrayPrototypePush = uncurryThis(ArrayPrototype.push);\n/** @type {(array: ArrayLike<unknown>, ...opts: any[]) => string} */\nexport const ArrayPrototypeToLocaleString = uncurryThis(\n ArrayPrototype.toLocaleString\n);\nexport const NativeArrayPrototypeSymbolIterator = ArrayPrototype[SymbolIterator];\n/** @type {<T>(array: T[]) => IterableIterator<T>} */\nexport const ArrayPrototypeSymbolIterator = uncurryThis(NativeArrayPrototypeSymbolIterator);\n\n// Math\nexport const {\n abs: MathAbs,\n trunc: MathTrunc,\n} = Math;\n\n// ArrayBuffer\nexport const NativeArrayBuffer = ArrayBuffer;\nexport const ArrayBufferIsView = NativeArrayBuffer.isView;\nconst ArrayBufferPrototype = NativeArrayBuffer.prototype;\n/** @type {(buffer: ArrayBuffer, begin?: number, end?: number) => number} */\nexport const ArrayBufferPrototypeSlice = uncurryThis(ArrayBufferPrototype.slice);\n/** @type {(buffer: ArrayBuffer) => ArrayBuffer} */\nexport const ArrayBufferPrototypeGetByteLength = uncurryThisGetter(ArrayBufferPrototype, \"byteLength\");\n\n// SharedArrayBuffer\nexport const NativeSharedArrayBuffer = typeof SharedArrayBuffer !== \"undefined\" ? SharedArrayBuffer : null;\n/** @type {(buffer: SharedArrayBuffer) => SharedArrayBuffer} */\nexport const SharedArrayBufferPrototypeGetByteLength = NativeSharedArrayBuffer\n && uncurryThisGetter(NativeSharedArrayBuffer.prototype, \"byteLength\");\n\n// TypedArray\n/** @typedef {Uint8Array|Uint8ClampedArray|Uint16Array|Uint32Array|Int8Array|Int16Array|Int32Array|Float32Array|Float64Array|BigUint64Array|BigInt64Array} TypedArray */\n/** @type {any} */\nexport const TypedArray = ReflectGetPrototypeOf(Uint8Array);\nconst TypedArrayFrom = TypedArray.from;\nexport const TypedArrayPrototype = TypedArray.prototype;\nexport const NativeTypedArrayPrototypeSymbolIterator = TypedArrayPrototype[SymbolIterator];\n/** @type {(typedArray: TypedArray) => IterableIterator<number>} */\nexport const TypedArrayPrototypeKeys = uncurryThis(TypedArrayPrototype.keys);\n/** @type {(typedArray: TypedArray) => IterableIterator<number>} */\nexport const TypedArrayPrototypeValues = uncurryThis(\n TypedArrayPrototype.values\n);\n/** @type {(typedArray: TypedArray) => IterableIterator<[number, number]>} */\nexport const TypedArrayPrototypeEntries = uncurryThis(\n TypedArrayPrototype.entries\n);\n/** @type {(typedArray: TypedArray, array: ArrayLike<number>, offset?: number) => void} */\nexport const TypedArrayPrototypeSet = uncurryThis(TypedArrayPrototype.set);\n/** @type {<T extends TypedArray>(typedArray: T) => T} */\nexport const TypedArrayPrototypeReverse = uncurryThis(\n TypedArrayPrototype.reverse\n);\n/** @type {<T extends TypedArray>(typedArray: T, value: number, start?: number, end?: number) => T} */\nexport const TypedArrayPrototypeFill = uncurryThis(TypedArrayPrototype.fill);\n/** @type {<T extends TypedArray>(typedArray: T, target: number, start: number, end?: number) => T} */\nexport const TypedArrayPrototypeCopyWithin = uncurryThis(\n TypedArrayPrototype.copyWithin\n);\n/** @type {<T extends TypedArray>(typedArray: T, compareFn?: (a: number, b: number) => number) => T} */\nexport const TypedArrayPrototypeSort = uncurryThis(TypedArrayPrototype.sort);\n/** @type {<T extends TypedArray>(typedArray: T, start?: number, end?: number) => T} */\nexport const TypedArrayPrototypeSlice = uncurryThis(TypedArrayPrototype.slice);\n/** @type {<T extends TypedArray>(typedArray: T, start?: number, end?: number) => T} */\nexport const TypedArrayPrototypeSubarray = uncurryThis(\n TypedArrayPrototype.subarray\n);\n/** @type {((typedArray: TypedArray) => ArrayBuffer)} */\nexport const TypedArrayPrototypeGetBuffer = uncurryThisGetter(\n TypedArrayPrototype,\n \"buffer\"\n);\n/** @type {((typedArray: TypedArray) => number)} */\nexport const TypedArrayPrototypeGetByteOffset = uncurryThisGetter(\n TypedArrayPrototype,\n \"byteOffset\"\n);\n/** @type {((typedArray: TypedArray) => number)} */\nexport const TypedArrayPrototypeGetLength = uncurryThisGetter(\n TypedArrayPrototype,\n \"length\"\n);\n/** @type {(target: unknown) => string} */\nexport const TypedArrayPrototypeGetSymbolToStringTag = uncurryThisGetter(\n TypedArrayPrototype,\n SymbolToStringTag\n);\n\n// Uint8Array\nexport const NativeUint8Array = Uint8Array;\n\n// Uint16Array\nexport const NativeUint16Array = Uint16Array;\n/** @type {Uint16ArrayConstructor[\"from\"]} */\nexport const Uint16ArrayFrom = (...args) => {\n return ReflectApply(TypedArrayFrom, NativeUint16Array, args);\n};\n\n// Uint32Array\nexport const NativeUint32Array = Uint32Array;\n\n// Float32Array\nexport const NativeFloat32Array = Float32Array;\n\n// ArrayIterator\n/** @type {any} */\nexport const ArrayIteratorPrototype = ReflectGetPrototypeOf([][SymbolIterator]());\n/** @type {<T>(arrayIterator: IterableIterator<T>) => IteratorResult<T>} */\nexport const ArrayIteratorPrototypeNext = uncurryThis(ArrayIteratorPrototype.next);\n\n// Generator\n/** @type {<T = unknown, TReturn = any, TNext = unknown>(generator: Generator<T, TReturn, TNext>, value?: TNext) => T} */\nexport const GeneratorPrototypeNext = uncurryThis((function* () {})().next);\n\n// Iterator\nexport const IteratorPrototype = ReflectGetPrototypeOf(ArrayIteratorPrototype);\n\n// DataView\nconst DataViewPrototype = DataView.prototype;\n/** @type {(dataView: DataView, byteOffset: number, littleEndian?: boolean) => number} */\nexport const DataViewPrototypeGetUint16 = uncurryThis(\n DataViewPrototype.getUint16\n);\n/** @type {(dataView: DataView, byteOffset: number, value: number, littleEndian?: boolean) => void} */\nexport const DataViewPrototypeSetUint16 = uncurryThis(\n DataViewPrototype.setUint16\n);\n\n// Error\nexport const NativeTypeError = TypeError;\nexport const NativeRangeError = RangeError;\n\n// WeakSet\n/**\n * Do not construct with arguments to avoid calling the \"add\" method\n * @type {{new <T extends {}>(): WeakSet<T>}}\n */\nexport const NativeWeakSet = WeakSet;\nconst WeakSetPrototype = NativeWeakSet.prototype;\n/** @type {<T extends {}>(set: WeakSet<T>, value: T) => Set<T>} */\nexport const WeakSetPrototypeAdd = uncurryThis(WeakSetPrototype.add);\n/** @type {<T extends {}>(set: WeakSet<T>, value: T) => boolean} */\nexport const WeakSetPrototypeHas = uncurryThis(WeakSetPrototype.has);\n\n// WeakMap\n/**\n * Do not construct with arguments to avoid calling the \"set\" method\n * @type {{new <K extends {}, V>(): WeakMap<K, V>}}\n */\nexport const NativeWeakMap = WeakMap;\nconst WeakMapPrototype = NativeWeakMap.prototype;\n/** @type {<K extends {}, V>(weakMap: WeakMap<K, V>, key: K) => V} */\nexport const WeakMapPrototypeGet = uncurryThis(WeakMapPrototype.get);\n/** @type {<K extends {}, V>(weakMap: WeakMap<K, V>, key: K) => boolean} */\nexport const WeakMapPrototypeHas = uncurryThis(WeakMapPrototype.has);\n/** @type {<K extends {}, V>(weakMap: WeakMap<K, V>, key: K, value: V) => WeakMap} */\nexport const WeakMapPrototypeSet = uncurryThis(WeakMapPrototype.set);\n","import {\n ArrayIteratorPrototype,\n ArrayIteratorPrototypeNext,\n ArrayPrototypeSymbolIterator,\n GeneratorPrototypeNext,\n IteratorPrototype,\n NativeArrayPrototypeSymbolIterator,\n NativeWeakMap,\n ObjectCreate,\n ObjectDefineProperty,\n ReflectGetOwnPropertyDescriptor,\n ReflectOwnKeys,\n SymbolIterator,\n WeakMapPrototypeGet,\n WeakMapPrototypeSet,\n} from \"./primordials.mjs\";\n\n/** @type {WeakMap<{}, IterableIterator<any>>} */\nconst arrayIterators = new NativeWeakMap();\n\nconst SafeIteratorPrototype = ObjectCreate(null, {\n next: {\n value: function next() {\n const arrayIterator = WeakMapPrototypeGet(arrayIterators, this);\n return ArrayIteratorPrototypeNext(arrayIterator);\n },\n },\n\n [SymbolIterator]: {\n value: function values() {\n return this;\n },\n },\n});\n\n/**\n * Wrap the Array around the SafeIterator If Array.prototype [@@iterator] has been modified\n * @type {<T>(array: T[]) => Iterable<T>}\n */\nexport function safeIfNeeded(array) {\n if (\n array[SymbolIterator] === NativeArrayPrototypeSymbolIterator &&\n ArrayIteratorPrototype.next === ArrayIteratorPrototypeNext\n ) {\n return array;\n }\n\n const safe = ObjectCreate(SafeIteratorPrototype);\n WeakMapPrototypeSet(arrayIterators, safe, ArrayPrototypeSymbolIterator(array));\n return safe;\n}\n\n/** @type {WeakMap<{}, Generator<any>>} */\nconst generators = new NativeWeakMap();\n\n/** @see https://tc39.es/ecma262/#sec-%arrayiteratorprototype%-object */\nconst DummyArrayIteratorPrototype = ObjectCreate(IteratorPrototype, {\n next: {\n value: function next() {\n const generator = WeakMapPrototypeGet(generators, this);\n return GeneratorPrototypeNext(generator);\n },\n writable: true,\n configurable: true,\n },\n});\n\nfor (const key of ReflectOwnKeys(ArrayIteratorPrototype)) {\n // next method has already defined\n if (key === \"next\") {\n continue;\n }\n\n // Copy ArrayIteratorPrototype descriptors to DummyArrayIteratorPrototype\n ObjectDefineProperty(DummyArrayIteratorPrototype, key, ReflectGetOwnPropertyDescriptor(ArrayIteratorPrototype, key));\n}\n\n/**\n * Wrap the Generator around the dummy ArrayIterator\n * @type {<T>(generator: Generator<T>) => IterableIterator<T>}\n */\nexport function wrap(generator) {\n const dummy = ObjectCreate(DummyArrayIteratorPrototype);\n WeakMapPrototypeSet(generators, dummy, generator);\n return dummy;\n}\n","import {\n EPSILON,\n MathAbs,\n NativeArrayBuffer,\n NativeFloat32Array,\n NativeUint16Array,\n NativeUint32Array,\n NativeUint8Array,\n NumberIsFinite,\n NumberIsNaN,\n} from \"./primordials.mjs\";\n\nconst INVERSE_OF_EPSILON = 1 / EPSILON;\n\n/**\n * rounds to the nearest value;\n * if the number falls midway, it is rounded to the nearest value with an even least significant digit\n * @param {number} num\n * @returns {number}\n */\nfunction roundTiesToEven(num) {\n return (num + INVERSE_OF_EPSILON) - INVERSE_OF_EPSILON;\n}\n\nconst FLOAT16_MIN_VALUE = 6.103515625e-05;\nconst FLOAT16_MAX_VALUE = 65504;\nconst FLOAT16_EPSILON = 0.0009765625;\n\nconst FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE = FLOAT16_EPSILON * FLOAT16_MIN_VALUE;\nconst FLOAT16_EPSILON_DEVIDED_BY_EPSILON = FLOAT16_EPSILON * INVERSE_OF_EPSILON;\n\n/**\n * round a number to a half float number\n * @param {unknown} num - double float\n * @returns {number} half float number\n */\nexport function roundToFloat16(num) {\n const number = +num;\n\n // NaN, Infinity, -Infinity, 0, -0\n if (!NumberIsFinite(number) || number === 0) {\n return number;\n }\n\n // finite except 0, -0\n const sign = number > 0 ? 1 : -1;\n const absolute = MathAbs(number);\n\n // small number\n if (absolute < FLOAT16_MIN_VALUE) {\n return sign * roundTiesToEven(absolute / FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE) * FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE;\n }\n\n const temp = (1 + FLOAT16_EPSILON_DEVIDED_BY_EPSILON) * absolute;\n const result = temp - (temp - absolute);\n\n // large number\n if (result > FLOAT16_MAX_VALUE || NumberIsNaN(result)) {\n return sign * Infinity;\n }\n\n return sign * result;\n}\n\n// base algorithm: http://fox-toolkit.org/ftp/fasthalffloatconversion.pdf\n\nconst buffer = new NativeArrayBuffer(4);\nconst floatView = new NativeFloat32Array(buffer);\nconst uint32View = new NativeUint32Array(buffer);\n\nconst baseTable = new NativeUint16Array(512);\nconst shiftTable = new NativeUint8Array(512);\n\nfor (let i = 0; i < 256; ++i) {\n const e = i - 127;\n\n // very small number (0, -0)\n if (e < -24) {\n baseTable[i] = 0x0000;\n baseTable[i | 0x100] = 0x8000;\n shiftTable[i] = 24;\n shiftTable[i | 0x100] = 24;\n\n // small number (denorm)\n } else if (e < -14) {\n baseTable[i] = 0x0400 >> (-e - 14);\n baseTable[i | 0x100] = (0x0400 >> (-e - 14)) | 0x8000;\n shiftTable[i] = -e - 1;\n shiftTable[i | 0x100] = -e - 1;\n\n // normal number\n } else if (e <= 15) {\n baseTable[i] = (e + 15) << 10;\n baseTable[i | 0x100] = ((e + 15) << 10) | 0x8000;\n shiftTable[i] = 13;\n shiftTable[i | 0x100] = 13;\n\n // large number (Infinity, -Infinity)\n } else if (e < 128) {\n baseTable[i] = 0x7c00;\n baseTable[i | 0x100] = 0xfc00;\n shiftTable[i] = 24;\n shiftTable[i | 0x100] = 24;\n\n // stay (NaN, Infinity, -Infinity)\n } else {\n baseTable[i] = 0x7c00;\n baseTable[i | 0x100] = 0xfc00;\n shiftTable[i] = 13;\n shiftTable[i | 0x100] = 13;\n }\n}\n\n/**\n * round a number to a half float number bits\n * @param {unknown} num - double float\n * @returns {number} half float number bits\n */\nexport function roundToFloat16Bits(num) {\n floatView[0] = roundToFloat16(num);\n const f = uint32View[0];\n const e = (f >> 23) & 0x1ff;\n return baseTable[e] + ((f & 0x007fffff) >> shiftTable[e]);\n}\n\nconst mantissaTable = new NativeUint32Array(2048);\nfor (let i = 1; i < 1024; ++i) {\n let m = i << 13; // zero pad mantissa bits\n let e = 0; // zero exponent\n\n // normalized\n while ((m & 0x00800000) === 0) {\n m <<= 1;\n e -= 0x00800000; // decrement exponent\n }\n\n m &= ~0x00800000; // clear leading 1 bit\n e += 0x38800000; // adjust bias\n\n mantissaTable[i] = m | e;\n}\nfor (let i = 1024; i < 2048; ++i) {\n mantissaTable[i] = 0x38000000 + ((i - 1024) << 13);\n}\n\nconst exponentTable = new NativeUint32Array(64);\nfor (let i = 1; i < 31; ++i) {\n exponentTable[i] = i << 23;\n}\nexponentTable[31] = 0x47800000;\nexponentTable[32] = 0x80000000;\nfor (let i = 33; i < 63; ++i) {\n exponentTable[i] = 0x80000000 + ((i - 32) << 23);\n}\nexponentTable[63] = 0xc7800000;\n\nconst offsetTable = new NativeUint16Array(64);\nfor (let i = 1; i < 64; ++i) {\n if (i !== 32) {\n offsetTable[i] = 1024;\n }\n}\n\n/**\n * convert a half float number bits to a number\n * @param {number} float16bits - half float number bits\n * @returns {number} double float\n */\nexport function convertToNumber(float16bits) {\n const i = float16bits >> 10;\n uint32View[0] = mantissaTable[offsetTable[i] + (float16bits & 0x3ff)] + exponentTable[i];\n return floatView[0];\n}\n","import { safeIfNeeded } from \"./_util/arrayIterator.mjs\";\nimport { convertToNumber, roundToFloat16Bits } from \"./_util/converter.mjs\";\nimport {\n DataViewPrototypeGetUint16,\n DataViewPrototypeSetUint16,\n} from \"./_util/primordials.mjs\";\n\n/**\n * returns an unsigned 16-bit float at the specified byte offset from the start of the DataView\n * @param {DataView} dataView\n * @param {number} byteOffset\n * @param {[boolean]} opts\n * @returns {number}\n */\nexport function getFloat16(dataView, byteOffset, ...opts) {\n return convertToNumber(\n DataViewPrototypeGetUint16(dataView, byteOffset, ...safeIfNeeded(opts))\n );\n}\n\n/**\n * stores an unsigned 16-bit float value at the specified byte offset from the start of the DataView\n * @param {DataView} dataView\n * @param {number} byteOffset\n * @param {number} value\n * @param {[boolean]} opts\n */\nexport function setFloat16(dataView, byteOffset, value, ...opts) {\n return DataViewPrototypeSetUint16(\n dataView,\n byteOffset,\n roundToFloat16Bits(value),\n ...safeIfNeeded(opts)\n );\n}\n","export default function getAttribute(tag, attributeName, options) {\n const debug = (options && options.debug) || false;\n if (debug) console.log(\"[xml-utils] getting \" + attributeName + \" in \" + tag);\n\n const xml = typeof tag === \"object\" ? tag.outer : tag;\n\n // only search for attributes in the opening tag\n const opening = xml.slice(0, xml.indexOf(\">\") + 1);\n\n const quotechars = ['\"', \"'\"];\n for (let i = 0; i < quotechars.length; i++) {\n const char = quotechars[i];\n const pattern = attributeName + \"\\\\=\" + char + \"([^\" + char + \"]*)\" + char;\n if (debug) console.log(\"[xml-utils] pattern:\", pattern);\n\n const re = new RegExp(pattern);\n const match = re.exec(opening);\n if (debug) console.log(\"[xml-utils] match:\", match);\n if (match) return match[1];\n }\n}\n","export default function indexOfMatch(xml, pattern, startIndex) {\n const re = new RegExp(pattern);\n const match = re.exec(xml.slice(startIndex));\n if (match) return startIndex + match.index;\n else return -1;\n}\n","export default function indexOfMatchEnd(xml, pattern, startIndex) {\n const re = new RegExp(pattern);\n const match = re.exec(xml.slice(startIndex));\n if (match) return startIndex + match.index + match[0].length - 1;\n else return -1;\n}\n","export default function countSubstring(string, substring) {\n const pattern = new RegExp(substring, \"g\");\n const match = string.match(pattern);\n return match ? match.length : 0;\n}\n","import indexOfMatch from \"./index-of-match.mjs\";\nimport indexOfMatchEnd from \"./index-of-match-end.mjs\";\nimport countSubstring from \"./count-substring.mjs\";\n\nexport default function findTagByName(xml, tagName, options) {\n const debug = (options && options.debug) || false;\n const nested = !(options && typeof options.nested === false);\n\n const startIndex = (options && options.startIndex) || 0;\n\n if (debug) console.log(\"[xml-utils] starting findTagByName with\", tagName, \" and \", options);\n\n const start = indexOfMatch(xml, `\\<${tagName}[ \\n\\>\\/]`, startIndex);\n if (debug) console.log(\"[xml-utils] start:\", start);\n if (start === -1) return undefined;\n\n const afterStart = xml.slice(start + tagName.length);\n\n let relativeEnd = indexOfMatchEnd(afterStart, \"^[^<]*[ /]>\", 0);\n\n const selfClosing = relativeEnd !== -1 && afterStart[relativeEnd - 1] === \"/\";\n if (debug) console.log(\"[xml-utils] selfClosing:\", selfClosing);\n\n if (selfClosing === false) {\n // check if tag has subtags with the same name\n if (nested) {\n let startIndex = 0;\n let openings = 1;\n let closings = 0;\n while ((relativeEnd = indexOfMatchEnd(afterStart, \"[ /]\" + tagName + \">\", startIndex)) !== -1) {\n const clip = afterStart.substring(startIndex, relativeEnd + 1);\n openings += countSubstring(clip, \"<\" + tagName + \"[ \\n\\t>]\");\n closings += countSubstring(clip, \"</\" + tagName + \">\");\n // we can't have more openings than closings\n if (closings >= openings) break;\n startIndex = relativeEnd;\n }\n } else {\n relativeEnd = indexOfMatchEnd(afterStart, \"[ /]\" + tagName + \">\", 0);\n }\n }\n\n const end = start + tagName.length + relativeEnd + 1;\n if (debug) console.log(\"[xml-utils] end:\", end);\n if (end === -1) return undefined;\n\n const outer = xml.slice(start, end);\n // tag is like <gml:identifier codeSpace=\"OGP\">urn:ogc:def:crs:EPSG::32617</gml:identifier>\n\n let inner;\n if (selfClosing) {\n inner = null;\n } else {\n inner = outer.slice(outer.indexOf(\">\") + 1, outer.lastIndexOf(\"<\"));\n }\n\n return { inner, outer, start, end };\n}\n","import findTagByName from \"./find-tag-by-name.mjs\";\n\nexport default function findTagsByName(xml, tagName, options) {\n const tags = [];\n const debug = (options && options.debug) || false;\n const nested = options && typeof options.nested === \"boolean\" ? options.nested : true;\n let startIndex = (options && options.startIndex) || 0;\n let tag;\n while ((tag = findTagByName(xml, tagName, { debug, startIndex }))) {\n if (nested) {\n startIndex = tag.start + 1 + tagName.length;\n } else {\n startIndex = tag.end;\n }\n tags.push(tag);\n }\n if (debug) console.log(\"findTagsByName found\", tags.length, \"tags\");\n return tags;\n}\n","export function fromWhiteIsZero(raster, max) {\n const { width, height } = raster;\n const rgbRaster = new Uint8Array(width * height * 3);\n let value;\n for (let i = 0, j = 0; i < raster.length; ++i, j += 3) {\n value = 256 - (raster[i] / max) * 256;\n rgbRaster[j] = value;\n rgbRaster[j + 1] = value;\n rgbRaster[j + 2] = value;\n }\n return rgbRaster;\n}\nexport function fromBlackIsZero(raster, max) {\n const { width, height } = raster;\n const rgbRaster = new Uint8Array(width * height * 3);\n let value;\n for (let i = 0, j = 0; i < raster.length; ++i, j += 3) {\n value = (raster[i] / max) * 256;\n rgbRaster[j] = value;\n rgbRaster[j + 1] = value;\n rgbRaster[j + 2] = value;\n }\n return rgbRaster;\n}\nexport function fromPalette(raster, colorMap) {\n const { width, height } = raster;\n const rgbRaster = new Uint8Array(width * height * 3);\n const greenOffset = colorMap.length / 3;\n const blueOffset = (colorMap.length / 3) * 2;\n for (let i = 0, j = 0; i < raster.length; ++i, j += 3) {\n const mapIndex = raster[i];\n rgbRaster[j] = (colorMap[mapIndex] / 65536) * 256;\n rgbRaster[j + 1] = (colorMap[mapIndex + greenOffset] / 65536) * 256;\n rgbRaster[j + 2] = (colorMap[mapIndex + blueOffset] / 65536) * 256;\n }\n return rgbRaster;\n}\nexport function fromCMYK(cmykRaster) {\n const { width, height } = cmykRaster;\n const rgbRaster = new Uint8Array(width * height * 3);\n for (let i = 0, j = 0; i < cmykRaster.length; i += 4, j += 3) {\n const c = cmykRaster[i];\n const m = cmykRaster[i + 1];\n const y = cmykRaster[i + 2];\n const k = cmykRaster[i + 3];\n rgbRaster[j] = 255 * ((255 - c) / 256) * ((255 - k) / 256);\n rgbRaster[j + 1] = 255 * ((255 - m) / 256) * ((255 - k) / 256);\n rgbRaster[j + 2] = 255 * ((255 - y) / 256) * ((255 - k) / 256);\n }\n return rgbRaster;\n}\nexport function fromYCbCr(yCbCrRaster) {\n const { width, height } = yCbCrRaster;\n const rgbRaster = new Uint8ClampedArray(width * height * 3);\n for (let i = 0, j = 0; i < yCbCrRaster.length; i += 3, j += 3) {\n const y = yCbCrRaster[i];\n const cb = yCbCrRaster[i + 1];\n const cr = yCbCrRaster[i + 2];\n rgbRaster[j] = y + 1.402 * (cr - 0x80);\n rgbRaster[j + 1] = y - 0.34414 * (cb - 0x80) - 0.71414 * (cr - 0x80);\n rgbRaster[j + 2] = y + 1.772 * (cb - 0x80);\n }\n return rgbRaster;\n}\nconst Xn = 0.95047;\nconst Yn = 1.0;\nconst Zn = 1.08883;\n// from https://github.com/antimatter15/rgb-lab/blob/master/color.js\nexport function fromCIELab(cieLabRaster) {\n const { width, height } = cieLabRaster;\n const rgbRaster = new Uint8Array(width * height * 3);\n for (let i = 0, j = 0; i < cieLabRaster.length; i += 3, j += 3) {\n const L = cieLabRaster[i + 0];\n const a_ = (cieLabRaster[i + 1] << 24) >> 24; // conversion from uint8 to int8\n const b_ = (cieLabRaster[i + 2] << 24) >> 24; // same\n let y = (L + 16) / 116;\n let x = a_ / 500 + y;\n let z = y - b_ / 200;\n let r;\n let g;\n let b;\n x = Xn * (x * x * x > 0.008856 ? x * x * x : (x - 16 / 116) / 7.787);\n y = Yn * (y * y * y > 0.008856 ? y * y * y : (y - 16 / 116) / 7.787);\n z = Zn * (z * z * z > 0.008856 ? z * z * z : (z - 16 / 116) / 7.787);\n r = x * 3.2406 + y * -1.5372 + z * -0.4986;\n g = x * -0.9689 + y * 1.8758 + z * 0.0415;\n b = x * 0.0557 + y * -0.204 + z * 1.057;\n r = r > 0.0031308 ? 1.055 * r ** (1 / 2.4) - 0.055 : 12.92 * r;\n g = g > 0.0031308 ? 1.055 * g ** (1 / 2.4) - 0.055 : 12.92 * g;\n b = b > 0.0031308 ? 1.055 * b ** (1 / 2.4) - 0.055 : 12.92 * b;\n rgbRaster[j] = Math.max(0, Math.min(1, r)) * 255;\n rgbRaster[j + 1] = Math.max(0, Math.min(1, g)) * 255;\n rgbRaster[j + 2] = Math.max(0, Math.min(1, b)) * 255;\n }\n return rgbRaster;\n}\n//# sourceMappingURL=rgb.js.map","/** @import BaseDecoder, {BaseDecoderParameters} from \"./basedecoder.js\" */\n/**\n * @typedef {Object} RegistryEntry\n * @property {function():Promise<typeof BaseDecoder>} importFn\n * @property {function(import(\"../imagefiledirectory.js\").ImageFileDirectory):Promise<BaseDecoderParameters>} decoderParameterFn\n * @property {boolean} preferWorker\n */\n/** @type {Map<number | undefined, RegistryEntry>} */\nconst registry = new Map();\n/**\n * Default decoder parameter retrieval function\n * @param {import(\"../imagefiledirectory.js\").ImageFileDirectory} fileDirectory\n * @returns {Promise<BaseDecoderParameters>}\n */\nasync function defaultDecoderParameterFn(fileDirectory) {\n const isTiled = !fileDirectory.hasTag('StripOffsets');\n return /** @type {BaseDecoderParameters} */ ({\n tileWidth: isTiled\n ? await fileDirectory.loadValue('TileWidth')\n : await fileDirectory.loadValue('ImageWidth'),\n tileHeight: isTiled\n ? await fileDirectory.loadValue('TileLength')\n : (await fileDirectory.loadValue('RowsPerStrip')\n || await fileDirectory.loadValue('ImageLength')),\n planarConfiguration: await fileDirectory.loadValue('PlanarConfiguration'),\n bitsPerSample: await fileDirectory.loadValue('BitsPerSample'),\n predictor: await fileDirectory.loadValue('Predictor') || 1,\n });\n}\n/**\n * Register a decoder for a specific compression method or a range of compressions\n * @param {(number|undefined|(number|undefined)[])} cases ids of the compression methods to register for\n * @param {function():Promise<typeof BaseDecoder>} importFn the function to import the decoder\n * @param {function(import(\"../imagefiledirectory.js\").ImageFileDirectory):Promise<BaseDecoderParameters>} decoderParameterFn\n * @param {boolean} preferWorker_ Whether to prefer running the decoder in a worker\n */\nexport function addDecoder(cases, importFn, decoderParameterFn = defaultDecoderParameterFn, preferWorker_ = true) {\n if (!Array.isArray(cases)) {\n cases = [cases]; // eslint-disable-line no-param-reassign\n }\n cases.forEach((c) => {\n registry.set(c, { importFn, decoderParameterFn, preferWorker: preferWorker_ });\n });\n}\n/**\n * Get the required decoder parameters for a specific compression method\n * @param {number|undefined} compression\n * @param {import('../imagefiledirectory.js').ImageFileDirectory} fileDirectory\n */\nexport async function getDecoderParameters(compression, fileDirectory) {\n if (!registry.has(compression)) {\n throw new Error(`Unknown compression method identifier: ${compression}`);\n }\n const { decoderParameterFn } = /** @type {RegistryEntry} */ (registry.get(compression));\n return decoderParameterFn(fileDirectory);\n}\n/**\n * Get a decoder for a specific compression and parameters\n * @param {number} compression the compression method identifier\n * @param {BaseDecoderParameters} decoderParameters the parameters for the decoder\n * @returns {Promise<import('./basedecoder.js').default>}\n */\nexport async function getDecoder(compression, decoderParameters) {\n if (!registry.has(compression)) {\n throw new Error(`Unknown compression method identifier: ${compression}`);\n }\n const { importFn } = /** @type {RegistryEntry} */ (registry.get(compression));\n const Decoder = await importFn();\n return new Decoder(decoderParameters);\n}\n/**\n * Whether to prefer running the decoder in a worker\n * @param {number|undefined} compression the compression method identifier\n * @returns {boolean}\n */\nexport function preferWorker(compression) {\n if (!registry.has(compression)) {\n throw new Error(`Unknown compression method identifier: ${compression}`);\n }\n return /** @type {RegistryEntry} */ (registry.get(compression)).preferWorker;\n}\nconst defaultDecoderDefinitions = [\n // No compression\n {\n cases: [undefined, 1],\n importFn: () => import('./raw.js').then((m) => m.default),\n preferWorker: false,\n },\n // LZW\n {\n cases: 5,\n importFn: () => import('./lzw.js').then((m) => m.default),\n },\n // Old-style JPEG\n {\n cases: 6,\n importFn: () => {\n throw new Error('old style JPEG compression is not supported.');\n },\n },\n // JPEG\n {\n cases: 7,\n importFn: () => import('./jpeg.js').then((m) => m.default),\n /**\n * @param {import(\"../imagefiledirectory.js\").ImageFileDirectory} fileDirectory\n */\n decoderParameterFn: async (fileDirectory) => {\n return {\n ...await defaultDecoderParameterFn(fileDirectory),\n JPEGTables: await fileDirectory.loadValue('JPEGTables'),\n };\n },\n },\n // Deflate / Adobe Deflate\n {\n cases: [8, 32946],\n importFn: () => import('./deflate.js').then((m) => m.default),\n },\n // PackBits\n {\n cases: 32773,\n importFn: () => import('./packbits.js').then((m) => m.default),\n },\n // LERC\n {\n cases: 34887,\n importFn: () => import('./lerc.js')\n .then(async (m) => {\n await m.zstd.init();\n return m;\n })\n .then((m) => m.default),\n /**\n * @param {import(\"../imagefiledirectory.js\").ImageFileDirectory} fileDirectory\n */\n decoderParameterFn: async (fileDirectory) => {\n return {\n ...await defaultDecoderParameterFn(fileDirectory),\n LercParameters: await fileDirectory.loadValue('LercParameters'),\n };\n },\n },\n // zstd\n {\n cases: 50000,\n importFn: () => import('./zstd.js')\n .then(async (m) => {\n await m.zstd.init();\n return m;\n })\n .then((m) => m.default),\n },\n // WebP Images\n {\n cases: 50001,\n importFn: () => import('./webimage.js').then((m) => m.default),\n /**\n * @param {import(\"../imagefiledirectory.js\").ImageFileDirectory} fileDirectory\n */\n decoderParameterFn: async (fileDirectory) => {\n return {\n ...await defaultDecoderParameterFn(fileDirectory),\n samplesPerPixel: Number(await fileDirectory.loadValue('SamplesPerPixel')) || 4,\n };\n },\n preferWorker: false,\n },\n];\n// Add default decoders to registry (end-user may override with other implementations)\nfor (const decoderDefinition of defaultDecoderDefinitions) {\n const { cases, importFn, decoderParameterFn, preferWorker: preferWorker_ } = decoderDefinition;\n addDecoder(cases, importFn, decoderParameterFn, preferWorker_);\n}\n//# sourceMappingURL=index.js.map","/**\n * @module resample\n */\n/**\n * @param {import(\"./geotiff.js\").TypedArray} array\n * @param {number} width\n * @param {number} height\n * @param {number} [samplesPerPixel=1]\n */\nfunction copyNewSize(array, width, height, samplesPerPixel = 1) {\n return new (Object.getPrototypeOf(array).constructor)(width * height * samplesPerPixel);\n}\n/**\n * Resample the input arrays using nearest neighbor value selection.\n * @param {import(\"./geotiff.js\").TypedArray[]} valueArrays The input arrays to resample\n * @param {number} inWidth The width of the input rasters\n * @param {number} inHeight The height of the input rasters\n * @param {number} outWidth The desired width of the output rasters\n * @param {number} outHeight The desired height of the output rasters\n * @returns {import(\"./geotiff.js\").TypedArray[]} The resampled rasters\n */\nexport function resampleNearest(valueArrays, inWidth, inHeight, outWidth, outHeight) {\n const relX = inWidth / outWidth;\n const relY = inHeight / outHeight;\n return valueArrays.map((array) => {\n const newArray = copyNewSize(array, outWidth, outHeight);\n for (let y = 0; y < outHeight; ++y) {\n const cy = Math.min(Math.round(relY * y), inHeight - 1);\n for (let x = 0; x < outWidth; ++x) {\n const cx = Math.min(Math.round(relX * x), inWidth - 1);\n const value = array[(cy * inWidth) + cx];\n newArray[(y * outWidth) + x] = value;\n }\n }\n return newArray;\n });\n}\n// simple linear interpolation, code from:\n// https://en.wikipedia.org/wiki/Linear_interpolation#Programming_language_support\n/**\n * @param {number} v0\n * @param {number} v1\n * @param {number} t\n */\nfunction lerp(v0, v1, t) {\n return ((1 - t) * v0) + (t * v1);\n}\n/**\n * Resample the input arrays using bilinear interpolation.\n * @param {import(\"./geotiff.js\").TypedArray[]} valueArrays The input arrays to resample\n * @param {number} inWidth The width of the input rasters\n * @param {number} inHeight The height of the input rasters\n * @param {number} outWidth The desired width of the output rasters\n * @param {number} outHeight The desired height of the output rasters\n * @returns {import(\"./geotiff.js\").TypedArray[]} The resampled rasters\n */\nexport function resampleBilinear(valueArrays, inWidth, inHeight, outWidth, outHeight) {\n const relX = inWidth / outWidth;\n const relY = inHeight / outHeight;\n return valueArrays.map((array) => {\n const newArray = copyNewSize(array, outWidth, outHeight);\n for (let y = 0; y < outHeight; ++y) {\n const rawY = relY * y;\n const yl = Math.floor(rawY);\n const yh = Math.min(Math.ceil(rawY), (inHeight - 1));\n for (let x = 0; x < outWidth; ++x) {\n const rawX = relX * x;\n const tx = rawX % 1;\n const xl = Math.floor(rawX);\n const xh = Math.min(Math.ceil(rawX), (inWidth - 1));\n const ll = array[(yl * inWidth) + xl];\n const hl = array[(yl * inWidth) + xh];\n const lh = array[(yh * inWidth) + xl];\n const hh = array[(yh * inWidth) + xh];\n const value = lerp(lerp(ll, hl, tx), lerp(lh, hh, tx), rawY % 1);\n newArray[(y * outWidth) + x] = value;\n }\n }\n return newArray;\n });\n}\n/**\n * Resample the input arrays using the selected resampling method.\n * @param {import(\"./geotiff.js\").TypedArray[]} valueArrays The input arrays to resample\n * @param {number} inWidth The width of the input rasters\n * @param {number} inHeight The height of the input rasters\n * @param {number} outWidth The desired width of the output rasters\n * @param {number} outHeight The desired height of the output rasters\n * @param {string} [method = 'nearest'] The desired resampling method\n * @returns {import(\"./geotiff.js\").TypedArray[]} The resampled rasters\n */\nexport function resample(valueArrays, inWidth, inHeight, outWidth, outHeight, method = 'nearest') {\n switch (method.toLowerCase()) {\n case 'nearest':\n return resampleNearest(valueArrays, inWidth, inHeight, outWidth, outHeight);\n case 'bilinear':\n case 'linear':\n return resampleBilinear(valueArrays, inWidth, inHeight, outWidth, outHeight);\n default:\n throw new Error(`Unsupported resampling method: '${method}'`);\n }\n}\n/**\n * Resample the pixel interleaved input array using nearest neighbor value selection.\n * @param {import(\"./geotiff.js\").TypedArray} valueArray The input array to resample\n * @param {number} inWidth The width of the input rasters\n * @param {number} inHeight The height of the input rasters\n * @param {number} outWidth The desired width of the output rasters\n * @param {number} outHeight The desired height of the output rasters\n * @param {number} samples The number of samples per pixel for pixel\n * interleaved data\n * @returns {import(\"./geotiff.js\").TypedArray} The resampled raster\n */\nexport function resampleNearestInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples) {\n const relX = inWidth / outWidth;\n const relY = inHeight / outHeight;\n const newArray = copyNewSize(valueArray, outWidth, outHeight, samples);\n for (let y = 0; y < outHeight; ++y) {\n const cy = Math.min(Math.round(relY * y), inHeight - 1);\n for (let x = 0; x < outWidth; ++x) {\n const cx = Math.min(Math.round(relX * x), inWidth - 1);\n for (let i = 0; i < samples; ++i) {\n const value = valueArray[(cy * inWidth * samples) + (cx * samples) + i];\n newArray[(y * outWidth * samples) + (x * samples) + i] = value;\n }\n }\n }\n return newArray;\n}\n/**\n * Resample the pixel interleaved input array using bilinear interpolation.\n * @param {import(\"./geotiff.js\").TypedArray} valueArray The input array to resample\n * @param {number} inWidth The width of the input rasters\n * @param {number} inHeight The height of the input rasters\n * @param {number} outWidth The desired width of the output rasters\n * @param {number} outHeight The desired height of the output rasters\n * @param {number} samples The number of samples per pixel for pixel\n * interleaved data\n * @returns {import(\"./geotiff.js\").TypedArray} The resampled raster\n */\nexport function resampleBilinearInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples) {\n const relX = inWidth / outWidth;\n const relY = inHeight / outHeight;\n const newArray = copyNewSize(valueArray, outWidth, outHeight, samples);\n for (let y = 0; y < outHeight; ++y) {\n const rawY = relY * y;\n const yl = Math.floor(rawY);\n const yh = Math.min(Math.ceil(rawY), (inHeight - 1));\n for (let x = 0; x < outWidth; ++x) {\n const rawX = relX * x;\n const tx = rawX % 1;\n const xl = Math.floor(rawX);\n const xh = Math.min(Math.ceil(rawX), (inWidth - 1));\n for (let i = 0; i < samples; ++i) {\n const ll = valueArray[(yl * inWidth * samples) + (xl * samples) + i];\n const hl = valueArray[(yl * inWidth * samples) + (xh * samples) + i];\n const lh = valueArray[(yh * inWidth * samples) + (xl * samples) + i];\n const hh = valueArray[(yh * inWidth * samples) + (xh * samples) + i];\n const value = lerp(lerp(ll, hl, tx), lerp(lh, hh, tx), rawY % 1);\n newArray[(y * outWidth * samples) + (x * samples) + i] = value;\n }\n }\n }\n return newArray;\n}\n/**\n * Resample the pixel interleaved input array using the selected resampling method.\n * @param {import(\"./geotiff.js\").TypedArray} valueArray The input array to resample\n * @param {number} inWidth The width of the input rasters\n * @param {number} inHeight The height of the input rasters\n * @param {number} outWidth The desired width of the output rasters\n * @param {number} outHeight The desired height of the output rasters\n * @param {number} samples The number of samples per pixel for pixel\n * interleaved data\n * @param {string} [method = 'nearest'] The desired resampling method\n * @returns {import(\"./geotiff.js\").TypedArray} The resampled rasters\n */\nexport function resampleInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples, method = 'nearest') {\n switch (method.toLowerCase()) {\n case 'nearest':\n return resampleNearestInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples);\n case 'bilinear':\n case 'linear':\n return resampleBilinearInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples);\n default:\n throw new Error(`Unsupported resampling method: '${method}'`);\n }\n}\n//# sourceMappingURL=resample.js.map","/** @module geotiffimage */\nimport { getFloat16 } from '@petamoriken/float16';\n// @ts-expect-error\nimport getAttribute from 'xml-utils/get-attribute'; // eslint-disable-line import/extensions\n// @ts-expect-error\nimport findTagsByName from 'xml-utils/find-tags-by-name'; // eslint-disable-line import/extensions\nimport { photometricInterpretations, ExtraSamplesValues } from './globals.js';\nimport { fromWhiteIsZero, fromBlackIsZero, fromPalette, fromCMYK, fromYCbCr, fromCIELab } from './rgb.js';\nimport { getDecoder, getDecoderParameters } from './compression/index.js';\nimport { resample, resampleInterleaved } from './resample.js';\n/** @import {DecoderWorker, TypedArray} from \"./geotiff.js\" */\n/** @import {ReadRasterResult} from \"./geotiff.js\" */\n/** @import {ReadRastersOptions} from \"./geotiff.js\" */\n/** @import {ReadRGBOptions} from \"./geotiff.js\" */\n/**\n * @param {Array<number>|TypedArray} array\n * @param {number} start\n * @param {number} end\n * @returns {number}\n */\nfunction sum(array, start, end) {\n let s = 0;\n for (let i = start; i < end; ++i) {\n s += array[i];\n }\n return s;\n}\n/**\n * @param {1|2|3} format\n * @param {number} bitsPerSample\n * @param {number|ArrayBufferLike} sizeOrData\n * @returns {TypedArray}\n */\nfunction arrayForType(format, bitsPerSample, sizeOrData) {\n let TypedArrayConstructor;\n switch (format) {\n case 1: // unsigned integer data\n if (bitsPerSample <= 8) {\n TypedArrayConstructor = Uint8Array;\n }\n else if (bitsPerSample <= 16) {\n TypedArrayConstructor = Uint16Array;\n }\n else if (bitsPerSample <= 32) {\n TypedArrayConstructor = Uint32Array;\n }\n break;\n case 2: // twos complement signed integer data\n if (bitsPerSample === 8) {\n TypedArrayConstructor = Int8Array;\n }\n else if (bitsPerSample === 16) {\n TypedArrayConstructor = Int16Array;\n }\n else if (bitsPerSample === 32) {\n TypedArrayConstructor = Int32Array;\n }\n break;\n case 3: // floating point data\n switch (bitsPerSample) {\n case 16:\n case 32:\n TypedArrayConstructor = Float32Array;\n break;\n case 64:\n TypedArrayConstructor = Float64Array;\n break;\n default:\n break;\n }\n break;\n default:\n break;\n }\n if (TypedArrayConstructor) {\n if (typeof sizeOrData === 'number') {\n return new TypedArrayConstructor(sizeOrData);\n }\n else if (sizeOrData instanceof ArrayBuffer) {\n return new TypedArrayConstructor(sizeOrData);\n }\n }\n throw Error('Unsupported data format/bitsPerSample');\n}\n/**\n * @param {1|2|3} format\n * @param {number} bitsPerSample\n * @returns {boolean}\n */\nfunction needsNormalization(format, bitsPerSample) {\n if ((format === 1 || format === 2) && bitsPerSample <= 32 && bitsPerSample % 8 === 0) {\n return false;\n }\n else if (format === 3 && (bitsPerSample === 16 || bitsPerSample === 32 || bitsPerSample === 64)) {\n return false;\n }\n return true;\n}\n/**\n * @param {ArrayBufferLike} inBuffer\n * @param {1|2|3} format\n * @param {1|2} planarConfiguration\n * @param {number} samplesPerPixel\n * @param {number} bitsPerSample\n * @param {number} tileWidth\n * @param {number} tileHeight\n * @returns {ArrayBufferLike}\n */\nfunction normalizeArray(inBuffer, format, planarConfiguration, samplesPerPixel, bitsPerSample, tileWidth, tileHeight) {\n // const inByteArray = new Uint8Array(inBuffer);\n const view = new DataView(inBuffer);\n const outSize = planarConfiguration === 2\n ? tileHeight * tileWidth\n : tileHeight * tileWidth * samplesPerPixel;\n const samplesToTransfer = planarConfiguration === 2\n ? 1 : samplesPerPixel;\n const outArray = arrayForType(format, bitsPerSample, outSize);\n // let pixel = 0;\n const bitMask = parseInt('1'.repeat(bitsPerSample), 2);\n if (format === 1) { // unsigned integer\n // translation of https://github.com/OSGeo/gdal/blob/master/gdal/frmts/gtiff/geotiff.cpp#L7337\n let pixelBitSkip;\n // let sampleBitOffset = 0;\n if (planarConfiguration === 1) {\n pixelBitSkip = samplesPerPixel * bitsPerSample;\n // sampleBitOffset = (samplesPerPixel - 1) * bitsPerSample;\n }\n else {\n pixelBitSkip = bitsPerSample;\n }\n // Bits per line rounds up to next byte boundary.\n let bitsPerLine = tileWidth * pixelBitSkip;\n if ((bitsPerLine & 7) !== 0) {\n bitsPerLine = (bitsPerLine + 7) & (~7);\n }\n for (let y = 0; y < tileHeight; ++y) {\n const lineBitOffset = y * bitsPerLine;\n for (let x = 0; x < tileWidth; ++x) {\n const pixelBitOffset = lineBitOffset + (x * samplesToTransfer * bitsPerSample);\n for (let i = 0; i < samplesToTransfer; ++i) {\n const bitOffset = pixelBitOffset + (i * bitsPerSample);\n const outIndex = (((y * tileWidth) + x) * samplesToTransfer) + i;\n const byteOffset = Math.floor(bitOffset / 8);\n const innerBitOffset = bitOffset % 8;\n if (innerBitOffset + bitsPerSample <= 8) {\n outArray[outIndex] = (view.getUint8(byteOffset) >> (8 - bitsPerSample) - innerBitOffset) & bitMask;\n }\n else if (innerBitOffset + bitsPerSample <= 16) {\n outArray[outIndex] = (view.getUint16(byteOffset) >> (16 - bitsPerSample) - innerBitOffset) & bitMask;\n }\n else if (innerBitOffset + bitsPerSample <= 24) {\n const raw = (view.getUint16(byteOffset) << 8) | (view.getUint8(byteOffset + 2));\n outArray[outIndex] = (raw >> (24 - bitsPerSample) - innerBitOffset) & bitMask;\n }\n else {\n outArray[outIndex] = (view.getUint32(byteOffset) >> (32 - bitsPerSample) - innerBitOffset) & bitMask;\n }\n // let outWord = 0;\n // for (let bit = 0; bit < bitsPerSample; ++bit) {\n // if (inByteArray[bitOffset >> 3]\n // & (0x80 >> (bitOffset & 7))) {\n // outWord |= (1 << (bitsPerSample - 1 - bit));\n // }\n // ++bitOffset;\n // }\n // outArray[outIndex] = outWord;\n // outArray[pixel] = outWord;\n // pixel += 1;\n }\n // bitOffset = bitOffset + pixelBitSkip - bitsPerSample;\n }\n }\n }\n else if (format === 3) { // floating point\n // Float16 is handled elsewhere\n // normalize 16/24 bit floats to 32 bit floats in the array\n // console.time();\n // if (bitsPerSample === 16) {\n // for (let byte = 0, outIndex = 0; byte < inBuffer.byteLength; byte += 2, ++outIndex) {\n // outArray[outIndex] = getFloat16(view, byte);\n // }\n // }\n // console.timeEnd()\n }\n return outArray.buffer;\n}\n/**\n * GeoTIFF sub-file image.\n */\nclass GeoTIFFImage {\n /**\n * @constructor\n * @param {import(\"./imagefiledirectory.js\").ImageFileDirectory} fileDirectory The parsed file directory\n * @param {Boolean} littleEndian Whether the file is encoded in little or big endian\n * @param {Boolean} cache Whether or not decoded tiles shall be cached\n * @param {import('./source/basesource.js').BaseSource} source The datasource to read from\n */\n constructor(fileDirectory, littleEndian, cache, source) {\n this.fileDirectory = fileDirectory;\n this.littleEndian = littleEndian;\n /** @type {Array<Promise<ArrayBufferLike>>|null} */\n this.tiles = cache ? [] : null;\n this.isTiled = !fileDirectory.hasTag('StripOffsets');\n const planarConfiguration = fileDirectory.getValue('PlanarConfiguration') ?? 1;\n if (planarConfiguration !== 1 && planarConfiguration !== 2) {\n throw new Error('Invalid planar configuration.');\n }\n /** @type {1 | 2} */\n this.planarConfiguration = planarConfiguration;\n this.source = source;\n }\n /**\n * Returns the associated parsed file directory.\n * @returns {import(\"./imagefiledirectory.js\").ImageFileDirectory} the parsed file directory\n */\n getFileDirectory() {\n return this.fileDirectory;\n }\n /**\n * Returns the associated parsed geo keys.\n * @returns {Partial<Record<import('./globals.js').GeoKeyName, *>>|null} the parsed geo keys\n */\n getGeoKeys() {\n return this.fileDirectory.parseGeoKeyDirectory();\n }\n /**\n * Returns the width of the image.\n * @returns {Number} the width of the image\n */\n getWidth() {\n return this.fileDirectory.getValue('ImageWidth') || 0;\n }\n /**\n * Returns the height of the image.\n * @returns {Number} the height of the image\n */\n getHeight() {\n return this.fileDirectory.getValue('ImageLength') || 0;\n }\n /**\n * Returns the number of samples per pixel.\n * @returns {number} the number of samples per pixel\n */\n getSamplesPerPixel() {\n return this.fileDirectory.getValue('SamplesPerPixel') ?? 1;\n }\n /**\n * Returns the width of each tile.\n * @returns {number} the width of each tile\n */\n getTileWidth() {\n return this.isTiled ? (this.fileDirectory.getValue('TileWidth') || 0) : this.getWidth();\n }\n /**\n * Returns the height of each tile.\n * @returns {number} the height of each tile\n */\n getTileHeight() {\n if (this.isTiled) {\n return this.fileDirectory.getValue('TileLength') || 0;\n }\n const rowsPerStrip = this.fileDirectory.hasTag('RowsPerStrip') && this.fileDirectory.getValue('RowsPerStrip');\n if (rowsPerStrip) {\n return Math.min(rowsPerStrip, this.getHeight());\n }\n return this.getHeight();\n }\n getBlockWidth() {\n return this.getTileWidth();\n }\n /**\n * @param {number} y\n * @returns {number}\n */\n getBlockHeight(y) {\n if (this.isTiled || (y + 1) * this.getTileHeight() <= this.getHeight()) {\n return this.getTileHeight();\n }\n else {\n return this.getHeight() - (y * this.getTileHeight());\n }\n }\n /**\n * Calculates the number of bytes for each pixel across all samples. Only full\n * bytes are supported, an exception is thrown when this is not the case.\n * @returns {Number} the bytes per pixel\n */\n getBytesPerPixel() {\n let bytes = 0;\n // this is a short list, so we assume this is already loaded\n const bitsPerSample = this.fileDirectory.getValue('BitsPerSample') || [];\n for (let i = 0; i < bitsPerSample.length; ++i) {\n bytes += this.getSampleByteSize(i);\n }\n return bytes;\n }\n /**\n * @param {number} i\n * @returns {number}\n */\n getSampleByteSize(i) {\n const bitsPerSample = this.fileDirectory.getValue('BitsPerSample') || [];\n if (i >= bitsPerSample.length) {\n throw new RangeError(`Sample index ${i} is out of range.`);\n }\n return Math.ceil(bitsPerSample[i] / 8);\n }\n /**\n * @param {number} sampleIndex\n * @returns {(this: DataView, byteOffset: number, littleEndian: boolean) => number}\n */\n getReaderForSample(sampleIndex) {\n const sampleFormat = this.fileDirectory.getValue('SampleFormat');\n const format = sampleFormat\n ? sampleFormat[sampleIndex] : 1;\n const bitsPerSample = (this.fileDirectory.getValue('BitsPerSample') || [])[sampleIndex];\n switch (format) {\n case 1: // unsigned integer data\n if (bitsPerSample <= 8) {\n return DataView.prototype.getUint8;\n }\n else if (bitsPerSample <= 16) {\n return DataView.prototype.getUint16;\n }\n else if (bitsPerSample <= 32) {\n return DataView.prototype.getUint32;\n }\n break;\n case 2: // twos complement signed integer data\n if (bitsPerSample <= 8) {\n return DataView.prototype.getInt8;\n }\n else if (bitsPerSample <= 16) {\n return DataView.prototype.getInt16;\n }\n else if (bitsPerSample <= 32) {\n return DataView.prototype.getInt32;\n }\n break;\n case 3:\n switch (bitsPerSample) {\n case 16:\n return function (offset, littleEndian) {\n return getFloat16(this, offset, littleEndian);\n };\n case 32:\n return DataView.prototype.getFloat32;\n case 64:\n return DataView.prototype.getFloat64;\n default:\n break;\n }\n break;\n default:\n break;\n }\n throw Error('Unsupported data format/bitsPerSample');\n }\n getSampleFormat(sampleIndex = 0) {\n const sampleFormat = this.fileDirectory.getValue('SampleFormat');\n return sampleFormat ? sampleFormat[sampleIndex] : 1;\n }\n getBitsPerSample(sampleIndex = 0) {\n const bitsPerSample = this.fileDirectory.getValue('BitsPerSample');\n return bitsPerSample ? bitsPerSample[sampleIndex] : 0;\n }\n /**\n * @param {number} sampleIndex\n * @param {number|ArrayBufferLike} sizeOrData\n * @returns {TypedArray}\n */\n getArrayForSample(sampleIndex, sizeOrData) {\n const format = /** @type {1|2|3} */ (this.getSampleFormat(sampleIndex));\n const bitsPerSample = this.getBitsPerSample(sampleIndex);\n return arrayForType(format, bitsPerSample, sizeOrData);\n }\n /**\n * Returns the decoded strip or tile.\n * @param {Number} x the strip or tile x-offset\n * @param {Number} y the tile y-offset (0 for stripped images)\n * @param {Number} sample the sample to get for separated samples\n * @param {DecoderWorker|import(\"./geotiff.js\").BaseDecoder} poolOrDecoder the decoder or decoder pool\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise.<{x: number, y: number, sample: number, data: ArrayBufferLike}>} the decoded strip or tile\n */\n async getTileOrStrip(x, y, sample, poolOrDecoder, signal) {\n const numTilesPerRow = Math.ceil(this.getWidth() / this.getTileWidth());\n const numTilesPerCol = Math.ceil(this.getHeight() / this.getTileHeight());\n let index;\n const { tiles } = this;\n if (this.planarConfiguration === 1) {\n index = (y * numTilesPerRow) + x;\n }\n else if (this.planarConfiguration === 2) {\n index = (sample * numTilesPerRow * numTilesPerCol) + (y * numTilesPerRow) + x;\n }\n if (index === undefined) {\n throw new Error('Could not determine tile or strip index.');\n }\n let offset;\n let byteCount;\n if (this.isTiled) {\n offset = Number(await this.fileDirectory.loadValueIndexed('TileOffsets', index));\n byteCount = Number(await this.fileDirectory.loadValueIndexed('TileByteCounts', index));\n }\n else {\n offset = Number(await this.fileDirectory.loadValueIndexed('StripOffsets', index));\n byteCount = Number(await this.fileDirectory.loadValueIndexed('StripByteCounts', index));\n }\n if (byteCount === 0) {\n const nPixels = this.getBlockHeight(y) * this.getTileWidth();\n const bytesPerPixel = (this.planarConfiguration === 2) ? this.getSampleByteSize(sample) : this.getBytesPerPixel();\n const data = new ArrayBuffer(nPixels * bytesPerPixel);\n const view = this.getArrayForSample(sample, data);\n view.fill(this.getGDALNoData() || 0);\n return { x, y, sample, data };\n }\n const slice = (await this.source.fetch([{ offset, length: byteCount }], signal))[0];\n let request;\n if (tiles === null || !tiles[index]) {\n // resolve each request by potentially applying array normalization\n request = (async () => {\n let data = await poolOrDecoder.decode(slice);\n const sampleFormat = /** @type {1|2|3} */ (this.getSampleFormat());\n const bitsPerSample = this.getBitsPerSample();\n if (needsNormalization(sampleFormat, bitsPerSample)) {\n data = normalizeArray(data, sampleFormat, this.planarConfiguration, this.getSamplesPerPixel(), bitsPerSample, this.getTileWidth(), this.getBlockHeight(y));\n }\n return data;\n })();\n // set the cache\n if (tiles !== null) {\n tiles[index] = request;\n }\n }\n else {\n // get from the cache\n request = tiles[index];\n }\n // cache the tile request\n return { x, y, sample, data: await request };\n }\n /**\n * Internal read function.\n * @private\n * @param {Array<number>} imageWindow The image window in pixel coordinates\n * @param {Array<number>} samples The selected samples (0-based indices)\n * @param {TypedArray|TypedArray[]} valueArrays The array(s) to write into\n * @param {boolean|undefined} interleave Whether or not to write in an interleaved manner\n * @param {DecoderWorker|import(\"./geotiff.js\").BaseDecoder} poolOrDecoder the decoder or decoder pool\n * @param {number} [width] the width of window to be read into\n * @param {number} [height] the height of window to be read into\n * @param {string} [resampleMethod] the resampling method to be used when interpolating\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<ReadRasterResult>}\n */\n async _readRaster(imageWindow, samples, valueArrays, interleave, poolOrDecoder, width, height, resampleMethod, signal) {\n const tileWidth = this.getTileWidth();\n const tileHeight = this.getTileHeight();\n const imageWidth = this.getWidth();\n const imageHeight = this.getHeight();\n const minXTile = Math.max(Math.floor(imageWindow[0] / tileWidth), 0);\n const maxXTile = Math.min(Math.ceil(imageWindow[2] / tileWidth), Math.ceil(imageWidth / tileWidth));\n const minYTile = Math.max(Math.floor(imageWindow[1] / tileHeight), 0);\n const maxYTile = Math.min(Math.ceil(imageWindow[3] / tileHeight), Math.ceil(imageHeight / tileHeight));\n const windowWidth = imageWindow[2] - imageWindow[0];\n let bytesPerPixel = this.getBytesPerPixel();\n /** @type {Array<number>} */\n const srcSampleOffsets = [];\n /** @type {Array<(this: DataView, byteOffset: number, littleEndian: boolean) => number>} */\n const sampleReaders = [];\n for (let i = 0; i < samples.length; ++i) {\n if (this.planarConfiguration === 1) {\n const bitsPerSample = await this.fileDirectory.loadValue('BitsPerSample');\n if (typeof bitsPerSample !== 'object') {\n throw new Error('Expected BitsPerSample to be an array or typed array.');\n }\n srcSampleOffsets.push(sum(bitsPerSample, 0, samples[i]) / 8);\n }\n else {\n srcSampleOffsets.push(0);\n }\n sampleReaders.push(this.getReaderForSample(samples[i]));\n }\n const promises = [];\n const { littleEndian } = this;\n for (let yTile = minYTile; yTile < maxYTile; ++yTile) {\n for (let xTile = minXTile; xTile < maxXTile; ++xTile) {\n let getPromise;\n if (this.planarConfiguration === 1) {\n getPromise = this.getTileOrStrip(xTile, yTile, 0, poolOrDecoder, signal);\n }\n for (let sampleIndex = 0; sampleIndex < samples.length; ++sampleIndex) {\n const si = sampleIndex;\n const sample = samples[sampleIndex];\n if (this.planarConfiguration === 2) {\n bytesPerPixel = this.getSampleByteSize(sample);\n getPromise = this.getTileOrStrip(xTile, yTile, sample, poolOrDecoder, signal);\n }\n if (!getPromise) {\n throw new Error('Could not get tile or strip data.');\n }\n const promise = getPromise.then((tile) => {\n const buffer = tile.data;\n const dataView = new DataView(buffer);\n const blockHeight = this.getBlockHeight(tile.y);\n const firstLine = tile.y * tileHeight;\n const firstCol = tile.x * tileWidth;\n const lastLine = firstLine + blockHeight;\n const lastCol = (tile.x + 1) * tileWidth;\n const reader = sampleReaders[si];\n const ymax = Math.min(blockHeight, blockHeight - (lastLine - imageWindow[3]), imageHeight - firstLine);\n const xmax = Math.min(tileWidth, tileWidth - (lastCol - imageWindow[2]), imageWidth - firstCol);\n for (let y = Math.max(0, imageWindow[1] - firstLine); y < ymax; ++y) {\n for (let x = Math.max(0, imageWindow[0] - firstCol); x < xmax; ++x) {\n const pixelOffset = ((y * tileWidth) + x) * bytesPerPixel;\n const value = reader.call(dataView, pixelOffset + srcSampleOffsets[si], littleEndian);\n let windowCoordinate;\n if (interleave) {\n windowCoordinate = ((y + firstLine - imageWindow[1]) * windowWidth * samples.length)\n + ((x + firstCol - imageWindow[0]) * samples.length)\n + si;\n valueArrays[windowCoordinate] = value;\n }\n else {\n windowCoordinate = ((y + firstLine - imageWindow[1]) * windowWidth) + x + firstCol - imageWindow[0];\n /** @type {TypedArray} */ (valueArrays[si])[windowCoordinate] = value;\n }\n }\n }\n });\n promises.push(promise);\n }\n }\n }\n await Promise.all(promises);\n if ((width && (imageWindow[2] - imageWindow[0]) !== width)\n || (height && (imageWindow[3] - imageWindow[1]) !== height)) {\n let resampled;\n if (interleave) {\n resampled = resampleInterleaved(\n /** @type {TypedArray} */ (valueArrays), imageWindow[2] - imageWindow[0], imageWindow[3] - imageWindow[1], \n /** @type {number} */ (width), /** @type {number} */ (height), samples.length, resampleMethod);\n }\n else {\n resampled = resample(\n /** @type {TypedArray[]} */ (valueArrays), imageWindow[2] - imageWindow[0], imageWindow[3] - imageWindow[1], \n /** @type {number} */ (width), /** @type {number} */ (height), resampleMethod);\n }\n const resampledWithDimensions = /** @type {ReadRasterResult} */ (resampled);\n resampledWithDimensions.width = width ?? imageWindow[2] - imageWindow[0];\n resampledWithDimensions.height = height ?? imageWindow[3] - imageWindow[1];\n return resampledWithDimensions;\n }\n const valueArraysWithDimensions = /** @type {ReadRasterResult} */ (valueArrays);\n valueArraysWithDimensions.width = width || imageWindow[2] - imageWindow[0];\n valueArraysWithDimensions.height = height || imageWindow[3] - imageWindow[1];\n return valueArraysWithDimensions;\n }\n /**\n * @overload\n * @param {ReadRastersOptions & {interleave: true}} options optional parameters\n * @returns {Promise<import(\"./geotiff.js\").TypedArrayWithDimensions>} the decoded arrays as a promise\n */\n /**\n * @overload\n * @param {ReadRastersOptions & {interleave: false}} options optional parameters\n * @returns {Promise<import(\"./geotiff.js\").TypedArrayArrayWithDimensions>} the decoded arrays as a promise\n */\n /**\n * @overload\n * @param {ReadRastersOptions & {interleave: boolean}} options optional parameters\n * @returns {Promise<ReadRasterResult>} the decoded arrays as a promise\n */\n /**\n * @overload\n * @param {ReadRastersOptions} [options={}] optional parameters\n * @returns {Promise<import(\"./geotiff.js\").TypedArrayArrayWithDimensions>} the decoded arrays as a promise\n */\n /**\n * Reads raster data from the image. This function reads all selected samples\n * into separate arrays of the correct type for that sample or into a single\n * combined array when `interleave` is set. When provided, only a subset\n * of the raster is read for each sample.\n *\n * @param {ReadRastersOptions} [options={}] optional parameters\n * @returns {Promise<ReadRasterResult>} the decoded arrays as a promise\n */\n async readRasters(options = {}) {\n const { window: wnd, samples = [], pool = null, width, height, resampleMethod, fillValue, signal, } = options;\n const interleave = 'interleave' in options && options.interleave;\n const imageWindow = wnd || [0, 0, this.getWidth(), this.getHeight()];\n // check parameters\n if (imageWindow[0] > imageWindow[2] || imageWindow[1] > imageWindow[3]) {\n throw new Error('Invalid subsets');\n }\n const imageWindowWidth = imageWindow[2] - imageWindow[0];\n const imageWindowHeight = imageWindow[3] - imageWindow[1];\n const numPixels = imageWindowWidth * imageWindowHeight;\n const samplesPerPixel = this.getSamplesPerPixel();\n if (!samples || !samples.length) {\n for (let i = 0; i < samplesPerPixel; ++i) {\n samples.push(i);\n }\n }\n else {\n for (let i = 0; i < samples.length; ++i) {\n if (samples[i] >= samplesPerPixel) {\n return Promise.reject(new RangeError(`Invalid sample index '${samples[i]}'.`));\n }\n }\n }\n /** @type {TypedArray|TypedArray[]} */\n let valueArrays;\n if (interleave) {\n const { fileDirectory } = this;\n const sampleFormat = fileDirectory.getValue('SampleFormat');\n const format = sampleFormat\n ? Math.max.apply(null, Array.from(sampleFormat)) : 1;\n if (format !== 1 && format !== 2 && format !== 3) {\n throw new Error('Unsupported sample format for interleaved data. Must be 1, 2, or 3.');\n }\n const bitsPerSample_ = fileDirectory.getValue('BitsPerSample');\n const bitsPerSample = bitsPerSample_\n ? Math.max.apply(null, Array.from(bitsPerSample_)) : 8;\n valueArrays = arrayForType(format, bitsPerSample, numPixels * samples.length);\n if (fillValue) {\n if (Array.isArray(fillValue)) {\n throw new Error('When reading interleaved data, fillValue must be a single number.');\n }\n valueArrays.fill(fillValue);\n }\n }\n else {\n valueArrays = [];\n for (let i = 0; i < samples.length; ++i) {\n const valueArray = this.getArrayForSample(samples[i], numPixels);\n if (Array.isArray(fillValue) && i < fillValue.length) {\n valueArray.fill(fillValue[i]);\n }\n else if (fillValue && !Array.isArray(fillValue)) {\n valueArray.fill(fillValue);\n }\n valueArrays.push(valueArray);\n }\n }\n const compression = this.fileDirectory.getValue('Compression') || 1;\n const decoderParameters = await getDecoderParameters(compression, this.fileDirectory);\n const poolOrDecoder = pool\n ? pool.bindParameters(compression, decoderParameters)\n : await getDecoder(compression, decoderParameters);\n const result = await this._readRaster(imageWindow, samples, valueArrays, interleave, poolOrDecoder, width, height, resampleMethod, signal);\n return result;\n }\n /**\n * @overload\n * @param {ReadRGBOptions & {interleave: true}} options optional parameters\n * @returns {Promise<import(\"./geotiff.js\").TypedArrayWithDimensions>} the RGB array as a Promise\n */\n /**\n * @overload\n * @param {ReadRGBOptions & {interleave: false}} options optional parameters\n * @returns {Promise<import(\"./geotiff.js\").TypedArrayArrayWithDimensions>} the RGB array as a Promise\n */\n /**\n * @overload\n * @param {ReadRGBOptions & {interleave: boolean}} options optional parameters\n * @returns {Promise<ReadRasterResult>} the RGB array as a Promise\n */\n /**\n * @overload\n * @param {ReadRGBOptions} [options={}] optional parameters\n * @returns {Promise<import(\"./geotiff.js\").TypedArrayArrayWithDimensions>} the RGB array as a Promise\n */\n /**\n * Reads raster data from the image as RGB.\n * Colorspaces other than RGB will be transformed to RGB, color maps expanded.\n * When no other method is applicable, the first sample is used to produce a\n * grayscale image.\n * When provided, only a subset of the raster is read for each sample.\n *\n * @param {ReadRGBOptions} [options] optional parameters\n * @returns {Promise<ReadRasterResult>} the RGB array as a Promise\n */\n async readRGB(options = {}) {\n const { window, pool = null, width, height, resampleMethod, enableAlpha = false, signal } = options;\n const interleave = ('interleave' in options && options.interleave) ?? false;\n const imageWindow = window || [0, 0, this.getWidth(), this.getHeight()];\n // check parameters\n if (imageWindow[0] > imageWindow[2] || imageWindow[1] > imageWindow[3]) {\n throw new Error('Invalid subsets');\n }\n const pi = this.fileDirectory.getValue('PhotometricInterpretation');\n if (pi === photometricInterpretations.RGB) {\n let s = [0, 1, 2];\n const extraSamples = this.fileDirectory.getValue('ExtraSamples');\n if (extraSamples && extraSamples[0] !== ExtraSamplesValues.Unspecified && enableAlpha) {\n s = [];\n const bitsPerSample = this.fileDirectory.getValue('BitsPerSample') || [];\n for (let i = 0; i < bitsPerSample.length; i += 1) {\n s.push(i);\n }\n }\n return this.readRasters({\n window,\n interleave,\n samples: s,\n pool,\n width,\n height,\n resampleMethod,\n signal,\n });\n }\n let samples;\n switch (pi) {\n case photometricInterpretations.WhiteIsZero:\n case photometricInterpretations.BlackIsZero:\n case photometricInterpretations.Palette:\n samples = [0];\n break;\n case photometricInterpretations.CMYK:\n samples = [0, 1, 2, 3];\n break;\n case photometricInterpretations.YCbCr:\n case photometricInterpretations.CIELab:\n samples = [0, 1, 2];\n break;\n default:\n throw new Error('Invalid or unsupported photometric interpretation.');\n }\n const subOptions = {\n window: imageWindow,\n /** @type {true} */\n interleave: true,\n samples,\n pool,\n width,\n height,\n resampleMethod,\n signal,\n };\n const { fileDirectory } = this;\n const raster = await this.readRasters(subOptions);\n const max = 2 ** this.getBitsPerSample(0);\n let data;\n switch (pi) {\n case photometricInterpretations.WhiteIsZero:\n data = fromWhiteIsZero(raster, max);\n break;\n case photometricInterpretations.BlackIsZero:\n data = fromBlackIsZero(raster, max);\n break;\n case photometricInterpretations.Palette:\n data = fromPalette(raster, /** @type {Uint16Array} */ (await fileDirectory.loadValue('ColorMap')));\n break;\n case photometricInterpretations.CMYK:\n data = fromCMYK(raster);\n break;\n case photometricInterpretations.YCbCr:\n data = fromYCbCr(raster);\n break;\n case photometricInterpretations.CIELab:\n data = fromCIELab(raster);\n break;\n default:\n throw new Error('Unsupported photometric interpretation.');\n }\n // if non-interleaved data is requested, we must split the channels\n // into their respective arrays\n if (!interleave) {\n const red = new Uint8Array(data.length / 3);\n const green = new Uint8Array(data.length / 3);\n const blue = new Uint8Array(data.length / 3);\n for (let i = 0, j = 0; i < data.length; i += 3, ++j) {\n red[j] = data[i];\n green[j] = data[i + 1];\n blue[j] = data[i + 2];\n }\n data = [red, green, blue];\n }\n const dataWithDimensions = /** @type {import(\"./geotiff.js\").ReadRasterResult} */ (data);\n dataWithDimensions.width = raster.width;\n dataWithDimensions.height = raster.height;\n return dataWithDimensions;\n }\n /**\n * Returns an array of tiepoints.\n * @returns {Promise<Array<{i: number, j: number, k: number, x: number, y: number, z: number}>>} the tiepoints\n */\n async getTiePoints() {\n if (!this.fileDirectory.hasTag('ModelTiepoint')) {\n return [];\n }\n const modelTiePoint = await this.fileDirectory.loadValue('ModelTiepoint');\n if (typeof modelTiePoint !== 'object') {\n throw new Error('Expected ModelTiepoint to be an array or typed array.');\n }\n const tiePoints = [];\n for (let i = 0; i < modelTiePoint.length; i += 6) {\n tiePoints.push({\n i: modelTiePoint[i],\n j: modelTiePoint[i + 1],\n k: modelTiePoint[i + 2],\n x: modelTiePoint[i + 3],\n y: modelTiePoint[i + 4],\n z: modelTiePoint[i + 5],\n });\n }\n return tiePoints;\n }\n /**\n * Returns the parsed GDAL metadata items.\n *\n * If sample is passed to null, dataset-level metadata will be returned.\n * Otherwise only metadata specific to the provided sample will be returned.\n *\n * @param {number|null} [sample=null] The sample index.\n * @returns {Promise<Record<string, unknown>|null>} The GDAL metadata items\n */\n async getGDALMetadata(sample = null) {\n /** @type {Record<string, unknown>} */\n const metadata = {};\n if (!this.fileDirectory.hasTag('GDAL_METADATA')) {\n return null;\n }\n const string = await this.fileDirectory.loadValue('GDAL_METADATA');\n /** @type {Array<{inner: unknown}>} */\n let items = findTagsByName(string, 'Item');\n if (sample === null) {\n items = items.filter((item) => getAttribute(item, 'sample') === undefined);\n }\n else {\n items = items.filter((item) => Number(getAttribute(item, 'sample')) === sample);\n }\n for (let i = 0; i < items.length; ++i) {\n const item = items[i];\n metadata[getAttribute(item, 'name')] = item.inner;\n }\n return metadata;\n }\n /**\n * Returns the GDAL nodata value\n * @returns {number|null}\n */\n getGDALNoData() {\n const string = this.fileDirectory.hasTag('GDAL_NODATA') && this.fileDirectory.getValue('GDAL_NODATA');\n if (!string) {\n return null;\n }\n return Number(string.substring(0, string.length - 1));\n }\n /**\n * Returns the image origin as a XYZ-vector. When the image has no affine\n * transformation, then an exception is thrown.\n * @returns {Array<number>} The origin as a vector\n */\n getOrigin() {\n const tiePoints = this.fileDirectory.getValue('ModelTiepoint');\n const modelTransformation = this.fileDirectory.getValue('ModelTransformation');\n if (tiePoints && tiePoints.length === 6) {\n return [\n tiePoints[3],\n tiePoints[4],\n tiePoints[5],\n ];\n }\n if (modelTransformation) {\n return [\n modelTransformation[3],\n modelTransformation[7],\n modelTransformation[11],\n ];\n }\n throw new Error('The image does not have an affine transformation.');\n }\n /**\n * Returns the image resolution as a XYZ-vector. When the image has no affine\n * transformation, then an exception is thrown.\n * @param {GeoTIFFImage|null} [referenceImage=null] A reference image to calculate the resolution from\n * in cases when the current image does not have the\n * required tags on its own.\n * @returns {Array<number>} The resolution as a vector\n */\n getResolution(referenceImage = null) {\n const modelPixelScale = this.fileDirectory.getValue('ModelPixelScale');\n const modelTransformation = this.fileDirectory.getValue('ModelTransformation');\n if (modelPixelScale) {\n return [\n modelPixelScale[0],\n -modelPixelScale[1],\n modelPixelScale[2],\n ];\n }\n if (modelTransformation) {\n if (modelTransformation[1] === 0 && modelTransformation[4] === 0) {\n return [\n modelTransformation[0],\n -modelTransformation[5],\n modelTransformation[10],\n ];\n }\n return [\n Math.sqrt((modelTransformation[0] * modelTransformation[0])\n + (modelTransformation[4] * modelTransformation[4])),\n -Math.sqrt((modelTransformation[1] * modelTransformation[1])\n + (modelTransformation[5] * modelTransformation[5])),\n modelTransformation[10]\n ];\n }\n if (referenceImage) {\n const [refResX, refResY, refResZ] = referenceImage.getResolution();\n return [\n refResX * referenceImage.getWidth() / this.getWidth(),\n refResY * referenceImage.getHeight() / this.getHeight(),\n refResZ * referenceImage.getWidth() / this.getWidth(),\n ];\n }\n throw new Error('The image does not have an affine transformation.');\n }\n /**\n * Returns whether or not the pixels of the image depict an area (or point).\n * @returns {Boolean} Whether the pixels are a point\n */\n pixelIsArea() {\n return this.getGeoKeys()?.GTRasterTypeGeoKey === 1;\n }\n /**\n * Returns the image bounding box as an array of 4 values: min-x, min-y,\n * max-x and max-y. When the image has no affine transformation, then an\n * exception is thrown.\n * @param {boolean} [tilegrid=false] If true return extent for a tilegrid\n * without adjustment for ModelTransformation.\n * @returns {Array<number>} The bounding box\n */\n getBoundingBox(tilegrid = false) {\n const height = this.getHeight();\n const width = this.getWidth();\n const modelTransformation = this.fileDirectory.getValue('ModelTransformation');\n if (modelTransformation && !tilegrid) {\n const [a, b, , d, e, f, , h] = modelTransformation;\n const corners = [\n [0, 0],\n [0, height],\n [width, 0],\n [width, height],\n ];\n const projected = corners.map(([I, J]) => [\n d + (a * I) + (b * J),\n h + (e * I) + (f * J),\n ]);\n const xs = projected.map((pt) => pt[0]);\n const ys = projected.map((pt) => pt[1]);\n return [\n Math.min(...xs),\n Math.min(...ys),\n Math.max(...xs),\n Math.max(...ys),\n ];\n }\n else {\n const origin = this.getOrigin();\n const resolution = this.getResolution();\n const x1 = origin[0];\n const y1 = origin[1];\n const x2 = x1 + (resolution[0] * width);\n const y2 = y1 + (resolution[1] * height);\n return [\n Math.min(x1, x2),\n Math.min(y1, y2),\n Math.max(x1, x2),\n Math.max(y1, y2),\n ];\n }\n }\n}\nexport default GeoTIFFImage;\n//# sourceMappingURL=geotiffimage.js.map","import { getFloat16 } from '@petamoriken/float16';\nexport default class DataView64 {\n /**\n * @param {ArrayBufferLike} arrayBuffer\n */\n constructor(arrayBuffer) {\n this._dataView = new DataView(arrayBuffer);\n }\n get buffer() {\n return this._dataView.buffer;\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getUint64(offset, littleEndian) {\n const left = this.getUint32(offset, littleEndian);\n const right = this.getUint32(offset + 4, littleEndian);\n let combined;\n if (littleEndian) {\n combined = left + ((2 ** 32) * right);\n if (!Number.isSafeInteger(combined)) {\n throw new Error(`${combined} exceeds MAX_SAFE_INTEGER. `\n + 'Precision may be lost. Please report if you get this message to https://github.com/geotiffjs/geotiff.js/issues');\n }\n return combined;\n }\n combined = ((2 ** 32) * left) + right;\n if (!Number.isSafeInteger(combined)) {\n throw new Error(`${combined} exceeds MAX_SAFE_INTEGER. `\n + 'Precision may be lost. Please report if you get this message to https://github.com/geotiffjs/geotiff.js/issues');\n }\n return combined;\n }\n /**\n * Adapted from https://stackoverflow.com/a/55338384/8060591\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getInt64(offset, littleEndian) {\n let value = 0;\n const isNegative = (this._dataView.getUint8(offset + (littleEndian ? 7 : 0)) & 0x80) > 0;\n let carrying = true;\n for (let i = 0; i < 8; i++) {\n let byte = this._dataView.getUint8(offset + (littleEndian ? i : 7 - i));\n if (isNegative) {\n if (carrying) {\n if (byte !== 0x00) {\n byte = ~(byte - 1) & 0xff;\n carrying = false;\n }\n }\n else {\n byte = ~byte & 0xff;\n }\n }\n value += byte * (256 ** i);\n }\n if (isNegative) {\n value = -value;\n }\n return value;\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n getUint8(offset) {\n return this._dataView.getUint8(offset);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n getInt8(offset) {\n return this._dataView.getInt8(offset);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getUint16(offset, littleEndian) {\n return this._dataView.getUint16(offset, littleEndian);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getInt16(offset, littleEndian) {\n return this._dataView.getInt16(offset, littleEndian);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getUint32(offset, littleEndian) {\n return this._dataView.getUint32(offset, littleEndian);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getInt32(offset, littleEndian) {\n return this._dataView.getInt32(offset, littleEndian);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getFloat16(offset, littleEndian) {\n return getFloat16(this._dataView, offset, littleEndian);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getFloat32(offset, littleEndian) {\n return this._dataView.getFloat32(offset, littleEndian);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getFloat64(offset, littleEndian) {\n return this._dataView.getFloat64(offset, littleEndian);\n }\n}\n//# sourceMappingURL=dataview64.js.map","export default class DataSlice {\n /**\n * @param {ArrayBufferLike} arrayBuffer\n * @param {number} sliceOffset\n * @param {boolean} littleEndian\n * @param {boolean} bigTiff\n */\n constructor(arrayBuffer, sliceOffset, littleEndian, bigTiff) {\n this._dataView = new DataView(arrayBuffer);\n this._sliceOffset = sliceOffset;\n this._littleEndian = littleEndian;\n this._bigTiff = bigTiff;\n }\n get sliceOffset() {\n return this._sliceOffset;\n }\n get sliceTop() {\n return this._sliceOffset + this.buffer.byteLength;\n }\n get littleEndian() {\n return this._littleEndian;\n }\n get bigTiff() {\n return this._bigTiff;\n }\n get buffer() {\n return this._dataView.buffer;\n }\n /**\n * @param {number} offset\n * @param {number} length\n * @returns {boolean}\n */\n covers(offset, length) {\n return this.sliceOffset <= offset && this.sliceTop >= offset + length;\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readUint8(offset) {\n return this._dataView.getUint8(offset - this._sliceOffset);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readInt8(offset) {\n return this._dataView.getInt8(offset - this._sliceOffset);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readUint16(offset) {\n return this._dataView.getUint16(offset - this._sliceOffset, this._littleEndian);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readInt16(offset) {\n return this._dataView.getInt16(offset - this._sliceOffset, this._littleEndian);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readUint32(offset) {\n return this._dataView.getUint32(offset - this._sliceOffset, this._littleEndian);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readInt32(offset) {\n return this._dataView.getInt32(offset - this._sliceOffset, this._littleEndian);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readFloat32(offset) {\n return this._dataView.getFloat32(offset - this._sliceOffset, this._littleEndian);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readFloat64(offset) {\n return this._dataView.getFloat64(offset - this._sliceOffset, this._littleEndian);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readUint64(offset) {\n const left = this.readUint32(offset);\n const right = this.readUint32(offset + 4);\n let combined;\n if (this._littleEndian) {\n combined = left + ((2 ** 32) * right);\n if (!Number.isSafeInteger(combined)) {\n throw new Error(`${combined} exceeds MAX_SAFE_INTEGER. `\n + 'Precision may be lost. Please report if you get this message to https://github.com/geotiffjs/geotiff.js/issues');\n }\n return combined;\n }\n combined = ((2 ** 32) * left) + right;\n if (!Number.isSafeInteger(combined)) {\n throw new Error(`${combined} exceeds MAX_SAFE_INTEGER. `\n + 'Precision may be lost. Please report if you get this message to https://github.com/geotiffjs/geotiff.js/issues');\n }\n return combined;\n }\n /**\n * Adapted from https://stackoverflow.com/a/55338384/8060591\n * @param {number} offset\n * @returns {number}\n */\n readInt64(offset) {\n let value = 0;\n const isNegative = (this._dataView.getUint8(offset + (this._littleEndian ? 7 : 0)) & 0x80)\n > 0;\n let carrying = true;\n for (let i = 0; i < 8; i++) {\n let byte = this._dataView.getUint8(offset + (this._littleEndian ? i : 7 - i));\n if (isNegative) {\n if (carrying) {\n if (byte !== 0x00) {\n byte = ~(byte - 1) & 0xff;\n carrying = false;\n }\n }\n else {\n byte = ~byte & 0xff;\n }\n }\n value += byte * (256 ** i);\n }\n if (isNegative) {\n value = -value;\n }\n return value;\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readOffset(offset) {\n if (this._bigTiff) {\n return this.readUint64(offset);\n }\n return this.readUint32(offset);\n }\n}\n//# sourceMappingURL=dataslice.js.map","/**\n * @typedef {Object} Slice\n * @property {number} offset\n * @property {number} length\n */\n/** @typedef {Slice & {data: ArrayBufferLike}} SliceWithData */\nexport class BaseSource {\n /**\n * @param {Array<Slice>} slices\n * @param {AbortSignal} [signal]\n * @returns {Promise<ArrayBufferLike[]>}\n */\n async fetch(slices, signal) {\n return Promise.all(slices.map(async (slice) => (await this.fetchSlice(slice, signal)).data));\n }\n /**\n * @param {Slice} slice\n * @param {AbortSignal} [_signal]\n * @returns {Promise<SliceWithData>}\n */\n async fetchSlice(slice, _signal) {\n throw new Error(`fetching of slice ${slice} not possible, not implemented`);\n }\n /**\n * Returns the filesize if already determined and null otherwise\n * @returns {number|null}\n */\n get fileSize() {\n return null;\n }\n async close() {\n // no-op by default\n }\n}\n//# sourceMappingURL=basesource.js.map","export function assign(target, source) {\n for (const key in source) {\n if (source.hasOwnProperty(key)) {\n target[key] = source[key];\n }\n }\n return target;\n}\nexport function chunk(iterable, length) {\n const results = [];\n const lengthOfIterable = iterable.length;\n for (let i = 0; i < lengthOfIterable; i += length) {\n const chunked = [];\n for (let ci = i; ci < i + length; ci++) {\n chunked.push(iterable[ci]);\n }\n results.push(chunked);\n }\n return results;\n}\nexport function endsWith(string, expectedEnding) {\n if (string.length < expectedEnding.length) {\n return false;\n }\n const actualEnding = string.substr(string.length - expectedEnding.length);\n return actualEnding === expectedEnding;\n}\nexport function forEach(iterable, func) {\n const { length } = iterable;\n for (let i = 0; i < length; i++) {\n func(iterable[i], i);\n }\n}\nexport function invert(oldObj) {\n const newObj = {};\n for (const key in oldObj) {\n if (oldObj.hasOwnProperty(key)) {\n const value = oldObj[key];\n newObj[value] = key;\n }\n }\n return newObj;\n}\nexport function range(n) {\n const results = [];\n for (let i = 0; i < n; i++) {\n results.push(i);\n }\n return results;\n}\nexport function times(numTimes, func) {\n const results = [];\n for (let i = 0; i < numTimes; i++) {\n results.push(func(i));\n }\n return results;\n}\nexport function toArray(iterable) {\n const results = [];\n const { length } = iterable;\n for (let i = 0; i < length; i++) {\n results.push(iterable[i]);\n }\n return results;\n}\nexport function toArrayRecursively(input) {\n if (isArrayLike(input)) {\n return toArray(input).map(toArrayRecursively);\n }\n return input;\n}\nfunction isArrayLike(v) {\n return Boolean(typeof v === 'object' && v !== null && 'length' in v);\n}\n/** Copied from https://github.com/academia-de-codigo/parse-content-range-header/blob/master/index.js */\nexport function parseContentRange(headerValue) {\n if (!headerValue) {\n return null;\n }\n if (typeof headerValue !== 'string') {\n throw new Error('invalid argument');\n }\n const parseInt = (number) => Number.parseInt(number, 10);\n // Check for presence of unit\n let matches = headerValue.match(/^(\\w*) /);\n const unit = matches && matches[1];\n // check for start-end/size header format\n matches = headerValue.match(/(\\d+)-(\\d+)\\/(\\d+|\\*)/);\n if (matches) {\n return {\n unit,\n first: parseInt(matches[1]),\n last: parseInt(matches[2]),\n length: matches[3] === '*' ? null : parseInt(matches[3]),\n };\n }\n // check for size header format\n matches = headerValue.match(/(\\d+|\\*)/);\n if (matches) {\n return {\n unit,\n first: null,\n last: null,\n length: matches[1] === '*' ? null : parseInt(matches[1]),\n };\n }\n return null;\n}\n/**\n * Promisified wrapper around 'setTimeout' to allow 'await'\n * @param {number} [milliseconds]\n * @returns {Promise<void>}\n */\nexport async function wait(milliseconds) {\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\nexport function zip(a, b) {\n const A = Array.isArray(a) ? a : Array.from(a);\n const B = Array.isArray(b) ? b : Array.from(b);\n return A.map((k, i) => [k, B[i]]);\n}\n// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error\nexport class AbortError extends Error {\n constructor(...args) {\n // Pass remaining arguments (including vendor specific ones) to parent constructor\n super(...args);\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, AbortError);\n }\n this.name = 'AbortError';\n this.signal = undefined;\n }\n}\nexport class CustomAggregateError extends Error {\n constructor(errors, message) {\n super(message);\n this.errors = errors;\n this.message = message;\n this.name = 'AggregateError';\n }\n}\nexport const AggregateError = CustomAggregateError;\nexport function isTypedFloatArray(input) {\n if (ArrayBuffer.isView(input)) {\n const ctr = input.constructor;\n if (ctr === Float32Array || ctr === Float64Array) {\n return true;\n }\n }\n return false;\n}\nexport function isTypedIntArray(input) {\n if (ArrayBuffer.isView(input)) {\n const ctr = input.constructor;\n if (ctr === Int8Array || ctr === Int16Array || ctr === Int32Array) {\n return true;\n }\n }\n return false;\n}\nexport function isTypedUintArray(input) {\n if (ArrayBuffer.isView(input)) {\n const ctr = input.constructor;\n if (ctr === Uint8Array ||\n ctr === Uint16Array ||\n ctr === Uint32Array ||\n ctr === Uint8ClampedArray) {\n return true;\n }\n }\n return false;\n}\nexport const typeMap = {\n Float64Array,\n Float32Array,\n Uint32Array,\n Uint16Array,\n Uint8Array,\n};\n//# sourceMappingURL=utils.js.map","import { BaseSource } from './basesource.js';\nimport { AbortError } from '../utils.js';\nclass ArrayBufferSource extends BaseSource {\n /**\n * @param {ArrayBuffer} arrayBuffer\n */\n constructor(arrayBuffer) {\n super();\n this.arrayBuffer = arrayBuffer;\n }\n /**\n * @param {import('./basesource.js').Slice} slice\n * @param {AbortSignal} [signal]\n * @returns {Promise<import('./basesource.js').SliceWithData>}\n */\n fetchSlice(slice, signal) {\n if (signal && signal.aborted) {\n throw new AbortError('Request aborted');\n }\n return Promise.resolve({\n data: this.arrayBuffer.slice(slice.offset, slice.offset + slice.length),\n offset: slice.offset,\n length: slice.length,\n });\n }\n}\n/** @param {ArrayBuffer} arrayBuffer */\nexport function makeBufferSource(arrayBuffer) {\n return new ArrayBufferSource(arrayBuffer);\n}\n//# sourceMappingURL=arraybuffer.js.map","import DataSlice from './dataslice.js';\nimport { fieldTypes, geoKeyNames, tagDefinitions, resolveTag, getFieldTypeSize, } from './globals.js';\n/**\n * Allocates an appropriate TypedArray based on the TIFF field type.\n * @param {number} fieldType - TIFF field type constant from fieldTypes\n * @param {number} count - Number of elements to allocate\n * @returns {import('./geotiff.js').TypedArray|Array<number>} The allocated typed array for the given field type\n * @throws {RangeError} If the field type is invalid\n */\nfunction getArrayForSamples(fieldType, count) {\n switch (fieldType) {\n case fieldTypes.BYTE:\n case fieldTypes.ASCII:\n case fieldTypes.UNDEFINED:\n return new Uint8Array(count);\n case fieldTypes.SBYTE:\n return new Int8Array(count);\n case fieldTypes.SHORT:\n return new Uint16Array(count);\n case fieldTypes.SSHORT:\n return new Int16Array(count);\n case fieldTypes.LONG:\n case fieldTypes.IFD:\n return new Uint32Array(count);\n case fieldTypes.SLONG:\n return new Int32Array(count);\n case fieldTypes.LONG8:\n case fieldTypes.IFD8:\n return new Array(count);\n case fieldTypes.SLONG8:\n return new Array(count);\n case fieldTypes.RATIONAL:\n return new Uint32Array(count * 2);\n case fieldTypes.SRATIONAL:\n return new Int32Array(count * 2);\n case fieldTypes.FLOAT:\n return new Float32Array(count);\n case fieldTypes.DOUBLE:\n return new Float64Array(count);\n default:\n throw new RangeError(`Invalid field type: ${fieldType}`);\n }\n}\n/**\n * Returns the appropriate DataSlice read method for a given field type.\n * @param {DataSlice} dataSlice - The DataSlice instance to get the reader from\n * @param {number} fieldType - TIFF field type constant from fieldTypes\n * @returns {Function} The bound read method (e.g., readUint16, readFloat32)\n * @throws {RangeError} If the field type is invalid\n */\nfunction getDataSliceReader(dataSlice, fieldType) {\n switch (fieldType) {\n case fieldTypes.BYTE:\n case fieldTypes.ASCII:\n case fieldTypes.UNDEFINED:\n return dataSlice.readUint8;\n case fieldTypes.SBYTE:\n return dataSlice.readInt8;\n case fieldTypes.SHORT:\n return dataSlice.readUint16;\n case fieldTypes.SSHORT:\n return dataSlice.readInt16;\n case fieldTypes.LONG:\n case fieldTypes.IFD:\n return dataSlice.readUint32;\n case fieldTypes.SLONG:\n return dataSlice.readInt32;\n case fieldTypes.LONG8:\n case fieldTypes.IFD8:\n return dataSlice.readUint64;\n case fieldTypes.SLONG8:\n return dataSlice.readInt64;\n case fieldTypes.RATIONAL:\n return dataSlice.readUint32;\n case fieldTypes.SRATIONAL:\n return dataSlice.readInt32;\n case fieldTypes.FLOAT:\n return dataSlice.readFloat32;\n case fieldTypes.DOUBLE:\n return dataSlice.readFloat64;\n default:\n throw new RangeError(`Invalid field type: ${fieldType}`);\n }\n}\n/**\n * @overload\n * @param {import('./geotiff.js').TypedArray|Array<number>|null} outValues - Optional pre-allocated output array\n * @param {Function} readMethod - DataView read method (e.g., getUint16)\n * @param {DataSlice} dataSlice - Source data slice\n * @param {number} fieldType - TIFF field type constant\n * @param {number} count - Number of values to read\n * @param {number} offset - Byte offset to start reading\n * @param {true} isArray - Whether to always return an array (vs single value)\n * @returns {import('./geotiff.js').TypedArray|Array<number>} The decoded value(s)\n */\n/**\n * @overload\n * @param {import('./geotiff.js').TypedArray|Array<number>|null} outValues - Optional pre-allocated output array\n * @param {Function} readMethod - DataView read method (e.g., getUint16)\n * @param {DataSlice} dataSlice - Source data slice\n * @param {number} fieldType - TIFF field type constant\n * @param {number} count - Number of values to read\n * @param {number} offset - Byte offset to start reading\n * @param {boolean} [isArray] - Whether to always return an array (vs single value)\n * @returns {import('./geotiff.js').TypedArray|Array<number>|string|number} The decoded value(s)\n */\n/**\n * Reads field values from a DataSlice.\n * @param {import('./geotiff.js').TypedArray|Array<number>|null} outValues - Optional pre-allocated output array\n * @param {Function} readMethod - DataView read method (e.g., getUint16)\n * @param {DataSlice} dataSlice - Source data slice\n * @param {import('./globals.js').FieldType} fieldType - TIFF field type constant\n * @param {number} count - Number of values to read\n * @param {number} offset - Byte offset to start reading\n * @param {boolean} [isArray] - Whether to always return an array (vs single value)\n * @returns {import('./geotiff.js').TypedArray|Array<number>|string|number} The decoded value(s)\n */\nfunction getValues(outValues = null, readMethod, dataSlice, fieldType, count, offset, isArray = false) {\n const fieldTypeLength = getFieldTypeSize(fieldType);\n const values = outValues || getArrayForSamples(fieldType, count);\n // const readMethod = getDataSliceReader(dataSlice, fieldType);\n const isRational = (fieldType === fieldTypes.RATIONAL || fieldType === fieldTypes.SRATIONAL);\n // normal fields\n if (!isRational) {\n for (let i = 0; i < count; ++i) {\n values[i] = readMethod.call(dataSlice, offset + (i * fieldTypeLength));\n }\n }\n else {\n // RATIONAL or SRATIONAL\n for (let i = 0; i < count; i += 2) {\n values[i] = readMethod.call(dataSlice, offset + (i * fieldTypeLength));\n values[i + 1] = readMethod.call(dataSlice, offset + ((i * fieldTypeLength) + 4));\n }\n }\n if (fieldType === fieldTypes.ASCII) {\n return new TextDecoder('utf-8').decode(/** @type {Uint8Array} */ (values));\n }\n if (count === 1 && !isArray && !isRational) {\n return values[0];\n }\n return values;\n}\n/**\n * Lazily-loaded array for large TIFF field values that are fetched on-demand.\n * Supports loading individual indices or the entire array. Uses a bitmap to track\n * which values have been loaded to avoid redundant fetches.\n */\nclass DeferredArray {\n /**\n * Creates a DeferredArray for lazy-loading of large TIFF field arrays.\n * @param {import(\"./source/basesource.js\").BaseSource} source - Data source for fetching\n * @param {number} arrayOffset - Byte offset where the array data starts\n * @param {boolean} littleEndian - Endianness of the data\n * @param {import('./globals.js').FieldType} fieldType - TIFF field type constant\n * @param {number} length - Number of elements in the array\n */\n constructor(source, arrayOffset, littleEndian, fieldType, length) {\n this.source = source;\n this.arrayOffset = arrayOffset;\n this.littleEndian = littleEndian;\n this.fieldType = fieldType;\n this.length = length;\n this.data = getArrayForSamples(fieldType, length);\n this.itemSize = getFieldTypeSize(fieldType);\n this.maskBitmap = new Uint8Array(Math.ceil(length / 8));\n this.fetchIndexPromises = new Map();\n this.fullFetchPromise = null;\n }\n /**\n * Loads all values in the deferred array at once.\n * Subsequent calls return the same promise to avoid redundant fetches.\n * @returns {Promise<import('./geotiff.js').TypedArray|Array<number>>} Promise resolving to the fully loaded array\n */\n async loadAll() {\n if (!this.fullFetchPromise) {\n this.fullFetchPromise = this.source.fetch([{\n offset: this.arrayOffset,\n length: this.itemSize * this.length,\n }]).then((data) => {\n const dataSlice = new DataSlice(data[0], this.arrayOffset, true, false);\n const result = getValues(this.data, getDataSliceReader(dataSlice, this.fieldType), dataSlice, this.fieldType, this.length, this.arrayOffset, true);\n // Mark all items as loaded in the bitmap\n this.maskBitmap.fill(0xFF);\n // Clean up any pending individual fetch promises since all data is now loaded\n this.fetchIndexPromises.clear();\n return result;\n });\n }\n return this.fullFetchPromise;\n }\n /**\n * Loads and returns a single value at the specified index.\n * If the value is already loaded, returns it immediately. Otherwise, fetches it\n * from the source. Multiple calls for the same index reuse the same promise.\n * @param {number} index - Zero-based index of the value to load\n * @returns {Promise<number|bigint>} Promise resolving to the value at the given index\n * @throws {RangeError} If index is out of bounds\n */\n async get(index) {\n if (index < 0 || index >= this.data.length) {\n throw new RangeError(`Index ${index} out of bounds for length ${this.data.length}`);\n }\n const byteIndex = Math.floor(index / 8);\n const bitMask = 1 << index % 8;\n const offset = this.arrayOffset + (index * this.itemSize);\n if ((this.maskBitmap[byteIndex] & bitMask) === 0) {\n if (!this.fetchIndexPromises.has(index)) {\n const fetchPromise = this.source.fetch([{\n offset,\n length: this.itemSize,\n }]).then((data) => {\n const dataSlice = new DataSlice(data[0], this.arrayOffset + (index * this.itemSize), true, false);\n const readMethod = getDataSliceReader(dataSlice, this.fieldType);\n const value = readMethod.call(dataSlice, offset);\n this.data[index] = value;\n this.maskBitmap[byteIndex] |= bitMask;\n this.fetchIndexPromises.delete(index);\n return value;\n });\n this.fetchIndexPromises.set(index, fetchPromise);\n }\n return this.fetchIndexPromises.get(index);\n }\n return this.data[index];\n }\n}\nexport class ImageFileDirectory {\n /**\n * Create an ImageFileDirectory.\n * @param {Map<string|number, number|string|Array<number|string>>} actualizedFields the file directory,\n * mapping tag names to values\n * @param {Map<string|number, Function>} deferredFields the deferred fields, mapping tag names to async functions\n * @param {Map<string|number, DeferredArray>} deferredArrays the deferred arrays, mapping tag names to\n * DeferredArray objects\n * @param {number} nextIFDByteOffset the byte offset to the next IFD\n */\n constructor(actualizedFields, deferredFields, deferredArrays, nextIFDByteOffset) {\n this.actualizedFields = actualizedFields;\n this.deferredFields = deferredFields;\n this.deferredFieldsBeingResolved = new Map();\n this.deferredArrays = deferredArrays;\n this.nextIFDByteOffset = nextIFDByteOffset;\n }\n /**\n * @param {import('./globals.js').TagName|number} tagIdentifier The field tag ID or name\n * @returns {boolean} whether the field exists (actualized or deferred)\n */\n hasTag(tagIdentifier) {\n const tag = resolveTag(tagIdentifier);\n return this.actualizedFields.has(tag) || this.deferredFields.has(tag) || this.deferredArrays.has(tag);\n }\n /**\n * Synchronously retrieves the value for a given tag. If it is deferred, an error is thrown.\n * @template {import('./globals.js').EagerTagName | import('./globals.js').EagerTag} [T=any]\n * @param {T} tagIdentifier The field tag ID or name\n * @returns {T extends import('./globals.js').TagName ? (import('./globals.js').TagValue<T> | undefined) : any}\n * the field value,\n * or undefined if it does not exist\n * @throws {Error} If the tag is deferred and requires asynchronous loading\n */\n getValue(tagIdentifier) {\n const tag = resolveTag(tagIdentifier);\n if (this.deferredFields.has(tag) || this.deferredArrays.has(tag)) {\n const tagDef = tagDefinitions[tag];\n const tagName = tagDef?.name || `Tag${tag}`;\n throw new Error(`Field '${tagName}' (${tag}) is deferred. Use loadValue() to load it asynchronously.`);\n }\n if (!this.actualizedFields.has(tag)) {\n return /** @type {any} */ (undefined);\n }\n return /** @type {any} */ (this.actualizedFields.get(tag));\n }\n /**\n * Retrieves the value for a given tag. If it is deferred, it will be loaded first.\n * @template {import('./globals.js').TagName} [T=any]\n * @param {T|number} tagIdentifier The field tag ID or name\n * @returns {Promise<T extends import('./globals.js').TagName ? (import('./globals.js').TagValue<T> | undefined) : any>}\n * the field value, or undefined if it does not exist\n */\n async loadValue(tagIdentifier) {\n const tag = resolveTag(tagIdentifier);\n if (this.actualizedFields.has(tag)) {\n return /** @type {any} */ (this.actualizedFields.get(tag));\n }\n if (this.deferredFieldsBeingResolved.has(tag)) {\n return /** @type {any} */ (this.deferredFieldsBeingResolved.get(tag));\n }\n const loaderFn = this.deferredFields.get(tag);\n if (loaderFn) {\n this.deferredFields.delete(tag);\n // Set promise BEFORE starting async work to prevent race conditions\n const valuePromise = (async () => {\n try {\n const value = await loaderFn();\n this.actualizedFields.set(tag, value);\n return value;\n }\n finally {\n this.deferredFieldsBeingResolved.delete(tag);\n }\n })();\n this.deferredFieldsBeingResolved.set(tag, valuePromise);\n return /** @type {any} */ (valuePromise);\n }\n const deferredArray = this.deferredArrays.get(tag);\n if (deferredArray) {\n return /** @type {any} */ (deferredArray.loadAll());\n }\n return /** @type {any} */ (undefined);\n }\n /**\n * Retrieves the value at a given index for a tag that is an array. If it is deferred, it will be loaded first.\n * @param {number|string} tagIdentifier The field tag ID or name\n * @param {number} index The index within the array\n * @returns {Promise<number|string|bigint|undefined>} the field value at the given index, or undefined if it does not exist\n */\n async loadValueIndexed(tagIdentifier, index) {\n const tag = resolveTag(tagIdentifier);\n if (this.actualizedFields.has(tag)) {\n const value = this.actualizedFields.get(tag);\n return /** @type {any} */ (value)[index];\n }\n else if (this.deferredArrays.has(tag)) {\n const deferredArray = /** @type {DeferredArray} */ (this.deferredArrays.get(tag));\n return deferredArray.get(index);\n }\n else if (this.hasTag(tag)) {\n const value = await this.loadValue(tag);\n if (value && typeof value !== 'number') {\n return value[index];\n }\n }\n return undefined;\n }\n /**\n * Parses the GeoTIFF GeoKeyDirectory tag into a structured object.\n * The GeoKeyDirectory is a special TIFF tag that contains geographic metadata\n * in a key-value format as defined by the GeoTIFF specification.\n * @returns {Partial<Record<import('./globals.js').GeoKeyName, *>>|null} Parsed geo key directory\n * mapping key names to values, or null if not present\n * @throws {Error} If a referenced geo key value cannot be retrieved\n */\n parseGeoKeyDirectory() {\n const rawGeoKeyDirectory = this.getValue('GeoKeyDirectory');\n if (!rawGeoKeyDirectory) {\n return null;\n }\n /** @type {Partial<Record<import('./globals.js').GeoKeyName, *>>} */\n const geoKeyDirectory = {};\n for (let i = 4; i <= rawGeoKeyDirectory[3] * 4; i += 4) {\n const key = ( /** @type {Record<number, import('./globals.js').GeoKeyName>} */(geoKeyNames))[rawGeoKeyDirectory[i]];\n const location = /** @type {import('./globals.js').EagerTag} */ (rawGeoKeyDirectory[i + 1]) || null;\n const count = rawGeoKeyDirectory[i + 2];\n const offset = rawGeoKeyDirectory[i + 3];\n let value = null;\n if (!location) {\n value = offset;\n }\n else {\n value = this.getValue(location);\n if (typeof value === 'undefined' || value === null) {\n throw new Error(`Could not get value of geoKey '${key}'.`);\n }\n else if (typeof value === 'string') {\n value = value.substring(offset, offset + count - 1);\n }\n else if (value.subarray) {\n value = value.subarray(offset, offset + count);\n if (count === 1) {\n value = value[0];\n }\n }\n }\n geoKeyDirectory[key] = value;\n }\n return geoKeyDirectory;\n }\n toObject() {\n /** @type {Record<string, unknown>} */\n const obj = {};\n for (const [tag, value] of this.actualizedFields.entries()) {\n const tagDefinition = typeof tag === 'number' ? tagDefinitions[tag] : undefined;\n const tagName = tagDefinition ? tagDefinition.name : `Tag${tag}`;\n obj[tagName] = value;\n }\n return obj;\n }\n}\n/**\n * Parser for Image File Directories (IFDs).\n */\nexport class ImageFileDirectoryParser {\n /**\n * @param {import(\"./source/basesource.js\").BaseSource} source the data source to fetch from\n * @param {boolean} littleEndian the endianness of the file\n * @param {boolean} bigTiff whether the file is a BigTIFF\n * @param {boolean} [eager=false] whether to eagerly fetch deferred fields.\n * When false (default), tags are loaded lazily on-demand.\n * When true, all tags are loaded immediately during parsing.\n */\n constructor(source, littleEndian, bigTiff, eager = false) {\n this.source = source;\n this.littleEndian = littleEndian;\n this.bigTiff = bigTiff;\n this.eager = eager;\n }\n /**\n * Helper function to retrieve a DataSlice from the source.\n * @param {number} offset Byte offset of the slice\n * @param {number} [length] Length of the slice\n * @returns {Promise<DataSlice>}\n */\n async getSlice(offset, length) {\n const fallbackLength = this.bigTiff ? 4048 : 1024;\n return new DataSlice((await this.source.fetch([\n {\n offset,\n length: typeof length !== 'undefined' ? length : fallbackLength,\n },\n ]))[0], offset, this.littleEndian, this.bigTiff);\n }\n /**\n * Instructs to parse an image file directory at the given file offset.\n * As there is no way to ensure that a location is indeed the start of an IFD,\n * this function must be called with caution (e.g only using the IFD offsets from\n * the headers or other IFDs).\n * @param {number} offset the offset to parse the IFD at\n * @returns {Promise<ImageFileDirectory>} the parsed IFD\n */\n async parseFileDirectoryAt(offset) {\n const entrySize = this.bigTiff ? 20 : 12;\n const offsetSize = this.bigTiff ? 8 : 2;\n let dataSlice = await this.getSlice(offset);\n const numDirEntries = this.bigTiff\n ? dataSlice.readUint64(offset)\n : dataSlice.readUint16(offset);\n // if the slice does not cover the whole IFD, request a bigger slice, where the\n // whole IFD fits: num of entries + n x tag length + offset to next IFD\n const byteSize = numDirEntries * (entrySize + (this.bigTiff ? 16 : 6));\n if (!dataSlice.covers(offset, byteSize)) {\n dataSlice = await this.getSlice(offset, byteSize);\n }\n const actualizedFields = new Map();\n const deferredFields = new Map();\n const deferredArrays = new Map();\n // loop over the IFD and create a file directory object\n let i = offset + (this.bigTiff ? 8 : 2);\n for (let entryCount = 0; entryCount < numDirEntries; i += entrySize, ++entryCount) {\n const fieldTag = dataSlice.readUint16(i);\n const fieldType = /** @type {import('./globals.js').FieldType} */ (dataSlice.readUint16(i + 2));\n const typeCount = this.bigTiff\n ? dataSlice.readUint64(i + 4)\n : dataSlice.readUint32(i + 4);\n let fieldValues = null;\n let deferredFieldValues = null;\n let deferredArray = null;\n const fieldTypeLength = getFieldTypeSize(fieldType);\n const valueOffset = i + (this.bigTiff ? 12 : 8);\n const isArray = tagDefinitions[fieldTag]?.isArray;\n const eager = tagDefinitions[fieldTag]?.eager || this.eager;\n // check whether the value is directly encoded in the tag or refers to a\n // different external byte range\n if (fieldTypeLength * typeCount <= (this.bigTiff ? 8 : 4)) {\n fieldValues = getValues(getArrayForSamples(fieldType, typeCount), getDataSliceReader(dataSlice, fieldType), dataSlice, fieldType, typeCount, valueOffset, isArray);\n }\n else {\n // resolve the reference to the actual byte range\n const actualOffset = dataSlice.readOffset(valueOffset);\n const length = getFieldTypeSize(fieldType) * typeCount;\n // check, whether we actually cover the referenced byte range\n if (dataSlice.covers(actualOffset, length)) {\n fieldValues = getValues(getArrayForSamples(fieldType, typeCount), getDataSliceReader(dataSlice, fieldType), dataSlice, fieldType, typeCount, actualOffset, isArray);\n }\n else if (eager) {\n // eager evaluation: fetch the data right now\n // TODO: instead of fetching the slice right here, collect all slices and fetch them together\n // to allow conjoined requests\n const fieldDataSlice = await this.getSlice(actualOffset, length);\n fieldValues = getValues(getArrayForSamples(fieldType, typeCount), getDataSliceReader(fieldDataSlice, fieldType), fieldDataSlice, fieldType, typeCount, actualOffset, isArray);\n }\n else if (isArray) {\n deferredArray = new DeferredArray(this.source, actualOffset, this.littleEndian, fieldType, typeCount);\n }\n else {\n deferredFieldValues = async () => {\n const fieldDataSlice = await this.getSlice(actualOffset, length);\n return getValues(getArrayForSamples(fieldType, typeCount), getDataSliceReader(fieldDataSlice, fieldType), fieldDataSlice, fieldType, typeCount, actualOffset, isArray);\n };\n }\n }\n if (fieldValues !== null) {\n actualizedFields.set(fieldTag, fieldValues);\n }\n else if (deferredFieldValues !== null) {\n deferredFields.set(fieldTag, deferredFieldValues);\n }\n else if (deferredArray !== null) {\n deferredArrays.set(fieldTag, deferredArray);\n }\n }\n const nextIFDByteOffset = dataSlice.readOffset(offset + offsetSize + (entrySize * numDirEntries));\n return new ImageFileDirectory(actualizedFields, deferredFields, deferredArrays, nextIFDByteOffset);\n }\n}\n//# sourceMappingURL=imagefiledirectory.js.map","/** @module geotiff */\nimport GeoTIFFImage from './geotiffimage.js';\nimport DataView64 from './dataview64.js';\nimport DataSlice from './dataslice.js';\nimport Pool from './pool.js';\nimport { makeRemoteSource, makeCustomSource } from './source/remote.js';\nimport { makeBufferSource } from './source/arraybuffer.js';\nimport { makeFileReaderSource } from './source/filereader.js';\nimport { makeFileSource } from './source/file.js';\nimport { BaseClient, BaseResponse } from './source/client/base.js';\nimport { ImageFileDirectoryParser } from './imagefiledirectory.js';\nimport { fieldTypes, getFieldTypeSize, registerTag } from './globals.js';\nimport { writeGeotiff } from './geotiffwriter.js';\nimport * as globals from './globals.js';\nimport * as rgb from './rgb.js';\nimport { getDecoder, addDecoder } from './compression/index.js';\nimport { setLogger } from './logging.js';\n/** @import { BaseSource } from './source/basesource.js' */\nexport { globals };\nexport { registerTag };\nexport { rgb };\nexport { default as BaseDecoder } from './compression/basedecoder.js';\nexport { getDecoder, addDecoder };\nexport { setLogger };\nexport { ImageFileDirectory } from './imagefiledirectory.js';\n/**\n * @typedef {Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array}\n * TypedArray\n */\n/**\n * @typedef {{ height:number, width: number }} Dimensions\n */\n/**\n * The autogenerated docs are a little confusing here. The effective type is:\n *\n * `TypedArray & { height: number; width: number}`\n * @typedef {TypedArray & Dimensions} TypedArrayWithDimensions\n */\n/**\n * The autogenerated docs are a little confusing here. The effective type is:\n *\n * `TypedArray[] & { height: number; width: number}`\n * @typedef {TypedArray[] & Dimensions} TypedArrayArrayWithDimensions\n */\n/**\n * @typedef {Object} GeotiffWriterMetadata\n * @property {number | number[]} [ImageWidth]\n * @property {number | number[]} [ImageLength]\n * @property {number} [width]\n * @property {number} [height]\n * @property {number | number[]} [BitsPerSample]\n * @property {number | number[]} [Compression]\n * @property {number | number[]} [PlanarConfiguration]\n * @property {number | number[]} [ExtraSamples]\n * @property {number | number[]} [PhotometricInterpretation]\n * @property {number | number[]} [SamplesPerPixel]\n * @property {number | number[]} [StripByteCounts]\n * @property {number[]} [ModelPixelScale]\n * @property {number[]} [ModelTransformation]\n * @property {number[]} [ModelTiepoint]\n * @property {number[]} [GeoKeyDirectory]\n * @property {string} [GeoAsciiParams]\n * @property {number[]} [GeoDoubleParams]\n * @property {number | number[]} [Orientation]\n * @property {number | number[]} [ResolutionUnit]\n * @property {number | number[]} [XPosition]\n * @property {number | number[]} [YPosition]\n * @property {number | number[]} [RowsPerStrip]\n * @property {number[]} [SampleFormat]\n * @property {number | number[]} [TileWidth]\n * @property {number | number[]} [TileLength]\n * @property {number[]} [TileOffsets]\n * @property {number[]} [TileByteCounts]\n * @property {string} [GDAL_NODATA]\n * @property {number | number[]} [GeographicTypeGeoKey]\n * @property {number | number[]} [ProjectedCSTypeGeoKey]\n * @property {string} [GeogCitationGeoKey]\n * @property {string} [GTCitationGeoKey]\n * @property {number | number[]} [GTModelTypeGeoKey]\n * @property {number | number[]} [GTRasterTypeGeoKey]\n */\n/**\n * The autogenerated docs are a little confusing here. The effective type is:\n *\n * `(TypedArray | TypedArray[]) & { height: number; width: number}`\n * @typedef {TypedArrayWithDimensions | TypedArrayArrayWithDimensions} ReadRasterResult\n */\n/**\n * @typedef {Object} DecoderWorker\n * Use the {@link Pool.bindParameters} method to get a decoder worker for\n * a specific compression and its parameters.\n *\n * @property {(buffer: ArrayBufferLike) => Promise<ArrayBufferLike>} decode\n * A function that takes a compressed buffer and returns a promise resolving to the decoded buffer.\n */\n/**\n * @typedef {Object} ReadRastersOptions\n * @property {Array<number>} [window] the subset to read data from in pixels. Whole window if not specified.\n * @property {Array<number>} [samples] the selection of samples to read from. Default is all samples.\n * All samples if not specified.\n * @property {Pool|null} [pool=null] The optional decoder pool to use.\n * @property {number} [width] The desired width of the output. When the width is not the\n * same as the images, resampling will be performed.\n * @property {number} [height] The desired height of the output. When the width is not the\n * same as the images, resampling will be performed.\n * @property {string} [resampleMethod='nearest'] The desired resampling method.\n * @property {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @property {number|number[]} [fillValue] The value to use for parts of the image\n * outside of the images extent. When multiple samples are requested and `interleave` is\n * `false`, an array of fill values can be passed.\n * @property {boolean|true|false} [interleave] whether the data shall be read\n * in one single array or separate arrays.\n */\n/**\n * @typedef {Object} ReadRGBOptions\n * @property {Array<number>} [window] the subset to read data from in pixels. Whole window if not specified.\n * @property {Pool|null} [pool=null] The optional decoder pool to use.\n * @property {number} [width] The desired width of the output. When the width is no the\n * same as the images, resampling will be performed.\n * @property {number} [height] The desired height of the output. When the width is no the\n * same as the images, resampling will be performed.\n * @property {string} [resampleMethod='nearest'] The desired resampling method.\n * @property {boolean} [enableAlpha=false] Enable reading alpha channel if present.\n * @property {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @property {boolean|true|false} [interleave] whether the data shall be read\n * in one single array or separate arrays.\n */\n/**\n * @typedef {Object} BlockedSourceOptions\n * @property {number} [blockSize] Block size for a BlockedSource.\n * @property {number} [cacheSize=100] The number of blocks to cache.\n */\n/**\n * @typedef {Object} RemoteSourceOptions\n * @property {Record<string, string>} [headers={}] Additional headers to add to each request\n * @property {number} [maxRanges=0] Maximum number of ranges to request in a single HTTP request. 0 means no multi-range requests.\n * @property {boolean} [allowFullFile=false] Whether to allow full file responses when requesting ranges\n * @property {boolean} [forceXHR=false] When the Fetch API would be used, force using XMLHttpRequest instead.\n */\n/**\n * @overload\n * @param {DataSlice} dataSlice\n * @param {0x0002} fieldType\n * @param {number} count\n * @param {number} offset\n * @returns {string}\n */\n/**\n * @param {DataSlice} dataSlice\n * @param {import('./globals.js').FieldType} fieldType\n * @param {number} count\n * @param {number} offset\n * @returns {TypedArray|Array<number>|string}\n */\nfunction getValues(dataSlice, fieldType, count, offset) {\n /** @type {TypedArray|Array<number>|null} */\n let values = null;\n let readMethod = null;\n const fieldTypeLength = getFieldTypeSize(fieldType);\n switch (fieldType) {\n case fieldTypes.BYTE:\n case fieldTypes.ASCII:\n case fieldTypes.UNDEFINED:\n values = new Uint8Array(count);\n readMethod = dataSlice.readUint8;\n break;\n case fieldTypes.SBYTE:\n values = new Int8Array(count);\n readMethod = dataSlice.readInt8;\n break;\n case fieldTypes.SHORT:\n values = new Uint16Array(count);\n readMethod = dataSlice.readUint16;\n break;\n case fieldTypes.SSHORT:\n values = new Int16Array(count);\n readMethod = dataSlice.readInt16;\n break;\n case fieldTypes.LONG:\n case fieldTypes.IFD:\n values = new Uint32Array(count);\n readMethod = dataSlice.readUint32;\n break;\n case fieldTypes.SLONG:\n values = new Int32Array(count);\n readMethod = dataSlice.readInt32;\n break;\n case fieldTypes.LONG8:\n case fieldTypes.IFD8:\n values = new Array(count);\n readMethod = dataSlice.readUint64;\n break;\n case fieldTypes.SLONG8:\n values = new Array(count);\n readMethod = dataSlice.readInt64;\n break;\n case fieldTypes.RATIONAL:\n values = new Uint32Array(count * 2);\n readMethod = dataSlice.readUint32;\n break;\n case fieldTypes.SRATIONAL:\n values = new Int32Array(count * 2);\n readMethod = dataSlice.readInt32;\n break;\n case fieldTypes.FLOAT:\n values = new Float32Array(count);\n readMethod = dataSlice.readFloat32;\n break;\n case fieldTypes.DOUBLE:\n values = new Float64Array(count);\n readMethod = dataSlice.readFloat64;\n break;\n default:\n // will throw below\n }\n if (values === null || readMethod === null) {\n throw new RangeError(`Invalid field type: ${fieldType}`);\n }\n // normal fields\n if (!(fieldType === fieldTypes.RATIONAL || fieldType === fieldTypes.SRATIONAL)) {\n for (let i = 0; i < count; ++i) {\n values[i] = readMethod.call(dataSlice, offset + (i * fieldTypeLength));\n }\n }\n else { // RATIONAL or SRATIONAL\n for (let i = 0; i < count; i += 2) {\n values[i] = readMethod.call(dataSlice, offset + (i * fieldTypeLength));\n values[i + 1] = readMethod.call(dataSlice, offset + ((i * fieldTypeLength) + 4));\n }\n }\n if (fieldType === fieldTypes.ASCII) {\n return new TextDecoder('utf-8').decode(/** @type {Uint8Array} */ (values));\n }\n return values;\n}\n/**\n * Error class for cases when an IFD index was requested, that does not exist\n * in the file.\n */\nclass GeoTIFFImageIndexError extends Error {\n /**\n * @param {number} index\n */\n constructor(index) {\n super(`No image at index ${index}`);\n this.index = index;\n }\n}\nclass GeoTIFFBase {\n /**\n * @param {number} [_index=0] the index of the image to return.\n * @returns {Promise<GeoTIFFImage>} the image at the given index\n */\n async getImage(_index = 0) {\n throw new Error('Not implemented');\n }\n /**\n * @returns {Promise<number>} the number of internal subfile images\n */\n async getImageCount() {\n throw new Error('Not implemented');\n }\n /**\n * @typedef {Object} ReadRastersWindowOptions\n * @property {number} [resX] desired Y resolution (world units per pixel)\n * @property {number} [resY] desired X resolution (world units per pixel)\n * @property {Array<number>} [bbox] the subset to read data from in\n * geographical coordinates. Whole image if not specified.\n */\n /**\n * (experimental) Reads raster data from the best fitting image. This function uses\n * the image with the lowest resolution that is still a higher resolution than the\n * requested resolution.\n * When specified, the `bbox` option is translated to the `window` option and the\n * `resX` and `resY` to `width` and `height` respectively.\n * Then, the [readRasters]{@link GeoTIFFImage#readRasters} method of the selected\n * image is called and the result returned.\n * @see GeoTIFFImage.readRasters\n * @param {ReadRastersOptions & ReadRastersWindowOptions} options optional parameters\n * @returns {Promise<ReadRasterResult>} the decoded array(s), with `height` and `width`, as a promise\n */\n async readRasters(options = {}) {\n const { window: imageWindow, width, height } = options;\n let { resX, resY, bbox } = options;\n const firstImage = await this.getImage();\n let usedImage = firstImage;\n const imageCount = await this.getImageCount();\n const imgBBox = firstImage.getBoundingBox();\n if (imageWindow && bbox) {\n throw new Error('Both \"bbox\" and \"window\" passed.');\n }\n // if width/height is passed, transform it to resolution\n if (width || height) {\n // if we have an image window (pixel coordinates), transform it to a BBox\n // using the origin/resolution of the first image.\n if (imageWindow) {\n const [oX, oY] = firstImage.getOrigin();\n const [rX, rY] = firstImage.getResolution();\n bbox = [\n oX + (imageWindow[0] * rX),\n oY + (imageWindow[1] * rY),\n oX + (imageWindow[2] * rX),\n oY + (imageWindow[3] * rY),\n ];\n }\n // if we have a bbox (or calculated one)\n const usedBBox = bbox || imgBBox;\n if (width) {\n if (resX) {\n throw new Error('Both width and resX passed');\n }\n resX = (usedBBox[2] - usedBBox[0]) / width;\n }\n if (height) {\n if (resY) {\n throw new Error('Both width and resY passed');\n }\n resY = (usedBBox[3] - usedBBox[1]) / height;\n }\n }\n // if resolution is set or calculated, try to get the image with the worst acceptable resolution\n if (resX || resY) {\n const allImages = [];\n for (let i = 0; i < imageCount; ++i) {\n const image = await this.getImage(i);\n const subfileType = image.fileDirectory.getValue('SubfileType');\n const newSubfileType = image.fileDirectory.getValue('NewSubfileType');\n if (i === 0 || subfileType === 2 || (newSubfileType || 0) & 1) {\n allImages.push(image);\n }\n }\n allImages.sort((a, b) => a.getWidth() - b.getWidth());\n for (let i = 0; i < allImages.length; ++i) {\n const image = allImages[i];\n const imgResX = (imgBBox[2] - imgBBox[0]) / image.getWidth();\n const imgResY = (imgBBox[3] - imgBBox[1]) / image.getHeight();\n usedImage = image;\n if ((resX && resX > imgResX) || (resY && resY > imgResY)) {\n break;\n }\n }\n }\n let wnd = imageWindow;\n if (bbox) {\n const [oX, oY] = firstImage.getOrigin();\n const [imageResX, imageResY] = usedImage.getResolution(firstImage);\n wnd = [\n Math.round((bbox[0] - oX) / imageResX),\n Math.round((bbox[1] - oY) / imageResY),\n Math.round((bbox[2] - oX) / imageResX),\n Math.round((bbox[3] - oY) / imageResY),\n ];\n wnd = [\n Math.min(wnd[0], wnd[2]),\n Math.min(wnd[1], wnd[3]),\n Math.max(wnd[0], wnd[2]),\n Math.max(wnd[1], wnd[3]),\n ];\n }\n return usedImage.readRasters({ ...options, window: wnd });\n }\n}\n/**\n * @typedef {Object} GeoTIFFOptions\n * @property {boolean} [cache=false] whether or not decoded tiles shall be cached.\n */\n/**\n * The abstraction for a whole GeoTIFF file.\n */\nclass GeoTIFF extends GeoTIFFBase {\n /**\n * @constructor\n * @param {BaseSource} source The datasource to read from.\n * @param {boolean} littleEndian Whether the image uses little endian.\n * @param {boolean} bigTiff Whether the image uses bigTIFF conventions.\n * @param {number} firstIFDOffset The numeric byte-offset from the start of the image\n * to the first IFD.\n * @param {GeoTIFFOptions} [options] further options.\n */\n constructor(source, littleEndian, bigTiff, firstIFDOffset, options = {}) {\n super();\n this.source = source;\n this.parser = new ImageFileDirectoryParser(source, littleEndian, bigTiff, false);\n this.littleEndian = littleEndian;\n this.bigTiff = bigTiff;\n this.firstIFDOffset = firstIFDOffset;\n this.cache = options.cache || false;\n /** @type {Array<Promise<import('./imagefiledirectory.js').ImageFileDirectory> | undefined>} */\n this.ifdRequests = [];\n /** @type {Record<string, unknown>|null} */\n this.ghostValues = null;\n }\n /**\n * @param {number} offset\n * @param {number} [size]\n * @returns {Promise<DataSlice>}\n */\n async getSlice(offset, size) {\n const fallbackSize = this.bigTiff ? 4048 : 1024;\n return new DataSlice((await this.source.fetch([{\n offset,\n length: typeof size !== 'undefined' ? size : fallbackSize,\n }]))[0], offset, this.littleEndian, this.bigTiff);\n }\n /**\n * @param {number} index\n * @return {Promise<import('./imagefiledirectory.js').ImageFileDirectory>}\n */\n async requestIFD(index) {\n // see if we already have that IFD index requested.\n if (this.ifdRequests[index]) {\n // attach to an already requested IFD\n return this.ifdRequests[index];\n }\n else if (index === 0) {\n // special case for index 0\n this.ifdRequests[index] = this.parser.parseFileDirectoryAt(this.firstIFDOffset);\n return this.ifdRequests[index];\n }\n else if (!this.ifdRequests[index - 1]) {\n // if the previous IFD was not yet loaded, load that one first\n // this is the recursive call.\n try {\n this.ifdRequests[index - 1] = this.requestIFD(index - 1);\n }\n catch (e) {\n // if the previous one already was an index error, rethrow\n // with the current index\n if (e instanceof GeoTIFFImageIndexError) {\n throw new GeoTIFFImageIndexError(index);\n }\n // rethrow anything else\n throw e;\n }\n }\n // if the previous IFD was loaded, we can finally fetch the one we are interested in.\n // we need to wrap this in an IIFE, otherwise this.ifdRequests[index] would be delayed\n this.ifdRequests[index] = (async () => {\n const previousPromise = this.ifdRequests[index - 1];\n if (!previousPromise) {\n throw new Error('Previous IFD request missing');\n }\n const previousIfd = await previousPromise;\n if (previousIfd.nextIFDByteOffset === 0) {\n throw new GeoTIFFImageIndexError(index);\n }\n return this.parser.parseFileDirectoryAt(previousIfd.nextIFDByteOffset);\n })();\n return this.ifdRequests[index];\n }\n /**\n * Get the n-th internal subfile of an image. By default, the first is returned.\n *\n * @param {number} [index=0] the index of the image to return.\n * @returns {Promise<GeoTIFFImage>} the image at the given index\n */\n async getImage(index = 0) {\n return new GeoTIFFImage(await this.requestIFD(index), this.littleEndian, this.cache, this.source);\n }\n /**\n * Returns the count of the internal subfiles.\n *\n * @returns {Promise<number>} the number of internal subfile images\n */\n async getImageCount() {\n let index = 0;\n // loop until we run out of IFDs\n let hasNext = true;\n while (hasNext) {\n try {\n await this.requestIFD(index);\n ++index;\n }\n catch (e) {\n if (e instanceof GeoTIFFImageIndexError) {\n hasNext = false;\n }\n else {\n throw e;\n }\n }\n }\n return index;\n }\n /**\n * Get the values of the COG ghost area as a parsed map.\n * See https://gdal.org/drivers/raster/cog.html#header-ghost-area for reference\n * @returns {Promise<Record<string, unknown>|null>} the parsed ghost area or null, if no such area was found\n */\n async getGhostValues() {\n const offset = this.bigTiff ? 16 : 8;\n if (this.ghostValues !== null) {\n return this.ghostValues;\n }\n const detectionString = 'GDAL_STRUCTURAL_METADATA_SIZE=';\n const heuristicAreaSize = detectionString.length + 100;\n let slice = await this.getSlice(offset, heuristicAreaSize);\n if (detectionString === getValues(slice, fieldTypes.ASCII, detectionString.length, offset)) {\n const valuesString = getValues(slice, fieldTypes.ASCII, heuristicAreaSize, offset);\n const firstLine = valuesString.split('\\n')[0];\n const metadataSize = Number(firstLine.split('=')[1].split(' ')[0]) + firstLine.length;\n if (metadataSize > heuristicAreaSize) {\n slice = await this.getSlice(offset, metadataSize);\n }\n const fullString = getValues(slice, fieldTypes.ASCII, metadataSize, offset);\n /** @type {Record<string, unknown>} */\n const ghostValues = {};\n fullString\n .split('\\n')\n .filter((line) => line.length > 0)\n .map((line) => line.split('='))\n .forEach(([key, value]) => {\n ghostValues[key] = value;\n });\n this.ghostValues = ghostValues;\n }\n return this.ghostValues;\n }\n /**\n * Parse a (Geo)TIFF file from the given source.\n *\n * @param {BaseSource} source The source of data to parse from.\n * @param {GeoTIFFOptions} [options] Additional options.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n */\n static async fromSource(source, options, signal) {\n const headerData = (await source.fetch([{ offset: 0, length: 1024 }], signal))[0];\n const dataView = new DataView64(headerData);\n const BOM = dataView.getUint16(0, false);\n let littleEndian;\n if (BOM === 0x4949) {\n littleEndian = true;\n }\n else if (BOM === 0x4D4D) {\n littleEndian = false;\n }\n else {\n throw new TypeError('Invalid byte order value.');\n }\n const magicNumber = dataView.getUint16(2, littleEndian);\n let bigTiff;\n if (magicNumber === 42) {\n bigTiff = false;\n }\n else if (magicNumber === 43) {\n bigTiff = true;\n const offsetByteSize = dataView.getUint16(4, littleEndian);\n if (offsetByteSize !== 8) {\n throw new Error('Unsupported offset byte-size.');\n }\n }\n else {\n throw new TypeError('Invalid magic number.');\n }\n const firstIFDOffset = bigTiff\n ? dataView.getUint64(8, littleEndian)\n : dataView.getUint32(4, littleEndian);\n return new GeoTIFF(source, littleEndian, bigTiff, firstIFDOffset, options);\n }\n /**\n * Closes the underlying file buffer\n * N.B. After the GeoTIFF has been completely processed it needs\n * to be closed but only if it has been constructed from a file.\n */\n close() {\n if (typeof this.source.close === 'function') {\n return this.source.close();\n }\n return false;\n }\n}\nexport { GeoTIFF };\nexport default GeoTIFF;\n/**\n * Wrapper for GeoTIFF files that have external overviews.\n * @augments GeoTIFFBase\n */\nclass MultiGeoTIFF extends GeoTIFFBase {\n /**\n * Construct a new MultiGeoTIFF from a main and several overview files.\n * @param {GeoTIFF} mainFile The main GeoTIFF file.\n * @param {GeoTIFF[]} overviewFiles An array of overview files.\n */\n constructor(mainFile, overviewFiles) {\n super();\n this.mainFile = mainFile;\n this.overviewFiles = overviewFiles;\n this.imageFiles = [mainFile].concat(overviewFiles);\n this.fileDirectoriesPerFile = null;\n this.fileDirectoriesPerFileParsing = null;\n this.imageCount = null;\n }\n async parseFileDirectoriesPerFile() {\n const requests = [this.mainFile.parser.parseFileDirectoryAt(this.mainFile.firstIFDOffset)]\n .concat(this.overviewFiles.map((file) => file.parser.parseFileDirectoryAt(file.firstIFDOffset)));\n this.fileDirectoriesPerFile = await Promise.all(requests);\n return this.fileDirectoriesPerFile;\n }\n /**\n * Get the n-th internal subfile of an image. By default, the first is returned.\n *\n * @param {number} [index=0] the index of the image to return.\n * @returns {Promise<GeoTIFFImage>} the image at the given index\n */\n async getImage(index = 0) {\n // Initialize this.imageCounts if not yet done\n await this.getImageCount();\n if (!this.imageCounts) {\n throw new Error('Image counts not available');\n }\n await this.parseFileDirectoriesPerFile();\n let visited = 0;\n let relativeIndex = 0;\n for (let i = 0; i < this.imageFiles.length; i++) {\n const imageFile = this.imageFiles[i];\n for (let ii = 0; ii < this.imageCounts[i]; ii++) {\n if (index === visited) {\n return new GeoTIFFImage(await imageFile.requestIFD(relativeIndex), imageFile.littleEndian, imageFile.cache, imageFile.source);\n }\n visited++;\n relativeIndex++;\n }\n relativeIndex = 0;\n }\n throw new RangeError('Invalid image index');\n }\n /**\n * Returns the count of the internal subfiles.\n *\n * @returns {Promise<number>} the number of internal subfile images\n */\n async getImageCount() {\n if (this.imageCount !== null) {\n return this.imageCount;\n }\n const requests = [this.mainFile.getImageCount()]\n .concat(this.overviewFiles.map((file) => file.getImageCount()));\n this.imageCounts = await Promise.all(requests);\n this.imageCount = this.imageCounts.reduce((count, ifds) => count + ifds, 0);\n return this.imageCount;\n }\n}\nexport { MultiGeoTIFF };\n/**\n * Creates a new GeoTIFF from a remote URL.\n * @param {string} url The URL to access the image from\n * @param {RemoteSourceOptions} [options] Additional options to pass to the source.\n * See {@link makeRemoteSource} for details.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<GeoTIFF>} The resulting GeoTIFF file.\n */\nexport async function fromUrl(url, options = {}, signal) {\n return GeoTIFF.fromSource(makeRemoteSource(url, options), undefined, signal);\n}\n/**\n * Creates a new GeoTIFF from a custom {@link BaseClient}.\n * @param {BaseClient} client The client.\n * @param {RemoteSourceOptions} [options] Additional options to pass to the source.\n * See {@link makeRemoteSource} for details.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<GeoTIFF>} The resulting GeoTIFF file.\n */\nexport async function fromCustomClient(client, options = {}, signal) {\n return GeoTIFF.fromSource(makeCustomSource(client, options), undefined, signal);\n}\n/**\n * Construct a new GeoTIFF from an\n * [ArrayBuffer]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer}.\n * @param {ArrayBuffer} arrayBuffer The data to read the file from.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<GeoTIFF>} The resulting GeoTIFF file.\n */\nexport async function fromArrayBuffer(arrayBuffer, signal) {\n return GeoTIFF.fromSource(makeBufferSource(arrayBuffer), undefined, signal);\n}\n/**\n * Construct a GeoTIFF from a local file path. This uses the node\n * [filesystem API]{@link https://nodejs.org/api/fs.html} and is\n * not available on browsers.\n *\n * N.B. After the GeoTIFF has been completely processed it needs\n * to be closed but only if it has been constructed from a file.\n * @param {string} path The file path to read from.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<GeoTIFF>} The resulting GeoTIFF file.\n */\nexport async function fromFile(path, signal) {\n return GeoTIFF.fromSource(makeFileSource(path), undefined, signal);\n}\n/**\n * Construct a GeoTIFF from an HTML\n * [Blob]{@link https://developer.mozilla.org/en-US/docs/Web/API/Blob} or\n * [File]{@link https://developer.mozilla.org/en-US/docs/Web/API/File}\n * object.\n * @param {Blob|File} blob The Blob or File object to read from.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<GeoTIFF>} The resulting GeoTIFF file.\n */\nexport async function fromBlob(blob, signal) {\n return GeoTIFF.fromSource(makeFileReaderSource(blob), undefined, signal);\n}\n/**\n * Construct a MultiGeoTIFF from the given URLs.\n * @param {string} mainUrl The URL for the main file.\n * @param {string[]} overviewUrls An array of URLs for the overview images.\n * @param {RemoteSourceOptions} [options] Additional options to pass to the source.\n * See [makeRemoteSource]{@link module:source.makeRemoteSource}\n * for details.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<MultiGeoTIFF>} The resulting MultiGeoTIFF file.\n */\nexport async function fromUrls(mainUrl, overviewUrls = [], options = {}, signal) {\n const mainFile = await GeoTIFF.fromSource(makeRemoteSource(mainUrl, options), undefined, signal);\n const overviewFiles = await Promise.all(overviewUrls.map((url) => GeoTIFF.fromSource(makeRemoteSource(url, options), undefined, signal)));\n return new MultiGeoTIFF(mainFile, overviewFiles);\n}\n/**\n * Main creating function for GeoTIFF files.\n * @param {Array<number>|Array<Array<Array<number>>>|TypedArray} values The pixel values to write.\n * Can be a flat array of all pixels or a 3-dimensional array of shape `[band][row][column]`.\n * @param {GeotiffWriterMetadata} metadata\n * @returns {ArrayBuffer}\n */\nexport function writeArrayBuffer(values, metadata) {\n return writeGeotiff(values, metadata);\n}\nexport { Pool };\nexport { GeoTIFFImage };\nexport { BaseClient, BaseResponse };\n//# sourceMappingURL=geotiff.js.map","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { fromArrayBuffer } from 'geotiff';\n\nimport { GeoTiffTable } from '../../../shared/interfaces';\nimport { LoadGeoTiffParams } from './interfaces';\nimport { DEFALT_COORDINATE_FORMAT } from '../../../shared/consts';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\n\nconst DEFAULT_MAX_PIXELS = 500_000;\n\n/**\n * Loads a GeoTIFF raster file into DuckDB as a spatially-indexed table.\n */\nexport class LoadGeoTiffUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n }\n\n async exec(params: LoadGeoTiffParams): Promise<GeoTiffTable> {\n const {\n geotiffFileUrl,\n geotiffArrayBuffer,\n outputTableName,\n coordinateFormat = DEFALT_COORDINATE_FORMAT,\n sourceCrs,\n workspace = 'main',\n boundingBox,\n maxPixels = DEFAULT_MAX_PIXELS,\n } = params;\n\n if (!geotiffFileUrl && !geotiffArrayBuffer) {\n throw new Error('Either geotiffFileUrl or geotiffArrayBuffer must be provided.');\n }\n if (geotiffFileUrl && geotiffArrayBuffer) {\n throw new Error('Cannot provide both geotiffFileUrl and geotiffArrayBuffer.');\n }\n\n const qualifiedTableName = `${workspace}.${outputTableName}`;\n const csvFile = `_geotiff_${Date.now()}_${Math.random().toString(36).substring(2, 7)}.csv`;\n\n // 1. Obtain the file buffer\n let buffer: ArrayBuffer;\n if (geotiffFileUrl) {\n const response = await fetch(geotiffFileUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch GeoTIFF from ${geotiffFileUrl}: HTTP ${response.status}`);\n }\n buffer = await response.arrayBuffer();\n } else {\n buffer = geotiffArrayBuffer!;\n }\n\n // 2. Parse metadata with geotiff.js\n const tiff = await fromArrayBuffer(buffer);\n const image = await tiff.getImage(0);\n\n const origin = image.getOrigin(); // [originX, originY] — top-left corner in source CRS\n const resolution = image.getResolution(); // [resX, resY] — resY is negative\n const originX = origin[0];\n const originY = origin[1];\n const resX = resolution[0];\n const resY = resolution[1]; // negative\n const fullWidth = Number(image.getWidth());\n const fullHeight = Number(image.getHeight());\n const bandCount = Number(image.getSamplesPerPixel());\n\n // 3. Compute pixel window from optional bounding box\n // Detect 0-360 longitude convention: originX >= 0 and raster spans > 180 degrees\n const rasterMaxX = originX + fullWidth * resX;\n const is0To360 = originX >= 0 && rasterMaxX > 180;\n\n let window: [number, number, number, number] | undefined;\n if (boundingBox) {\n let minLon = boundingBox.minLon;\n let maxLon = boundingBox.maxLon;\n\n // Convert -180/180 bounding box to 0-360 if the raster uses that convention\n if (is0To360) {\n if (minLon < 0) minLon += 360;\n if (maxLon < 0) maxLon += 360;\n }\n\n const xMin = Math.max(0, Math.floor((minLon - originX) / resX));\n const xMax = Math.min(fullWidth, Math.ceil((maxLon - originX) / resX));\n // resY is negative so the lat comparison is inverted\n const yMin = Math.max(0, Math.floor((boundingBox.maxLat - originY) / resY));\n const yMax = Math.min(fullHeight, Math.ceil((boundingBox.minLat - originY) / resY));\n if (xMin >= xMax || yMin >= yMax) {\n console.warn(\n `[LoadGeoTiff] Bounding box does not overlap with raster extent — loading full raster. ` +\n `Computed window [${xMin}, ${yMin}, ${xMax}, ${yMax}] is invalid. ` +\n `Raster uses ${is0To360 ? '0–360' : '-180–180'} longitude convention, ` +\n `origin: (${originX}, ${originY}), size: ${fullWidth}×${fullHeight}.`\n );\n } else {\n window = [xMin, yMin, xMax, yMax];\n }\n }\n\n const windowWidth = window ? window[2] - window[0] : fullWidth;\n const windowHeight = window ? window[3] - window[1] : fullHeight;\n const pixelCount = windowWidth * windowHeight;\n\n if (pixelCount > maxPixels) {\n throw new Error(\n `GeoTIFF region is ${pixelCount.toLocaleString()} pixels, which exceeds the limit of ` +\n `${maxPixels.toLocaleString()}. Supply a 'boundingBox' to clip to a smaller area, ` +\n `or increase 'maxPixels' if your environment can handle it.`\n );\n }\n\n // 4. Decode pixel data (optionally windowed)\n const rasters = await image.readRasters({ window });\n const colOffset = window ? window[0] : 0;\n const rowOffset = window ? window[1] : 0;\n\n // 5. Collect band arrays\n const bandNames: string[] = [];\n const bandData: Array<ArrayLike<number>> = [];\n for (let b = 0; b < bandCount; b++) {\n bandNames.push(`band_${b + 1}`);\n bandData.push((rasters as unknown as Array<ArrayLike<number>>)[b]);\n }\n\n // 6. Build CSV: header + one row per pixel\n const header = ['lon', 'lat', ...bandNames].join(',');\n const lines: string[] = [header];\n for (let row = 0; row < windowHeight; row++) {\n for (let col = 0; col < windowWidth; col++) {\n const idx = row * windowWidth + col;\n const lon = originX + (colOffset + col + 0.5) * resX;\n const lat = originY + (rowOffset + row + 0.5) * resY;\n const bands = bandData.map((b) => { const v = b[idx]; return isNaN(v) ? '' : v; }).join(',');\n lines.push(`${lon},${lat},${bands}`);\n }\n }\n\n await this.db.registerFileText(csvFile, lines.join('\\n'));\n\n try {\n // 7. Build geometry expression with optional CRS reprojection\n const shouldTransform = sourceCrs && sourceCrs !== coordinateFormat;\n const geomExpr = shouldTransform\n ? `ST_Transform(ST_Point(lon, lat), '${sourceCrs}', '${coordinateFormat}', always_xy := true)`\n : `ST_Point(lon, lat)`;\n\n const propertiesExpr =\n bandNames.length > 0\n ? `{${bandNames.map((n) => `'${n}': \"${n}\"`).join(', ')}}`\n : `NULL::JSON`;\n\n // 8. Create the final table from the CSV\n await this.conn.query(`\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT\n ${geomExpr} AS geometry,\n ${propertiesExpr} AS properties\n FROM read_csv('${csvFile}', header=true, delim=',');\n `);\n\n // 9. Spatial index for query performance\n await this.conn.query(\n `CREATE INDEX idx_${outputTableName}_geometry ON ${qualifiedTableName} USING RTREE (geometry);`\n );\n\n const describeResult = await this.conn.query(`DESCRIBE ${qualifiedTableName};`);\n return {\n source: 'geotiff',\n type: 'raster',\n name: outputTableName,\n columns: getColumnsFromDuckDbTableDescribe(describeResult.toArray()),\n };\n } finally {\n await this.db.dropFile(csvFile);\n }\n }\n}\n","/**\n * Custom error types for raw query validation.\n */\n\nexport class NonSelectQueryError extends Error {\n constructor() {\n super('Only SELECT queries are allowed for raw queries.');\n this.name = 'NonSelectQueryError';\n }\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { RawQueryParams, RawQueryOutput } from './interfaces';\nimport { NonSelectQueryError } from './errors';\nimport { Table } from '../../../shared/interfaces';\nimport { getColumnsFromDuckDbTableDescribe, toPlain } from '../../shared/utils';\n\n/**\n * Executes a raw SQL query with safety validation against mutation statements.\n */\nexport class RawQueryUseCase {\n private conn: AsyncDuckDBConnection;\n\n constructor(conn: AsyncDuckDBConnection) {\n this.conn = conn;\n }\n\n async exec(params: RawQueryParams): Promise<Table | RawQueryOutput> {\n this.validateQuery(params.query);\n\n if (params.output.type === 'CREATE_TABLE') {\n if (!params.output.tableName) {\n throw new Error('output.tableName must be provided when output.type is \"CREATE_TABLE\"');\n }\n\n const tableName = params.output.tableName;\n\n const createTableQuery = `CREATE OR REPLACE TABLE ${tableName} AS\\n${params.query};\\n\\nDESCRIBE ${tableName};`;\n\n const describeResult = await this.conn.query(createTableQuery);\n\n const table = {\n source: params.output.source || 'user',\n type: params.output.tableType || 'pointset',\n name: tableName,\n columns: getColumnsFromDuckDbTableDescribe(describeResult.toArray()),\n } as unknown as Table;\n\n return table;\n }\n\n const res = await this.conn.query(params.query);\n return res.toArray().map((row) => toPlain(row.toJSON())) as RawQueryOutput;\n }\n\n private validateQuery(query: string) {\n const q = query.trim().toLowerCase();\n\n // Allow queries that start with SELECT or WITH (CTE followed by SELECT)\n const isSelectLike = q.startsWith('select') || q.startsWith('with');\n\n const forbidden = ['insert', 'update', 'delete', 'create', 'alter', 'drop', 'truncate', 'replace'];\n const hasForbidden = forbidden.some((word) => new RegExp(`\\\\b${word}\\\\b`, 'i').test(q));\n\n if (!isSelectLike || hasForbidden) {\n throw new NonSelectQueryError();\n }\n }\n}\n","export const GET_BOUNDING_BOX_FROM_OSM_QUERY = (osmTableName: string, workspace: string) => {\n const qualifiedTableName = `${workspace}.${osmTableName}`;\n return `\n SELECT \n CAST(MIN(lon) AS DOUBLE) as minLon,\n CAST(MIN(lat) AS DOUBLE) as minLat,\n CAST(MAX(lon) AS DOUBLE) as maxLon,\n CAST(MAX(lat) AS DOUBLE) as maxLat\n FROM ${qualifiedTableName}\n WHERE lat IS NOT NULL AND lon IS NOT NULL;\n `;\n};\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { BoundingBox } from '../../../../shared/interfaces';\nimport { GetBoundingBoxFromOsmParams } from './interfaces';\nimport { GET_BOUNDING_BOX_FROM_OSM_QUERY } from './queries';\n\n/**\n * Computes the geographic bounding box of an OSM boundary table.\n */\nexport class GetBoundingBoxFromOsmUseCase {\n constructor(private conn: AsyncDuckDBConnection) {}\n\n /**\n * Queries the spatial extent of boundary way geometries in an OSM table.\n *\n * @param params.osmTableName Name of the OSM boundaries table.\n * @param params.workspace Optional workspace name (defaults to `main`).\n * @returns Named bounding box.\n * @throws If the table has no coordinates or invalid values.\n */\n async exec(params: GetBoundingBoxFromOsmParams): Promise<BoundingBox> {\n const workspace = params.workspace || 'main';\n const result = await this.conn.query(GET_BOUNDING_BOX_FROM_OSM_QUERY(params.osmTableName, workspace));\n const rows = result.toArray();\n\n if (rows.length === 0) {\n throw new Error(`Could not calculate bounding box - no coordinates found in table ${params.osmTableName}`);\n }\n\n const row = rows[0];\n\n if (row.minLon == null || row.minLat == null || row.maxLon == null || row.maxLat == null) {\n throw new Error(`Could not calculate bounding box - invalid coordinates found in table ${params.osmTableName}`);\n }\n\n return {\n minLon: row.minLon,\n minLat: row.minLat,\n maxLon: row.maxLon,\n maxLat: row.maxLat,\n };\n }\n}\n","export const LOAD_POLYGONIZED_LAYER_QUERY = (\n featureCollectionTableName: string,\n outputTableName: string,\n workspace: string,\n) => {\n const qualifiedFeatureCollectionTableName = `${workspace}.${featureCollectionTableName}`;\n const qualifiedOutputTableName = `${workspace}.${outputTableName}`;\n \n return `\n CREATE OR REPLACE TABLE ${qualifiedOutputTableName} AS\n SELECT\n ST_GeomFromGeoJSON(JSON(feature.geometry)) AS geometry,\n feature.properties AS properties\n FROM (\n SELECT UNNEST(features) AS feature\n FROM ${qualifiedFeatureCollectionTableName}\n );\n\n DROP TABLE ${qualifiedFeatureCollectionTableName};\n\n DESCRIBE ${qualifiedOutputTableName};\n `;\n};\n\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { FeatureCollection, LineString, Polygon } from 'geojson';\nimport { polygonize } from '@turf/turf';\n\nimport { PolygonizeSurfaceLayerParams } from './interfaces';\nimport { LayerTable } from '../../../shared/interfaces';\nimport { GetLayerGeojsonUseCase } from '../get-layer-geojson';\nimport { LOAD_FEATURE_COLLECTION_QUERY } from '../load-custom-layer/queries';\nimport { LOAD_POLYGONIZED_LAYER_QUERY } from './queries';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\n\n/**\n * Polygonizes a surface layer from line geometries into closed polygons.\n */\nexport class PolygonizeSurfaceLayerUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n private getLayerGeojsonUseCase: GetLayerGeojsonUseCase;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n this.getLayerGeojsonUseCase = new GetLayerGeojsonUseCase(conn);\n }\n\n async exec(params: PolygonizeSurfaceLayerParams, surfaceTable: LayerTable): Promise<LayerTable> {\n const { surfaceTableName, workspace = 'main' } = params;\n const qualifiedSurfaceTableName = `${workspace}.${surfaceTableName}`;\n const qualifiedFeatureCollectionTableName = `${workspace}.${surfaceTableName}_feature_collection`;\n\n const geojson = await this.getLayerGeojsonUseCase.exec(surfaceTable, workspace) as FeatureCollection<LineString>;\n const polygonizedGeojson = polygonize(geojson) as FeatureCollection<Polygon>;\n\n await this.conn.query(`DROP TABLE IF EXISTS ${qualifiedSurfaceTableName};`);\n await this.conn.query(`DROP TABLE IF EXISTS ${qualifiedFeatureCollectionTableName};`);\n\n const fileName = `temp_polygonized_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.json`;\n\n await this.db.registerFileText(fileName, JSON.stringify(polygonizedGeojson));\n\n const featureCollectionQuery = LOAD_FEATURE_COLLECTION_QUERY(fileName, `${surfaceTableName}_feature_collection`, workspace);\n await this.conn.query(featureCollectionQuery);\n\n const queryLayer = LOAD_POLYGONIZED_LAYER_QUERY(\n `${surfaceTableName}_feature_collection`,\n surfaceTableName,\n workspace,\n );\n\n const describeTableResponse = await this.conn.query(queryLayer);\n await this.db.dropFile(fileName);\n\n console.log('Loaded polygonized layer!');\n\n return {\n source: 'osm',\n type: 'surface',\n columns: getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray()),\n name: surfaceTableName,\n };\n }\n}\n"," \nimport { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { BuildHeatmapParams } from './interfaces';\nimport { BoundingBox, Table } from '../../../shared/interfaces';\nimport { LoadGridLayerUseCase } from '../load-grid-layer/LoadGridLayerUseCase';\nimport { SpatialJoinUseCase } from '../spatial-join/SpatialJoinUseCase';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\n\n/**\n * Builds a heatmap grid by spatially joining source data into grid cells.\n */\nexport class BuildHeatmapUseCase {\n private loadGridLayerUseCase: LoadGridLayerUseCase;\n private spatialJoinUseCase: SpatialJoinUseCase;\n\n constructor(private conn: AsyncDuckDBConnection) {\n this.loadGridLayerUseCase = new LoadGridLayerUseCase(conn);\n this.spatialJoinUseCase = new SpatialJoinUseCase(conn);\n }\n\n async exec(\n params: BuildHeatmapParams,\n tables: Array<Table>,\n boundingBox?: BoundingBox,\n ): Promise<Table> {\n if (!boundingBox) {\n throw new Error('Bounding box is required to build a heatmap.');\n }\n\n const sourceTable = tables.find((t) => t.name === params.tableJoinName);\n if (!sourceTable) {\n throw new Error(`Table ${params.tableJoinName} not found.`);\n }\n\n const gridTableName = params.outputTableName;\n const gridTable = await this.loadGridLayerUseCase.exec({\n boundingBox,\n rows: params.grid.rows,\n columns: params.grid.columns,\n outputTableName: gridTableName,\n });\n\n const joinResult = await this.spatialJoinUseCase.exec(\n {\n tableRootName: gridTableName,\n tableJoinName: params.tableJoinName,\n joinType: 'LEFT',\n spatialPredicate: 'NEAR',\n nearDistance: params.nearDistance,\n groupBy: params.groupBy,\n output: {\n type: 'MODIFY_ROOT',\n },\n },\n [...tables, gridTable],\n );\n\n await this.transformToRasterFormat(\n gridTableName,\n params.grid.rows,\n params.grid.columns\n );\n\n // Get updated columns after transformation\n const describeTableResponse = await this.conn.query(`DESCRIBE ${gridTableName}`);\n const updatedColumns = getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray());\n\n return {\n ...joinResult.table,\n columns: updatedColumns,\n };\n }\n\n private async transformToRasterFormat(\n tableName: string,\n rows: number,\n columns: number\n ): Promise<void> {\n const transformQuery = `\n CREATE OR REPLACE TABLE ${tableName} AS\n SELECT \n ST_Point(0, 0) AS geometry,\n {\n 'raster': list(properties.sjoin ORDER BY CAST(properties->>'row' AS INTEGER), CAST(properties->>'column' AS INTEGER)),\n 'rasterResX': ${columns},\n 'rasterResY': ${rows}\n } AS properties\n FROM ${tableName};\n `;\n\n await this.conn.query(transformQuery);\n }\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { GetTableDataParams, GetTableDataOutput } from './interfaces';\nimport { toPlain } from '../../shared/utils';\n\n/**\n * Reads rows from any table as plain JavaScript objects.\n */\nexport class GetTableDataUseCase {\n private conn: AsyncDuckDBConnection;\n\n constructor(conn: AsyncDuckDBConnection) {\n this.conn = conn;\n }\n\n async exec(params: GetTableDataParams): Promise<GetTableDataOutput> {\n const workspace = params.workspace || 'main';\n const qualifiedTableName = `${workspace}.${params.tableName}`;\n let query = `SELECT * FROM ${qualifiedTableName}`;\n\n if (params.limit !== undefined) {\n query += ` LIMIT ${params.limit}`;\n }\n\n if (params.offset !== undefined) {\n query += ` OFFSET ${params.offset}`;\n }\n\n const result = await this.conn.query(query);\n return result.toArray().map((row) => toPlain(row.toJSON())) as GetTableDataOutput;\n }\n}\n\n","import { FeatureCollection } from 'geojson';\nimport { Table, Column } from '../../../shared/interfaces';\n\nexport type UpdateStrategy = 'replace' | 'update';\n\nexport interface UpdateTableParams {\n tableName: string;\n data: FeatureCollection | Record<string, unknown>[];\n /**\n * Strategy for updating the table:\n * - 'replace': Drop and recreate the entire table with the new data\n * - 'update': Update existing records by ID (does NOT insert new records)\n */\n strategy: UpdateStrategy;\n /**\n * Required when strategy is 'update'.\n * Supports:\n * - Direct column: 'id' → matches on the id column directly\n * - Nested in properties: 'properties.building_id' → matches on properties->>'building_id'\n */\n idColumn?: string;\n workspace?: string;\n}\n\nexport interface UpdateTableResult {\n table: Table;\n updatedColumns: Column[];\n}\n\n/**\n * Parses the idColumn parameter to determine if it's a direct column or nested in properties.\n * @param idColumn - The id column specification (e.g., 'id' or 'properties.building_id')\n * @returns An object with the column expression for SQL and whether it's in properties\n */\nexport function parseIdColumn(idColumn: string): { \n isPropertiesPath: boolean; \n columnName: string;\n sqlExpression: string;\n} {\n if (idColumn.startsWith('properties.')) {\n const propertyKey = idColumn.slice('properties.'.length);\n return {\n isPropertiesPath: true,\n columnName: propertyKey,\n sqlExpression: `properties->>'${propertyKey}'`,\n };\n }\n \n return {\n isPropertiesPath: false,\n columnName: idColumn,\n sqlExpression: idColumn,\n };\n}\n","/**\n * Query to create a temporary table from a GeoJSON file for layer updates.\n * Transforms GeoJSON features into the internal layer format (geometry + properties).\n */\nexport const REPLACE_LAYER_TABLE_QUERY = (\n tempFileName: string,\n tableName: string,\n workspace: string,\n) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n \n return `\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT\n ST_GeomFromGeoJSON(JSON(feature.geometry)) AS geometry,\n CAST(feature.properties AS JSON) AS properties\n FROM (\n SELECT UNNEST(features) AS feature\n FROM read_json_auto('${tempFileName}')\n );\n \n DESCRIBE ${qualifiedTableName};\n `;\n};\n\n/**\n * Query to replace a non-layer table (CSV/JSON) with new data.\n * Data is inserted directly without geometry transformation.\n */\nexport const REPLACE_DATA_TABLE_QUERY = (\n tempFileName: string,\n tableName: string,\n workspace: string,\n) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n \n return `\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT * FROM read_json_auto('${tempFileName}');\n \n DESCRIBE ${qualifiedTableName};\n `;\n};\n\n/**\n * Query to load GeoJSON features into a temporary staging table for upsert operations.\n */\nexport const CREATE_LAYER_STAGING_TABLE_QUERY = (\n tempFileName: string,\n stagingTableName: string,\n) => {\n return `\n CREATE OR REPLACE TEMP TABLE ${stagingTableName} AS\n SELECT\n ST_GeomFromGeoJSON(JSON(feature.geometry)) AS geometry,\n CAST(feature.properties AS JSON) AS properties\n FROM (\n SELECT UNNEST(features) AS feature\n FROM read_json_auto('${tempFileName}')\n );\n `;\n};\n\n/**\n * Query to load JSON array into a temporary staging table for upsert operations.\n */\nexport const CREATE_DATA_STAGING_TABLE_QUERY = (\n tempFileName: string,\n stagingTableName: string,\n) => {\n return `\n CREATE OR REPLACE TEMP TABLE ${stagingTableName} AS\n SELECT * FROM read_json_auto('${tempFileName}');\n `;\n};\n\n/**\n * Query to update existing layer records (geometry and properties) based on ID match.\n * Used for upsert operations on layer tables.\n */\nexport const UPDATE_LAYER_FROM_STAGING_QUERY = (\n tableName: string,\n stagingTableName: string,\n idSqlExpression: string,\n workspace: string,\n) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n \n // Use explicit column references without table alias for the JSON expression\n // to avoid syntax issues with DuckDB's JSON operators\n return `\n UPDATE ${qualifiedTableName}\n SET \n geometry = staging.geometry,\n properties = staging.properties\n FROM ${stagingTableName} AS staging\n WHERE ${qualifiedTableName}.${idSqlExpression} = staging.${idSqlExpression};\n `;\n};\n\n/**\n * Query to delete matching records from target table based on IDs in staging table.\n */\nexport const DELETE_MATCHING_IDS_QUERY = (\n tableName: string,\n stagingTableName: string,\n idSqlExpression: string,\n workspace: string,\n) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n \n return `\n DELETE FROM ${qualifiedTableName}\n WHERE ${idSqlExpression} IN (\n SELECT ${idSqlExpression} FROM ${stagingTableName}\n );\n `;\n};\n\n/**\n * Query to insert all records from staging table into target table.\n * Only works when staging table has same columns as target table.\n */\nexport const INSERT_FROM_STAGING_QUERY = (\n tableName: string,\n stagingTableName: string,\n workspace: string,\n) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n \n return `\n INSERT INTO ${qualifiedTableName}\n SELECT * FROM ${stagingTableName};\n `;\n};\n\n/**\n * Query to insert layer records (geometry, properties) from staging into target.\n * Used for inserting new records that don't exist in target.\n */\nexport const INSERT_LAYER_FROM_STAGING_QUERY = (\n tableName: string,\n stagingTableName: string,\n idSqlExpression: string,\n workspace: string,\n) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n \n return `\n INSERT INTO ${qualifiedTableName} (geometry, properties)\n SELECT staging.geometry, staging.properties\n FROM ${stagingTableName} AS staging\n WHERE NOT EXISTS (\n SELECT 1 FROM ${qualifiedTableName} AS target\n WHERE target.${idSqlExpression} = staging.${idSqlExpression}\n );\n `;\n};\n\n/**\n * Query to drop the staging table after upsert operation.\n */\nexport const DROP_STAGING_TABLE_QUERY = (stagingTableName: string) => {\n return `DROP TABLE IF EXISTS ${stagingTableName};`;\n};\n\n/**\n * Query to describe a table and get its column information.\n */\nexport const DESCRIBE_TABLE_QUERY = (tableName: string, workspace: string) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `DESCRIBE ${qualifiedTableName};`;\n};\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { FeatureCollection } from 'geojson';\n\nimport { Table } from '../../../shared/interfaces';\nimport { UpdateTableParams, UpdateTableResult, parseIdColumn } from './interfaces';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport {\n REPLACE_LAYER_TABLE_QUERY,\n REPLACE_DATA_TABLE_QUERY,\n CREATE_LAYER_STAGING_TABLE_QUERY,\n CREATE_DATA_STAGING_TABLE_QUERY,\n DELETE_MATCHING_IDS_QUERY,\n INSERT_FROM_STAGING_QUERY,\n UPDATE_LAYER_FROM_STAGING_QUERY,\n DROP_STAGING_TABLE_QUERY,\n DESCRIBE_TABLE_QUERY,\n} from './queries';\n\n/**\n * Updates an existing table with new data, supporting replace and update-by-id strategies.\n */\nexport class UpdateTableUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n }\n\n async exec(params: UpdateTableParams, existingTable: Table): Promise<UpdateTableResult> {\n const { strategy, workspace = 'main' } = params;\n\n if (strategy === 'update' && !params.idColumn) {\n throw new Error('idColumn is required when using the update strategy');\n }\n\n const isLayerTable = this.isLayerTable(existingTable);\n\n if (strategy === 'replace') {\n return this.executeReplaceStrategy(params, existingTable, isLayerTable, workspace);\n } else {\n return this.executeUpdateStrategy(params, existingTable, isLayerTable, workspace);\n }\n }\n\n /**\n * Determines if a table is a layer table (has geometry) based on its source.\n */\n private isLayerTable(table: Table): boolean {\n return table.source === 'osm' || table.source === 'geojson';\n }\n\n /**\n * Validates that the input data format matches the table type.\n */\n private validateDataFormat(data: FeatureCollection | Record<string, unknown>[], isLayerTable: boolean): void {\n if (isLayerTable) {\n if (!this.isFeatureCollection(data)) {\n throw new Error('Layer tables require a GeoJSON FeatureCollection as input data');\n }\n } else {\n if (this.isFeatureCollection(data)) {\n throw new Error('Non-layer tables (CSV/JSON) require an array of objects as input data');\n }\n }\n }\n\n /**\n * Type guard to check if data is a FeatureCollection.\n */\n private isFeatureCollection(data: unknown): data is FeatureCollection {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'type' in data &&\n (data as FeatureCollection).type === 'FeatureCollection' &&\n 'features' in data &&\n Array.isArray((data as FeatureCollection).features)\n );\n }\n\n /**\n * Creates a temporary file with the data and returns the file name.\n */\n private async createTempFile(data: FeatureCollection | Record<string, unknown>[]): Promise<string> {\n const fileName = `temp_update_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.json`;\n await this.db.registerFileText(fileName, JSON.stringify(data));\n return fileName;\n }\n\n /**\n * Cleans up the temporary file.\n */\n private async cleanupTempFile(fileName: string): Promise<void> {\n try {\n await this.db.dropFile(fileName);\n } catch {\n // Ignore errors during cleanup\n }\n }\n\n /**\n * Executes the replace strategy: drop and recreate the table with new data.\n */\n private async executeReplaceStrategy(\n params: UpdateTableParams,\n existingTable: Table,\n isLayerTable: boolean,\n workspace: string,\n ): Promise<UpdateTableResult> {\n const { tableName, data } = params;\n\n this.validateDataFormat(data, isLayerTable);\n\n const tempFileName = await this.createTempFile(data);\n\n try {\n let query: string;\n if (isLayerTable) {\n query = REPLACE_LAYER_TABLE_QUERY(tempFileName, tableName, workspace);\n } else {\n query = REPLACE_DATA_TABLE_QUERY(tempFileName, tableName, workspace);\n }\n\n const describeResult = await this.conn.query(query);\n const updatedColumns = getColumnsFromDuckDbTableDescribe(describeResult.toArray());\n\n const updatedTable: Table = {\n ...existingTable,\n columns: updatedColumns,\n };\n\n return {\n table: updatedTable,\n updatedColumns,\n };\n } finally {\n await this.cleanupTempFile(tempFileName);\n }\n }\n\n /**\n * Executes the update strategy: update existing records by ID.\n * Does NOT insert new records - only modifies records that already exist.\n */\n private async executeUpdateStrategy(\n params: UpdateTableParams,\n existingTable: Table,\n isLayerTable: boolean,\n workspace: string,\n ): Promise<UpdateTableResult> {\n const { tableName, data, idColumn } = params;\n\n this.validateDataFormat(data, isLayerTable);\n\n const { sqlExpression } = parseIdColumn(idColumn!);\n const stagingTableName = `_staging_${tableName}_${Date.now()}`;\n const tempFileName = await this.createTempFile(data);\n\n try {\n // 1. Create staging table with transformed data\n let createStagingQuery: string;\n if (isLayerTable) {\n createStagingQuery = CREATE_LAYER_STAGING_TABLE_QUERY(tempFileName, stagingTableName);\n } else {\n createStagingQuery = CREATE_DATA_STAGING_TABLE_QUERY(tempFileName, stagingTableName);\n }\n await this.conn.query(createStagingQuery);\n\n if (isLayerTable) {\n // For layer tables: UPDATE existing records only\n // We can't INSERT new records because OSM layers require columns (id, refs)\n // that we don't have in the GeoJSON data\n const updateQuery = UPDATE_LAYER_FROM_STAGING_QUERY(tableName, stagingTableName, sqlExpression, workspace);\n await this.conn.query(updateQuery);\n } else {\n // For non-layer tables: DELETE + INSERT (full row replacement)\n \n // 2. Delete matching records from target table\n const deleteQuery = DELETE_MATCHING_IDS_QUERY(tableName, stagingTableName, sqlExpression, workspace);\n await this.conn.query(deleteQuery);\n\n // 3. Insert all records from staging table\n const insertQuery = INSERT_FROM_STAGING_QUERY(tableName, stagingTableName, workspace);\n await this.conn.query(insertQuery);\n }\n\n // 4. Clean up staging table\n const dropStagingQuery = DROP_STAGING_TABLE_QUERY(stagingTableName);\n await this.conn.query(dropStagingQuery);\n\n // 5. Get updated column information\n const describeQuery = DESCRIBE_TABLE_QUERY(tableName, workspace);\n const describeResult = await this.conn.query(describeQuery);\n const updatedColumns = getColumnsFromDuckDbTableDescribe(describeResult.toArray());\n\n const updatedTable: Table = {\n ...existingTable,\n columns: updatedColumns,\n };\n\n return {\n table: updatedTable,\n updatedColumns,\n };\n } finally {\n await this.cleanupTempFile(tempFileName);\n // Ensure staging table is dropped even on error\n try {\n await this.conn.query(DROP_STAGING_TABLE_QUERY(stagingTableName));\n } catch {\n // Ignore errors during cleanup\n }\n }\n }\n}\n"," \nimport { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { CsvTable, CustomLayerTable, LayerTable, JsonTable, Table } from '../shared/interfaces';\nimport { loadDb } from '../config/duckdb';\nimport { LoadLayerUseCase, LoadLayerParams } from './use-cases/load-layer';\nimport { LoadCsvUseCase, LoadCsvParams } from './use-cases/load-csv';\nimport { LoadJsonUseCase, LoadJsonParams } from './use-cases/load-json';\nimport { GetLayerGeojsonUseCase } from './use-cases/get-layer-geojson';\nimport { FeatureCollection } from 'geojson';\nimport { isLayerType } from 'autk-core';\nimport { LoadCustomLayerParams, LoadCustomLayerUseCase } from './use-cases/load-custom-layer';\nimport { AssignBuildingIdsUseCase } from './use-cases/assign-building-ids/AssignBuildingIdsUseCase';\nimport { SpatialQueryParams } from './use-cases/spatial-join/interfaces';\nimport { SpatialJoinUseCase } from './use-cases/spatial-join/SpatialJoinUseCase';\nimport { DropTableUseCase } from './shared/use-cases/drop-table/DropTableUseCase';\nimport { BoundingBox } from '../shared/interfaces';\nimport { TransformBoundingBoxCoordinatesUseCase } from './shared/use-cases/transform-bounding-box-coordinates/TransformBoundingBoxCoordinatesUseCase';\nimport { GetBoundingBoxFromLayerUseCase } from './shared/use-cases/get-bounding-box-from-layer/GetBoundingBoxFromLayerUseCase';\nimport { LoadOsmParams, LoadOsmFromOverpassApiUseCase } from './use-cases/load-osm-from-overpass-api';\nimport { LoadOsmFromPbfUseCase } from './use-cases/load-osm-from-pbf';\nimport { OsmProcessingPipeline } from './use-cases/osm-processing-pipeline/OsmProcessingPipeline';\nimport type { OsmLoadTimings } from './use-cases/load-osm-from-overpass-api/interfaces';\nimport { LoadGridLayerParams, LoadGridLayerUseCase } from './use-cases/load-grid-layer/LoadGridLayerUseCase';\nimport { GridLayerTable, GeoTiffTable } from '../shared/interfaces';\nimport { LoadGeoTiffUseCase, LoadGeoTiffParams } from './use-cases/load-geotiff';\nimport { RawQueryOutput, RawQueryParams } from './use-cases/raw-query/interfaces';\nimport { RawQueryUseCase } from './use-cases/raw-query';\nimport { GetBoundingBoxFromOsmUseCase } from './shared/use-cases/get-bounding-box-from-osm/GetBoundingBoxFromOsmUseCase';\nimport { PolygonizeSurfaceLayerUseCase } from './use-cases/polygonize-surface-layer';\nimport { BuildHeatmapParams, BuildHeatmapUseCase } from './use-cases/build-heatmap';\nimport { GetTableDataParams, GetTableDataOutput, GetTableDataUseCase } from './use-cases/get-table-data';\nimport { UpdateTableUseCase, UpdateTableParams } from './use-cases/update-table';\nimport { toPlain } from './shared/utils';\n\ninterface WorkspaceData {\n tables: Array<Table>;\n osmBoundingBox?: BoundingBox;\n osmBoundingBoxWgs84?: BoundingBox;\n}\n\n/**\n * SpatialDb class provides methods to interact with a DuckDB database for spatial data operations.\n *\n * It allows loading OSM data, CSV, JSON, custom layers, and grid layers,\n * as well as performing spatial joins and raw queries.\n * DuckDB-backed spatial database for OSM, CSV, JSON, and raster data.\n *\n * Supports multiple isolated workspaces, each with its own schema and tables.\n *\n * @example\n * const db = new AutkSpatialDb();\n * await db.init();\n * const layer = await db.getLayer('osm_buildings');\n */\nexport class AutkSpatialDb {\n private db?: AsyncDuckDB;\n private conn?: AsyncDuckDBConnection;\n private currentWorkspace: string = 'main';\n private workspaces: Map<string, WorkspaceData> = new Map();\n \n public get tables(): Array<Table> {\n return this.getCurrentWorkspaceData().tables;\n }\n \n private osmProcessingPipeline?: OsmProcessingPipeline;\n private loadOsmFromOverpassApiUseCase?: LoadOsmFromOverpassApiUseCase;\n private loadOsmFromPbfUseCase?: LoadOsmFromPbfUseCase;\n private loadCsvUseCase?: LoadCsvUseCase;\n private loadLayerUseCase?: LoadLayerUseCase;\n private loadCustomLayerUseCase?: LoadCustomLayerUseCase;\n private assignBuildingIdsUseCase?: AssignBuildingIdsUseCase;\n private loadJsonUseCase?: LoadJsonUseCase;\n private getLayerGeojsonUseCase?: GetLayerGeojsonUseCase;\n private spatialJoinUseCase?: SpatialJoinUseCase;\n private getBoundingBoxFromLayerUseCase?: GetBoundingBoxFromLayerUseCase;\n private dropTableUseCase?: DropTableUseCase;\n private transformBoundingBoxCoordinatesUseCase?: TransformBoundingBoxCoordinatesUseCase;\n private loadGridLayerUseCase?: LoadGridLayerUseCase;\n private loadGeoTiffUseCase?: LoadGeoTiffUseCase;\n private rawQueryUseCase?: RawQueryUseCase;\n private getBoundingBoxFromOsmUseCase?: GetBoundingBoxFromOsmUseCase;\n private polygonizeSurfaceLayerUseCase?: PolygonizeSurfaceLayerUseCase;\n private buildHeatmapUseCase?: BuildHeatmapUseCase;\n private getTableDataUseCase?: GetTableDataUseCase;\n private updateTableUseCase?: UpdateTableUseCase;\n\n /**\n * Gets the workspace data for the current workspace.\n * @returns The WorkspaceData for the current workspace.\n * @private\n */\n private getCurrentWorkspaceData(): WorkspaceData {\n const data = this.workspaces.get(this.currentWorkspace);\n if (!data) {\n throw new Error(`Workspace '${this.currentWorkspace}' not found. This should not happen.`);\n }\n return data;\n }\n\n /**\n * Initializes DuckDB, loads the spatial extension, and creates use-case instances.\n *\n * @returns A promise that resolves when initialization is complete.\n * @throws If DuckDB WebAssembly fails to load or the spatial extension cannot be installed.\n * @example\n * await db.init();\n */\n async init() {\n this.db = await loadDb();\n this.conn = await this.db.connect();\n\n // Install and load spatial extension\n await this.conn.query('INSTALL spatial; LOAD spatial;');\n\n // Create main schema and initialize default workspace\n await this.conn.query('CREATE SCHEMA IF NOT EXISTS main');\n this.workspaces.set('main', {\n tables: [],\n osmBoundingBox: undefined,\n });\n\n this.osmProcessingPipeline = new OsmProcessingPipeline(this.db, this.conn);\n this.loadOsmFromOverpassApiUseCase = new LoadOsmFromOverpassApiUseCase(this.conn, this.osmProcessingPipeline);\n this.loadOsmFromPbfUseCase = new LoadOsmFromPbfUseCase(this.conn, this.osmProcessingPipeline);\n this.loadCsvUseCase = new LoadCsvUseCase(this.db, this.conn);\n this.loadJsonUseCase = new LoadJsonUseCase(this.db, this.conn);\n this.loadLayerUseCase = new LoadLayerUseCase(this.db, this.conn);\n this.loadCustomLayerUseCase = new LoadCustomLayerUseCase(this.db, this.conn);\n this.assignBuildingIdsUseCase = new AssignBuildingIdsUseCase(this.db, this.conn);\n this.getLayerGeojsonUseCase = new GetLayerGeojsonUseCase(this.conn);\n this.spatialJoinUseCase = new SpatialJoinUseCase(this.conn);\n this.getBoundingBoxFromLayerUseCase = new GetBoundingBoxFromLayerUseCase(this.conn);\n this.dropTableUseCase = new DropTableUseCase(this.conn);\n this.transformBoundingBoxCoordinatesUseCase = new TransformBoundingBoxCoordinatesUseCase(this.conn);\n this.loadGridLayerUseCase = new LoadGridLayerUseCase(this.conn);\n this.loadGeoTiffUseCase = new LoadGeoTiffUseCase(this.db, this.conn);\n this.rawQueryUseCase = new RawQueryUseCase(this.conn);\n this.getBoundingBoxFromOsmUseCase = new GetBoundingBoxFromOsmUseCase(this.conn);\n this.polygonizeSurfaceLayerUseCase = new PolygonizeSurfaceLayerUseCase(this.db, this.conn);\n this.buildHeatmapUseCase = new BuildHeatmapUseCase(this.conn);\n this.getTableDataUseCase = new GetTableDataUseCase(this.conn);\n this.updateTableUseCase = new UpdateTableUseCase(this.db, this.conn);\n }\n\n /**\n * Switches to a workspace, creating it if it doesn't exist.\n *\n * @param name The name of the workspace to switch to.\n * @returns A promise that resolves when the workspace is set.\n * @throws If the database has not been initialized.\n */\n async setWorkspace(name: string): Promise<void> {\n if (!this.conn) {\n throw new Error('Database not initialized. Please call init() first.');\n }\n\n if (!this.workspaces.has(name)) {\n await this.conn.query(`CREATE SCHEMA IF NOT EXISTS ${name}`);\n this.workspaces.set(name, {\n tables: [],\n osmBoundingBox: undefined,\n });\n }\n\n this.currentWorkspace = name;\n }\n\n /**\n * Gets the list of all available workspaces.\n * @returns An array of workspace names.\n */\n getWorkspaces(): string[] {\n return Array.from(this.workspaces.keys());\n }\n\n /**\n * Gets the name of the current active workspace.\n * @returns The current workspace name.\n */\n getCurrentWorkspace(): string {\n return this.currentWorkspace;\n }\n\n /**\n * Registers a table in the current workspace's tables array. If a table with the same name already exists,\n * it will be replaced and a warning will be logged to the console.\n * @param table - The table to register.\n */\n private _registerTable(table: Table): void {\n const workspaceData = this.getCurrentWorkspaceData();\n const existingIndex = workspaceData.tables.findIndex((t) => t.name === table.name);\n \n if (existingIndex !== -1) {\n console.warn(`Table '${table.name}' already exists in workspace '${this.currentWorkspace}'. Overwriting...`);\n workspaceData.tables[existingIndex] = table;\n } else {\n workspaceData.tables.push(table);\n }\n }\n\n // ---- LOAD's methods\n\n private async clipLayerToSurface(\n layerTableName: string,\n surfaceTableName: string,\n workspace: string,\n cropGeometry: boolean = true,\n ): Promise<void> {\n const qualifiedLayer = `${workspace}.${layerTableName}`;\n const qualifiedSurface = `${workspace}.${surfaceTableName}`;\n const geometrySelect = cropGeometry ? 'ST_Intersection(l.geometry, surf.geom)' : 'l.geometry';\n const emptyFilter = cropGeometry ? 'WHERE NOT ST_IsEmpty(geometry)' : '';\n\n await this.conn!.query(`\n CREATE OR REPLACE TABLE ${qualifiedLayer} AS\n WITH surf AS (\n SELECT ST_Union_Agg(geometry) AS geom FROM ${qualifiedSurface}\n ),\n clipped AS (\n SELECT l.* EXCLUDE (geometry),\n ${geometrySelect} AS geometry\n FROM ${qualifiedLayer} l, surf\n WHERE ST_Intersects(l.geometry, surf.geom)\n )\n SELECT * FROM clipped\n ${emptyFilter};\n `);\n }\n\n /**\n * Loads OSM data from the Overpass API and optionally loads layers based on the provided parameters.\n * When autoLoadLayers is enabled, this method will automatically extract and process specific layers\n * (e.g., buildings, roads, surface) from the OSM data, and optionally polygonize the surface layer.\n *\n * @param params - Parameters for loading OSM data and layers.\n * @returns A promise that resolves when the OSM data and layers are fully loaded.\n * @throws Error if the database or connection is not initialized.\n */\n async loadOsm(params: LoadOsmParams): Promise<OsmLoadTimings> {\n if (\n !this.db ||\n !this.conn ||\n !this.loadOsmFromOverpassApiUseCase ||\n !this.loadOsmFromPbfUseCase ||\n !this.dropTableUseCase ||\n !this.getBoundingBoxFromOsmUseCase ||\n !this.transformBoundingBoxCoordinatesUseCase ||\n !this.polygonizeSurfaceLayerUseCase\n )\n throw new Error('Database not initialized. Please call init() first.');\n\n const execResult = params.pbfFileUrl\n ? await this.loadOsmFromPbfUseCase.exec({ ...params, workspace: this.currentWorkspace })\n : await this.loadOsmFromOverpassApiUseCase.exec({ ...params, workspace: this.currentWorkspace });\n for (const table of execResult.tables) {\n this._registerTable(table);\n }\n\n const timings: OsmLoadTimings = {\n osmElementCount: execResult.osmElementCount,\n boundaryElementCount: execResult.boundaryElementCount,\n osmDataProcessingMs: execResult.osmDataProcessingMs,\n boundariesProcessingMs: execResult.boundariesProcessingMs,\n layers: [],\n };\n\n if (params.autoLoadLayers) {\n const boundaryTableName = `${params.outputTableName}_boundaries`;\n const rawBoundingBox = await this.getBoundingBoxFromOsmUseCase.exec({\n osmTableName: boundaryTableName,\n workspace: this.currentWorkspace\n });\n\n const workspaceData = this.getCurrentWorkspaceData();\n workspaceData.osmBoundingBoxWgs84 = rawBoundingBox;\n workspaceData.osmBoundingBox = await this.transformBoundingBoxCoordinatesUseCase.exec({\n boundingBox: rawBoundingBox,\n coordinateFormat: params.autoLoadLayers.coordinateFormat,\n });\n\n let surfaceLayerName: string | null = null;\n const clippableLayerNames: string[] = [];\n\n for (const layer of params.autoLoadLayers.layers) {\n const shouldCropToBbox = layer !== 'buildings';\n\n const layerParams: LoadLayerParams = {\n osmInputTableName: params.outputTableName,\n coordinateFormat: params.autoLoadLayers.coordinateFormat,\n layer,\n };\n\n layerParams.boundingBox = shouldCropToBbox ? workspaceData.osmBoundingBox : undefined;\n\n const t0 = performance.now();\n const layerTable = await this.loadLayer(layerParams);\n const loadMs = performance.now() - t0;\n\n const countResult = await this.conn.query(\n `SELECT COUNT(*) as cnt FROM ${this.currentWorkspace}.${layerTable.name}`\n );\n const featureCount = Number(countResult.toArray()[0].cnt);\n\n timings.layers.push({ layerName: layerTable.name, layerType: layer, loadMs, featureCount });\n\n // Polygonize surface layer\n if (layer === 'surface') {\n const updatedTable = await this.polygonizeSurfaceLayerUseCase.exec(\n { surfaceTableName: layerTable.name, workspace: this.currentWorkspace },\n layerTable\n );\n const tableIndex = workspaceData.tables.findIndex((t) => t.name === layerTable.name);\n if (tableIndex !== -1) workspaceData.tables[tableIndex] = updatedTable;\n surfaceLayerName = layerTable.name;\n } else {\n clippableLayerNames.push(layerTable.name);\n }\n }\n\n // Clip thematic layers to the surface polygon. Buildings are only filtered by overlap.\n if (surfaceLayerName && clippableLayerNames.length > 0) {\n for (const layerName of clippableLayerNames) {\n const cropGeometry = !layerName.endsWith('_buildings');\n await this.clipLayerToSurface(layerName, surfaceLayerName, this.currentWorkspace, cropGeometry);\n }\n }\n\n if (params.autoLoadLayers.dropOsmTable) {\n for (const table of execResult.tables) {\n await this.dropTableUseCase.exec({ tableName: table.name, workspace: this.currentWorkspace });\n workspaceData.tables = workspaceData.tables.filter((t) => t.name !== table.name);\n }\n }\n\n console.log(`OSM data loaded and completed in workspace '${this.currentWorkspace}'!`);\n }\n\n return timings;\n }\n\n /**\n * Loads a CSV file into the database and returns the created CsvTable.\n * @param params - Parameters for loading the CSV file, including file path and table name.\n * @returns A promise that resolves to the created CsvTable.\n * @throws Error if the database or connection is not initialized.\n */\n async loadCsv(params: LoadCsvParams): Promise<CsvTable> {\n if (!this.db || !this.conn || !this.loadCsvUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const table = await this.loadCsvUseCase.exec({ ...params, workspace: this.currentWorkspace });\n this._registerTable(table);\n\n return table;\n }\n\n /**\n * Loads a JSON file into the database and returns the created JsonTable.\n * @param params - Parameters for loading the JSON file, including file path and table name.\n * @returns A promise that resolves to the created JsonTable.\n * @throws Error if the database or connection is not initialized.\n */\n async loadJson(params: LoadJsonParams): Promise<JsonTable> {\n if (!this.db || !this.conn || !this.loadJsonUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const table = await this.loadJsonUseCase.exec({ ...params, workspace: this.currentWorkspace });\n this._registerTable(table);\n\n return table;\n }\n\n /**\n * Loads a layer from an OSM input table and returns the created LayerTable.\n * @param params - Parameters for loading the layer.\n * @returns A promise that resolves to the created LayerTable.\n * @throws Error if the database or connection is not initialized.\n * @throws Error if the OSM input table is not found or is not of the correct type.\n */\n async loadLayer(params: LoadLayerParams): Promise<LayerTable> {\n if (!this.db || !this.conn || !this.loadLayerUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const osmTable = this.tables.find((t) => t.name === params.osmInputTableName);\n if (!osmTable) throw new Error(`Table ${params.osmInputTableName} not found.`);\n if (!(osmTable.source === 'osm' && osmTable.type === 'pointset'))\n throw new Error(`Table ${params.osmInputTableName} is not an OSM table.`);\n\n const table = await this.loadLayerUseCase.exec({ ...params, workspace: this.currentWorkspace });\n this._registerTable(table);\n\n return table;\n }\n\n /**\n * Loads a custom layer from a GeoJSON file and returns the created CustomLayerTable.\n * If OSM bounding box is available, it will be automatically applied to crop the layer.\n * @param params - Parameters for loading the custom layer, including file path, table name, and layer type.\n * @returns A promise that resolves to the created CustomLayerTable.\n * @throws Error if the database or connection is not initialized.\n */\n async loadCustomLayer(params: LoadCustomLayerParams): Promise<CustomLayerTable> {\n if (!this.db || !this.conn || !this.loadCustomLayerUseCase || !this.assignBuildingIdsUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const workspaceData = this.getCurrentWorkspaceData();\n const table = await this.loadCustomLayerUseCase.exec({ \n ...params, \n boundingBox: workspaceData.osmBoundingBox,\n workspace: this.currentWorkspace \n });\n this._registerTable(table);\n\n // When loading as buildings, compute building_id by clustering overlapping geometries\n if (params.layerType === 'buildings') {\n const columns = await this.assignBuildingIdsUseCase.exec({\n tableName: table.name,\n workspace: this.currentWorkspace,\n });\n table.columns = columns;\n }\n\n return table;\n }\n\n /**\n * Loads a grid layer and returns the created GridLayerTable.\n * If no bounding box is provided in params, the OSM bounding box will be used if available.\n * @param params - Parameters for loading the grid layer, including grid size, cell size, and optional bounding box.\n * @returns A promise that resolves to the created GridLayerTable.\n * @throws Error if the database or connection is not initialized.\n */\n async loadGridLayer(params: LoadGridLayerParams): Promise<GridLayerTable> {\n if (!this.db || !this.conn || !this.loadGridLayerUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const workspaceData = this.getCurrentWorkspaceData();\n const table = await this.loadGridLayerUseCase.exec({\n ...params,\n boundingBox: params.boundingBox || workspaceData.osmBoundingBox,\n workspace: this.currentWorkspace\n });\n this._registerTable(table);\n\n return table;\n }\n\n /**\n * Loads a GeoTIFF raster file into the database.\n * Uses DuckDB's spatial extension (GDAL-backed ST_Read) to parse the file.\n * The resulting table has a `geometry` column (cell centroids) and a\n * `properties` struct column containing one field per raster band.\n * @param params - Parameters including the file URL or ArrayBuffer, output table name,\n * and optional coordinate transformation settings.\n * @returns A promise that resolves to the created GeoTiffTable.\n */\n async loadGeoTiff(params: LoadGeoTiffParams): Promise<GeoTiffTable> {\n if (!this.db || !this.conn || !this.loadGeoTiffUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const table = await this.loadGeoTiffUseCase.exec({\n ...params,\n workspace: this.currentWorkspace,\n });\n this._registerTable(table);\n\n return table;\n }\n\n /**\n * Retrieves a loaded GeoTIFF table as a FeatureCollection suitable for rendering with autk-map.\n *\n * The returned collection has a single feature whose `properties.raster` is an array of per-pixel\n * property objects (one per cell, in row-major top-to-bottom order), plus `rasterResX` / `rasterResY`\n * dimensions and a `bbox`.\n *\n * Pass the result directly to `AutkMap.loadRasterCollection()` and supply a `property` callback that\n * extracts the numeric band value you want to visualise, e.g. `(cell) => cell.band_1 ?? 0`.\n *\n * @param tableName - The name of the GeoTiff table (as given to `loadGeoTiff`).\n * @returns A promise that resolves to a packed raster FeatureCollection.\n */\n async getGeoTiffLayer(tableName: string): Promise<FeatureCollection<null>> {\n if (!this.db || !this.conn)\n throw new Error('Database not initialized. Please call init() first.');\n\n const table = this.tables.find((t) => t.name === tableName);\n if (!table || table.source !== 'geotiff')\n throw new Error(`Table ${tableName} is not a GeoTiff table.`);\n\n const qualifiedName = `${this.currentWorkspace}.${tableName}`;\n\n const result = await this.conn.query(`\n WITH pixels AS (\n SELECT\n t.properties AS properties,\n ST_X(t.geometry) AS px,\n ST_Y(t.geometry) AS py\n FROM ${qualifiedName} t\n )\n SELECT\n COUNT(DISTINCT ROUND(px, 8))::INTEGER AS res_x,\n COUNT(DISTINCT ROUND(py, 8))::INTEGER AS res_y,\n MIN(px) AS min_lon,\n MIN(py) AS min_lat,\n MAX(px) AS max_lon,\n MAX(py) AS max_lat,\n list(properties ORDER BY py ASC, px ASC) AS raster\n FROM pixels\n `);\n\n const row = toPlain(result.toArray()[0]?.toJSON());\n if (!row) throw new Error(`No data found in GeoTiff table ${tableName}.`);\n\n const { res_x, res_y, min_lon, min_lat, max_lon, max_lat, raster } = row;\n\n // Expand bbox by half a pixel on each side so single-column/row rasters don't collapse to zero width/height.\n const spacingX = Number(res_x) > 1 ? Math.abs((Number(max_lon) - Number(min_lon)) / (Number(res_x) - 1)) : null;\n const spacingY = Number(res_y) > 1 ? Math.abs((Number(max_lat) - Number(min_lat)) / (Number(res_y) - 1)) : null;\n const halfX = (spacingX ?? spacingY ?? 0) / 2;\n const halfY = (spacingY ?? spacingX ?? 0) / 2;\n\n return {\n type: 'FeatureCollection',\n bbox: [Number(min_lon) - halfX, Number(min_lat) - halfY, Number(max_lon) + halfX, Number(max_lat) + halfY],\n features: [\n {\n type: 'Feature',\n geometry: null,\n properties: {\n rasterResX: res_x,\n rasterResY: res_y,\n raster,\n },\n },\n ],\n };\n }\n\n // GETTER'S\n\n /**\n * Retrieves the GeoJSON representation of a layer by its table name.\n * The returned FeatureCollection will include a bbox property with the layer's bounding box.\n * @param layerTableName - The name of the layer table to retrieve.\n * @returns A promise that resolves to the GeoJSON FeatureCollection of the layer with bbox.\n * @throws Error if the database or connection is not initialized.\n * @throws Error if the layer table is not found or is not a Layer table.\n */\n async getLayer(layerTableName: string): Promise<FeatureCollection> {\n if (!this.db || !this.conn || !this.getLayerGeojsonUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const layerTable = this.tables.find((t) => t.name === layerTableName);\n if (!layerTable) throw new Error(`Table ${layerTableName} not found.`);\n if (!isLayerType(layerTable.type)) throw new Error(`Table ${layerTableName} is not a Layer table.`);\n\n const featureCollection = await this.getLayerGeojsonUseCase.exec(layerTable as LayerTable | CustomLayerTable, this.currentWorkspace);\n\n const osmBoundingBox = this.getOsmBoundingBox();\n if (osmBoundingBox) {\n featureCollection.bbox = osmBoundingBox;\n } else {\n const layerBoundingBox = await this.getBoundingBoxFromLayer(layerTableName);\n featureCollection.bbox = [\n layerBoundingBox.minLon,\n layerBoundingBox.minLat,\n layerBoundingBox.maxLon,\n layerBoundingBox.maxLat,\n ];\n }\n\n return featureCollection;\n }\n\n /**\n * Retrieves the OSM bounding box for the current workspace.\n *\n * @returns The bounding box as `[minLon, minLat, maxLon, maxLat]`, or `null` if no OSM data has been loaded.\n * @throws Never throws.\n */\n getOsmBoundingBox(): [number, number, number, number] | null {\n const workspaceData = this.getCurrentWorkspaceData();\n if (!workspaceData.osmBoundingBox) return null;\n\n return [\n workspaceData.osmBoundingBox.minLon,\n workspaceData.osmBoundingBox.minLat,\n workspaceData.osmBoundingBox.maxLon,\n workspaceData.osmBoundingBox.maxLat,\n ]\n }\n\n /**\n * Returns the OSM bounding box in WGS84 (EPSG:4326) for clipping rasters.\n *\n * @returns The bounding box or `null` if no OSM data has been loaded.\n * @throws Never throws.\n */\n getOsmBoundingBoxWgs84(): BoundingBox | null {\n return this.getCurrentWorkspaceData().osmBoundingBoxWgs84 ?? null;\n }\n\n /**\n * Retrieves the bounding box of a layer by its table name.\n * @param layerName - The name of the layer table to retrieve the bounding box from.\n * @returns A promise that resolves to the bounding box of the layer.\n * @throws Error if the database or connection is not initialized.\n * @throws Error if the layer table is not found.\n * @throws Error if the layer table does not have a geometry column.\n */\n async getBoundingBoxFromLayer(layerName: string): Promise<BoundingBox> {\n if (!this.db || !this.conn || !this.getBoundingBoxFromLayerUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const layerTable = this.tables.find((t) => t.name === layerName);\n if (!layerTable) throw new Error(`Table ${layerName} not found.`);\n\n // Verify the table has a geometry column\n const hasGeometry = layerTable.columns.find((column) => column.type === 'GEOMETRY');\n if (!hasGeometry) {\n throw new Error(\n `Table ${layerName} does not have a geometry column. This method only works with layer tables that contain geometries.`,\n );\n }\n\n return this.getBoundingBoxFromLayerUseCase.exec({\n layerTableName: layerName,\n workspace: this.currentWorkspace,\n });\n }\n\n /**\n * Retrieves all layer tables from the loaded tables.\n *\n * @returns An array of `LayerTable` and `CustomLayerTable` objects.\n * @throws Never throws.\n */\n getLayerTables(): Array<LayerTable | CustomLayerTable> {\n return this.tables.filter((table): table is LayerTable | CustomLayerTable => {\n return (\n (table.source === 'osm' && isLayerType(table.type)) ||\n (table.source === 'geojson' && isLayerType(table.type)) ||\n (table.source === 'user' && isLayerType(table.type)) // TODO: check if this is correct\n );\n });\n }\n\n /**\n * Retrieves the data from any table as an array of plain JavaScript objects.\n * This method works with all table types (CSV, JSON, Layer, Grid, etc.).\n * @param params - Parameters including table name and optional pagination (limit, offset).\n * @returns A promise that resolves to an array of objects representing the table rows.\n * @throws Error if the database or connection is not initialized.\n * @throws Error if the table is not found.\n */\n async getTableData(params: GetTableDataParams): Promise<GetTableDataOutput> {\n if (!this.db || !this.conn || !this.getTableDataUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const table = this.tables.find((t) => t.name === params.tableName);\n if (!table) throw new Error(`Table ${params.tableName} not found.`);\n\n return this.getTableDataUseCase.exec({ ...params, workspace: this.currentWorkspace });\n }\n\n // ---- UPDATE methods\n\n /**\n * Updates an existing table with new data.\n * \n * For layer tables (OSM, GeoJSON), the input data should be a GeoJSON FeatureCollection.\n * For non-layer tables (CSV, JSON), the input data should be an array of objects.\n * \n * @param params - Parameters for updating the table:\n * - tableName: The name of the table to update\n * - data: The new data (FeatureCollection for layers, Record<string, unknown>[] for CSV/JSON)\n * - strategy: 'replace' (drop and recreate) or 'update' (update existing records by ID)\n * - idColumn: Required for 'update' strategy. Supports 'id' or 'properties.attribute_name' format\n * @returns A promise that resolves to the updated Table with refreshed column metadata.\n * @throws Error if the database or connection is not initialized.\n * @throws Error if the table is not found.\n * @throws Error if idColumn is not provided when using 'update' strategy.\n */\n async updateTable(params: Omit<UpdateTableParams, 'workspace'>): Promise<Table> {\n if (!this.db || !this.conn || !this.updateTableUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const table = this.tables.find((t) => t.name === params.tableName);\n if (!table) throw new Error(`Table ${params.tableName} not found.`);\n\n const result = await this.updateTableUseCase.exec(\n { ...params, workspace: this.currentWorkspace },\n table\n );\n\n // Update the table in the workspace\n const workspaceData = this.getCurrentWorkspaceData();\n const tableIndex = workspaceData.tables.findIndex((t) => t.name === params.tableName);\n if (tableIndex !== -1) {\n workspaceData.tables[tableIndex] = result.table;\n }\n\n return result.table;\n }\n\n // CUSTOM QUERIES\n\n /**\n * Performs a spatial join between two tables and returns the resulting table.\n * The method can either create a new table or update an existing one based on the parameters.\n * @param params - Parameters for the spatial join operation, including source and target tables, join type, and output table name.\n * @returns A promise that resolves to the resulting table after the spatial join.\n * @throws Error if the database or connection is not initialized.\n */\n async spatialQuery(params: SpatialQueryParams): Promise<Table> {\n if (!this.db || !this.conn || !this.spatialJoinUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const workspaceData = this.getCurrentWorkspaceData();\n const { created, table } = await this.spatialJoinUseCase.exec(params, workspaceData.tables);\n if (created) this._registerTable(table);\n else workspaceData.tables = workspaceData.tables.map((t) => (t.name === table.name ? table : t));\n\n return table;\n }\n\n /**\n * Executes a raw SQL query and returns the result.\n * @param params - Parameters for the raw query, including the SQL query string and output type.\n * @returns A promise that resolves to a Table if output type is 'CREATE_TABLE', otherwise returns the query result of type T.\n * @throws Error if the database or connection is not initialized.\n */\n async rawQuery<T = RawQueryOutput>(params: RawQueryParams): Promise<T | Table> {\n if (!this.db || !this.conn || !this.rawQueryUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const result = await this.rawQueryUseCase.exec(params);\n\n if (params.output.type === 'CREATE_TABLE') {\n this._registerTable(result as Table);\n return result as Table;\n }\n\n return result as unknown as T;\n }\n\n /**\n * Drops a table from the database and removes it from the current workspace.\n * @param tableName - The name of the table to remove.\n * @returns A promise that resolves when the table has been dropped.\n * @throws Error if the database or connection is not initialized.\n */\n async removeLayer(tableName: string): Promise<void> {\n if (!this.conn || !this.dropTableUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n await this.dropTableUseCase.exec({ tableName, workspace: this.currentWorkspace });\n\n const workspaceData = this.getCurrentWorkspaceData();\n workspaceData.tables = workspaceData.tables.filter((t) => t.name !== tableName);\n }\n\n /**\n * Builds a heatmap from spatial data by creating a grid and aggregating values.\n * The heatmap is generated by creating a grid over the bounding box and aggregating values from the source table into each grid cell.\n * @param params - Parameters for building the heatmap, including source table, grid configuration, and aggregation method.\n * @returns A promise that resolves to the resulting GridLayerTable containing the heatmap data.\n * @throws Error if the database or connection is not initialized.\n */\n async buildHeatmap(params: BuildHeatmapParams): Promise<Table> {\n if (!this.db || !this.conn || !this.buildHeatmapUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const workspaceData = this.getCurrentWorkspaceData();\n const table = await this.buildHeatmapUseCase.exec(params, workspaceData.tables, workspaceData.osmBoundingBox);\n this._registerTable(table);\n\n return table;\n }\n}\n"],"x_google_ignoreList":[5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,40,42,43,44,59,60,61,62,63,64,65,66,67,68,69,70,71,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98],"mappings":"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"}
1
+ {"version":3,"file":"autk-db.js","names":["sum","u","sum","bc","ca","ab","bct","cat","abt","u","_8","_8b","_16","fin","fin2","bc","ab","_8","_16","_48","fin","pip","defaultCompare","sweeplineIntersections","lib","point2","booleanPointInPolygon2","intersects","createNode","EPSILON","create","glMatrix.ARRAY_TYPE","glMatrix.ARRAY_TYPE","getValues"],"sources":["../src/shared/osm-tag-definitions.ts","../src/config/duckdb.ts","../src/spatial/use-cases/load-layer/queries.ts","../src/spatial/shared/utils.ts","../src/shared/consts.ts","../../node_modules/@turf/helpers/dist/esm/index.js","../../node_modules/@turf/invariant/dist/esm/index.js","../../node_modules/@turf/meta/dist/esm/index.js","../../node_modules/@turf/bbox/dist/esm/index.js","../../node_modules/@turf/bbox-polygon/dist/esm/index.js","../../node_modules/point-in-polygon-hao/node_modules/robust-predicates/esm/util.js","../../node_modules/point-in-polygon-hao/node_modules/robust-predicates/esm/orient2d.js","../../node_modules/point-in-polygon-hao/node_modules/robust-predicates/esm/orient3d.js","../../node_modules/point-in-polygon-hao/node_modules/robust-predicates/esm/incircle.js","../../node_modules/point-in-polygon-hao/node_modules/robust-predicates/esm/insphere.js","../../node_modules/point-in-polygon-hao/dist/esm/index.js","../../node_modules/@turf/boolean-point-in-polygon/dist/esm/index.js","../../node_modules/sweepline-intersections/dist/sweeplineIntersections.esm.js","../../node_modules/@turf/line-intersect/dist/esm/index.js","../../node_modules/@turf/polygon-to-line/dist/esm/index.js","../../node_modules/@turf/boolean-disjoint/dist/esm/index.js","../../node_modules/@turf/boolean-intersects/dist/esm/index.js","../../node_modules/@turf/envelope/dist/esm/index.js","../../node_modules/@turf/polygonize/dist/esm/index.js","../../node_modules/quickselect/index.js","../../node_modules/rbush/index.js","../src/shared/clusterIntersectingFeatures.ts","../src/spatial/use-cases/assign-building-ids/AssignBuildingIdsUseCase.ts","../src/spatial/use-cases/aggregate-building-layer/AggregateBuildingLayerUseCase.ts","../src/spatial/use-cases/load-layer/osm-processing-config.ts","../src/spatial/use-cases/load-layer/LoadLayerUseCase.ts","../src/spatial/use-cases/load-csv/queries.ts","../src/spatial/use-cases/load-csv/LoadCsvUseCase.ts","../src/spatial/use-cases/load-json/queries.ts","../src/spatial/use-cases/load-json/LoadJsonUseCase.ts","../src/spatial/use-cases/get-layer-geojson/queries.ts","../src/spatial/use-cases/get-layer-geojson/GetLayerGeojsonUseCase.ts","../../autk-core/src/types-colormap.ts","../../autk-core/src/colormap.ts","../../autk-core/src/utils-geometry.ts","../../node_modules/earcut/src/earcut.js","../../autk-core/src/triangulator-polylines.ts","../../node_modules/gl-matrix/esm/common.js","../../node_modules/gl-matrix/esm/mat4.js","../../node_modules/gl-matrix/esm/vec3.js","../../autk-core/src/camera.ts","../../autk-core/src/utils-layer.ts","../src/spatial/use-cases/load-custom-layer/queries.ts","../src/spatial/use-cases/load-custom-layer/LoadCustomLayerUseCase.ts","../src/spatial/use-cases/spatial-join/errors.ts","../src/spatial/use-cases/spatial-join/queries.ts","../src/spatial/use-cases/spatial-join/SpatialJoinUseCase.ts","../src/spatial/shared/use-cases/drop-table/DropTableUseCase.ts","../src/spatial/shared/use-cases/transform-bounding-box-coordinates/queries.ts","../src/spatial/shared/use-cases/transform-bounding-box-coordinates/TransformBoundingBoxCoordinatesUseCase.ts","../src/spatial/shared/use-cases/get-bounding-box-from-layer/queries.ts","../src/spatial/shared/use-cases/get-bounding-box-from-layer/GetBoundingBoxFromLayerUseCase.ts","../src/shared/HttpCache.ts","../src/spatial/use-cases/load-osm-from-overpass-api/LoadOsmFromOverpassApiUseCase.ts","../../node_modules/pbf/index.js","../../node_modules/@osmix/pbf/dist/proto/osmformat.js","../../node_modules/@osmix/shared/dist/bytes-to-stream.js","../../node_modules/@osmix/shared/dist/concat-bytes.js","../../node_modules/@osmix/shared/dist/stream-to-bytes.js","../../node_modules/@osmix/shared/dist/transform-bytes.js","../../node_modules/@osmix/pbf/dist/utils.js","../../node_modules/@osmix/pbf/dist/blobs-to-blocks.js","../../node_modules/@osmix/pbf/dist/proto/fileformat.js","../../node_modules/@osmix/pbf/dist/spec.js","../../node_modules/@osmix/pbf/dist/blocks-to-pbf.js","../../node_modules/@osmix/pbf/dist/pbf-to-blocks.js","../../node_modules/@osmix/pbf/dist/pbf-to-blobs.js","../src/spatial/use-cases/load-osm-from-pbf/osm-pbf-parser.ts","../src/spatial/use-cases/load-osm-from-pbf/LoadOsmFromPbfUseCase.ts","../src/spatial/use-cases/load-osm-from-overpass-api/queries.ts","../src/spatial/use-cases/osm-processing-pipeline/OsmProcessingPipeline.ts","../src/spatial/use-cases/load-grid-layer/LoadGridLayerUseCase.ts","../../node_modules/@petamoriken/float16/src/_util/messages.mjs","../../node_modules/@petamoriken/float16/src/_util/primordials.mjs","../../node_modules/@petamoriken/float16/src/_util/arrayIterator.mjs","../../node_modules/@petamoriken/float16/src/_util/converter.mjs","../../node_modules/@petamoriken/float16/src/DataView.mjs","../../node_modules/xml-utils/get-attribute.mjs","../../node_modules/xml-utils/index-of-match.mjs","../../node_modules/xml-utils/index-of-match-end.mjs","../../node_modules/xml-utils/count-substring.mjs","../../node_modules/xml-utils/find-tag-by-name.mjs","../../node_modules/xml-utils/find-tags-by-name.mjs","../../node_modules/geotiff/dist-module/rgb.js","../../node_modules/geotiff/dist-module/compression/index.js","../../node_modules/geotiff/dist-module/resample.js","../../node_modules/geotiff/dist-module/geotiffimage.js","../../node_modules/geotiff/dist-module/dataview64.js","../../node_modules/geotiff/dist-module/dataslice.js","../../node_modules/geotiff/dist-module/source/basesource.js","../../node_modules/geotiff/dist-module/utils.js","../../node_modules/geotiff/dist-module/source/arraybuffer.js","../../node_modules/geotiff/dist-module/imagefiledirectory.js","../../node_modules/geotiff/dist-module/geotiff.js","../src/spatial/use-cases/load-geotiff/LoadGeoTiffUseCase.ts","../src/spatial/use-cases/raw-query/errors.ts","../src/spatial/use-cases/raw-query/RawQueryUseCase.ts","../src/spatial/shared/use-cases/get-bounding-box-from-osm/queries.ts","../src/spatial/shared/use-cases/get-bounding-box-from-osm/GetBoundingBoxFromOsmUseCase.ts","../src/spatial/use-cases/polygonize-surface-layer/queries.ts","../src/spatial/use-cases/polygonize-surface-layer/PolygonizeSurfaceLayerUseCase.ts","../src/spatial/use-cases/build-heatmap/BuildHeatmapUseCase.ts","../src/spatial/use-cases/get-table-data/GetTableDataUseCase.ts","../src/spatial/use-cases/update-table/interfaces.ts","../src/spatial/use-cases/update-table/queries.ts","../src/spatial/use-cases/update-table/UpdateTableUseCase.ts","../src/spatial/SpatialDb.ts"],"sourcesContent":["/**\n * OSM tag value definitions used across Overpass queries and layer classification.\n *\n * Centralized here so both the Overpass query builder and the SQL layer filters\n * reference the same source of truth.\n */\n\nexport const PARKS_LEISURE_VALUES = ['dog_park', 'park', 'playground', 'recreation_ground'] as const;\nexport const PARKS_LANDUSE_VALUES = ['wood', 'grass', 'forest', 'orchard', 'village_green', 'vineyard', 'cemetery', 'meadow'] as const;\nexport const PARKS_NATURAL_VALUES = ['wood', 'grass', 'grassland', 'forest', 'scrub', 'heath', 'meadow'] as const;\n\nexport const WATER_NATURAL_VALUES = ['water', 'wetland', 'strait', 'spring'] as const;\nexport const WATER_FEATURE_VALUES = ['pond', 'reservoir', 'lagoon', 'stream_pool', 'lake', 'pool', 'canal', 'river'] as const;\n\nexport const EXCLUDED_HIGHWAY_VALUES = ['cycleway', 'elevator', 'footway', 'steps', 'pedestrian', 'proposed', 'construction', 'abandoned', 'platform', 'raceway'] as const;\nexport const EXCLUDED_BUILDING_VALUES = ['shed', 'garage', 'garages', 'carport', 'hut', 'kiosk', 'toilets', 'service', 'transformer_tower', 'sty', 'container'] as const;\n","import * as duckdb from '@duckdb/duckdb-wasm';\n\nconst BROWSER_BUNDLES: duckdb.DuckDBBundles = {\n mvp: {\n mainModule: new URL(/* @vite-ignore */ './duckdb-mvp.wasm', import.meta.url).href,\n mainWorker: new URL(/* @vite-ignore */ './duckdb-browser-mvp.worker.js', import.meta.url).href,\n },\n eh: {\n mainModule: new URL(/* @vite-ignore */ './duckdb-eh.wasm', import.meta.url).href,\n mainWorker: new URL(/* @vite-ignore */ './duckdb-browser-eh.worker.js', import.meta.url).href,\n },\n};\n\n/**\n * Loads and instantiates a DuckDB database, with Node.js and browser support.\n *\n * @returns An instantiated `AsyncDuckDB` instance ready for connections.\n * @throws If DuckDB WebAssembly fails to load or instantiate.\n */\nexport async function loadDb() {\n if (typeof process !== 'undefined' && process.versions?.node) {\n const path = await import(/* @vite-ignore */ 'node:path');\n const { Worker: NodeWorker } = await import(/* @vite-ignore */ 'node:worker_threads');\n const { createRequire } = await import(/* @vite-ignore */ 'node:module');\n const require = createRequire(import.meta.url);\n const dist = path.dirname(require.resolve('@duckdb/duckdb-wasm'));\n const workerPath = path.join(dist, 'duckdb-node-eh.worker.cjs');\n\n // Stub: polyfill the Web Worker globals the duckdb worker expects,\n // then require() it so it loads with proper CJS scope.\n const stub =\n `const { parentPort } = require('node:worker_threads');` +\n `globalThis.postMessage = (msg, transfer) => parentPort.postMessage(msg, transfer);` +\n `parentPort.on('message', (data) => { if (typeof globalThis.onmessage === 'function') globalThis.onmessage({ data }); });` +\n `require(${JSON.stringify(workerPath)});`;\n const nodeWorker = new NodeWorker(stub, { eval: true });\n\n const listeners = new Map<(event: any) => void, [string, (...args: any[]) => void]>();\n const adapter = {\n addEventListener(event: string, handler: (e: any) => void) {\n const wrapped =\n event === 'error'\n ? (err: any) =>\n handler({\n error: err,\n message: err?.message ?? String(err),\n target: adapter,\n })\n : (data: any) => handler({ data, target: adapter });\n listeners.set(handler, [event, wrapped]);\n nodeWorker.on(event, wrapped);\n },\n removeEventListener(_event: string, handler: (e: any) => void) {\n const r = listeners.get(handler);\n if (r) {\n nodeWorker.off(r[0], r[1]);\n listeners.delete(handler);\n }\n },\n postMessage(data: any, transfer?: any[]) {\n nodeWorker.postMessage(data, transfer);\n },\n terminate() {\n return nodeWorker.terminate();\n },\n };\n\n const db = new duckdb.AsyncDuckDB(new duckdb.VoidLogger(), adapter as unknown as Worker);\n await db.instantiate(path.join(dist, 'duckdb-eh.wasm'));\n return db;\n }\n\n const bundle = await duckdb.selectBundle(BROWSER_BUNDLES);\n const worker = new Worker(bundle.mainWorker!);\n const db = new duckdb.AsyncDuckDB(new duckdb.VoidLogger(), worker);\n await db.instantiate(bundle.mainModule);\n return db;\n}\n","import { LayerType } from './interfaces';\nimport { BoundingBox } from '../../../shared/interfaces';\n\ntype Params = {\n tableName: string;\n layer: LayerType;\n outputFormat: string;\n outputTableName: string;\n boundingBox?: BoundingBox;\n workspace?: string;\n};\n\nconst AREA_LAYERS: LayerType[] = ['buildings', 'parks', 'water'];\n\nexport const LOAD_LAYER_QUERY = ({ tableName, layer, outputFormat, outputTableName, boundingBox, workspace = 'main' }: Params) => {\n const query = getLayerQuery(layer);\n \n const qualifiedInputTableName = `${workspace}.${tableName}`;\n const qualifiedOutputTableName = `${workspace}.${outputTableName}`;\n \n let actualTableName = qualifiedInputTableName;\n if (layer === 'surface') {\n const baseTableName = tableName.replace(new RegExp(`^${workspace}\\\\.`), '');\n actualTableName = `${workspace}.${baseTableName}_boundaries`;\n }\n\n return `\n ${query(actualTableName)}\n CREATE OR REPLACE TEMP TABLE ${layer}_with_nodes_refs AS\n SELECT id, UNNEST(refs) as ref, UNNEST(range(length(refs))) as ref_idx\n FROM ${actualTableName}\n SEMI JOIN ${layer} USING (id)\n WHERE kind IN ('way', 'relation');\n\n CREATE OR REPLACE TEMP TABLE ${layer}_required_nodes_with_geometries AS\n SELECT id, ST_POINT(lon, lat) geometry\n FROM ${actualTableName} nodes\n SEMI JOIN ${layer}_with_nodes_refs\n ON nodes.id = ${layer}_with_nodes_refs.ref\n WHERE kind = 'node';\n\n CREATE OR REPLACE TABLE ${qualifiedOutputTableName} AS\n SELECT\n ${layer}.id,\n ${layer}.tags properties,\n ${layer}.refs,\n ${buildGeometrySelect({ outputFormat, boundingBox, layer })} geometry\n FROM ${layer}\n JOIN ${layer}_with_nodes_refs\n ON ${layer}.id = ${layer}_with_nodes_refs.id\n JOIN ${layer}_required_nodes_with_geometries nodes\n ON ${layer}_with_nodes_refs.ref = nodes.id\n GROUP BY 1, 2, 3\n ${buildHavingClause({ outputFormat, boundingBox, layer })};\n\n DESCRIBE ${qualifiedOutputTableName};\n `;\n};\n\nfunction buildAreaGeometryExpression(outputFormat: string, boundingBox?: BoundingBox) {\n const baseGeometry = `\n CASE \n WHEN refs[1] = refs[array_length(refs)] AND array_length(refs) > 3 THEN\n ST_Transform(\n ST_MakePolygon(\n ST_MakeLine(\n list(nodes.geometry ORDER BY ref_idx ASC)\n )\n ),\n 'EPSG:4326',\n '${outputFormat}',\n always_xy := true\n )\n ELSE\n ST_Transform(\n ST_MakeLine(\n list(nodes.geometry ORDER BY ref_idx ASC)\n ),\n 'EPSG:4326',\n '${outputFormat}',\n always_xy := true\n )\n END`;\n\n if (!boundingBox) return baseGeometry;\n\n const clippingGeometry = `ST_MakeEnvelope(${boundingBox.minLon}, ${boundingBox.minLat}, ${boundingBox.maxLon}, ${boundingBox.maxLat})`;\n return `ST_Intersection(${baseGeometry}, ${clippingGeometry})`;\n}\n\nfunction buildGeometrySelect({\n outputFormat,\n boundingBox,\n layer,\n}: {\n outputFormat: string;\n boundingBox?: BoundingBox;\n layer: LayerType;\n}) {\n return AREA_LAYERS.includes(layer)\n ? buildAreaGeometryExpression(outputFormat, boundingBox)\n : `ST_Transform(\n ST_MakeLine(\n list(nodes.geometry ORDER BY ref_idx ASC)\n ),\n 'EPSG:4326',\n '${outputFormat}',\n always_xy := true\n )`;\n}\n\nfunction buildHavingClause({\n outputFormat,\n boundingBox,\n layer,\n}: {\n outputFormat: string;\n boundingBox?: BoundingBox;\n layer: LayerType;\n}) {\n if (!boundingBox || !AREA_LAYERS.includes(layer)) return '';\n\n const geometry = buildAreaGeometryExpression(outputFormat, boundingBox);\n const clippingGeometry = `ST_MakeEnvelope(${boundingBox.minLon}, ${boundingBox.minLat}, ${boundingBox.maxLon}, ${boundingBox.maxLat})`;\n return `HAVING ST_Intersects(${geometry}, ${clippingGeometry})`;\n}\n\nfunction getLayerQuery(layer: string): (t: string) => string {\n switch (layer) {\n case 'parks':\n return GET_PARKS;\n case 'water':\n return GET_WATER;\n case 'buildings':\n return GET_BUILDINGS;\n case 'roads':\n return GET_ROADS;\n case 'surface':\n return GET_SURFACE;\n default:\n return () => '';\n }\n}\n\nconst GET_PARKS = (tableName: string) => `\n CREATE OR REPLACE TEMP TABLE parks AS\n SELECT id, tags, refs FROM ${tableName}\n WHERE kind = 'way' AND map_extract(tags, '__autk_layer')[1] = 'parks';\n`;\n\nconst GET_WATER = (tableName: string) => `\n CREATE OR REPLACE TEMP TABLE water AS\n SELECT id, tags, refs FROM ${tableName}\n WHERE kind = 'way' AND map_extract(tags, '__autk_layer')[1] = 'water';\n`;\n\nconst GET_BUILDINGS = (tableName: string) => `\n CREATE OR REPLACE TEMP TABLE buildings AS\n SELECT id, tags, refs FROM ${tableName}\n WHERE kind = 'way' AND map_extract(tags, '__autk_layer')[1] = 'buildings';\n`;\n\nconst GET_ROADS = (tableName: string) => `\n CREATE OR REPLACE TEMP TABLE roads AS\n SELECT id, tags, refs FROM ${tableName}\n WHERE kind = 'way' AND map_extract(tags, '__autk_layer')[1] = 'roads' AND array_length(refs) > 1;\n`;\n\nconst GET_SURFACE = (tableName: string) => `\n CREATE OR REPLACE TEMP TABLE surface AS\n SELECT id, tags, refs FROM ${tableName}\n WHERE kind IN ('way');\n`;\n","import { Column } from '../../shared/interfaces';\n\ntype DuckDbTableDescriptionColumn = {\n column_name: string;\n column_type: string;\n};\n\n/**\n * Converts DuckDB `DESCRIBE` output rows into `Column` metadata objects.\n *\n * @param tableDescribeResponse Array of `{ column_name, column_type }` rows from DuckDB.\n * @returns Array of `{ name, type }` column descriptors.\n * @throws Never throws.\n */\nexport function getColumnsFromDuckDbTableDescribe(\n tableDescribeResponse: Array<DuckDbTableDescriptionColumn>,\n): Array<Column> {\n return tableDescribeResponse.map((column: DuckDbTableDescriptionColumn) => {\n return {\n name: column.column_name,\n type: column.column_type,\n };\n });\n}\n\n/**\n * Recursively converts values returned by DuckDB-Wasm / Apache Arrow into\n * plain JavaScript values so they can be safely logged or serialised. It\n * handles nested arrays, structs and any object exposing a `toJSON()` method.\n */\nexport function toPlain<T = unknown>(value: T): T {\n // Primitives (string, number, boolean, undefined, null, bigint, symbol)\n if (value === null || typeof value !== 'object') {\n // Arrow sometimes encodes primitive strings as a JSON string literal, e.g.\n // value === '\"secondary\"'\n // Detect that pattern and decode it.\n if (typeof value === 'string') {\n const trimmed = value.trim();\n if (trimmed.length >= 2 && trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n try {\n return JSON.parse(trimmed) as unknown as T;\n } catch {\n /* ignore parse errors and fall through */\n }\n }\n }\n return value;\n }\n\n // Arrow/DuckDB objects usually implement toJSON() to expose their contents.\n const maybeJsonifiable = value as unknown as { toJSON?: () => unknown };\n if (typeof maybeJsonifiable.toJSON === 'function') {\n // Recurse after conversion to remove any nested wrappers.\n return toPlain(maybeJsonifiable.toJSON()) as T;\n }\n\n // Arrays – normalise every element.\n if (Array.isArray(value)) {\n return value.map((v) => toPlain(v)) as unknown as T;\n }\n\n // Generic object – normalise each property.\n const plainObj = Object.fromEntries(\n Object.entries(value as Record<string, unknown>).map(([k, v]) => [k, toPlain(v)]),\n );\n return plainObj as T;\n}\n","/** Default coordinate reference system used for spatial operations. */\nexport const DEFALT_COORDINATE_FORMAT = 'EPSG:4326';\n/** Default geometry column name for point-based tables. */\nexport const DEFAULT_GEO_COLUMN_NAME = 'geoPoint';\n","// index.ts\nvar earthRadius = 63710088e-1;\nvar factors = {\n centimeters: earthRadius * 100,\n centimetres: earthRadius * 100,\n degrees: 360 / (2 * Math.PI),\n feet: earthRadius * 3.28084,\n inches: earthRadius * 39.37,\n kilometers: earthRadius / 1e3,\n kilometres: earthRadius / 1e3,\n meters: earthRadius,\n metres: earthRadius,\n miles: earthRadius / 1609.344,\n millimeters: earthRadius * 1e3,\n millimetres: earthRadius * 1e3,\n nauticalmiles: earthRadius / 1852,\n radians: 1,\n yards: earthRadius * 1.0936\n};\nvar areaFactors = {\n acres: 247105e-9,\n centimeters: 1e4,\n centimetres: 1e4,\n feet: 10.763910417,\n hectares: 1e-4,\n inches: 1550.003100006,\n kilometers: 1e-6,\n kilometres: 1e-6,\n meters: 1,\n metres: 1,\n miles: 386e-9,\n nauticalmiles: 29155334959812285e-23,\n millimeters: 1e6,\n millimetres: 1e6,\n yards: 1.195990046\n};\nfunction feature(geom, properties, options = {}) {\n const feat = { type: \"Feature\" };\n if (options.id === 0 || options.id) {\n feat.id = options.id;\n }\n if (options.bbox) {\n feat.bbox = options.bbox;\n }\n feat.properties = properties || {};\n feat.geometry = geom;\n return feat;\n}\nfunction geometry(type, coordinates, _options = {}) {\n switch (type) {\n case \"Point\":\n return point(coordinates).geometry;\n case \"LineString\":\n return lineString(coordinates).geometry;\n case \"Polygon\":\n return polygon(coordinates).geometry;\n case \"MultiPoint\":\n return multiPoint(coordinates).geometry;\n case \"MultiLineString\":\n return multiLineString(coordinates).geometry;\n case \"MultiPolygon\":\n return multiPolygon(coordinates).geometry;\n default:\n throw new Error(type + \" is invalid\");\n }\n}\nfunction point(coordinates, properties, options = {}) {\n if (!coordinates) {\n throw new Error(\"coordinates is required\");\n }\n if (!Array.isArray(coordinates)) {\n throw new Error(\"coordinates must be an Array\");\n }\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be at least 2 numbers long\");\n }\n if (!isNumber(coordinates[0]) || !isNumber(coordinates[1])) {\n throw new Error(\"coordinates must contain numbers\");\n }\n const geom = {\n type: \"Point\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction points(coordinates, properties, options = {}) {\n return featureCollection(\n coordinates.map((coords) => {\n return point(coords, properties);\n }),\n options\n );\n}\nfunction polygon(coordinates, properties, options = {}) {\n for (const ring of coordinates) {\n if (ring.length < 4) {\n throw new Error(\n \"Each LinearRing of a Polygon must have 4 or more Positions.\"\n );\n }\n if (ring[ring.length - 1].length !== ring[0].length) {\n throw new Error(\"First and last Position are not equivalent.\");\n }\n for (let j = 0; j < ring[ring.length - 1].length; j++) {\n if (ring[ring.length - 1][j] !== ring[0][j]) {\n throw new Error(\"First and last Position are not equivalent.\");\n }\n }\n }\n const geom = {\n type: \"Polygon\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction polygons(coordinates, properties, options = {}) {\n return featureCollection(\n coordinates.map((coords) => {\n return polygon(coords, properties);\n }),\n options\n );\n}\nfunction lineString(coordinates, properties, options = {}) {\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be an array of two or more positions\");\n }\n const geom = {\n type: \"LineString\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction lineStrings(coordinates, properties, options = {}) {\n return featureCollection(\n coordinates.map((coords) => {\n return lineString(coords, properties);\n }),\n options\n );\n}\nfunction featureCollection(features, options = {}) {\n const fc = { type: \"FeatureCollection\" };\n if (options.id) {\n fc.id = options.id;\n }\n if (options.bbox) {\n fc.bbox = options.bbox;\n }\n fc.features = features;\n return fc;\n}\nfunction multiLineString(coordinates, properties, options = {}) {\n const geom = {\n type: \"MultiLineString\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction multiPoint(coordinates, properties, options = {}) {\n const geom = {\n type: \"MultiPoint\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction multiPolygon(coordinates, properties, options = {}) {\n const geom = {\n type: \"MultiPolygon\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction geometryCollection(geometries, properties, options = {}) {\n const geom = {\n type: \"GeometryCollection\",\n geometries\n };\n return feature(geom, properties, options);\n}\nfunction round(num, precision = 0) {\n if (precision && !(precision >= 0)) {\n throw new Error(\"precision must be a positive number\");\n }\n const multiplier = Math.pow(10, precision || 0);\n return Math.round(num * multiplier) / multiplier;\n}\nfunction radiansToLength(radians, units = \"kilometers\") {\n const factor = factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return radians * factor;\n}\nfunction lengthToRadians(distance, units = \"kilometers\") {\n const factor = factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return distance / factor;\n}\nfunction lengthToDegrees(distance, units) {\n return radiansToDegrees(lengthToRadians(distance, units));\n}\nfunction bearingToAzimuth(bearing) {\n let angle = bearing % 360;\n if (angle < 0) {\n angle += 360;\n }\n return angle;\n}\nfunction azimuthToBearing(angle) {\n angle = angle % 360;\n if (angle > 180) {\n return angle - 360;\n } else if (angle < -180) {\n return angle + 360;\n }\n return angle;\n}\nfunction radiansToDegrees(radians) {\n const normalisedRadians = radians % (2 * Math.PI);\n return normalisedRadians * 180 / Math.PI;\n}\nfunction degreesToRadians(degrees) {\n const normalisedDegrees = degrees % 360;\n return normalisedDegrees * Math.PI / 180;\n}\nfunction convertLength(length, originalUnit = \"kilometers\", finalUnit = \"kilometers\") {\n if (!(length >= 0)) {\n throw new Error(\"length must be a positive number\");\n }\n return radiansToLength(lengthToRadians(length, originalUnit), finalUnit);\n}\nfunction convertArea(area, originalUnit = \"meters\", finalUnit = \"kilometers\") {\n if (!(area >= 0)) {\n throw new Error(\"area must be a positive number\");\n }\n const startFactor = areaFactors[originalUnit];\n if (!startFactor) {\n throw new Error(\"invalid original units\");\n }\n const finalFactor = areaFactors[finalUnit];\n if (!finalFactor) {\n throw new Error(\"invalid final units\");\n }\n return area / startFactor * finalFactor;\n}\nfunction isNumber(num) {\n return !isNaN(num) && num !== null && !Array.isArray(num);\n}\nfunction isObject(input) {\n return input !== null && typeof input === \"object\" && !Array.isArray(input);\n}\nfunction validateBBox(bbox) {\n if (!bbox) {\n throw new Error(\"bbox is required\");\n }\n if (!Array.isArray(bbox)) {\n throw new Error(\"bbox must be an Array\");\n }\n if (bbox.length !== 4 && bbox.length !== 6) {\n throw new Error(\"bbox must be an Array of 4 or 6 numbers\");\n }\n bbox.forEach((num) => {\n if (!isNumber(num)) {\n throw new Error(\"bbox must only contain numbers\");\n }\n });\n}\nfunction validateId(id) {\n if (!id) {\n throw new Error(\"id is required\");\n }\n if ([\"string\", \"number\"].indexOf(typeof id) === -1) {\n throw new Error(\"id must be a number or a string\");\n }\n}\nexport {\n areaFactors,\n azimuthToBearing,\n bearingToAzimuth,\n convertArea,\n convertLength,\n degreesToRadians,\n earthRadius,\n factors,\n feature,\n featureCollection,\n geometry,\n geometryCollection,\n isNumber,\n isObject,\n lengthToDegrees,\n lengthToRadians,\n lineString,\n lineStrings,\n multiLineString,\n multiPoint,\n multiPolygon,\n point,\n points,\n polygon,\n polygons,\n radiansToDegrees,\n radiansToLength,\n round,\n validateBBox,\n validateId\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { isNumber } from \"@turf/helpers\";\nfunction getCoord(coord) {\n if (!coord) {\n throw new Error(\"coord is required\");\n }\n if (!Array.isArray(coord)) {\n if (coord.type === \"Feature\" && coord.geometry !== null && coord.geometry.type === \"Point\") {\n return [...coord.geometry.coordinates];\n }\n if (coord.type === \"Point\") {\n return [...coord.coordinates];\n }\n }\n if (Array.isArray(coord) && coord.length >= 2 && !Array.isArray(coord[0]) && !Array.isArray(coord[1])) {\n return [...coord];\n }\n throw new Error(\"coord must be GeoJSON Point or an Array of numbers\");\n}\nfunction getCoords(coords) {\n if (Array.isArray(coords)) {\n return coords;\n }\n if (coords.type === \"Feature\") {\n if (coords.geometry !== null) {\n return coords.geometry.coordinates;\n }\n } else {\n if (coords.coordinates) {\n return coords.coordinates;\n }\n }\n throw new Error(\n \"coords must be GeoJSON Feature, Geometry Object or an Array\"\n );\n}\nfunction containsNumber(coordinates) {\n if (coordinates.length > 1 && isNumber(coordinates[0]) && isNumber(coordinates[1])) {\n return true;\n }\n if (Array.isArray(coordinates[0]) && coordinates[0].length) {\n return containsNumber(coordinates[0]);\n }\n throw new Error(\"coordinates must only contain numbers\");\n}\nfunction geojsonType(value, type, name) {\n if (!type || !name) {\n throw new Error(\"type and name required\");\n }\n if (!value || value.type !== type) {\n throw new Error(\n \"Invalid input to \" + name + \": must be a \" + type + \", given \" + value.type\n );\n }\n}\nfunction featureOf(feature, type, name) {\n if (!feature) {\n throw new Error(\"No feature passed\");\n }\n if (!name) {\n throw new Error(\".featureOf() requires a name\");\n }\n if (!feature || feature.type !== \"Feature\" || !feature.geometry) {\n throw new Error(\n \"Invalid input to \" + name + \", Feature with geometry required\"\n );\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error(\n \"Invalid input to \" + name + \": must be a \" + type + \", given \" + feature.geometry.type\n );\n }\n}\nfunction collectionOf(featureCollection, type, name) {\n if (!featureCollection) {\n throw new Error(\"No featureCollection passed\");\n }\n if (!name) {\n throw new Error(\".collectionOf() requires a name\");\n }\n if (!featureCollection || featureCollection.type !== \"FeatureCollection\") {\n throw new Error(\n \"Invalid input to \" + name + \", FeatureCollection required\"\n );\n }\n for (const feature of featureCollection.features) {\n if (!feature || feature.type !== \"Feature\" || !feature.geometry) {\n throw new Error(\n \"Invalid input to \" + name + \", Feature with geometry required\"\n );\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error(\n \"Invalid input to \" + name + \": must be a \" + type + \", given \" + feature.geometry.type\n );\n }\n }\n}\nfunction getGeom(geojson) {\n if (geojson.type === \"Feature\") {\n return geojson.geometry;\n }\n return geojson;\n}\nfunction getType(geojson, _name) {\n if (geojson.type === \"FeatureCollection\") {\n return \"FeatureCollection\";\n }\n if (geojson.type === \"GeometryCollection\") {\n return \"GeometryCollection\";\n }\n if (geojson.type === \"Feature\" && geojson.geometry !== null) {\n return geojson.geometry.type;\n }\n return geojson.type;\n}\nexport {\n collectionOf,\n containsNumber,\n featureOf,\n geojsonType,\n getCoord,\n getCoords,\n getGeom,\n getType\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { feature, point, lineString, isObject } from \"@turf/helpers\";\nfunction coordEach(geojson, callback, excludeWrapCoord) {\n if (geojson === null) return;\n var j, k, l, geometry, stopG, coords, geometryMaybeCollection, wrapShrink = 0, coordIndex = 0, isGeometryCollection, type = geojson.type, isFeatureCollection = type === \"FeatureCollection\", isFeature = type === \"Feature\", stop = isFeatureCollection ? geojson.features.length : 1;\n for (var featureIndex = 0; featureIndex < stop; featureIndex++) {\n geometryMaybeCollection = isFeatureCollection ? (\n // @ts-expect-error: Known type conflict\n geojson.features[featureIndex].geometry\n ) : isFeature ? (\n // @ts-expect-error: Known type conflict\n geojson.geometry\n ) : geojson;\n isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === \"GeometryCollection\" : false;\n stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;\n for (var geomIndex = 0; geomIndex < stopG; geomIndex++) {\n var multiFeatureIndex = 0;\n var geometryIndex = 0;\n geometry = isGeometryCollection ? geometryMaybeCollection.geometries[geomIndex] : geometryMaybeCollection;\n if (geometry === null) continue;\n coords = geometry.coordinates;\n var geomType = geometry.type;\n wrapShrink = excludeWrapCoord && (geomType === \"Polygon\" || geomType === \"MultiPolygon\") ? 1 : 0;\n switch (geomType) {\n case null:\n break;\n case \"Point\":\n if (\n // @ts-expect-error: Known type conflict\n callback(\n coords,\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n multiFeatureIndex++;\n break;\n case \"LineString\":\n case \"MultiPoint\":\n for (j = 0; j < coords.length; j++) {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n coords[j],\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n if (geomType === \"MultiPoint\") multiFeatureIndex++;\n }\n if (geomType === \"LineString\") multiFeatureIndex++;\n break;\n case \"Polygon\":\n case \"MultiLineString\":\n for (j = 0; j < coords.length; j++) {\n for (k = 0; k < coords[j].length - wrapShrink; k++) {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n coords[j][k],\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n }\n if (geomType === \"MultiLineString\") multiFeatureIndex++;\n if (geomType === \"Polygon\") geometryIndex++;\n }\n if (geomType === \"Polygon\") multiFeatureIndex++;\n break;\n case \"MultiPolygon\":\n for (j = 0; j < coords.length; j++) {\n geometryIndex = 0;\n for (k = 0; k < coords[j].length; k++) {\n for (l = 0; l < coords[j][k].length - wrapShrink; l++) {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n coords[j][k][l],\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n }\n geometryIndex++;\n }\n multiFeatureIndex++;\n }\n break;\n case \"GeometryCollection\":\n for (j = 0; j < geometry.geometries.length; j++)\n if (\n // @ts-expect-error: Known type conflict\n coordEach(geometry.geometries[j], callback, excludeWrapCoord) === false\n )\n return false;\n break;\n default:\n throw new Error(\"Unknown Geometry Type\");\n }\n }\n }\n}\nfunction coordReduce(geojson, callback, initialValue, excludeWrapCoord) {\n var previousValue = initialValue;\n coordEach(\n geojson,\n function(currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {\n if (coordIndex === 0 && initialValue === void 0)\n previousValue = currentCoord;\n else\n previousValue = callback(\n // @ts-expect-error: Known type conflict\n previousValue,\n currentCoord,\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n );\n },\n excludeWrapCoord\n );\n return previousValue;\n}\nfunction propEach(geojson, callback) {\n var i;\n switch (geojson.type) {\n case \"FeatureCollection\":\n for (i = 0; i < geojson.features.length; i++) {\n if (callback(geojson.features[i].properties, i) === false) break;\n }\n break;\n case \"Feature\":\n callback(geojson.properties, 0);\n break;\n }\n}\nfunction propReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n propEach(geojson, function(currentProperties, featureIndex) {\n if (featureIndex === 0 && initialValue === void 0)\n previousValue = currentProperties;\n else\n previousValue = callback(previousValue, currentProperties, featureIndex);\n });\n return previousValue;\n}\nfunction featureEach(geojson, callback) {\n if (geojson.type === \"Feature\") {\n callback(geojson, 0);\n } else if (geojson.type === \"FeatureCollection\") {\n for (var i = 0; i < geojson.features.length; i++) {\n if (callback(geojson.features[i], i) === false) break;\n }\n }\n}\nfunction featureReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n featureEach(geojson, function(currentFeature, featureIndex) {\n if (featureIndex === 0 && initialValue === void 0)\n previousValue = currentFeature;\n else previousValue = callback(previousValue, currentFeature, featureIndex);\n });\n return previousValue;\n}\nfunction coordAll(geojson) {\n var coords = [];\n coordEach(geojson, function(coord) {\n coords.push(coord);\n });\n return coords;\n}\nfunction geomEach(geojson, callback) {\n var i, j, g, geometry, stopG, geometryMaybeCollection, isGeometryCollection, featureProperties, featureBBox, featureId, featureIndex = 0, isFeatureCollection = geojson.type === \"FeatureCollection\", isFeature = geojson.type === \"Feature\", stop = isFeatureCollection ? geojson.features.length : 1;\n for (i = 0; i < stop; i++) {\n geometryMaybeCollection = isFeatureCollection ? (\n // @ts-expect-error: Known type conflict\n geojson.features[i].geometry\n ) : isFeature ? (\n // @ts-expect-error: Known type conflict\n geojson.geometry\n ) : geojson;\n featureProperties = isFeatureCollection ? (\n // @ts-expect-error: Known type conflict\n geojson.features[i].properties\n ) : isFeature ? (\n // @ts-expect-error: Known type conflict\n geojson.properties\n ) : {};\n featureBBox = isFeatureCollection ? (\n // @ts-expect-error: Known type conflict\n geojson.features[i].bbox\n ) : isFeature ? (\n // @ts-expect-error: Known type conflict\n geojson.bbox\n ) : void 0;\n featureId = isFeatureCollection ? (\n // @ts-expect-error: Known type conflict\n geojson.features[i].id\n ) : isFeature ? (\n // @ts-expect-error: Known type conflict\n geojson.id\n ) : void 0;\n isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === \"GeometryCollection\" : false;\n stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;\n for (g = 0; g < stopG; g++) {\n geometry = isGeometryCollection ? geometryMaybeCollection.geometries[g] : geometryMaybeCollection;\n if (geometry === null) {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n // @ts-expect-error: Known type conflict\n null,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) === false\n )\n return false;\n continue;\n }\n switch (geometry.type) {\n case \"Point\":\n case \"LineString\":\n case \"MultiPoint\":\n case \"Polygon\":\n case \"MultiLineString\":\n case \"MultiPolygon\": {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n geometry,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) === false\n )\n return false;\n break;\n }\n case \"GeometryCollection\": {\n for (j = 0; j < geometry.geometries.length; j++) {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n geometry.geometries[j],\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) === false\n )\n return false;\n }\n break;\n }\n default:\n throw new Error(\"Unknown Geometry Type\");\n }\n }\n featureIndex++;\n }\n}\nfunction geomReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n geomEach(\n geojson,\n function(currentGeometry, featureIndex, featureProperties, featureBBox, featureId) {\n if (featureIndex === 0 && initialValue === void 0)\n previousValue = currentGeometry;\n else\n previousValue = callback(\n // @ts-expect-error: Known type conflict\n previousValue,\n currentGeometry,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n );\n }\n );\n return previousValue;\n}\nfunction flattenEach(geojson, callback) {\n geomEach(geojson, function(geometry, featureIndex, properties, bbox, id) {\n var type = geometry === null ? null : geometry.type;\n switch (type) {\n case null:\n case \"Point\":\n case \"LineString\":\n case \"Polygon\":\n if (\n // @ts-expect-error: Known type conflict\n callback(\n feature(geometry, properties, { bbox, id }),\n featureIndex,\n 0\n ) === false\n )\n return false;\n return;\n }\n var geomType;\n switch (type) {\n case \"MultiPoint\":\n geomType = \"Point\";\n break;\n case \"MultiLineString\":\n geomType = \"LineString\";\n break;\n case \"MultiPolygon\":\n geomType = \"Polygon\";\n break;\n }\n for (\n var multiFeatureIndex = 0;\n // @ts-expect-error: Known type conflict\n multiFeatureIndex < geometry.coordinates.length;\n multiFeatureIndex++\n ) {\n var coordinate = geometry.coordinates[multiFeatureIndex];\n var geom = {\n type: geomType,\n coordinates: coordinate\n };\n if (\n // @ts-expect-error: Known type conflict\n callback(feature(geom, properties), featureIndex, multiFeatureIndex) === false\n )\n return false;\n }\n });\n}\nfunction flattenReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n flattenEach(\n geojson,\n function(currentFeature, featureIndex, multiFeatureIndex) {\n if (featureIndex === 0 && multiFeatureIndex === 0 && initialValue === void 0)\n previousValue = currentFeature;\n else\n previousValue = callback(\n // @ts-expect-error: Known type conflict\n previousValue,\n currentFeature,\n featureIndex,\n multiFeatureIndex\n );\n }\n );\n return previousValue;\n}\nfunction segmentEach(geojson, callback) {\n flattenEach(geojson, function(feature2, featureIndex, multiFeatureIndex) {\n var segmentIndex = 0;\n if (!feature2.geometry) return;\n var type = feature2.geometry.type;\n if (type === \"Point\" || type === \"MultiPoint\") return;\n var previousCoords;\n var previousFeatureIndex = 0;\n var previousMultiIndex = 0;\n var prevGeomIndex = 0;\n if (\n // @ts-expect-error: Known type conflict\n coordEach(\n feature2,\n function(currentCoord, coordIndex, featureIndexCoord, multiPartIndexCoord, geometryIndex) {\n if (\n // @ts-expect-error: Known type conflict\n previousCoords === void 0 || featureIndex > previousFeatureIndex || multiPartIndexCoord > previousMultiIndex || geometryIndex > prevGeomIndex\n ) {\n previousCoords = currentCoord;\n previousFeatureIndex = featureIndex;\n previousMultiIndex = multiPartIndexCoord;\n prevGeomIndex = geometryIndex;\n segmentIndex = 0;\n return;\n }\n var currentSegment = lineString(\n // @ts-expect-error: Known type conflict\n [previousCoords, currentCoord],\n feature2.properties\n );\n if (\n // @ts-expect-error: Known type conflict\n callback(\n // @ts-expect-error: Known type conflict\n currentSegment,\n featureIndex,\n multiFeatureIndex,\n geometryIndex,\n segmentIndex\n ) === false\n )\n return false;\n segmentIndex++;\n previousCoords = currentCoord;\n }\n ) === false\n )\n return false;\n });\n}\nfunction segmentReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n var started = false;\n segmentEach(\n geojson,\n function(currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) {\n if (started === false && initialValue === void 0)\n previousValue = currentSegment;\n else\n previousValue = callback(\n previousValue,\n // @ts-expect-error: Known type conflict\n currentSegment,\n featureIndex,\n multiFeatureIndex,\n geometryIndex,\n segmentIndex\n );\n started = true;\n }\n );\n return previousValue;\n}\nfunction lineEach(geojson, callback) {\n if (!geojson) throw new Error(\"geojson is required\");\n flattenEach(geojson, function(feature2, featureIndex, multiFeatureIndex) {\n if (feature2.geometry === null) return;\n var type = feature2.geometry.type;\n var coords = feature2.geometry.coordinates;\n switch (type) {\n case \"LineString\":\n if (callback(feature2, featureIndex, multiFeatureIndex, 0, 0) === false)\n return false;\n break;\n case \"Polygon\":\n for (var geometryIndex = 0; geometryIndex < coords.length; geometryIndex++) {\n if (\n // @ts-expect-error: Known type conflict\n callback(\n // @ts-expect-error: Known type conflict\n lineString(coords[geometryIndex], feature2.properties),\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n }\n break;\n }\n });\n}\nfunction lineReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n lineEach(\n geojson,\n function(currentLine, featureIndex, multiFeatureIndex, geometryIndex) {\n if (featureIndex === 0 && initialValue === void 0)\n previousValue = currentLine;\n else\n previousValue = callback(\n previousValue,\n currentLine,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n );\n }\n );\n return previousValue;\n}\nfunction findSegment(geojson, options) {\n options = options || {};\n if (!isObject(options)) throw new Error(\"options is invalid\");\n var featureIndex = options.featureIndex || 0;\n var multiFeatureIndex = options.multiFeatureIndex || 0;\n var geometryIndex = options.geometryIndex || 0;\n var segmentIndex = options.segmentIndex || 0;\n var properties = options.properties;\n var geometry;\n switch (geojson.type) {\n case \"FeatureCollection\":\n if (featureIndex < 0)\n featureIndex = geojson.features.length + featureIndex;\n properties = properties || geojson.features[featureIndex].properties;\n geometry = geojson.features[featureIndex].geometry;\n break;\n case \"Feature\":\n properties = properties || geojson.properties;\n geometry = geojson.geometry;\n break;\n case \"Point\":\n case \"MultiPoint\":\n return null;\n case \"LineString\":\n case \"Polygon\":\n case \"MultiLineString\":\n case \"MultiPolygon\":\n geometry = geojson;\n break;\n default:\n throw new Error(\"geojson is invalid\");\n }\n if (geometry === null) return null;\n var coords = geometry.coordinates;\n switch (geometry.type) {\n case \"Point\":\n case \"MultiPoint\":\n return null;\n case \"LineString\":\n if (segmentIndex < 0) segmentIndex = coords.length + segmentIndex - 1;\n return lineString(\n // @ts-expect-error: Known type conflict\n [coords[segmentIndex], coords[segmentIndex + 1]],\n properties,\n options\n );\n case \"Polygon\":\n if (geometryIndex < 0) geometryIndex = coords.length + geometryIndex;\n if (segmentIndex < 0)\n segmentIndex = coords[geometryIndex].length + segmentIndex - 1;\n return lineString(\n [\n // @ts-expect-error: Known type conflict\n coords[geometryIndex][segmentIndex],\n // @ts-expect-error: Known type conflict\n coords[geometryIndex][segmentIndex + 1]\n ],\n properties,\n options\n );\n case \"MultiLineString\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (segmentIndex < 0)\n segmentIndex = coords[multiFeatureIndex].length + segmentIndex - 1;\n return lineString(\n [\n // @ts-expect-error: Known type conflict\n coords[multiFeatureIndex][segmentIndex],\n // @ts-expect-error: Known type conflict\n coords[multiFeatureIndex][segmentIndex + 1]\n ],\n properties,\n options\n );\n case \"MultiPolygon\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (geometryIndex < 0)\n geometryIndex = coords[multiFeatureIndex].length + geometryIndex;\n if (segmentIndex < 0)\n segmentIndex = // @ts-expect-error: Known type conflict\n coords[multiFeatureIndex][geometryIndex].length - segmentIndex - 1;\n return lineString(\n [\n // @ts-expect-error: Known type conflict\n coords[multiFeatureIndex][geometryIndex][segmentIndex],\n // @ts-expect-error: Known type conflict\n coords[multiFeatureIndex][geometryIndex][segmentIndex + 1]\n ],\n properties,\n options\n );\n }\n throw new Error(\"geojson is invalid\");\n}\nfunction findPoint(geojson, options) {\n options = options || {};\n if (!isObject(options)) throw new Error(\"options is invalid\");\n var featureIndex = options.featureIndex || 0;\n var multiFeatureIndex = options.multiFeatureIndex || 0;\n var geometryIndex = options.geometryIndex || 0;\n var coordIndex = options.coordIndex || 0;\n var properties = options.properties;\n var geometry;\n switch (geojson.type) {\n case \"FeatureCollection\":\n if (featureIndex < 0)\n featureIndex = geojson.features.length + featureIndex;\n properties = properties || geojson.features[featureIndex].properties;\n geometry = geojson.features[featureIndex].geometry;\n break;\n case \"Feature\":\n properties = properties || geojson.properties;\n geometry = geojson.geometry;\n break;\n case \"Point\":\n case \"MultiPoint\":\n return null;\n case \"LineString\":\n case \"Polygon\":\n case \"MultiLineString\":\n case \"MultiPolygon\":\n geometry = geojson;\n break;\n default:\n throw new Error(\"geojson is invalid\");\n }\n if (geometry === null) return null;\n var coords = geometry.coordinates;\n switch (geometry.type) {\n case \"Point\":\n return point(coords, properties, options);\n case \"MultiPoint\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n return point(coords[multiFeatureIndex], properties, options);\n case \"LineString\":\n if (coordIndex < 0) coordIndex = coords.length + coordIndex;\n return point(coords[coordIndex], properties, options);\n case \"Polygon\":\n if (geometryIndex < 0) geometryIndex = coords.length + geometryIndex;\n if (coordIndex < 0)\n coordIndex = coords[geometryIndex].length + coordIndex;\n return point(coords[geometryIndex][coordIndex], properties, options);\n case \"MultiLineString\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (coordIndex < 0)\n coordIndex = coords[multiFeatureIndex].length + coordIndex;\n return point(coords[multiFeatureIndex][coordIndex], properties, options);\n case \"MultiPolygon\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (geometryIndex < 0)\n geometryIndex = coords[multiFeatureIndex].length + geometryIndex;\n if (coordIndex < 0)\n coordIndex = coords[multiFeatureIndex][geometryIndex].length - coordIndex;\n return point(\n coords[multiFeatureIndex][geometryIndex][coordIndex],\n properties,\n options\n );\n }\n throw new Error(\"geojson is invalid\");\n}\nexport {\n coordAll,\n coordEach,\n coordReduce,\n featureEach,\n featureReduce,\n findPoint,\n findSegment,\n flattenEach,\n flattenReduce,\n geomEach,\n geomReduce,\n lineEach,\n lineReduce,\n propEach,\n propReduce,\n segmentEach,\n segmentReduce\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { coordEach } from \"@turf/meta\";\nfunction bbox(geojson, options = {}) {\n if (geojson.bbox != null && true !== options.recompute) {\n return geojson.bbox;\n }\n const result = [Infinity, Infinity, -Infinity, -Infinity];\n coordEach(geojson, (coord) => {\n if (result[0] > coord[0]) {\n result[0] = coord[0];\n }\n if (result[1] > coord[1]) {\n result[1] = coord[1];\n }\n if (result[2] < coord[0]) {\n result[2] = coord[0];\n }\n if (result[3] < coord[1]) {\n result[3] = coord[1];\n }\n });\n return result;\n}\nvar index_default = bbox;\nexport {\n bbox,\n index_default as default\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { polygon } from \"@turf/helpers\";\nfunction bboxPolygon(bbox, options = {}) {\n const west = Number(bbox[0]);\n const south = Number(bbox[1]);\n const east = Number(bbox[2]);\n const north = Number(bbox[3]);\n if (bbox.length === 6) {\n throw new Error(\n \"@turf/bbox-polygon does not support BBox with 6 positions\"\n );\n }\n const lowLeft = [west, south];\n const topLeft = [west, north];\n const topRight = [east, north];\n const lowRight = [east, south];\n return polygon(\n [[lowLeft, lowRight, topRight, topLeft, lowLeft]],\n options.properties,\n { bbox, id: options.id }\n );\n}\nvar index_default = bboxPolygon;\nexport {\n bboxPolygon,\n index_default as default\n};\n//# sourceMappingURL=index.js.map","export const epsilon = 1.1102230246251565e-16;\nexport const splitter = 134217729;\nexport const resulterrbound = (3 + 8 * epsilon) * epsilon;\n\n// fast_expansion_sum_zeroelim routine from original code\nexport function sum(elen, e, flen, f, h) {\n let Q, Qnew, hh, bvirt;\n let enow = e[0];\n let fnow = f[0];\n let eindex = 0;\n let findex = 0;\n if ((fnow > enow) === (fnow > -enow)) {\n Q = enow;\n enow = e[++eindex];\n } else {\n Q = fnow;\n fnow = f[++findex];\n }\n let hindex = 0;\n if (eindex < elen && findex < flen) {\n if ((fnow > enow) === (fnow > -enow)) {\n Qnew = enow + Q;\n hh = Q - (Qnew - enow);\n enow = e[++eindex];\n } else {\n Qnew = fnow + Q;\n hh = Q - (Qnew - fnow);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n while (eindex < elen && findex < flen) {\n if ((fnow > enow) === (fnow > -enow)) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n } else {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n }\n while (eindex < elen) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n while (findex < flen) {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\n\nexport function sum_three(alen, a, blen, b, clen, c, tmp, out) {\n return sum(sum(alen, a, blen, b, tmp), tmp, clen, c, out);\n}\n\n// scale_expansion_zeroelim routine from oritinal code\nexport function scale(elen, e, b, h) {\n let Q, sum, hh, product1, product0;\n let bvirt, c, ahi, alo, bhi, blo;\n\n c = splitter * b;\n bhi = c - (c - b);\n blo = b - bhi;\n let enow = e[0];\n Q = enow * b;\n c = splitter * enow;\n ahi = c - (c - enow);\n alo = enow - ahi;\n hh = alo * blo - (Q - ahi * bhi - alo * bhi - ahi * blo);\n let hindex = 0;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n for (let i = 1; i < elen; i++) {\n enow = e[i];\n product1 = enow * b;\n c = splitter * enow;\n ahi = c - (c - enow);\n alo = enow - ahi;\n product0 = alo * blo - (product1 - ahi * bhi - alo * bhi - ahi * blo);\n sum = Q + product0;\n bvirt = sum - Q;\n hh = Q - (sum - bvirt) + (product0 - bvirt);\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n Q = product1 + sum;\n hh = sum - (Q - product1);\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\n\nexport function negate(elen, e) {\n for (let i = 0; i < elen; i++) e[i] = -e[i];\n return elen;\n}\n\nexport function estimate(elen, e) {\n let Q = e[0];\n for (let i = 1; i < elen; i++) Q += e[i];\n return Q;\n}\n\nexport function vec(n) {\n return new Float64Array(n);\n}\n","import {epsilon, splitter, resulterrbound, estimate, vec, sum} from './util.js';\n\nconst ccwerrboundA = (3 + 16 * epsilon) * epsilon;\nconst ccwerrboundB = (2 + 12 * epsilon) * epsilon;\nconst ccwerrboundC = (9 + 64 * epsilon) * epsilon * epsilon;\n\nconst B = vec(4);\nconst C1 = vec(8);\nconst C2 = vec(12);\nconst D = vec(16);\nconst u = vec(4);\n\nfunction orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {\n let acxtail, acytail, bcxtail, bcytail;\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;\n\n const acx = ax - cx;\n const bcx = bx - cx;\n const acy = ay - cy;\n const bcy = by - cy;\n\n s1 = acx * bcy;\n c = splitter * acx;\n ahi = c - (c - acx);\n alo = acx - ahi;\n c = splitter * bcy;\n bhi = c - (c - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acy * bcx;\n c = splitter * acy;\n ahi = c - (c - acy);\n alo = acy - ahi;\n c = splitter * bcx;\n bhi = c - (c - bcx);\n blo = bcx - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n B[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n B[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n B[2] = _j - (u3 - bvirt) + (_i - bvirt);\n B[3] = u3;\n\n let det = estimate(4, B);\n let errbound = ccwerrboundB * detsum;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n bvirt = ax - acx;\n acxtail = ax - (acx + bvirt) + (bvirt - cx);\n bvirt = bx - bcx;\n bcxtail = bx - (bcx + bvirt) + (bvirt - cx);\n bvirt = ay - acy;\n acytail = ay - (acy + bvirt) + (bvirt - cy);\n bvirt = by - bcy;\n bcytail = by - (bcy + bvirt) + (bvirt - cy);\n\n if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {\n return det;\n }\n\n errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);\n det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);\n if (det >= errbound || -det >= errbound) return det;\n\n s1 = acxtail * bcy;\n c = splitter * acxtail;\n ahi = c - (c - acxtail);\n alo = acxtail - ahi;\n c = splitter * bcy;\n bhi = c - (c - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acytail * bcx;\n c = splitter * acytail;\n ahi = c - (c - acytail);\n alo = acytail - ahi;\n c = splitter * bcx;\n bhi = c - (c - bcx);\n blo = bcx - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const C1len = sum(4, B, 4, u, C1);\n\n s1 = acx * bcytail;\n c = splitter * acx;\n ahi = c - (c - acx);\n alo = acx - ahi;\n c = splitter * bcytail;\n bhi = c - (c - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acy * bcxtail;\n c = splitter * acy;\n ahi = c - (c - acy);\n alo = acy - ahi;\n c = splitter * bcxtail;\n bhi = c - (c - bcxtail);\n blo = bcxtail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const C2len = sum(C1len, C1, 4, u, C2);\n\n s1 = acxtail * bcytail;\n c = splitter * acxtail;\n ahi = c - (c - acxtail);\n alo = acxtail - ahi;\n c = splitter * bcytail;\n bhi = c - (c - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acytail * bcxtail;\n c = splitter * acytail;\n ahi = c - (c - acytail);\n alo = acytail - ahi;\n c = splitter * bcxtail;\n bhi = c - (c - bcxtail);\n blo = bcxtail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const Dlen = sum(C2len, C2, 4, u, D);\n\n return D[Dlen - 1];\n}\n\nexport function orient2d(ax, ay, bx, by, cx, cy) {\n const detleft = (ay - cy) * (bx - cx);\n const detright = (ax - cx) * (by - cy);\n const det = detleft - detright;\n\n const detsum = Math.abs(detleft + detright);\n if (Math.abs(det) >= ccwerrboundA * detsum) return det;\n\n return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);\n}\n\nexport function orient2dfast(ax, ay, bx, by, cx, cy) {\n return (ay - cy) * (bx - cx) - (ax - cx) * (by - cy);\n}\n","import {epsilon, splitter, resulterrbound, estimate, vec, sum, scale} from './util.js';\n\nconst o3derrboundA = (7 + 56 * epsilon) * epsilon;\nconst o3derrboundB = (3 + 28 * epsilon) * epsilon;\nconst o3derrboundC = (26 + 288 * epsilon) * epsilon * epsilon;\n\nconst bc = vec(4);\nconst ca = vec(4);\nconst ab = vec(4);\nconst at_b = vec(4);\nconst at_c = vec(4);\nconst bt_c = vec(4);\nconst bt_a = vec(4);\nconst ct_a = vec(4);\nconst ct_b = vec(4);\nconst bct = vec(8);\nconst cat = vec(8);\nconst abt = vec(8);\nconst u = vec(4);\n\nconst _8 = vec(8);\nconst _8b = vec(8);\nconst _16 = vec(16);\nconst _12 = vec(12);\n\nlet fin = vec(192);\nlet fin2 = vec(192);\n\nfunction finadd(finlen, alen, a) {\n finlen = sum(finlen, fin, alen, a, fin2);\n const tmp = fin; fin = fin2; fin2 = tmp;\n return finlen;\n}\n\nfunction tailinit(xtail, ytail, ax, ay, bx, by, a, b) {\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _k, _0, s1, s0, t1, t0, u3, negate;\n if (xtail === 0) {\n if (ytail === 0) {\n a[0] = 0;\n b[0] = 0;\n return 1;\n }\n negate = -ytail;\n s1 = negate * ax;\n c = splitter * negate;\n ahi = c - (c - negate);\n alo = negate - ahi;\n c = splitter * ax;\n bhi = c - (c - ax);\n blo = ax - bhi;\n a[0] = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n a[1] = s1;\n s1 = ytail * bx;\n c = splitter * ytail;\n ahi = c - (c - ytail);\n alo = ytail - ahi;\n c = splitter * bx;\n bhi = c - (c - bx);\n blo = bx - bhi;\n b[0] = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n b[1] = s1;\n return 2;\n }\n if (ytail === 0) {\n s1 = xtail * ay;\n c = splitter * xtail;\n ahi = c - (c - xtail);\n alo = xtail - ahi;\n c = splitter * ay;\n bhi = c - (c - ay);\n blo = ay - bhi;\n a[0] = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n a[1] = s1;\n negate = -xtail;\n s1 = negate * by;\n c = splitter * negate;\n ahi = c - (c - negate);\n alo = negate - ahi;\n c = splitter * by;\n bhi = c - (c - by);\n blo = by - bhi;\n b[0] = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n b[1] = s1;\n return 2;\n }\n s1 = xtail * ay;\n c = splitter * xtail;\n ahi = c - (c - xtail);\n alo = xtail - ahi;\n c = splitter * ay;\n bhi = c - (c - ay);\n blo = ay - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = ytail * ax;\n c = splitter * ytail;\n ahi = c - (c - ytail);\n alo = ytail - ahi;\n c = splitter * ax;\n bhi = c - (c - ax);\n blo = ax - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n a[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n a[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n a[2] = _j - (u3 - bvirt) + (_i - bvirt);\n a[3] = u3;\n s1 = ytail * bx;\n c = splitter * ytail;\n ahi = c - (c - ytail);\n alo = ytail - ahi;\n c = splitter * bx;\n bhi = c - (c - bx);\n blo = bx - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = xtail * by;\n c = splitter * xtail;\n ahi = c - (c - xtail);\n alo = xtail - ahi;\n c = splitter * by;\n bhi = c - (c - by);\n blo = by - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n b[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n b[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n b[2] = _j - (u3 - bvirt) + (_i - bvirt);\n b[3] = u3;\n return 4;\n}\n\nfunction tailadd(finlen, a, b, k, z) {\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _k, _0, s1, s0, u3;\n s1 = a * b;\n c = splitter * a;\n ahi = c - (c - a);\n alo = a - ahi;\n c = splitter * b;\n bhi = c - (c - b);\n blo = b - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n c = splitter * k;\n bhi = c - (c - k);\n blo = k - bhi;\n _i = s0 * k;\n c = splitter * s0;\n ahi = c - (c - s0);\n alo = s0 - ahi;\n u[0] = alo * blo - (_i - ahi * bhi - alo * bhi - ahi * blo);\n _j = s1 * k;\n c = splitter * s1;\n ahi = c - (c - s1);\n alo = s1 - ahi;\n _0 = alo * blo - (_j - ahi * bhi - alo * bhi - ahi * blo);\n _k = _i + _0;\n bvirt = _k - _i;\n u[1] = _i - (_k - bvirt) + (_0 - bvirt);\n u3 = _j + _k;\n u[2] = _k - (u3 - _j);\n u[3] = u3;\n finlen = finadd(finlen, 4, u);\n if (z !== 0) {\n c = splitter * z;\n bhi = c - (c - z);\n blo = z - bhi;\n _i = s0 * z;\n c = splitter * s0;\n ahi = c - (c - s0);\n alo = s0 - ahi;\n u[0] = alo * blo - (_i - ahi * bhi - alo * bhi - ahi * blo);\n _j = s1 * z;\n c = splitter * s1;\n ahi = c - (c - s1);\n alo = s1 - ahi;\n _0 = alo * blo - (_j - ahi * bhi - alo * bhi - ahi * blo);\n _k = _i + _0;\n bvirt = _k - _i;\n u[1] = _i - (_k - bvirt) + (_0 - bvirt);\n u3 = _j + _k;\n u[2] = _k - (u3 - _j);\n u[3] = u3;\n finlen = finadd(finlen, 4, u);\n }\n return finlen;\n}\n\nfunction orient3dadapt(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, permanent) {\n let finlen;\n let adxtail, bdxtail, cdxtail;\n let adytail, bdytail, cdytail;\n let adztail, bdztail, cdztail;\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _k, _0, s1, s0, t1, t0, u3;\n\n const adx = ax - dx;\n const bdx = bx - dx;\n const cdx = cx - dx;\n const ady = ay - dy;\n const bdy = by - dy;\n const cdy = cy - dy;\n const adz = az - dz;\n const bdz = bz - dz;\n const cdz = cz - dz;\n\n s1 = bdx * cdy;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n c = splitter * cdy;\n bhi = c - (c - cdy);\n blo = cdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cdx * bdy;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n c = splitter * bdy;\n bhi = c - (c - bdy);\n blo = bdy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bc[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bc[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n bc[2] = _j - (u3 - bvirt) + (_i - bvirt);\n bc[3] = u3;\n s1 = cdx * ady;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n c = splitter * ady;\n bhi = c - (c - ady);\n blo = ady - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = adx * cdy;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n c = splitter * cdy;\n bhi = c - (c - cdy);\n blo = cdy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ca[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ca[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ca[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ca[3] = u3;\n s1 = adx * bdy;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n c = splitter * bdy;\n bhi = c - (c - bdy);\n blo = bdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bdx * ady;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n c = splitter * ady;\n bhi = c - (c - ady);\n blo = ady - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ab[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ab[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ab[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ab[3] = u3;\n\n finlen = sum(\n sum(\n scale(4, bc, adz, _8), _8,\n scale(4, ca, bdz, _8b), _8b, _16), _16,\n scale(4, ab, cdz, _8), _8, fin);\n\n let det = estimate(finlen, fin);\n let errbound = o3derrboundB * permanent;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n bvirt = ax - adx;\n adxtail = ax - (adx + bvirt) + (bvirt - dx);\n bvirt = bx - bdx;\n bdxtail = bx - (bdx + bvirt) + (bvirt - dx);\n bvirt = cx - cdx;\n cdxtail = cx - (cdx + bvirt) + (bvirt - dx);\n bvirt = ay - ady;\n adytail = ay - (ady + bvirt) + (bvirt - dy);\n bvirt = by - bdy;\n bdytail = by - (bdy + bvirt) + (bvirt - dy);\n bvirt = cy - cdy;\n cdytail = cy - (cdy + bvirt) + (bvirt - dy);\n bvirt = az - adz;\n adztail = az - (adz + bvirt) + (bvirt - dz);\n bvirt = bz - bdz;\n bdztail = bz - (bdz + bvirt) + (bvirt - dz);\n bvirt = cz - cdz;\n cdztail = cz - (cdz + bvirt) + (bvirt - dz);\n\n if (adxtail === 0 && bdxtail === 0 && cdxtail === 0 &&\n adytail === 0 && bdytail === 0 && cdytail === 0 &&\n adztail === 0 && bdztail === 0 && cdztail === 0) {\n return det;\n }\n\n errbound = o3derrboundC * permanent + resulterrbound * Math.abs(det);\n det +=\n adz * (bdx * cdytail + cdy * bdxtail - (bdy * cdxtail + cdx * bdytail)) + adztail * (bdx * cdy - bdy * cdx) +\n bdz * (cdx * adytail + ady * cdxtail - (cdy * adxtail + adx * cdytail)) + bdztail * (cdx * ady - cdy * adx) +\n cdz * (adx * bdytail + bdy * adxtail - (ady * bdxtail + bdx * adytail)) + cdztail * (adx * bdy - ady * bdx);\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n const at_len = tailinit(adxtail, adytail, bdx, bdy, cdx, cdy, at_b, at_c);\n const bt_len = tailinit(bdxtail, bdytail, cdx, cdy, adx, ady, bt_c, bt_a);\n const ct_len = tailinit(cdxtail, cdytail, adx, ady, bdx, bdy, ct_a, ct_b);\n\n const bctlen = sum(bt_len, bt_c, ct_len, ct_b, bct);\n finlen = finadd(finlen, scale(bctlen, bct, adz, _16), _16);\n\n const catlen = sum(ct_len, ct_a, at_len, at_c, cat);\n finlen = finadd(finlen, scale(catlen, cat, bdz, _16), _16);\n\n const abtlen = sum(at_len, at_b, bt_len, bt_a, abt);\n finlen = finadd(finlen, scale(abtlen, abt, cdz, _16), _16);\n\n if (adztail !== 0) {\n finlen = finadd(finlen, scale(4, bc, adztail, _12), _12);\n finlen = finadd(finlen, scale(bctlen, bct, adztail, _16), _16);\n }\n if (bdztail !== 0) {\n finlen = finadd(finlen, scale(4, ca, bdztail, _12), _12);\n finlen = finadd(finlen, scale(catlen, cat, bdztail, _16), _16);\n }\n if (cdztail !== 0) {\n finlen = finadd(finlen, scale(4, ab, cdztail, _12), _12);\n finlen = finadd(finlen, scale(abtlen, abt, cdztail, _16), _16);\n }\n\n if (adxtail !== 0) {\n if (bdytail !== 0) {\n finlen = tailadd(finlen, adxtail, bdytail, cdz, cdztail);\n }\n if (cdytail !== 0) {\n finlen = tailadd(finlen, -adxtail, cdytail, bdz, bdztail);\n }\n }\n if (bdxtail !== 0) {\n if (cdytail !== 0) {\n finlen = tailadd(finlen, bdxtail, cdytail, adz, adztail);\n }\n if (adytail !== 0) {\n finlen = tailadd(finlen, -bdxtail, adytail, cdz, cdztail);\n }\n }\n if (cdxtail !== 0) {\n if (adytail !== 0) {\n finlen = tailadd(finlen, cdxtail, adytail, bdz, bdztail);\n }\n if (bdytail !== 0) {\n finlen = tailadd(finlen, -cdxtail, bdytail, adz, adztail);\n }\n }\n\n return fin[finlen - 1];\n}\n\nexport function orient3d(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz) {\n const adx = ax - dx;\n const bdx = bx - dx;\n const cdx = cx - dx;\n const ady = ay - dy;\n const bdy = by - dy;\n const cdy = cy - dy;\n const adz = az - dz;\n const bdz = bz - dz;\n const cdz = cz - dz;\n\n const bdxcdy = bdx * cdy;\n const cdxbdy = cdx * bdy;\n\n const cdxady = cdx * ady;\n const adxcdy = adx * cdy;\n\n const adxbdy = adx * bdy;\n const bdxady = bdx * ady;\n\n const det =\n adz * (bdxcdy - cdxbdy) +\n bdz * (cdxady - adxcdy) +\n cdz * (adxbdy - bdxady);\n\n const permanent =\n (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * Math.abs(adz) +\n (Math.abs(cdxady) + Math.abs(adxcdy)) * Math.abs(bdz) +\n (Math.abs(adxbdy) + Math.abs(bdxady)) * Math.abs(cdz);\n\n const errbound = o3derrboundA * permanent;\n if (det > errbound || -det > errbound) {\n return det;\n }\n\n return orient3dadapt(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, permanent);\n}\n\nexport function orient3dfast(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz) {\n const adx = ax - dx;\n const bdx = bx - dx;\n const cdx = cx - dx;\n const ady = ay - dy;\n const bdy = by - dy;\n const cdy = cy - dy;\n const adz = az - dz;\n const bdz = bz - dz;\n const cdz = cz - dz;\n\n return adx * (bdy * cdz - bdz * cdy) +\n bdx * (cdy * adz - cdz * ady) +\n cdx * (ady * bdz - adz * bdy);\n}\n","import {epsilon, splitter, resulterrbound, estimate, vec, sum, sum_three, scale} from './util.js';\n\nconst iccerrboundA = (10 + 96 * epsilon) * epsilon;\nconst iccerrboundB = (4 + 48 * epsilon) * epsilon;\nconst iccerrboundC = (44 + 576 * epsilon) * epsilon * epsilon;\n\nconst bc = vec(4);\nconst ca = vec(4);\nconst ab = vec(4);\nconst aa = vec(4);\nconst bb = vec(4);\nconst cc = vec(4);\nconst u = vec(4);\nconst v = vec(4);\nconst axtbc = vec(8);\nconst aytbc = vec(8);\nconst bxtca = vec(8);\nconst bytca = vec(8);\nconst cxtab = vec(8);\nconst cytab = vec(8);\nconst abt = vec(8);\nconst bct = vec(8);\nconst cat = vec(8);\nconst abtt = vec(4);\nconst bctt = vec(4);\nconst catt = vec(4);\n\nconst _8 = vec(8);\nconst _16 = vec(16);\nconst _16b = vec(16);\nconst _16c = vec(16);\nconst _32 = vec(32);\nconst _32b = vec(32);\nconst _48 = vec(48);\nconst _64 = vec(64);\n\nlet fin = vec(1152);\nlet fin2 = vec(1152);\n\nfunction finadd(finlen, a, alen) {\n finlen = sum(finlen, fin, a, alen, fin2);\n const tmp = fin; fin = fin2; fin2 = tmp;\n return finlen;\n}\n\nfunction incircleadapt(ax, ay, bx, by, cx, cy, dx, dy, permanent) {\n let finlen;\n let adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;\n let axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;\n let abtlen, bctlen, catlen;\n let abttlen, bcttlen, cattlen;\n let n1, n0;\n\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;\n\n const adx = ax - dx;\n const bdx = bx - dx;\n const cdx = cx - dx;\n const ady = ay - dy;\n const bdy = by - dy;\n const cdy = cy - dy;\n\n s1 = bdx * cdy;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n c = splitter * cdy;\n bhi = c - (c - cdy);\n blo = cdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cdx * bdy;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n c = splitter * bdy;\n bhi = c - (c - bdy);\n blo = bdy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bc[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bc[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n bc[2] = _j - (u3 - bvirt) + (_i - bvirt);\n bc[3] = u3;\n s1 = cdx * ady;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n c = splitter * ady;\n bhi = c - (c - ady);\n blo = ady - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = adx * cdy;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n c = splitter * cdy;\n bhi = c - (c - cdy);\n blo = cdy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ca[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ca[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ca[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ca[3] = u3;\n s1 = adx * bdy;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n c = splitter * bdy;\n bhi = c - (c - bdy);\n blo = bdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bdx * ady;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n c = splitter * ady;\n bhi = c - (c - ady);\n blo = ady - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ab[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ab[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ab[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ab[3] = u3;\n\n finlen = sum(\n sum(\n sum(\n scale(scale(4, bc, adx, _8), _8, adx, _16), _16,\n scale(scale(4, bc, ady, _8), _8, ady, _16b), _16b, _32), _32,\n sum(\n scale(scale(4, ca, bdx, _8), _8, bdx, _16), _16,\n scale(scale(4, ca, bdy, _8), _8, bdy, _16b), _16b, _32b), _32b, _64), _64,\n sum(\n scale(scale(4, ab, cdx, _8), _8, cdx, _16), _16,\n scale(scale(4, ab, cdy, _8), _8, cdy, _16b), _16b, _32), _32, fin);\n\n let det = estimate(finlen, fin);\n let errbound = iccerrboundB * permanent;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n bvirt = ax - adx;\n adxtail = ax - (adx + bvirt) + (bvirt - dx);\n bvirt = ay - ady;\n adytail = ay - (ady + bvirt) + (bvirt - dy);\n bvirt = bx - bdx;\n bdxtail = bx - (bdx + bvirt) + (bvirt - dx);\n bvirt = by - bdy;\n bdytail = by - (bdy + bvirt) + (bvirt - dy);\n bvirt = cx - cdx;\n cdxtail = cx - (cdx + bvirt) + (bvirt - dx);\n bvirt = cy - cdy;\n cdytail = cy - (cdy + bvirt) + (bvirt - dy);\n if (adxtail === 0 && bdxtail === 0 && cdxtail === 0 && adytail === 0 && bdytail === 0 && cdytail === 0) {\n return det;\n }\n\n errbound = iccerrboundC * permanent + resulterrbound * Math.abs(det);\n det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail) - (bdy * cdxtail + cdx * bdytail)) +\n 2 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx)) +\n ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail) - (cdy * adxtail + adx * cdytail)) +\n 2 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx)) +\n ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail) - (ady * bdxtail + bdx * adytail)) +\n 2 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));\n\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n if (bdxtail !== 0 || bdytail !== 0 || cdxtail !== 0 || cdytail !== 0) {\n s1 = adx * adx;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n s0 = alo * alo - (s1 - ahi * ahi - (ahi + ahi) * alo);\n t1 = ady * ady;\n c = splitter * ady;\n ahi = c - (c - ady);\n alo = ady - ahi;\n t0 = alo * alo - (t1 - ahi * ahi - (ahi + ahi) * alo);\n _i = s0 + t0;\n bvirt = _i - s0;\n aa[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n aa[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n aa[2] = _j - (u3 - bvirt) + (_i - bvirt);\n aa[3] = u3;\n }\n if (cdxtail !== 0 || cdytail !== 0 || adxtail !== 0 || adytail !== 0) {\n s1 = bdx * bdx;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n s0 = alo * alo - (s1 - ahi * ahi - (ahi + ahi) * alo);\n t1 = bdy * bdy;\n c = splitter * bdy;\n ahi = c - (c - bdy);\n alo = bdy - ahi;\n t0 = alo * alo - (t1 - ahi * ahi - (ahi + ahi) * alo);\n _i = s0 + t0;\n bvirt = _i - s0;\n bb[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n bb[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n bb[2] = _j - (u3 - bvirt) + (_i - bvirt);\n bb[3] = u3;\n }\n if (adxtail !== 0 || adytail !== 0 || bdxtail !== 0 || bdytail !== 0) {\n s1 = cdx * cdx;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n s0 = alo * alo - (s1 - ahi * ahi - (ahi + ahi) * alo);\n t1 = cdy * cdy;\n c = splitter * cdy;\n ahi = c - (c - cdy);\n alo = cdy - ahi;\n t0 = alo * alo - (t1 - ahi * ahi - (ahi + ahi) * alo);\n _i = s0 + t0;\n bvirt = _i - s0;\n cc[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n cc[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n cc[2] = _j - (u3 - bvirt) + (_i - bvirt);\n cc[3] = u3;\n }\n\n if (adxtail !== 0) {\n axtbclen = scale(4, bc, adxtail, axtbc);\n finlen = finadd(finlen, sum_three(\n scale(axtbclen, axtbc, 2 * adx, _16), _16,\n scale(scale(4, cc, adxtail, _8), _8, bdy, _16b), _16b,\n scale(scale(4, bb, adxtail, _8), _8, -cdy, _16c), _16c, _32, _48), _48);\n }\n if (adytail !== 0) {\n aytbclen = scale(4, bc, adytail, aytbc);\n finlen = finadd(finlen, sum_three(\n scale(aytbclen, aytbc, 2 * ady, _16), _16,\n scale(scale(4, bb, adytail, _8), _8, cdx, _16b), _16b,\n scale(scale(4, cc, adytail, _8), _8, -bdx, _16c), _16c, _32, _48), _48);\n }\n if (bdxtail !== 0) {\n bxtcalen = scale(4, ca, bdxtail, bxtca);\n finlen = finadd(finlen, sum_three(\n scale(bxtcalen, bxtca, 2 * bdx, _16), _16,\n scale(scale(4, aa, bdxtail, _8), _8, cdy, _16b), _16b,\n scale(scale(4, cc, bdxtail, _8), _8, -ady, _16c), _16c, _32, _48), _48);\n }\n if (bdytail !== 0) {\n bytcalen = scale(4, ca, bdytail, bytca);\n finlen = finadd(finlen, sum_three(\n scale(bytcalen, bytca, 2 * bdy, _16), _16,\n scale(scale(4, cc, bdytail, _8), _8, adx, _16b), _16b,\n scale(scale(4, aa, bdytail, _8), _8, -cdx, _16c), _16c, _32, _48), _48);\n }\n if (cdxtail !== 0) {\n cxtablen = scale(4, ab, cdxtail, cxtab);\n finlen = finadd(finlen, sum_three(\n scale(cxtablen, cxtab, 2 * cdx, _16), _16,\n scale(scale(4, bb, cdxtail, _8), _8, ady, _16b), _16b,\n scale(scale(4, aa, cdxtail, _8), _8, -bdy, _16c), _16c, _32, _48), _48);\n }\n if (cdytail !== 0) {\n cytablen = scale(4, ab, cdytail, cytab);\n finlen = finadd(finlen, sum_three(\n scale(cytablen, cytab, 2 * cdy, _16), _16,\n scale(scale(4, aa, cdytail, _8), _8, bdx, _16b), _16b,\n scale(scale(4, bb, cdytail, _8), _8, -adx, _16c), _16c, _32, _48), _48);\n }\n\n if (adxtail !== 0 || adytail !== 0) {\n if (bdxtail !== 0 || bdytail !== 0 || cdxtail !== 0 || cdytail !== 0) {\n s1 = bdxtail * cdy;\n c = splitter * bdxtail;\n ahi = c - (c - bdxtail);\n alo = bdxtail - ahi;\n c = splitter * cdy;\n bhi = c - (c - cdy);\n blo = cdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bdx * cdytail;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n c = splitter * cdytail;\n bhi = c - (c - cdytail);\n blo = cdytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 + t0;\n bvirt = _i - s0;\n u[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n u[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n s1 = cdxtail * -bdy;\n c = splitter * cdxtail;\n ahi = c - (c - cdxtail);\n alo = cdxtail - ahi;\n c = splitter * -bdy;\n bhi = c - (c - -bdy);\n blo = -bdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cdx * -bdytail;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n c = splitter * -bdytail;\n bhi = c - (c - -bdytail);\n blo = -bdytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 + t0;\n bvirt = _i - s0;\n v[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n v[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n v[2] = _j - (u3 - bvirt) + (_i - bvirt);\n v[3] = u3;\n bctlen = sum(4, u, 4, v, bct);\n s1 = bdxtail * cdytail;\n c = splitter * bdxtail;\n ahi = c - (c - bdxtail);\n alo = bdxtail - ahi;\n c = splitter * cdytail;\n bhi = c - (c - cdytail);\n blo = cdytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cdxtail * bdytail;\n c = splitter * cdxtail;\n ahi = c - (c - cdxtail);\n alo = cdxtail - ahi;\n c = splitter * bdytail;\n bhi = c - (c - bdytail);\n blo = bdytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bctt[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bctt[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n bctt[2] = _j - (u3 - bvirt) + (_i - bvirt);\n bctt[3] = u3;\n bcttlen = 4;\n } else {\n bct[0] = 0;\n bctlen = 1;\n bctt[0] = 0;\n bcttlen = 1;\n }\n if (adxtail !== 0) {\n const len = scale(bctlen, bct, adxtail, _16c);\n finlen = finadd(finlen, sum(\n scale(axtbclen, axtbc, adxtail, _16), _16,\n scale(len, _16c, 2 * adx, _32), _32, _48), _48);\n\n const len2 = scale(bcttlen, bctt, adxtail, _8);\n finlen = finadd(finlen, sum_three(\n scale(len2, _8, 2 * adx, _16), _16,\n scale(len2, _8, adxtail, _16b), _16b,\n scale(len, _16c, adxtail, _32), _32, _32b, _64), _64);\n\n if (bdytail !== 0) {\n finlen = finadd(finlen, scale(scale(4, cc, adxtail, _8), _8, bdytail, _16), _16);\n }\n if (cdytail !== 0) {\n finlen = finadd(finlen, scale(scale(4, bb, -adxtail, _8), _8, cdytail, _16), _16);\n }\n }\n if (adytail !== 0) {\n const len = scale(bctlen, bct, adytail, _16c);\n finlen = finadd(finlen, sum(\n scale(aytbclen, aytbc, adytail, _16), _16,\n scale(len, _16c, 2 * ady, _32), _32, _48), _48);\n\n const len2 = scale(bcttlen, bctt, adytail, _8);\n finlen = finadd(finlen, sum_three(\n scale(len2, _8, 2 * ady, _16), _16,\n scale(len2, _8, adytail, _16b), _16b,\n scale(len, _16c, adytail, _32), _32, _32b, _64), _64);\n }\n }\n if (bdxtail !== 0 || bdytail !== 0) {\n if (cdxtail !== 0 || cdytail !== 0 || adxtail !== 0 || adytail !== 0) {\n s1 = cdxtail * ady;\n c = splitter * cdxtail;\n ahi = c - (c - cdxtail);\n alo = cdxtail - ahi;\n c = splitter * ady;\n bhi = c - (c - ady);\n blo = ady - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cdx * adytail;\n c = splitter * cdx;\n ahi = c - (c - cdx);\n alo = cdx - ahi;\n c = splitter * adytail;\n bhi = c - (c - adytail);\n blo = adytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 + t0;\n bvirt = _i - s0;\n u[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n u[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n n1 = -cdy;\n n0 = -cdytail;\n s1 = adxtail * n1;\n c = splitter * adxtail;\n ahi = c - (c - adxtail);\n alo = adxtail - ahi;\n c = splitter * n1;\n bhi = c - (c - n1);\n blo = n1 - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = adx * n0;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n c = splitter * n0;\n bhi = c - (c - n0);\n blo = n0 - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 + t0;\n bvirt = _i - s0;\n v[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n v[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n v[2] = _j - (u3 - bvirt) + (_i - bvirt);\n v[3] = u3;\n catlen = sum(4, u, 4, v, cat);\n s1 = cdxtail * adytail;\n c = splitter * cdxtail;\n ahi = c - (c - cdxtail);\n alo = cdxtail - ahi;\n c = splitter * adytail;\n bhi = c - (c - adytail);\n blo = adytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = adxtail * cdytail;\n c = splitter * adxtail;\n ahi = c - (c - adxtail);\n alo = adxtail - ahi;\n c = splitter * cdytail;\n bhi = c - (c - cdytail);\n blo = cdytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n catt[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n catt[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n catt[2] = _j - (u3 - bvirt) + (_i - bvirt);\n catt[3] = u3;\n cattlen = 4;\n } else {\n cat[0] = 0;\n catlen = 1;\n catt[0] = 0;\n cattlen = 1;\n }\n if (bdxtail !== 0) {\n const len = scale(catlen, cat, bdxtail, _16c);\n finlen = finadd(finlen, sum(\n scale(bxtcalen, bxtca, bdxtail, _16), _16,\n scale(len, _16c, 2 * bdx, _32), _32, _48), _48);\n\n const len2 = scale(cattlen, catt, bdxtail, _8);\n finlen = finadd(finlen, sum_three(\n scale(len2, _8, 2 * bdx, _16), _16,\n scale(len2, _8, bdxtail, _16b), _16b,\n scale(len, _16c, bdxtail, _32), _32, _32b, _64), _64);\n\n if (cdytail !== 0) {\n finlen = finadd(finlen, scale(scale(4, aa, bdxtail, _8), _8, cdytail, _16), _16);\n }\n if (adytail !== 0) {\n finlen = finadd(finlen, scale(scale(4, cc, -bdxtail, _8), _8, adytail, _16), _16);\n }\n }\n if (bdytail !== 0) {\n const len = scale(catlen, cat, bdytail, _16c);\n finlen = finadd(finlen, sum(\n scale(bytcalen, bytca, bdytail, _16), _16,\n scale(len, _16c, 2 * bdy, _32), _32, _48), _48);\n\n const len2 = scale(cattlen, catt, bdytail, _8);\n finlen = finadd(finlen, sum_three(\n scale(len2, _8, 2 * bdy, _16), _16,\n scale(len2, _8, bdytail, _16b), _16b,\n scale(len, _16c, bdytail, _32), _32, _32b, _64), _64);\n }\n }\n if (cdxtail !== 0 || cdytail !== 0) {\n if (adxtail !== 0 || adytail !== 0 || bdxtail !== 0 || bdytail !== 0) {\n s1 = adxtail * bdy;\n c = splitter * adxtail;\n ahi = c - (c - adxtail);\n alo = adxtail - ahi;\n c = splitter * bdy;\n bhi = c - (c - bdy);\n blo = bdy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = adx * bdytail;\n c = splitter * adx;\n ahi = c - (c - adx);\n alo = adx - ahi;\n c = splitter * bdytail;\n bhi = c - (c - bdytail);\n blo = bdytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 + t0;\n bvirt = _i - s0;\n u[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n u[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n n1 = -ady;\n n0 = -adytail;\n s1 = bdxtail * n1;\n c = splitter * bdxtail;\n ahi = c - (c - bdxtail);\n alo = bdxtail - ahi;\n c = splitter * n1;\n bhi = c - (c - n1);\n blo = n1 - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bdx * n0;\n c = splitter * bdx;\n ahi = c - (c - bdx);\n alo = bdx - ahi;\n c = splitter * n0;\n bhi = c - (c - n0);\n blo = n0 - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 + t0;\n bvirt = _i - s0;\n v[0] = s0 - (_i - bvirt) + (t0 - bvirt);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 + t1;\n bvirt = _i - _0;\n v[1] = _0 - (_i - bvirt) + (t1 - bvirt);\n u3 = _j + _i;\n bvirt = u3 - _j;\n v[2] = _j - (u3 - bvirt) + (_i - bvirt);\n v[3] = u3;\n abtlen = sum(4, u, 4, v, abt);\n s1 = adxtail * bdytail;\n c = splitter * adxtail;\n ahi = c - (c - adxtail);\n alo = adxtail - ahi;\n c = splitter * bdytail;\n bhi = c - (c - bdytail);\n blo = bdytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bdxtail * adytail;\n c = splitter * bdxtail;\n ahi = c - (c - bdxtail);\n alo = bdxtail - ahi;\n c = splitter * adytail;\n bhi = c - (c - adytail);\n blo = adytail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n abtt[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n abtt[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n abtt[2] = _j - (u3 - bvirt) + (_i - bvirt);\n abtt[3] = u3;\n abttlen = 4;\n } else {\n abt[0] = 0;\n abtlen = 1;\n abtt[0] = 0;\n abttlen = 1;\n }\n if (cdxtail !== 0) {\n const len = scale(abtlen, abt, cdxtail, _16c);\n finlen = finadd(finlen, sum(\n scale(cxtablen, cxtab, cdxtail, _16), _16,\n scale(len, _16c, 2 * cdx, _32), _32, _48), _48);\n\n const len2 = scale(abttlen, abtt, cdxtail, _8);\n finlen = finadd(finlen, sum_three(\n scale(len2, _8, 2 * cdx, _16), _16,\n scale(len2, _8, cdxtail, _16b), _16b,\n scale(len, _16c, cdxtail, _32), _32, _32b, _64), _64);\n\n if (adytail !== 0) {\n finlen = finadd(finlen, scale(scale(4, bb, cdxtail, _8), _8, adytail, _16), _16);\n }\n if (bdytail !== 0) {\n finlen = finadd(finlen, scale(scale(4, aa, -cdxtail, _8), _8, bdytail, _16), _16);\n }\n }\n if (cdytail !== 0) {\n const len = scale(abtlen, abt, cdytail, _16c);\n finlen = finadd(finlen, sum(\n scale(cytablen, cytab, cdytail, _16), _16,\n scale(len, _16c, 2 * cdy, _32), _32, _48), _48);\n\n const len2 = scale(abttlen, abtt, cdytail, _8);\n finlen = finadd(finlen, sum_three(\n scale(len2, _8, 2 * cdy, _16), _16,\n scale(len2, _8, cdytail, _16b), _16b,\n scale(len, _16c, cdytail, _32), _32, _32b, _64), _64);\n }\n }\n\n return fin[finlen - 1];\n}\n\nexport function incircle(ax, ay, bx, by, cx, cy, dx, dy) {\n const adx = ax - dx;\n const bdx = bx - dx;\n const cdx = cx - dx;\n const ady = ay - dy;\n const bdy = by - dy;\n const cdy = cy - dy;\n\n const bdxcdy = bdx * cdy;\n const cdxbdy = cdx * bdy;\n const alift = adx * adx + ady * ady;\n\n const cdxady = cdx * ady;\n const adxcdy = adx * cdy;\n const blift = bdx * bdx + bdy * bdy;\n\n const adxbdy = adx * bdy;\n const bdxady = bdx * ady;\n const clift = cdx * cdx + cdy * cdy;\n\n const det =\n alift * (bdxcdy - cdxbdy) +\n blift * (cdxady - adxcdy) +\n clift * (adxbdy - bdxady);\n\n const permanent =\n (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * alift +\n (Math.abs(cdxady) + Math.abs(adxcdy)) * blift +\n (Math.abs(adxbdy) + Math.abs(bdxady)) * clift;\n\n const errbound = iccerrboundA * permanent;\n\n if (det > errbound || -det > errbound) {\n return det;\n }\n return incircleadapt(ax, ay, bx, by, cx, cy, dx, dy, permanent);\n}\n\nexport function incirclefast(ax, ay, bx, by, cx, cy, dx, dy) {\n const adx = ax - dx;\n const ady = ay - dy;\n const bdx = bx - dx;\n const bdy = by - dy;\n const cdx = cx - dx;\n const cdy = cy - dy;\n\n const abdet = adx * bdy - bdx * ady;\n const bcdet = bdx * cdy - cdx * bdy;\n const cadet = cdx * ady - adx * cdy;\n const alift = adx * adx + ady * ady;\n const blift = bdx * bdx + bdy * bdy;\n const clift = cdx * cdx + cdy * cdy;\n\n return alift * bcdet + blift * cadet + clift * abdet;\n}\n","import {epsilon, splitter, resulterrbound, estimate, vec, sum, sum_three, scale, negate} from './util.js';\n\nconst isperrboundA = (16 + 224 * epsilon) * epsilon;\nconst isperrboundB = (5 + 72 * epsilon) * epsilon;\nconst isperrboundC = (71 + 1408 * epsilon) * epsilon * epsilon;\n\nconst ab = vec(4);\nconst bc = vec(4);\nconst cd = vec(4);\nconst de = vec(4);\nconst ea = vec(4);\nconst ac = vec(4);\nconst bd = vec(4);\nconst ce = vec(4);\nconst da = vec(4);\nconst eb = vec(4);\n\nconst abc = vec(24);\nconst bcd = vec(24);\nconst cde = vec(24);\nconst dea = vec(24);\nconst eab = vec(24);\nconst abd = vec(24);\nconst bce = vec(24);\nconst cda = vec(24);\nconst deb = vec(24);\nconst eac = vec(24);\n\nconst adet = vec(1152);\nconst bdet = vec(1152);\nconst cdet = vec(1152);\nconst ddet = vec(1152);\nconst edet = vec(1152);\nconst abdet = vec(2304);\nconst cddet = vec(2304);\nconst cdedet = vec(3456);\nconst deter = vec(5760);\n\nconst _8 = vec(8);\nconst _8b = vec(8);\nconst _8c = vec(8);\nconst _16 = vec(16);\nconst _24 = vec(24);\nconst _48 = vec(48);\nconst _48b = vec(48);\nconst _96 = vec(96);\nconst _192 = vec(192);\nconst _384x = vec(384);\nconst _384y = vec(384);\nconst _384z = vec(384);\nconst _768 = vec(768);\n\nfunction sum_three_scale(a, b, c, az, bz, cz, out) {\n return sum_three(\n scale(4, a, az, _8), _8,\n scale(4, b, bz, _8b), _8b,\n scale(4, c, cz, _8c), _8c, _16, out);\n}\n\nfunction liftexact(alen, a, blen, b, clen, c, dlen, d, x, y, z, out) {\n const len = sum(\n sum(alen, a, blen, b, _48), _48,\n negate(sum(clen, c, dlen, d, _48b), _48b), _48b, _96);\n\n return sum_three(\n scale(scale(len, _96, x, _192), _192, x, _384x), _384x,\n scale(scale(len, _96, y, _192), _192, y, _384y), _384y,\n scale(scale(len, _96, z, _192), _192, z, _384z), _384z, _768, out);\n}\n\nfunction insphereexact(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez) {\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;\n\n s1 = ax * by;\n c = splitter * ax;\n ahi = c - (c - ax);\n alo = ax - ahi;\n c = splitter * by;\n bhi = c - (c - by);\n blo = by - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bx * ay;\n c = splitter * bx;\n ahi = c - (c - bx);\n alo = bx - ahi;\n c = splitter * ay;\n bhi = c - (c - ay);\n blo = ay - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ab[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ab[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ab[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ab[3] = u3;\n s1 = bx * cy;\n c = splitter * bx;\n ahi = c - (c - bx);\n alo = bx - ahi;\n c = splitter * cy;\n bhi = c - (c - cy);\n blo = cy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cx * by;\n c = splitter * cx;\n ahi = c - (c - cx);\n alo = cx - ahi;\n c = splitter * by;\n bhi = c - (c - by);\n blo = by - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bc[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bc[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n bc[2] = _j - (u3 - bvirt) + (_i - bvirt);\n bc[3] = u3;\n s1 = cx * dy;\n c = splitter * cx;\n ahi = c - (c - cx);\n alo = cx - ahi;\n c = splitter * dy;\n bhi = c - (c - dy);\n blo = dy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = dx * cy;\n c = splitter * dx;\n ahi = c - (c - dx);\n alo = dx - ahi;\n c = splitter * cy;\n bhi = c - (c - cy);\n blo = cy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n cd[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n cd[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n cd[2] = _j - (u3 - bvirt) + (_i - bvirt);\n cd[3] = u3;\n s1 = dx * ey;\n c = splitter * dx;\n ahi = c - (c - dx);\n alo = dx - ahi;\n c = splitter * ey;\n bhi = c - (c - ey);\n blo = ey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = ex * dy;\n c = splitter * ex;\n ahi = c - (c - ex);\n alo = ex - ahi;\n c = splitter * dy;\n bhi = c - (c - dy);\n blo = dy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n de[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n de[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n de[2] = _j - (u3 - bvirt) + (_i - bvirt);\n de[3] = u3;\n s1 = ex * ay;\n c = splitter * ex;\n ahi = c - (c - ex);\n alo = ex - ahi;\n c = splitter * ay;\n bhi = c - (c - ay);\n blo = ay - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = ax * ey;\n c = splitter * ax;\n ahi = c - (c - ax);\n alo = ax - ahi;\n c = splitter * ey;\n bhi = c - (c - ey);\n blo = ey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ea[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ea[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ea[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ea[3] = u3;\n s1 = ax * cy;\n c = splitter * ax;\n ahi = c - (c - ax);\n alo = ax - ahi;\n c = splitter * cy;\n bhi = c - (c - cy);\n blo = cy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cx * ay;\n c = splitter * cx;\n ahi = c - (c - cx);\n alo = cx - ahi;\n c = splitter * ay;\n bhi = c - (c - ay);\n blo = ay - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ac[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ac[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ac[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ac[3] = u3;\n s1 = bx * dy;\n c = splitter * bx;\n ahi = c - (c - bx);\n alo = bx - ahi;\n c = splitter * dy;\n bhi = c - (c - dy);\n blo = dy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = dx * by;\n c = splitter * dx;\n ahi = c - (c - dx);\n alo = dx - ahi;\n c = splitter * by;\n bhi = c - (c - by);\n blo = by - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bd[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bd[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n bd[2] = _j - (u3 - bvirt) + (_i - bvirt);\n bd[3] = u3;\n s1 = cx * ey;\n c = splitter * cx;\n ahi = c - (c - cx);\n alo = cx - ahi;\n c = splitter * ey;\n bhi = c - (c - ey);\n blo = ey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = ex * cy;\n c = splitter * ex;\n ahi = c - (c - ex);\n alo = ex - ahi;\n c = splitter * cy;\n bhi = c - (c - cy);\n blo = cy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ce[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ce[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n ce[2] = _j - (u3 - bvirt) + (_i - bvirt);\n ce[3] = u3;\n s1 = dx * ay;\n c = splitter * dx;\n ahi = c - (c - dx);\n alo = dx - ahi;\n c = splitter * ay;\n bhi = c - (c - ay);\n blo = ay - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = ax * dy;\n c = splitter * ax;\n ahi = c - (c - ax);\n alo = ax - ahi;\n c = splitter * dy;\n bhi = c - (c - dy);\n blo = dy - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n da[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n da[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n da[2] = _j - (u3 - bvirt) + (_i - bvirt);\n da[3] = u3;\n s1 = ex * by;\n c = splitter * ex;\n ahi = c - (c - ex);\n alo = ex - ahi;\n c = splitter * by;\n bhi = c - (c - by);\n blo = by - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bx * ey;\n c = splitter * bx;\n ahi = c - (c - bx);\n alo = bx - ahi;\n c = splitter * ey;\n bhi = c - (c - ey);\n blo = ey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n eb[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n eb[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n eb[2] = _j - (u3 - bvirt) + (_i - bvirt);\n eb[3] = u3;\n\n const abclen = sum_three_scale(ab, bc, ac, cz, az, -bz, abc);\n const bcdlen = sum_three_scale(bc, cd, bd, dz, bz, -cz, bcd);\n const cdelen = sum_three_scale(cd, de, ce, ez, cz, -dz, cde);\n const dealen = sum_three_scale(de, ea, da, az, dz, -ez, dea);\n const eablen = sum_three_scale(ea, ab, eb, bz, ez, -az, eab);\n const abdlen = sum_three_scale(ab, bd, da, dz, az, bz, abd);\n const bcelen = sum_three_scale(bc, ce, eb, ez, bz, cz, bce);\n const cdalen = sum_three_scale(cd, da, ac, az, cz, dz, cda);\n const deblen = sum_three_scale(de, eb, bd, bz, dz, ez, deb);\n const eaclen = sum_three_scale(ea, ac, ce, cz, ez, az, eac);\n\n const deterlen = sum_three(\n liftexact(cdelen, cde, bcelen, bce, deblen, deb, bcdlen, bcd, ax, ay, az, adet), adet,\n liftexact(dealen, dea, cdalen, cda, eaclen, eac, cdelen, cde, bx, by, bz, bdet), bdet,\n sum_three(\n liftexact(eablen, eab, deblen, deb, abdlen, abd, dealen, dea, cx, cy, cz, cdet), cdet,\n liftexact(abclen, abc, eaclen, eac, bcelen, bce, eablen, eab, dx, dy, dz, ddet), ddet,\n liftexact(bcdlen, bcd, abdlen, abd, cdalen, cda, abclen, abc, ex, ey, ez, edet), edet, cddet, cdedet), cdedet, abdet, deter);\n\n return deter[deterlen - 1];\n}\n\nconst xdet = vec(96);\nconst ydet = vec(96);\nconst zdet = vec(96);\nconst fin = vec(1152);\n\nfunction liftadapt(a, b, c, az, bz, cz, x, y, z, out) {\n const len = sum_three_scale(a, b, c, az, bz, cz, _24);\n return sum_three(\n scale(scale(len, _24, x, _48), _48, x, xdet), xdet,\n scale(scale(len, _24, y, _48), _48, y, ydet), ydet,\n scale(scale(len, _24, z, _48), _48, z, zdet), zdet, _192, out);\n}\n\nfunction insphereadapt(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez, permanent) {\n let ab3, bc3, cd3, da3, ac3, bd3;\n\n let aextail, bextail, cextail, dextail;\n let aeytail, beytail, ceytail, deytail;\n let aeztail, beztail, ceztail, deztail;\n\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0;\n\n const aex = ax - ex;\n const bex = bx - ex;\n const cex = cx - ex;\n const dex = dx - ex;\n const aey = ay - ey;\n const bey = by - ey;\n const cey = cy - ey;\n const dey = dy - ey;\n const aez = az - ez;\n const bez = bz - ez;\n const cez = cz - ez;\n const dez = dz - ez;\n\n s1 = aex * bey;\n c = splitter * aex;\n ahi = c - (c - aex);\n alo = aex - ahi;\n c = splitter * bey;\n bhi = c - (c - bey);\n blo = bey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = bex * aey;\n c = splitter * bex;\n ahi = c - (c - bex);\n alo = bex - ahi;\n c = splitter * aey;\n bhi = c - (c - aey);\n blo = aey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ab[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ab[1] = _0 - (_i + bvirt) + (bvirt - t1);\n ab3 = _j + _i;\n bvirt = ab3 - _j;\n ab[2] = _j - (ab3 - bvirt) + (_i - bvirt);\n ab[3] = ab3;\n s1 = bex * cey;\n c = splitter * bex;\n ahi = c - (c - bex);\n alo = bex - ahi;\n c = splitter * cey;\n bhi = c - (c - cey);\n blo = cey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cex * bey;\n c = splitter * cex;\n ahi = c - (c - cex);\n alo = cex - ahi;\n c = splitter * bey;\n bhi = c - (c - bey);\n blo = bey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bc[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bc[1] = _0 - (_i + bvirt) + (bvirt - t1);\n bc3 = _j + _i;\n bvirt = bc3 - _j;\n bc[2] = _j - (bc3 - bvirt) + (_i - bvirt);\n bc[3] = bc3;\n s1 = cex * dey;\n c = splitter * cex;\n ahi = c - (c - cex);\n alo = cex - ahi;\n c = splitter * dey;\n bhi = c - (c - dey);\n blo = dey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = dex * cey;\n c = splitter * dex;\n ahi = c - (c - dex);\n alo = dex - ahi;\n c = splitter * cey;\n bhi = c - (c - cey);\n blo = cey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n cd[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n cd[1] = _0 - (_i + bvirt) + (bvirt - t1);\n cd3 = _j + _i;\n bvirt = cd3 - _j;\n cd[2] = _j - (cd3 - bvirt) + (_i - bvirt);\n cd[3] = cd3;\n s1 = dex * aey;\n c = splitter * dex;\n ahi = c - (c - dex);\n alo = dex - ahi;\n c = splitter * aey;\n bhi = c - (c - aey);\n blo = aey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = aex * dey;\n c = splitter * aex;\n ahi = c - (c - aex);\n alo = aex - ahi;\n c = splitter * dey;\n bhi = c - (c - dey);\n blo = dey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n da[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n da[1] = _0 - (_i + bvirt) + (bvirt - t1);\n da3 = _j + _i;\n bvirt = da3 - _j;\n da[2] = _j - (da3 - bvirt) + (_i - bvirt);\n da[3] = da3;\n s1 = aex * cey;\n c = splitter * aex;\n ahi = c - (c - aex);\n alo = aex - ahi;\n c = splitter * cey;\n bhi = c - (c - cey);\n blo = cey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = cex * aey;\n c = splitter * cex;\n ahi = c - (c - cex);\n alo = cex - ahi;\n c = splitter * aey;\n bhi = c - (c - aey);\n blo = aey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n ac[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n ac[1] = _0 - (_i + bvirt) + (bvirt - t1);\n ac3 = _j + _i;\n bvirt = ac3 - _j;\n ac[2] = _j - (ac3 - bvirt) + (_i - bvirt);\n ac[3] = ac3;\n s1 = bex * dey;\n c = splitter * bex;\n ahi = c - (c - bex);\n alo = bex - ahi;\n c = splitter * dey;\n bhi = c - (c - dey);\n blo = dey - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = dex * bey;\n c = splitter * dex;\n ahi = c - (c - dex);\n alo = dex - ahi;\n c = splitter * bey;\n bhi = c - (c - bey);\n blo = bey - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n bd[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n bd[1] = _0 - (_i + bvirt) + (bvirt - t1);\n bd3 = _j + _i;\n bvirt = bd3 - _j;\n bd[2] = _j - (bd3 - bvirt) + (_i - bvirt);\n bd[3] = bd3;\n\n const finlen = sum(\n sum(\n negate(liftadapt(bc, cd, bd, dez, bez, -cez, aex, aey, aez, adet), adet), adet,\n liftadapt(cd, da, ac, aez, cez, dez, bex, bey, bez, bdet), bdet, abdet), abdet,\n sum(\n negate(liftadapt(da, ab, bd, bez, dez, aez, cex, cey, cez, cdet), cdet), cdet,\n liftadapt(ab, bc, ac, cez, aez, -bez, dex, dey, dez, ddet), ddet, cddet), cddet, fin);\n\n let det = estimate(finlen, fin);\n let errbound = isperrboundB * permanent;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n bvirt = ax - aex;\n aextail = ax - (aex + bvirt) + (bvirt - ex);\n bvirt = ay - aey;\n aeytail = ay - (aey + bvirt) + (bvirt - ey);\n bvirt = az - aez;\n aeztail = az - (aez + bvirt) + (bvirt - ez);\n bvirt = bx - bex;\n bextail = bx - (bex + bvirt) + (bvirt - ex);\n bvirt = by - bey;\n beytail = by - (bey + bvirt) + (bvirt - ey);\n bvirt = bz - bez;\n beztail = bz - (bez + bvirt) + (bvirt - ez);\n bvirt = cx - cex;\n cextail = cx - (cex + bvirt) + (bvirt - ex);\n bvirt = cy - cey;\n ceytail = cy - (cey + bvirt) + (bvirt - ey);\n bvirt = cz - cez;\n ceztail = cz - (cez + bvirt) + (bvirt - ez);\n bvirt = dx - dex;\n dextail = dx - (dex + bvirt) + (bvirt - ex);\n bvirt = dy - dey;\n deytail = dy - (dey + bvirt) + (bvirt - ey);\n bvirt = dz - dez;\n deztail = dz - (dez + bvirt) + (bvirt - ez);\n if (aextail === 0 && aeytail === 0 && aeztail === 0 &&\n bextail === 0 && beytail === 0 && beztail === 0 &&\n cextail === 0 && ceytail === 0 && ceztail === 0 &&\n dextail === 0 && deytail === 0 && deztail === 0) {\n return det;\n }\n\n errbound = isperrboundC * permanent + resulterrbound * Math.abs(det);\n\n const abeps = (aex * beytail + bey * aextail) - (aey * bextail + bex * aeytail);\n const bceps = (bex * ceytail + cey * bextail) - (bey * cextail + cex * beytail);\n const cdeps = (cex * deytail + dey * cextail) - (cey * dextail + dex * ceytail);\n const daeps = (dex * aeytail + aey * dextail) - (dey * aextail + aex * deytail);\n const aceps = (aex * ceytail + cey * aextail) - (aey * cextail + cex * aeytail);\n const bdeps = (bex * deytail + dey * bextail) - (bey * dextail + dex * beytail);\n det +=\n (((bex * bex + bey * bey + bez * bez) * ((cez * daeps + dez * aceps + aez * cdeps) +\n (ceztail * da3 + deztail * ac3 + aeztail * cd3)) + (dex * dex + dey * dey + dez * dez) *\n ((aez * bceps - bez * aceps + cez * abeps) + (aeztail * bc3 - beztail * ac3 + ceztail * ab3))) -\n ((aex * aex + aey * aey + aez * aez) * ((bez * cdeps - cez * bdeps + dez * bceps) +\n (beztail * cd3 - ceztail * bd3 + deztail * bc3)) + (cex * cex + cey * cey + cez * cez) *\n ((dez * abeps + aez * bdeps + bez * daeps) + (deztail * ab3 + aeztail * bd3 + beztail * da3)))) +\n 2 * (((bex * bextail + bey * beytail + bez * beztail) * (cez * da3 + dez * ac3 + aez * cd3) +\n (dex * dextail + dey * deytail + dez * deztail) * (aez * bc3 - bez * ac3 + cez * ab3)) -\n ((aex * aextail + aey * aeytail + aez * aeztail) * (bez * cd3 - cez * bd3 + dez * bc3) +\n (cex * cextail + cey * ceytail + cez * ceztail) * (dez * ab3 + aez * bd3 + bez * da3)));\n\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n return insphereexact(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez);\n}\n\nexport function insphere(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez) {\n const aex = ax - ex;\n const bex = bx - ex;\n const cex = cx - ex;\n const dex = dx - ex;\n const aey = ay - ey;\n const bey = by - ey;\n const cey = cy - ey;\n const dey = dy - ey;\n const aez = az - ez;\n const bez = bz - ez;\n const cez = cz - ez;\n const dez = dz - ez;\n\n const aexbey = aex * bey;\n const bexaey = bex * aey;\n const ab = aexbey - bexaey;\n const bexcey = bex * cey;\n const cexbey = cex * bey;\n const bc = bexcey - cexbey;\n const cexdey = cex * dey;\n const dexcey = dex * cey;\n const cd = cexdey - dexcey;\n const dexaey = dex * aey;\n const aexdey = aex * dey;\n const da = dexaey - aexdey;\n const aexcey = aex * cey;\n const cexaey = cex * aey;\n const ac = aexcey - cexaey;\n const bexdey = bex * dey;\n const dexbey = dex * bey;\n const bd = bexdey - dexbey;\n\n const alift = aex * aex + aey * aey + aez * aez;\n const blift = bex * bex + bey * bey + bez * bez;\n const clift = cex * cex + cey * cey + cez * cez;\n const dlift = dex * dex + dey * dey + dez * dez;\n\n const det =\n (clift * (dez * ab + aez * bd + bez * da) - dlift * (aez * bc - bez * ac + cez * ab)) +\n (alift * (bez * cd - cez * bd + dez * bc) - blift * (cez * da + dez * ac + aez * cd));\n\n const aezplus = Math.abs(aez);\n const bezplus = Math.abs(bez);\n const cezplus = Math.abs(cez);\n const dezplus = Math.abs(dez);\n const aexbeyplus = Math.abs(aexbey) + Math.abs(bexaey);\n const bexceyplus = Math.abs(bexcey) + Math.abs(cexbey);\n const cexdeyplus = Math.abs(cexdey) + Math.abs(dexcey);\n const dexaeyplus = Math.abs(dexaey) + Math.abs(aexdey);\n const aexceyplus = Math.abs(aexcey) + Math.abs(cexaey);\n const bexdeyplus = Math.abs(bexdey) + Math.abs(dexbey);\n const permanent =\n (cexdeyplus * bezplus + bexdeyplus * cezplus + bexceyplus * dezplus) * alift +\n (dexaeyplus * cezplus + aexceyplus * dezplus + cexdeyplus * aezplus) * blift +\n (aexbeyplus * dezplus + bexdeyplus * aezplus + dexaeyplus * bezplus) * clift +\n (bexceyplus * aezplus + aexceyplus * bezplus + aexbeyplus * cezplus) * dlift;\n\n const errbound = isperrboundA * permanent;\n if (det > errbound || -det > errbound) {\n return det;\n }\n return -insphereadapt(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez, permanent);\n}\n\nexport function inspherefast(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez) {\n const aex = ax - ex;\n const bex = bx - ex;\n const cex = cx - ex;\n const dex = dx - ex;\n const aey = ay - ey;\n const bey = by - ey;\n const cey = cy - ey;\n const dey = dy - ey;\n const aez = az - ez;\n const bez = bz - ez;\n const cez = cz - ez;\n const dez = dz - ez;\n\n const ab = aex * bey - bex * aey;\n const bc = bex * cey - cex * bey;\n const cd = cex * dey - dex * cey;\n const da = dex * aey - aex * dey;\n const ac = aex * cey - cex * aey;\n const bd = bex * dey - dex * bey;\n\n const abc = aez * bc - bez * ac + cez * ab;\n const bcd = bez * cd - cez * bd + dez * bc;\n const cda = cez * da + dez * ac + aez * cd;\n const dab = dez * ab + aez * bd + bez * da;\n\n const alift = aex * aex + aey * aey + aez * aez;\n const blift = bex * bex + bey * bey + bez * bez;\n const clift = cex * cex + cey * cey + cez * cez;\n const dlift = dex * dex + dey * dey + dez * dez;\n\n return (clift * dab - dlift * abc) + (alift * bcd - blift * cda);\n}\n","import { orient2d } from 'robust-predicates';\n\nfunction pointInPolygon(p, polygon) {\n var i;\n var ii;\n var k = 0;\n var f;\n var u1;\n var v1;\n var u2;\n var v2;\n var currentP;\n var nextP;\n\n var x = p[0];\n var y = p[1];\n\n var numContours = polygon.length;\n for (i = 0; i < numContours; i++) {\n ii = 0;\n var contour = polygon[i];\n var contourLen = contour.length - 1;\n\n currentP = contour[0];\n if (currentP[0] !== contour[contourLen][0] &&\n currentP[1] !== contour[contourLen][1]) {\n throw new Error('First and last coordinates in a ring must be the same')\n }\n\n u1 = currentP[0] - x;\n v1 = currentP[1] - y;\n\n for (ii; ii < contourLen; ii++) {\n nextP = contour[ii + 1];\n\n u2 = nextP[0] - x;\n v2 = nextP[1] - y;\n\n if (v1 === 0 && v2 === 0) {\n if ((u2 <= 0 && u1 >= 0) || (u1 <= 0 && u2 >= 0)) { return 0 }\n } else if ((v2 >= 0 && v1 <= 0) || (v2 <= 0 && v1 >= 0)) {\n f = orient2d(u1, u2, v1, v2, 0, 0);\n if (f === 0) { return 0 }\n if ((f > 0 && v2 > 0 && v1 <= 0) || (f < 0 && v2 <= 0 && v1 > 0)) { k++; }\n }\n currentP = nextP;\n v1 = v2;\n u1 = u2;\n }\n }\n\n if (k % 2 === 0) { return false }\n return true\n}\n\nexport { pointInPolygon as default };\n","// index.ts\nimport pip from \"point-in-polygon-hao\";\nimport { getCoord, getGeom } from \"@turf/invariant\";\nfunction booleanPointInPolygon(point, polygon, options = {}) {\n if (!point) {\n throw new Error(\"point is required\");\n }\n if (!polygon) {\n throw new Error(\"polygon is required\");\n }\n const pt = getCoord(point);\n const geom = getGeom(polygon);\n const type = geom.type;\n const bbox = polygon.bbox;\n let polys = geom.coordinates;\n if (bbox && inBBox(pt, bbox) === false) {\n return false;\n }\n if (type === \"Polygon\") {\n polys = [polys];\n }\n let result = false;\n for (var i = 0; i < polys.length; ++i) {\n const polyResult = pip(pt, polys[i]);\n if (polyResult === 0) return options.ignoreBoundary ? false : true;\n else if (polyResult) result = true;\n }\n return result;\n}\nfunction inBBox(pt, bbox) {\n return bbox[0] <= pt[0] && bbox[1] <= pt[1] && bbox[2] >= pt[0] && bbox[3] >= pt[1];\n}\nvar index_default = booleanPointInPolygon;\nexport {\n booleanPointInPolygon,\n index_default as default\n};\n//# sourceMappingURL=index.js.map","class TinyQueue {\n constructor(data = [], compare = defaultCompare) {\n this.data = data;\n this.length = this.data.length;\n this.compare = compare;\n\n if (this.length > 0) {\n for (let i = (this.length >> 1) - 1; i >= 0; i--) this._down(i);\n }\n }\n\n push(item) {\n this.data.push(item);\n this.length++;\n this._up(this.length - 1);\n }\n\n pop() {\n if (this.length === 0) return undefined;\n\n const top = this.data[0];\n const bottom = this.data.pop();\n this.length--;\n\n if (this.length > 0) {\n this.data[0] = bottom;\n this._down(0);\n }\n\n return top;\n }\n\n peek() {\n return this.data[0];\n }\n\n _up(pos) {\n const {data, compare} = this;\n const item = data[pos];\n\n while (pos > 0) {\n const parent = (pos - 1) >> 1;\n const current = data[parent];\n if (compare(item, current) >= 0) break;\n data[pos] = current;\n pos = parent;\n }\n\n data[pos] = item;\n }\n\n _down(pos) {\n const {data, compare} = this;\n const halfLength = this.length >> 1;\n const item = data[pos];\n\n while (pos < halfLength) {\n let left = (pos << 1) + 1;\n let best = data[left];\n const right = left + 1;\n\n if (right < this.length && compare(data[right], best) < 0) {\n left = right;\n best = data[right];\n }\n if (compare(best, item) >= 0) break;\n\n data[pos] = best;\n pos = left;\n }\n\n data[pos] = item;\n }\n}\n\nfunction defaultCompare(a, b) {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\nfunction checkWhichEventIsLeft (e1, e2) {\n if (e1.p.x > e2.p.x) return 1\n if (e1.p.x < e2.p.x) return -1\n\n if (e1.p.y !== e2.p.y) return e1.p.y > e2.p.y ? 1 : -1\n return 1\n}\n\nfunction checkWhichSegmentHasRightEndpointFirst (seg1, seg2) {\n if (seg1.rightSweepEvent.p.x > seg2.rightSweepEvent.p.x) return 1\n if (seg1.rightSweepEvent.p.x < seg2.rightSweepEvent.p.x) return -1\n\n if (seg1.rightSweepEvent.p.y !== seg2.rightSweepEvent.p.y) return seg1.rightSweepEvent.p.y < seg2.rightSweepEvent.p.y ? 1 : -1\n return 1\n}\n\nclass Event {\n\n constructor (p, featureId, ringId, eventId) {\n this.p = {\n x: p[0],\n y: p[1]\n };\n this.featureId = featureId;\n this.ringId = ringId;\n this.eventId = eventId;\n\n this.otherEvent = null;\n this.isLeftEndpoint = null;\n }\n\n isSamePoint (eventToCheck) {\n return this.p.x === eventToCheck.p.x && this.p.y === eventToCheck.p.y\n }\n}\n\nfunction fillEventQueue (geojson, eventQueue) {\n if (geojson.type === 'FeatureCollection') {\n const features = geojson.features;\n for (let i = 0; i < features.length; i++) {\n processFeature(features[i], eventQueue);\n }\n } else {\n processFeature(geojson, eventQueue);\n }\n}\n\nlet featureId = 0;\nlet ringId = 0;\nlet eventId = 0;\nfunction processFeature (featureOrGeometry, eventQueue) {\n const geom = featureOrGeometry.type === 'Feature' ? featureOrGeometry.geometry : featureOrGeometry;\n let coords = geom.coordinates;\n // standardise the input\n if (geom.type === 'Polygon' || geom.type === 'MultiLineString') coords = [coords];\n if (geom.type === 'LineString') coords = [[coords]];\n\n for (let i = 0; i < coords.length; i++) {\n for (let ii = 0; ii < coords[i].length; ii++) {\n let currentP = coords[i][ii][0];\n let nextP = null;\n ringId = ringId + 1;\n for (let iii = 0; iii < coords[i][ii].length - 1; iii++) {\n nextP = coords[i][ii][iii + 1];\n\n const e1 = new Event(currentP, featureId, ringId, eventId);\n const e2 = new Event(nextP, featureId, ringId, eventId + 1);\n\n e1.otherEvent = e2;\n e2.otherEvent = e1;\n\n if (checkWhichEventIsLeft(e1, e2) > 0) {\n e2.isLeftEndpoint = true;\n e1.isLeftEndpoint = false;\n } else {\n e1.isLeftEndpoint = true;\n e2.isLeftEndpoint = false;\n }\n eventQueue.push(e1);\n eventQueue.push(e2);\n\n currentP = nextP;\n eventId = eventId + 1;\n }\n }\n }\n featureId = featureId + 1;\n}\n\nclass Segment {\n\n constructor (event) {\n this.leftSweepEvent = event;\n this.rightSweepEvent = event.otherEvent;\n }\n}\n\nfunction testSegmentIntersect (seg1, seg2) {\n if (seg1 === null || seg2 === null) return false\n\n if (seg1.leftSweepEvent.ringId === seg2.leftSweepEvent.ringId &&\n (seg1.rightSweepEvent.isSamePoint(seg2.leftSweepEvent) ||\n seg1.rightSweepEvent.isSamePoint(seg2.leftSweepEvent) ||\n seg1.rightSweepEvent.isSamePoint(seg2.rightSweepEvent) ||\n seg1.leftSweepEvent.isSamePoint(seg2.leftSweepEvent) ||\n seg1.leftSweepEvent.isSamePoint(seg2.rightSweepEvent))) return false\n\n const x1 = seg1.leftSweepEvent.p.x;\n const y1 = seg1.leftSweepEvent.p.y;\n const x2 = seg1.rightSweepEvent.p.x;\n const y2 = seg1.rightSweepEvent.p.y;\n const x3 = seg2.leftSweepEvent.p.x;\n const y3 = seg2.leftSweepEvent.p.y;\n const x4 = seg2.rightSweepEvent.p.x;\n const y4 = seg2.rightSweepEvent.p.y;\n\n const denom = ((y4 - y3) * (x2 - x1)) - ((x4 - x3) * (y2 - y1));\n const numeA = ((x4 - x3) * (y1 - y3)) - ((y4 - y3) * (x1 - x3));\n const numeB = ((x2 - x1) * (y1 - y3)) - ((y2 - y1) * (x1 - x3));\n\n if (denom === 0) {\n if (numeA === 0 && numeB === 0) return false\n return false\n }\n\n const uA = numeA / denom;\n const uB = numeB / denom;\n\n if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {\n const x = x1 + (uA * (x2 - x1));\n const y = y1 + (uA * (y2 - y1));\n return [x, y]\n }\n return false\n}\n\n// import {debugEventAndSegments, debugRemovingSegment} from './debug'\n\nfunction runCheck (eventQueue, ignoreSelfIntersections) {\n ignoreSelfIntersections = ignoreSelfIntersections ? ignoreSelfIntersections : false;\n\n const intersectionPoints = [];\n const outQueue = new TinyQueue([], checkWhichSegmentHasRightEndpointFirst);\n\n while (eventQueue.length) {\n const event = eventQueue.pop();\n if (event.isLeftEndpoint) {\n // debugEventAndSegments(event.p, outQueue.data)\n const segment = new Segment(event);\n for (let i = 0; i < outQueue.data.length; i++) {\n const otherSeg = outQueue.data[i];\n if (ignoreSelfIntersections) {\n if (otherSeg.leftSweepEvent.featureId === event.featureId) continue\n }\n const intersection = testSegmentIntersect(segment, otherSeg);\n if (intersection !== false) intersectionPoints.push(intersection);\n }\n outQueue.push(segment);\n } else if (event.isLeftEndpoint === false) {\n outQueue.pop();\n // const seg = outQueue.pop()\n // debugRemovingSegment(event.p, seg)\n }\n }\n return intersectionPoints\n}\n\nfunction sweeplineIntersections (geojson, ignoreSelfIntersections) {\n const eventQueue = new TinyQueue([], checkWhichEventIsLeft);\n fillEventQueue(geojson, eventQueue);\n return runCheck(eventQueue, ignoreSelfIntersections)\n}\n\nexport default sweeplineIntersections;\n","// index.ts\nimport { feature, featureCollection, point } from \"@turf/helpers\";\n\n// lib/sweepline-intersections-export.ts\nimport lib from \"sweepline-intersections\";\nvar sweeplineIntersections = lib;\n\n// index.ts\nfunction lineIntersect(line1, line2, options = {}) {\n const { removeDuplicates = true, ignoreSelfIntersections = true } = options;\n let features = [];\n if (line1.type === \"FeatureCollection\")\n features = features.concat(line1.features);\n else if (line1.type === \"Feature\") features.push(line1);\n else if (line1.type === \"LineString\" || line1.type === \"Polygon\" || line1.type === \"MultiLineString\" || line1.type === \"MultiPolygon\") {\n features.push(feature(line1));\n }\n if (line2.type === \"FeatureCollection\")\n features = features.concat(line2.features);\n else if (line2.type === \"Feature\") features.push(line2);\n else if (line2.type === \"LineString\" || line2.type === \"Polygon\" || line2.type === \"MultiLineString\" || line2.type === \"MultiPolygon\") {\n features.push(feature(line2));\n }\n const intersections = sweeplineIntersections(\n featureCollection(features),\n ignoreSelfIntersections\n );\n let results = [];\n if (removeDuplicates) {\n const unique = {};\n intersections.forEach((intersection) => {\n const key = intersection.join(\",\");\n if (!unique[key]) {\n unique[key] = true;\n results.push(intersection);\n }\n });\n } else {\n results = intersections;\n }\n return featureCollection(results.map((r) => point(r)));\n}\nvar index_default = lineIntersect;\nexport {\n index_default as default,\n lineIntersect\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { featureCollection, lineString, multiLineString } from \"@turf/helpers\";\nimport { getGeom } from \"@turf/invariant\";\nfunction polygonToLine(poly, options = {}) {\n const geom = getGeom(poly);\n if (!options.properties && poly.type === \"Feature\") {\n options.properties = poly.properties;\n }\n switch (geom.type) {\n case \"Polygon\":\n return singlePolygonToLine(geom, options);\n case \"MultiPolygon\":\n return multiPolygonToLine(geom, options);\n default:\n throw new Error(\"invalid poly\");\n }\n}\nfunction singlePolygonToLine(poly, options = {}) {\n const geom = getGeom(poly);\n const coords = geom.coordinates;\n const properties = options.properties ? options.properties : poly.type === \"Feature\" ? poly.properties : {};\n return coordsToLine(coords, properties);\n}\nfunction multiPolygonToLine(multiPoly, options = {}) {\n const geom = getGeom(multiPoly);\n const coords = geom.coordinates;\n const properties = options.properties ? options.properties : multiPoly.type === \"Feature\" ? multiPoly.properties : {};\n const lines = [];\n coords.forEach((coord) => {\n lines.push(coordsToLine(coord, properties));\n });\n return featureCollection(lines);\n}\nfunction coordsToLine(coords, properties) {\n if (coords.length > 1) {\n return multiLineString(coords, properties);\n }\n return lineString(coords[0], properties);\n}\nvar index_default = polygonToLine;\nexport {\n coordsToLine,\n index_default as default,\n multiPolygonToLine,\n polygonToLine,\n singlePolygonToLine\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { booleanPointInPolygon } from \"@turf/boolean-point-in-polygon\";\nimport { lineIntersect } from \"@turf/line-intersect\";\nimport { flattenEach } from \"@turf/meta\";\nimport { polygonToLine } from \"@turf/polygon-to-line\";\nfunction booleanDisjoint(feature1, feature2, {\n ignoreSelfIntersections = true\n} = { ignoreSelfIntersections: true }) {\n let bool = true;\n flattenEach(feature1, (flatten1) => {\n flattenEach(feature2, (flatten2) => {\n if (bool === false) {\n return false;\n }\n bool = disjoint(\n flatten1.geometry,\n flatten2.geometry,\n ignoreSelfIntersections\n );\n });\n });\n return bool;\n}\nfunction disjoint(geom1, geom2, ignoreSelfIntersections) {\n switch (geom1.type) {\n case \"Point\":\n switch (geom2.type) {\n case \"Point\":\n return !compareCoords(geom1.coordinates, geom2.coordinates);\n case \"LineString\":\n return !isPointOnLine(geom2, geom1);\n case \"Polygon\":\n return !booleanPointInPolygon(geom1, geom2);\n }\n break;\n case \"LineString\":\n switch (geom2.type) {\n case \"Point\":\n return !isPointOnLine(geom1, geom2);\n case \"LineString\":\n return !isLineOnLine(geom1, geom2, ignoreSelfIntersections);\n case \"Polygon\":\n return !isLineInPoly(geom2, geom1, ignoreSelfIntersections);\n }\n break;\n case \"Polygon\":\n switch (geom2.type) {\n case \"Point\":\n return !booleanPointInPolygon(geom2, geom1);\n case \"LineString\":\n return !isLineInPoly(geom1, geom2, ignoreSelfIntersections);\n case \"Polygon\":\n return !isPolyInPoly(geom2, geom1, ignoreSelfIntersections);\n }\n }\n return false;\n}\nfunction isPointOnLine(lineString, pt) {\n for (let i = 0; i < lineString.coordinates.length - 1; i++) {\n if (isPointOnLineSegment(\n lineString.coordinates[i],\n lineString.coordinates[i + 1],\n pt.coordinates\n )) {\n return true;\n }\n }\n return false;\n}\nfunction isLineOnLine(lineString1, lineString2, ignoreSelfIntersections) {\n const doLinesIntersect = lineIntersect(lineString1, lineString2, {\n ignoreSelfIntersections\n });\n if (doLinesIntersect.features.length > 0) {\n return true;\n }\n return false;\n}\nfunction isLineInPoly(polygon, lineString, ignoreSelfIntersections) {\n for (const coord of lineString.coordinates) {\n if (booleanPointInPolygon(coord, polygon)) {\n return true;\n }\n }\n const doLinesIntersect = lineIntersect(lineString, polygonToLine(polygon), {\n ignoreSelfIntersections\n });\n if (doLinesIntersect.features.length > 0) {\n return true;\n }\n return false;\n}\nfunction isPolyInPoly(feature1, feature2, ignoreSelfIntersections) {\n for (const coord1 of feature1.coordinates[0]) {\n if (booleanPointInPolygon(coord1, feature2)) {\n return true;\n }\n }\n for (const coord2 of feature2.coordinates[0]) {\n if (booleanPointInPolygon(coord2, feature1)) {\n return true;\n }\n }\n const doLinesIntersect = lineIntersect(\n polygonToLine(feature1),\n polygonToLine(feature2),\n { ignoreSelfIntersections }\n );\n if (doLinesIntersect.features.length > 0) {\n return true;\n }\n return false;\n}\nfunction isPointOnLineSegment(lineSegmentStart, lineSegmentEnd, pt) {\n const dxc = pt[0] - lineSegmentStart[0];\n const dyc = pt[1] - lineSegmentStart[1];\n const dxl = lineSegmentEnd[0] - lineSegmentStart[0];\n const dyl = lineSegmentEnd[1] - lineSegmentStart[1];\n const cross = dxc * dyl - dyc * dxl;\n if (cross !== 0) {\n return false;\n }\n if (Math.abs(dxl) >= Math.abs(dyl)) {\n if (dxl > 0) {\n return lineSegmentStart[0] <= pt[0] && pt[0] <= lineSegmentEnd[0];\n } else {\n return lineSegmentEnd[0] <= pt[0] && pt[0] <= lineSegmentStart[0];\n }\n } else if (dyl > 0) {\n return lineSegmentStart[1] <= pt[1] && pt[1] <= lineSegmentEnd[1];\n } else {\n return lineSegmentEnd[1] <= pt[1] && pt[1] <= lineSegmentStart[1];\n }\n}\nfunction compareCoords(pair1, pair2) {\n return pair1[0] === pair2[0] && pair1[1] === pair2[1];\n}\nvar index_default = booleanDisjoint;\nexport {\n booleanDisjoint,\n index_default as default\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { booleanDisjoint } from \"@turf/boolean-disjoint\";\nimport { flattenEach } from \"@turf/meta\";\nfunction booleanIntersects(feature1, feature2, {\n ignoreSelfIntersections = true\n} = {}) {\n let bool = false;\n flattenEach(feature1, (flatten1) => {\n flattenEach(feature2, (flatten2) => {\n if (bool === true) {\n return true;\n }\n bool = !booleanDisjoint(flatten1.geometry, flatten2.geometry, {\n ignoreSelfIntersections\n });\n });\n });\n return bool;\n}\nvar index_default = booleanIntersects;\nexport {\n booleanIntersects,\n index_default as default\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { bbox } from \"@turf/bbox\";\nimport { bboxPolygon } from \"@turf/bbox-polygon\";\nfunction envelope(geojson) {\n return bboxPolygon(bbox(geojson));\n}\nvar index_default = envelope;\nexport {\n index_default as default,\n envelope\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { featureCollection } from \"@turf/helpers\";\n\n// lib/util.ts\nimport { booleanPointInPolygon } from \"@turf/boolean-point-in-polygon\";\nimport { point } from \"@turf/helpers\";\nfunction mathSign(x) {\n return (x > 0) - (x < 0) || +x;\n}\nfunction orientationIndex(p1, p2, q) {\n const dx1 = p2[0] - p1[0], dy1 = p2[1] - p1[1], dx2 = q[0] - p2[0], dy2 = q[1] - p2[1];\n return mathSign(dx1 * dy2 - dx2 * dy1);\n}\nfunction envelopeIsEqual(env1, env2) {\n const envX1 = env1.geometry.coordinates[0].map((c) => c[0]), envY1 = env1.geometry.coordinates[0].map((c) => c[1]), envX2 = env2.geometry.coordinates[0].map((c) => c[0]), envY2 = env2.geometry.coordinates[0].map((c) => c[1]);\n return Math.max.apply(null, envX1) === Math.max.apply(null, envX2) && Math.max.apply(null, envY1) === Math.max.apply(null, envY2) && Math.min.apply(null, envX1) === Math.min.apply(null, envX2) && Math.min.apply(null, envY1) === Math.min.apply(null, envY2);\n}\nfunction envelopeContains(self, env) {\n return env.geometry.coordinates[0].every(\n (c) => booleanPointInPolygon(point(c), self)\n );\n}\nfunction coordinatesEqual(coord1, coord2) {\n return coord1[0] === coord2[0] && coord1[1] === coord2[1];\n}\n\n// lib/Node.ts\nvar Node = class _Node {\n static buildId(coordinates) {\n return coordinates.join(\",\");\n }\n constructor(coordinates) {\n this.id = _Node.buildId(coordinates);\n this.coordinates = coordinates;\n this.innerEdges = [];\n this.outerEdges = [];\n this.outerEdgesSorted = false;\n }\n removeInnerEdge(edge) {\n this.innerEdges = this.innerEdges.filter((e) => e.from.id !== edge.from.id);\n }\n removeOuterEdge(edge) {\n this.outerEdges = this.outerEdges.filter((e) => e.to.id !== edge.to.id);\n }\n /**\n * Outer edges are stored CCW order.\n *\n * @memberof Node\n * @param {Edge} edge - Edge to add as an outerEdge.\n */\n addOuterEdge(edge) {\n this.outerEdges.push(edge);\n this.outerEdgesSorted = false;\n }\n /**\n * Sorts outer edges in CCW way.\n *\n * @memberof Node\n * @private\n */\n sortOuterEdges() {\n if (!this.outerEdgesSorted) {\n this.outerEdges.sort((a, b) => {\n const aNode = a.to, bNode = b.to;\n if (aNode.coordinates[0] - this.coordinates[0] >= 0 && bNode.coordinates[0] - this.coordinates[0] < 0)\n return 1;\n if (aNode.coordinates[0] - this.coordinates[0] < 0 && bNode.coordinates[0] - this.coordinates[0] >= 0)\n return -1;\n if (aNode.coordinates[0] - this.coordinates[0] === 0 && bNode.coordinates[0] - this.coordinates[0] === 0) {\n if (aNode.coordinates[1] - this.coordinates[1] >= 0 || bNode.coordinates[1] - this.coordinates[1] >= 0)\n return aNode.coordinates[1] - bNode.coordinates[1];\n return bNode.coordinates[1] - aNode.coordinates[1];\n }\n const det = orientationIndex(\n this.coordinates,\n aNode.coordinates,\n bNode.coordinates\n );\n if (det < 0) return 1;\n if (det > 0) return -1;\n const d1 = Math.pow(aNode.coordinates[0] - this.coordinates[0], 2) + Math.pow(aNode.coordinates[1] - this.coordinates[1], 2), d2 = Math.pow(bNode.coordinates[0] - this.coordinates[0], 2) + Math.pow(bNode.coordinates[1] - this.coordinates[1], 2);\n return d1 - d2;\n });\n this.outerEdgesSorted = true;\n }\n }\n /**\n * Retrieves outer edges.\n *\n * They are sorted if they aren't in the CCW order.\n *\n * @memberof Node\n * @returns {Edge[]} - List of outer edges sorted in a CCW order.\n */\n getOuterEdges() {\n this.sortOuterEdges();\n return this.outerEdges;\n }\n getOuterEdge(i) {\n this.sortOuterEdges();\n return this.outerEdges[i];\n }\n addInnerEdge(edge) {\n this.innerEdges.push(edge);\n }\n};\n\n// lib/Edge.ts\nimport { lineString } from \"@turf/helpers\";\nvar Edge = class _Edge {\n /**\n * Creates or get the symetric Edge.\n *\n * @returns {Edge} - Symetric Edge.\n */\n getSymetric() {\n if (!this.symetric) {\n this.symetric = new _Edge(this.to, this.from);\n this.symetric.symetric = this;\n }\n return this.symetric;\n }\n /**\n * @param {Node} from - start node of the Edge\n * @param {Node} to - end node of the edge\n */\n constructor(from, to) {\n this.from = from;\n this.to = to;\n this.next = void 0;\n this.label = void 0;\n this.symetric = void 0;\n this.ring = void 0;\n this.from.addOuterEdge(this);\n this.to.addInnerEdge(this);\n }\n /**\n * Removes edge from from and to nodes.\n */\n deleteEdge() {\n this.from.removeOuterEdge(this);\n this.to.removeInnerEdge(this);\n }\n /**\n * Compares Edge equallity.\n *\n * An edge is equal to another, if the from and to nodes are the same.\n *\n * @param {Edge} edge - Another Edge\n * @returns {boolean} - True if Edges are equal, False otherwise\n */\n isEqual(edge) {\n return this.from.id === edge.from.id && this.to.id === edge.to.id;\n }\n toString() {\n return `Edge { ${this.from.id} -> ${this.to.id} }`;\n }\n /**\n * Returns a LineString representation of the Edge\n *\n * @returns {Feature<LineString>} - LineString representation of the Edge\n */\n toLineString() {\n return lineString([this.from.coordinates, this.to.coordinates]);\n }\n /**\n * Comparator of two edges.\n *\n * Implementation of geos::planargraph::DirectedEdge::compareTo.\n *\n * @param {Edge} edge - Another edge to compare with this one\n * @returns {number} -1 if this Edge has a greater angle with the positive x-axis than b,\n * 0 if the Edges are colinear,\n * 1 otherwise\n */\n compareTo(edge) {\n return orientationIndex(\n edge.from.coordinates,\n edge.to.coordinates,\n this.to.coordinates\n );\n }\n};\n\n// lib/EdgeRing.ts\nimport { multiPoint, polygon, point as point2 } from \"@turf/helpers\";\nimport { envelope } from \"@turf/envelope\";\nimport { booleanPointInPolygon as booleanPointInPolygon2 } from \"@turf/boolean-point-in-polygon\";\nvar EdgeRing = class {\n constructor() {\n this.edges = [];\n this.polygon = void 0;\n this.envelope = void 0;\n }\n /**\n * Add an edge to the ring, inserting it in the last position.\n *\n * @memberof EdgeRing\n * @param {Edge} edge - Edge to be inserted\n */\n push(edge) {\n this.edges.push(edge);\n this.polygon = this.envelope = void 0;\n }\n /**\n * Get Edge.\n *\n * @memberof EdgeRing\n * @param {number} i - Index\n * @returns {Edge} - Edge in the i position\n */\n get(i) {\n return this.edges[i];\n }\n /**\n * Getter of length property.\n *\n * @memberof EdgeRing\n * @returns {number} - Length of the edge ring.\n */\n get length() {\n return this.edges.length;\n }\n /**\n * Similar to Array.prototype.forEach for the list of Edges in the EdgeRing.\n *\n * @memberof EdgeRing\n * @param {Function} f - The same function to be passed to Array.prototype.forEach\n */\n forEach(f) {\n this.edges.forEach(f);\n }\n /**\n * Similar to Array.prototype.map for the list of Edges in the EdgeRing.\n *\n * @memberof EdgeRing\n * @param {Function} f - The same function to be passed to Array.prototype.map\n * @returns {Array} - The mapped values in the function\n */\n map(f) {\n return this.edges.map(f);\n }\n /**\n * Similar to Array.prototype.some for the list of Edges in the EdgeRing.\n *\n * @memberof EdgeRing\n * @param {Function} f - The same function to be passed to Array.prototype.some\n * @returns {boolean} - True if an Edge check the condition\n */\n some(f) {\n return this.edges.some(f);\n }\n /**\n * Check if the ring is valid in geomtry terms.\n *\n * A ring must have either 0 or 4 or more points. The first and the last must be\n * equal (in 2D)\n * geos::geom::LinearRing::validateConstruction\n *\n * @memberof EdgeRing\n * @returns {boolean} - Validity of the EdgeRing\n */\n isValid() {\n return true;\n }\n /**\n * Tests whether this ring is a hole.\n *\n * A ring is a hole if it is oriented counter-clockwise.\n * Similar implementation of geos::algorithm::CGAlgorithms::isCCW\n *\n * @memberof EdgeRing\n * @returns {boolean} - true: if it is a hole\n */\n isHole() {\n const hiIndex = this.edges.reduce((high, edge, i) => {\n if (edge.from.coordinates[1] > this.edges[high].from.coordinates[1])\n high = i;\n return high;\n }, 0), iPrev = (hiIndex === 0 ? this.length : hiIndex) - 1, iNext = (hiIndex + 1) % this.length, disc = orientationIndex(\n this.edges[iPrev].from.coordinates,\n this.edges[hiIndex].from.coordinates,\n this.edges[iNext].from.coordinates\n );\n if (disc === 0)\n return this.edges[iPrev].from.coordinates[0] > this.edges[iNext].from.coordinates[0];\n return disc > 0;\n }\n /**\n * Creates a MultiPoint representing the EdgeRing (discarts edges directions).\n *\n * @memberof EdgeRing\n * @returns {Feature<MultiPoint>} - Multipoint representation of the EdgeRing\n */\n toMultiPoint() {\n return multiPoint(this.edges.map((edge) => edge.from.coordinates));\n }\n /**\n * Creates a Polygon representing the EdgeRing.\n *\n * @memberof EdgeRing\n * @returns {Feature<Polygon>} - Polygon representation of the Edge Ring\n */\n toPolygon() {\n if (this.polygon) return this.polygon;\n const coordinates = this.edges.map((edge) => edge.from.coordinates);\n coordinates.push(this.edges[0].from.coordinates);\n return this.polygon = polygon([coordinates]);\n }\n /**\n * Calculates the envelope of the EdgeRing.\n *\n * @memberof EdgeRing\n * @returns {Feature<Polygon>} - envelope\n */\n getEnvelope() {\n if (this.envelope) return this.envelope;\n return this.envelope = envelope(this.toPolygon());\n }\n /**\n * `geos::operation::polygonize::EdgeRing::findEdgeRingContaining`\n *\n * @param {EdgeRing} testEdgeRing - EdgeRing to look in the list\n * @param {EdgeRing[]} shellList - List of EdgeRing in which to search\n *\n * @returns {EdgeRing} - EdgeRing which contains the testEdgeRing\n */\n static findEdgeRingContaining(testEdgeRing, shellList) {\n const testEnvelope = testEdgeRing.getEnvelope();\n let minEnvelope, minShell;\n shellList.forEach((shell) => {\n const tryEnvelope = shell.getEnvelope();\n if (minShell) minEnvelope = minShell.getEnvelope();\n if (envelopeIsEqual(tryEnvelope, testEnvelope)) return;\n if (envelopeContains(tryEnvelope, testEnvelope)) {\n const testEdgeRingCoordinates = testEdgeRing.map(\n (edge) => edge.from.coordinates\n );\n let testPoint;\n for (const pt of testEdgeRingCoordinates) {\n if (!shell.some((edge) => coordinatesEqual(pt, edge.from.coordinates))) {\n testPoint = pt;\n }\n }\n if (testPoint && shell.inside(point2(testPoint))) {\n if (!minShell || envelopeContains(minEnvelope, tryEnvelope))\n minShell = shell;\n }\n }\n });\n return minShell;\n }\n /**\n * Checks if the point is inside the edgeRing\n *\n * @param {Feature<Point>} pt - Point to check if it is inside the edgeRing\n * @returns {boolean} - True if it is inside, False otherwise\n */\n inside(pt) {\n return booleanPointInPolygon2(pt, this.toPolygon());\n }\n};\n\n// lib/Graph.ts\nimport { flattenEach, coordReduce } from \"@turf/meta\";\nimport { featureOf } from \"@turf/invariant\";\nfunction validateGeoJson(geoJson) {\n if (!geoJson) throw new Error(\"No geojson passed\");\n if (geoJson.type !== \"FeatureCollection\" && geoJson.type !== \"GeometryCollection\" && geoJson.type !== \"MultiLineString\" && geoJson.type !== \"LineString\" && geoJson.type !== \"Feature\")\n throw new Error(\n `Invalid input type '${geoJson.type}'. Geojson must be FeatureCollection, GeometryCollection, LineString, MultiLineString or Feature`\n );\n}\nvar Graph = class _Graph {\n /**\n * Creates a graph from a GeoJSON.\n *\n * @param {FeatureCollection<LineString>} geoJson - it must comply with the restrictions detailed in the index\n * @returns {Graph} - The newly created graph\n * @throws {Error} if geoJson is invalid.\n */\n static fromGeoJson(geoJson) {\n validateGeoJson(geoJson);\n const graph = new _Graph();\n flattenEach(geoJson, (feature) => {\n featureOf(feature, \"LineString\", \"Graph::fromGeoJson\");\n coordReduce(feature, (prev, cur) => {\n if (prev) {\n const start = graph.getNode(prev), end = graph.getNode(cur);\n graph.addEdge(start, end);\n }\n return cur;\n });\n });\n return graph;\n }\n /**\n * Creates or get a Node.\n *\n * @param {number[]} coordinates - Coordinates of the node\n * @returns {Node} - The created or stored node\n */\n getNode(coordinates) {\n const id = Node.buildId(coordinates);\n let node = this.nodes[id];\n if (!node) node = this.nodes[id] = new Node(coordinates);\n return node;\n }\n /**\n * Adds an Edge and its symetricall.\n *\n * Edges are added symetrically, i.e.: we also add its symetric\n *\n * @param {Node} from - Node which starts the Edge\n * @param {Node} to - Node which ends the Edge\n */\n addEdge(from, to) {\n const edge = new Edge(from, to), symetricEdge = edge.getSymetric();\n this.edges.push(edge);\n this.edges.push(symetricEdge);\n }\n constructor() {\n this.edges = [];\n this.nodes = {};\n }\n /**\n * Removes Dangle Nodes (nodes with grade 1).\n */\n deleteDangles() {\n Object.keys(this.nodes).map((id) => this.nodes[id]).forEach((node) => this._removeIfDangle(node));\n }\n /**\n * Check if node is dangle, if so, remove it.\n *\n * It calls itself recursively, removing a dangling node might cause another dangling node\n *\n * @param {Node} node - Node to check if it's a dangle\n */\n _removeIfDangle(node) {\n if (node.innerEdges.length <= 1) {\n const outerNodes = node.getOuterEdges().map((e) => e.to);\n this.removeNode(node);\n outerNodes.forEach((n) => this._removeIfDangle(n));\n }\n }\n /**\n * Delete cut-edges (bridge edges).\n *\n * The graph will be traversed, all the edges will be labeled according the ring\n * in which they are. (The label is a number incremented by 1). Edges with the same\n * label are cut-edges.\n */\n deleteCutEdges() {\n this._computeNextCWEdges();\n this._findLabeledEdgeRings();\n this.edges.forEach((edge) => {\n if (edge.label === edge.symetric.label) {\n this.removeEdge(edge.symetric);\n this.removeEdge(edge);\n }\n });\n }\n /**\n * Set the `next` property of each Edge.\n *\n * The graph will be transversed in a CW form, so, we set the next of the symetrical edge as the previous one.\n * OuterEdges are sorted CCW.\n *\n * @param {Node} [node] - If no node is passed, the function calls itself for every node in the Graph\n */\n _computeNextCWEdges(node) {\n if (typeof node === \"undefined\") {\n Object.keys(this.nodes).forEach(\n (id) => this._computeNextCWEdges(this.nodes[id])\n );\n } else {\n node.getOuterEdges().forEach((edge, i) => {\n node.getOuterEdge(\n (i === 0 ? node.getOuterEdges().length : i) - 1\n ).symetric.next = edge;\n });\n }\n }\n /**\n * Computes the next edge pointers going CCW around the given node, for the given edgering label.\n *\n * This algorithm has the effect of converting maximal edgerings into minimal edgerings\n *\n * XXX: method literally transcribed from `geos::operation::polygonize::PolygonizeGraph::computeNextCCWEdges`,\n * could be written in a more javascript way.\n *\n * @param {Node} node - Node\n * @param {number} label - Ring's label\n */\n _computeNextCCWEdges(node, label) {\n const edges = node.getOuterEdges();\n let firstOutDE, prevInDE;\n for (let i = edges.length - 1; i >= 0; --i) {\n let de = edges[i], sym = de.symetric, outDE, inDE;\n if (de.label === label) outDE = de;\n if (sym.label === label) inDE = sym;\n if (!outDE || !inDE)\n continue;\n if (inDE) prevInDE = inDE;\n if (outDE) {\n if (prevInDE) {\n prevInDE.next = outDE;\n prevInDE = void 0;\n }\n if (!firstOutDE) firstOutDE = outDE;\n }\n }\n if (prevInDE) prevInDE.next = firstOutDE;\n }\n /**\n * Finds rings and labels edges according to which rings are.\n *\n * The label is a number which is increased for each ring.\n *\n * @returns {Edge[]} edges that start rings\n */\n _findLabeledEdgeRings() {\n const edgeRingStarts = [];\n let label = 0;\n this.edges.forEach((edge) => {\n if (edge.label >= 0) return;\n edgeRingStarts.push(edge);\n let e = edge;\n do {\n e.label = label;\n e = e.next;\n } while (!edge.isEqual(e));\n label++;\n });\n return edgeRingStarts;\n }\n /**\n * Computes the EdgeRings formed by the edges in this graph.\n *\n * @returns {EdgeRing[]} - A list of all the EdgeRings in the graph.\n */\n getEdgeRings() {\n this._computeNextCWEdges();\n this.edges.forEach((edge) => {\n edge.label = void 0;\n });\n this._findLabeledEdgeRings().forEach((edge) => {\n this._findIntersectionNodes(edge).forEach((node) => {\n this._computeNextCCWEdges(node, edge.label);\n });\n });\n const edgeRingList = [];\n this.edges.forEach((edge) => {\n if (edge.ring) return;\n edgeRingList.push(this._findEdgeRing(edge));\n });\n return edgeRingList;\n }\n /**\n * Find all nodes in a Maxima EdgeRing which are self-intersection nodes.\n *\n * @param {Node} startEdge - Start Edge of the Ring\n * @returns {Node[]} - intersection nodes\n */\n _findIntersectionNodes(startEdge) {\n const intersectionNodes = [];\n let edge = startEdge;\n do {\n let degree = 0;\n edge.from.getOuterEdges().forEach((e) => {\n if (e.label === startEdge.label) ++degree;\n });\n if (degree > 1) intersectionNodes.push(edge.from);\n edge = edge.next;\n } while (!startEdge.isEqual(edge));\n return intersectionNodes;\n }\n /**\n * Get the edge-ring which starts from the provided Edge.\n *\n * @param {Edge} startEdge - starting edge of the edge ring\n * @returns {EdgeRing} - EdgeRing which start Edge is the provided one.\n */\n _findEdgeRing(startEdge) {\n let edge = startEdge;\n const edgeRing = new EdgeRing();\n do {\n edgeRing.push(edge);\n edge.ring = edgeRing;\n edge = edge.next;\n } while (!startEdge.isEqual(edge));\n return edgeRing;\n }\n /**\n * Removes a node from the Graph.\n *\n * It also removes edges asociated to that node\n * @param {Node} node - Node to be removed\n */\n removeNode(node) {\n node.getOuterEdges().forEach((edge) => this.removeEdge(edge));\n node.innerEdges.forEach((edge) => this.removeEdge(edge));\n delete this.nodes[node.id];\n }\n /**\n * Remove edge from the graph and deletes the edge.\n *\n * @param {Edge} edge - Edge to be removed\n */\n removeEdge(edge) {\n this.edges = this.edges.filter((e) => !e.isEqual(edge));\n edge.deleteEdge();\n }\n};\n\n// index.ts\nfunction polygonize(geoJson) {\n const graph = Graph.fromGeoJson(geoJson);\n graph.deleteDangles();\n graph.deleteCutEdges();\n const holes = [], shells = [];\n graph.getEdgeRings().filter((edgeRing) => edgeRing.isValid()).forEach((edgeRing) => {\n if (edgeRing.isHole()) holes.push(edgeRing);\n else shells.push(edgeRing);\n });\n holes.forEach((hole) => {\n if (EdgeRing.findEdgeRingContaining(hole, shells)) shells.push(hole);\n });\n return featureCollection(shells.map((shell) => shell.toPolygon()));\n}\nvar index_default = polygonize;\nexport {\n index_default as default,\n polygonize\n};\n//# sourceMappingURL=index.js.map","\n/**\n * Rearranges items so that all items in the [left, k] are the smallest.\n * The k-th element will have the (k - left + 1)-th smallest value in [left, right].\n *\n * @template T\n * @param {T[]} arr the array to partially sort (in place)\n * @param {number} k middle index for partial sorting (as defined above)\n * @param {number} [left=0] left index of the range to sort\n * @param {number} [right=arr.length-1] right index\n * @param {(a: T, b: T) => number} [compare = (a, b) => a - b] compare function\n */\nexport default function quickselect(arr, k, left = 0, right = arr.length - 1, compare = defaultCompare) {\n\n while (right > left) {\n if (right - left > 600) {\n const n = right - left + 1;\n const m = k - left + 1;\n const z = Math.log(n);\n const s = 0.5 * Math.exp(2 * z / 3);\n const sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);\n const newLeft = Math.max(left, Math.floor(k - m * s / n + sd));\n const newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));\n quickselect(arr, k, newLeft, newRight, compare);\n }\n\n const t = arr[k];\n let i = left;\n /** @type {number} */\n let j = right;\n\n swap(arr, left, k);\n if (compare(arr[right], t) > 0) swap(arr, left, right);\n\n while (i < j) {\n swap(arr, i, j);\n i++;\n j--;\n while (compare(arr[i], t) < 0) i++;\n while (compare(arr[j], t) > 0) j--;\n }\n\n if (compare(arr[left], t) === 0) swap(arr, left, j);\n else {\n j++;\n swap(arr, j, right);\n }\n\n if (j <= k) left = j + 1;\n if (k <= j) right = j - 1;\n }\n}\n\n/**\n * @template T\n * @param {T[]} arr\n * @param {number} i\n * @param {number} j\n */\nfunction swap(arr, i, j) {\n const tmp = arr[i];\n arr[i] = arr[j];\n arr[j] = tmp;\n}\n\n/**\n * @template T\n * @param {T} a\n * @param {T} b\n * @returns {number}\n */\nfunction defaultCompare(a, b) {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n","import quickselect from 'quickselect';\n\nexport default class RBush {\n constructor(maxEntries = 9) {\n // max entries in a node is 9 by default; min node fill is 40% for best performance\n this._maxEntries = Math.max(4, maxEntries);\n this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));\n this.clear();\n }\n\n all() {\n return this._all(this.data, []);\n }\n\n search(bbox) {\n let node = this.data;\n const result = [];\n\n if (!intersects(bbox, node)) return result;\n\n const toBBox = this.toBBox;\n const nodesToSearch = [];\n\n while (node) {\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n const childBBox = node.leaf ? toBBox(child) : child;\n\n if (intersects(bbox, childBBox)) {\n if (node.leaf) result.push(child);\n else if (contains(bbox, childBBox)) this._all(child, result);\n else nodesToSearch.push(child);\n }\n }\n node = nodesToSearch.pop();\n }\n\n return result;\n }\n\n collides(bbox) {\n let node = this.data;\n\n if (!intersects(bbox, node)) return false;\n\n const nodesToSearch = [];\n while (node) {\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n const childBBox = node.leaf ? this.toBBox(child) : child;\n\n if (intersects(bbox, childBBox)) {\n if (node.leaf || contains(bbox, childBBox)) return true;\n nodesToSearch.push(child);\n }\n }\n node = nodesToSearch.pop();\n }\n\n return false;\n }\n\n load(data) {\n if (!(data && data.length)) return this;\n\n if (data.length < this._minEntries) {\n for (let i = 0; i < data.length; i++) {\n this.insert(data[i]);\n }\n return this;\n }\n\n // recursively build the tree with the given data from scratch using OMT algorithm\n let node = this._build(data.slice(), 0, data.length - 1, 0);\n\n if (!this.data.children.length) {\n // save as is if tree is empty\n this.data = node;\n\n } else if (this.data.height === node.height) {\n // split root if trees have the same height\n this._splitRoot(this.data, node);\n\n } else {\n if (this.data.height < node.height) {\n // swap trees if inserted one is bigger\n const tmpNode = this.data;\n this.data = node;\n node = tmpNode;\n }\n\n // insert the small tree into the large tree at appropriate level\n this._insert(node, this.data.height - node.height - 1, true);\n }\n\n return this;\n }\n\n insert(item) {\n if (item) this._insert(item, this.data.height - 1);\n return this;\n }\n\n clear() {\n this.data = createNode([]);\n return this;\n }\n\n remove(item, equalsFn) {\n if (!item) return this;\n\n let node = this.data;\n const bbox = this.toBBox(item);\n const path = [];\n const indexes = [];\n let i, parent, goingUp;\n\n // depth-first iterative tree traversal\n while (node || path.length) {\n\n if (!node) { // go up\n node = path.pop();\n parent = path[path.length - 1];\n i = indexes.pop();\n goingUp = true;\n }\n\n if (node.leaf) { // check current node\n const index = findItem(item, node.children, equalsFn);\n\n if (index !== -1) {\n // item found, remove the item and condense tree upwards\n node.children.splice(index, 1);\n path.push(node);\n this._condense(path);\n return this;\n }\n }\n\n if (!goingUp && !node.leaf && contains(node, bbox)) { // go down\n path.push(node);\n indexes.push(i);\n i = 0;\n parent = node;\n node = node.children[0];\n\n } else if (parent) { // go right\n i++;\n node = parent.children[i];\n goingUp = false;\n\n } else node = null; // nothing found\n }\n\n return this;\n }\n\n toBBox(item) { return item; }\n\n compareMinX(a, b) { return a.minX - b.minX; }\n compareMinY(a, b) { return a.minY - b.minY; }\n\n toJSON() { return this.data; }\n\n fromJSON(data) {\n this.data = data;\n return this;\n }\n\n _all(node, result) {\n const nodesToSearch = [];\n while (node) {\n if (node.leaf) result.push(...node.children);\n else nodesToSearch.push(...node.children);\n\n node = nodesToSearch.pop();\n }\n return result;\n }\n\n _build(items, left, right, height) {\n\n const N = right - left + 1;\n let M = this._maxEntries;\n let node;\n\n if (N <= M) {\n // reached leaf level; return leaf\n node = createNode(items.slice(left, right + 1));\n calcBBox(node, this.toBBox);\n return node;\n }\n\n if (!height) {\n // target height of the bulk-loaded tree\n height = Math.ceil(Math.log(N) / Math.log(M));\n\n // target number of root entries to maximize storage utilization\n M = Math.ceil(N / Math.pow(M, height - 1));\n }\n\n node = createNode([]);\n node.leaf = false;\n node.height = height;\n\n // split the items into M mostly square tiles\n\n const N2 = Math.ceil(N / M);\n const N1 = N2 * Math.ceil(Math.sqrt(M));\n\n multiSelect(items, left, right, N1, this.compareMinX);\n\n for (let i = left; i <= right; i += N1) {\n\n const right2 = Math.min(i + N1 - 1, right);\n\n multiSelect(items, i, right2, N2, this.compareMinY);\n\n for (let j = i; j <= right2; j += N2) {\n\n const right3 = Math.min(j + N2 - 1, right2);\n\n // pack each entry recursively\n node.children.push(this._build(items, j, right3, height - 1));\n }\n }\n\n calcBBox(node, this.toBBox);\n\n return node;\n }\n\n _chooseSubtree(bbox, node, level, path) {\n while (true) {\n path.push(node);\n\n if (node.leaf || path.length - 1 === level) break;\n\n let minArea = Infinity;\n let minEnlargement = Infinity;\n let targetNode;\n\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n const area = bboxArea(child);\n const enlargement = enlargedArea(bbox, child) - area;\n\n // choose entry with the least area enlargement\n if (enlargement < minEnlargement) {\n minEnlargement = enlargement;\n minArea = area < minArea ? area : minArea;\n targetNode = child;\n\n } else if (enlargement === minEnlargement) {\n // otherwise choose one with the smallest area\n if (area < minArea) {\n minArea = area;\n targetNode = child;\n }\n }\n }\n\n node = targetNode || node.children[0];\n }\n\n return node;\n }\n\n _insert(item, level, isNode) {\n const bbox = isNode ? item : this.toBBox(item);\n const insertPath = [];\n\n // find the best node for accommodating the item, saving all nodes along the path too\n const node = this._chooseSubtree(bbox, this.data, level, insertPath);\n\n // put the item into the node\n node.children.push(item);\n extend(node, bbox);\n\n // split on node overflow; propagate upwards if necessary\n while (level >= 0) {\n if (insertPath[level].children.length > this._maxEntries) {\n this._split(insertPath, level);\n level--;\n } else break;\n }\n\n // adjust bboxes along the insertion path\n this._adjustParentBBoxes(bbox, insertPath, level);\n }\n\n // split overflowed node into two\n _split(insertPath, level) {\n const node = insertPath[level];\n const M = node.children.length;\n const m = this._minEntries;\n\n this._chooseSplitAxis(node, m, M);\n\n const splitIndex = this._chooseSplitIndex(node, m, M);\n\n const newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));\n newNode.height = node.height;\n newNode.leaf = node.leaf;\n\n calcBBox(node, this.toBBox);\n calcBBox(newNode, this.toBBox);\n\n if (level) insertPath[level - 1].children.push(newNode);\n else this._splitRoot(node, newNode);\n }\n\n _splitRoot(node, newNode) {\n // split root node\n this.data = createNode([node, newNode]);\n this.data.height = node.height + 1;\n this.data.leaf = false;\n calcBBox(this.data, this.toBBox);\n }\n\n _chooseSplitIndex(node, m, M) {\n let index;\n let minOverlap = Infinity;\n let minArea = Infinity;\n\n for (let i = m; i <= M - m; i++) {\n const bbox1 = distBBox(node, 0, i, this.toBBox);\n const bbox2 = distBBox(node, i, M, this.toBBox);\n\n const overlap = intersectionArea(bbox1, bbox2);\n const area = bboxArea(bbox1) + bboxArea(bbox2);\n\n // choose distribution with minimum overlap\n if (overlap < minOverlap) {\n minOverlap = overlap;\n index = i;\n\n minArea = area < minArea ? area : minArea;\n\n } else if (overlap === minOverlap) {\n // otherwise choose distribution with minimum area\n if (area < minArea) {\n minArea = area;\n index = i;\n }\n }\n }\n\n return index || M - m;\n }\n\n // sorts node children by the best axis for split\n _chooseSplitAxis(node, m, M) {\n const compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;\n const compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;\n const xMargin = this._allDistMargin(node, m, M, compareMinX);\n const yMargin = this._allDistMargin(node, m, M, compareMinY);\n\n // if total distributions margin value is minimal for x, sort by minX,\n // otherwise it's already sorted by minY\n if (xMargin < yMargin) node.children.sort(compareMinX);\n }\n\n // total margin of all possible split distributions where each node is at least m full\n _allDistMargin(node, m, M, compare) {\n node.children.sort(compare);\n\n const toBBox = this.toBBox;\n const leftBBox = distBBox(node, 0, m, toBBox);\n const rightBBox = distBBox(node, M - m, M, toBBox);\n let margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);\n\n for (let i = m; i < M - m; i++) {\n const child = node.children[i];\n extend(leftBBox, node.leaf ? toBBox(child) : child);\n margin += bboxMargin(leftBBox);\n }\n\n for (let i = M - m - 1; i >= m; i--) {\n const child = node.children[i];\n extend(rightBBox, node.leaf ? toBBox(child) : child);\n margin += bboxMargin(rightBBox);\n }\n\n return margin;\n }\n\n _adjustParentBBoxes(bbox, path, level) {\n // adjust bboxes along the given tree path\n for (let i = level; i >= 0; i--) {\n extend(path[i], bbox);\n }\n }\n\n _condense(path) {\n // go through the path, removing empty nodes and updating bboxes\n for (let i = path.length - 1, siblings; i >= 0; i--) {\n if (path[i].children.length === 0) {\n if (i > 0) {\n siblings = path[i - 1].children;\n siblings.splice(siblings.indexOf(path[i]), 1);\n\n } else this.clear();\n\n } else calcBBox(path[i], this.toBBox);\n }\n }\n}\n\nfunction findItem(item, items, equalsFn) {\n if (!equalsFn) return items.indexOf(item);\n\n for (let i = 0; i < items.length; i++) {\n if (equalsFn(item, items[i])) return i;\n }\n return -1;\n}\n\n// calculate node's bbox from bboxes of its children\nfunction calcBBox(node, toBBox) {\n distBBox(node, 0, node.children.length, toBBox, node);\n}\n\n// min bounding rectangle of node children from k to p-1\nfunction distBBox(node, k, p, toBBox, destNode) {\n if (!destNode) destNode = createNode(null);\n destNode.minX = Infinity;\n destNode.minY = Infinity;\n destNode.maxX = -Infinity;\n destNode.maxY = -Infinity;\n\n for (let i = k; i < p; i++) {\n const child = node.children[i];\n extend(destNode, node.leaf ? toBBox(child) : child);\n }\n\n return destNode;\n}\n\nfunction extend(a, b) {\n a.minX = Math.min(a.minX, b.minX);\n a.minY = Math.min(a.minY, b.minY);\n a.maxX = Math.max(a.maxX, b.maxX);\n a.maxY = Math.max(a.maxY, b.maxY);\n return a;\n}\n\nfunction compareNodeMinX(a, b) { return a.minX - b.minX; }\nfunction compareNodeMinY(a, b) { return a.minY - b.minY; }\n\nfunction bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }\nfunction bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }\n\nfunction enlargedArea(a, b) {\n return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *\n (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));\n}\n\nfunction intersectionArea(a, b) {\n const minX = Math.max(a.minX, b.minX);\n const minY = Math.max(a.minY, b.minY);\n const maxX = Math.min(a.maxX, b.maxX);\n const maxY = Math.min(a.maxY, b.maxY);\n\n return Math.max(0, maxX - minX) *\n Math.max(0, maxY - minY);\n}\n\nfunction contains(a, b) {\n return a.minX <= b.minX &&\n a.minY <= b.minY &&\n b.maxX <= a.maxX &&\n b.maxY <= a.maxY;\n}\n\nfunction intersects(a, b) {\n return b.minX <= a.maxX &&\n b.minY <= a.maxY &&\n b.maxX >= a.minX &&\n b.maxY >= a.minY;\n}\n\nfunction createNode(children) {\n return {\n children,\n height: 1,\n leaf: true,\n minX: Infinity,\n minY: Infinity,\n maxX: -Infinity,\n maxY: -Infinity\n };\n}\n\n// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;\n// combines selection algorithm with binary divide & conquer approach\n\nfunction multiSelect(arr, left, right, n, compare) {\n const stack = [left, right];\n\n while (stack.length) {\n right = stack.pop();\n left = stack.pop();\n\n if (right - left <= n) continue;\n\n const mid = left + Math.ceil((right - left) / n / 2) * n;\n quickselect(arr, mid, left, right, compare);\n\n stack.push(left, mid, mid, right);\n }\n}\n","import { booleanIntersects, bbox as turfBbox } from '@turf/turf';\nimport RBush from 'rbush';\nimport { Geometry } from 'geojson';\n\n/**\n * Computes connected components (clusters) of intersecting geometries and returns\n * a mapping from feature id to cluster id. The input array must contain an\n * application-level identifier for each geometry. Cluster ids are stable only\n * within a single invocation and start at 0.\n */\nexport function computeIntersectingClusterIds(\n items: Array<{ id: number | string; geometry: Geometry | null | undefined }>,\n): Map<string, number> {\n const validItems = items.map((it, idx) => ({ ...it, __idx: idx })).filter((it) => it.geometry != null) as Array<{\n id: number | string;\n geometry: Geometry;\n __idx: number;\n }>;\n\n const n = validItems.length;\n if (n === 0) return new Map();\n\n // Union-find structure\n const parent = new Array(n).fill(0).map((_, i) => i);\n const find = (i: number): number => (parent[i] === i ? i : (parent[i] = find(parent[i])));\n const union = (a: number, b: number) => {\n const ra = find(a);\n const rb = find(b);\n if (ra !== rb) parent[rb] = ra;\n };\n\n // Build R-tree of bboxes\n interface RTreeItem {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n idx: number; // index within validItems\n }\n const rtree = new RBush<RTreeItem>();\n const itemsForTree: RTreeItem[] = new Array(n);\n for (let i = 0; i < n; i++) {\n const [minX, minY, maxX, maxY] = turfBbox(validItems[i].geometry as any);\n itemsForTree[i] = { minX, minY, maxX, maxY, idx: i };\n }\n rtree.load(itemsForTree);\n\n // Intersections among nearby candidates\n for (let i = 0; i < n; i++) {\n const aItem = itemsForTree[i];\n const candidates = rtree.search(aItem);\n for (const cand of candidates) {\n const j = cand.idx;\n if (j <= i) continue;\n try {\n if (booleanIntersects(validItems[i].geometry as any, validItems[j].geometry as any)) {\n union(i, j);\n }\n } catch {\n // ignore invalid geometries\n }\n }\n }\n\n // Assign compact cluster ids\n const rootToClusterId = new Map<number, number>();\n let nextClusterId = 0;\n const result = new Map<string, number>();\n for (let i = 0; i < n; i++) {\n const root = find(i);\n if (!rootToClusterId.has(root)) rootToClusterId.set(root, nextClusterId++);\n const clusterId = rootToClusterId.get(root)!;\n const appId = String(validItems[i].id);\n result.set(appId, clusterId);\n }\n\n return result;\n}\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { Column } from '../../../shared/interfaces';\nimport { computeIntersectingClusterIds } from '../../../shared/clusterIntersectingFeatures';\n\n/**\n * Assigns stable `building_id` values by clustering intersecting building geometries.\n */\nexport class AssignBuildingIdsUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n }\n\n /**\n * Reads geometries from the provided building table, computes intersecting\n * clusters in JS, writes a stable building_id per row back to the table, and\n * returns the updated column list for the table.\n */\n async exec(params: { tableName: string; workspace?: string }): Promise<Column[]> {\n const { tableName, workspace = 'main' } = params;\n const qualifiedTableName = `${workspace}.${tableName}`;\n\n // Read id and geometry as GeoJSON for JS processing\n const selectSql = `\n SELECT id, CAST(ST_AsGeoJSON(geometry) AS JSON) AS geometry_json\n FROM ${qualifiedTableName}\n `;\n const res = await this.conn.query(selectSql);\n const rows = res.toArray();\n\n const items = rows.map((r: any) => ({ id: r.id as number, geometry: JSON.parse(r.geometry_json) as any }));\n\n const idToCluster = computeIntersectingClusterIds(items);\n\n // Skip if nothing to assign\n if (idToCluster.size === 0) {\n return await this.describeColumns(qualifiedTableName);\n }\n\n // Ensure building_id column exists\n const hasBuildingId = await this.columnExists(qualifiedTableName, 'building_id');\n if (!hasBuildingId) {\n await this.conn.query(`ALTER TABLE ${qualifiedTableName} ADD COLUMN building_id BIGINT`);\n }\n\n // Bulk insert using an in-memory JSON file (same pattern as custom layer loader)\n const jsonRows = Array.from(idToCluster.entries()).map(([id, building_id]) => ({ id: Number(id), building_id }));\n const vfsPath = `tmp_building_ids_${Date.now()}_${Math.random().toString(36).slice(2, 10)}.json`;\n await this.db.registerFileText(vfsPath, JSON.stringify({ rows: jsonRows }));\n\n await this.conn.query(`CREATE TEMP TABLE __tmp_building_ids_json AS SELECT * FROM '${vfsPath}'`);\n await this.conn.query(`\n CREATE TEMP TABLE __tmp_building_ids AS\n SELECT CAST(row.id AS BIGINT) AS id, CAST(row.building_id AS BIGINT) AS building_id\n FROM (SELECT UNNEST(rows) AS row FROM __tmp_building_ids_json);\n `);\n\n // Update table by joining on id\n await this.conn.query(\n `UPDATE ${qualifiedTableName} AS t SET building_id = b.building_id FROM __tmp_building_ids AS b WHERE t.id = b.id`,\n );\n\n // Cleanup temp table\n await this.conn.query(`DROP TABLE __tmp_building_ids`);\n await this.conn.query(`DROP TABLE __tmp_building_ids_json`);\n await this.db.dropFile(vfsPath);\n\n return await this.describeColumns(qualifiedTableName);\n }\n\n private async columnExists(tableName: string, columnName: string): Promise<boolean> {\n const pragma = await this.conn.query(`PRAGMA table_info('${tableName}')`);\n const arr = pragma?.toArray?.() ?? [];\n return arr.some((r: any) => String(r.name) === columnName);\n }\n\n private async describeColumns(tableName: string): Promise<Column[]> {\n const describe = await this.conn.query(`DESCRIBE ${tableName}`);\n const rows = describe?.toArray?.() ?? [];\n return rows.map((r: any) => ({ name: r[0] ?? r.column_name ?? r.name, type: r[1] ?? r.column_type ?? r.type }));\n }\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nconst BATCH_SIZE = 100;\n\n/**\n * Aggregates building geometries by `building_id` into union geometries.\n */\nexport class AggregateBuildingLayerUseCase {\n private conn: AsyncDuckDBConnection;\n\n constructor(conn: AsyncDuckDBConnection) {\n this.conn = conn;\n }\n\n async exec(params: { inputTableName: string; workspace?: string }): Promise<void> {\n const { inputTableName, workspace = 'main' } = params;\n const qualifiedTableName = `${workspace}.${inputTableName}`;\n const tempTableName = `${inputTableName}_temp_agg`;\n\n const result = await this.conn.query(`\n SELECT building_id\n FROM ${qualifiedTableName}\n WHERE building_id IS NOT NULL\n GROUP BY building_id\n `);\n const buildingIds: bigint[] = result.toArray().map((r: any) => r.building_id as bigint);\n\n await this.conn.query(`CREATE OR REPLACE TEMP TABLE ${tempTableName} (building_id BIGINT, agg_geometry BLOB)`);\n\n for (let i = 0; i < buildingIds.length; i += BATCH_SIZE) {\n const batch = buildingIds.slice(i, i + BATCH_SIZE);\n const ids = batch.map(id => String(id)).join(',');\n\n const query = `\n INSERT INTO ${tempTableName}\n SELECT\n building_id,\n ST_Union_Agg(ST_Buffer(geometry, 0.0)) AS agg_geometry\n FROM ${qualifiedTableName}\n WHERE building_id IN (${ids})\n AND ST_IsValid(geometry)\n GROUP BY building_id;\n `;\n\n try {\n await this.conn.query(query);\n } catch (_error) {\n for (const bid of batch) {\n try {\n await this.conn.query(`\n INSERT INTO ${tempTableName}\n SELECT\n ${String(bid)} AS building_id,\n ST_Union_Agg(ST_Buffer(geometry, 0.0)) AS agg_geometry\n FROM ${qualifiedTableName}\n WHERE building_id = ${String(bid)}\n AND ST_IsValid(geometry)\n GROUP BY building_id;\n `);\n } catch (_e) {\n console.warn(\n `[AggregateBuildingLayer] failed for building_id=${String(bid)}:`,\n (_e as Error).message,\n );\n await this.conn.query(`\n INSERT INTO ${tempTableName} (building_id, agg_geometry)\n VALUES (${String(bid)}, NULL);\n `);\n }\n }\n }\n }\n\n const addColumnQuery = `\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT\n b.*,\n agg.agg_geometry\n FROM ${qualifiedTableName} b\n LEFT JOIN ${tempTableName} agg ON b.building_id = agg.building_id;\n `;\n\n await this.conn.query(addColumnQuery);\n\n const nullCount = (\n await this.conn.query(`\n SELECT COUNT(*) AS cnt\n FROM ${qualifiedTableName}\n WHERE agg_geometry IS NULL\n `)\n ).toArray()[0]?.cnt as number;\n\n if (nullCount > 0) {\n console.warn(`[AggregateBuildingLayer] ${nullCount} rows have no agg_geometry (union failed)`);\n }\n\n await this.conn.query(`DROP TABLE IF EXISTS ${tempTableName};`);\n }\n}","import { LayerType } from 'autk-core';\n\nexport type OsmLayerType = Exclude<LayerType, 'background'>;\n\nexport interface OsmProcessingConfig {\n type: OsmLayerType;\n processesRelations: boolean;\n createsPolygons: boolean;\n postProcessing?: 'building-aggregation' | 'surface-polygonization' | null;\n}\n\nexport const OSM_PROCESSING_CONFIGS: Record<OsmLayerType, OsmProcessingConfig> = {\n surface: { type: 'surface', processesRelations: false, createsPolygons: false, postProcessing: 'surface-polygonization' },\n water: { type: 'water', processesRelations: true, createsPolygons: true, postProcessing: null },\n parks: { type: 'parks', processesRelations: true, createsPolygons: true, postProcessing: null },\n roads: { type: 'roads', processesRelations: false, createsPolygons: false, postProcessing: null },\n buildings: { type: 'buildings', processesRelations: true, createsPolygons: true, postProcessing: 'building-aggregation' },\n points: { type: 'points', processesRelations: false, createsPolygons: false, postProcessing: null },\n polygons: { type: 'polygons', processesRelations: false, createsPolygons: true, postProcessing: null },\n polylines: { type: 'polylines', processesRelations: false, createsPolygons: false, postProcessing: null },\n raster: { type: 'raster', processesRelations: false, createsPolygons: false, postProcessing: null },\n};\n\nexport function getOsmProcessingConfig(layer: LayerType): OsmProcessingConfig | null {\n if (layer === 'background') return null;\n return OSM_PROCESSING_CONFIGS[layer];\n}\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport type { Geometry, MultiPolygon, Polygon, Position } from 'geojson';\n\nimport { LoadLayerParams, LayerType } from './interfaces';\nimport { LOAD_LAYER_QUERY } from './queries';\nimport { BoundingBox, LayerTable } from '../../../shared/interfaces';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport { DEFALT_COORDINATE_FORMAT } from '../../../shared/consts';\nimport { AssignBuildingIdsUseCase } from '../assign-building-ids/AssignBuildingIdsUseCase';\nimport { AggregateBuildingLayerUseCase } from '../aggregate-building-layer/AggregateBuildingLayerUseCase';\nimport { getOsmProcessingConfig } from './osm-processing-config';\n\ntype RelationRow = {\n id: number | bigint;\n refs: unknown;\n ref_roles: unknown;\n ref_types: unknown;\n tags_json: unknown;\n};\n\ntype WayRow = {\n id: number | bigint;\n refs: unknown;\n};\n\ntype NodeRow = {\n id: number | bigint;\n lat: number;\n lon: number;\n};\n\ntype WayRing = {\n refs: number[];\n coordinates: Position[];\n};\n\ntype RelationAreaRecord = {\n id: number;\n tags: Array<{ k: string; v: string }>;\n geometry: Geometry;\n};\n\n/**\n * Extracts a thematic layer (roads, buildings, parks, water, surface) from raw OSM data.\n */\nexport class LoadLayerUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n private assignBuildingIdsUseCase: AssignBuildingIdsUseCase;\n private aggregateBuildingLayerUseCase: AggregateBuildingLayerUseCase;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n this.assignBuildingIdsUseCase = new AssignBuildingIdsUseCase(db, conn);\n this.aggregateBuildingLayerUseCase = new AggregateBuildingLayerUseCase(conn);\n }\n\n async exec(params: LoadLayerParams): Promise<LayerTable> {\n if (!params.coordinateFormat) params.coordinateFormat = DEFALT_COORDINATE_FORMAT;\n const workspace = params.workspace || 'main';\n\n const layerOutputTableName = params.outputTableName || `${params.osmInputTableName}_${params.layer}`;\n const qualifiedOutputTableName = `${workspace}.${layerOutputTableName}`;\n\n const layerQuery = LOAD_LAYER_QUERY({\n layer: params.layer,\n tableName: params.osmInputTableName,\n outputFormat: params.coordinateFormat,\n outputTableName: layerOutputTableName,\n boundingBox: params.boundingBox,\n workspace,\n });\n const describeTableResponse = await this.conn.query(layerQuery);\n let columns = getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray());\n let totalSkippedRelations = 0;\n\n const config = getOsmProcessingConfig(params.layer);\n if (!config) throw new Error(`Unsupported layer type for OSM processing: ${params.layer}`);\n\n if (config.processesRelations) {\n totalSkippedRelations = await this.appendRelationAreaGeometries({\n inputTableName: params.osmInputTableName,\n outputTableName: layerOutputTableName,\n layer: params.layer,\n coordinateFormat: params.coordinateFormat,\n boundingBox: params.boundingBox,\n workspace,\n });\n\n const describeUpdatedTableResponse = await this.conn.query(`DESCRIBE ${qualifiedOutputTableName}`);\n columns = getColumnsFromDuckDbTableDescribe(describeUpdatedTableResponse.toArray());\n }\n\n if (totalSkippedRelations > 0) {\n console.warn(`[LoadLayerUseCase] loaded ${params.layer}: ${totalSkippedRelations} relations skipped.`);\n }\n\n if (config.postProcessing === 'building-aggregation') {\n await this.assignBuildingIdsUseCase.exec({ tableName: layerOutputTableName, workspace });\n\n await this.aggregateBuildingLayerUseCase.exec({\n inputTableName: layerOutputTableName,\n workspace,\n });\n\n const describeUpdatedTableResponse = await this.conn.query(`DESCRIBE ${qualifiedOutputTableName}`);\n columns = getColumnsFromDuckDbTableDescribe(describeUpdatedTableResponse.toArray());\n }\n\n return {\n source: 'osm',\n type: params.layer,\n columns,\n name: layerOutputTableName,\n };\n }\n\n private async appendRelationAreaGeometries(params: {\n inputTableName: string;\n outputTableName: string;\n layer: LayerType;\n coordinateFormat: string;\n boundingBox?: BoundingBox;\n workspace: string;\n }): Promise<number> {\n const { records, skipped } = await this.buildRelationAreaRecords(params.inputTableName, params.layer, params.workspace);\n if (records.length === 0) return skipped;\n\n const fileName = `temp_${params.layer}_relations_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.json`;\n await this.db.registerFileText(fileName, JSON.stringify(records));\n\n const qualifiedOutputTableName = `${params.workspace}.${params.outputTableName}`;\n const geometryWgs84 = 'ST_GeomFromGeoJSON(JSON(geometry))';\n const transformedGeometry = `ST_Transform(${geometryWgs84}, 'EPSG:4326', '${params.coordinateFormat}', always_xy := true)`;\n const clippingGeometry = params.boundingBox\n ? `ST_MakeEnvelope(${params.boundingBox.minLon}, ${params.boundingBox.minLat}, ${params.boundingBox.maxLon}, ${params.boundingBox.maxLat})`\n : null;\n const geometrySelect = clippingGeometry\n ? `ST_Intersection(${transformedGeometry}, ${clippingGeometry})`\n : transformedGeometry;\n const whereClause = clippingGeometry\n ? `WHERE ST_Intersects(${transformedGeometry}, ${clippingGeometry})`\n : '';\n\n try {\n await this.conn.query(`\n INSERT INTO ${qualifiedOutputTableName} (id, properties, refs, geometry)\n SELECT\n id::BIGINT,\n CASE\n WHEN tags IS NULL OR tags = [] THEN NULL\n ELSE map_from_entries(tags)\n END AS properties,\n []::BIGINT[] AS refs,\n ${geometrySelect} AS geometry\n FROM '${fileName}'\n ${whereClause};\n `);\n } finally {\n await this.db.dropFile(fileName);\n }\n\n return skipped;\n }\n\n private async buildRelationAreaRecords(\n inputTableName: string,\n layer: LayerType,\n workspace: string,\n ): Promise<{ records: RelationAreaRecord[]; skipped: number }> {\n const qualifiedInputTableName = `${workspace}.${inputTableName}`;\n const relations = (await this.conn.query(`\n SELECT id, refs, ref_roles, ref_types, CAST(tags AS JSON) AS tags_json\n FROM ${qualifiedInputTableName}\n WHERE kind = 'relation' AND map_extract(tags, '__autk_layer')[1] = '${layer}';\n `)).toArray() as unknown as RelationRow[];\n\n if (relations.length === 0) return { records: [], skipped: 0 };\n\n const ways = (await this.conn.query(`\n SELECT id, refs\n FROM ${qualifiedInputTableName}\n WHERE kind = 'way';\n `)).toArray() as unknown as WayRow[];\n const nodes = (await this.conn.query(`\n SELECT id, lat, lon\n FROM ${qualifiedInputTableName}\n WHERE kind = 'node';\n `)).toArray() as unknown as NodeRow[];\n\n const refsByWayId = new Map<number, number[]>();\n for (const way of ways) {\n refsByWayId.set(this.toNumber(way.id), this.toNumberArray(way.refs));\n }\n\n const coordinateByNodeId = new Map<number, Position>();\n for (const node of nodes) {\n coordinateByNodeId.set(this.toNumber(node.id), [node.lon, node.lat]);\n }\n\n const records: RelationAreaRecord[] = [];\n let skipped = 0;\n for (const relation of relations) {\n const geometry = this.buildRelationGeometry(relation, refsByWayId, coordinateByNodeId);\n if (!geometry) {\n skipped++;\n continue;\n }\n\n const tags = this.parseTags(relation.tags_json);\n records.push({\n id: this.toNumber(relation.id),\n tags: Object.entries(tags).map(([k, v]) => ({ k, v })),\n geometry,\n });\n }\n\n if (skipped > 0) {\n console.warn(`[autk-db] ${layer}: ${skipped} relations skipped (missing member ways or geometry).`);\n }\n\n return { records, skipped };\n }\n\n private buildRelationGeometry(\n relation: RelationRow,\n refsByWayId: Map<number, number[]>,\n coordinateByNodeId: Map<number, Position>,\n ): Polygon | MultiPolygon | null {\n const refs = this.toNumberArray(relation.refs);\n const roles = this.toStringArray(relation.ref_roles);\n const types = this.toStringArray(relation.ref_types);\n\n const outerWayIds: number[] = [];\n const innerWayIds: number[] = [];\n\n refs.forEach((ref, index) => {\n if (types[index] !== 'way') return;\n\n const role = roles[index] ?? '';\n if (role === 'inner') {\n innerWayIds.push(ref);\n } else if (role === 'outer' || role === '') {\n outerWayIds.push(ref);\n }\n });\n\n const outerRings = this.buildClosedRings(outerWayIds, refsByWayId, coordinateByNodeId);\n const innerRings = this.buildClosedRings(innerWayIds, refsByWayId, coordinateByNodeId);\n if (outerRings.length === 0) return null;\n\n const polygons = outerRings.map((outer) => [outer.coordinates] as Position[][]);\n\n for (const inner of innerRings) {\n const matchIndex = outerRings.length === 1\n ? 0\n : outerRings.findIndex((outer) => this.ringContainsPosition(outer.coordinates, inner.coordinates[0]));\n\n if (matchIndex === -1) {\n console.warn(`[autk-db] Skipped unmatched inner ring in relation ${String(relation.id)}.`);\n continue;\n }\n\n polygons[matchIndex].push(inner.coordinates);\n }\n\n if (polygons.length === 1) {\n return {\n type: 'Polygon',\n coordinates: polygons[0],\n };\n }\n\n return {\n type: 'MultiPolygon',\n coordinates: polygons,\n };\n }\n\n private buildClosedRings(\n wayIds: number[],\n refsByWayId: Map<number, number[]>,\n coordinateByNodeId: Map<number, Position>,\n ): WayRing[] {\n const standaloneClosedRings: WayRing[] = [];\n const openSegments: WayRing[] = [];\n\n for (const wayId of wayIds) {\n const refs = refsByWayId.get(wayId);\n if (!refs || refs.length < 2) continue;\n\n const coordinates = refs.map((ref) => coordinateByNodeId.get(ref));\n if (coordinates.some((coordinate) => !coordinate)) continue;\n\n const ring = { refs: [...refs], coordinates: coordinates as Position[] };\n if (refs.length > 3 && refs[0] === refs[refs.length - 1]) {\n standaloneClosedRings.push(ring);\n } else {\n openSegments.push(ring);\n }\n }\n\n return [...standaloneClosedRings, ...this.stitchOpenWaySegmentsIntoRings(openSegments)];\n }\n\n private stitchOpenWaySegmentsIntoRings(segments: WayRing[]): WayRing[] {\n const unusedSegments = [...segments];\n const rings: WayRing[] = [];\n\n while (unusedSegments.length > 0) {\n let current = unusedSegments.shift()!;\n let extended = true;\n\n while (extended) {\n extended = false;\n for (let i = 0; i < unusedSegments.length; i++) {\n const merged = this.tryMergeRings(current, unusedSegments[i]);\n if (!merged) continue;\n\n current = merged;\n unusedSegments.splice(i, 1);\n extended = true;\n break;\n }\n }\n\n if (current.refs.length > 3 && current.refs[0] === current.refs[current.refs.length - 1]) {\n rings.push(current);\n }\n }\n\n return rings;\n }\n\n private tryMergeRings(a: WayRing, b: WayRing): WayRing | null {\n const aStart = a.refs[0];\n const aEnd = a.refs[a.refs.length - 1];\n const bStart = b.refs[0];\n const bEnd = b.refs[b.refs.length - 1];\n\n if (aEnd === bStart) return this.concatRings(a, b);\n if (aEnd === bEnd) return this.concatRings(a, this.reverseRing(b));\n if (aStart === bEnd) return this.concatRings(b, a);\n if (aStart === bStart) return this.concatRings(this.reverseRing(b), a);\n\n return null;\n }\n\n private concatRings(left: WayRing, right: WayRing): WayRing {\n return {\n refs: [...left.refs, ...right.refs.slice(1)],\n coordinates: [...left.coordinates, ...right.coordinates.slice(1)],\n };\n }\n\n private reverseRing(ring: WayRing): WayRing {\n return {\n refs: [...ring.refs].reverse(),\n coordinates: [...ring.coordinates].reverse(),\n };\n }\n\n private ringContainsPosition(ring: Position[], position: Position): boolean {\n const [x, y] = position;\n let inside = false;\n\n for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n const [xi, yi] = ring[i];\n const [xj, yj] = ring[j];\n const intersects = ((yi > y) !== (yj > y))\n && (x < ((xj - xi) * (y - yi)) / (yj - yi) + xi);\n if (intersects) inside = !inside;\n }\n\n return inside;\n }\n\n private parseTags(rawTags: unknown): Record<string, string> {\n const value = typeof rawTags === 'string' ? JSON.parse(rawTags) as unknown : rawTags;\n if (!value) return {};\n\n if (value instanceof Map) {\n return Object.fromEntries([...value.entries()].map(([k, v]) => [String(k), String(v)]));\n }\n\n if (Array.isArray(value)) {\n const entries = value.flatMap((entry): [string, string][] => {\n if (!entry || typeof entry !== 'object') return [];\n const record = entry as Record<string, unknown>;\n if ('k' in record && 'v' in record) return [[String(record.k), String(record.v)]];\n if ('key' in record && 'value' in record) return [[String(record.key), String(record.value)]];\n return [];\n });\n return Object.fromEntries(entries);\n }\n\n if (typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).map(([k, v]) => [k, String(v)]),\n );\n }\n\n return {};\n }\n\n private toNumberArray(value: unknown): number[] {\n if (!value) return [];\n return Array.from(value as Iterable<unknown>).map((item) => this.toNumber(item));\n }\n\n private toStringArray(value: unknown): string[] {\n if (!value) return [];\n return Array.from(value as Iterable<unknown>).map((item) => String(item));\n }\n\n private toNumber(value: unknown): number {\n return typeof value === 'bigint' ? Number(value) : Number(value);\n }\n}\n","import { DEFAULT_GEO_COLUMN_NAME } from '../../../shared/consts';\n\nexport const LOAD_CSV_ON_TABLE_QUERY = (csvFileUrl: string, tableName: string, delimiter: string, workspace: string) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT * FROM READ_CSV(\n '${csvFileUrl}',\n delim='${delimiter}',\n HEADER=TRUE,\n AUTO_DETECT=TRUE\n );\n\n DESCRIBE ${qualifiedTableName};\n `;\n};\n\ninterface LoadCsvOnTableWithCoordinatesParams {\n csvFileUrl: string;\n tableName: string;\n delimiter: string;\n latColumnName: string;\n longColumnName: string;\n coordinateFormat: string;\n workspace: string;\n}\nexport const LOAD_CSV_ON_TABLE_WITH_COORDINATES_QUERY = ({\n csvFileUrl,\n tableName,\n delimiter,\n latColumnName,\n longColumnName,\n coordinateFormat,\n workspace,\n}: LoadCsvOnTableWithCoordinatesParams) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `\n CREATE TABLE ${qualifiedTableName} AS\n SELECT\n *,\n ST_Transform(\n ST_Point(CAST(${longColumnName} AS DOUBLE), CAST(${latColumnName} AS DOUBLE)),\n 'EPSG:4326',\n '${coordinateFormat}',\n always_xy := true\n ) AS ${DEFAULT_GEO_COLUMN_NAME}\n FROM READ_CSV(\n '${csvFileUrl}',\n delim='${delimiter}',\n HEADER=TRUE,\n AUTO_DETECT=TRUE\n );\n\n DESCRIBE ${qualifiedTableName};\n `;\n};\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { LoadCsvParams } from './interfaces';\nimport { CsvTable } from '../../../shared/interfaces';\nimport { LOAD_CSV_ON_TABLE_QUERY, LOAD_CSV_ON_TABLE_WITH_COORDINATES_QUERY } from './queries';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport { DEFALT_COORDINATE_FORMAT, DEFAULT_GEO_COLUMN_NAME } from '../../../shared/consts';\n\n/**\n * Loads CSV data into DuckDB, with optional geometry column creation.\n */\nexport class LoadCsvUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n }\n\n async exec({ csvFileUrl, csvObject, outputTableName, geometryColumns, delimiter = ',', workspace = 'main' }: LoadCsvParams): Promise<CsvTable> {\n if (!csvFileUrl && !csvObject) {\n throw new Error('Either csvFileUrl or csvObject must be provided');\n }\n if (csvFileUrl && csvObject) {\n throw new Error('Cannot provide both csvFileUrl and csvObject. Please provide only one.');\n }\n\n const csvString = csvFileUrl\n ? await fetch(csvFileUrl).then((r) => {\n if (!r.ok) throw new Error(`HTTP error! Error to load ${csvFileUrl}! Status: ${r.status}`);\n return r.text();\n })\n : this.buildCsvString(csvObject!, delimiter);\n\n const csvPath = `temp_csv_${Date.now()}_${Math.random().toString(36).slice(2, 11)}.csv`;\n await this.db.registerFileText(csvPath, csvString);\n\n const qualifiedTableName = `${workspace}.${outputTableName}`;\n \n let loadCsvQuery: string;\n if (geometryColumns) {\n loadCsvQuery = LOAD_CSV_ON_TABLE_WITH_COORDINATES_QUERY({\n csvFileUrl: csvPath,\n tableName: outputTableName,\n delimiter,\n latColumnName: geometryColumns.latColumnName,\n longColumnName: geometryColumns.longColumnName,\n coordinateFormat: geometryColumns.coordinateFormat || DEFALT_COORDINATE_FORMAT,\n workspace,\n });\n } else {\n loadCsvQuery = LOAD_CSV_ON_TABLE_QUERY(csvPath, outputTableName, delimiter, workspace);\n }\n\n const describeTableResponse = await this.conn.query(loadCsvQuery);\n\n // Automatically create spatial index for geometry column\n if (geometryColumns) {\n const indexName = `idx_${outputTableName}_geometry`;\n await this.conn.query(`CREATE INDEX ${indexName} ON ${qualifiedTableName} USING RTREE (${DEFAULT_GEO_COLUMN_NAME});`);\n }\n\n await this.db.dropFile(csvPath);\n\n return {\n source: 'csv',\n type: 'pointset',\n name: outputTableName,\n columns: getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray()),\n };\n }\n\n private buildCsvString(csvObject: unknown[][], delimiter: string): string {\n return csvObject\n .map((row) =>\n row\n .map((value) => {\n const str = String(value ?? '');\n const escaped = str.replace(/\"/g, '\"\"');\n return `\"${escaped}\"`;\n })\n .join(delimiter),\n )\n .join('\\n');\n }\n}\n","import { DEFAULT_GEO_COLUMN_NAME } from '../../../shared/consts';\n\nexport const LOAD_JSON_ON_TABLE_QUERY = (jsonFileUrl: string, tableName: string, workspace: string) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT * FROM read_json_auto('${jsonFileUrl}');\n\n DESCRIBE ${qualifiedTableName};\n `;\n};\n\ninterface LoadJsonOnTableWithCoordinatesParams {\n jsonFileUrl: string;\n tableName: string;\n latColumnName: string;\n longColumnName: string;\n coordinateFormat: string;\n workspace: string;\n}\nexport const LOAD_JSON_ON_TABLE_WITH_COORDINATES_QUERY = ({\n jsonFileUrl,\n tableName,\n latColumnName,\n longColumnName,\n coordinateFormat,\n workspace,\n}: LoadJsonOnTableWithCoordinatesParams) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `\n CREATE TABLE ${qualifiedTableName} AS\n SELECT\n *,\n ST_Transform(\n ST_Point(CAST(${longColumnName} AS DOUBLE), CAST(${latColumnName} AS DOUBLE)),\n 'EPSG:4326',\n '${coordinateFormat}',\n always_xy := true\n ) AS ${DEFAULT_GEO_COLUMN_NAME}\n FROM read_json_auto('${jsonFileUrl}');\n\n DESCRIBE ${qualifiedTableName};\n `;\n};\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { LoadJsonParams } from './interfaces';\nimport { JsonTable } from '../../../shared/interfaces';\nimport { LOAD_JSON_ON_TABLE_QUERY, LOAD_JSON_ON_TABLE_WITH_COORDINATES_QUERY } from './queries';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport { DEFALT_COORDINATE_FORMAT } from '../../../shared/consts';\n\n/**\n * Loads JSON data into DuckDB, with optional geometry column creation.\n */\nexport class LoadJsonUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n }\n\n async exec({ jsonFileUrl, jsonObject, outputTableName, geometryColumns, workspace = 'main' }: LoadJsonParams): Promise<JsonTable> {\n if (!jsonFileUrl && !jsonObject) {\n throw new Error('Either jsonFileUrl or jsonObject must be provided');\n }\n if (jsonFileUrl && jsonObject) {\n throw new Error('Cannot provide both jsonFileUrl and jsonObject. Please provide only one.');\n }\n\n let jsonPath = jsonFileUrl as string;\n let tempFileCreated = false;\n\n if (jsonObject) {\n const jsonString = JSON.stringify(jsonObject);\n jsonPath = `temp_json_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.json`;\n await this.db.registerFileText(jsonPath, jsonString);\n tempFileCreated = true;\n }\n\n let loadJsonQuery: string;\n if (geometryColumns) {\n loadJsonQuery = LOAD_JSON_ON_TABLE_WITH_COORDINATES_QUERY({\n jsonFileUrl: jsonPath,\n tableName: outputTableName,\n latColumnName: geometryColumns.latColumnName,\n longColumnName: geometryColumns.longColumnName,\n coordinateFormat: geometryColumns.coordinateFormat || DEFALT_COORDINATE_FORMAT,\n workspace,\n });\n } else {\n loadJsonQuery = LOAD_JSON_ON_TABLE_QUERY(jsonPath, outputTableName, workspace);\n }\n\n const describeTableResponse = await this.conn.query(loadJsonQuery);\n\n if (tempFileCreated) {\n await this.db.dropFile(jsonPath);\n }\n\n return {\n source: 'json',\n type: 'pointset',\n name: outputTableName,\n columns: getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray()),\n };\n }\n}\n","import { CustomLayerTable, LayerTable } from '../../../shared/interfaces';\n\nexport const GET_LAYER_AS_GEOJSON_QUERY = (layerTable: LayerTable | CustomLayerTable, workspace: string) => {\n const hasBuildingIdColumn = !!layerTable.columns?.some((c) => c.name === 'building_id');\n const qualifiedTableName = `${workspace}.${layerTable.name}`;\n\n if (layerTable.type === 'buildings' && hasBuildingIdColumn) {\n // Aggregate building parts into one feature per building.\n // Geometry becomes a GeometryCollection of all part polygons (one per part).\n // Properties contain a 'parts' array with per-part OSM properties (heights, tags, etc.)\n // aligned by index with geometry.geometries, plus shared/join properties at the top level.\n return `\n SELECT json_object(\n 'type', 'FeatureCollection',\n 'features', json_group_array(feature)\n ) AS geojson\n FROM (\n SELECT json_object(\n 'type', 'Feature',\n 'geometry', json_object('type', 'GeometryCollection', 'geometries', geom_array),\n 'properties', json_merge_patch(rep_props, json_object('building_id', building_id, 'parts', parts_array))\n ) AS feature\n FROM (\n SELECT\n building_id,\n json_group_array(CAST(ST_AsGeoJSON(geometry) AS JSON)) AS geom_array,\n any_value(COALESCE(CAST(properties AS JSON), '{}'::JSON)) AS rep_props,\n json_group_array(COALESCE(CAST(properties AS JSON), '{}'::JSON)) AS parts_array\n FROM ${qualifiedTableName}\n WHERE ST_IsValid(geometry)\n GROUP BY building_id\n ) agg\n ) sub;\n `;\n }\n\n if (layerTable.type === 'buildings') {\n // Fallback for buildings without building_id — wrap each row in a single-part GeometryCollection.\n // This path should rarely be hit since building_id is auto-assigned on load.\n return `\n SELECT json_object(\n 'type', 'FeatureCollection',\n 'features', json_group_array(feature)\n ) AS geojson\n FROM (\n SELECT json_object(\n 'type', 'Feature',\n 'geometry', json_object('type', 'GeometryCollection', 'geometries', json_array(CAST(ST_AsGeoJSON(geometry) AS JSON))),\n 'properties', properties\n ) AS feature\n FROM ${qualifiedTableName}\n ) sub;\n `;\n }\n\n return `\n SELECT json_object(\n 'type', 'FeatureCollection',\n 'features', json_group_array(feature)\n ) AS geojson\n FROM (\n SELECT json_object(\n 'type', 'Feature',\n 'geometry', CAST(ST_AsGeoJSON(geometry) AS JSON),\n 'properties', properties\n ) AS feature\n FROM ${qualifiedTableName}\n ) sub;\n`;\n};\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { FeatureCollection } from 'geojson';\n\nimport { GET_LAYER_AS_GEOJSON_QUERY } from './queries';\nimport { CustomLayerTable, LayerTable } from '../../../shared/interfaces';\n\n/**\n * Exports a layer table as a GeoJSON FeatureCollection.\n */\nexport class GetLayerGeojsonUseCase {\n private conn: AsyncDuckDBConnection;\n\n constructor(conn: AsyncDuckDBConnection) {\n this.conn = conn;\n }\n\n async exec(table: LayerTable | CustomLayerTable, workspace: string = 'main'): Promise<FeatureCollection> {\n const query = GET_LAYER_AS_GEOJSON_QUERY(table, workspace);\n const response = await this.conn.query(query);\n\n const raw: string = response.toArray()[0]?.geojson ?? '{\"type\":\"FeatureCollection\",\"features\":[]}';\n return JSON.parse(raw.replace(/\\bNaN\\b/g, 'null')) as FeatureCollection;\n }\n}\n","/**\n * @module ColorMapTypes\n * Shared enums and types for color mapping, legend generation, and color-buffer\n * exchange across the toolkit.\n *\n * This module defines the contracts used by the shared color-mapping API in\n * `autk-core` and `@urban-toolkit/autk-map`. It describes how a domain is requested and\n * resolved, which d3-backed interpolators can be selected, and how colors are\n * represented when exchanged as hex strings, RGBA objects, or flat texture\n * buffers.\n */\n\n/**\n * Strategies for deriving a colormap domain.\n *\n * The selected strategy determines whether the domain is supplied directly,\n * computed from numeric min/max values, or computed from numeric percentiles.\n */\nexport enum ColorMapDomainStrategy {\n /** Use the caller-provided domain verbatim. */\n USER = 'user',\n /** Derive the domain from the observed minimum and maximum values. */\n MIN_MAX = 'minMax',\n /** Derive the domain from lower and upper percentiles. */\n PERCENTILE = 'percentile',\n}\n\n/**\n * Domain resolved from input data and a colormap configuration.\n *\n * Numeric domains are returned for continuous interpolators, while string\n * domains are returned for categorical schemes and legend labeling.\n */\nexport type ResolvedDomain = number[] | string[];\n\n/**\n * Specification for how a colormap domain should be derived.\n *\n * `USER` supplies an explicit domain, `MIN_MAX` derives a numeric range from\n * the input values, and `PERCENTILE` derives a numeric range from percentile\n * bounds.\n */\nexport type ColorMapDomainSpec =\n /** Explicit domain supplied by the caller. */\n | { type: ColorMapDomainStrategy.USER; params: number[] | string[] }\n /** Domain inferred from the minimum and maximum numeric values. */\n | { type: ColorMapDomainStrategy.MIN_MAX }\n /** Domain inferred from lower and upper numeric percentiles in the 0-100 range. */\n | { type: ColorMapDomainStrategy.PERCENTILE; params?: [number, number] };\n\n/**\n * Identifiers for the supported color schemes and interpolators.\n *\n * Values map to d3-scale-chromatic categorical, sequential, and diverging\n * schemes used by the shared color-mapping engine.\n */\nexport enum ColorMapInterpolator {\n /** Accent categorical scheme. */\n CAT_ACCENT = 'schemeAccent',\n /** Dark2 categorical scheme. */\n CAT_DARK2 = 'schemeDark2',\n /** Category10 categorical scheme. */\n CAT_CATEGORY10 = 'schemeCategory10',\n /** Observable10 categorical scheme. */\n CAT_OBSERVABLE10 = 'schemeObservable10',\n /** Paired categorical scheme. */\n CAT_PAIRED = 'schemePaired',\n /** Pastel1 categorical scheme. */\n CAT_PASTEL1 = 'schemePastel1',\n /** Pastel2 categorical scheme. */\n CAT_PASTEL2 = 'schemePastel2',\n /** Set1 categorical scheme. */\n CAT_SET1 = 'schemeSet1',\n /** Set2 categorical scheme. */\n CAT_SET2 = 'schemeSet2',\n /** Set3 categorical scheme. */\n CAT_SET3 = 'schemeSet3',\n /** Tableau10 categorical scheme. */\n CAT_TABLEAU10 = 'schemeTableau10',\n /** Reds sequential scheme. */\n SEQ_REDS = 'interpolateReds',\n /** Blues sequential scheme. */\n SEQ_BLUES = 'interpolateBlues',\n /** Greens sequential scheme. */\n SEQ_GREENS = 'interpolateGreens',\n /** Greys sequential scheme. */\n SEQ_GREYS = 'interpolateGreys',\n /** Oranges sequential scheme. */\n SEQ_ORANGES = 'interpolateOranges',\n /** Purples sequential scheme. */\n SEQ_PURPLES = 'interpolatePurples',\n /** Turbo sequential scheme. */\n SEQ_TURBO = 'interpolateTurbo',\n /** Viridis sequential scheme. */\n SEQ_VIRIDIS = 'interpolateViridis',\n /** Inferno sequential scheme. */\n SEQ_INFERNO = 'interpolateInferno',\n /** Magma sequential scheme. */\n SEQ_MAGMA = 'interpolateMagma',\n /** Plasma sequential scheme. */\n SEQ_PLASMA = 'interpolatePlasma',\n /** Cividis sequential scheme. */\n SEQ_CIVIDIS = 'interpolateCividis',\n /** Warm sequential scheme. */\n SEQ_WARM = 'interpolateWarm',\n /** Cool sequential scheme. */\n SEQ_COOL = 'interpolateCool',\n /** Default cubehelix sequential scheme. */\n SEQ_CUBEHELIX_DEFAULT = 'interpolateCubehelixDefault',\n /** Blue-Green sequential scheme. */\n SEQ_BU_GN = 'interpolateBuGn',\n /** Blue-Purple sequential scheme. */\n SEQ_BU_PU = 'interpolateBuPu',\n /** Green-Blue sequential scheme. */\n SEQ_GN_BU = 'interpolateGnBu',\n /** Orange-Red sequential scheme. */\n SEQ_OR_RD = 'interpolateOrRd',\n /** Purple-Blue-Green sequential scheme. */\n SEQ_PU_BU_GN = 'interpolatePuBuGn',\n /** Purple-Blue sequential scheme. */\n SEQ_PU_BU = 'interpolatePuBu',\n /** Purple-Red sequential scheme. */\n SEQ_PU_RD = 'interpolatePuRd',\n /** Red-Purple sequential scheme. */\n SEQ_RD_PU = 'interpolateRdPu',\n /** Yellow-Green-Blue sequential scheme. */\n SEQ_YL_GN_BU = 'interpolateYlGnBu',\n /** Yellow-Green sequential scheme. */\n SEQ_YL_GN = 'interpolateYlGn',\n /** Yellow-Orange-Brown sequential scheme. */\n SEQ_YL_OR_BR = 'interpolateYlOrBr',\n /** Yellow-Orange-Red sequential scheme. */\n SEQ_YL_OR_RD = 'interpolateYlOrRd',\n /** Brown-Blue-Green diverging scheme. */\n DIV_BR_BG = 'interpolateBrBG',\n /** Purple-Green diverging scheme. */\n DIV_PR_GN = 'interpolatePRGn',\n /** Pink-Yellow-Green diverging scheme. */\n DIV_PI_YG = 'interpolatePiYG',\n /** Purple-Orange diverging scheme. */\n DIV_PU_OR = 'interpolatePuOr',\n /** Red-Blue diverging scheme. */\n DIV_RED_BLUE = 'interpolateRdBu',\n /** Red-Grey diverging scheme. */\n DIV_RED_GREY = 'interpolateRdGy',\n /** Red-Yellow-Blue diverging scheme. */\n DIV_RED_YELLOW_BLUE = 'interpolateRdYlBu',\n /** Red-Yellow-Green diverging scheme. */\n DIV_RED_YELLOW_GREEN = 'interpolateRdYlGn',\n /** Spectral diverging scheme. */\n DIV_SPECTRAL = 'interpolateSpectral',\n}\n\n/**\n * Unified color-map configuration used by map rendering and legend generation.\n *\n * This config couples the selected interpolator with the domain strategy so\n * both `autk-core` and `@urban-toolkit/autk-map` resolve and display the same scale.\n */\nexport type ColorMapConfig = {\n /** Selected interpolator or color scheme. */\n interpolator: ColorMapInterpolator;\n /** Strategy used to derive the domain passed to the interpolator. */\n domainSpec: ColorMapDomainSpec;\n};\n\n/**\n * Hexadecimal color string used by styling APIs.\n */\nexport type ColorHEX = `#${string}`;\n\n/**\n * RGBA color representation used by sampling and map styling APIs.\n */\nexport type ColorRGB = {\n /** Red channel value. */\n r: number;\n /** Green channel value. */\n g: number;\n /** Blue channel value. */\n b: number;\n /** Alpha channel value, typically normalized to the 0-1 range. */\n alpha: number;\n};\n\n/**\n * Flat RGBA texture buffer laid out as `[r, g, b, a, ...]`.\n */\nexport type ColorTEX = number[];\n","/**\n * @module ColorMap\n * Color-domain resolution, sampling, and legend-label utilities.\n *\n * This module centralizes the logic for turning raw numeric or categorical\n * inputs into resolved color-map domains, d3-backed interpolators, GPU-ready\n * texture data, and human-readable legend labels. It also exposes helpers for\n * converting between RGB and hex representations.\n */\nimport * as d3_color from 'd3-color';\nimport * as d3_format from 'd3-format';\nimport * as d3_scale from 'd3-scale';\nimport * as d3_scheme from 'd3-scale-chromatic';\n\nimport {\n ColorMapDomainStrategy,\n ColorMapConfig,\n ColorHEX,\n ColorMapInterpolator,\n ResolvedDomain,\n ColorRGB,\n ColorTEX,\n} from './types-colormap';\n\nimport type { TypedArray } from './types-buffer';\n\n/** Two-point numeric domain used by sequential color interpolators. */\ntype SequentialDomain = [number, number];\n/** Three-point numeric domain used by diverging color interpolators. */\ntype DivergingDomain = [number, number, number];\n/** Ordered set of category labels used by categorical color schemes. */\ntype CategoricalDomain = string[];\n\n/** Default number of texels used to sample continuous color maps. */\nexport const DEFAULT_COLORMAP_RESOLUTION = 256;\n\n/** Interpolators backed by discrete categorical color schemes. */\nconst CATEGORICAL_INTERPOLATORS = new Set<ColorMapInterpolator>([\n ColorMapInterpolator.CAT_ACCENT,\n ColorMapInterpolator.CAT_DARK2,\n ColorMapInterpolator.CAT_CATEGORY10,\n ColorMapInterpolator.CAT_OBSERVABLE10,\n ColorMapInterpolator.CAT_PAIRED,\n ColorMapInterpolator.CAT_PASTEL1,\n ColorMapInterpolator.CAT_PASTEL2,\n ColorMapInterpolator.CAT_SET1,\n ColorMapInterpolator.CAT_SET2,\n ColorMapInterpolator.CAT_SET3,\n ColorMapInterpolator.CAT_TABLEAU10,\n]);\n\n/** Interpolators backed by diverging continuous color scales. */\nconst DIVERGING_INTERPOLATORS = new Set<ColorMapInterpolator>([\n ColorMapInterpolator.DIV_BR_BG,\n ColorMapInterpolator.DIV_PR_GN,\n ColorMapInterpolator.DIV_PI_YG,\n ColorMapInterpolator.DIV_PU_OR,\n ColorMapInterpolator.DIV_RED_BLUE,\n ColorMapInterpolator.DIV_RED_GREY,\n ColorMapInterpolator.DIV_RED_YELLOW_BLUE,\n ColorMapInterpolator.DIV_RED_YELLOW_GREEN,\n ColorMapInterpolator.DIV_SPECTRAL,\n]);\n\n/**\n * Color utility for resolving domains, sampling color scales, and building\n * legend and texture representations.\n *\n * `ColorMap` decides whether a scheme should be treated as categorical,\n * sequential, or diverging; derives a compatible domain from data and\n * configuration; and exposes helpers for sampling colors or generating flat\n * RGBA textures for GPU upload.\n */\nexport class ColorMap {\n /**\n * Samples a color interpolator at a normalized value, returning RGBA.\n *\n * @param value - Normalized sample position in `[0, 1]`.\n * @param color - Interpolator identifier to sample.\n * @param domain - Optional explicit domain used to parameterize the scale.\n * @returns Sampled color in RGBA object form.\n * @throws Never throws.\n * @example\n * const c = ColorMap.getColor(0.5, ColorMapInterpolator.SEQ_VIRIDIS);\n * // c → { r: 33, g: 144, b: 141, alpha: 1 }\n */\n public static getColor(value: number, color: ColorMapInterpolator, domain?: SequentialDomain | DivergingDomain | CategoricalDomain): ColorRGB {\n const interpolator = ColorMap.buildInterpolator(color, domain);\n const { r, g, b } = d3_color.rgb(interpolator(value));\n return { r, g, b, alpha: 1 };\n }\n\n /**\n * Builds a flat RGBA texture array for GPU upload from a color scheme.\n *\n * @param color - Interpolator identifier to sample.\n * @param res - Number of texels to generate (default `256`).\n * @param domain - Optional explicit domain used to parameterize the scale.\n * @returns Flat RGBA texture values `[r, g, b, a, ...]`.\n * @throws Never throws. Non-positive `res` returns an empty array.\n * @example\n * const tex = ColorMap.getColorMap(ColorMapInterpolator.SEQ_VIRIDIS, 4);\n * // tex → [68, 1, 84, 1, 59, 82, 139, 1, 33, 144, 141, 1, 253, 231, 37, 1]\n */\n public static getColorMap(\n color: ColorMapInterpolator,\n res: number = DEFAULT_COLORMAP_RESOLUTION,\n domain?: SequentialDomain | DivergingDomain | CategoricalDomain,\n ): ColorTEX {\n if (res <= 0) { return []; }\n if (res === 1) {\n const { r, g, b } = d3_color.rgb(ColorMap.buildInterpolator(color, domain)(0.5));\n return [r, g, b, 1];\n }\n\n const interpolator = ColorMap.buildInterpolator(color, domain);\n const tex: number[] = [];\n for (let id = 0; id < res; id++) {\n const { r, g, b } = d3_color.rgb(interpolator(id / (res - 1)));\n tex.push(r, g, b, 1);\n }\n return tex;\n }\n\n /**\n * Builds an array of sampled RGBA color objects from a color scheme.\n *\n * @param color - Interpolator identifier to sample.\n * @param res - Number of samples to generate (default `256`).\n * @param domain - Optional explicit domain used to parameterize the scale.\n * @returns Array of sampled RGBA color objects.\n * @throws Never throws. Non-positive `res` returns an empty array.\n * @example\n * const colors = ColorMap.getColorArray(ColorMapInterpolator.CAT_SET1, 3);\n * // colors → [{ r: 228, g: 26, b: 28, alpha: 1 }, ...]\n */\n public static getColorArray(\n color: ColorMapInterpolator,\n res: number = DEFAULT_COLORMAP_RESOLUTION,\n domain?: SequentialDomain | DivergingDomain | CategoricalDomain,\n ): ColorRGB[] {\n if (res <= 0) { return []; }\n if (res === 1) {\n const { r, g, b } = d3_color.rgb(ColorMap.buildInterpolator(color, domain)(0.5));\n return [{ r, g, b, alpha: 1 }];\n }\n\n const interpolator = ColorMap.buildInterpolator(color, domain);\n const result: ColorRGB[] = [];\n for (let id = 0; id < res; id++) {\n const { r, g, b } = d3_color.rgb(interpolator(id / (res - 1)));\n result.push({ r, g, b, alpha: 1 });\n }\n return result;\n }\n\n /**\n * Converts an RGBA color object into a hex color string.\n *\n * @param color - RGB color to convert.\n * @returns Hexadecimal color string.\n * @throws Never throws.\n * @example\n * ColorMap.rgbToHex({ r: 255, g: 128, b: 0, alpha: 1 }); // '#ff8000'\n */\n public static rgbToHex(color: ColorRGB): ColorHEX {\n const hex = d3_color.rgb(color.r, color.g, color.b, 1).formatHex();\n return <ColorHEX>hex;\n }\n\n /**\n * Converts a hex color string into an RGBA color object.\n *\n * @param color - Hexadecimal color string to convert.\n * @returns RGBA color object with alpha fixed to `1`.\n * @throws Never throws.\n * @example\n * ColorMap.hexToRgb('#ff8000'); // { r: 255, g: 128, b: 0, alpha: 1 }\n */\n public static hexToRgb(color: ColorHEX): ColorRGB {\n const rgb = d3_color.rgb(color);\n return { r: rgb.r, g: rgb.g, b: rgb.b, alpha: 1.0 };\n }\n\n /**\n * Computes the numeric minimum and maximum of a value array.\n *\n * @param values - Numeric values to inspect.\n * @returns Two-element tuple `[min, max]`, or `[0, 0]` when the input is empty.\n * @throws Never throws. Empty input returns `[0, 0]`.\n * @example\n * ColorMap.computeMinMaxRange([3, 7, 2, 9, 4]); // [2, 9]\n */\n public static computeMinMaxRange(values: number[] | TypedArray): [number, number] {\n if (values.length === 0) return [0, 0];\n let min = Infinity;\n let max = -Infinity;\n for (let i = 0; i < values.length; i++) {\n const v = values[i];\n if (v < min) min = v;\n if (v > max) max = v;\n }\n return [min, max];\n }\n\n /**\n * Returns `true` when an interpolator uses a discrete categorical scheme.\n *\n * @param interpolator - Interpolator identifier to classify.\n * @returns `true` for categorical schemes, otherwise `false`.\n * @throws Never throws.\n * @example\n * ColorMap.isCategorical(ColorMapInterpolator.CAT_SET1); // true\n * ColorMap.isCategorical(ColorMapInterpolator.SEQ_VIRIDIS); // false\n */\n public static isCategorical(interpolator: ColorMapInterpolator): boolean {\n return CATEGORICAL_INTERPOLATORS.has(interpolator);\n }\n \n /**\n * Returns `true` when an interpolator uses a diverging continuous scale.\n *\n * @param interpolator - Interpolator identifier to classify.\n * @returns `true` for diverging interpolators, otherwise `false`.\n * @throws Never throws.\n */\n private static isDiverging(interpolator: ColorMapInterpolator): boolean {\n return DIVERGING_INTERPOLATORS.has(interpolator);\n }\n\n /**\n * Returns the number of colors in a categorical color scheme.\n *\n * @param interpolator - Interpolator identifier to inspect.\n * @returns Scheme size for categorical interpolators, or `null` otherwise.\n * @throws Never throws.\n * @example\n * ColorMap.getCategoricalSchemeSize(ColorMapInterpolator.CAT_SET1); // 9\n * ColorMap.getCategoricalSchemeSize(ColorMapInterpolator.SEQ_VIRIDIS); // null\n */\n public static getCategoricalSchemeSize(interpolator: ColorMapInterpolator): number | null {\n if (!ColorMap.isCategorical(interpolator)) return null;\n return (d3_scheme[interpolator] as string[]).length;\n }\n\n\n /**\n * Resolves a numeric domain from data and color-map configuration.\n *\n * USER domains must contain finite numbers and must match the interpolator\n * shape: sequential schemes require at least two values, while diverging\n * schemes accept either two endpoints or an explicit three-point domain.\n * Percentile resolution ignores non-finite values. When no finite values are\n * available, sequential schemes fall back to `[0, 0]` and diverging schemes\n * fall back to `[0, 0, 0]`.\n *\n * @param values - Numeric input values used to derive the domain.\n * @param config - Color-map configuration controlling the domain strategy.\n * @param interpolator - Interpolator used to decide sequential vs diverging behavior.\n * @returns Resolved sequential or diverging numeric domain.\n */\n private static resolveNumericDomainFromConfig(\n values: number[] | TypedArray,\n config: ColorMapConfig,\n interpolator: ColorMapInterpolator,\n ): SequentialDomain | DivergingDomain {\n const mode = config.domainSpec.type;\n\n if (mode === ColorMapDomainStrategy.USER) {\n const params = config.domainSpec.params;\n if (!params.length || params.some(v => typeof v !== 'number' || !Number.isFinite(v))) {\n throw new Error('ColorMap USER domain for numeric interpolators must be number[].');\n }\n const numeric = params as number[];\n if (ColorMap.isDiverging(interpolator)) {\n if (numeric.length === 3) return [numeric[0], numeric[1], numeric[2]];\n if (numeric.length === 2) {\n const center = (numeric[0] + numeric[1]) / 2;\n return [numeric[0], center, numeric[1]];\n }\n throw new Error('Diverging USER domain must have 2 or 3 numeric values.');\n }\n if (numeric.length < 2) {\n throw new Error('Sequential USER domain must have at least 2 numeric values.');\n }\n return [numeric[0], numeric[numeric.length - 1]];\n }\n\n const finiteValues = (ArrayBuffer.isView(values) ? Array.from(values) : values)\n .filter((value) => Number.isFinite(value));\n\n if (finiteValues.length === 0) {\n return ColorMap.isDiverging(interpolator) ? [0, 0, 0] : [0, 0];\n }\n\n if (mode === ColorMapDomainStrategy.PERCENTILE) {\n const [lowerPercentile, upperPercentile] = config.domainSpec.params ?? [2, 98];\n const low = ColorMap.computePercentile(finiteValues, lowerPercentile / 100);\n const high = ColorMap.computePercentile(finiteValues, upperPercentile / 100);\n if (ColorMap.isDiverging(interpolator)) {\n const center = ColorMap.computePercentile(finiteValues, 50 / 100);\n return [low, center, high];\n }\n return [low, high];\n }\n\n const [min, max] = ColorMap.computeMinMaxRange(finiteValues);\n if (ColorMap.isDiverging(interpolator)) {\n const center = (min + max) / 2;\n return [min, center, max];\n }\n return [min, max];\n }\n\n /**\n * Resolves a categorical domain from a color-map configuration.\n *\n * USER domains are used verbatim after string conversion. Data-derived\n * domains preserve first-seen order and remove duplicates.\n *\n * @param values - Input category values.\n * @param config - Color-map configuration controlling the domain strategy.\n * @returns Ordered categorical domain labels.\n */\n private static resolveCategoricalDomainFromConfig(\n values: string[],\n config: ColorMapConfig,\n ): CategoricalDomain {\n if (config.domainSpec.type === ColorMapDomainStrategy.USER) {\n return config.domainSpec.params.map(v => String(v));\n }\n return Array.from(new Set(values.map(v => String(v))));\n }\n\n /**\n * Derives human-readable legend labels from a domain.\n *\n * Categorical domains are returned as-is. Numeric domains are formatted\n * with a magnitude-aware d3 formatter so legend labels remain compact for\n * large values and readable for small decimals.\n *\n * @param domain Any supported color-scale domain.\n * @returns Ordered label strings suitable for a legend.\n * @throws Never throws.\n * @example\n * ColorMap.computeLabels([0, 500000, 1000000]); // ['0', '500,000', '1M']\n * ColorMap.computeLabels(['low', 'mid', 'high']); // ['low', 'mid', 'high']\n */\n public static computeLabels(\n domain: ResolvedDomain,\n ): string[] {\n if (typeof domain[0] === 'string') return domain as string[];\n\n const numeric = domain as number[];\n const maxAbs = numeric.reduce((acc, v) => Math.max(acc, Math.abs(v)), 0);\n const formatter = maxAbs >= 1_000_000\n ? d3_format.format('.3s')\n : maxAbs >= 1\n ? d3_format.format(',.2f')\n : d3_format.format('.3~g');\n\n return numeric.map(v => formatter(v));\n }\n\n /**\n * Resolves a color domain from data and configuration.\n *\n * The method infers categorical handling when the selected interpolator is\n * categorical, when a USER domain contains string values, or when the input\n * array contains non-numeric strings. Numeric-looking strings in normal\n * arrays are still treated as numeric values. Unsupported domain shapes are\n * not coerced beyond this inference.\n *\n * @param values - Source values used to derive the domain.\n * @param config - Color-map configuration controlling the resolution mode.\n * @returns Resolved categorical or numeric domain.\n * @throws {Error} When USER domain has invalid shape for the selected\n * interpolator (e.g. non-numeric values for a sequential interpolator).\n * @example\n * const domain = ColorMap.resolveDomainFromData(\n * [10, 50, 30, 80, 20],\n * { interpolator: ColorMapInterpolator.SEQ_VIRIDIS, domainSpec: { type: ColorMapDomainStrategy.MIN_MAX } }\n * );\n * // domain → [10, 80]\n */\n public static resolveDomainFromData(\n values: number[] | string[] | TypedArray,\n config: ColorMapConfig,\n ): ResolvedDomain {\n const isCategorical = ColorMap.isCategorical(config.interpolator)\n || (config.domainSpec.type === ColorMapDomainStrategy.USER && config.domainSpec.params.some(v => typeof v === 'string'))\n || (!ArrayBuffer.isView(values) && (values as Array<number|string>).some(v => typeof v === 'string' && isNaN(Number(v))));\n\n if (isCategorical) {\n return ColorMap.resolveCategoricalDomainFromConfig(values as string[], config);\n } else {\n return ColorMap.resolveNumericDomainFromConfig(values as number[] | TypedArray, config, config.interpolator);\n }\n }\n\n /**\n * Builds a d3-compatible interpolator function for the requested color scheme.\n *\n * Categorical schemes map values by index into the underlying d3 scheme.\n * When no domain is provided, the full categorical scheme length is used.\n * Diverging scales default to `[0, 0.5, 1]` and sequential scales default to\n * `[0, 1]`.\n *\n * @param color - Interpolator identifier to build.\n * @param domain - Optional explicit domain used to parameterize the scale.\n * @returns Function that maps normalized scalar values to CSS color strings.\n */\n private static buildInterpolator(\n color: ColorMapInterpolator,\n domain?: SequentialDomain | DivergingDomain | CategoricalDomain,\n ): (t: number) => string {\n if (ColorMap.isCategorical(color)) {\n const scheme = d3_scheme[color] as string[];\n const n = domain?.length ?? scheme.length;\n return (t: number) => {\n const idx = Math.min(Math.round(t * (n - 1)), scheme.length - 1);\n return scheme[idx];\n };\n }\n\n if (ColorMap.isDiverging(color)) {\n return d3_scale.scaleDiverging(d3_scheme[color] as (t: number) => string)\n .domain((domain as DivergingDomain) ?? [0, 0.5, 1]);\n }\n\n return d3_scale.scaleSequential(d3_scheme[color] as (t: number) => string)\n .domain((domain as SequentialDomain) ?? [0, 1]);\n }\n\n /**\n * Computes a percentile value from a numeric array.\n *\n * @param values - Numeric values to sample.\n * @param p - Percentile in normalized `[0, 1]` form.\n * @returns Interpolated percentile value, or `0` for empty input.\n */\n private static computePercentile(values: number[] | TypedArray, p: number): number {\n if (values.length === 0) return 0;\n const sorted = (ArrayBuffer.isView(values) ? new Float32Array(values) : [...values]).sort((a, b) => a - b);\n const idx = p * (sorted.length - 1);\n const lo = Math.floor(idx);\n const hi = Math.ceil(idx);\n return sorted[lo] + (sorted[hi] - sorted[lo]) * (idx - lo);\n }\n}\n","/**\n * @module GeometryUtils\n * Planar geometry helpers for triangulation and ring analysis.\n *\n * This module groups small 2D primitives used to offset local-space\n * polylines, normalize polygon rings, measure ring properties, test\n * convexity, and derive convex hulls. The helpers assume coordinates are\n * already expressed in a local planar system.\n */\n\n/**\n * Builds a closed polygon buffer around a polyline for stroke rendering.\n *\n * Input coordinates are expected to already be in a local planar system.\n * Consecutive duplicate points are skipped before the offset is computed.\n * The returned polygon includes a repeated closing vertex and is suitable for\n * triangulation with earcut.\n *\n * @param points - Ordered local-space polyline coordinates.\n * @param distance - Offset distance applied on both sides of the polyline.\n * @returns A closed polygon describing the buffered polyline footprint in\n * local planar coordinates. Returns an empty array when the input contains\n * fewer than two distinct points or when `distance` is `0`.\n * @throws Never throws. Degenerate inputs return an empty array rather than\n * raising an error.\n * @example\n * const poly = offsetPolyline([[0, 0], [10, 0], [10, 10]], 2);\n * // poly is a closed ring e.g. [[-0, 2], [10, -2], [12, 10], …]\n */\nexport function offsetPolyline(points: number[][], distance: number): [number, number][] {\n const clean = points.filter((point, index) => {\n if (index === 0) return true;\n const prev = points[index - 1];\n return point[0] !== prev[0] || point[1] !== prev[1];\n }) as [number, number][];\n\n if (clean.length < 2 || distance === 0) {\n return [];\n }\n\n const left: [number, number][] = [];\n const right: [number, number][] = [];\n\n for (let i = 0; i < clean.length; i++) {\n const prev = i > 0 ? clean[i - 1] : null;\n const curr = clean[i];\n const next = i < clean.length - 1 ? clean[i + 1] : null;\n\n const prevNormal = prev ? getUnitLeftNormal(prev, curr) : null;\n const nextNormal = next ? getUnitLeftNormal(curr, next) : null;\n\n const leftPoint = computeOffsetPoint(prev, curr, next, prevNormal, nextNormal, distance, 1);\n const rightPoint = computeOffsetPoint(prev, curr, next, prevNormal, nextNormal, distance, -1);\n\n left.push(leftPoint);\n right.push(rightPoint);\n }\n\n const polygon = [...left, ...right.reverse()];\n if (polygon.length > 0) {\n polygon.push([polygon[0][0], polygon[0][1]]);\n }\n\n return polygon;\n}\n\n/**\n * Returns a shallow copy of a ring without a duplicated closing vertex.\n *\n * Only the final vertex is removed, and only when it matches the first vertex\n * exactly. Rings that are already open are copied unchanged.\n *\n * @param ring - Polygon ring to normalize.\n * @returns A shallow copy of the ring without a repeated closing point.\n * @throws Never throws. Always returns a shallow copy, even for degenerate inputs.\n * @example\n * const open = normalizeRing([[0, 0], [10, 0], [10, 10], [0, 0]]);\n * // open → [[0, 0], [10, 0], [10, 10]]\n */\nexport function normalizeRing(ring: number[][]): number[][] {\n if (ring.length < 2) return [...ring];\n const normalized = [...ring];\n const first = normalized[0];\n const last = normalized[normalized.length - 1];\n if (first[0] === last[0] && first[1] === last[1]) {\n normalized.pop();\n }\n return normalized;\n}\n\n/**\n * Computes the convex hull of a 2D point set using the monotonic chain algorithm.\n *\n * Duplicate points are removed before hull computation. Collinear interior\n * points are discarded from the outer boundary. Degenerate inputs with\n * three or fewer unique points are returned as shallow copies.\n *\n * @param points - Input points to reduce to a convex hull.\n * @returns Hull points ordered around the outer boundary in CCW order.\n * @throws Never throws. Degenerate inputs are returned verbatim (limited copies).\n * @example\n * const hull = computePointConvexHull([[0, 0], [10, 0], [10, 10], [5, 5], [0, 10]]);\n * // hull → [[0, 0], [10, 0], [10, 10], [0, 10]] (interior point [5,5] discarded)\n */\nexport function computePointConvexHull(points: number[][]): number[][] {\n const unique = Array.from(new Map(\n normalizeRing(points).map((point) => [`${point[0]},${point[1]}`, point as [number, number]])\n ).values());\n\n if (unique.length <= 3) {\n return unique.map(([x, y]) => [x, y]);\n }\n\n unique.sort((a, b) => (a[0] - b[0]) || (a[1] - b[1]));\n\n const lower: Array<[number, number]> = [];\n for (const point of unique) {\n while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], point) <= 0) {\n lower.pop();\n }\n lower.push(point);\n }\n\n const upper: Array<[number, number]> = [];\n for (let i = unique.length - 1; i >= 0; i--) {\n const point = unique[i];\n while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], point) <= 0) {\n upper.pop();\n }\n upper.push(point);\n }\n\n lower.pop();\n upper.pop();\n return [...lower, ...upper].map(([x, y]) => [x, y]);\n}\n\n/**\n * Computes the signed planar area of a polygon ring.\n *\n * Positive area indicates counterclockwise winding; negative area indicates\n * clockwise winding. The ring is automatically closed between the last and\n * first vertex.\n *\n * @param ring - Ring vertices in order around the polygon.\n * @returns Signed area of the ring. Counterclockwise rings produce positive\n * area and clockwise rings produce negative area.\n * @throws Never throws. Degenerate rings return `0`.\n * @example\n * const area = computeRingArea([[0, 0], [10, 0], [10, 10]]);\n * // area → 50 (CCW triangle)\n */\nexport function computeRingArea(ring: number[][]): number {\n let area = 0;\n for (let i = 0; i < ring.length; i++) {\n const [x1, y1] = ring[i];\n const [x2, y2] = ring[(i + 1) % ring.length];\n area += x1 * y2 - x2 * y1;\n }\n return area * 0.5;\n}\n\n/**\n * Computes the total perimeter length of a polygon ring.\n *\n * The ring is traversed in order and closed automatically between the last\n * and first vertex.\n *\n * @param ring - Ring vertices in order around the polygon.\n * @returns Sum of Euclidean edge lengths around the ring.\n * @throws Never throws. Returns `0` for rings with fewer than 2 vertices.\n * @example\n * const len = polygonPerimeter([[0, 0], [10, 0], [10, 10]]);\n * // len → 10 + 10 + 14.14…\n */\nexport function polygonPerimeter(ring: number[][]): number {\n let perimeter = 0;\n const n = ring.length;\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const dx = ring[i][0] - ring[j][0];\n const dy = ring[i][1] - ring[j][1];\n perimeter += Math.sqrt(dx * dx + dy * dy);\n }\n return perimeter;\n}\n\n/**\n * Returns true when a polygon ring is convex.\n *\n * Assumes the ring is already open, with no duplicated closing vertex.\n * Collinear vertices are ignored when testing turn direction consistency.\n *\n * @param ring - Open polygon ring to test.\n * @returns `true` when all non-zero cross products share the same sign,\n * otherwise `false`.\n * @throws Never throws. Rings with fewer than 3 vertices return `true`.\n * @example\n * isConvex([[0, 0], [10, 0], [10, 10], [0, 10]]); // true\n * isConvex([[0, 0], [10, 0], [5, 5], [10, 10], [0, 10]]); // false (concave)\n */\nexport function isConvex(ring: number[][]): boolean {\n const n = ring.length;\n let sign = 0;\n for (let i = 0; i < n; i++) {\n const prev = (i + n - 1) % n;\n const next = (i + 1) % n;\n const e1x = ring[i][0] - ring[prev][0];\n const e1y = ring[i][1] - ring[prev][1];\n const e2x = ring[next][0] - ring[i][0];\n const e2y = ring[next][1] - ring[i][1];\n const turn = e1x * e2y - e1y * e2x;\n if (Math.abs(turn) < 1e-10) continue;\n const currentSign = turn > 0 ? 1 : -1;\n if (sign === 0) sign = currentSign;\n else if (currentSign !== sign) return false;\n }\n return true;\n}\n\n/**\n * Computes the unit left-hand normal for a directed segment.\n *\n * The left-hand normal is the vector perpendicular to the segment direction\n * rotated 90° counterclockwise, used by `offsetPolyline` to push vertices\n * outward.\n *\n * @param a - Start point of the segment.\n * @param b - End point of the segment.\n * @returns A normalized left-hand perpendicular vector, or `null` when the\n * segment has zero length.\n */\nfunction getUnitLeftNormal(a: [number, number], b: [number, number]): [number, number] | null {\n const dx = b[0] - a[0];\n const dy = b[1] - a[1];\n const length = Math.hypot(dx, dy);\n\n if (length === 0) {\n return null;\n }\n\n return [-dy / length, dx / length];\n}\n\n/**\n * Computes the offset vertex for one side of a polyline at a given vertex.\n *\n * Endpoints fall back to a single segment normal. Interior vertices are formed\n * by intersecting the adjacent offset segments when possible; when segments\n * are parallel or nearly so, the averaged normal direction is used instead.\n *\n * @param prev - Previous polyline point, or `null` when `curr` is the first point.\n * @param curr - Current polyline point being offset.\n * @param next - Next polyline point, or `null` when `curr` is the last point.\n * @param prevNormal - Unit left normal of the incoming segment, if available.\n * @param nextNormal - Unit left normal of the outgoing segment, if available.\n * @param distance - Offset distance applied away from the source polyline.\n * @param side - Offset side multiplier: `1` for the left outline, `-1` for the right outline.\n * @returns The offset point for the requested side at `curr`. Falls back to\n * `curr` itself when both normals are unavailable.\n */\nfunction computeOffsetPoint(\n prev: [number, number] | null,\n curr: [number, number],\n next: [number, number] | null,\n prevNormal: [number, number] | null,\n nextNormal: [number, number] | null,\n distance: number,\n side: 1 | -1,\n): [number, number] {\n if (!prevNormal && !nextNormal) {\n return curr;\n }\n\n if (!prev || !prevNormal) {\n return [\n curr[0] + nextNormal![0] * distance * side,\n curr[1] + nextNormal![1] * distance * side,\n ];\n }\n\n if (!next || !nextNormal) {\n return [\n curr[0] + prevNormal[0] * distance * side,\n curr[1] + prevNormal[1] * distance * side,\n ];\n }\n\n const prevOffsetA: [number, number] = [\n prev[0] + prevNormal[0] * distance * side,\n prev[1] + prevNormal[1] * distance * side,\n ];\n const prevOffsetB: [number, number] = [\n curr[0] + prevNormal[0] * distance * side,\n curr[1] + prevNormal[1] * distance * side,\n ];\n const nextOffsetA: [number, number] = [\n curr[0] + nextNormal[0] * distance * side,\n curr[1] + nextNormal[1] * distance * side,\n ];\n const nextOffsetB: [number, number] = [\n next[0] + nextNormal[0] * distance * side,\n next[1] + nextNormal[1] * distance * side,\n ];\n\n const intersection = intersectLines(prevOffsetA, prevOffsetB, nextOffsetA, nextOffsetB);\n if (intersection) {\n return intersection;\n }\n\n const avgX = prevNormal[0] + nextNormal[0];\n const avgY = prevNormal[1] + nextNormal[1];\n const avgLength = Math.hypot(avgX, avgY);\n\n if (avgLength === 0) {\n return [\n curr[0] + nextNormal[0] * distance * side,\n curr[1] + nextNormal[1] * distance * side,\n ];\n }\n\n return [\n curr[0] + (avgX / avgLength) * distance * side,\n curr[1] + (avgY / avgLength) * distance * side,\n ];\n}\n\n/**\n * Computes the intersection point of two infinite 2D lines.\n *\n * The lines are defined by the point pairs `a1`-`a2` and `b1`-`b2`.\n * Parallel or nearly parallel lines (determinant < 1e-9) return `null`.\n * Used by `computeOffsetPoint` to resolve mitered corners.\n *\n * @param a1 - First point on the first line.\n * @param a2 - Second point on the first line.\n * @param b1 - First point on the second line.\n * @param b2 - Second point on the second line.\n * @returns The line intersection point, or `null` when the lines are parallel\n * or nearly so.\n */\nfunction intersectLines(\n a1: [number, number],\n a2: [number, number],\n b1: [number, number],\n b2: [number, number],\n): [number, number] | null {\n const x1 = a1[0];\n const y1 = a1[1];\n const x2 = a2[0];\n const y2 = a2[1];\n const x3 = b1[0];\n const y3 = b1[1];\n const x4 = b2[0];\n const y4 = b2[1];\n\n const denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);\n if (Math.abs(denom) < 1e-9) {\n return null;\n }\n\n const detA = x1 * y2 - y1 * x2;\n const detB = x3 * y4 - y3 * x4;\n\n return [\n (detA * (x3 - x4) - (x1 - x2) * detB) / denom,\n (detA * (y3 - y4) - (y1 - y2) * detB) / denom,\n ];\n}\n\n/**\n * Computes the signed cross product of the turn from `a` → `b` → `c`.\n *\n * Used by `computePointConvexHull` to test point-to-line orientation during\n * monotonic chain construction.\n *\n * @param a - First point.\n * @param b - Second point.\n * @param c - Third point.\n * @returns Positive for counterclockwise turns, negative for clockwise\n * turns, and `0` for collinear points.\n */\nfunction cross(a: [number, number], b: [number, number], c: [number, number]): number {\n return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);\n}\n","\nexport default function earcut(data, holeIndices, dim = 2) {\n\n const hasHoles = holeIndices && holeIndices.length;\n const outerLen = hasHoles ? holeIndices[0] * dim : data.length;\n let outerNode = linkedList(data, 0, outerLen, dim, true);\n const triangles = [];\n\n if (!outerNode || outerNode.next === outerNode.prev) return triangles;\n\n let minX, minY, invSize;\n\n if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);\n\n // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox\n if (data.length > 80 * dim) {\n minX = data[0];\n minY = data[1];\n let maxX = minX;\n let maxY = minY;\n\n for (let i = dim; i < outerLen; i += dim) {\n const x = data[i];\n const y = data[i + 1];\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n }\n\n // minX, minY and invSize are later used to transform coords into integers for z-order calculation\n invSize = Math.max(maxX - minX, maxY - minY);\n invSize = invSize !== 0 ? 32767 / invSize : 0;\n }\n\n earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);\n\n return triangles;\n}\n\n// create a circular doubly linked list from polygon points in the specified winding order\nfunction linkedList(data, start, end, dim, clockwise) {\n let last;\n\n if (clockwise === (signedArea(data, start, end, dim) > 0)) {\n for (let i = start; i < end; i += dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);\n } else {\n for (let i = end - dim; i >= start; i -= dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);\n }\n\n if (last && equals(last, last.next)) {\n removeNode(last);\n last = last.next;\n }\n\n return last;\n}\n\n// eliminate colinear or duplicate points\nfunction filterPoints(start, end) {\n if (!start) return start;\n if (!end) end = start;\n\n let p = start,\n again;\n do {\n again = false;\n\n if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {\n removeNode(p);\n p = end = p.prev;\n if (p === p.next) break;\n again = true;\n\n } else {\n p = p.next;\n }\n } while (again || p !== end);\n\n return end;\n}\n\n// main ear slicing loop which triangulates a polygon (given as a linked list)\nfunction earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {\n if (!ear) return;\n\n // interlink polygon nodes in z-order\n if (!pass && invSize) indexCurve(ear, minX, minY, invSize);\n\n let stop = ear;\n\n // iterate through ears, slicing them one by one\n while (ear.prev !== ear.next) {\n const prev = ear.prev;\n const next = ear.next;\n\n if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {\n triangles.push(prev.i, ear.i, next.i); // cut off the triangle\n\n removeNode(ear);\n\n // skipping the next vertex leads to less sliver triangles\n ear = next.next;\n stop = next.next;\n\n continue;\n }\n\n ear = next;\n\n // if we looped through the whole remaining polygon and can't find any more ears\n if (ear === stop) {\n // try filtering points and slicing again\n if (!pass) {\n earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);\n\n // if this didn't work, try curing all small self-intersections locally\n } else if (pass === 1) {\n ear = cureLocalIntersections(filterPoints(ear), triangles);\n earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);\n\n // as a last resort, try splitting the remaining polygon into two\n } else if (pass === 2) {\n splitEarcut(ear, triangles, dim, minX, minY, invSize);\n }\n\n break;\n }\n }\n}\n\n// check whether a polygon node forms a valid ear with adjacent nodes\nfunction isEar(ear) {\n const a = ear.prev,\n b = ear,\n c = ear.next;\n\n if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\n\n // now make sure we don't have other points inside the potential ear\n const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;\n\n // triangle bbox\n const x0 = Math.min(ax, bx, cx),\n y0 = Math.min(ay, by, cy),\n x1 = Math.max(ax, bx, cx),\n y1 = Math.max(ay, by, cy);\n\n let p = c.next;\n while (p !== a) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&\n pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) &&\n area(p.prev, p, p.next) >= 0) return false;\n p = p.next;\n }\n\n return true;\n}\n\nfunction isEarHashed(ear, minX, minY, invSize) {\n const a = ear.prev,\n b = ear,\n c = ear.next;\n\n if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\n\n const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;\n\n // triangle bbox\n const x0 = Math.min(ax, bx, cx),\n y0 = Math.min(ay, by, cy),\n x1 = Math.max(ax, bx, cx),\n y1 = Math.max(ay, by, cy);\n\n // z-order range for the current triangle bbox;\n const minZ = zOrder(x0, y0, minX, minY, invSize),\n maxZ = zOrder(x1, y1, minX, minY, invSize);\n\n let p = ear.prevZ,\n n = ear.nextZ;\n\n // look for points inside the triangle in both directions\n while (p && p.z >= minZ && n && n.z <= maxZ) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&\n pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.prevZ;\n\n if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&\n pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;\n n = n.nextZ;\n }\n\n // look for remaining points in decreasing z-order\n while (p && p.z >= minZ) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&\n pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.prevZ;\n }\n\n // look for remaining points in increasing z-order\n while (n && n.z <= maxZ) {\n if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&\n pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;\n n = n.nextZ;\n }\n\n return true;\n}\n\n// go through all polygon nodes and cure small local self-intersections\nfunction cureLocalIntersections(start, triangles) {\n let p = start;\n do {\n const a = p.prev,\n b = p.next.next;\n\n if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {\n\n triangles.push(a.i, p.i, b.i);\n\n // remove two nodes involved\n removeNode(p);\n removeNode(p.next);\n\n p = start = b;\n }\n p = p.next;\n } while (p !== start);\n\n return filterPoints(p);\n}\n\n// try splitting polygon into two and triangulate them independently\nfunction splitEarcut(start, triangles, dim, minX, minY, invSize) {\n // look for a valid diagonal that divides the polygon into two\n let a = start;\n do {\n let b = a.next.next;\n while (b !== a.prev) {\n if (a.i !== b.i && isValidDiagonal(a, b)) {\n // split the polygon in two by the diagonal\n let c = splitPolygon(a, b);\n\n // filter colinear points around the cuts\n a = filterPoints(a, a.next);\n c = filterPoints(c, c.next);\n\n // run earcut on each half\n earcutLinked(a, triangles, dim, minX, minY, invSize, 0);\n earcutLinked(c, triangles, dim, minX, minY, invSize, 0);\n return;\n }\n b = b.next;\n }\n a = a.next;\n } while (a !== start);\n}\n\n// link every hole into the outer loop, producing a single-ring polygon without holes\nfunction eliminateHoles(data, holeIndices, outerNode, dim) {\n const queue = [];\n\n for (let i = 0, len = holeIndices.length; i < len; i++) {\n const start = holeIndices[i] * dim;\n const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n const list = linkedList(data, start, end, dim, false);\n if (list === list.next) list.steiner = true;\n queue.push(getLeftmost(list));\n }\n\n queue.sort(compareXYSlope);\n\n // process holes from left to right\n for (let i = 0; i < queue.length; i++) {\n outerNode = eliminateHole(queue[i], outerNode);\n }\n\n return outerNode;\n}\n\nfunction compareXYSlope(a, b) {\n let result = a.x - b.x;\n // when the left-most point of 2 holes meet at a vertex, sort the holes counterclockwise so that when we find\n // the bridge to the outer shell is always the point that they meet at.\n if (result === 0) {\n result = a.y - b.y;\n if (result === 0) {\n const aSlope = (a.next.y - a.y) / (a.next.x - a.x);\n const bSlope = (b.next.y - b.y) / (b.next.x - b.x);\n result = aSlope - bSlope;\n }\n }\n return result;\n}\n\n// find a bridge between vertices that connects hole with an outer ring and link it\nfunction eliminateHole(hole, outerNode) {\n const bridge = findHoleBridge(hole, outerNode);\n if (!bridge) {\n return outerNode;\n }\n\n const bridgeReverse = splitPolygon(bridge, hole);\n\n // filter collinear points around the cuts\n filterPoints(bridgeReverse, bridgeReverse.next);\n return filterPoints(bridge, bridge.next);\n}\n\n// David Eberly's algorithm for finding a bridge between hole and outer polygon\nfunction findHoleBridge(hole, outerNode) {\n let p = outerNode;\n const hx = hole.x;\n const hy = hole.y;\n let qx = -Infinity;\n let m;\n\n // find a segment intersected by a ray from the hole's leftmost point to the left;\n // segment's endpoint with lesser x will be potential connection point\n // unless they intersect at a vertex, then choose the vertex\n if (equals(hole, p)) return p;\n do {\n if (equals(hole, p.next)) return p.next;\n else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {\n const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);\n if (x <= hx && x > qx) {\n qx = x;\n m = p.x < p.next.x ? p : p.next;\n if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint\n }\n }\n p = p.next;\n } while (p !== outerNode);\n\n if (!m) return null;\n\n // look for points inside the triangle of hole point, segment intersection and endpoint;\n // if there are no points found, we have a valid connection;\n // otherwise choose the point of the minimum angle with the ray as connection point\n\n const stop = m;\n const mx = m.x;\n const my = m.y;\n let tanMin = Infinity;\n\n p = m;\n\n do {\n if (hx >= p.x && p.x >= mx && hx !== p.x &&\n pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {\n\n const tan = Math.abs(hy - p.y) / (hx - p.x); // tangential\n\n if (locallyInside(p, hole) &&\n (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {\n m = p;\n tanMin = tan;\n }\n }\n\n p = p.next;\n } while (p !== stop);\n\n return m;\n}\n\n// whether sector in vertex m contains sector in vertex p in the same coordinates\nfunction sectorContainsSector(m, p) {\n return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;\n}\n\n// interlink polygon nodes in z-order\nfunction indexCurve(start, minX, minY, invSize) {\n let p = start;\n do {\n if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);\n p.prevZ = p.prev;\n p.nextZ = p.next;\n p = p.next;\n } while (p !== start);\n\n p.prevZ.nextZ = null;\n p.prevZ = null;\n\n sortLinked(p);\n}\n\n// Simon Tatham's linked list merge sort algorithm\n// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html\nfunction sortLinked(list) {\n let numMerges;\n let inSize = 1;\n\n do {\n let p = list;\n let e;\n list = null;\n let tail = null;\n numMerges = 0;\n\n while (p) {\n numMerges++;\n let q = p;\n let pSize = 0;\n for (let i = 0; i < inSize; i++) {\n pSize++;\n q = q.nextZ;\n if (!q) break;\n }\n let qSize = inSize;\n\n while (pSize > 0 || (qSize > 0 && q)) {\n\n if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {\n e = p;\n p = p.nextZ;\n pSize--;\n } else {\n e = q;\n q = q.nextZ;\n qSize--;\n }\n\n if (tail) tail.nextZ = e;\n else list = e;\n\n e.prevZ = tail;\n tail = e;\n }\n\n p = q;\n }\n\n tail.nextZ = null;\n inSize *= 2;\n\n } while (numMerges > 1);\n\n return list;\n}\n\n// z-order of a point given coords and inverse of the longer side of data bbox\nfunction zOrder(x, y, minX, minY, invSize) {\n // coords are transformed into non-negative 15-bit integer range\n x = (x - minX) * invSize | 0;\n y = (y - minY) * invSize | 0;\n\n x = (x | (x << 8)) & 0x00FF00FF;\n x = (x | (x << 4)) & 0x0F0F0F0F;\n x = (x | (x << 2)) & 0x33333333;\n x = (x | (x << 1)) & 0x55555555;\n\n y = (y | (y << 8)) & 0x00FF00FF;\n y = (y | (y << 4)) & 0x0F0F0F0F;\n y = (y | (y << 2)) & 0x33333333;\n y = (y | (y << 1)) & 0x55555555;\n\n return x | (y << 1);\n}\n\n// find the leftmost node of a polygon ring\nfunction getLeftmost(start) {\n let p = start,\n leftmost = start;\n do {\n if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;\n p = p.next;\n } while (p !== start);\n\n return leftmost;\n}\n\n// check if a point lies within a convex triangle\nfunction pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {\n return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&\n (ax - px) * (by - py) >= (bx - px) * (ay - py) &&\n (bx - px) * (cy - py) >= (cx - px) * (by - py);\n}\n\n// check if a point lies within a convex triangle but false if its equal to the first point of the triangle\nfunction pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, px, py) {\n return !(ax === px && ay === py) && pointInTriangle(ax, ay, bx, by, cx, cy, px, py);\n}\n\n// check if a diagonal between two polygon nodes is valid (lies in polygon interior)\nfunction isValidDiagonal(a, b) {\n return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // doesn't intersect other edges\n (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible\n (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors\n equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case\n}\n\n// signed area of a triangle\nfunction area(p, q, r) {\n return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);\n}\n\n// check if two points are equal\nfunction equals(p1, p2) {\n return p1.x === p2.x && p1.y === p2.y;\n}\n\n// check if two segments intersect\nfunction intersects(p1, q1, p2, q2) {\n const o1 = sign(area(p1, q1, p2));\n const o2 = sign(area(p1, q1, q2));\n const o3 = sign(area(p2, q2, p1));\n const o4 = sign(area(p2, q2, q1));\n\n if (o1 !== o2 && o3 !== o4) return true; // general case\n\n if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1\n if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1\n if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2\n if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2\n\n return false;\n}\n\n// for collinear points p, q, r, check if point q lies on segment pr\nfunction onSegment(p, q, r) {\n return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);\n}\n\nfunction sign(num) {\n return num > 0 ? 1 : num < 0 ? -1 : 0;\n}\n\n// check if a polygon diagonal intersects any polygon segments\nfunction intersectsPolygon(a, b) {\n let p = a;\n do {\n if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&\n intersects(p, p.next, a, b)) return true;\n p = p.next;\n } while (p !== a);\n\n return false;\n}\n\n// check if a polygon diagonal is locally inside the polygon\nfunction locallyInside(a, b) {\n return area(a.prev, a, a.next) < 0 ?\n area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :\n area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;\n}\n\n// check if the middle point of a polygon diagonal is inside the polygon\nfunction middleInside(a, b) {\n let p = a;\n let inside = false;\n const px = (a.x + b.x) / 2;\n const py = (a.y + b.y) / 2;\n do {\n if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&\n (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))\n inside = !inside;\n p = p.next;\n } while (p !== a);\n\n return inside;\n}\n\n// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;\n// if one belongs to the outer ring and another to a hole, it merges it into a single ring\nfunction splitPolygon(a, b) {\n const a2 = createNode(a.i, a.x, a.y),\n b2 = createNode(b.i, b.x, b.y),\n an = a.next,\n bp = b.prev;\n\n a.next = b;\n b.prev = a;\n\n a2.next = an;\n an.prev = a2;\n\n b2.next = a2;\n a2.prev = b2;\n\n bp.next = b2;\n b2.prev = bp;\n\n return b2;\n}\n\n// create a node and optionally link it with previous one (in a circular doubly linked list)\nfunction insertNode(i, x, y, last) {\n const p = createNode(i, x, y);\n\n if (!last) {\n p.prev = p;\n p.next = p;\n\n } else {\n p.next = last.next;\n p.prev = last;\n last.next.prev = p;\n last.next = p;\n }\n return p;\n}\n\nfunction removeNode(p) {\n p.next.prev = p.prev;\n p.prev.next = p.next;\n\n if (p.prevZ) p.prevZ.nextZ = p.nextZ;\n if (p.nextZ) p.nextZ.prevZ = p.prevZ;\n}\n\nfunction createNode(i, x, y) {\n return {\n i, // vertex index in coordinates array\n x, y, // vertex coordinates\n prev: null, // previous and next vertex nodes in a polygon ring\n next: null,\n z: 0, // z-order curve value\n prevZ: null, // previous and next nodes in z-order\n nextZ: null,\n steiner: false // indicates whether this is a steiner point\n };\n}\n\n// return a percentage difference between the polygon area and its triangulation area;\n// used to verify correctness of triangulation\nexport function deviation(data, holeIndices, dim, triangles) {\n const hasHoles = holeIndices && holeIndices.length;\n const outerLen = hasHoles ? holeIndices[0] * dim : data.length;\n\n let polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));\n if (hasHoles) {\n for (let i = 0, len = holeIndices.length; i < len; i++) {\n const start = holeIndices[i] * dim;\n const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n polygonArea -= Math.abs(signedArea(data, start, end, dim));\n }\n }\n\n let trianglesArea = 0;\n for (let i = 0; i < triangles.length; i += 3) {\n const a = triangles[i] * dim;\n const b = triangles[i + 1] * dim;\n const c = triangles[i + 2] * dim;\n trianglesArea += Math.abs(\n (data[a] - data[c]) * (data[b + 1] - data[a + 1]) -\n (data[a] - data[b]) * (data[c + 1] - data[a + 1]));\n }\n\n return polygonArea === 0 && trianglesArea === 0 ? 0 :\n Math.abs((trianglesArea - polygonArea) / polygonArea);\n}\n\nfunction signedArea(data, start, end, dim) {\n let sum = 0;\n for (let i = start, j = end - dim; i < end; i += dim) {\n sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);\n j = i;\n }\n return sum;\n}\n\n// turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts\nexport function flatten(data) {\n const vertices = [];\n const holes = [];\n const dimensions = data[0][0].length;\n let holeIndex = 0;\n let prevLen = 0;\n\n for (const ring of data) {\n for (const p of ring) {\n for (let d = 0; d < dimensions; d++) vertices.push(p[d]);\n }\n if (prevLen) {\n holeIndex += prevLen;\n holes.push(holeIndex);\n }\n prevLen = ring.length;\n }\n return {vertices, holes, dimensions};\n}\n","import { FeatureCollection, Feature, LineString, MultiLineString, GeometryCollection } from 'geojson';\n\nimport { LayerGeometry, LayerComponent } from './types-mesh';\n\nimport { offsetPolyline } from './utils-geometry';\nimport earcut from 'earcut';\n\n/**\n * @module triangulator-polylines\n * Polyline triangulation helpers for GeoJSON line geometries.\n *\n * This module converts `LineString`, `MultiLineString`, and supported\n * `GeometryCollection` children into closed buffered polygons in local planar\n * coordinates, then triangulates the resulting rings with `earcut` for mesh\n * rendering.\n */\nexport class TriangulatorPolylines {\n /** Default half-width, in local planar units, used when buffering source polylines. */\n static offset: number = 5;\n\n /** OSM road half-widths, in local planar units, keyed by normalized `highway` tag value. */\n static readonly ROAD_HALF_WIDTH_BY_HIGHWAY: Record<string, number> = {\n motorway: 10,\n motorway_link: 3.5,\n trunk: 8,\n trunk_link: 3.5,\n primary: 6,\n primary_link: 3,\n secondary: 5,\n secondary_link: 2.5,\n tertiary: 4,\n tertiary_link: 2,\n unclassified: 3.5,\n residential: 3.5,\n service: 2.5,\n living_street: 2.5,\n road: 3.5,\n track: 1.5,\n path: 0.75,\n };\n\n /** Default road half-width used when no known `highway` tag value is available. */\n static readonly DEFAULT_ROAD_HALF_WIDTH: number = 3.5;\n\n /** Optional callback used to resolve a per-feature polyline half-width. */\n static readonly defaultOffsetResolver = (_feature: Feature, _featureIndex: number): number => TriangulatorPolylines.offset;\n\n /**\n * Builds triangulated polyline geometry for a GeoJSON feature collection.\n *\n * @param geojson Source feature collection containing polyline geometries.\n * @param origin World-space origin subtracted before converting to local planar space.\n * @param resolveOffset Optional per-feature half-width resolver.\n * @returns A tuple of triangulated geometry chunks and per-feature component metadata.\n * @throws Never throws. Unsupported or degenerate features are skipped.\n * @example\n * const [meshes, comps] = TriangulatorPolylines.buildMesh(lineFC, origin);\n */\n static buildMesh(\n geojson: FeatureCollection,\n origin: number[],\n resolveOffset: (feature: Feature, featureIndex: number) => number = TriangulatorPolylines.defaultOffsetResolver,\n ): [LayerGeometry[], LayerComponent[]] {\n const mesh: LayerGeometry[] = [];\n const comps: LayerComponent[] = [];\n\n const collection: Feature[] = geojson['features'];\n\n let meshes: { flatCoords: number[], flatIds: number[] }[];\n for (let fId = 0; fId < collection.length; fId++) {\n const feature = collection[fId];\n if (!feature.geometry) {\n TriangulatorPolylines.warnSkippedFeature(fId, null);\n continue;\n }\n\n const resolvedOffset = resolveOffset(feature, fId);\n const offset = Number.isFinite(resolvedOffset) && resolvedOffset > 0\n ? resolvedOffset\n : TriangulatorPolylines.offset;\n\n if (feature.geometry.type === 'LineString') {\n meshes = TriangulatorPolylines.lineStringToPolyline(feature, origin, offset);\n } else if (feature.geometry.type === 'MultiLineString') {\n meshes = TriangulatorPolylines.multiLineStringToPolyline(feature, origin, offset);\n } else if (feature.geometry.type === 'GeometryCollection') {\n meshes = TriangulatorPolylines.geometryCollectionToPolyline(feature, origin, offset, fId);\n } else {\n TriangulatorPolylines.warnSkippedFeature(fId, feature.geometry.type);\n continue;\n }\n\n let nPoints = 0;\n let nTriangles = 0;\n\n for (const triangulation of meshes) {\n mesh.push({ \n position: new Float32Array(triangulation.flatCoords), \n indices: new Uint32Array(triangulation.flatIds),\n featureIndex: fId,\n });\n nPoints += triangulation.flatCoords.length / 2;\n nTriangles += triangulation.flatIds.length / 3;\n }\n comps.push({ nPoints, nTriangles, featureIndex: fId, featureId: feature.id });\n }\n return [mesh, comps];\n }\n\n /**\n * Converts a single `LineString` feature into triangulated polyline mesh data.\n *\n * @param feature Source feature with `LineString` geometry.\n * @param origin World-space origin subtracted before buffering.\n * @param offset Polyline half-width used for planar buffering.\n * @returns One triangulated polygon mesh, or an empty array when buffering fails.\n * @throws Never throws. Degenerate buffers return an empty array.\n * @example\n * const [mesh] = TriangulatorPolylines.lineStringToPolyline(feature, origin, 5);\n */\n static lineStringToPolyline(feature: Feature, origin: number[], offset: number): { flatCoords: number[], flatIds: number[] }[] {\n const base = <LineString>feature.geometry;\n const localCoords = base.coordinates.map((coord: number[]) => [coord[0] - origin[0], coord[1] - origin[1]]);\n const polygon = offsetPolyline(localCoords, offset);\n if (polygon.length < 4) {\n return [];\n }\n\n const flatIds = earcut(polygon.flat());\n const flatCoords = polygon.map((coord: number[]) => [coord[0], coord[1]]).flat();\n\n return [{ flatCoords, flatIds }];\n }\n\n /**\n * Converts a `MultiLineString` feature into triangulated polyline meshes.\n *\n * @param feature Source feature with `MultiLineString` geometry.\n * @param origin World-space origin subtracted before buffering.\n * @param offset Polyline half-width used for planar buffering.\n * @returns Triangulated meshes for each valid buffered line string.\n * @throws Never throws. Invalid buffered lines are silently ignored.\n * @example\n * const meshes = TriangulatorPolylines.multiLineStringToPolyline(feature, origin, 5);\n */\n static multiLineStringToPolyline(feature: Feature, origin: number[], offset: number): { flatCoords: number[], flatIds: number[] }[] {\n const { coordinates } = <MultiLineString>feature.geometry;\n\n const meshes = [];\n for (const ls of coordinates) {\n const localCoords = ls.map((coord: number[]) => [coord[0] - origin[0], coord[1] - origin[1]]);\n const polygon = offsetPolyline(localCoords, offset);\n if (polygon.length < 4) {\n continue;\n }\n\n const flatIds = earcut(polygon.flat());\n const flatCoords = polygon.map((coord: number[]) => [coord[0], coord[1]]).flat();\n\n meshes.push({ flatCoords, flatIds });\n }\n\n return meshes;\n }\n\n /**\n * Flattens supported children of a `GeometryCollection` into polyline meshes.\n *\n * @param feature Source feature with `GeometryCollection` geometry.\n * @param origin World-space origin subtracted before buffering.\n * @param offset Polyline half-width used for planar buffering.\n * @param featureIndex Index of the parent feature in the source collection.\n * @returns Triangulated meshes for all supported child geometries.\n * @throws Never throws. Unsupported children are skipped with a console warning.\n * @example\n * const meshes = TriangulatorPolylines.geometryCollectionToPolyline(feature, origin, 5, 0);\n */\n static geometryCollectionToPolyline(feature: Feature, origin: number[], offset: number, featureIndex: number): { flatCoords: number[], flatIds: number[] }[] {\n const { geometries } = <GeometryCollection>feature.geometry;\n const meshes = [];\n for (const geom of geometries) {\n const syntheticFeature = { ...feature, geometry: geom } as Feature;\n if (geom.type === 'LineString') {\n meshes.push(...TriangulatorPolylines.lineStringToPolyline(syntheticFeature, origin, offset));\n } else if (geom.type === 'MultiLineString') {\n meshes.push(...TriangulatorPolylines.multiLineStringToPolyline(syntheticFeature, origin, offset));\n } else {\n TriangulatorPolylines.warnSkippedGeometryCollectionChild(featureIndex, geom.type);\n }\n }\n return meshes;\n }\n\n /**\n * Resolves a road polyline half-width from OSM `highway` tag semantics.\n *\n * @param feature Source road feature with `highway` property.\n * @returns Polyline half-width in local planar units.\n * @throws Never throws. Falls back to `DEFAULT_ROAD_HALF_WIDTH`.\n * @example\n * const hw = TriangulatorPolylines.resolveRoadHalfWidth(roadFeature);\n * // hw → 10 for motorway, 6 for primary, 3.5 for unknown\n */\n static resolveRoadHalfWidth(feature: Feature): number {\n const highway = TriangulatorPolylines.normalizeRoadHighwayValue(feature.properties?.highway);\n return highway\n ? (TriangulatorPolylines.ROAD_HALF_WIDTH_BY_HIGHWAY[highway] ?? TriangulatorPolylines.DEFAULT_ROAD_HALF_WIDTH)\n : TriangulatorPolylines.DEFAULT_ROAD_HALF_WIDTH;\n }\n\n /**\n * Normalizes an OSM `highway` tag value for road-width lookup.\n *\n * @param highway Raw `highway` property value (string, semicolon-delimited, or array).\n * @returns Normalized highway token, or `null` when unavailable.\n * @throws Never throws.\n * @example\n * TriangulatorPolylines.normalizeRoadHighwayValue('motorway'); // 'motorway'\n * TriangulatorPolylines.normalizeRoadHighwayValue('primary;secondary'); // 'primary'\n */\n static normalizeRoadHighwayValue(highway: unknown): string | null {\n const values = Array.isArray(highway)\n ? highway\n : typeof highway === 'string'\n ? highway.split(';')\n : [];\n\n for (const value of values) {\n if (typeof value !== 'string') {\n continue;\n }\n\n const normalized = value.trim().toLowerCase();\n if (normalized.length > 0) {\n return normalized;\n }\n }\n\n return null;\n }\n\n /**\n * Emits a warning when a feature does not contain a supported polyline geometry.\n *\n * @param featureIndex Index of the skipped feature in the source collection.\n * @param geometryType Encountered geometry type, or `null` when geometry is missing.\n * @returns Nothing. A warning is written to the console.\n */\n private static warnSkippedFeature(featureIndex: number, geometryType: string | null): void {\n console.warn(\n `[autk-core] TriangulatorPolylines skipped feature ${featureIndex}: expected LineString or MultiLineString geometry, got ${geometryType ?? 'null'}.`\n );\n }\n\n /**\n * Emits a warning when a `GeometryCollection` child is not a supported polyline geometry.\n *\n * @param featureIndex Index of the parent feature in the source collection.\n * @param geometryType Encountered unsupported child geometry type.\n * @returns Nothing. A warning is written to the console.\n */\n private static warnSkippedGeometryCollectionChild(featureIndex: number, geometryType: string): void {\n console.warn(\n `[autk-core] TriangulatorPolylines skipped GeometryCollection child in feature ${featureIndex}: expected LineString or MultiLineString geometry, got ${geometryType}.`\n );\n }\n}\n","/**\n * Common utilities\n * @module glMatrix\n */\n\n// Configuration Constants\nexport var EPSILON = 0.000001;\nexport var ARRAY_TYPE = typeof Float32Array !== \"undefined\" ? Float32Array : Array;\nexport var RANDOM = Math.random;\nexport var ANGLE_ORDER = \"zyx\";\n\n/**\n * Symmetric round\n * see https://www.npmjs.com/package/round-half-up-symmetric#user-content-detailed-background\n *\n * @param {Number} a value to round\n */\nexport function round(a) {\n if (a >= 0) return Math.round(a);\n return a % 0.5 === 0 ? Math.floor(a) : Math.round(a);\n}\n\n/**\n * Sets the type of array used when creating new vectors and matrices\n *\n * @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array\n */\nexport function setMatrixArrayType(type) {\n ARRAY_TYPE = type;\n}\nvar degree = Math.PI / 180;\nvar radian = 180 / Math.PI;\n\n/**\n * Convert Degree To Radian\n *\n * @param {Number} a Angle in Degrees\n */\nexport function toRadian(a) {\n return a * degree;\n}\n\n/**\n * Convert Radian To Degree\n *\n * @param {Number} a Angle in Radians\n */\nexport function toDegree(a) {\n return a * radian;\n}\n\n/**\n * Tests whether or not the arguments have approximately the same value, within an absolute\n * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less\n * than or equal to 1.0, and a relative tolerance is used for larger values)\n *\n * @param {Number} a The first number to test.\n * @param {Number} b The second number to test.\n * @param {Number} tolerance Absolute or relative tolerance (default glMatrix.EPSILON)\n * @returns {Boolean} True if the numbers are approximately equal, false otherwise.\n */\nexport function equals(a, b) {\n var tolerance = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : EPSILON;\n return Math.abs(a - b) <= tolerance * Math.max(1, Math.abs(a), Math.abs(b));\n}","import * as glMatrix from \"./common.js\";\n\n/**\n * 4x4 Matrix<br>Format: column-major, when typed out it looks like row-major<br>The matrices are being post multiplied.\n * @module mat4\n */\n\n/**\n * Creates a new identity mat4\n *\n * @returns {mat4} a new 4x4 matrix\n */\nexport function create() {\n var out = new glMatrix.ARRAY_TYPE(16);\n if (glMatrix.ARRAY_TYPE != Float32Array) {\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n }\n out[0] = 1;\n out[5] = 1;\n out[10] = 1;\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a new mat4 initialized with values from an existing matrix\n *\n * @param {ReadonlyMat4} a matrix to clone\n * @returns {mat4} a new 4x4 matrix\n */\nexport function clone(a) {\n var out = new glMatrix.ARRAY_TYPE(16);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n\n/**\n * Copy the values from one mat4 to another\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\nexport function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n\n/**\n * Create a new mat4 with the given values\n *\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\n * @returns {mat4} A new mat4\n */\nexport function fromValues(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\n var out = new glMatrix.ARRAY_TYPE(16);\n out[0] = m00;\n out[1] = m01;\n out[2] = m02;\n out[3] = m03;\n out[4] = m10;\n out[5] = m11;\n out[6] = m12;\n out[7] = m13;\n out[8] = m20;\n out[9] = m21;\n out[10] = m22;\n out[11] = m23;\n out[12] = m30;\n out[13] = m31;\n out[14] = m32;\n out[15] = m33;\n return out;\n}\n\n/**\n * Set the components of a mat4 to the given values\n *\n * @param {mat4} out the receiving matrix\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\n * @returns {mat4} out\n */\nexport function set(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\n out[0] = m00;\n out[1] = m01;\n out[2] = m02;\n out[3] = m03;\n out[4] = m10;\n out[5] = m11;\n out[6] = m12;\n out[7] = m13;\n out[8] = m20;\n out[9] = m21;\n out[10] = m22;\n out[11] = m23;\n out[12] = m30;\n out[13] = m31;\n out[14] = m32;\n out[15] = m33;\n return out;\n}\n\n/**\n * Set a mat4 to the identity matrix\n *\n * @param {mat4} out the receiving matrix\n * @returns {mat4} out\n */\nexport function identity(out) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Transpose the values of a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\nexport function transpose(out, a) {\n // If we are transposing ourselves we can skip a few steps but have to cache some values\n if (out === a) {\n var a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a12 = a[6],\n a13 = a[7];\n var a23 = a[11];\n out[1] = a[4];\n out[2] = a[8];\n out[3] = a[12];\n out[4] = a01;\n out[6] = a[9];\n out[7] = a[13];\n out[8] = a02;\n out[9] = a12;\n out[11] = a[14];\n out[12] = a03;\n out[13] = a13;\n out[14] = a23;\n } else {\n out[0] = a[0];\n out[1] = a[4];\n out[2] = a[8];\n out[3] = a[12];\n out[4] = a[1];\n out[5] = a[5];\n out[6] = a[9];\n out[7] = a[13];\n out[8] = a[2];\n out[9] = a[6];\n out[10] = a[10];\n out[11] = a[14];\n out[12] = a[3];\n out[13] = a[7];\n out[14] = a[11];\n out[15] = a[15];\n }\n return out;\n}\n\n/**\n * Inverts a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4 | null} out, or null if source matrix is not invertible\n */\nexport function invert(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b00 = a00 * a11 - a01 * a10;\n var b01 = a00 * a12 - a02 * a10;\n var b02 = a00 * a13 - a03 * a10;\n var b03 = a01 * a12 - a02 * a11;\n var b04 = a01 * a13 - a03 * a11;\n var b05 = a02 * a13 - a03 * a12;\n var b06 = a20 * a31 - a21 * a30;\n var b07 = a20 * a32 - a22 * a30;\n var b08 = a20 * a33 - a23 * a30;\n var b09 = a21 * a32 - a22 * a31;\n var b10 = a21 * a33 - a23 * a31;\n var b11 = a22 * a33 - a23 * a32;\n\n // Calculate the determinant\n var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n if (!det) {\n return null;\n }\n det = 1.0 / det;\n out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;\n out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;\n out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;\n out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;\n out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;\n out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;\n out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;\n out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;\n out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;\n out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;\n out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;\n out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;\n out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;\n out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;\n out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;\n out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;\n return out;\n}\n\n/**\n * Calculates the adjugate of a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\nexport function adjoint(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b00 = a00 * a11 - a01 * a10;\n var b01 = a00 * a12 - a02 * a10;\n var b02 = a00 * a13 - a03 * a10;\n var b03 = a01 * a12 - a02 * a11;\n var b04 = a01 * a13 - a03 * a11;\n var b05 = a02 * a13 - a03 * a12;\n var b06 = a20 * a31 - a21 * a30;\n var b07 = a20 * a32 - a22 * a30;\n var b08 = a20 * a33 - a23 * a30;\n var b09 = a21 * a32 - a22 * a31;\n var b10 = a21 * a33 - a23 * a31;\n var b11 = a22 * a33 - a23 * a32;\n out[0] = a11 * b11 - a12 * b10 + a13 * b09;\n out[1] = a02 * b10 - a01 * b11 - a03 * b09;\n out[2] = a31 * b05 - a32 * b04 + a33 * b03;\n out[3] = a22 * b04 - a21 * b05 - a23 * b03;\n out[4] = a12 * b08 - a10 * b11 - a13 * b07;\n out[5] = a00 * b11 - a02 * b08 + a03 * b07;\n out[6] = a32 * b02 - a30 * b05 - a33 * b01;\n out[7] = a20 * b05 - a22 * b02 + a23 * b01;\n out[8] = a10 * b10 - a11 * b08 + a13 * b06;\n out[9] = a01 * b08 - a00 * b10 - a03 * b06;\n out[10] = a30 * b04 - a31 * b02 + a33 * b00;\n out[11] = a21 * b02 - a20 * b04 - a23 * b00;\n out[12] = a11 * b07 - a10 * b09 - a12 * b06;\n out[13] = a00 * b09 - a01 * b07 + a02 * b06;\n out[14] = a31 * b01 - a30 * b03 - a32 * b00;\n out[15] = a20 * b03 - a21 * b01 + a22 * b00;\n return out;\n}\n\n/**\n * Calculates the determinant of a mat4\n *\n * @param {ReadonlyMat4} a the source matrix\n * @returns {Number} determinant of a\n */\nexport function determinant(a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b0 = a00 * a11 - a01 * a10;\n var b1 = a00 * a12 - a02 * a10;\n var b2 = a01 * a12 - a02 * a11;\n var b3 = a20 * a31 - a21 * a30;\n var b4 = a20 * a32 - a22 * a30;\n var b5 = a21 * a32 - a22 * a31;\n var b6 = a00 * b5 - a01 * b4 + a02 * b3;\n var b7 = a10 * b5 - a11 * b4 + a12 * b3;\n var b8 = a20 * b2 - a21 * b1 + a22 * b0;\n var b9 = a30 * b2 - a31 * b1 + a32 * b0;\n\n // Calculate the determinant\n return a13 * b6 - a03 * b7 + a33 * b8 - a23 * b9;\n}\n\n/**\n * Multiplies two mat4s\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\nexport function multiply(out, a, b) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n\n // Cache only the current line of the second matrix\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[4];\n b1 = b[5];\n b2 = b[6];\n b3 = b[7];\n out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[8];\n b1 = b[9];\n b2 = b[10];\n b3 = b[11];\n out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[12];\n b1 = b[13];\n b2 = b[14];\n b3 = b[15];\n out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n return out;\n}\n\n/**\n * Translate a mat4 by the given vector\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to translate\n * @param {ReadonlyVec3} v vector to translate by\n * @returns {mat4} out\n */\nexport function translate(out, a, v) {\n var x = v[0],\n y = v[1],\n z = v[2];\n var a00, a01, a02, a03;\n var a10, a11, a12, a13;\n var a20, a21, a22, a23;\n if (a === out) {\n out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];\n out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];\n out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];\n out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];\n } else {\n a00 = a[0];\n a01 = a[1];\n a02 = a[2];\n a03 = a[3];\n a10 = a[4];\n a11 = a[5];\n a12 = a[6];\n a13 = a[7];\n a20 = a[8];\n a21 = a[9];\n a22 = a[10];\n a23 = a[11];\n out[0] = a00;\n out[1] = a01;\n out[2] = a02;\n out[3] = a03;\n out[4] = a10;\n out[5] = a11;\n out[6] = a12;\n out[7] = a13;\n out[8] = a20;\n out[9] = a21;\n out[10] = a22;\n out[11] = a23;\n out[12] = a00 * x + a10 * y + a20 * z + a[12];\n out[13] = a01 * x + a11 * y + a21 * z + a[13];\n out[14] = a02 * x + a12 * y + a22 * z + a[14];\n out[15] = a03 * x + a13 * y + a23 * z + a[15];\n }\n return out;\n}\n\n/**\n * Scales the mat4 by the dimensions in the given vec3 not using vectorization\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to scale\n * @param {ReadonlyVec3} v the vec3 to scale the matrix by\n * @returns {mat4} out\n **/\nexport function scale(out, a, v) {\n var x = v[0],\n y = v[1],\n z = v[2];\n out[0] = a[0] * x;\n out[1] = a[1] * x;\n out[2] = a[2] * x;\n out[3] = a[3] * x;\n out[4] = a[4] * y;\n out[5] = a[5] * y;\n out[6] = a[6] * y;\n out[7] = a[7] * y;\n out[8] = a[8] * z;\n out[9] = a[9] * z;\n out[10] = a[10] * z;\n out[11] = a[11] * z;\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n\n/**\n * Rotates a mat4 by the given angle around the given axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @param {ReadonlyVec3} axis the axis to rotate around\n * @returns {mat4} out\n */\nexport function rotate(out, a, rad, axis) {\n var x = axis[0],\n y = axis[1],\n z = axis[2];\n var len = Math.sqrt(x * x + y * y + z * z);\n var s, c, t;\n var a00, a01, a02, a03;\n var a10, a11, a12, a13;\n var a20, a21, a22, a23;\n var b00, b01, b02;\n var b10, b11, b12;\n var b20, b21, b22;\n if (len < glMatrix.EPSILON) {\n return null;\n }\n len = 1 / len;\n x *= len;\n y *= len;\n z *= len;\n s = Math.sin(rad);\n c = Math.cos(rad);\n t = 1 - c;\n a00 = a[0];\n a01 = a[1];\n a02 = a[2];\n a03 = a[3];\n a10 = a[4];\n a11 = a[5];\n a12 = a[6];\n a13 = a[7];\n a20 = a[8];\n a21 = a[9];\n a22 = a[10];\n a23 = a[11];\n\n // Construct the elements of the rotation matrix\n b00 = x * x * t + c;\n b01 = y * x * t + z * s;\n b02 = z * x * t - y * s;\n b10 = x * y * t - z * s;\n b11 = y * y * t + c;\n b12 = z * y * t + x * s;\n b20 = x * z * t + y * s;\n b21 = y * z * t - x * s;\n b22 = z * z * t + c;\n\n // Perform rotation-specific matrix multiplication\n out[0] = a00 * b00 + a10 * b01 + a20 * b02;\n out[1] = a01 * b00 + a11 * b01 + a21 * b02;\n out[2] = a02 * b00 + a12 * b01 + a22 * b02;\n out[3] = a03 * b00 + a13 * b01 + a23 * b02;\n out[4] = a00 * b10 + a10 * b11 + a20 * b12;\n out[5] = a01 * b10 + a11 * b11 + a21 * b12;\n out[6] = a02 * b10 + a12 * b11 + a22 * b12;\n out[7] = a03 * b10 + a13 * b11 + a23 * b12;\n out[8] = a00 * b20 + a10 * b21 + a20 * b22;\n out[9] = a01 * b20 + a11 * b21 + a21 * b22;\n out[10] = a02 * b20 + a12 * b21 + a22 * b22;\n out[11] = a03 * b20 + a13 * b21 + a23 * b22;\n if (a !== out) {\n // If the source and destination differ, copy the unchanged last row\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n }\n return out;\n}\n\n/**\n * Rotates a matrix by the given angle around the X axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\nexport function rotateX(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a10 = a[4];\n var a11 = a[5];\n var a12 = a[6];\n var a13 = a[7];\n var a20 = a[8];\n var a21 = a[9];\n var a22 = a[10];\n var a23 = a[11];\n if (a !== out) {\n // If the source and destination differ, copy the unchanged rows\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n }\n\n // Perform axis-specific matrix multiplication\n out[4] = a10 * c + a20 * s;\n out[5] = a11 * c + a21 * s;\n out[6] = a12 * c + a22 * s;\n out[7] = a13 * c + a23 * s;\n out[8] = a20 * c - a10 * s;\n out[9] = a21 * c - a11 * s;\n out[10] = a22 * c - a12 * s;\n out[11] = a23 * c - a13 * s;\n return out;\n}\n\n/**\n * Rotates a matrix by the given angle around the Y axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\nexport function rotateY(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a00 = a[0];\n var a01 = a[1];\n var a02 = a[2];\n var a03 = a[3];\n var a20 = a[8];\n var a21 = a[9];\n var a22 = a[10];\n var a23 = a[11];\n if (a !== out) {\n // If the source and destination differ, copy the unchanged rows\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n }\n\n // Perform axis-specific matrix multiplication\n out[0] = a00 * c - a20 * s;\n out[1] = a01 * c - a21 * s;\n out[2] = a02 * c - a22 * s;\n out[3] = a03 * c - a23 * s;\n out[8] = a00 * s + a20 * c;\n out[9] = a01 * s + a21 * c;\n out[10] = a02 * s + a22 * c;\n out[11] = a03 * s + a23 * c;\n return out;\n}\n\n/**\n * Rotates a matrix by the given angle around the Z axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\nexport function rotateZ(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a00 = a[0];\n var a01 = a[1];\n var a02 = a[2];\n var a03 = a[3];\n var a10 = a[4];\n var a11 = a[5];\n var a12 = a[6];\n var a13 = a[7];\n if (a !== out) {\n // If the source and destination differ, copy the unchanged last row\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n }\n\n // Perform axis-specific matrix multiplication\n out[0] = a00 * c + a10 * s;\n out[1] = a01 * c + a11 * s;\n out[2] = a02 * c + a12 * s;\n out[3] = a03 * c + a13 * s;\n out[4] = a10 * c - a00 * s;\n out[5] = a11 * c - a01 * s;\n out[6] = a12 * c - a02 * s;\n out[7] = a13 * c - a03 * s;\n return out;\n}\n\n/**\n * Creates a matrix from a vector translation\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, dest, vec);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyVec3} v Translation vector\n * @returns {mat4} out\n */\nexport function fromTranslation(out, v) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from a vector scaling\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.scale(dest, dest, vec);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyVec3} v Scaling vector\n * @returns {mat4} out\n */\nexport function fromScaling(out, v) {\n out[0] = v[0];\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = v[1];\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = v[2];\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from a given angle around a given axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotate(dest, dest, rad, axis);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @param {ReadonlyVec3} axis the axis to rotate around\n * @returns {mat4} out\n */\nexport function fromRotation(out, rad, axis) {\n var x = axis[0],\n y = axis[1],\n z = axis[2];\n var len = Math.sqrt(x * x + y * y + z * z);\n var s, c, t;\n if (len < glMatrix.EPSILON) {\n return null;\n }\n len = 1 / len;\n x *= len;\n y *= len;\n z *= len;\n s = Math.sin(rad);\n c = Math.cos(rad);\n t = 1 - c;\n\n // Perform rotation-specific matrix multiplication\n out[0] = x * x * t + c;\n out[1] = y * x * t + z * s;\n out[2] = z * x * t - y * s;\n out[3] = 0;\n out[4] = x * y * t - z * s;\n out[5] = y * y * t + c;\n out[6] = z * y * t + x * s;\n out[7] = 0;\n out[8] = x * z * t + y * s;\n out[9] = y * z * t - x * s;\n out[10] = z * z * t + c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from the given angle around the X axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateX(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\nexport function fromXRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n\n // Perform axis-specific matrix multiplication\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = c;\n out[6] = s;\n out[7] = 0;\n out[8] = 0;\n out[9] = -s;\n out[10] = c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from the given angle around the Y axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateY(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\nexport function fromYRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n\n // Perform axis-specific matrix multiplication\n out[0] = c;\n out[1] = 0;\n out[2] = -s;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = s;\n out[9] = 0;\n out[10] = c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from the given angle around the Z axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateZ(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\nexport function fromZRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n\n // Perform axis-specific matrix multiplication\n out[0] = c;\n out[1] = s;\n out[2] = 0;\n out[3] = 0;\n out[4] = -s;\n out[5] = c;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from a quaternion rotation and vector translation\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, dest, vec);\n * let quatMat = mat4.create();\n * mat4.fromQuat(quatMat, quat);\n * mat4.multiply(dest, dest, quatMat);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @returns {mat4} out\n */\nexport function fromRotationTranslation(out, q, v) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n out[0] = 1 - (yy + zz);\n out[1] = xy + wz;\n out[2] = xz - wy;\n out[3] = 0;\n out[4] = xy - wz;\n out[5] = 1 - (xx + zz);\n out[6] = yz + wx;\n out[7] = 0;\n out[8] = xz + wy;\n out[9] = yz - wx;\n out[10] = 1 - (xx + yy);\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a new mat4 from a dual quat.\n *\n * @param {mat4} out Matrix\n * @param {ReadonlyQuat2} a Dual Quaternion\n * @returns {mat4} mat4 receiving operation result\n */\nexport function fromQuat2(out, a) {\n var translation = new glMatrix.ARRAY_TYPE(3);\n var bx = -a[0],\n by = -a[1],\n bz = -a[2],\n bw = a[3],\n ax = a[4],\n ay = a[5],\n az = a[6],\n aw = a[7];\n var magnitude = bx * bx + by * by + bz * bz + bw * bw;\n //Only scale if it makes sense\n if (magnitude > 0) {\n translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;\n translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;\n translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;\n } else {\n translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;\n translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;\n translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;\n }\n fromRotationTranslation(out, a, translation);\n return out;\n}\n\n/**\n * Returns the translation vector component of a transformation\n * matrix. If a matrix is built with fromRotationTranslation,\n * the returned vector will be the same as the translation vector\n * originally supplied.\n * @param {vec3} out Vector to receive translation component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {vec3} out\n */\nexport function getTranslation(out, mat) {\n out[0] = mat[12];\n out[1] = mat[13];\n out[2] = mat[14];\n return out;\n}\n\n/**\n * Returns the scaling factor component of a transformation\n * matrix. If a matrix is built with fromRotationTranslationScale\n * with a normalized Quaternion parameter, the returned vector will be\n * the same as the scaling vector\n * originally supplied.\n * @param {vec3} out Vector to receive scaling factor component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {vec3} out\n */\nexport function getScaling(out, mat) {\n var m11 = mat[0];\n var m12 = mat[1];\n var m13 = mat[2];\n var m21 = mat[4];\n var m22 = mat[5];\n var m23 = mat[6];\n var m31 = mat[8];\n var m32 = mat[9];\n var m33 = mat[10];\n out[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13);\n out[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23);\n out[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33);\n return out;\n}\n\n/**\n * Returns a quaternion representing the rotational component\n * of a transformation matrix. If a matrix is built with\n * fromRotationTranslation, the returned quaternion will be the\n * same as the quaternion originally supplied.\n * @param {quat} out Quaternion to receive the rotation component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {quat} out\n */\nexport function getRotation(out, mat) {\n var scaling = new glMatrix.ARRAY_TYPE(3);\n getScaling(scaling, mat);\n var is1 = 1 / scaling[0];\n var is2 = 1 / scaling[1];\n var is3 = 1 / scaling[2];\n var sm11 = mat[0] * is1;\n var sm12 = mat[1] * is2;\n var sm13 = mat[2] * is3;\n var sm21 = mat[4] * is1;\n var sm22 = mat[5] * is2;\n var sm23 = mat[6] * is3;\n var sm31 = mat[8] * is1;\n var sm32 = mat[9] * is2;\n var sm33 = mat[10] * is3;\n var trace = sm11 + sm22 + sm33;\n var S = 0;\n if (trace > 0) {\n S = Math.sqrt(trace + 1.0) * 2;\n out[3] = 0.25 * S;\n out[0] = (sm23 - sm32) / S;\n out[1] = (sm31 - sm13) / S;\n out[2] = (sm12 - sm21) / S;\n } else if (sm11 > sm22 && sm11 > sm33) {\n S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;\n out[3] = (sm23 - sm32) / S;\n out[0] = 0.25 * S;\n out[1] = (sm12 + sm21) / S;\n out[2] = (sm31 + sm13) / S;\n } else if (sm22 > sm33) {\n S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;\n out[3] = (sm31 - sm13) / S;\n out[0] = (sm12 + sm21) / S;\n out[1] = 0.25 * S;\n out[2] = (sm23 + sm32) / S;\n } else {\n S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;\n out[3] = (sm12 - sm21) / S;\n out[0] = (sm31 + sm13) / S;\n out[1] = (sm23 + sm32) / S;\n out[2] = 0.25 * S;\n }\n return out;\n}\n\n/**\n * Decomposes a transformation matrix into its rotation, translation\n * and scale components. Returns only the rotation component\n * @param {quat} out_r Quaternion to receive the rotation component\n * @param {vec3} out_t Vector to receive the translation vector\n * @param {vec3} out_s Vector to receive the scaling factor\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @returns {quat} out_r\n */\nexport function decompose(out_r, out_t, out_s, mat) {\n out_t[0] = mat[12];\n out_t[1] = mat[13];\n out_t[2] = mat[14];\n var m11 = mat[0];\n var m12 = mat[1];\n var m13 = mat[2];\n var m21 = mat[4];\n var m22 = mat[5];\n var m23 = mat[6];\n var m31 = mat[8];\n var m32 = mat[9];\n var m33 = mat[10];\n out_s[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13);\n out_s[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23);\n out_s[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33);\n var is1 = 1 / out_s[0];\n var is2 = 1 / out_s[1];\n var is3 = 1 / out_s[2];\n var sm11 = m11 * is1;\n var sm12 = m12 * is2;\n var sm13 = m13 * is3;\n var sm21 = m21 * is1;\n var sm22 = m22 * is2;\n var sm23 = m23 * is3;\n var sm31 = m31 * is1;\n var sm32 = m32 * is2;\n var sm33 = m33 * is3;\n var trace = sm11 + sm22 + sm33;\n var S = 0;\n if (trace > 0) {\n S = Math.sqrt(trace + 1.0) * 2;\n out_r[3] = 0.25 * S;\n out_r[0] = (sm23 - sm32) / S;\n out_r[1] = (sm31 - sm13) / S;\n out_r[2] = (sm12 - sm21) / S;\n } else if (sm11 > sm22 && sm11 > sm33) {\n S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;\n out_r[3] = (sm23 - sm32) / S;\n out_r[0] = 0.25 * S;\n out_r[1] = (sm12 + sm21) / S;\n out_r[2] = (sm31 + sm13) / S;\n } else if (sm22 > sm33) {\n S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;\n out_r[3] = (sm31 - sm13) / S;\n out_r[0] = (sm12 + sm21) / S;\n out_r[1] = 0.25 * S;\n out_r[2] = (sm23 + sm32) / S;\n } else {\n S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;\n out_r[3] = (sm12 - sm21) / S;\n out_r[0] = (sm31 + sm13) / S;\n out_r[1] = (sm23 + sm32) / S;\n out_r[2] = 0.25 * S;\n }\n return out_r;\n}\n\n/**\n * Creates a matrix from a quaternion rotation, vector translation and vector scale\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, dest, vec);\n * let quatMat = mat4.create();\n * mat4.fromQuat(quatMat, quat);\n * mat4.multiply(dest, dest, quatMat);\n * mat4.scale(dest, dest, scale)\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @param {ReadonlyVec3} s Scaling vector\n * @returns {mat4} out\n */\nexport function fromRotationTranslationScale(out, q, v, s) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n var sx = s[0];\n var sy = s[1];\n var sz = s[2];\n out[0] = (1 - (yy + zz)) * sx;\n out[1] = (xy + wz) * sx;\n out[2] = (xz - wy) * sx;\n out[3] = 0;\n out[4] = (xy - wz) * sy;\n out[5] = (1 - (xx + zz)) * sy;\n out[6] = (yz + wx) * sy;\n out[7] = 0;\n out[8] = (xz + wy) * sz;\n out[9] = (yz - wx) * sz;\n out[10] = (1 - (xx + yy)) * sz;\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n\n/**\n * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, dest, vec);\n * mat4.translate(dest, dest, origin);\n * let quatMat = mat4.create();\n * mat4.fromQuat(quatMat, quat);\n * mat4.multiply(dest, dest, quatMat);\n * mat4.scale(dest, dest, scale)\n * mat4.translate(dest, dest, negativeOrigin);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @param {ReadonlyVec3} s Scaling vector\n * @param {ReadonlyVec3} o The origin vector around which to scale and rotate\n * @returns {mat4} out\n */\nexport function fromRotationTranslationScaleOrigin(out, q, v, s, o) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n var sx = s[0];\n var sy = s[1];\n var sz = s[2];\n var ox = o[0];\n var oy = o[1];\n var oz = o[2];\n var out0 = (1 - (yy + zz)) * sx;\n var out1 = (xy + wz) * sx;\n var out2 = (xz - wy) * sx;\n var out4 = (xy - wz) * sy;\n var out5 = (1 - (xx + zz)) * sy;\n var out6 = (yz + wx) * sy;\n var out8 = (xz + wy) * sz;\n var out9 = (yz - wx) * sz;\n var out10 = (1 - (xx + yy)) * sz;\n out[0] = out0;\n out[1] = out1;\n out[2] = out2;\n out[3] = 0;\n out[4] = out4;\n out[5] = out5;\n out[6] = out6;\n out[7] = 0;\n out[8] = out8;\n out[9] = out9;\n out[10] = out10;\n out[11] = 0;\n out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);\n out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);\n out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);\n out[15] = 1;\n return out;\n}\n\n/**\n * Calculates a 4x4 matrix from the given quaternion\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyQuat} q Quaternion to create matrix from\n *\n * @returns {mat4} out\n */\nexport function fromQuat(out, q) {\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var yx = y * x2;\n var yy = y * y2;\n var zx = z * x2;\n var zy = z * y2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n out[0] = 1 - yy - zz;\n out[1] = yx + wz;\n out[2] = zx - wy;\n out[3] = 0;\n out[4] = yx - wz;\n out[5] = 1 - xx - zz;\n out[6] = zy + wx;\n out[7] = 0;\n out[8] = zx + wy;\n out[9] = zy - wx;\n out[10] = 1 - xx - yy;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n\n/**\n * Generates a frustum matrix with the given bounds\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {Number} left Left bound of the frustum\n * @param {Number} right Right bound of the frustum\n * @param {Number} bottom Bottom bound of the frustum\n * @param {Number} top Top bound of the frustum\n * @param {Number} near Near bound of the frustum\n * @param {Number} far Far bound of the frustum\n * @returns {mat4} out\n */\nexport function frustum(out, left, right, bottom, top, near, far) {\n var rl = 1 / (right - left);\n var tb = 1 / (top - bottom);\n var nf = 1 / (near - far);\n out[0] = near * 2 * rl;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = near * 2 * tb;\n out[6] = 0;\n out[7] = 0;\n out[8] = (right + left) * rl;\n out[9] = (top + bottom) * tb;\n out[10] = (far + near) * nf;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[14] = far * near * 2 * nf;\n out[15] = 0;\n return out;\n}\n\n/**\n * Generates a perspective projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],\n * which matches WebGL/OpenGL's clip volume.\n * Passing null/undefined/no value for far will generate infinite projection matrix.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} fovy Vertical field of view in radians\n * @param {number} aspect Aspect ratio. typically viewport width/height\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum, can be null or Infinity\n * @returns {mat4} out\n */\nexport function perspectiveNO(out, fovy, aspect, near, far) {\n var f = 1.0 / Math.tan(fovy / 2);\n out[0] = f / aspect;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = f;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[15] = 0;\n if (far != null && far !== Infinity) {\n var nf = 1 / (near - far);\n out[10] = (far + near) * nf;\n out[14] = 2 * far * near * nf;\n } else {\n out[10] = -1;\n out[14] = -2 * near;\n }\n return out;\n}\n\n/**\n * Alias for {@link mat4.perspectiveNO}\n * @function\n */\nexport var perspective = perspectiveNO;\n\n/**\n * Generates a perspective projection matrix suitable for WebGPU with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],\n * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.\n * Passing null/undefined/no value for far will generate infinite projection matrix.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} fovy Vertical field of view in radians\n * @param {number} aspect Aspect ratio. typically viewport width/height\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum, can be null or Infinity\n * @returns {mat4} out\n */\nexport function perspectiveZO(out, fovy, aspect, near, far) {\n var f = 1.0 / Math.tan(fovy / 2);\n out[0] = f / aspect;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = f;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[15] = 0;\n if (far != null && far !== Infinity) {\n var nf = 1 / (near - far);\n out[10] = far * nf;\n out[14] = far * near * nf;\n } else {\n out[10] = -1;\n out[14] = -near;\n }\n return out;\n}\n\n/**\n * Generates a perspective projection matrix with the given field of view.\n * This is primarily useful for generating projection matrices to be used\n * with the still experiemental WebVR API.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\nexport function perspectiveFromFieldOfView(out, fov, near, far) {\n var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);\n var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);\n var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);\n var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);\n var xScale = 2.0 / (leftTan + rightTan);\n var yScale = 2.0 / (upTan + downTan);\n out[0] = xScale;\n out[1] = 0.0;\n out[2] = 0.0;\n out[3] = 0.0;\n out[4] = 0.0;\n out[5] = yScale;\n out[6] = 0.0;\n out[7] = 0.0;\n out[8] = -((leftTan - rightTan) * xScale * 0.5);\n out[9] = (upTan - downTan) * yScale * 0.5;\n out[10] = far / (near - far);\n out[11] = -1.0;\n out[12] = 0.0;\n out[13] = 0.0;\n out[14] = far * near / (near - far);\n out[15] = 0.0;\n return out;\n}\n\n/**\n * Generates a orthogonal projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],\n * which matches WebGL/OpenGL's clip volume.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} left Left bound of the frustum\n * @param {number} right Right bound of the frustum\n * @param {number} bottom Bottom bound of the frustum\n * @param {number} top Top bound of the frustum\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\nexport function orthoNO(out, left, right, bottom, top, near, far) {\n var lr = 1 / (left - right);\n var bt = 1 / (bottom - top);\n var nf = 1 / (near - far);\n out[0] = -2 * lr;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = -2 * bt;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 2 * nf;\n out[11] = 0;\n out[12] = (left + right) * lr;\n out[13] = (top + bottom) * bt;\n out[14] = (far + near) * nf;\n out[15] = 1;\n return out;\n}\n\n/**\n * Alias for {@link mat4.orthoNO}\n * @function\n */\nexport var ortho = orthoNO;\n\n/**\n * Generates a orthogonal projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],\n * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} left Left bound of the frustum\n * @param {number} right Right bound of the frustum\n * @param {number} bottom Bottom bound of the frustum\n * @param {number} top Top bound of the frustum\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\nexport function orthoZO(out, left, right, bottom, top, near, far) {\n var lr = 1 / (left - right);\n var bt = 1 / (bottom - top);\n var nf = 1 / (near - far);\n out[0] = -2 * lr;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = -2 * bt;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = nf;\n out[11] = 0;\n out[12] = (left + right) * lr;\n out[13] = (top + bottom) * bt;\n out[14] = near * nf;\n out[15] = 1;\n return out;\n}\n\n/**\n * Generates a look-at matrix with the given eye position, focal point, and up axis.\n * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {ReadonlyVec3} eye Position of the viewer\n * @param {ReadonlyVec3} center Point the viewer is looking at\n * @param {ReadonlyVec3} up vec3 pointing up\n * @returns {mat4} out\n */\nexport function lookAt(out, eye, center, up) {\n var x0, x1, x2, y0, y1, y2, z0, z1, z2, len;\n var eyex = eye[0];\n var eyey = eye[1];\n var eyez = eye[2];\n var upx = up[0];\n var upy = up[1];\n var upz = up[2];\n var centerx = center[0];\n var centery = center[1];\n var centerz = center[2];\n if (Math.abs(eyex - centerx) < glMatrix.EPSILON && Math.abs(eyey - centery) < glMatrix.EPSILON && Math.abs(eyez - centerz) < glMatrix.EPSILON) {\n return identity(out);\n }\n z0 = eyex - centerx;\n z1 = eyey - centery;\n z2 = eyez - centerz;\n len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);\n z0 *= len;\n z1 *= len;\n z2 *= len;\n x0 = upy * z2 - upz * z1;\n x1 = upz * z0 - upx * z2;\n x2 = upx * z1 - upy * z0;\n len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);\n if (!len) {\n x0 = 0;\n x1 = 0;\n x2 = 0;\n } else {\n len = 1 / len;\n x0 *= len;\n x1 *= len;\n x2 *= len;\n }\n y0 = z1 * x2 - z2 * x1;\n y1 = z2 * x0 - z0 * x2;\n y2 = z0 * x1 - z1 * x0;\n len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);\n if (!len) {\n y0 = 0;\n y1 = 0;\n y2 = 0;\n } else {\n len = 1 / len;\n y0 *= len;\n y1 *= len;\n y2 *= len;\n }\n out[0] = x0;\n out[1] = y0;\n out[2] = z0;\n out[3] = 0;\n out[4] = x1;\n out[5] = y1;\n out[6] = z1;\n out[7] = 0;\n out[8] = x2;\n out[9] = y2;\n out[10] = z2;\n out[11] = 0;\n out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);\n out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);\n out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);\n out[15] = 1;\n return out;\n}\n\n/**\n * Generates a matrix that makes something look at something else.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {ReadonlyVec3} eye Position of the viewer\n * @param {ReadonlyVec3} target Point the viewer is looking at\n * @param {ReadonlyVec3} up vec3 pointing up\n * @returns {mat4} out\n */\nexport function targetTo(out, eye, target, up) {\n var eyex = eye[0],\n eyey = eye[1],\n eyez = eye[2],\n upx = up[0],\n upy = up[1],\n upz = up[2];\n var z0 = eyex - target[0],\n z1 = eyey - target[1],\n z2 = eyez - target[2];\n var len = z0 * z0 + z1 * z1 + z2 * z2;\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n z0 *= len;\n z1 *= len;\n z2 *= len;\n }\n var x0 = upy * z2 - upz * z1,\n x1 = upz * z0 - upx * z2,\n x2 = upx * z1 - upy * z0;\n len = x0 * x0 + x1 * x1 + x2 * x2;\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n x0 *= len;\n x1 *= len;\n x2 *= len;\n }\n out[0] = x0;\n out[1] = x1;\n out[2] = x2;\n out[3] = 0;\n out[4] = z1 * x2 - z2 * x1;\n out[5] = z2 * x0 - z0 * x2;\n out[6] = z0 * x1 - z1 * x0;\n out[7] = 0;\n out[8] = z0;\n out[9] = z1;\n out[10] = z2;\n out[11] = 0;\n out[12] = eyex;\n out[13] = eyey;\n out[14] = eyez;\n out[15] = 1;\n return out;\n}\n\n/**\n * Returns a string representation of a mat4\n *\n * @param {ReadonlyMat4} a matrix to represent as a string\n * @returns {String} string representation of the matrix\n */\nexport function str(a) {\n return \"mat4(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \", \" + a[4] + \", \" + a[5] + \", \" + a[6] + \", \" + a[7] + \", \" + a[8] + \", \" + a[9] + \", \" + a[10] + \", \" + a[11] + \", \" + a[12] + \", \" + a[13] + \", \" + a[14] + \", \" + a[15] + \")\";\n}\n\n/**\n * Returns Frobenius norm of a mat4\n *\n * @param {ReadonlyMat4} a the matrix to calculate Frobenius norm of\n * @returns {Number} Frobenius norm\n */\nexport function frob(a) {\n return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2] + a[3] * a[3] + a[4] * a[4] + a[5] * a[5] + a[6] * a[6] + a[7] * a[7] + a[8] * a[8] + a[9] * a[9] + a[10] * a[10] + a[11] * a[11] + a[12] * a[12] + a[13] * a[13] + a[14] * a[14] + a[15] * a[15]);\n}\n\n/**\n * Adds two mat4's\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\nexport function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n out[4] = a[4] + b[4];\n out[5] = a[5] + b[5];\n out[6] = a[6] + b[6];\n out[7] = a[7] + b[7];\n out[8] = a[8] + b[8];\n out[9] = a[9] + b[9];\n out[10] = a[10] + b[10];\n out[11] = a[11] + b[11];\n out[12] = a[12] + b[12];\n out[13] = a[13] + b[13];\n out[14] = a[14] + b[14];\n out[15] = a[15] + b[15];\n return out;\n}\n\n/**\n * Subtracts matrix b from matrix a\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\nexport function subtract(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n out[3] = a[3] - b[3];\n out[4] = a[4] - b[4];\n out[5] = a[5] - b[5];\n out[6] = a[6] - b[6];\n out[7] = a[7] - b[7];\n out[8] = a[8] - b[8];\n out[9] = a[9] - b[9];\n out[10] = a[10] - b[10];\n out[11] = a[11] - b[11];\n out[12] = a[12] - b[12];\n out[13] = a[13] - b[13];\n out[14] = a[14] - b[14];\n out[15] = a[15] - b[15];\n return out;\n}\n\n/**\n * Multiply each element of the matrix by a scalar.\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to scale\n * @param {Number} b amount to scale the matrix's elements by\n * @returns {mat4} out\n */\nexport function multiplyScalar(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n out[3] = a[3] * b;\n out[4] = a[4] * b;\n out[5] = a[5] * b;\n out[6] = a[6] * b;\n out[7] = a[7] * b;\n out[8] = a[8] * b;\n out[9] = a[9] * b;\n out[10] = a[10] * b;\n out[11] = a[11] * b;\n out[12] = a[12] * b;\n out[13] = a[13] * b;\n out[14] = a[14] * b;\n out[15] = a[15] * b;\n return out;\n}\n\n/**\n * Adds two mat4's after multiplying each element of the second operand by a scalar value.\n *\n * @param {mat4} out the receiving vector\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @param {Number} scale the amount to scale b's elements by before adding\n * @returns {mat4} out\n */\nexport function multiplyScalarAndAdd(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n out[3] = a[3] + b[3] * scale;\n out[4] = a[4] + b[4] * scale;\n out[5] = a[5] + b[5] * scale;\n out[6] = a[6] + b[6] * scale;\n out[7] = a[7] + b[7] * scale;\n out[8] = a[8] + b[8] * scale;\n out[9] = a[9] + b[9] * scale;\n out[10] = a[10] + b[10] * scale;\n out[11] = a[11] + b[11] * scale;\n out[12] = a[12] + b[12] * scale;\n out[13] = a[13] + b[13] * scale;\n out[14] = a[14] + b[14] * scale;\n out[15] = a[15] + b[15] * scale;\n return out;\n}\n\n/**\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyMat4} a The first matrix.\n * @param {ReadonlyMat4} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\nexport function exactEquals(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];\n}\n\n/**\n * Returns whether or not the matrices have approximately the same elements in the same position.\n *\n * @param {ReadonlyMat4} a The first matrix.\n * @param {ReadonlyMat4} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\nexport function equals(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3];\n var a4 = a[4],\n a5 = a[5],\n a6 = a[6],\n a7 = a[7];\n var a8 = a[8],\n a9 = a[9],\n a10 = a[10],\n a11 = a[11];\n var a12 = a[12],\n a13 = a[13],\n a14 = a[14],\n a15 = a[15];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n var b4 = b[4],\n b5 = b[5],\n b6 = b[6],\n b7 = b[7];\n var b8 = b[8],\n b9 = b[9],\n b10 = b[10],\n b11 = b[11];\n var b12 = b[12],\n b13 = b[13],\n b14 = b[14],\n b15 = b[15];\n return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && Math.abs(a9 - b9) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && Math.abs(a10 - b10) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && Math.abs(a11 - b11) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && Math.abs(a12 - b12) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && Math.abs(a13 - b13) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && Math.abs(a14 - b14) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && Math.abs(a15 - b15) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15));\n}\n\n/**\n * Alias for {@link mat4.multiply}\n * @function\n */\nexport var mul = multiply;\n\n/**\n * Alias for {@link mat4.subtract}\n * @function\n */\nexport var sub = subtract;","import * as glMatrix from \"./common.js\";\n\n/**\n * 3 Dimensional Vector\n * @module vec3\n */\n\n/**\n * Creates a new, empty vec3\n *\n * @returns {vec3} a new 3D vector\n */\nexport function create() {\n var out = new glMatrix.ARRAY_TYPE(3);\n if (glMatrix.ARRAY_TYPE != Float32Array) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n }\n return out;\n}\n\n/**\n * Creates a new vec3 initialized with values from an existing vector\n *\n * @param {ReadonlyVec3} a vector to clone\n * @returns {vec3} a new 3D vector\n */\nexport function clone(a) {\n var out = new glMatrix.ARRAY_TYPE(3);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n return out;\n}\n\n/**\n * Calculates the length of a vec3\n *\n * @param {ReadonlyVec3} a vector to calculate length of\n * @returns {Number} length of a\n */\nexport function length(a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n return Math.sqrt(x * x + y * y + z * z);\n}\n\n/**\n * Creates a new vec3 initialized with the given values\n *\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @returns {vec3} a new 3D vector\n */\nexport function fromValues(x, y, z) {\n var out = new glMatrix.ARRAY_TYPE(3);\n out[0] = x;\n out[1] = y;\n out[2] = z;\n return out;\n}\n\n/**\n * Copy the values from one vec3 to another\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the source vector\n * @returns {vec3} out\n */\nexport function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n return out;\n}\n\n/**\n * Set the components of a vec3 to the given values\n *\n * @param {vec3} out the receiving vector\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @returns {vec3} out\n */\nexport function set(out, x, y, z) {\n out[0] = x;\n out[1] = y;\n out[2] = z;\n return out;\n}\n\n/**\n * Adds two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n return out;\n}\n\n/**\n * Subtracts vector b from vector a\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function subtract(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n return out;\n}\n\n/**\n * Multiplies two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function multiply(out, a, b) {\n out[0] = a[0] * b[0];\n out[1] = a[1] * b[1];\n out[2] = a[2] * b[2];\n return out;\n}\n\n/**\n * Divides two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function divide(out, a, b) {\n out[0] = a[0] / b[0];\n out[1] = a[1] / b[1];\n out[2] = a[2] / b[2];\n return out;\n}\n\n/**\n * Math.ceil the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to ceil\n * @returns {vec3} out\n */\nexport function ceil(out, a) {\n out[0] = Math.ceil(a[0]);\n out[1] = Math.ceil(a[1]);\n out[2] = Math.ceil(a[2]);\n return out;\n}\n\n/**\n * Math.floor the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to floor\n * @returns {vec3} out\n */\nexport function floor(out, a) {\n out[0] = Math.floor(a[0]);\n out[1] = Math.floor(a[1]);\n out[2] = Math.floor(a[2]);\n return out;\n}\n\n/**\n * Returns the minimum of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function min(out, a, b) {\n out[0] = Math.min(a[0], b[0]);\n out[1] = Math.min(a[1], b[1]);\n out[2] = Math.min(a[2], b[2]);\n return out;\n}\n\n/**\n * Returns the maximum of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function max(out, a, b) {\n out[0] = Math.max(a[0], b[0]);\n out[1] = Math.max(a[1], b[1]);\n out[2] = Math.max(a[2], b[2]);\n return out;\n}\n\n/**\n * symmetric round the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to round\n * @returns {vec3} out\n */\nexport function round(out, a) {\n out[0] = glMatrix.round(a[0]);\n out[1] = glMatrix.round(a[1]);\n out[2] = glMatrix.round(a[2]);\n return out;\n}\n\n/**\n * Scales a vec3 by a scalar number\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to scale\n * @param {Number} b amount to scale the vector by\n * @returns {vec3} out\n */\nexport function scale(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n return out;\n}\n\n/**\n * Adds two vec3's after scaling the second operand by a scalar value\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {Number} scale the amount to scale b by before adding\n * @returns {vec3} out\n */\nexport function scaleAndAdd(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n return out;\n}\n\n/**\n * Calculates the euclidian distance between two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} distance between a and b\n */\nexport function distance(a, b) {\n var x = b[0] - a[0];\n var y = b[1] - a[1];\n var z = b[2] - a[2];\n return Math.sqrt(x * x + y * y + z * z);\n}\n\n/**\n * Calculates the squared euclidian distance between two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} squared distance between a and b\n */\nexport function squaredDistance(a, b) {\n var x = b[0] - a[0];\n var y = b[1] - a[1];\n var z = b[2] - a[2];\n return x * x + y * y + z * z;\n}\n\n/**\n * Calculates the squared length of a vec3\n *\n * @param {ReadonlyVec3} a vector to calculate squared length of\n * @returns {Number} squared length of a\n */\nexport function squaredLength(a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n return x * x + y * y + z * z;\n}\n\n/**\n * Negates the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to negate\n * @returns {vec3} out\n */\nexport function negate(out, a) {\n out[0] = -a[0];\n out[1] = -a[1];\n out[2] = -a[2];\n return out;\n}\n\n/**\n * Returns the inverse of the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to invert\n * @returns {vec3} out\n */\nexport function inverse(out, a) {\n out[0] = 1.0 / a[0];\n out[1] = 1.0 / a[1];\n out[2] = 1.0 / a[2];\n return out;\n}\n\n/**\n * Normalize a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to normalize\n * @returns {vec3} out\n */\nexport function normalize(out, a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n var len = x * x + y * y + z * z;\n if (len > 0) {\n //TODO: evaluate use of glm_invsqrt here?\n len = 1 / Math.sqrt(len);\n }\n out[0] = a[0] * len;\n out[1] = a[1] * len;\n out[2] = a[2] * len;\n return out;\n}\n\n/**\n * Calculates the dot product of two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} dot product of a and b\n */\nexport function dot(a, b) {\n return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\n}\n\n/**\n * Computes the cross product of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\nexport function cross(out, a, b) {\n var ax = a[0],\n ay = a[1],\n az = a[2];\n var bx = b[0],\n by = b[1],\n bz = b[2];\n out[0] = ay * bz - az * by;\n out[1] = az * bx - ax * bz;\n out[2] = ax * by - ay * bx;\n return out;\n}\n\n/**\n * Performs a linear interpolation between two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\nexport function lerp(out, a, b, t) {\n var ax = a[0];\n var ay = a[1];\n var az = a[2];\n out[0] = ax + t * (b[0] - ax);\n out[1] = ay + t * (b[1] - ay);\n out[2] = az + t * (b[2] - az);\n return out;\n}\n\n/**\n * Performs a spherical linear interpolation between two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\nexport function slerp(out, a, b, t) {\n var angle = Math.acos(Math.min(Math.max(dot(a, b), -1), 1));\n var sinTotal = Math.sin(angle);\n var ratioA = Math.sin((1 - t) * angle) / sinTotal;\n var ratioB = Math.sin(t * angle) / sinTotal;\n out[0] = ratioA * a[0] + ratioB * b[0];\n out[1] = ratioA * a[1] + ratioB * b[1];\n out[2] = ratioA * a[2] + ratioB * b[2];\n return out;\n}\n\n/**\n * Performs a hermite interpolation with two control points\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {ReadonlyVec3} c the third operand\n * @param {ReadonlyVec3} d the fourth operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\nexport function hermite(out, a, b, c, d, t) {\n var factorTimes2 = t * t;\n var factor1 = factorTimes2 * (2 * t - 3) + 1;\n var factor2 = factorTimes2 * (t - 2) + t;\n var factor3 = factorTimes2 * (t - 1);\n var factor4 = factorTimes2 * (3 - 2 * t);\n out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n return out;\n}\n\n/**\n * Performs a bezier interpolation with two control points\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {ReadonlyVec3} c the third operand\n * @param {ReadonlyVec3} d the fourth operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\nexport function bezier(out, a, b, c, d, t) {\n var inverseFactor = 1 - t;\n var inverseFactorTimesTwo = inverseFactor * inverseFactor;\n var factorTimes2 = t * t;\n var factor1 = inverseFactorTimesTwo * inverseFactor;\n var factor2 = 3 * t * inverseFactorTimesTwo;\n var factor3 = 3 * factorTimes2 * inverseFactor;\n var factor4 = factorTimes2 * t;\n out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n return out;\n}\n\n/**\n * Generates a random vector with the given scale\n *\n * @param {vec3} out the receiving vector\n * @param {Number} [scale] Length of the resulting vector. If omitted, a unit vector will be returned\n * @returns {vec3} out\n */\nexport function random(out, scale) {\n scale = scale === undefined ? 1.0 : scale;\n var r = glMatrix.RANDOM() * 2.0 * Math.PI;\n var z = glMatrix.RANDOM() * 2.0 - 1.0;\n var zScale = Math.sqrt(1.0 - z * z) * scale;\n out[0] = Math.cos(r) * zScale;\n out[1] = Math.sin(r) * zScale;\n out[2] = z * scale;\n return out;\n}\n\n/**\n * Transforms the vec3 with a mat4.\n * 4th vector component is implicitly '1'\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyMat4} m matrix to transform with\n * @returns {vec3} out\n */\nexport function transformMat4(out, a, m) {\n var x = a[0],\n y = a[1],\n z = a[2];\n var w = m[3] * x + m[7] * y + m[11] * z + m[15];\n w = w || 1.0;\n out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;\n out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;\n out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;\n return out;\n}\n\n/**\n * Transforms the vec3 with a mat3.\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyMat3} m the 3x3 matrix to transform with\n * @returns {vec3} out\n */\nexport function transformMat3(out, a, m) {\n var x = a[0],\n y = a[1],\n z = a[2];\n out[0] = x * m[0] + y * m[3] + z * m[6];\n out[1] = x * m[1] + y * m[4] + z * m[7];\n out[2] = x * m[2] + y * m[5] + z * m[8];\n return out;\n}\n\n/**\n * Transforms the vec3 with a quat\n * Can also be used for dual quaternions. (Multiply it with the real part)\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyQuat} q normalized quaternion to transform with\n * @returns {vec3} out\n */\nexport function transformQuat(out, a, q) {\n // Fast Vector Rotation using Quaternions by Robert Eisele\n // https://raw.org/proof/vector-rotation-using-quaternions/\n\n var qx = q[0],\n qy = q[1],\n qz = q[2],\n qw = q[3];\n var vx = a[0],\n vy = a[1],\n vz = a[2];\n\n // t = q x v\n var tx = qy * vz - qz * vy;\n var ty = qz * vx - qx * vz;\n var tz = qx * vy - qy * vx;\n\n // t = 2t\n tx = tx + tx;\n ty = ty + ty;\n tz = tz + tz;\n\n // v + w t + q x t\n out[0] = vx + qw * tx + qy * tz - qz * ty;\n out[1] = vy + qw * ty + qz * tx - qx * tz;\n out[2] = vz + qw * tz + qx * ty - qy * tx;\n return out;\n}\n\n/**\n * Rotate a 3D vector around the x-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\nexport function rotateX(out, a, b, rad) {\n var p = [],\n r = [];\n //Translate point to the origin\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2];\n\n //perform rotation\n r[0] = p[0];\n r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);\n r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad);\n\n //translate to correct position\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n\n/**\n * Rotate a 3D vector around the y-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\nexport function rotateY(out, a, b, rad) {\n var p = [],\n r = [];\n //Translate point to the origin\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2];\n\n //perform rotation\n r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);\n r[1] = p[1];\n r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad);\n\n //translate to correct position\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n\n/**\n * Rotate a 3D vector around the z-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\nexport function rotateZ(out, a, b, rad) {\n var p = [],\n r = [];\n //Translate point to the origin\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2];\n\n //perform rotation\n r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);\n r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);\n r[2] = p[2];\n\n //translate to correct position\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n\n/**\n * Get the angle between two 3D vectors\n * @param {ReadonlyVec3} a The first operand\n * @param {ReadonlyVec3} b The second operand\n * @returns {Number} The angle in radians\n */\nexport function angle(a, b) {\n var ax = a[0],\n ay = a[1],\n az = a[2],\n bx = b[0],\n by = b[1],\n bz = b[2],\n mag = Math.sqrt((ax * ax + ay * ay + az * az) * (bx * bx + by * by + bz * bz)),\n cosine = mag && dot(a, b) / mag;\n return Math.acos(Math.min(Math.max(cosine, -1), 1));\n}\n\n/**\n * Set the components of a vec3 to zero\n *\n * @param {vec3} out the receiving vector\n * @returns {vec3} out\n */\nexport function zero(out) {\n out[0] = 0.0;\n out[1] = 0.0;\n out[2] = 0.0;\n return out;\n}\n\n/**\n * Returns a string representation of a vector\n *\n * @param {ReadonlyVec3} a vector to represent as a string\n * @returns {String} string representation of the vector\n */\nexport function str(a) {\n return \"vec3(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \")\";\n}\n\n/**\n * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyVec3} a The first vector.\n * @param {ReadonlyVec3} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\nexport function exactEquals(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];\n}\n\n/**\n * Returns whether or not the vectors have approximately the same elements in the same position.\n *\n * @param {ReadonlyVec3} a The first vector.\n * @param {ReadonlyVec3} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\nexport function equals(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2];\n return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2));\n}\n\n/**\n * Alias for {@link vec3.subtract}\n * @function\n */\nexport var sub = subtract;\n\n/**\n * Alias for {@link vec3.multiply}\n * @function\n */\nexport var mul = multiply;\n\n/**\n * Alias for {@link vec3.divide}\n * @function\n */\nexport var div = divide;\n\n/**\n * Alias for {@link vec3.distance}\n * @function\n */\nexport var dist = distance;\n\n/**\n * Alias for {@link vec3.squaredDistance}\n * @function\n */\nexport var sqrDist = squaredDistance;\n\n/**\n * Alias for {@link vec3.length}\n * @function\n */\nexport var len = length;\n\n/**\n * Alias for {@link vec3.squaredLength}\n * @function\n */\nexport var sqrLen = squaredLength;\n\n/**\n * Perform some operation over an array of vec3s.\n *\n * @param {Array} a the array of vectors to iterate over\n * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed\n * @param {Number} offset Number of elements to skip at the beginning of the array\n * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array\n * @param {Function} fn Function to call for each vector in the array\n * @param {Object} [arg] additional argument to pass to fn\n * @returns {Array} a\n * @function\n */\nexport var forEach = function () {\n var vec = create();\n return function (a, stride, offset, count, fn, arg) {\n var i, l;\n if (!stride) {\n stride = 3;\n }\n if (!offset) {\n offset = 0;\n }\n if (count) {\n l = Math.min(count * stride + offset, a.length);\n } else {\n l = a.length;\n }\n for (i = offset; i < l; i += stride) {\n vec[0] = a[i];\n vec[1] = a[i + 1];\n vec[2] = a[i + 2];\n fn(vec, vec, arg);\n a[i] = vec[0];\n a[i + 1] = vec[1];\n a[i + 2] = vec[2];\n }\n return a;\n };\n}();","/**\n * @module Camera\n * Interactive camera primitives for WebGPU scene navigation.\n *\n * This module defines the `Camera` class, which keeps the current eye,\n * look-at, and up vectors in sync with view and projection matrices. It also\n * exposes a one-shot helper for building view-projection matrices from\n * explicit parameters when a persistent camera instance is not needed.\n */\n\nimport { vec3, mat4 } from 'gl-matrix';\n\n/**\n * Initial camera state used to seed or reset a `Camera` instance.\n */\nexport interface CameraData {\n /** World-space up vector. */\n up: number[];\n /** Initial eye (camera) position in world space. */\n eye: number[];\n /** Point the camera looks at in world space. */\n lookAt: number[];\n}\n\n/**\n * Explicit parameters for building a single view-projection matrix.\n */\nexport interface ViewProjectionParams {\n /** Eye (camera) position in world space. */\n eye: [number, number, number];\n /** Point the camera looks at in world space. */\n lookAt: [number, number, number];\n /** World-space up vector. */\n up: [number, number, number];\n /** Vertical field of view in degrees. */\n fovDeg: number;\n /** Viewport aspect ratio (width / height). */\n aspect: number;\n /** Near clipping plane distance. */\n near: number;\n /** Far clipping plane distance. */\n far: number;\n}\n\n/**\n * Interactive 3-DOF camera for orbit-style navigation.\n *\n * The camera tracks world-space eye, look-at, and up vectors together with the\n * current viewport size. Call the navigation methods to adjust state, then\n * call {@link Camera.update} to rebuild the matrices. Projection uses\n * reversed-Z depth mapping for improved precision at distance.\n *\n * @example\n * const camera = new Camera();\n * camera.resize(width, height);\n * camera.zoom(-1, 0.5, 0.5);\n * camera.update();\n */\nexport class Camera {\n /** Eye (camera) position in world space. */\n protected wEye: vec3 = vec3.create();\n /** Look-at target in world space. */\n protected wLookAt: vec3 = vec3.create();\n /** Normalised direction vector from eye to look-at. */\n protected wEyeDir: vec3 = vec3.create();\n /** World-space up vector. */\n protected wUp: vec3 = vec3.create();\n /** Near clipping plane distance. */\n protected wNear: number = 0;\n /** Far clipping plane distance. */\n protected wFar: number = 0;\n /** Vertical field of view in radians. */\n protected fovy = (45 * Math.PI) / 180.0;\n /** Current projection matrix. */\n protected mProjectionMatrix: mat4 = mat4.create();\n /** Current view matrix. */\n protected mViewMatrix: mat4 = mat4.create();\n private viewportWidth: number = 0;\n private viewportHeight: number = 0;\n\n private static defaultParams: CameraData = {\n up: [0, 1, 0],\n eye: [0, 0, 10000],\n lookAt: [0, 0, 0],\n };\n\n /**\n * Creates a camera with the provided initial state.\n *\n * @param params - Initial camera position and orientation (defaults to `[0, 1, 0]` up, 10k units above origin).\n * @throws Never throws.\n * @example\n * const camera = new Camera();\n * const custom = new Camera({ eye: [0, 0, 500], lookAt: [0, 0, 0], up: [0, 1, 0] });\n */\n constructor(params: CameraData = Camera.defaultParams) {\n this.resetCamera(params.up, params.lookAt, params.eye);\n }\n\n /**\n * Resets the camera to a new position, orientation, and default projection.\n *\n * @param wUp - World-space up vector.\n * @param wLookAt - Point to look at in world space.\n * @param wEye - Eye position in world space.\n * @throws Never throws.\n * @example\n * camera.resetCamera([0, 1, 0], [100, 200, 0], [100, 200, 500]);\n * camera.update();\n */\n public resetCamera(wUp: number[], wLookAt: number[], wEye: number[]): void {\n this.fovy = (45 * Math.PI) / 180.0;\n this.mProjectionMatrix = mat4.create();\n this.mViewMatrix = mat4.create();\n this.wNear = 1;\n this.wFar = 5e5;\n this.wLookAt = vec3.fromValues(wLookAt[0], wLookAt[1], wLookAt[2]);\n this.wEye = vec3.fromValues(wEye[0], wEye[1], wEye[2]);\n this.updateEyeDirAndLen();\n this.wUp = vec3.fromValues(wUp[0], wUp[1], wUp[2]);\n }\n\n /**\n * Returns the current projection matrix.\n *\n * @returns The projection matrix in column-major `mat4`.\n * @throws Never throws.\n * @example\n * camera.update();\n * const proj = camera.getProjectionMatrix();\n */\n public getProjectionMatrix(): mat4 {\n return this.mProjectionMatrix;\n }\n\n /**\n * Returns the current view (model-view) matrix.\n *\n * @returns The view matrix in column-major `mat4`.\n * @throws Never throws.\n * @example\n * camera.update();\n * const view = camera.getModelViewMatrix();\n */\n public getModelViewMatrix(): mat4 {\n return this.mViewMatrix;\n }\n\n /**\n * Updates viewport size and recomputes matrices in one call.\n *\n * Pass drawable canvas pixel size, not CSS size.\n *\n * @param width - Viewport width in pixels.\n * @param height - Viewport height in pixels.\n * @throws Never throws.\n * @example\n * camera.resize(1920, 1080); // calls update() internally\n */\n public resize(width: number, height: number): void {\n this.viewportWidth = width;\n this.viewportHeight = height;\n this.update();\n }\n\n /**\n * Zooms the camera at the cursor position, preserving it in world space.\n *\n * @param delta - Normalized scroll delta (positive = zoom out, negative = zoom in).\n * @param x - Normalized cursor X position (0–1, left to right).\n * @param y - Normalized cursor Y position (0–1, bottom to top).\n * @throws Never throws.\n * @example\n * camera.zoom(-1, 0.5, 0.5); // zoom in at screen center\n * camera.update();\n */\n public zoom(delta: number, x: number, y: number): void {\n const zoomScale = Math.max(Math.abs(this.wEye[2]), 1) * 0.2;\n delta = -delta * zoomScale;\n const dir = this.screenCoordToWorldDir(x, y);\n vec3.scaleAndAdd(this.wEye, this.wEye, dir, delta);\n vec3.scaleAndAdd(this.wLookAt, this.wEye, this.wEyeDir, vec3.length(this.wEyeDir));\n }\n\n /**\n * Pans the camera in screen space, scaled by the current view distance.\n *\n * @param dx - Normalized horizontal drag delta (0–1).\n * @param dy - Normalized vertical drag delta (0–1).\n * @throws Never throws.\n * @example\n * camera.translate(0.1, 0); // pan right\n * camera.update();\n */\n public translate(dx: number, dy: number): void {\n const scale = this.wEye[2];\n const X = vec3.create();\n vec3.normalize(X, vec3.cross(X, this.wEyeDir, this.wUp));\n const D = vec3.add(\n vec3.create(),\n vec3.scale(vec3.create(), X, dx * scale),\n vec3.scale(vec3.create(), this.wUp, dy * scale),\n );\n vec3.add(this.wEye, this.wEye, D);\n vec3.scaleAndAdd(this.wLookAt, this.wEye, this.wEyeDir, vec3.length(this.wEyeDir));\n }\n\n /**\n * Rotates the camera around the world Z-axis (compass bearing).\n *\n * @param delta - Rotation angle in radians.\n * @throws Never throws.\n * @example\n * camera.yaw(Math.PI / 4); // rotate 45° clockwise\n * camera.update();\n */\n public yaw(delta: number): void {\n vec3.rotateZ(this.wEyeDir, this.wEyeDir, vec3.fromValues(0, 0, 0), delta);\n vec3.rotateZ(this.wUp, this.wUp, vec3.fromValues(0, 0, 0), delta);\n vec3.scaleAndAdd(this.wLookAt, this.wEye, this.wEyeDir, vec3.length(this.wEyeDir));\n }\n\n /**\n * Tilts the camera up or down (elevation angle).\n *\n * @param delta - Tilt angle in radians. Positive values tilt upward.\n * @throws Never throws.\n * @example\n * camera.pitch(-0.3); // tilt downward ~17°\n * camera.update();\n */\n public pitch(delta: number): void {\n delta = -delta;\n vec3.add(\n this.wEyeDir,\n vec3.scale(vec3.create(), this.wUp, Math.sin(delta)),\n vec3.scale(vec3.create(), this.wEyeDir, Math.cos(delta)),\n );\n vec3.normalize(this.wEyeDir, this.wEyeDir);\n vec3.scaleAndAdd(this.wLookAt, this.wEye, this.wEyeDir, vec3.length(this.wEyeDir));\n vec3.cross(this.wUp, vec3.cross(vec3.create(), this.wEyeDir, this.wUp), this.wEyeDir);\n vec3.normalize(this.wUp, this.wUp);\n }\n\n /**\n * Rebuilds view and projection matrices from the current camera state.\n *\n * Uses reversed-Z depth for improved precision at long range.\n *\n * @throws Never throws.\n * @example\n * camera.zoom(-1, 0.5, 0.5);\n * camera.update(); // rebuild matrices after navigation change\n */\n public update(): void {\n const aspect = this.viewportWidth / this.viewportHeight;\n mat4.lookAt(this.mViewMatrix, this.wEye, this.wLookAt, this.wUp);\n // Reversed-Z: swap near/far so near→1 and far→0 in NDC.\n // Combined with depthClearValue=0 and depthCompare='greater-equal' this\n // distributes float32 precision logarithmically, eliminating z-fighting\n // at distance without requiring an absurdly large far plane.\n mat4.perspectiveZO(this.mProjectionMatrix, this.fovy, aspect, this.wFar, this.wNear);\n }\n\n /**\n * Builds a stateless view-projection matrix from explicit parameters.\n *\n * @param p - Camera and projection parameters.\n * @returns Column-major `Float32Array` of length 16.\n * @throws Never throws.\n * @example\n * const vp = Camera.buildViewProjection({\n * eye: [0, 0, 500], lookAt: [0, 0, 0], up: [0, 1, 0],\n * fovDeg: 45, aspect: 16/9, near: 0.1, far: 10000,\n * });\n */\n public static buildViewProjection(p: ViewProjectionParams): Float32Array {\n const view = mat4.lookAt(mat4.create(), p.eye, p.lookAt, p.up);\n const proj = mat4.perspectiveZO(mat4.create(), p.fovDeg * (Math.PI / 180), p.aspect, p.near, p.far);\n return new Float32Array(mat4.mul(mat4.create(), proj, view));\n }\n\n /**\n * Converts a normalized screen coordinate to a world-space direction ray.\n *\n * @param x - Normalized screen X (0–1, left to right).\n * @param y - Normalized screen Y (0–1, bottom to top).\n * @returns Normalized direction vector in world space.\n * @throws Never throws.\n */\n protected screenCoordToWorldDir(x: number, y: number): vec3 {\n const wRight = vec3.create();\n vec3.normalize(wRight, vec3.cross(wRight, this.wEyeDir, this.wUp));\n const upOffset = vec3.scale(vec3.create(), this.wUp, Math.tan(this.fovy / 2) * (y - 0.5) * 2);\n const aspect = this.viewportWidth / this.viewportHeight;\n const rightOffset = vec3.scale(vec3.create(), wRight, Math.tan(this.fovy / 2) * (x - 0.5) * 2 * aspect);\n const offset = vec3.add(vec3.create(), upOffset, rightOffset);\n const dir = vec3.add(vec3.create(), this.wEyeDir, offset);\n vec3.normalize(dir, dir);\n return dir;\n }\n\n /**\n * Recomputes the normalized eye direction from current eye and look-at.\n *\n * @throws Never throws.\n */\n protected updateEyeDirAndLen(): void {\n this.wEyeDir = vec3.create();\n vec3.sub(this.wEyeDir, this.wLookAt, this.wEye);\n vec3.normalize(this.wEyeDir, this.wEyeDir);\n }\n}\n","/**\n * @module LayerUtils\n * Shared helpers for the toolkit's layer taxonomy.\n *\n * This module centralizes the canonical `LayerType` guard and the GeoJSON\n * geometry classification used by layer-loading code. It keeps layer identity\n * checks and geometry-to-layer inference consistent across packages that share\n * the same taxonomy.\n */\nimport type { Geometry } from 'geojson';\n\nimport type { LayerType } from './types-layer';\n\n/**\n * Type guard checking whether a string is a supported shared layer type.\n *\n * @param value Candidate layer identifier to validate.\n * @returns `true` when `value` is a recognized `LayerType`, narrowing the type.\n * @throws Never throws.\n * @example\n * if (isLayerType(userInput)) {\n * // userInput is now typed as LayerType\n * }\n */\nexport function isLayerType(value: string): value is LayerType {\n return value === 'surface'\n || value === 'water'\n || value === 'parks'\n || value === 'roads'\n || value === 'buildings'\n || value === 'points'\n || value === 'polygons'\n || value === 'polylines'\n || value === 'raster';\n}\n\n/**\n * Maps a GeoJSON geometry type to the corresponding shared layer family.\n *\n * @param geometryType GeoJSON geometry type to classify.\n * @returns One of `points`, `polylines`, or `polygons`.\n * @throws Never throws.\n * @example\n * mapGeometryTypeToLayerType('Polygon'); // 'polygons'\n * mapGeometryTypeToLayerType('Point'); // 'points'\n */\nexport function mapGeometryTypeToLayerType(\n geometryType: Geometry['type'],\n): Extract<LayerType, 'points' | 'polygons' | 'polylines'> {\n switch (geometryType) {\n case 'Point':\n case 'MultiPoint':\n return 'points';\n case 'LineString':\n case 'MultiLineString':\n return 'polylines';\n case 'Polygon':\n case 'MultiPolygon':\n case 'GeometryCollection':\n return 'polygons';\n }\n}\n","import { BoundingBox } from '../../../shared/interfaces';\n\nexport const LOAD_FEATURE_COLLECTION_QUERY = (geojsonFileUrl: string, featureCollectionTableName: string, workspace: string) => {\n const qualifiedTableName = `${workspace}.${featureCollectionTableName}`;\n return `\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT * FROM read_json('${geojsonFileUrl}', maximum_object_size=104857600);\n `;\n};\n\n// TODO: update this name columns, its not linestring (i just do not want to break pattern right now)\nexport const LOAD_LAYER_FROM_FEATURE_COLLECTION_QUERY = (\n featureCollectionTableName: string,\n outputTableName: string,\n coordinateFormat: string,\n workspace: string,\n boundingBox?: BoundingBox,\n) => {\n const qualifiedFeatureCollectionTableName = `${workspace}.${featureCollectionTableName}`;\n const qualifiedOutputTableName = `${workspace}.${outputTableName}`;\n \n const geometryTransform = `ST_Transform(\n ST_GeomFromGeoJSON(JSON(feature.geometry)),\n 'EPSG:4326',\n '${coordinateFormat}',\n always_xy := true\n )`;\n\n const geometrySelect = boundingBox\n ? `ST_Intersection(\n ${geometryTransform},\n ST_MakeEnvelope(${boundingBox.minLon}, ${boundingBox.minLat}, ${boundingBox.maxLon}, ${boundingBox.maxLat})\n )`\n : geometryTransform;\n\n return `\n CREATE OR REPLACE TABLE ${qualifiedOutputTableName} AS\n SELECT\n row_number() OVER () AS id,\n ${geometrySelect} AS geometry,\n feature.properties AS properties\n FROM (\n SELECT UNNEST(features) AS feature\n FROM ${qualifiedFeatureCollectionTableName}\n )\n ${boundingBox ? 'WHERE ST_Intersects(' + geometryTransform + ', ST_MakeEnvelope(' + boundingBox.minLon + ', ' + boundingBox.minLat + ', ' + boundingBox.maxLon + ', ' + boundingBox.maxLat + '))' : ''};\n\n DROP TABLE ${qualifiedFeatureCollectionTableName};\n\n DESCRIBE ${qualifiedOutputTableName};\n `;\n};\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { CustomLayerTable } from '../../../shared/interfaces';\nimport { LoadCustomLayerParams } from './interfaces';\nimport { DEFALT_COORDINATE_FORMAT } from '../../../shared/consts';\nimport { LOAD_FEATURE_COLLECTION_QUERY, LOAD_LAYER_FROM_FEATURE_COLLECTION_QUERY } from './queries';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport { FeatureCollection } from 'geojson';\nimport { BoundingBox } from '../../../shared/interfaces';\nimport { mapGeometryTypeToLayerType } from 'autk-core';\n\n/**\n * Loads a GeoJSON FeatureCollection as a spatial layer table.\n */\nexport class LoadCustomLayerUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n }\n\n async exec({\n geojsonFileUrl,\n geojsonObject,\n outputTableName,\n coordinateFormat = DEFALT_COORDINATE_FORMAT,\n boundingBox,\n workspace = 'main',\n layerType,\n }: LoadCustomLayerParams): Promise<CustomLayerTable> {\n if (!geojsonFileUrl && !geojsonObject) {\n throw new Error('Either geojsonFileUrl or geojsonObject must be provided');\n }\n if (geojsonFileUrl && geojsonObject) {\n throw new Error('Cannot provide both geojsonFileUrl and geojsonObject. Please provide only one.');\n }\n\n let geojson: FeatureCollection;\n\n if (geojsonFileUrl) {\n const response = await fetch(geojsonFileUrl);\n if (!response.ok) {\n throw new Error(`HTTP error! Error to load ${geojsonFileUrl}! Status: ${response.status}`);\n }\n geojson = await response.json();\n } else {\n geojson = geojsonObject!;\n }\n\n if (geojson.type !== 'FeatureCollection') {\n throw new Error(`Invalid GeoJSON type! Just accepting FeatureCollection for now!`);\n }\n\n // Extract geometry type from the first feature\n if (!geojson.features || geojson.features.length === 0) {\n throw new Error('FeatureCollection is empty - no features found');\n }\n\n const firstFeature = geojson.features[0];\n if (!firstFeature.geometry || !firstFeature.geometry.type) {\n throw new Error('First feature has no geometry or geometry type');\n }\n\n const geometryType = layerType ?? mapGeometryTypeToLayerType(firstFeature.geometry.type);\n\n const describeTableResponse = await this.createTableFromFeatureCollection(\n geojson,\n outputTableName,\n coordinateFormat,\n workspace,\n boundingBox,\n );\n\n return {\n source: 'geojson',\n type: geometryType,\n columns: getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray()),\n name: outputTableName,\n };\n }\n\n private async createTableFromFeatureCollection(\n geojson: FeatureCollection,\n outputTableName: string,\n coordinateFormat: string,\n workspace: string,\n boundingBox?: BoundingBox,\n ) {\n // Create temporary file with GeoJSON data\n const fileName = `temp_geojson_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.json`;\n\n // Register the GeoJSON as a temporary file in DuckDB\n await this.db.registerFileText(fileName, JSON.stringify(geojson));\n\n // Create feature collection table from the temporary file\n const featureCollectionQuery = LOAD_FEATURE_COLLECTION_QUERY(fileName, `${outputTableName}_feature_collection`, workspace);\n await this.conn.query(featureCollectionQuery);\n\n // Create the final layer table\n const queryLayer = LOAD_LAYER_FROM_FEATURE_COLLECTION_QUERY(\n `${outputTableName}_feature_collection`,\n outputTableName,\n coordinateFormat,\n workspace,\n boundingBox,\n );\n\n await this.db.dropFile(fileName);\n\n return await this.conn.query(queryLayer);\n }\n}\n","/** Custom error types for spatial join operations. */\n\nexport class TableNotFoundError extends Error {\n constructor(tableName: string) {\n super(`Table ${tableName} not found`);\n this.name = 'TableNotFoundError';\n }\n}\n\nexport class GeometryColumnNotFoundError extends Error {\n constructor(tableName: string) {\n super(`Table ${tableName} does not have a geometry column`);\n this.name = 'GeometryColumnNotFoundError';\n }\n}\n","import { Table } from '../../../shared/interfaces';\nimport { isLayerType } from 'autk-core';\n\ntype InternalColumn = { table: Table; column: string; aggregateFn?: string; aggregateFnResultColumnName?: string; normalize?: boolean };\n\ninterface Params {\n tableRoot: Table;\n tableJoin: Table;\n geometricColumnRoot: string;\n geometricColumnJoin: string;\n joinType: string;\n spatialPredicate: string;\n nearDistance?: number;\n nearUseCentroid?: boolean;\n groupBy: { selectColumns: Array<InternalColumn> } | null;\n outputTableName: string;\n}\n\n// Alias used for the pre-filtered join table CTE in NEAR queries\nconst NEAR_CTE_ALIAS = 'csv_candidates';\n\nexport const SPATIAL_JOIN_QUERY = (params: Params) => {\n const isNear = params.spatialPredicate === 'NEAR';\n\n // For NEAR queries we reference the CTE alias instead of the real table name\n // in both the SELECT and JOIN clauses, so the optimizer sees a pre-filtered dataset.\n const effectiveJoinTable: Table = isNear\n ? { ...params.tableJoin, name: NEAR_CTE_ALIAS }\n : params.tableJoin;\n\n // Also remap any groupBy column references that point to the join table so that\n // generated expressions like COUNT(noise.\"col\") become COUNT(csv_candidates.\"col\").\n const effectiveGroupBy = isNear && params.groupBy\n ? {\n selectColumns: params.groupBy.selectColumns.map((col) => ({\n ...col,\n // Preserve the original table name as the result column name so the generated\n // JSON key stays e.g. 'noise' instead of falling back to 'csv_candidates'.\n aggregateFnResultColumnName: col.aggregateFnResultColumnName ?? (col.table.name === params.tableJoin.name ? col.table.name : undefined),\n table: col.table.name === params.tableJoin.name ? effectiveJoinTable : col.table,\n })),\n }\n : params.groupBy;\n\n const selectString = getSelectString({\n tableRoot: params.tableRoot,\n tableJoin: effectiveJoinTable,\n geometricColumnRoot: params.geometricColumnRoot,\n geometricColumnJoin: params.geometricColumnJoin,\n nearUseCentroid: params.nearUseCentroid,\n groupBy: effectiveGroupBy,\n });\n\n const joinString = getJoinString({\n spatialPredicate: params.spatialPredicate,\n joinType: params.joinType,\n tableJoin: effectiveJoinTable,\n tableRoot: params.tableRoot,\n geometricColumnRoot: params.geometricColumnRoot,\n geometricColumnJoin: params.geometricColumnJoin,\n nearDistance: params.nearDistance,\n nearUseCentroid: params.nearUseCentroid,\n });\n\n const groupByString = getGroupByString(params.tableRoot);\n\n // For NEAR queries: a CTE that pre-filters the join table using an ST_Intersects\n // WHERE clause so the R-tree index fires. Stored separately so it can be combined\n // with a normalization CTE when needed.\n const rootGeomExpr = (col: string) =>\n params.nearUseCentroid ? `ST_Centroid(\"${col}\")` : `\"${col}\"`;\n\n const nearCtePart = isNear\n ? `${NEAR_CTE_ALIAS} AS (\n SELECT * FROM ${params.tableJoin.name}\n WHERE ST_Intersects(\n (SELECT ST_Union_Agg(ST_Expand(${rootGeomExpr(params.geometricColumnRoot)}, ${params.nearDistance})) FROM ${params.tableRoot.name}),\n ${params.tableJoin.name}.\"${params.geometricColumnJoin}\"\n )\n )`\n : null;\n\n const innerQuery = `\n ${selectString}\n FROM ${params.tableRoot.name}\n ${joinString}\n ${params.groupBy ? groupByString : ''}\n `;\n\n const normalizedColumns = effectiveGroupBy?.selectColumns.filter((col) => col.normalize) ?? [];\n\n if (normalizedColumns.length > 0) {\n const cteParts = [...(nearCtePart ? [nearCtePart] : []), `sjoin_base AS (${innerQuery})`];\n const normPatch = buildNormalizationMergePatch(normalizedColumns);\n return `\n WITH ${cteParts.join(',\\n')}\n SELECT * REPLACE (${normPatch} AS properties)\n FROM sjoin_base;\n `;\n }\n\n return `\n ${nearCtePart ? `WITH ${nearCtePart}` : ''}\n ${innerQuery};\n `;\n};\n\n/* Select Logic */\nfunction getSelectString(params: {\n tableRoot: Table;\n tableJoin: Table;\n geometricColumnRoot: string;\n geometricColumnJoin: string;\n nearUseCentroid?: boolean;\n groupBy: { selectColumns: Array<InternalColumn> } | null;\n}) {\n if (params.groupBy) {\n const { aggregatesByFunction, nonAggregateColumns } = groupColumnsByAggregateFunction(params.groupBy.selectColumns);\n const sjoinObjectSql = buildSjoinObject(aggregatesByFunction, nonAggregateColumns, {\n tableRoot: params.tableRoot,\n tableJoin: params.tableJoin,\n geometricColumnRoot: params.geometricColumnRoot,\n geometricColumnJoin: params.geometricColumnJoin,\n nearUseCentroid: params.nearUseCentroid,\n });\n\n // Get all additional columns from tableRoot (excluding geometry and properties)\n const additionalColumns = params.tableRoot.columns\n .filter((col) => col.name !== 'geometry' && col.name !== 'properties')\n .map((col) => `${params.tableRoot.name}.${col.name}`);\n\n const additionalColumnsStr =\n additionalColumns.length > 0 ? `,\\n ${additionalColumns.join(',\\n ')}` : '';\n\n return `\n SELECT \n ${params.tableRoot.name}.geometry,\n json_merge_patch(\n COALESCE(CAST(\"${params.tableRoot.name}\".properties AS JSON), '{}'::JSON),\n json_object(\n 'sjoin', json_object(\n ${sjoinObjectSql}\n )\n )\n ) AS properties${additionalColumnsStr}\n `;\n }\n\n return buildSimpleJoinSelect(params.tableRoot, params.tableJoin, params.geometricColumnJoin);\n}\n\nfunction groupColumnsByAggregateFunction(selectColumns: Array<InternalColumn>) {\n const aggregatesByFunction: Record<\n string,\n Array<{ table: Table; column: string; aggregateFnResultColumnName?: string }>\n > = {};\n const nonAggregateColumns: Array<{ table: Table; column: string; aggregateFnResultColumnName?: string }> = [];\n\n selectColumns.forEach((column) => {\n if (column.aggregateFn) {\n const funcName = column.aggregateFn.toLowerCase();\n if (!aggregatesByFunction[funcName]) {\n aggregatesByFunction[funcName] = [];\n }\n aggregatesByFunction[funcName].push({\n table: column.table,\n column: column.column,\n aggregateFnResultColumnName: column.aggregateFnResultColumnName,\n });\n } else {\n nonAggregateColumns.push({\n table: column.table,\n column: column.column,\n aggregateFnResultColumnName: column.aggregateFnResultColumnName,\n });\n }\n });\n\n return { aggregatesByFunction, nonAggregateColumns };\n}\n\nfunction buildSjoinObject(\n aggregatesByFunction: Record<string, Array<{ table: Table; column: string; aggregateFnResultColumnName?: string }>>,\n nonAggregateColumns: Array<{ table: Table; column: string; aggregateFnResultColumnName?: string }>,\n geomContext: { tableRoot: Table; tableJoin: Table; geometricColumnRoot: string; geometricColumnJoin: string; nearUseCentroid?: boolean },\n): string {\n const sjoinParts: string[] = [];\n\n // Handle aggregate functions\n Object.entries(aggregatesByFunction).forEach(([funcName, columns]) => {\n if (funcName === 'count') {\n sjoinParts.push(buildCountExpression(columns[0]));\n } else if (funcName === 'weighted') {\n sjoinParts.push(buildWeightedExpression(columns[0], geomContext));\n } else if (funcName === 'collect') {\n sjoinParts.push(buildCollectExpression(columns[0]));\n } else {\n sjoinParts.push(buildNestedFunctionExpression(funcName, columns));\n }\n });\n\n // Handle non-aggregate columns\n if (nonAggregateColumns.length > 0) {\n sjoinParts.push(buildNonAggregateColumns(nonAggregateColumns));\n }\n\n return sjoinParts.join(', ');\n}\n\nfunction buildWeightedExpression(\n column: { table: Table; column: string; aggregateFnResultColumnName?: string },\n geomContext: { tableRoot: Table; tableJoin: Table; geometricColumnRoot: string; geometricColumnJoin: string; nearUseCentroid?: boolean },\n): string {\n const { tableRoot, tableJoin, geometricColumnRoot, geometricColumnJoin, nearUseCentroid } = geomContext;\n const rootGeom = nearUseCentroid\n ? `ST_Centroid(${tableRoot.name}.\"${geometricColumnRoot}\")`\n : `${tableRoot.name}.\"${geometricColumnRoot}\"`;\n const joinGeom = nearUseCentroid\n ? `ST_Centroid(${tableJoin.name}.\"${geometricColumnJoin}\")`\n : `${tableJoin.name}.\"${geometricColumnJoin}\"`;\n const columnName = column.aggregateFnResultColumnName ?? column.table.name;\n return `'weighted', json_object('${columnName}', SUM(1.0 / (ST_Distance(${rootGeom}, ${joinGeom}) + 1.0)))`;\n}\n\nfunction buildCollectExpression(column: { table: Table; column: string; aggregateFnResultColumnName?: string }): string {\n const columnName = column.aggregateFnResultColumnName ?? column.table.name;\n const valueExpression = generateValueExpression(column.table, column.column, 'COLLECT');\n return `'collect', json_object('${columnName}', ${valueExpression})`;\n}\n\nfunction buildCollectColumnExpression(table: Table, columnName: string): string {\n if (table.source === 'geotiff') return `${table.name}.properties.${columnName}`;\n if (isLayerType(table.type)) return buildJsonExtract(table.name, columnName);\n return `${table.name}.\"${columnName}\"`;\n}\n\nfunction buildCountExpression(column: { table: Table; column: string; aggregateFnResultColumnName?: string }): string {\n const valueExpression = generateValueExpression(column.table, column.column, 'COUNT');\n const columnName = column.aggregateFnResultColumnName || column.table.name;\n return `'count', json_object('${columnName}', ${valueExpression})`;\n}\n\nfunction buildNestedFunctionExpression(\n funcName: string,\n columns: Array<{ table: Table; column: string; aggregateFnResultColumnName?: string }>,\n): string {\n const functionAttributes = columns\n .map((column) => {\n const valueExpression = generateValueExpression(column.table, column.column, funcName.toUpperCase());\n const columnName = column.aggregateFnResultColumnName || `${column.table.name}.${column.column}`;\n return `'${columnName}', ${valueExpression}`;\n })\n .join(', ');\n\n return `'${funcName}', json_object(${functionAttributes})`;\n}\n\nfunction buildNonAggregateColumns(\n nonAggregateColumns: Array<{ table: Table; column: string; aggregateFnResultColumnName?: string }>,\n): string {\n return nonAggregateColumns\n .map((column) => {\n const valueExpression = column.table.source === 'geotiff'\n ? `${column.table.name}.properties.${column.column}`\n : isLayerType(column.table.type)\n ? buildJsonExtract(column.table.name, column.column)\n : `${column.table.name}.\"${column.column}\"`;\n const columnName = column.aggregateFnResultColumnName || column.column;\n return `'${columnName}', ${valueExpression}`;\n })\n .join(', ');\n}\n\nfunction generateValueExpression(table: Table, columnName: string, aggregateFunction: string): string {\n if (aggregateFunction === 'COLLECT') {\n // '*' collects the entire properties object of the join row; otherwise collects a specific column.\n if (columnName === '*') {\n if (table.source === 'geotiff') return `json_group_array(${table.name}.properties)`;\n if (isLayerType(table.type)) return `json_group_array(CAST(${table.name}.properties AS JSON))`;\n // CSV/JSON tables: build a json_object from all non-geometry columns\n const cols = table.columns\n .filter(c => c.name !== 'geometry')\n .map(c => `'${c.name}', ${table.name}.\"${c.name}\"`)\n .join(', ');\n return `json_group_array(json_object(${cols}))`;\n }\n // Single-column collect: wrap in json_object so consumers always get an array of objects.\n const colExpr = buildCollectColumnExpression(table, columnName);\n return `json_group_array(json_object('${columnName}', ${colExpr}))`;\n }\n if (table.source === 'geotiff') {\n return `${aggregateFunction}(${table.name}.properties.${columnName})`;\n }\n if (isLayerType(table.type)) {\n const extract = buildJsonExtract(table.name, columnName);\n const castExpr = aggregateFunction === 'COUNT' ? extract : `CAST(${extract} AS DOUBLE)`;\n return `${aggregateFunction}(${castExpr})`;\n }\n return `${aggregateFunction}(${table.name}.\"${columnName}\")`;\n}\n\n/**\n * Builds a DuckDB JSON/STRUCT extraction expression for a (possibly nested) column path.\n * Supports dot-notation paths like 'compute.skyViewFactor'.\n * Uses chained -> / ->> operators which work for both DuckDB STRUCT and JSON column types.\n */\nfunction buildJsonExtract(tableName: string, columnPath: string): string {\n const parts = columnPath.split('.');\n const last = parts.pop()!;\n const chain = parts.reduce((acc, p) => `${acc}->'${p}'`, `${tableName}.properties`);\n return `${chain}->>'${last}'`;\n}\n\nfunction buildNormalizationMergePatch(normalizedColumns: Array<InternalColumn>): string {\n // Group columns by aggregateFn so we can build the nested sjoin JSON structure\n const byAggFn: Record<string, Array<{ colKey: string; jsonPath: string }>> = {};\n\n for (const col of normalizedColumns) {\n const funcName = col.aggregateFn?.toLowerCase() ?? 'value';\n const colKey =\n funcName === 'count'\n ? (col.aggregateFnResultColumnName ?? col.table.name)\n : (col.aggregateFnResultColumnName ?? `${col.table.name}.${col.column}`);\n const jsonPath = `$.sjoin.${funcName}.${colKey}`;\n\n if (!byAggFn[funcName]) byAggFn[funcName] = [];\n byAggFn[funcName].push({ colKey, jsonPath });\n }\n\n const aggFnParts = Object.entries(byAggFn)\n .map(([funcName, cols]) => {\n const colParts = cols\n .map(({ colKey, jsonPath }) => {\n const rawVal = `COALESCE(json_extract(properties, '${jsonPath}')::DOUBLE, 0)`;\n const normExpr =\n `(${rawVal} - MIN(${rawVal}) OVER ()) / ` +\n `NULLIF(MAX(${rawVal}) OVER () - MIN(${rawVal}) OVER (), 0)`;\n return `'${colKey}_norm', ${normExpr}`;\n })\n .join(',\\n ');\n return `'${funcName}', json_object(${colParts})`;\n })\n .join(',\\n ');\n\n return `json_merge_patch(\n properties,\n json_object('sjoin', json_object(\n ${aggFnParts}\n ))\n )`;\n}\n\nfunction buildSimpleJoinSelect(tableRoot: Table, tableJoin: Table, geometricColumnJoin: string): string {\n // Get all additional columns from tableRoot (excluding geometry and properties)\n const additionalColumns = tableRoot.columns\n .filter((col) => col.name !== 'geometry' && col.name !== 'properties')\n .map((col) => `${tableRoot.name}.${col.name}`);\n\n const additionalColumnsStr =\n additionalColumns.length > 0 ? `,\\n ${additionalColumns.join(',\\n ')}` : '';\n\n // When the join table is a layer type (OSM / GeoJSON), its data lives in a 'properties'\n // JSON column. Using json_object(tableJoin.properties) would fail because json_object()\n // requires an even number of key-value pair arguments. Instead, merge the JSON blob directly.\n const joinPropertiesExpr = isLayerType(tableJoin.type)\n ? `COALESCE(CAST(${tableJoin.name}.properties AS JSON), '{}'::JSON)`\n : `json_object(${tableJoin.columns\n .filter((column) => column.name !== geometricColumnJoin)\n .map((column) => `'${column.name}', ${tableJoin.name}.\"${column.name}\"`)\n .join(', ')})`;\n\n return `\n SELECT \n ${tableRoot.name}.geometry,\n json_merge_patch(\n json_object('sjoin', ${joinPropertiesExpr}),\n COALESCE(CAST(\"${tableRoot.name}\".properties AS JSON), '{}'::JSON)\n ) AS properties${additionalColumnsStr}\n `;\n}\n\n\n/* Join Logic */\nfunction getJoinString({\n spatialPredicate,\n joinType,\n tableJoin,\n tableRoot,\n geometricColumnRoot,\n geometricColumnJoin,\n nearDistance,\n nearUseCentroid,\n}: {\n spatialPredicate: string;\n joinType: string;\n tableJoin: Table;\n tableRoot: Table;\n geometricColumnRoot: string;\n geometricColumnJoin: string;\n nearDistance?: number;\n nearUseCentroid?: boolean;\n}) {\n if (spatialPredicate === 'NEAR') {\n const rootExpr = nearUseCentroid\n ? `ST_Centroid(${tableRoot.name}.\"${geometricColumnRoot}\")`\n : `${tableRoot.name}.\"${geometricColumnRoot}\"`;\n const joinExpr = nearUseCentroid\n ? `ST_Centroid(${tableJoin.name}.\"${geometricColumnJoin}\")`\n : `${tableJoin.name}.\"${geometricColumnJoin}\"`;\n return `${joinType || ''} JOIN ${tableJoin.name} ON ST_Distance(${rootExpr}, ${joinExpr}) <= ${nearDistance}`;\n }\n\n return `${joinType || ''} JOIN ${tableJoin.name} ON ST_Intersects( ${tableRoot.name}.\"${geometricColumnRoot}\", ${tableJoin.name}.\"${geometricColumnJoin}\")`;\n}\n\n/* Group By Logic */\nfunction getGroupByString(tableRoot: Table) {\n // Get all additional columns from tableRoot (excluding geometry and properties)\n const additionalColumns = tableRoot.columns\n .filter((col) => col.name !== 'geometry' && col.name !== 'properties')\n .map((col) => `${tableRoot.name}.${col.name}`);\n\n const allGroupByColumns = [`${tableRoot.name}.geometry`, `${tableRoot.name}.properties`, ...additionalColumns];\n\n return `\n GROUP BY ${allGroupByColumns.join(', ')}\n `;\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { SpatialQueryParams } from './interfaces';\nimport { Table } from '../../../shared/interfaces';\nimport { GeometryColumnNotFoundError, TableNotFoundError } from './errors';\nimport { SPATIAL_JOIN_QUERY } from './queries';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\n\n/**\n * Performs a spatial join between two tables, with optional aggregation.\n */\nexport class SpatialJoinUseCase {\n private conn: AsyncDuckDBConnection;\n\n constructor(conn: AsyncDuckDBConnection) {\n this.conn = conn;\n }\n\n async exec(params: SpatialQueryParams, tables: Table[]): Promise<{ created: boolean; table: Table }> {\n const tableRoot = tables.find((table) => table.name === params.tableRootName);\n if (!tableRoot) throw new TableNotFoundError(params.tableRootName);\n\n const tableJoin = tables.find((table) => table.name === params.tableJoinName);\n if (!tableJoin) throw new TableNotFoundError(params.tableJoinName);\n\n const geometricColumnRoot = this.getGeometryColumnName(tableRoot);\n if (!geometricColumnRoot) throw new GeometryColumnNotFoundError(tableRoot.name);\n\n const geometricColumnJoin = this.getGeometryColumnName(tableJoin);\n if (!geometricColumnJoin) throw new GeometryColumnNotFoundError(tableJoin.name);\n\n const joinType = params.joinType || 'INNER';\n const spatialPredicate = params.spatialPredicate || 'INTERSECT';\n\n let nearUseCentroid = params.nearUseCentroid;\n if (nearUseCentroid === undefined && spatialPredicate === 'NEAR') {\n nearUseCentroid = await this.isPolygonTable(tableRoot.name, geometricColumnRoot);\n }\n\n const outputTableName = (params.output.type === 'CREATE_NEW' ? params.output.tableName : tableRoot.name) as string;\n const query = SPATIAL_JOIN_QUERY({\n tableRoot,\n tableJoin,\n geometricColumnRoot,\n geometricColumnJoin,\n joinType,\n spatialPredicate,\n groupBy: this.addTablesToGroupBy(params.groupBy, tables),\n nearDistance: params.nearDistance,\n nearUseCentroid,\n outputTableName,\n });\n\n // console.log({ query });\n const tableDescribeResponse = await this.conn.query(`\n CREATE OR REPLACE TABLE ${outputTableName} AS\n ${query}\n\n DESCRIBE ${outputTableName};\n `);\n\n return {\n table: {\n source: tableRoot.source,\n type: tableRoot.type,\n name: outputTableName,\n columns: getColumnsFromDuckDbTableDescribe(tableDescribeResponse.toArray()),\n } as Table,\n created: params.output.type === 'CREATE_NEW',\n };\n }\n\n /**\n * Gets the appropriate geometry column name for a table.\n * For building tables, prioritizes 'agg_geometry' if available, otherwise falls back to 'geometry'.\n * For other tables, returns the first geometry column found.\n */\n private async isPolygonTable(tableName: string, geomColumn: string): Promise<boolean> {\n const result = await this.conn.query(\n `SELECT ST_GeometryType(\"${geomColumn}\") AS geom_type FROM ${tableName} WHERE \"${geomColumn}\" IS NOT NULL LIMIT 1`\n );\n const rows = result.toArray();\n if (rows.length === 0) return false;\n const geomType = String(rows[0].geom_type).toUpperCase();\n return geomType === 'POLYGON' || geomType === 'MULTIPOLYGON';\n }\n\n private getGeometryColumnName(table: Table): string | undefined {\n if (table.source === 'osm' && table.type === 'buildings') {\n const aggGeometryColumn = table.columns.find(\n (column) => column.name === 'agg_geometry' && column.type === 'GEOMETRY',\n );\n\n if (aggGeometryColumn) return aggGeometryColumn.name;\n }\n\n // Default behavior: return first geometry column found\n return table.columns.find((column) => column.type === 'GEOMETRY')?.name;\n }\n\n private addTablesToGroupBy(\n groupBy: SpatialQueryParams['groupBy'],\n tables: Table[],\n ): {\n selectColumns: Array<{ table: Table; column: string; aggregateFn?: string; aggregateFnResultColumnName?: string; normalize?: boolean }>;\n } | null {\n if (!groupBy) return null;\n\n return {\n selectColumns: groupBy.selectColumns.map((column) => {\n const table = tables.find((table) => table.name === column.tableName);\n if (!table) throw new TableNotFoundError(column.tableName);\n\n return {\n table,\n column: column.column,\n aggregateFn: column.aggregateFn,\n aggregateFnResultColumnName: column.aggregateFnResultColumnName,\n normalize: column.normalize,\n };\n }),\n };\n }\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nexport interface DropTableParams {\n tableName: string;\n workspace?: string;\n}\n\nexport interface DropTableResult {\n success: boolean;\n message: string;\n}\n\n/**\n * Drops a table from the current workspace.\n */\nexport class DropTableUseCase {\n constructor(private conn: AsyncDuckDBConnection) {}\n\n /**\n * Drops the specified table, returning success/failure rather than throwing.\n *\n * @param params.tableName Name of the table to drop.\n * @param params.workspace Optional workspace name (defaults to `main`).\n * @returns Result indicating success or failure with a message.\n * @throws Never throws. Errors are caught and returned in the result.\n */\n async exec(params: DropTableParams): Promise<DropTableResult> {\n try {\n const workspace = params.workspace || 'main';\n const qualifiedTableName = `${workspace}.${params.tableName}`;\n await this.conn.query(`DROP TABLE IF EXISTS ${qualifiedTableName};`);\n return {\n success: true,\n message: `Table ${params.tableName} dropped successfully`,\n };\n } catch (error) {\n return {\n success: false,\n message: `Error dropping table ${params.tableName}: ${error}`,\n };\n }\n }\n}\n","type Params = {\n boundingBox: {\n minLat: number;\n maxLat: number;\n minLon: number;\n maxLon: number;\n };\n coordinateFormat: string;\n};\n\nexport const TRANSFORM_BOUNDING_BOX_COORDINATES_QUERY = ({ boundingBox, coordinateFormat }: Params) => {\n return `\n WITH transformed_bounds AS (\n SELECT\n ST_Transform(ST_Point(${boundingBox.minLon}, ${boundingBox.minLat}), 'EPSG:4326', '${coordinateFormat}', always_xy := true) as min_point,\n ST_Transform(ST_Point(${boundingBox.maxLon}, ${boundingBox.maxLat}), 'EPSG:4326', '${coordinateFormat}', always_xy := true) as max_point\n )\n SELECT \n CAST(ST_X(min_point) AS DOUBLE) as minLon,\n CAST(ST_Y(min_point) AS DOUBLE) as minLat,\n CAST(ST_X(max_point) AS DOUBLE) as maxLon,\n CAST(ST_Y(max_point) AS DOUBLE) as maxLat\n FROM transformed_bounds;\n `;\n};\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { TransformBoundingBoxCoordinatesParams } from './interfaces';\nimport { BoundingBox } from '../../../../shared/interfaces';\nimport { TRANSFORM_BOUNDING_BOX_COORDINATES_QUERY } from './queries';\n\n/**\n * Transforms a bounding box between coordinate reference systems.\n */\nexport class TransformBoundingBoxCoordinatesUseCase {\n constructor(private conn: AsyncDuckDBConnection) {}\n\n /**\n * Transforms bounding box coordinates using DuckDB's `ST_Transform`.\n * EPSG:4326 inputs are returned unchanged.\n *\n * @param params.boundingBox Source bounding box to transform.\n * @param params.coordinateFormat Target CRS (e.g. `EPSG:3857`).\n * @returns Transformed bounding box.\n * @throws If the coordinate transformation fails.\n */\n async exec(params: TransformBoundingBoxCoordinatesParams): Promise<BoundingBox> {\n // If already in EPSG:4326, no conversion needed\n if (params.coordinateFormat === 'EPSG:4326') {\n return {\n minLon: params.boundingBox.minLon,\n minLat: params.boundingBox.minLat,\n maxLon: params.boundingBox.maxLon,\n maxLat: params.boundingBox.maxLat,\n };\n }\n\n // Transform coordinates using DuckDB's ST_Transform function\n const result = await this.conn.query(\n TRANSFORM_BOUNDING_BOX_COORDINATES_QUERY({\n boundingBox: params.boundingBox,\n coordinateFormat: params.coordinateFormat,\n }),\n );\n const rows = result.toArray();\n\n if (rows.length === 0) {\n throw new Error('Could not transform bounding box coordinates');\n }\n\n return {\n minLon: rows[0].minLon,\n minLat: rows[0].minLat,\n maxLon: rows[0].maxLon,\n maxLat: rows[0].maxLat,\n };\n }\n}\n","export const GET_BOUNDING_BOX_FROM_LAYER_QUERY = (layerTableName: string, workspace: string) => {\n const qualifiedTableName = `${workspace}.${layerTableName}`;\n return `\n WITH geometry_bounds AS (\n SELECT \n ST_XMin(geometry) as min_x,\n ST_YMin(geometry) as min_y,\n ST_XMax(geometry) as max_x,\n ST_YMax(geometry) as max_y\n FROM ${qualifiedTableName}\n WHERE geometry IS NOT NULL\n )\n SELECT \n CAST(MIN(min_x) AS DOUBLE) as minLon,\n CAST(MIN(min_y) AS DOUBLE) as minLat,\n CAST(MAX(max_x) AS DOUBLE) as maxLon,\n CAST(MAX(max_y) AS DOUBLE) as maxLat\n FROM geometry_bounds;\n `;\n};\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { GetBoundingBoxFromLayerParams } from './interfaces';\nimport { BoundingBox } from '../../../../shared/interfaces';\nimport { GET_BOUNDING_BOX_FROM_LAYER_QUERY } from './queries';\n\n/**\n * Computes the geographic bounding box of a layer table.\n */\nexport class GetBoundingBoxFromLayerUseCase {\n constructor(private conn: AsyncDuckDBConnection) {}\n\n /**\n * Queries the spatial extent of a layer's geometry column.\n *\n * @param params.layerTableName Name of the layer table.\n * @param params.workspace Optional workspace name (defaults to `main`).\n * @returns Named bounding box with `minLon`, `minLat`, `maxLon`, `maxLat`.\n * @throws If the table has no geometries or invalid coordinates.\n */\n async exec(params: GetBoundingBoxFromLayerParams): Promise<BoundingBox> {\n const workspace = params.workspace || 'main';\n const result = await this.conn.query(GET_BOUNDING_BOX_FROM_LAYER_QUERY(params.layerTableName, workspace));\n const rows = result.toArray();\n\n if (rows.length === 0) {\n throw new Error(`Could not calculate bounding box - no geometries found in table ${params.layerTableName}`);\n }\n\n const row = rows[0];\n\n // Validate that we have valid coordinates\n if (row.minLon == null || row.minLat == null || row.maxLon == null || row.maxLat == null) {\n throw new Error(`Could not calculate bounding box - invalid coordinates found in table ${params.layerTableName}`);\n }\n\n return {\n minLon: row.minLon,\n minLat: row.minLat,\n maxLon: row.maxLon,\n maxLat: row.maxLat,\n };\n }\n}\n","/**\n * Simple HTTP cache using Browser Cache API with TTL support\n */\nexport class HttpCache<T = any> {\n private cache: Cache | null = null;\n private readonly cacheName: string;\n private readonly ttl: number;\n\n /**\n * Creates an HTTP cache with the given name and TTL.\n *\n * @param cacheName Name of the cache storage.\n * @param ttl Time to live in milliseconds (default: 24 hours).\n * @throws Never throws.\n */\n constructor(cacheName: string, ttl: number = 24 * 60 * 60 * 1000) {\n this.cacheName = cacheName;\n this.ttl = ttl;\n }\n\n /**\n * Initializes the Cache API storage if available.\n *\n * @throws Never throws. Failures leave the cache as `null`.\n */\n private async init(): Promise<void> {\n if ('caches' in self && !this.cache) {\n try {\n this.cache = await caches.open(this.cacheName);\n } catch {\n this.cache = null;\n }\n }\n }\n\n /**\n * Returns cached data for a key, or `null` if missing or expired.\n *\n * @param key Cache key to look up.\n * @returns Cached data or `null`.\n * @throws Never throws. Errors are caught and return `null`.\n */\n async get(key: string): Promise<T | null> {\n await this.init();\n if (!this.cache) return null;\n\n try {\n const response = await this.cache.match(this.toRequest(key));\n if (!response) return null;\n\n const cached = await response.json();\n const now = Date.now();\n\n // Check if expired\n if (now - cached.timestamp > this.ttl) {\n await this.cache.delete(this.toRequest(key));\n return null;\n }\n\n return cached.data as T;\n } catch {\n return null;\n }\n }\n\n private toRequest(key: string): Request {\n return new Request(`https://cache.local/${encodeURIComponent(key)}`);\n }\n\n /**\n * Stores data in the cache with a current timestamp.\n *\n * @param key Cache key to store under.\n * @param data Value to cache.\n * @returns Nothing.\n * @throws Never throws. Errors are silently caught.\n */\n async set(key: string, data: T): Promise<void> {\n await this.init();\n if (!this.cache) return;\n\n try {\n const cached = {\n data,\n timestamp: Date.now(),\n };\n\n const response = new Response(JSON.stringify(cached), {\n headers: { 'Content-Type': 'application/json' },\n });\n\n await this.cache.put(this.toRequest(key), response);\n } catch {\n // Ignore cache errors\n }\n }\n\n /**\n * Deletes a specific key from the cache.\n *\n * @param key Cache key to remove.\n * @returns Nothing.\n * @throws Never throws. Errors are silently caught.\n */\n async delete(key: string): Promise<void> {\n await this.init();\n if (!this.cache) return;\n\n try {\n await this.cache.delete(this.toRequest(key));\n } catch {\n // Ignore errors\n }\n }\n\n /**\n * Clears all items from this cache.\n *\n * @returns Nothing.\n * @throws Never throws. Errors are silently caught.\n */\n async clear(): Promise<void> {\n await this.init();\n if (!this.cache) return;\n\n try {\n const keys = await this.cache.keys();\n await Promise.all(keys.map((request) => this.cache!.delete(request)));\n } catch {\n // Ignore errors\n }\n }\n}\n\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { LoadOsmParams, OsmElement, OnLoadingProgress } from './interfaces';\nimport { OsmTable } from '../../../shared/interfaces';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport { HttpCache } from '../../../shared/HttpCache';\nimport {\n PARKS_LEISURE_VALUES,\n PARKS_LANDUSE_VALUES,\n PARKS_NATURAL_VALUES,\n WATER_NATURAL_VALUES,\n WATER_FEATURE_VALUES,\n EXCLUDED_BUILDING_VALUES,\n EXCLUDED_HIGHWAY_VALUES,\n} from '../../../shared/osm-tag-definitions';\n\nimport { OsmProcessingPipeline } from '../osm-processing-pipeline/OsmProcessingPipeline';\n\ninterface OverpassApiResponse {\n elements: OsmElement[];\n}\n\ninterface OsmExecResult {\n tables: OsmTable[];\n osmElementCount: number;\n boundaryElementCount: number;\n osmDataProcessingMs: number;\n boundariesProcessingMs: number;\n}\n\ntype OverpassTagSelectors = {\n way: string[];\n relation: string[];\n};\n\n/**\n * Loads OSM data from the Overpass API with caching, retry, and slot polling.\n */\nexport class LoadOsmFromOverpassApiUseCase {\n private readonly conn: AsyncDuckDBConnection;\n private readonly cache: HttpCache<OverpassApiResponse>;\n private readonly pipeline: OsmProcessingPipeline;\n\n constructor(conn: AsyncDuckDBConnection, pipeline: OsmProcessingPipeline) {\n this.conn = conn;\n this.cache = new HttpCache('overpass-api-cache', 24 * 60 * 60 * 1000); // 24h TTL\n this.pipeline = pipeline;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n async exec(params: LoadOsmParams): Promise<OsmExecResult> {\n const workspace = params.workspace || 'main';\n const onProgress = params.onProgress;\n\n const combined = await this.fetchCombinedOsmData(\n params.queryArea,\n params.autoLoadLayers?.layers,\n onProgress,\n params.forceRefresh,\n );\n\n // Verify every requested area has an admin boundary relation in the response.\n const relationNames = new Set(\n combined.elements\n .filter(e => e.type === 'relation' && e.tags?.name)\n .map(e => e.tags!.name),\n );\n const missingAreas = params.queryArea.areas.filter(area => !relationNames.has(area));\n if (missingAreas.length > 0) {\n throw new Error(\n `No administrative boundary found in OSM for: ${missingAreas.map(a => `\"${a}\"`).join(', ')}. ` +\n `Verify the area names match OSM relation names exactly (check openstreetmap.org).`,\n );\n }\n\n const { osmData, boundariesData } = this.pipeline.splitCombinedResponse(combined, params.queryArea);\n console.log(`[autk-db] Split: ${osmData.elements.length} OSM elements, ${boundariesData.elements.length} boundary elements`);\n\n onProgress?.('processing-osm-data');\n const t0 = performance.now();\n await this.pipeline.insertOsmDataUsingJson(params.outputTableName, osmData, workspace);\n const osmDataProcessingMs = performance.now() - t0;\n console.log(`Successfully inserted ${osmData.elements.length} OSM elements into ${params.outputTableName}`);\n\n onProgress?.('processing-boundaries');\n const t1 = performance.now();\n await this.pipeline.insertOsmDataUsingJson(`${params.outputTableName}_boundaries`, boundariesData, workspace, true);\n const boundariesProcessingMs = performance.now() - t1;\n console.log(`Successfully inserted ${boundariesData.elements.length} boundaries into ${params.outputTableName}_boundaries`);\n\n const qualifiedTableName = `${workspace}.${params.outputTableName}`;\n const tableDescribeResponse = await this.conn.query(`DESCRIBE ${qualifiedTableName}`);\n const columns = getColumnsFromDuckDbTableDescribe(tableDescribeResponse.toArray());\n\n return {\n tables: [\n { source: 'osm', type: 'pointset', name: params.outputTableName, columns },\n { source: 'osm', type: 'pointset', name: `${params.outputTableName}_boundaries`, columns },\n ],\n osmElementCount: osmData.elements.length,\n boundaryElementCount: boundariesData.elements.length,\n osmDataProcessingMs,\n boundariesProcessingMs,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Cache\n // ---------------------------------------------------------------------------\n\n private getCacheKey(queryArea: { geocodeArea: string; areas: string[] }, layers?: string[]): string {\n const areas = [...queryArea.areas].sort().join(',');\n const layerKey = layers && layers.length > 0 ? `-layers:${[...layers].sort().join('+')}` : '';\n return `overpass-combined-${queryArea.geocodeArea}-${areas}${layerKey}`;\n }\n\n private getFullDataCacheKey(queryArea: { geocodeArea: string; areas: string[] }): string {\n const areas = [...queryArea.areas].sort().join(',');\n return `overpass-combined-${queryArea.geocodeArea}-${areas}`;\n }\n\n // ---------------------------------------------------------------------------\n // Overpass fetch orchestration\n // ---------------------------------------------------------------------------\n\n /**\n * Fetches OSM data as four independent requests — boundaries, parks+water,\n * roads, buildings — so each request is smaller and less likely to trigger a\n * 504. A pause between requests avoids immediate rate-limiting. Results are\n * cached for 24h.\n *\n * `geocodeArea` (e.g. \"New York\") is used only as a disambiguation scope.\n * All data is spatially constrained to the entries in `queryArea.areas`.\n */\n private async fetchCombinedOsmData(\n queryArea: { geocodeArea: string; areas: string[] },\n layers: string[] | undefined,\n onProgress?: OnLoadingProgress,\n forceRefresh: boolean = false,\n ): Promise<OverpassApiResponse> {\n const cacheKey = this.getCacheKey(queryArea, layers);\n if (!forceRefresh) {\n const cachedData = await this.cache.get(cacheKey);\n if (cachedData) {\n console.log(`[autk-db] Using cached Overpass data: ${cacheKey}`);\n return cachedData;\n }\n\n // A full-data cache entry (no layer filter) is a valid superset — reuse it.\n const fullDataCacheKey = this.getFullDataCacheKey(queryArea);\n if (fullDataCacheKey !== cacheKey) {\n const fullData = await this.cache.get(fullDataCacheKey);\n if (fullData) {\n console.log(`[autk-db] Using cached Overpass full-data superset: ${fullDataCacheKey}`);\n return fullData;\n }\n }\n } else {\n console.log(`[autk-db] forceRefresh enabled — bypassing Overpass cache for: ${cacheKey}`);\n }\n\n const requestedLayers = layers && layers.length > 0 ? layers : ['roads', 'buildings', 'parks', 'water'];\n const pause = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n const BETWEEN_REQUESTS_MS = 3_000;\n\n onProgress?.('querying-osm-server');\n\n // Request 1: boundaries (always needed, always small)\n console.log('[autk-db] Fetching boundary data from Overpass API…');\n const boundariesResponse = await this.fetchWithRetry(this.buildBoundariesQuery(queryArea));\n onProgress?.('downloading-osm-data');\n const boundariesData: OverpassApiResponse = await boundariesResponse.json();\n console.log(`[autk-db] Boundaries: ${boundariesData.elements?.length ?? 0} elements`);\n let combined: OverpassApiResponse = boundariesData;\n\n // Compute the area bbox once from boundary data only — independent of which\n // layers are requested, so parks/roads/etc. never pollute the extent.\n const boundariesBbox = this.pipeline.computeBboxFromElements(boundariesData.elements ?? []);\n\n // Requests 2–4: one per layer group, skipped when not requested.\n // Buildings are fetched as a 2×2 tiled grid to stay within Overpass maxsize limits.\n const layerGroups: [string, string[]][] = [\n ['parks+water', ['parks', 'water']],\n ['roads', ['roads']],\n ['buildings', ['buildings']],\n ];\n\n let anyGroupEmpty = false;\n\n for (const [label, group] of layerGroups) {\n const activeGroup = group.filter(l => requestedLayers.includes(l));\n if (activeGroup.length === 0) continue;\n\n if (activeGroup.includes('buildings')) {\n const tileQueries = boundariesBbox\n ? this.buildBuildingsTileQueries(queryArea, boundariesBbox)\n : [this.buildLayerGroupQuery(queryArea, activeGroup)!];\n\n let buildingsTotal = 0;\n for (let t = 0; t < tileQueries.length; t++) {\n await pause(BETWEEN_REQUESTS_MS);\n console.log(`[autk-db] Fetching buildings tile ${t + 1}/${tileQueries.length}…`);\n const response = await this.fetchWithRetry(tileQueries[t]);\n const data: OverpassApiResponse = await response.json();\n const count = data.elements?.length ?? 0;\n console.log(`[autk-db] buildings tile ${t + 1}: ${count} elements`);\n buildingsTotal += count;\n combined = this.mergeResponses(combined, data);\n }\n if (buildingsTotal === 0) {\n console.warn('[autk-db] buildings: 0 elements across all tiles — skipping cache.');\n anyGroupEmpty = true;\n }\n continue;\n }\n\n const query = this.buildLayerGroupQuery(queryArea, activeGroup);\n if (!query) continue;\n\n await pause(BETWEEN_REQUESTS_MS);\n console.log(`[autk-db] Fetching ${label} data from Overpass API…`);\n const response = await this.fetchWithRetry(query);\n const data: OverpassApiResponse = await response.json();\n const count = data.elements?.length ?? 0;\n console.log(`[autk-db] ${label}: ${count} elements`);\n if (count === 0) {\n console.warn(`[autk-db] ${label}: 0 elements — skipping cache.`);\n anyGroupEmpty = true;\n }\n combined = this.mergeResponses(combined, data);\n }\n\n if (anyGroupEmpty) {\n return combined;\n }\n\n await this.cache.set(cacheKey, combined);\n return combined;\n }\n\n // ---------------------------------------------------------------------------\n // Overpass HTTP — slot checking and retry\n // ---------------------------------------------------------------------------\n\n private static readonly OVERPASS_ENDPOINT = 'https://overpass-api.de/api/interpreter';\n private static readonly OVERPASS_STATUS_ENDPOINT = 'https://overpass-api.de/api/status';\n\n // Query [timeout] is stepped down on each consecutive 504 / network rejection\n // to make the request look cheaper to the server.\n private static readonly QUERY_TIMEOUTS_S = [60, 45, 30, 20, 15, 10];\n\n private static setQueryTimeout(query: string, timeoutS: number): string {\n return query.replace(/\\[timeout:\\d+\\]/, `[timeout:${timeoutS}]`);\n }\n\n /**\n * Polls the Overpass status endpoint until a slot is free, then returns.\n * Fails silently — a status check error never blocks the actual request.\n */\n private async waitForSlot(): Promise<void> {\n const POLL_INTERVAL_MS = 3_000;\n const MAX_CHECKS = 60; // bail out after ~3 min of polling\n const wait = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n\n for (let check = 0; check < MAX_CHECKS; check++) {\n try {\n const res = await fetch(LoadOsmFromOverpassApiUseCase.OVERPASS_STATUS_ENDPOINT);\n if (!res.ok) return;\n const text = await res.text();\n\n const available = text.match(/(\\d+) slots available now/);\n if (available && parseInt(available[1]) > 0) return;\n\n const waitTimes = [...text.matchAll(/in (\\d+) seconds/g)].map(m => parseInt(m[1]));\n if (waitTimes.length === 0) return;\n\n const nextFreeS = Math.min(...waitTimes);\n console.log(`[autk-db] No Overpass slots available (next free in ${nextFreeS}s). Waiting…`);\n await wait(POLL_INTERVAL_MS);\n } catch {\n return;\n }\n }\n }\n\n /**\n * POSTs a query to the Overpass API with slot checking and automatic retry.\n *\n * POST is used so large queries are never truncated by proxy URL-length limits.\n * Before each top-level call the slot status is checked and waited on.\n *\n * Retryable conditions:\n * - 429 / 503 — server overloaded; backoff: 20s → 45s → 90s → 120s → 180s → 240s\n * - 504 / ERR_EMPTY_RESPONSE / fetch timeout — proxy rejection; backoff:\n * 10s → 20s → 45s → 90s → 120s → 180s, plus [timeout] in the query is\n * stepped down (60s → 45s → 30s → 20s → 15s → 10s) so each retry looks\n * cheaper to the server.\n *\n * All backoff values have ±10% jitter. The fetch-level AbortController\n * deadline is derived from the current query [timeout] + 30s overhead.\n */\n private async fetchWithRetry(query: string): Promise<Response> {\n const MAX_RETRIES = 6;\n const FETCH_OVERHEAD_MS = 30_000;\n const BACKOFF_429_MS = [20_000, 45_000, 90_000, 120_000, 180_000, 240_000];\n const BACKOFF_504_MS = [10_000, 20_000, 45_000, 90_000, 120_000, 180_000];\n\n const endpoint = LoadOsmFromOverpassApiUseCase.OVERPASS_ENDPOINT;\n const jitter = (ms: number) => ms * (0.9 + Math.random() * 0.2);\n const wait = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n const isRetryable = (status: number) => status === 429 || status === 503 || status === 504;\n\n await this.waitForSlot();\n\n let consecutive504s = 0;\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n const queryTimeoutS = LoadOsmFromOverpassApiUseCase.QUERY_TIMEOUTS_S[consecutive504s] ?? 10;\n const fetchTimeoutMs = queryTimeoutS * 1000 + FETCH_OVERHEAD_MS;\n const activeQuery = LoadOsmFromOverpassApiUseCase.setQueryTimeout(query, queryTimeoutS);\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), fetchTimeoutMs);\n let response: Response;\n\n try {\n response = await fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: 'data=' + encodeURIComponent(activeQuery),\n signal: controller.signal,\n });\n } catch (networkErr) {\n clearTimeout(timeoutId);\n if (attempt < MAX_RETRIES) {\n const isTimeout = (networkErr as Error)?.name === 'AbortError';\n consecutive504s++;\n const nextTimeoutS = LoadOsmFromOverpassApiUseCase.QUERY_TIMEOUTS_S[consecutive504s] ?? 10;\n const ms = jitter(BACKOFF_504_MS[attempt] ?? 180_000);\n console.warn(\n `[autk-db] Overpass ${isTimeout ? 'fetch timeout' : 'network error'} ` +\n `(attempt ${attempt + 1}/${MAX_RETRIES + 1}): ${networkErr}. ` +\n `Reducing query timeout ${queryTimeoutS}s → ${nextTimeoutS}s. ` +\n `Retrying in ${(ms / 1000).toFixed(0)}s…`,\n );\n await wait(ms);\n continue;\n }\n throw networkErr;\n }\n\n clearTimeout(timeoutId);\n\n if (response.ok) return response;\n\n if (isRetryable(response.status) && attempt < MAX_RETRIES) {\n const backoff = response.status === 504 ? BACKOFF_504_MS : BACKOFF_429_MS;\n const ms = jitter(backoff[attempt] ?? 240_000);\n if (response.status === 504) {\n consecutive504s++;\n const nextTimeoutS = LoadOsmFromOverpassApiUseCase.QUERY_TIMEOUTS_S[consecutive504s] ?? 10;\n console.warn(\n `[autk-db] Overpass 504 (attempt ${attempt + 1}/${MAX_RETRIES + 1}). ` +\n `Reducing query timeout ${queryTimeoutS}s → ${nextTimeoutS}s. ` +\n `Retrying in ${(ms / 1000).toFixed(0)}s…`,\n );\n } else {\n consecutive504s = 0;\n console.warn(\n `[autk-db] Overpass ${response.status} (attempt ${attempt + 1}/${MAX_RETRIES + 1}). ` +\n `Retrying in ${(ms / 1000).toFixed(0)}s…`,\n );\n }\n await wait(ms);\n continue;\n }\n\n throw new Error(`Overpass API error: ${response.status} ${response.statusText}`);\n }\n\n throw new Error('Overpass API: max retries exceeded');\n }\n\n // ---------------------------------------------------------------------------\n // Query builders\n // ---------------------------------------------------------------------------\n\n /**\n * Builds the boundaries query: admin relations + their member ways.\n * Relations are output with `body` only (tags + member IDs); ways get full\n * inline geometry via `out geom qt`.\n */\n private buildBoundariesQuery(queryArea: { geocodeArea: string; areas: string[] }): string {\n const geocodeLine = `area[\"name\"=\"${queryArea.geocodeArea}\"]->.areaMain;`;\n const areaLines: string[] = [];\n const relSelectors: string[] = [];\n const boundaryWaySelectors: string[] = [];\n\n queryArea.areas.forEach((areaName, idx) => {\n const i = idx + 1;\n areaLines.push(`area[\"name\"=\"${areaName}\"](area.areaMain)->.area${i};`);\n areaLines.push(`relation[\"name\"=\"${areaName}\"](area.areaMain)->.rel${i};`);\n areaLines.push(`way(r.rel${i})->.boundaryWays${i};`);\n relSelectors.push(`.rel${i};`);\n boundaryWaySelectors.push(`.boundaryWays${i};`);\n });\n\n return `\n [out:json][timeout:60][maxsize:134217728];\n\n ${geocodeLine}\n ${areaLines.join('\\n ')}\n\n ( ${relSelectors.join(' ')} );\n out body;\n\n ( ${boundaryWaySelectors.join(' ')} );\n out geom qt;\n `;\n }\n\n /**\n * Builds a query for a specific group of layers.\n * Returns null when no tag selectors apply to the given group (e.g. surface-only).\n */\n private buildLayerGroupQuery(\n queryArea: { geocodeArea: string; areas: string[] },\n layerGroup: string[],\n ): string | null {\n const tagSelectors = this.getTagSelectorsForLayers(layerGroup);\n if (tagSelectors.way.length === 0 && tagSelectors.relation.length === 0) return null;\n\n const geocodeLine = `area[\"name\"=\"${queryArea.geocodeArea}\"]->.areaMain;`;\n const areaLines: string[] = [];\n const dataWaySelectors: string[] = [];\n const dataRelationSelectors: string[] = [];\n const relationWaySelectors: string[] = [];\n\n queryArea.areas.forEach((areaName, idx) => {\n const i = idx + 1;\n areaLines.push(`area[\"name\"=\"${areaName}\"](area.areaMain)->.area${i};`);\n if (tagSelectors.way.length > 0) {\n areaLines.push(`(\n ${tagSelectors.way.map(filter => `way[${filter}](area.area${i});`).join('\\n ')}\n )->.dataWays${i};`);\n dataWaySelectors.push(`.dataWays${i};`);\n }\n if (tagSelectors.relation.length > 0) {\n areaLines.push(`(\n ${tagSelectors.relation.map(filter => `relation[${filter}](area.area${i});`).join('\\n ')}\n )->.dataRelations${i};`);\n areaLines.push(`way(r.dataRelations${i})->.dataRelationWays${i};`);\n dataRelationSelectors.push(`.dataRelations${i};`);\n relationWaySelectors.push(`.dataRelationWays${i};`);\n }\n });\n\n const allWaySelectors = [...dataWaySelectors, ...relationWaySelectors];\n const relationOutput = dataRelationSelectors.length > 0\n ? `\n ( ${dataRelationSelectors.join(' ')} );\n out body;`\n : '';\n const wayOutput = allWaySelectors.length > 0\n ? `\n ( ${allWaySelectors.join(' ')} );\n out geom qt;`\n : '';\n\n return `\n [out:json][timeout:60][maxsize:268435456];\n\n ${geocodeLine}\n ${areaLines.join('\\n ')}\n ${relationOutput}\n ${wayOutput}\n `;\n }\n\n /**\n * Returns Overpass tag filter expressions for the requested layers.\n * Uses value-level specificity for `natural` to avoid fetching unused types\n * (coastline, beach, cliff, etc.). `surface` needs no selectors — its ways\n * come from `way(r.rel)` in the boundaries query.\n */\n private getTagSelectorsForLayers(layers: string[]): OverpassTagSelectors {\n const wayFilters = new Set<string>();\n const relationFilters = new Set<string>();\n\n for (const layer of layers) {\n switch (layer) {\n case 'roads':\n wayFilters.add(`\"highway\"][\"area\"!=\"yes\"][\"highway\"!~\"^(${EXCLUDED_HIGHWAY_VALUES.join('|')})$\"`);\n break;\n case 'buildings':\n wayFilters.add(`\"building\"][${this.buildExcludedValueSelector('building', EXCLUDED_BUILDING_VALUES)}]`);\n wayFilters.add(`\"building:part\"][${this.buildExcludedValueSelector('building:part', EXCLUDED_BUILDING_VALUES)}]`);\n wayFilters.add(`\"type\"=\"building\"`);\n relationFilters.add(`\"building\"][${this.buildExcludedValueSelector('building', EXCLUDED_BUILDING_VALUES)}]`);\n relationFilters.add(`\"building:part\"][${this.buildExcludedValueSelector('building:part', EXCLUDED_BUILDING_VALUES)}]`);\n break;\n case 'parks':\n wayFilters.add(this.buildExactValueSelector('leisure', PARKS_LEISURE_VALUES));\n wayFilters.add(this.buildExactValueSelector('landuse', PARKS_LANDUSE_VALUES));\n wayFilters.add(this.buildExactValueSelector('natural', PARKS_NATURAL_VALUES));\n relationFilters.add(this.buildExactValueSelector('leisure', PARKS_LEISURE_VALUES));\n relationFilters.add(this.buildExactValueSelector('landuse', PARKS_LANDUSE_VALUES));\n relationFilters.add(this.buildExactValueSelector('natural', PARKS_NATURAL_VALUES));\n break;\n case 'water':\n wayFilters.add(this.buildExactValueSelector('natural', WATER_NATURAL_VALUES));\n wayFilters.add(this.buildExactValueSelector('water', WATER_FEATURE_VALUES));\n relationFilters.add(this.buildExactValueSelector('natural', WATER_NATURAL_VALUES));\n relationFilters.add(this.buildExactValueSelector('water', WATER_FEATURE_VALUES));\n break;\n case 'surface':\n break;\n }\n }\n\n return {\n way: [...wayFilters],\n relation: [...relationFilters],\n };\n }\n\n private buildExactValueSelector(key: string, values: readonly string[]): string {\n return `\"${key}\"~\"^(${values.join('|')})$\"`;\n }\n\n private buildExcludedValueSelector(key: string, values: readonly string[]): string {\n return `\"${key}\"!~\"^(${values.join('|')})$\"`;\n }\n\n /**\n * Returns `cols × rows` Overpass queries that together cover `bbox`, each\n * using a combined area + tile-bbox filter so only features inside both the\n * named OSM area and the tile are returned. 256 MB maxsize per tile keeps\n * each response well within Overpass limits.\n */\n private buildBuildingsTileQueries(\n queryArea: { geocodeArea: string; areas: string[] },\n bbox: { south: number; north: number; west: number; east: number },\n cols = 2,\n rows = 2,\n ): string[] {\n const latStep = (bbox.north - bbox.south) / rows;\n const lonStep = (bbox.east - bbox.west) / cols;\n const queries: string[] = [];\n\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < cols; col++) {\n const south = bbox.south + row * latStep;\n const north = south + latStep;\n const west = bbox.west + col * lonStep;\n const east = west + lonStep;\n const tileBbox = `${south},${west},${north},${east}`;\n\n const geocodeLine = `area[\"name\"=\"${queryArea.geocodeArea}\"]->.areaMain;`;\n const areaLines: string[] = [];\n const dataWaySelectors: string[] = [];\n const dataRelationSelectors: string[] = [];\n const relationWaySelectors: string[] = [];\n\n queryArea.areas.forEach((areaName, idx) => {\n const i = idx + 1;\n areaLines.push(`area[\"name\"=\"${areaName}\"](area.areaMain)->.area${i};`);\n areaLines.push(`(\n way[\"building\"][${this.buildExcludedValueSelector('building', EXCLUDED_BUILDING_VALUES)}](area.area${i})(${tileBbox});\n way[\"building:part\"][${this.buildExcludedValueSelector('building:part', EXCLUDED_BUILDING_VALUES)}](area.area${i})(${tileBbox});\n way[\"type\"=\"building\"](area.area${i})(${tileBbox});\n )->.dataWays${i};`);\n dataWaySelectors.push(`.dataWays${i};`);\n areaLines.push(`(\n relation[\"building\"][${this.buildExcludedValueSelector('building', EXCLUDED_BUILDING_VALUES)}](area.area${i})(${tileBbox});\n relation[\"building:part\"][${this.buildExcludedValueSelector('building:part', EXCLUDED_BUILDING_VALUES)}](area.area${i})(${tileBbox});\n )->.dataRelations${i};`);\n areaLines.push(`way(r.dataRelations${i})->.dataRelationWays${i};`);\n dataRelationSelectors.push(`.dataRelations${i};`);\n relationWaySelectors.push(`.dataRelationWays${i};`);\n });\n\n const allWaySelectors = [...dataWaySelectors, ...relationWaySelectors];\n\n queries.push(`\n [out:json][timeout:60][maxsize:268435456];\n\n ${geocodeLine}\n ${areaLines.join('\\n ')}\n\n ( ${dataRelationSelectors.join(' ')} );\n out body;\n\n ( ${allWaySelectors.join(' ')} );\n out geom qt;\n `);\n }\n }\n\n return queries;\n }\n\n /** Merges two Overpass responses, deduplicating all elements by (type, id). */\n private mergeResponses(a: OverpassApiResponse, b: OverpassApiResponse): OverpassApiResponse {\n const existingIds = new Set<string>();\n for (const e of a.elements) {\n existingIds.add(`${e.type}:${e.id}`);\n }\n const dedupedB = b.elements.filter(e => !existingIds.has(`${e.type}:${e.id}`));\n return { elements: [...a.elements, ...dedupedB] };\n }\n\n}\n","\nconst SHIFT_LEFT_32 = (1 << 16) * (1 << 16);\nconst SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32;\n\n// Threshold chosen based on both benchmarking and knowledge about browser string\n// data structures (which currently switch structure types at 12 bytes or more)\nconst TEXT_DECODER_MIN_LENGTH = 12;\nconst utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8');\n\nconst PBF_VARINT = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum\nconst PBF_FIXED64 = 1; // 64-bit: double, fixed64, sfixed64\nconst PBF_BYTES = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields\nconst PBF_FIXED32 = 5; // 32-bit: float, fixed32, sfixed32\n\nexport default class Pbf {\n /**\n * @param {Uint8Array | ArrayBuffer} [buf]\n */\n constructor(buf = new Uint8Array(16)) {\n this.buf = ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf);\n this.dataView = new DataView(this.buf.buffer);\n this.pos = 0;\n this.type = 0;\n this.length = this.buf.length;\n }\n\n // === READING =================================================================\n\n /**\n * @template T\n * @param {(tag: number, result: T, pbf: Pbf) => void} readField\n * @param {T} result\n * @param {number} [end]\n */\n readFields(readField, result, end = this.length) {\n while (this.pos < end) {\n const val = this.readVarint(),\n tag = val >> 3,\n startPos = this.pos;\n\n this.type = val & 0x7;\n readField(tag, result, this);\n\n if (this.pos === startPos) this.skip(val);\n }\n return result;\n }\n\n /**\n * @template T\n * @param {(tag: number, result: T, pbf: Pbf) => void} readField\n * @param {T} result\n */\n readMessage(readField, result) {\n return this.readFields(readField, result, this.readVarint() + this.pos);\n }\n\n readFixed32() {\n const val = this.dataView.getUint32(this.pos, true);\n this.pos += 4;\n return val;\n }\n\n readSFixed32() {\n const val = this.dataView.getInt32(this.pos, true);\n this.pos += 4;\n return val;\n }\n\n // 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)\n\n readFixed64() {\n const val = this.dataView.getUint32(this.pos, true) + this.dataView.getUint32(this.pos + 4, true) * SHIFT_LEFT_32;\n this.pos += 8;\n return val;\n }\n\n readSFixed64() {\n const val = this.dataView.getUint32(this.pos, true) + this.dataView.getInt32(this.pos + 4, true) * SHIFT_LEFT_32;\n this.pos += 8;\n return val;\n }\n\n readFloat() {\n const val = this.dataView.getFloat32(this.pos, true);\n this.pos += 4;\n return val;\n }\n\n readDouble() {\n const val = this.dataView.getFloat64(this.pos, true);\n this.pos += 8;\n return val;\n }\n\n /**\n * @param {boolean} [isSigned]\n */\n readVarint(isSigned) {\n const buf = this.buf;\n let val, b;\n\n b = buf[this.pos++]; val = b & 0x7f; if (b < 0x80) return val;\n b = buf[this.pos++]; val |= (b & 0x7f) << 7; if (b < 0x80) return val;\n b = buf[this.pos++]; val |= (b & 0x7f) << 14; if (b < 0x80) return val;\n b = buf[this.pos++]; val |= (b & 0x7f) << 21; if (b < 0x80) return val;\n b = buf[this.pos]; val |= (b & 0x0f) << 28;\n\n return readVarintRemainder(val, isSigned, this);\n }\n\n readVarint64() { // for compatibility with v2.0.1\n return this.readVarint(true);\n }\n\n readSVarint() {\n const num = this.readVarint();\n return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding\n }\n\n readBoolean() {\n return Boolean(this.readVarint());\n }\n\n readString() {\n const end = this.readVarint() + this.pos;\n const pos = this.pos;\n this.pos = end;\n\n if (end - pos >= TEXT_DECODER_MIN_LENGTH && utf8TextDecoder) {\n // longer strings are fast with the built-in browser TextDecoder API\n return utf8TextDecoder.decode(this.buf.subarray(pos, end));\n }\n // short strings are fast with our custom implementation\n return readUtf8(this.buf, pos, end);\n }\n\n readBytes() {\n const end = this.readVarint() + this.pos,\n buffer = this.buf.subarray(this.pos, end);\n this.pos = end;\n return buffer;\n }\n\n // verbose for performance reasons; doesn't affect gzipped size\n\n /**\n * @param {number[]} [arr]\n * @param {boolean} [isSigned]\n */\n readPackedVarint(arr = [], isSigned) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readVarint(isSigned));\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedSVarint(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readSVarint());\n return arr;\n }\n /** @param {boolean[]} [arr] */\n readPackedBoolean(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readBoolean());\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedFloat(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readFloat());\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedDouble(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readDouble());\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedFixed32(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readFixed32());\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedSFixed32(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readSFixed32());\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedFixed64(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readFixed64());\n return arr;\n }\n /** @param {number[]} [arr] */\n readPackedSFixed64(arr = []) {\n const end = this.readPackedEnd();\n while (this.pos < end) arr.push(this.readSFixed64());\n return arr;\n }\n readPackedEnd() {\n return this.type === PBF_BYTES ? this.readVarint() + this.pos : this.pos + 1;\n }\n\n /** @param {number} val */\n skip(val) {\n const type = val & 0x7;\n if (type === PBF_VARINT) while (this.buf[this.pos++] > 0x7f) {}\n else if (type === PBF_BYTES) this.pos = this.readVarint() + this.pos;\n else if (type === PBF_FIXED32) this.pos += 4;\n else if (type === PBF_FIXED64) this.pos += 8;\n else throw new Error(`Unimplemented type: ${type}`);\n }\n\n // === WRITING =================================================================\n\n /**\n * @param {number} tag\n * @param {number} type\n */\n writeTag(tag, type) {\n this.writeVarint((tag << 3) | type);\n }\n\n /** @param {number} min */\n realloc(min) {\n let length = this.length || 16;\n\n while (length < this.pos + min) length *= 2;\n\n if (length !== this.length) {\n const buf = new Uint8Array(length);\n buf.set(this.buf);\n this.buf = buf;\n this.dataView = new DataView(buf.buffer);\n this.length = length;\n }\n }\n\n finish() {\n this.length = this.pos;\n this.pos = 0;\n return this.buf.subarray(0, this.length);\n }\n\n /** @param {number} val */\n writeFixed32(val) {\n this.realloc(4);\n this.dataView.setInt32(this.pos, val, true);\n this.pos += 4;\n }\n\n /** @param {number} val */\n writeSFixed32(val) {\n this.realloc(4);\n this.dataView.setInt32(this.pos, val, true);\n this.pos += 4;\n }\n\n /** @param {number} val */\n writeFixed64(val) {\n this.realloc(8);\n this.dataView.setInt32(this.pos, val & -1, true);\n this.dataView.setInt32(this.pos + 4, Math.floor(val * SHIFT_RIGHT_32), true);\n this.pos += 8;\n }\n\n /** @param {number} val */\n writeSFixed64(val) {\n this.realloc(8);\n this.dataView.setInt32(this.pos, val & -1, true);\n this.dataView.setInt32(this.pos + 4, Math.floor(val * SHIFT_RIGHT_32), true);\n this.pos += 8;\n }\n\n /** @param {number} val */\n writeVarint(val) {\n val = +val || 0;\n\n if (val > 0xfffffff || val < 0) {\n writeBigVarint(val, this);\n return;\n }\n\n this.realloc(4);\n\n this.buf[this.pos++] = val & 0x7f | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;\n this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;\n this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;\n this.buf[this.pos++] = (val >>> 7) & 0x7f;\n }\n\n /** @param {number} val */\n writeSVarint(val) {\n this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);\n }\n\n /** @param {boolean} val */\n writeBoolean(val) {\n this.writeVarint(+val);\n }\n\n /** @param {string} str */\n writeString(str) {\n str = String(str);\n this.realloc(str.length * 4);\n\n this.pos++; // reserve 1 byte for short string length\n\n const startPos = this.pos;\n // write the string directly to the buffer and see how much was written\n this.pos = writeUtf8(this.buf, str, this.pos);\n const len = this.pos - startPos;\n\n if (len >= 0x80) makeRoomForExtraLength(startPos, len, this);\n\n // finally, write the message length in the reserved place and restore the position\n this.pos = startPos - 1;\n this.writeVarint(len);\n this.pos += len;\n }\n\n /** @param {number} val */\n writeFloat(val) {\n this.realloc(4);\n this.dataView.setFloat32(this.pos, val, true);\n this.pos += 4;\n }\n\n /** @param {number} val */\n writeDouble(val) {\n this.realloc(8);\n this.dataView.setFloat64(this.pos, val, true);\n this.pos += 8;\n }\n\n /** @param {Uint8Array} buffer */\n writeBytes(buffer) {\n const len = buffer.length;\n this.writeVarint(len);\n this.realloc(len);\n for (let i = 0; i < len; i++) this.buf[this.pos++] = buffer[i];\n }\n\n /**\n * @template T\n * @param {(obj: T, pbf: Pbf) => void} fn\n * @param {T} obj\n */\n writeRawMessage(fn, obj) {\n this.pos++; // reserve 1 byte for short message length\n\n // write the message directly to the buffer and see how much was written\n const startPos = this.pos;\n fn(obj, this);\n const len = this.pos - startPos;\n\n if (len >= 0x80) makeRoomForExtraLength(startPos, len, this);\n\n // finally, write the message length in the reserved place and restore the position\n this.pos = startPos - 1;\n this.writeVarint(len);\n this.pos += len;\n }\n\n /**\n * @template T\n * @param {number} tag\n * @param {(obj: T, pbf: Pbf) => void} fn\n * @param {T} obj\n */\n writeMessage(tag, fn, obj) {\n this.writeTag(tag, PBF_BYTES);\n this.writeRawMessage(fn, obj);\n }\n\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedVarint(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedVarint, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedSVarint(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedSVarint, arr);\n }\n /**\n * @param {number} tag\n * @param {boolean[]} arr\n */\n writePackedBoolean(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedBoolean, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedFloat(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedFloat, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedDouble(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedDouble, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedFixed32(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedFixed32, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedSFixed32(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedSFixed32, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedFixed64(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedFixed64, arr);\n }\n /**\n * @param {number} tag\n * @param {number[]} arr\n */\n writePackedSFixed64(tag, arr) {\n if (arr.length) this.writeMessage(tag, writePackedSFixed64, arr);\n }\n\n /**\n * @param {number} tag\n * @param {Uint8Array} buffer\n */\n writeBytesField(tag, buffer) {\n this.writeTag(tag, PBF_BYTES);\n this.writeBytes(buffer);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeFixed32Field(tag, val) {\n this.writeTag(tag, PBF_FIXED32);\n this.writeFixed32(val);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeSFixed32Field(tag, val) {\n this.writeTag(tag, PBF_FIXED32);\n this.writeSFixed32(val);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeFixed64Field(tag, val) {\n this.writeTag(tag, PBF_FIXED64);\n this.writeFixed64(val);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeSFixed64Field(tag, val) {\n this.writeTag(tag, PBF_FIXED64);\n this.writeSFixed64(val);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeVarintField(tag, val) {\n this.writeTag(tag, PBF_VARINT);\n this.writeVarint(val);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeSVarintField(tag, val) {\n this.writeTag(tag, PBF_VARINT);\n this.writeSVarint(val);\n }\n /**\n * @param {number} tag\n * @param {string} str\n */\n writeStringField(tag, str) {\n this.writeTag(tag, PBF_BYTES);\n this.writeString(str);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeFloatField(tag, val) {\n this.writeTag(tag, PBF_FIXED32);\n this.writeFloat(val);\n }\n /**\n * @param {number} tag\n * @param {number} val\n */\n writeDoubleField(tag, val) {\n this.writeTag(tag, PBF_FIXED64);\n this.writeDouble(val);\n }\n /**\n * @param {number} tag\n * @param {boolean} val\n */\n writeBooleanField(tag, val) {\n this.writeVarintField(tag, +val);\n }\n};\n\n/**\n * @param {number} l\n * @param {boolean | undefined} s\n * @param {Pbf} p\n */\nfunction readVarintRemainder(l, s, p) {\n const buf = p.buf;\n let h, b;\n\n b = buf[p.pos++]; h = (b & 0x70) >> 4; if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++]; h |= (b & 0x7f) << 3; if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++]; h |= (b & 0x7f) << 10; if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++]; h |= (b & 0x7f) << 17; if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++]; h |= (b & 0x7f) << 24; if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++]; h |= (b & 0x01) << 31; if (b < 0x80) return toNum(l, h, s);\n\n throw new Error('Expected varint not more than 10 bytes');\n}\n\n/**\n * @param {number} low\n * @param {number} high\n * @param {boolean} [isSigned]\n */\nfunction toNum(low, high, isSigned) {\n return isSigned ? high * 0x100000000 + (low >>> 0) : ((high >>> 0) * 0x100000000) + (low >>> 0);\n}\n\n/**\n * @param {number} val\n * @param {Pbf} pbf\n */\nfunction writeBigVarint(val, pbf) {\n let low, high;\n\n if (val >= 0) {\n low = (val % 0x100000000) | 0;\n high = (val / 0x100000000) | 0;\n } else {\n low = ~(-val % 0x100000000);\n high = ~(-val / 0x100000000);\n\n if (low ^ 0xffffffff) {\n low = (low + 1) | 0;\n } else {\n low = 0;\n high = (high + 1) | 0;\n }\n }\n\n if (val >= 0x10000000000000000 || val < -0x10000000000000000) {\n throw new Error('Given varint doesn\\'t fit into 10 bytes');\n }\n\n pbf.realloc(10);\n\n writeBigVarintLow(low, high, pbf);\n writeBigVarintHigh(high, pbf);\n}\n\n/**\n * @param {number} high\n * @param {number} low\n * @param {Pbf} pbf\n */\nfunction writeBigVarintLow(low, high, pbf) {\n pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;\n pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;\n pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;\n pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;\n pbf.buf[pbf.pos] = low & 0x7f;\n}\n\n/**\n * @param {number} high\n * @param {Pbf} pbf\n */\nfunction writeBigVarintHigh(high, pbf) {\n const lsb = (high & 0x07) << 4;\n\n pbf.buf[pbf.pos++] |= lsb | ((high >>>= 3) ? 0x80 : 0); if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f;\n}\n\n/**\n * @param {number} startPos\n * @param {number} len\n * @param {Pbf} pbf\n */\nfunction makeRoomForExtraLength(startPos, len, pbf) {\n const extraLen =\n len <= 0x3fff ? 1 :\n len <= 0x1fffff ? 2 :\n len <= 0xfffffff ? 3 : Math.floor(Math.log(len) / (Math.LN2 * 7));\n\n // if 1 byte isn't enough for encoding message length, shift the data to the right\n pbf.realloc(extraLen);\n for (let i = pbf.pos - 1; i >= startPos; i--) pbf.buf[i + extraLen] = pbf.buf[i];\n}\n\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedVarint(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeVarint(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedSVarint(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeSVarint(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedFloat(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeFloat(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedDouble(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeDouble(arr[i]);\n}\n/**\n * @param {boolean[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedBoolean(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeBoolean(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedFixed32(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeFixed32(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedSFixed32(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeSFixed32(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedFixed64(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeFixed64(arr[i]);\n}\n/**\n * @param {number[]} arr\n * @param {Pbf} pbf\n */\nfunction writePackedSFixed64(arr, pbf) {\n for (let i = 0; i < arr.length; i++) pbf.writeSFixed64(arr[i]);\n}\n\n// Buffer code below from https://github.com/feross/buffer, MIT-licensed\n\n/**\n * @param {Uint8Array} buf\n * @param {number} pos\n * @param {number} end\n */\nfunction readUtf8(buf, pos, end) {\n let str = '';\n let i = pos;\n\n while (i < end) {\n const b0 = buf[i];\n let c = null; // codepoint\n let bytesPerSequence =\n b0 > 0xEF ? 4 :\n b0 > 0xDF ? 3 :\n b0 > 0xBF ? 2 : 1;\n\n if (i + bytesPerSequence > end) break;\n\n let b1, b2, b3;\n\n if (bytesPerSequence === 1) {\n if (b0 < 0x80) {\n c = b0;\n }\n } else if (bytesPerSequence === 2) {\n b1 = buf[i + 1];\n if ((b1 & 0xC0) === 0x80) {\n c = (b0 & 0x1F) << 0x6 | (b1 & 0x3F);\n if (c <= 0x7F) {\n c = null;\n }\n }\n } else if (bytesPerSequence === 3) {\n b1 = buf[i + 1];\n b2 = buf[i + 2];\n if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80) {\n c = (b0 & 0xF) << 0xC | (b1 & 0x3F) << 0x6 | (b2 & 0x3F);\n if (c <= 0x7FF || (c >= 0xD800 && c <= 0xDFFF)) {\n c = null;\n }\n }\n } else if (bytesPerSequence === 4) {\n b1 = buf[i + 1];\n b2 = buf[i + 2];\n b3 = buf[i + 3];\n if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {\n c = (b0 & 0xF) << 0x12 | (b1 & 0x3F) << 0xC | (b2 & 0x3F) << 0x6 | (b3 & 0x3F);\n if (c <= 0xFFFF || c >= 0x110000) {\n c = null;\n }\n }\n }\n\n if (c === null) {\n c = 0xFFFD;\n bytesPerSequence = 1;\n\n } else if (c > 0xFFFF) {\n c -= 0x10000;\n str += String.fromCharCode(c >>> 10 & 0x3FF | 0xD800);\n c = 0xDC00 | c & 0x3FF;\n }\n\n str += String.fromCharCode(c);\n i += bytesPerSequence;\n }\n\n return str;\n}\n\n/**\n * @param {Uint8Array} buf\n * @param {string} str\n * @param {number} pos\n */\nfunction writeUtf8(buf, str, pos) {\n for (let i = 0, c, lead; i < str.length; i++) {\n c = str.charCodeAt(i); // code point\n\n if (c > 0xD7FF && c < 0xE000) {\n if (lead) {\n if (c < 0xDC00) {\n buf[pos++] = 0xEF;\n buf[pos++] = 0xBF;\n buf[pos++] = 0xBD;\n lead = c;\n continue;\n } else {\n c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000;\n lead = null;\n }\n } else {\n if (c > 0xDBFF || (i + 1 === str.length)) {\n buf[pos++] = 0xEF;\n buf[pos++] = 0xBF;\n buf[pos++] = 0xBD;\n } else {\n lead = c;\n }\n continue;\n }\n } else if (lead) {\n buf[pos++] = 0xEF;\n buf[pos++] = 0xBF;\n buf[pos++] = 0xBD;\n lead = null;\n }\n\n if (c < 0x80) {\n buf[pos++] = c;\n } else {\n if (c < 0x800) {\n buf[pos++] = c >> 0x6 | 0xC0;\n } else {\n if (c < 0x10000) {\n buf[pos++] = c >> 0xC | 0xE0;\n } else {\n buf[pos++] = c >> 0x12 | 0xF0;\n buf[pos++] = c >> 0xC & 0x3F | 0x80;\n }\n buf[pos++] = c >> 0x6 & 0x3F | 0x80;\n }\n buf[pos++] = c & 0x3F | 0x80;\n }\n }\n return pos;\n}\n","/**\n * Reads an `OsmPbfHeaderBlock` message from the provided Pbf reader.\n */\nexport function readHeaderBlock(pbf, end) {\n return pbf.readFields(readHeaderBlockField, {\n required_features: [],\n optional_features: [],\n }, end);\n}\n/**\n * Populates header block fields based on the protobuf tag encountered.\n */\nfunction readHeaderBlockField(tag, obj, pbf) {\n if (tag === 1)\n obj.bbox = readHeaderBBox(pbf, pbf.readVarint() + pbf.pos);\n else if (tag === 4)\n obj.required_features.push(pbf.readString());\n else if (tag === 5)\n obj.optional_features.push(pbf.readString());\n else if (tag === 16)\n obj.writingprogram = pbf.readString();\n else if (tag === 17)\n obj.source = pbf.readString();\n else if (tag === 32)\n obj.osmosis_replication_timestamp = pbf.readVarint(true);\n else if (tag === 33) {\n obj.osmosis_replication_sequence_number = pbf.readVarint(true);\n }\n else if (tag === 34)\n obj.osmosis_replication_base_url = pbf.readString();\n}\n/**\n * Serializes an `OsmPbfHeaderBlock` message into the Pbf writer.\n */\nexport function writeHeaderBlock(obj, pbf) {\n if (obj.bbox)\n pbf.writeMessage(1, writeHeaderBBox, obj.bbox);\n if (obj.required_features) {\n for (const item of obj.required_features)\n pbf.writeStringField(4, item);\n }\n if (obj.optional_features) {\n for (const item of obj.optional_features)\n pbf.writeStringField(5, item);\n }\n if (obj.writingprogram)\n pbf.writeStringField(16, obj.writingprogram);\n if (obj.source)\n pbf.writeStringField(17, obj.source);\n if (obj.osmosis_replication_timestamp) {\n pbf.writeVarintField(32, obj.osmosis_replication_timestamp);\n }\n if (obj.osmosis_replication_sequence_number) {\n pbf.writeVarintField(33, obj.osmosis_replication_sequence_number);\n }\n if (obj.osmosis_replication_base_url) {\n pbf.writeStringField(34, obj.osmosis_replication_base_url);\n }\n}\n/**\n * Reads a header bounding box and converts nanodegrees to degrees.\n */\nfunction readHeaderBBox(pbf, end) {\n return pbf.readFields(readHeaderBBoxField, { left: 0, right: 0, top: 0, bottom: 0 }, end);\n}\n/**\n * Populates bounding box properties while converting from nanodegrees.\n */\nfunction readHeaderBBoxField(tag, obj, pbf) {\n if (tag === 1)\n obj.left = pbf.readSVarint() / 1e9;\n else if (tag === 2)\n obj.right = pbf.readSVarint() / 1e9;\n else if (tag === 3)\n obj.top = pbf.readSVarint() / 1e9;\n else if (tag === 4)\n obj.bottom = pbf.readSVarint() / 1e9;\n}\n/**\n * Serializes a header bounding box, converting degrees back to nanodegrees.\n */\nfunction writeHeaderBBox(obj, pbf) {\n if (obj.left)\n pbf.writeSVarintField(1, obj.left * 1e9);\n if (obj.right)\n pbf.writeSVarintField(2, obj.right * 1e9);\n if (obj.top)\n pbf.writeSVarintField(3, obj.top * 1e9);\n if (obj.bottom)\n pbf.writeSVarintField(4, obj.bottom * 1e9);\n}\n/**\n * Reads a primitive block containing string tables and primitive groups.\n */\nexport function readPrimitiveBlock(pbf, end) {\n return pbf.readFields(readPrimitiveBlockField, {\n stringtable: [],\n primitivegroup: [],\n }, end);\n}\n/**\n * Populates primitive block fields based on protobuf tags.\n */\nfunction readPrimitiveBlockField(tag, obj, pbf) {\n if (tag === 1) {\n obj.stringtable = readStringTable(pbf, pbf.readVarint() + pbf.pos);\n }\n else if (tag === 2) {\n obj.primitivegroup.push(readPrimitiveGroup(pbf, pbf.readVarint() + pbf.pos));\n }\n else if (tag === 17) {\n obj.granularity = pbf.readVarint(true);\n obj.granularity = !obj.granularity ? 1e7 : 1e9 / obj.granularity;\n }\n else if (tag === 19)\n obj.lat_offset = pbf.readVarint(true) * 1e-9;\n else if (tag === 20)\n obj.lon_offset = pbf.readVarint(true) * 1e-9;\n else if (tag === 18)\n obj.date_granularity = pbf.readVarint(true) ?? 1000;\n}\n/**\n * Serializes a primitive block including its string table and primitive groups.\n */\nexport function writePrimitiveBlock(obj, pbf) {\n if (obj.stringtable)\n pbf.writeMessage(1, writeStringTable, obj.stringtable);\n if (obj.primitivegroup) {\n for (const item of obj.primitivegroup) {\n pbf.writeMessage(2, writePrimitiveGroup, item);\n }\n }\n if (obj.granularity != null && obj.granularity !== 1e7) {\n pbf.writeVarintField(17, 1e9 / obj.granularity);\n }\n if (obj.lat_offset)\n pbf.writeVarintField(19, obj.lat_offset / 1e-9);\n if (obj.lon_offset)\n pbf.writeVarintField(20, obj.lon_offset / 1e-9);\n if (obj.date_granularity != null && obj.date_granularity !== 1000) {\n pbf.writeVarintField(18, obj.date_granularity);\n }\n}\n/**\n * Reads a primitive group with collections of primitives.\n */\nfunction readPrimitiveGroup(pbf, end) {\n return pbf.readFields(readPrimitiveGroupField, { nodes: [], ways: [], relations: [] }, end);\n}\n/**\n * Populates primitive group collections from protobuf data.\n */\nfunction readPrimitiveGroupField(tag, obj, pbf) {\n if (tag === 1)\n obj.nodes.push(readNode(pbf, pbf.readVarint() + pbf.pos));\n else if (tag === 2) {\n obj.dense = readDenseNodes(pbf, pbf.readVarint() + pbf.pos);\n }\n else if (tag === 3)\n obj.ways.push(readWay(pbf, pbf.readVarint() + pbf.pos));\n else if (tag === 4) {\n obj.relations.push(readRelation(pbf, pbf.readVarint() + pbf.pos));\n }\n}\n/**\n * Serializes a primitive group to protobuf.\n */\nfunction writePrimitiveGroup(obj, pbf) {\n if (obj.nodes) {\n for (const item of obj.nodes)\n pbf.writeMessage(1, writeNode, item);\n }\n if (obj.dense)\n pbf.writeMessage(2, writeDenseNodes, obj.dense);\n if (obj.ways) {\n for (const item of obj.ways)\n pbf.writeMessage(3, writeWay, item);\n }\n if (obj.relations) {\n for (const item of obj.relations)\n pbf.writeMessage(4, writeRelation, item);\n }\n}\n/**\n * Reads the shared string table for a primitive block.\n */\nfunction readStringTable(pbf, end) {\n return pbf.readFields(readStringTableField, [], end);\n}\n/**\n * Appends string table entries as they are encountered.\n */\nfunction readStringTableField(tag, obj, pbf) {\n if (tag === 1)\n obj.push(pbf.readBytes());\n}\n/**\n * Serializes string table entries.\n */\nfunction writeStringTable(obj, pbf) {\n if (obj) {\n for (const item of obj)\n pbf.writeBytesField(1, item);\n }\n}\n/**\n * Reads metadata describing a single primitive.\n */\nfunction readInfo(pbf, end) {\n return pbf.readFields(readInfoField, {}, end);\n}\n/**\n * Populates primitive metadata fields.\n */\nfunction readInfoField(tag, obj, pbf) {\n if (tag === 1)\n obj.version = pbf.readVarint(true);\n else if (tag === 2)\n obj.timestamp = pbf.readVarint(true);\n else if (tag === 3)\n obj.changeset = pbf.readVarint(true);\n else if (tag === 4)\n obj.uid = pbf.readVarint(true);\n else if (tag === 5)\n obj.user_sid = pbf.readVarint();\n else if (tag === 6)\n obj.visible = pbf.readBoolean();\n}\n/**\n * Serializes primitive metadata fields.\n */\nfunction writeInfo(obj, pbf) {\n if (obj.version != null && obj.version !== -1) {\n pbf.writeVarintField(1, obj.version);\n }\n if (obj.timestamp)\n pbf.writeVarintField(2, obj.timestamp);\n if (obj.changeset)\n pbf.writeVarintField(3, obj.changeset);\n if (obj.uid)\n pbf.writeVarintField(4, obj.uid);\n if (obj.user_sid)\n pbf.writeVarintField(5, obj.user_sid);\n if (obj.visible)\n pbf.writeBooleanField(6, obj.visible);\n}\n/**\n * Reads dense node metadata collections.\n */\nfunction readDenseInfo(pbf, end) {\n return pbf.readFields(readDenseInfoField, {\n version: [],\n timestamp: [],\n changeset: [],\n uid: [],\n user_sid: [],\n visible: [],\n }, end);\n}\n/**\n * Populates dense node metadata arrays from packed fields.\n */\nfunction readDenseInfoField(tag, obj, pbf) {\n if (tag === 1)\n pbf.readPackedVarint(obj.version, true);\n else if (tag === 2)\n pbf.readPackedSVarint(obj.timestamp);\n else if (tag === 3)\n pbf.readPackedSVarint(obj.changeset);\n else if (tag === 4)\n pbf.readPackedSVarint(obj.uid);\n else if (tag === 5)\n pbf.readPackedSVarint(obj.user_sid);\n else if (tag === 6)\n pbf.readPackedBoolean(obj.visible);\n}\n/**\n * Serializes dense node metadata arrays.\n */\nfunction writeDenseInfo(obj, pbf) {\n if (obj.version)\n pbf.writePackedVarint(1, obj.version);\n if (obj.timestamp)\n pbf.writePackedSVarint(2, obj.timestamp);\n if (obj.changeset)\n pbf.writePackedSVarint(3, obj.changeset);\n if (obj.uid)\n pbf.writePackedSVarint(4, obj.uid);\n if (obj.user_sid)\n pbf.writePackedSVarint(5, obj.user_sid);\n if (obj.visible)\n pbf.writePackedBoolean(6, obj.visible);\n}\n/**\n * Reads a node primitive from the protobuf stream.\n */\nfunction readNode(pbf, end) {\n return pbf.readFields(readNodeField, { id: 0, keys: [], vals: [], lat: 0, lon: 0 }, end);\n}\n/**\n * Populates node fields based on protobuf tags.\n */\nfunction readNodeField(tag, obj, pbf) {\n if (tag === 1)\n obj.id = pbf.readSVarint();\n else if (tag === 2)\n pbf.readPackedVarint(obj.keys);\n else if (tag === 3)\n pbf.readPackedVarint(obj.vals);\n else if (tag === 4)\n obj.info = readInfo(pbf, pbf.readVarint() + pbf.pos);\n else if (tag === 8)\n obj.lat = pbf.readSVarint();\n else if (tag === 9)\n obj.lon = pbf.readSVarint();\n}\n/**\n * Serializes a node primitive to protobuf.\n */\nfunction writeNode(obj, pbf) {\n if (obj.id)\n pbf.writeSVarintField(1, obj.id);\n if (obj.keys)\n pbf.writePackedVarint(2, obj.keys);\n if (obj.vals)\n pbf.writePackedVarint(3, obj.vals);\n if (obj.info)\n pbf.writeMessage(4, writeInfo, obj.info);\n if (obj.lat)\n pbf.writeSVarintField(8, obj.lat);\n if (obj.lon)\n pbf.writeSVarintField(9, obj.lon);\n}\n/**\n * Reads dense node collections from the protobuf stream.\n */\nfunction readDenseNodes(pbf, end) {\n return pbf.readFields(readDenseNodesField, { id: [], lat: [], lon: [], keys_vals: [] }, end);\n}\n/**\n * Populates dense node arrays using packed encoding.\n */\nfunction readDenseNodesField(tag, obj, pbf) {\n if (tag === 1)\n pbf.readPackedSVarint(obj.id);\n else if (tag === 5) {\n obj.denseinfo = readDenseInfo(pbf, pbf.readVarint() + pbf.pos);\n }\n else if (tag === 8)\n pbf.readPackedSVarint(obj.lat);\n else if (tag === 9)\n pbf.readPackedSVarint(obj.lon);\n else if (tag === 10)\n pbf.readPackedVarint(obj.keys_vals, true);\n}\n/**\n * Serializes dense node collections back to protobuf.\n */\nfunction writeDenseNodes(obj, pbf) {\n if (obj.id)\n pbf.writePackedSVarint(1, obj.id);\n if (obj.denseinfo)\n pbf.writeMessage(5, writeDenseInfo, obj.denseinfo);\n if (obj.lat)\n pbf.writePackedSVarint(8, obj.lat);\n if (obj.lon)\n pbf.writePackedSVarint(9, obj.lon);\n if (obj.keys_vals)\n pbf.writePackedVarint(10, obj.keys_vals);\n}\n/**\n * Reads a way primitive from the protobuf stream.\n */\nfunction readWay(pbf, end) {\n return pbf.readFields(readWayField, { id: 0, keys: [], vals: [], refs: [], lat: [], lon: [] }, end);\n}\n/**\n * Populates way fields based on protobuf tags.\n */\nfunction readWayField(tag, obj, pbf) {\n if (tag === 1)\n obj.id = pbf.readVarint(true);\n else if (tag === 2)\n pbf.readPackedVarint(obj.keys);\n else if (tag === 3)\n pbf.readPackedVarint(obj.vals);\n else if (tag === 4)\n obj.info = readInfo(pbf, pbf.readVarint() + pbf.pos);\n else if (tag === 8)\n pbf.readPackedSVarint(obj.refs);\n}\n/**\n * Serializes a way primitive to protobuf.\n */\nfunction writeWay(obj, pbf) {\n if (obj.id)\n pbf.writeVarintField(1, obj.id);\n if (obj.keys)\n pbf.writePackedVarint(2, obj.keys);\n if (obj.vals)\n pbf.writePackedVarint(3, obj.vals);\n if (obj.info)\n pbf.writeMessage(4, writeInfo, obj.info);\n if (obj.refs)\n pbf.writePackedSVarint(8, obj.refs);\n}\n/**\n * Reads a relation primitive from the protobuf stream.\n */\nfunction readRelation(pbf, end) {\n return pbf.readFields(readRelationField, {\n id: 0,\n keys: [],\n vals: [],\n roles_sid: [],\n memids: [],\n types: [],\n }, end);\n}\n/**\n * Populates relation fields based on protobuf tags.\n */\nfunction readRelationField(tag, obj, pbf) {\n if (tag === 1)\n obj.id = pbf.readVarint(true);\n else if (tag === 2)\n pbf.readPackedVarint(obj.keys);\n else if (tag === 3)\n pbf.readPackedVarint(obj.vals);\n else if (tag === 4)\n obj.info = readInfo(pbf, pbf.readVarint() + pbf.pos);\n else if (tag === 8)\n pbf.readPackedVarint(obj.roles_sid, true);\n else if (tag === 9)\n pbf.readPackedSVarint(obj.memids);\n else if (tag === 10)\n pbf.readPackedVarint(obj.types);\n}\n/**\n * Serializes a relation primitive to protobuf.\n */\nfunction writeRelation(obj, pbf) {\n if (obj.id)\n pbf.writeVarintField(1, obj.id);\n if (obj.keys)\n pbf.writePackedVarint(2, obj.keys);\n if (obj.vals)\n pbf.writePackedVarint(3, obj.vals);\n if (obj.info)\n pbf.writeMessage(4, writeInfo, obj.info);\n if (obj.roles_sid)\n pbf.writePackedVarint(8, obj.roles_sid);\n if (obj.memids)\n pbf.writePackedSVarint(9, obj.memids);\n if (obj.types)\n pbf.writePackedVarint(10, obj.types);\n}\n//# sourceMappingURL=osmformat.js.map","/**\n * Byte array to stream conversion.\n *\n * Wraps a Uint8Array in a ReadableStream for use with streaming APIs.\n *\n * @module\n */\n/**\n * Create a ReadableStream from a Uint8Array.\n *\n * The stream will emit the entire byte array as a single chunk,\n * then close immediately.\n *\n * @param bytes - The byte array to wrap.\n * @returns A ReadableStream that emits the bytes.\n */\nexport function bytesToStream(bytes) {\n return new ReadableStream({\n start(controller) {\n controller.enqueue(bytes);\n controller.close();\n },\n });\n}\n//# sourceMappingURL=bytes-to-stream.js.map","/**\n * Concatenates multiple `Uint8Array` segments into a contiguous array.\n */\nexport function concatBytes(parts) {\n const total = parts.reduce((n, p) => n + p.length, 0);\n const out = new Uint8Array(new ArrayBuffer(total));\n let offset = 0;\n for (const p of parts) {\n out.set(p, offset);\n offset += p.length;\n }\n return out;\n}\n//# sourceMappingURL=concat-bytes.js.map","/**\n * Stream to byte array conversion.\n *\n * Consumes a ReadableStream and concatenates all chunks into a single Uint8Array.\n *\n * @module\n */\nimport { concatBytes } from \"./concat-bytes.js\";\n/**\n * Consume a ReadableStream and return all data as a single Uint8Array.\n *\n * Reads all chunks from the stream and concatenates them.\n * The stream will be fully consumed after this function returns.\n *\n * @param stream - The stream to consume.\n * @returns A Promise resolving to the concatenated bytes.\n */\nexport async function streamToBytes(stream) {\n const reader = stream.getReader();\n const chunks = [];\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (value !== undefined)\n chunks.push(value);\n }\n return concatBytes(chunks);\n}\n//# sourceMappingURL=stream-to-bytes.js.map","/**\n * Transform stream utilities.\n *\n * Helpers for piping byte arrays through TransformStreams (e.g., compression).\n *\n * @module\n */\nimport { bytesToStream } from \"./bytes-to-stream.js\";\nimport { streamToBytes } from \"./stream-to-bytes.js\";\n/**\n * Pipe a byte array through a TransformStream and return the result.\n *\n * Useful for applying compression/decompression or other transformations\n * to byte data using the Web Streams API.\n *\n * @param bytes - The input bytes.\n * @param transformStream - The transform to apply (e.g., CompressionStream).\n * @returns A Promise resolving to the transformed bytes.\n *\n * @example\n * ```ts\n * const compressed = await transformBytes(data, new CompressionStream('gzip'))\n * ```\n */\nexport async function transformBytes(bytes, transformStream) {\n return streamToBytes(bytesToStream(bytes).pipeThrough(transformStream));\n}\n//# sourceMappingURL=transform-bytes.js.map","import { assertValue as assert } from \"@osmix/shared/assert\";\nimport { transformBytes } from \"@osmix/shared/transform-bytes\";\n/**\n * Normalizes values, streams, and iterables into a unified async generator interface.\n */\nexport async function* toAsyncGenerator(v) {\n if (v instanceof Promise)\n return toAsyncGenerator(await v);\n if (v == null)\n throw Error(\"Value is null\");\n if (v instanceof ReadableStream) {\n const reader = v.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done)\n break;\n yield value;\n }\n reader.releaseLock();\n }\n else if (ArrayBuffer.isView(v) || v instanceof ArrayBuffer) {\n // Treat ArrayBuffer and TypedArrays (like Uint8Array, Buffer) as single values\n yield v;\n }\n else if (typeof v === \"object\" &&\n (Symbol.asyncIterator in v || Symbol.iterator in v)) {\n return v;\n }\n else {\n yield v;\n }\n}\n/**\n * Web decompression stream\n */\nexport async function webDecompress(data) {\n return transformBytes(data, new DecompressionStream(\"deflate\"));\n}\n/**\n * Web compression stream\n */\nexport async function webCompress(data) {\n return transformBytes(data, new CompressionStream(\"deflate\"));\n}\n/**\n * Concatenates multiple `Uint8Array` segments into a contiguous array.\n */\nexport function concatUint8(...parts) {\n const total = parts.reduce((n, p) => n + p.length, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const p of parts) {\n out.set(p, offset);\n offset += p.length;\n }\n return out;\n}\n/**\n * Encodes a 32-bit big-endian unsigned integer as a four-byte buffer.\n */\nexport function uint32BE(n) {\n const out = new Uint8Array(4);\n out[0] = (n >>> 24) & 0xff;\n out[1] = (n >>> 16) & 0xff;\n out[2] = (n >>> 8) & 0xff;\n out[3] = n & 0xff;\n return out;\n}\nexport async function testOsmPbfReader(osm, pbf) {\n assert(JSON.stringify(osm.header.bbox) === JSON.stringify(pbf.bbox), `Header bbox ${JSON.stringify(osm.header.bbox)} != ${JSON.stringify(pbf.bbox)}`);\n const { onGroup, count } = createOsmEntityCounter();\n for await (const block of osm.blocks)\n for (const group of block.primitivegroup)\n onGroup(group);\n assert(count.nodes === pbf.nodes, `Expected nodes: ${pbf.nodes}, got: ${count.nodes}`);\n assert(count.ways === pbf.ways, `Expected ways: ${pbf.ways}, got: ${count.ways}`);\n assert(count.relations === pbf.relations, `Expected relations: ${pbf.relations}, got: ${count.relations}`);\n assert(count.node0 === pbf.node0.id, `Expected node0: ${pbf.node0.id}, got: ${count.node0}`);\n assert(count.way0 === pbf.way0, `Expected way0: ${pbf.way0}, got: ${count.way0}`);\n assert(count.relation0 === pbf.relation0, `Expected relation0: ${pbf.relation0}, got: ${count.relation0}`);\n return count;\n}\nexport function createOsmEntityCounter() {\n const count = {\n nodes: 0,\n ways: 0,\n relations: 0,\n node0: -1,\n way0: -1,\n relation0: -1,\n };\n const onGroup = (group) => {\n if (count.node0 === -1 && group.dense?.id?.[0] != null) {\n count.node0 = group.dense.id[0];\n }\n if (count.way0 === -1 && group.ways?.[0]?.id != null) {\n count.way0 = group.ways[0].id;\n }\n if (count.relation0 === -1 && group.relations?.[0]?.id != null) {\n count.relation0 = group.relations[0].id;\n }\n count.nodes += group.nodes?.length ?? 0;\n if (group.dense) {\n count.nodes += group.dense.id.length;\n }\n count.ways += group.ways?.length ?? 0;\n count.relations += group.relations?.length ?? 0;\n };\n return {\n onGroup,\n count,\n };\n}\n//# sourceMappingURL=utils.js.map","/**\n * Blob-to-block conversion utilities.\n *\n * Handles decompression and protobuf decoding of raw OSM PBF blobs into\n * typed header and primitive block structures.\n *\n * @module\n */\nimport Pbf from \"pbf\";\nimport { readHeaderBlock, readPrimitiveBlock, } from \"./proto/osmformat.js\";\nimport { webDecompress } from \"./utils.js\";\n/**\n * Decompress and decode a stream of raw PBF blobs into typed blocks.\n *\n * This async generator handles the transition from compressed bytes to parsed\n * protobuf structures. The first blob is always decoded as a header block;\n * subsequent blobs are decoded as primitive blocks containing OSM entities.\n *\n * @param blobs - Async or sync generator yielding compressed blob payloads.\n * @param decompress - Optional decompression function (defaults to Web Streams zlib).\n * @yields Header block first, then primitive blocks.\n *\n * @example\n * ```ts\n * import { osmPbfBlobsToBlocksGenerator, createOsmPbfBlobGenerator } from \"@osmix/pbf\"\n *\n * const generateBlobs = createOsmPbfBlobGenerator()\n * const blobsGen = (async function* () {\n * for await (const chunk of stream) {\n * yield* generateBlobs(chunk)\n * }\n * })()\n *\n * for await (const block of osmPbfBlobsToBlocksGenerator(blobsGen)) {\n * // First iteration yields header, rest yield primitive blocks\n * }\n * ```\n */\nexport async function* osmPbfBlobsToBlocksGenerator(blobs, decompress = webDecompress) {\n let headerRead = false;\n for await (const blob of blobs) {\n if (!headerRead) {\n headerRead = true;\n yield readOsmHeaderBlock(blob, decompress);\n }\n else {\n yield readOsmPrimitiveBlock(blob, decompress);\n }\n }\n}\n/**\n * Decompress and parse a header block from a compressed blob.\n *\n * @param compressedBlob - Zlib-compressed protobuf header blob.\n * @param decompress - Optional decompression function.\n * @returns Parsed header block with required/optional features and bbox.\n */\nexport async function readOsmHeaderBlock(compressedBlob, decompress = webDecompress) {\n const decompressedBlob = await decompress(compressedBlob);\n const pbf = new Pbf(decompressedBlob);\n return readHeaderBlock(pbf);\n}\n/**\n * Decompress and parse a primitive block from a compressed blob.\n *\n * @param compressedBlob - Zlib-compressed protobuf primitive blob.\n * @param decompress - Optional decompression function.\n * @returns Parsed primitive block with string table and primitive groups.\n */\nexport async function readOsmPrimitiveBlock(compressedBlob, decompress = webDecompress) {\n const decompressedBlob = await decompress(compressedBlob);\n const pbf = new Pbf(decompressedBlob);\n return readPrimitiveBlock(pbf);\n}\n//# sourceMappingURL=blobs-to-blocks.js.map","/**\n * Reads an `OsmPbfBlob` message from the current position in the Pbf reader.\n */\nexport function readBlob(pbf, end) {\n return pbf.readFields(readBlobField, {\n raw_size: 0,\n }, end);\n}\n/**\n * Dispatches individual Blob fields based on their protobuf tag.\n */\nfunction readBlobField(tag, obj, pbf) {\n if (tag === 2)\n obj.raw_size = pbf.readVarint(true);\n else if (tag === 1) {\n obj.raw = pbf.readBytes();\n }\n else if (tag === 3) {\n obj.zlib_data = pbf.readBytes();\n }\n}\n/**\n * Writes an `OsmPbfBlob` message to the provided Pbf writer.\n */\nexport function writeBlob(obj, pbf) {\n if (obj.raw_size)\n pbf.writeVarintField(2, obj.raw_size);\n if (obj.raw != null)\n pbf.writeBytesField(1, obj.raw);\n if (obj.zlib_data != null)\n pbf.writeBytesField(3, obj.zlib_data);\n}\n/**\n * Reads an `OsmPbfBlobHeader` from the current position in the Pbf reader.\n */\nexport function readBlobHeader(pbf, end) {\n return pbf.readFields(readBlobHeaderField, { type: \"OSMData\", datasize: 0 }, end);\n}\n/**\n * Dispatches individual BlobHeader fields based on their protobuf tag.\n */\nfunction readBlobHeaderField(tag, obj, pbf) {\n if (tag === 1)\n obj.type = pbf.readString();\n else if (tag === 3)\n obj.datasize = pbf.readVarint(true);\n}\n/**\n * Writes an `OsmPbfBlobHeader` message to the provided Pbf writer.\n */\nexport function writeBlobHeader(obj, pbf) {\n if (obj.type)\n pbf.writeStringField(1, obj.type);\n if (obj.datasize)\n pbf.writeVarintField(3, obj.datasize);\n}\n//# sourceMappingURL=fileformat.js.map","// Recommended and maximum header and blob sizes as defined by the OSM PBF specification\n// Header: 32 KiB and 64 KiB\nexport const RECOMMENDED_HEADER_SIZE_BYTES = 32 * 1024;\nexport const MAX_HEADER_SIZE_BYTES = 64 * 1024;\n// Blob: 16 MiB and 32 MiB\nexport const RECOMMENDED_BLOB_SIZE_BYTES = 16 * 1024 * 1024;\nexport const MAX_BLOB_SIZE_BYTES = 32 * 1024 * 1024;\n// Recommended maximum number of entities per block\nexport const MAX_ENTITIES_PER_BLOCK = 8_000;\n//# sourceMappingURL=spec.js.map","/**\n * Block-to-PBF serialization utilities.\n *\n * Converts parsed OSM header and primitive blocks back into spec-compliant\n * PBF byte sequences with proper framing, compression, and size validation.\n *\n * @module\n */\nimport Pbf from \"pbf\";\nimport { writeBlob, writeBlobHeader } from \"./proto/fileformat.js\";\nimport { writeHeaderBlock, writePrimitiveBlock } from \"./proto/osmformat.js\";\nimport { MAX_BLOB_SIZE_BYTES, MAX_HEADER_SIZE_BYTES, RECOMMENDED_BLOB_SIZE_BYTES, RECOMMENDED_HEADER_SIZE_BYTES, } from \"./spec.js\";\nimport { concatUint8, uint32BE, webCompress } from \"./utils.js\";\n/**\n * Serialize a header or primitive block into spec-compliant PBF bytes.\n *\n * Handles protobuf encoding, zlib compression, blob wrapping, and length prefixing.\n * Validates output against OSM PBF specification size limits and logs warnings\n * if recommended sizes are exceeded.\n *\n * @param block - Parsed header or primitive block to encode.\n * @param compress - Optional compression function (defaults to Web Streams zlib).\n * @returns Complete blob bytes: 4-byte length prefix + BlobHeader + Blob.\n * @throws If blob exceeds maximum size limits (64 KiB header, 32 MiB data).\n *\n * @example\n * ```ts\n * import { osmBlockToPbfBlobBytes } from \"@osmix/pbf\"\n *\n * const headerBytes = await osmBlockToPbfBlobBytes({\n * required_features: [\"OsmSchema-V0.6\", \"DenseNodes\"],\n * optional_features: [],\n * })\n * ```\n */\nexport async function osmBlockToPbfBlobBytes(block, compress = webCompress) {\n const contentPbf = new Pbf();\n let type;\n if (\"primitivegroup\" in block) {\n type = \"OSMData\";\n writePrimitiveBlock(block, contentPbf);\n }\n else {\n type = \"OSMHeader\";\n writeHeaderBlock(block, contentPbf);\n }\n const contentData = contentPbf.finish();\n const raw_size = contentData.length;\n const compressedBuffer = await compress(contentData);\n const blobPbf = new Pbf();\n writeBlob({\n raw_size,\n zlib_data: compressedBuffer,\n }, blobPbf);\n const blob = blobPbf.finish();\n const blobHeaderPbf = new Pbf();\n writeBlobHeader({\n type,\n datasize: blob.length,\n }, blobHeaderPbf);\n const blobHeader = blobHeaderPbf.finish();\n const blobHeaderSize = uint32BE(blobHeader.byteLength);\n // Check the BlobHeader and Blob sizes, log error if over the recommended size, throw error if over the maximum size\n if (blobHeader.byteLength > RECOMMENDED_HEADER_SIZE_BYTES) {\n const sizeKiB = (blobHeader.byteLength / 1024).toFixed(2);\n if (blobHeader.byteLength > MAX_HEADER_SIZE_BYTES) {\n throw new Error(`BlobHeader is ${sizeKiB} KiB, the maximum size is 64KiB`);\n }\n console.warn(`BlobHeader is ${sizeKiB} KiB, the recommended size is 32KiB`);\n }\n if (blob.byteLength > RECOMMENDED_BLOB_SIZE_BYTES) {\n const sizeMiB = (blob.byteLength / 1024 / 1024).toFixed(2);\n if (blob.byteLength > MAX_BLOB_SIZE_BYTES) {\n throw new Error(`Blob is ${sizeMiB} MiB, the maximum size is 32MiB`);\n }\n console.warn(`Blob is ${sizeMiB} MiB, the recommended size is 16MiB`);\n }\n return concatUint8(blobHeaderSize, blobHeader, blob);\n}\n/**\n * Web `TransformStream` that encodes OSM blocks into PBF byte chunks.\n *\n * Accepts a stream of header and primitive blocks and outputs spec-compliant\n * PBF bytes. The header block must be the first item in the stream.\n *\n * @throws If a primitive block is received before the header.\n *\n * @example\n * ```ts\n * import { OsmBlocksToPbfBytesTransformStream } from \"@osmix/pbf\"\n *\n * const pbfStream = blocksStream.pipeThrough(new OsmBlocksToPbfBytesTransformStream())\n * await pbfStream.pipeTo(writableFile)\n * ```\n */\nexport class OsmBlocksToPbfBytesTransformStream extends TransformStream {\n headerEnqueued = false;\n constructor() {\n super({\n transform: async (block, controller) => {\n if (\"primitivegroup\" in block && !this.headerEnqueued) {\n throw Error(\"Header first in ReadableStream of blocks.\");\n }\n this.headerEnqueued = true;\n controller.enqueue(await osmBlockToPbfBlobBytes(block));\n },\n });\n }\n}\n//# sourceMappingURL=blocks-to-pbf.js.map","import Pbf from \"pbf\";\nimport { osmPbfBlobsToBlocksGenerator } from \"./blobs-to-blocks.js\";\nimport { createOsmPbfBlobGenerator } from \"./pbf-to-blobs.js\";\nimport { readHeaderBlock, readPrimitiveBlock, } from \"./proto/osmformat.js\";\nimport { toAsyncGenerator, webDecompress, } from \"./utils.js\";\n/** Number of bytes used to encode the BlobHeader length prefix (big-endian uint32). */\nexport const HEADER_LENGTH_BYTES = 4;\n/**\n * Parse an OSM PBF file from various input sources.\n *\n * Accepts `ArrayBuffer`, `Uint8Array`, `ReadableStream<Uint8Array>`, or async generators.\n * Returns the file header and a lazy async generator of primitive blocks for on-demand parsing.\n *\n * @param data - PBF bytes as buffer, stream, or async iterable.\n * @returns Object with `header` (file metadata) and `blocks` (async generator of primitive blocks).\n * @throws If the header block is missing or malformed.\n *\n * @example\n * ```ts\n * import { readOsmPbf } from \"@osmix/pbf\"\n *\n * // From a file stream\n * const { header, blocks } = await readOsmPbf(Bun.file('./monaco.pbf').stream())\n *\n * // From a fetch response\n * const response = await fetch('/data/monaco.pbf')\n * const { header, blocks } = await readOsmPbf(response.body!)\n *\n * // Iterate blocks lazily\n * for await (const block of blocks) {\n * for (const group of block.primitivegroup) {\n * console.log(group.dense?.id.length ?? 0, \"dense nodes\")\n * }\n * }\n * ```\n */\nexport async function readOsmPbf(data) {\n const generateBlobsFromChunk = createOsmPbfBlobGenerator();\n const blocks = osmPbfBlobsToBlocksGenerator((async function* () {\n for await (const chunk of toAsyncGenerator(data)) {\n for await (const blob of generateBlobsFromChunk(chunk)) {\n yield blob;\n }\n }\n })());\n const header = (await blocks.next()).value;\n if (header == null || !(\"required_features\" in header)) {\n throw Error(\"OSM PBF header block not found\");\n }\n return {\n header,\n blocks: blocks,\n };\n}\n/**\n * Web `TransformStream` that decodes raw PBF byte chunks into OSM header and data blocks.\n *\n * The first blob in an OSM PBF file is always the header block; subsequent blobs\n * contain primitive data (nodes, ways, relations). This stream handles the framing,\n * decompression, and protobuf decoding automatically.\n *\n * @example\n * ```ts\n * import { OsmPbfBytesToBlocksTransformStream } from \"@osmix/pbf\"\n *\n * const response = await fetch('/data/monaco.pbf')\n * const blocksStream = response.body!\n * .pipeThrough(new OsmPbfBytesToBlocksTransformStream())\n *\n * const reader = blocksStream.getReader()\n * const { value: header } = await reader.read() // First read yields header\n * // Subsequent reads yield primitive blocks\n * ```\n */\nexport class OsmPbfBytesToBlocksTransformStream extends TransformStream {\n generateBlobsFromChunk = createOsmPbfBlobGenerator();\n header = null;\n constructor(decompress = webDecompress) {\n super({\n transform: async (bytesChunk, controller) => {\n for await (const rawBlobs of this.generateBlobsFromChunk(bytesChunk)) {\n const decompressed = await decompress(rawBlobs);\n const pbf = new Pbf(decompressed);\n if (this.header == null) {\n this.header = readHeaderBlock(pbf);\n controller.enqueue(this.header);\n }\n else {\n controller.enqueue(readPrimitiveBlock(pbf));\n }\n }\n },\n });\n }\n}\n//# sourceMappingURL=pbf-to-blocks.js.map","import Pbf from \"pbf\";\nimport { HEADER_LENGTH_BYTES } from \"./pbf-to-blocks.js\";\nimport { readBlob, readBlobHeader, } from \"./proto/fileformat.js\";\n/**\n * Create a stateful parser that extracts compressed blobs from raw PBF bytes.\n *\n * OSM PBF files consist of length-prefixed blobs. This function returns a generator\n * that accumulates incoming byte chunks and yields complete compressed blobs as they\n * become available. The caller is responsible for decompression.\n *\n * The first yielded blob contains the file header; subsequent blobs contain primitive data.\n *\n * @returns A generator function that accepts byte chunks and yields compressed blob payloads.\n *\n * @example\n * ```ts\n * import { createOsmPbfBlobGenerator } from \"@osmix/pbf\"\n *\n * const generateBlobs = createOsmPbfBlobGenerator()\n *\n * for await (const chunk of stream) {\n * for (const compressedBlob of generateBlobs(chunk)) {\n * // Decompress and parse blob...\n * }\n * }\n * ```\n */\nexport function createOsmPbfBlobGenerator() {\n let pbf = new Pbf(new Uint8Array(0));\n let state = \"header-length\";\n let bytesNeeded = HEADER_LENGTH_BYTES;\n let blobHeader = null;\n /**\n * Feed the parser with the next chunk of bytes and yield any complete compressed blobs.\n * @param chunk - Raw bytes from the PBF file.\n * @yields Compressed blob payloads (zlib-compressed protobuf data).\n */\n return function* nextChunk(chunk) {\n const currentBuffer = pbf.buf.slice(pbf.pos);\n const tmpBuffer = new Uint8Array(currentBuffer.buffer.byteLength + chunk.byteLength);\n tmpBuffer.set(currentBuffer.subarray(0));\n tmpBuffer.set(new Uint8Array(chunk), currentBuffer.byteLength);\n pbf = new Pbf(tmpBuffer);\n while (pbf.pos + bytesNeeded <= pbf.length) {\n if (state === \"header-length\") {\n const dataView = new DataView(pbf.buf.buffer);\n bytesNeeded = dataView.getInt32(pbf.pos, false); // network byte order\n pbf.pos += HEADER_LENGTH_BYTES;\n state = \"header\";\n }\n else if (state === \"header\") {\n blobHeader = readBlobHeader(pbf, pbf.pos + bytesNeeded);\n bytesNeeded = blobHeader.datasize;\n state = \"blob\";\n }\n else if (state === \"blob\") {\n if (blobHeader == null)\n throw Error(\"Blob header has not been read\");\n const blob = readBlob(pbf, pbf.pos + bytesNeeded);\n if (blob.zlib_data === undefined || blob.zlib_data.length === 0)\n throw Error(\"Blob has no zlib data. Format is unsupported.\");\n yield blob.zlib_data;\n state = \"header-length\";\n bytesNeeded = HEADER_LENGTH_BYTES;\n blobHeader = null;\n }\n }\n };\n}\n//# sourceMappingURL=pbf-to-blobs.js.map","import type {\n OsmPbfBlock,\n OsmPbfNode,\n OsmPbfDenseNodes,\n OsmPbfWay,\n OsmPbfRelation,\n} from '@osmix/pbf';\n\nimport type { OsmElement } from '../load-osm-from-overpass-api/interfaces';\n\nconst TEXT_DECODER = new TextDecoder();\n\n/**\n * Converts a `@osmix/pbf` block into an array of `OsmElement` records.\n *\n * Handles all four primitive types:\n * - regular nodes\n * - dense nodes (delta-encoded, compact storage)\n * - ways (with node refs)\n * - relations (with member refs)\n *\n * StringTable indices are resolved to actual tag strings.\n * Way geometry is **not** resolved here — caller must build a node index\n * and call `resolveWayGeometries()` afterwards.\n */\nexport function blockToElements(block: OsmPbfBlock): OsmElement[] {\n const elements: OsmElement[] = [];\n const st = block.stringtable;\n const str = (sid: number) => TEXT_DECODER.decode(st[sid]);\n\n for (const group of block.primitivegroup) {\n // Regular nodes\n for (const node of group.nodes ?? []) {\n elements.push(pbfNodeToElement(node, block, str));\n }\n\n // Dense nodes (compact delta-encoded format)\n if (group.dense) {\n elements.push(...denseNodesToElements(group.dense, block, str));\n }\n\n // Ways\n for (const way of group.ways ?? []) {\n elements.push(pbfWayToElement(way, block, str));\n }\n\n // Relations\n for (const rel of group.relations ?? []) {\n elements.push(pbfRelationToElement(rel, block, str));\n }\n }\n\n return elements;\n}\n\n// ---------------------------------------------------------------------------\n// Internal converters\n// ---------------------------------------------------------------------------\n\nfunction pbfNodeToElement(\n node: OsmPbfNode,\n block: OsmPbfBlock,\n _str: (sid: number) => string,\n): OsmElement {\n return {\n type: 'node',\n id: node.id,\n lat: decodeLat(block, node.lat),\n lon: decodeLon(block, node.lon),\n tags: tagsFromKv(node.keys, node.vals, block, _str),\n };\n}\n\nfunction denseNodesToElements(\n dense: OsmPbfDenseNodes,\n block: OsmPbfBlock,\n str: (sid: number) => string,\n): OsmElement[] {\n const elements: OsmElement[] = [];\n const { id, lat, lon, keys_vals } = dense;\n\n let prevId = 0;\n let prevLat = 0;\n let prevLon = 0;\n let kvIdx = 0;\n\n for (let i = 0; i < id.length; i++) {\n // Delta decoding\n prevId += id[i];\n prevLat += lat[i];\n prevLon += lon[i];\n\n // Decode tags from interleaved keys_vals array\n const tags: Record<string, string> = {};\n while (kvIdx < keys_vals.length) {\n const keySid = keys_vals[kvIdx];\n if (keySid === 0) {\n kvIdx++; // skip sentinel\n break;\n }\n const valSid = keys_vals[kvIdx + 1];\n tags[str(keySid)] = str(valSid);\n kvIdx += 2;\n }\n\n elements.push({\n type: 'node',\n id: prevId,\n lat: decodeLat(block, prevLat),\n lon: decodeLon(block, prevLon),\n tags: Object.keys(tags).length > 0 ? tags : undefined,\n });\n }\n\n return elements;\n}\n\nfunction pbfWayToElement(\n way: OsmPbfWay,\n _block: OsmPbfBlock,\n str: (sid: number) => string,\n): OsmElement {\n // Delta-decode refs\n const refs: number[] = [];\n let prevRef = 0;\n for (const ref of way.refs) {\n prevRef += ref;\n refs.push(prevRef);\n }\n\n return {\n type: 'way',\n id: way.id,\n nodes: refs,\n geometry: undefined, // resolved later by caller\n tags: tagsFromKv(way.keys, way.vals, _block, str),\n };\n}\n\nfunction pbfRelationToElement(\n rel: OsmPbfRelation,\n _block: OsmPbfBlock,\n str: (sid: number) => string,\n): OsmElement {\n // Delta-decode member IDs\n const members: OsmElement['members'] = [];\n let prevMemId = 0;\n for (let i = 0; i < rel.memids.length; i++) {\n prevMemId += rel.memids[i];\n const memberType = rel.types[i];\n const typeMap: Record<number, 'node' | 'way' | 'relation'> = {\n 0: 'node',\n 1: 'way',\n 2: 'relation',\n };\n members.push({\n type: typeMap[memberType] ?? 'node',\n ref: prevMemId,\n role: rel.roles_sid[i] !== undefined ? str(rel.roles_sid[i]) : '',\n });\n }\n\n return {\n type: 'relation',\n id: rel.id,\n members,\n tags: tagsFromKv(rel.keys, rel.vals, _block, str),\n };\n}\n\nfunction tagsFromKv(\n keys: number[],\n vals: number[],\n _block: OsmPbfBlock,\n str: (sid: number) => string,\n): Record<string, string> | undefined {\n if (keys.length === 0) return undefined;\n const tags: Record<string, string> = {};\n for (let i = 0; i < keys.length; i++) {\n tags[str(keys[i])] = str(vals[i]);\n }\n return tags;\n}\n\nfunction decodeLat(block: OsmPbfBlock, value: number): number {\n return value / (block.granularity ?? 1e7) + (block.lat_offset ?? 0);\n}\n\nfunction decodeLon(block: OsmPbfBlock, value: number): number {\n return value / (block.granularity ?? 1e7) + (block.lon_offset ?? 0);\n}\n\n/**\n * Resolves inline `geometry` for every way by looking up node coordinates.\n *\n * Mutates the `elements` array in place — each way that has a non-empty\n * `nodes[]` array gets a matching `geometry[]` array.\n *\n * @returns A `Map<nodeId, {lat, lon}>` for downstream use (e.g. bbox computation).\n */\nexport function resolveWayGeometries(elements: OsmElement[]): Map<number, { lat: number; lon: number }> {\n const nodeIndex = new Map<number, { lat: number; lon: number }>();\n\n // Build node index\n for (const el of elements) {\n if (el.type === 'node' && el.lat !== undefined && el.lon !== undefined) {\n nodeIndex.set(el.id, { lat: el.lat, lon: el.lon });\n }\n }\n\n // Resolve way geometries\n for (const el of elements) {\n if (el.type === 'way' && el.nodes && el.nodes.length > 0) {\n const geometry: { lat: number; lon: number }[] = [];\n for (const nodeId of el.nodes) {\n const coord = nodeIndex.get(nodeId);\n if (coord) {\n geometry.push(coord);\n }\n }\n if (geometry.length > 0) {\n el.geometry = geometry;\n }\n }\n }\n\n return nodeIndex;\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { readOsmPbf } from '@osmix/pbf';\n\nimport { OsmTable } from '../../../shared/interfaces';\nimport {\n EXCLUDED_BUILDING_VALUES,\n EXCLUDED_HIGHWAY_VALUES,\n PARKS_LANDUSE_VALUES,\n PARKS_LEISURE_VALUES,\n PARKS_NATURAL_VALUES,\n WATER_NATURAL_VALUES,\n WATER_FEATURE_VALUES,\n} from '../../../shared/osm-tag-definitions';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport { LoadOsmParams, OsmElement } from '../load-osm-from-overpass-api/interfaces';\nimport { OsmProcessingPipeline } from '../osm-processing-pipeline/OsmProcessingPipeline';\nimport { blockToElements, resolveWayGeometries } from './osm-pbf-parser';\n\ninterface OverpassApiResponse {\n elements: OsmElement[];\n}\n\ninterface OsmExecResult {\n tables: OsmTable[];\n osmElementCount: number;\n boundaryElementCount: number;\n osmDataProcessingMs: number;\n boundariesProcessingMs: number;\n}\n\ntype RequestedLayer = 'roads' | 'buildings' | 'parks' | 'water';\ntype Bbox = { south: number; north: number; west: number; east: number };\n\nclass IdFilter {\n private bits: Uint8Array;\n private bitCount: number;\n\n constructor(bitCount: number = 1 << 27) {\n this.bitCount = bitCount;\n this.bits = new Uint8Array(Math.ceil(bitCount / 8));\n }\n\n add(id: number): void {\n this.setBit(this.hash1(id));\n this.setBit(this.hash2(id));\n this.setBit(this.hash3(id));\n }\n\n has(id: number): boolean {\n return this.getBit(this.hash1(id)) && this.getBit(this.hash2(id)) && this.getBit(this.hash3(id));\n }\n\n private setBit(index: number): void {\n this.bits[index >> 3] |= 1 << (index & 7);\n }\n\n private getBit(index: number): boolean {\n return (this.bits[index >> 3] & (1 << (index & 7))) !== 0;\n }\n\n private hash1(id: number): number {\n return this.mix(id, 0x9e3779b1);\n }\n\n private hash2(id: number): number {\n return this.mix(id, 0x85ebca6b);\n }\n\n private hash3(id: number): number {\n return this.mix(id, 0xc2b2ae35);\n }\n\n private mix(id: number, seed: number): number {\n let x = Math.floor(id) ^ seed;\n x = Math.imul(x ^ (x >>> 16), 0x45d9f3b);\n x = Math.imul(x ^ (x >>> 16), 0x45d9f3b);\n x = x ^ (x >>> 16);\n return (x >>> 0) % this.bitCount;\n }\n}\n\n/**\n * Loads OSM data from a local PBF file with multi-pass streaming.\n */\nexport class LoadOsmFromPbfUseCase {\n private readonly conn: AsyncDuckDBConnection;\n private readonly pipeline: OsmProcessingPipeline;\n\n constructor(conn: AsyncDuckDBConnection, pipeline: OsmProcessingPipeline) {\n this.conn = conn;\n this.pipeline = pipeline;\n }\n\n async exec(params: LoadOsmParams): Promise<OsmExecResult> {\n const pbfFileUrl = params.pbfFileUrl;\n if (!pbfFileUrl) throw new Error('pbfFileUrl must be provided for PBF loading');\n const workspace = params.workspace || 'main';\n const onProgress = params.onProgress;\n const requestedLayers = this.getRequestedLayers(params);\n\n onProgress?.('downloading-osm-data');\n\n const boundaryContext = await this.collectBoundaryContext(pbfFileUrl, params.queryArea.areas);\n const bbox = await this.collectBoundaryBbox(pbfFileUrl, boundaryContext.boundaryWayIds);\n\n onProgress?.('processing-osm-data');\n console.log('[autk-db] PBF pass 3/3: thematic collection started');\n\n const candidates = await this.collectCandidateWaysAndRelations(\n pbfFileUrl,\n boundaryContext.boundaryRelationIds,\n boundaryContext.boundaryWayIds,\n requestedLayers,\n );\n\n await this.collectRequiredNodes(pbfFileUrl, candidates.requiredNodeIds, candidates.elements);\n resolveWayGeometries(candidates.elements);\n\n const filteredElements = this.filterFinalElements(\n candidates.elements,\n bbox,\n boundaryContext.boundaryRelationIds,\n boundaryContext.boundaryWayIds,\n );\n const grouped = this.buildGroupedCollections(\n filteredElements,\n boundaryContext.boundaryRelationIds,\n boundaryContext.boundaryWayIds,\n );\n console.log('[autk-db] PBF pass 3/3: thematic collection finished');\n console.log(\n `[autk-db] PBF filter summary: boundaries=${grouped.boundaries.elements.length}, parks+water=${grouped.parksWater.elements.length}, roads=${grouped.roads.elements.length}, buildings=${grouped.buildings.elements.length}, total=${filteredElements.length}`\n );\n\n const combined = this.mergeResponses(\n this.mergeResponses(grouped.boundaries, grouped.parksWater),\n this.mergeResponses(grouped.roads, grouped.buildings),\n );\n const { osmData, boundariesData } = this.pipeline.splitCombinedResponse(combined, params.queryArea);\n\n const t0 = performance.now();\n await this.pipeline.insertOsmDataUsingJson(params.outputTableName, osmData, workspace);\n const osmDataProcessingMs = performance.now() - t0;\n\n onProgress?.('processing-boundaries');\n const t1 = performance.now();\n await this.pipeline.insertOsmDataUsingJson(`${params.outputTableName}_boundaries`, boundariesData, workspace, true);\n const boundariesProcessingMs = performance.now() - t1;\n\n const qualifiedTableName = `${workspace}.${params.outputTableName}`;\n const tableDescribeResponse = await this.conn.query(`DESCRIBE ${qualifiedTableName}`);\n const columns = getColumnsFromDuckDbTableDescribe(tableDescribeResponse.toArray());\n\n return {\n tables: [\n { source: 'osm', type: 'pointset', name: params.outputTableName, columns },\n { source: 'osm', type: 'pointset', name: `${params.outputTableName}_boundaries`, columns },\n ],\n osmElementCount: osmData.elements.length,\n boundaryElementCount: boundariesData.elements.length,\n osmDataProcessingMs,\n boundariesProcessingMs,\n };\n }\n\n private getRequestedLayers(params: LoadOsmParams): RequestedLayer[] {\n const layers = params.autoLoadLayers?.layers ?? ['roads', 'buildings', 'parks', 'water'];\n return layers.filter((layer): layer is RequestedLayer =>\n layer === 'roads' || layer === 'buildings' || layer === 'parks' || layer === 'water',\n );\n }\n\n // Pass 1: find requested boundary relations and their member ways\n private async collectBoundaryContext(\n pbfFileUrl: string,\n areaNames: string[],\n ): Promise<{\n boundaryRelationIds: Set<number>;\n boundaryWayIds: Set<number>;\n }> {\n console.log('[autk-db] PBF pass 1/3: boundary discovery started');\n const requestedAreaNames = new Set(areaNames);\n const foundAreaNames = new Set<string>();\n const boundaryRelationIds = new Set<number>();\n const boundaryWayIds = new Set<number>();\n\n await this.streamPbfBlocks(pbfFileUrl, async (elements) => {\n for (const element of elements) {\n if (element.type !== 'relation') continue;\n const name = element.tags?.name;\n if (!name || !requestedAreaNames.has(name)) continue;\n\n foundAreaNames.add(name);\n boundaryRelationIds.add(element.id);\n for (const member of element.members ?? []) {\n if (member.type === 'way') boundaryWayIds.add(member.ref);\n }\n }\n });\n\n const missingAreas = areaNames.filter((name) => !foundAreaNames.has(name));\n if (missingAreas.length > 0) {\n throw new Error(\n `No administrative boundary found in PBF for: ${missingAreas.map(a => `\"${a}\"`).join(', ')}. ` +\n `Verify the area names match OSM relation names exactly.`,\n );\n }\n\n console.log(\n `[autk-db] PBF pass 1/3: boundary discovery finished (${boundaryRelationIds.size} relations, ${boundaryWayIds.size} ways)`\n );\n return { boundaryRelationIds, boundaryWayIds };\n }\n\n // Pass 2: collect boundary ways/nodes and compute bbox\n private async collectBoundaryBbox(\n pbfFileUrl: string,\n boundaryWayIds: Set<number>,\n ): Promise<Bbox> {\n console.log('[autk-db] PBF pass 2/3: boundary bbox collection started');\n const elements: OsmElement[] = [];\n const requiredNodeIds = new IdFilter();\n\n await this.streamPbfBlocks(pbfFileUrl, async (blockElements) => {\n for (const element of blockElements) {\n if (element.type !== 'way' || !boundaryWayIds.has(element.id)) continue;\n elements.push(element);\n for (const nodeId of element.nodes ?? []) requiredNodeIds.add(nodeId);\n }\n });\n\n await this.collectRequiredNodes(pbfFileUrl, requiredNodeIds, elements);\n resolveWayGeometries(elements);\n\n const bbox = this.pipeline.computeBboxFromElements(elements);\n if (!bbox) throw new Error('Failed to compute bounding box from boundary elements');\n\n console.log(\n `[autk-db] PBF pass 2/3: boundary bbox collection finished (${bbox.south}, ${bbox.west}) → (${bbox.north}, ${bbox.east})`\n );\n return bbox;\n }\n\n // Pass 3: collect candidate thematic relations + ways and required node ids\n private async collectCandidateWaysAndRelations(\n pbfFileUrl: string,\n boundaryRelationIds: Set<number>,\n boundaryWayIds: Set<number>,\n requestedLayers: RequestedLayer[],\n ): Promise<{\n elements: OsmElement[];\n requiredNodeIds: IdFilter;\n }> {\n const elements: OsmElement[] = [];\n const relationWayIds = new Set<number>();\n\n await this.streamPbfBlocks(pbfFileUrl, async (blockElements) => {\n for (const element of blockElements) {\n if (element.type !== 'relation') continue;\n\n if (boundaryRelationIds.has(element.id) || this.matchesRequestedRelationLayers(element.tags, requestedLayers)) {\n elements.push(element);\n for (const member of element.members ?? []) {\n if (member.type === 'way') relationWayIds.add(member.ref);\n }\n }\n }\n });\n\n const requiredNodeIds = new IdFilter();\n\n await this.streamPbfBlocks(pbfFileUrl, async (blockElements) => {\n for (const element of blockElements) {\n if (element.type !== 'way') continue;\n\n const keep =\n boundaryWayIds.has(element.id) ||\n relationWayIds.has(element.id) ||\n this.matchesRequestedWayLayers(element.tags, requestedLayers);\n\n if (!keep) continue;\n\n elements.push(element);\n for (const nodeId of element.nodes ?? []) {\n requiredNodeIds.add(nodeId);\n }\n }\n });\n\n return { elements, requiredNodeIds };\n }\n\n private async collectRequiredNodes(\n pbfFileUrl: string,\n requiredNodeIds: IdFilter,\n elements: OsmElement[],\n ): Promise<void> {\n await this.streamPbfBlocks(pbfFileUrl, async (blockElements) => {\n for (const element of blockElements) {\n if (element.type !== 'node') continue;\n if (!requiredNodeIds.has(element.id)) continue;\n elements.push(element);\n }\n });\n }\n\n private filterFinalElements(\n elements: OsmElement[],\n bbox: Bbox,\n boundaryRelationIds: Set<number>,\n boundaryWayIds: Set<number>,\n ): OsmElement[] {\n const intersectingWays = new IdFilter();\n\n for (const element of elements) {\n if (element.type !== 'way') continue;\n if (boundaryWayIds.has(element.id) || this.wayIntersectsBbox(element, bbox)) {\n intersectingWays.add(element.id);\n }\n }\n\n const keptRelationIds = new IdFilter();\n const relationMemberWayIds = new IdFilter();\n\n for (const element of elements) {\n if (element.type !== 'relation') continue;\n\n if (boundaryRelationIds.has(element.id)) {\n keptRelationIds.add(element.id);\n for (const member of element.members ?? []) {\n if (member.type === 'way') relationMemberWayIds.add(member.ref);\n }\n continue;\n }\n\n const memberWayRefs = this.getRelationWayRefs(element);\n\n if (memberWayRefs.some((ref) => intersectingWays.has(ref))) {\n keptRelationIds.add(element.id);\n for (const ref of memberWayRefs) relationMemberWayIds.add(ref);\n }\n }\n\n const keptWays = new IdFilter();\n for (const element of elements) {\n if (element.type !== 'way') continue;\n if (intersectingWays.has(element.id) || relationMemberWayIds.has(element.id)) {\n keptWays.add(element.id);\n }\n }\n\n const keptNodeIds = new IdFilter();\n for (const element of elements) {\n if (element.type === 'way' && keptWays.has(element.id)) {\n for (const nodeId of element.nodes ?? []) keptNodeIds.add(nodeId);\n }\n }\n\n return elements.filter((element) => {\n if (element.type === 'way') return keptWays.has(element.id);\n if (element.type === 'node') return keptNodeIds.has(element.id);\n if (element.type === 'relation') return keptRelationIds.has(element.id);\n return false;\n });\n }\n\n private buildGroupedCollections(\n elements: OsmElement[],\n boundaryRelationIds: Set<number>,\n boundaryWayIds: Set<number>,\n ): {\n boundaries: OverpassApiResponse;\n parksWater: OverpassApiResponse;\n roads: OverpassApiResponse;\n buildings: OverpassApiResponse;\n } {\n const boundaryWaySet = new Set<number>();\n const parksWaterWaySet = new Set<number>();\n const roadsWaySet = new Set<number>();\n const buildingsWaySet = new Set<number>();\n\n const boundaryNodeIds = new IdFilter();\n const parksWaterNodeIds = new IdFilter();\n const roadsNodeIds = new IdFilter();\n const buildingsNodeIds = new IdFilter();\n\n const boundaries: OsmElement[] = [];\n const parksWater: OsmElement[] = [];\n const roads: OsmElement[] = [];\n const buildings: OsmElement[] = [];\n\n const addWayNodes = (nodeIds: number[] | undefined, nodeFilter: IdFilter) => {\n for (const nodeId of nodeIds ?? []) nodeFilter.add(nodeId);\n };\n\n for (const element of elements) {\n if (element.type !== 'relation') continue;\n\n if (boundaryRelationIds.has(element.id)) {\n boundaries.push(element);\n for (const member of element.members ?? []) {\n if (member.type === 'way') boundaryWaySet.add(member.ref);\n }\n continue;\n }\n\n if (this.isBuildingTagSet(element.tags ?? {})) {\n buildings.push(element);\n for (const member of element.members ?? []) {\n if (member.type === 'way') buildingsWaySet.add(member.ref);\n }\n continue;\n }\n\n if (this.isRoadTagSet(element.tags ?? {})) {\n roads.push(element);\n for (const member of element.members ?? []) {\n if (member.type === 'way') roadsWaySet.add(member.ref);\n }\n continue;\n }\n\n if (this.isParkTagSet(element.tags ?? {}) || this.isWaterTagSet(element.tags ?? {})) {\n parksWater.push(element);\n for (const member of element.members ?? []) {\n if (member.type === 'way') parksWaterWaySet.add(member.ref);\n }\n }\n }\n\n for (const element of elements) {\n if (element.type !== 'way') continue;\n\n if (boundaryWayIds.has(element.id) || boundaryWaySet.has(element.id)) {\n boundaries.push(element);\n boundaryWaySet.add(element.id);\n addWayNodes(element.nodes, boundaryNodeIds);\n continue;\n }\n if (buildingsWaySet.has(element.id) || this.isBuildingTagSet(element.tags ?? {})) {\n buildings.push(element);\n buildingsWaySet.add(element.id);\n addWayNodes(element.nodes, buildingsNodeIds);\n continue;\n }\n if (roadsWaySet.has(element.id) || this.isRoadTagSet(element.tags ?? {})) {\n roads.push(element);\n roadsWaySet.add(element.id);\n addWayNodes(element.nodes, roadsNodeIds);\n continue;\n }\n if (parksWaterWaySet.has(element.id) || this.isParkTagSet(element.tags ?? {}) || this.isWaterTagSet(element.tags ?? {})) {\n parksWater.push(element);\n parksWaterWaySet.add(element.id);\n addWayNodes(element.nodes, parksWaterNodeIds);\n continue;\n }\n }\n\n for (const element of elements) {\n if (element.type !== 'node') continue;\n if (boundaryNodeIds.has(element.id)) boundaries.push(element);\n if (parksWaterNodeIds.has(element.id)) parksWater.push(element);\n if (roadsNodeIds.has(element.id)) roads.push(element);\n if (buildingsNodeIds.has(element.id)) buildings.push(element);\n }\n\n return {\n boundaries: { elements: boundaries },\n parksWater: { elements: parksWater },\n roads: { elements: roads },\n buildings: { elements: buildings },\n };\n }\n\n private mergeResponses(a: OverpassApiResponse, b: OverpassApiResponse): OverpassApiResponse {\n const existingIds = new Set<string>();\n for (const e of a.elements) existingIds.add(`${e.type}:${e.id}`);\n const dedupedB = b.elements.filter(e => !existingIds.has(`${e.type}:${e.id}`));\n return { elements: [...a.elements, ...dedupedB] };\n }\n\n private getRelationWayRefs(element: OsmElement): number[] {\n return (element.members ?? [])\n .filter((member) => member.type === 'way')\n .map((member) => member.ref);\n }\n\n private wayIntersectsBbox(element: OsmElement, bbox: Bbox): boolean {\n const points = element.geometry;\n if (!points || points.length === 0) return false;\n\n let minLat = Infinity;\n let maxLat = -Infinity;\n let minLon = Infinity;\n let maxLon = -Infinity;\n\n for (const pt of points) {\n if (pt.lat < minLat) minLat = pt.lat;\n if (pt.lat > maxLat) maxLat = pt.lat;\n if (pt.lon < minLon) minLon = pt.lon;\n if (pt.lon > maxLon) maxLon = pt.lon;\n }\n\n return !(maxLat < bbox.south || minLat > bbox.north || maxLon < bbox.west || minLon > bbox.east);\n }\n\n private async streamPbfBlocks(\n pbfFileUrl: string,\n onBlock: (elements: OsmElement[]) => Promise<void> | void,\n ): Promise<void> {\n const response = await fetch(pbfFileUrl);\n if (!response.ok || !response.body) {\n throw new Error(`Failed to fetch PBF file: ${response.status} ${response.statusText}`);\n }\n\n const { blocks } = await readOsmPbf(response.body);\n for await (const block of blocks) {\n await onBlock(blockToElements(block));\n }\n }\n\n private matchesRequestedWayLayers(tags: Record<string, string> | undefined, requestedLayers: RequestedLayer[]): boolean {\n if (!tags) return false;\n for (const layer of requestedLayers) {\n switch (layer) {\n case 'roads':\n if (this.isRoadTagSet(tags)) return true;\n break;\n case 'buildings':\n if (this.isBuildingTagSet(tags)) return true;\n break;\n case 'parks':\n if (this.isParkTagSet(tags)) return true;\n break;\n case 'water':\n if (this.isWaterTagSet(tags)) return true;\n break;\n }\n }\n return false;\n }\n\n private matchesRequestedRelationLayers(tags: Record<string, string> | undefined, requestedLayers: RequestedLayer[]): boolean {\n return this.matchesRequestedWayLayers(tags, requestedLayers);\n }\n\n private isRoadTagSet(tags: Record<string, string>): boolean {\n return (\n tags.highway !== undefined &&\n tags.area !== 'yes' &&\n !this.hasTagValue(tags, 'highway', EXCLUDED_HIGHWAY_VALUES)\n );\n }\n\n private isBuildingTagSet(tags: Record<string, string>): boolean {\n return (\n (tags.building !== undefined && !this.hasTagValue(tags, 'building', EXCLUDED_BUILDING_VALUES)) ||\n (tags['building:part'] !== undefined && !this.hasTagValue(tags, 'building:part', EXCLUDED_BUILDING_VALUES)) ||\n tags.type === 'building' ||\n (tags.type === 'multipolygon' && tags.building !== undefined && !this.hasTagValue(tags, 'building', EXCLUDED_BUILDING_VALUES)) ||\n (tags.type === 'multipolygon' && tags['building:part'] !== undefined && !this.hasTagValue(tags, 'building:part', EXCLUDED_BUILDING_VALUES))\n );\n }\n\n private isParkTagSet(tags: Record<string, string>): boolean {\n return (\n this.hasTagValue(tags, 'leisure', PARKS_LEISURE_VALUES) ||\n this.hasTagValue(tags, 'landuse', PARKS_LANDUSE_VALUES) ||\n this.hasTagValue(tags, 'natural', PARKS_NATURAL_VALUES)\n );\n }\n\n private isWaterTagSet(tags: Record<string, string>): boolean {\n return (\n this.hasTagValue(tags, 'natural', WATER_NATURAL_VALUES) ||\n this.hasTagValue(tags, 'water', WATER_FEATURE_VALUES)\n );\n }\n\n private hasTagValue(tags: Record<string, string>, key: string, values: readonly string[]): boolean {\n const value = tags[key];\n return value !== undefined && values.includes(value);\n }\n}\n","export const CREATE_OSM_TABLE_QUERY = (tableName: string, workspace: string): string => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `\n CREATE OR REPLACE TABLE ${qualifiedTableName} (\n kind VARCHAR,\n id BIGINT,\n tags MAP(VARCHAR, VARCHAR),\n refs BIGINT[],\n lat DOUBLE,\n lon DOUBLE,\n ref_roles VARCHAR[],\n ref_types VARCHAR[]\n );\n`;\n};\n\nexport const INSERT_OSM_DATA_QUERY = (tableName: string, fileName: string, workspace: string, ignoreTags: boolean = false): string => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `\n INSERT INTO ${qualifiedTableName} \n SELECT \n kind::VARCHAR,\n id::BIGINT,\n ${\n ignoreTags\n ? 'NULL'\n : `CASE \n WHEN tags IS NULL OR tags = [] THEN NULL\n ELSE map_from_entries(tags)\n END`\n } AS tags,\n refs::BIGINT[],\n lat::DOUBLE,\n lon::DOUBLE,\n ref_roles::VARCHAR[],\n ref_types::VARCHAR[]\n FROM '${fileName}';\n`;\n};\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { OsmElement } from '../load-osm-from-overpass-api/interfaces';\nimport {\n PARKS_LEISURE_VALUES,\n PARKS_LANDUSE_VALUES,\n PARKS_NATURAL_VALUES,\n WATER_NATURAL_VALUES,\n WATER_FEATURE_VALUES,\n EXCLUDED_HIGHWAY_VALUES,\n EXCLUDED_BUILDING_VALUES,\n} from '../../../shared/osm-tag-definitions';\n\nimport { CREATE_OSM_TABLE_QUERY, INSERT_OSM_DATA_QUERY } from '../load-osm-from-overpass-api/queries';\n\ninterface OverpassApiResponse {\n elements: OsmElement[];\n}\n\n/**\n * Shared OSM processing pipeline for splitting, tagging, and inserting OSM data.\n *\n * Consumed identically by both the Overpass API and PBF loading paths.\n */\nexport class OsmProcessingPipeline {\n constructor(\n private readonly db: AsyncDuckDB,\n private readonly conn: AsyncDuckDBConnection,\n ) {}\n\n // ---------------------------------------------------------------------------\n // Response splitting\n // ---------------------------------------------------------------------------\n\n /**\n * Splits the merged OSM response into two datasets:\n * - `osmData`: all nodes, ways, and non-boundary relations\n * - `boundariesData`: only the ways that form admin boundary rings + their nodes\n */\n splitCombinedResponse(\n combined: OverpassApiResponse,\n queryArea: { geocodeArea: string; areas: string[] },\n ): {\n osmData: OverpassApiResponse;\n boundariesData: OverpassApiResponse;\n } {\n const elements = combined.elements ?? [];\n const boundaryRelationIds = this.getBoundaryRelationIds(elements, queryArea.areas);\n\n const boundaryWayIds = new Set<number>();\n for (const element of elements) {\n if (element.type === 'relation' && boundaryRelationIds.has(element.id) && element.members) {\n for (const member of element.members) {\n if (member.type === 'way') boundaryWayIds.add(member.ref);\n }\n }\n }\n\n const osmData: OverpassApiResponse = {\n elements: elements.filter(e => e.type !== 'relation' || !boundaryRelationIds.has(e.id)),\n };\n\n const boundaryNodeIds = new Set<number>();\n for (const element of elements) {\n if (element.type === 'way' && boundaryWayIds.has(element.id) && element.nodes) {\n element.nodes.forEach(nodeId => boundaryNodeIds.add(nodeId));\n }\n }\n\n const boundariesData: OverpassApiResponse = {\n elements: elements.filter(\n e =>\n (e.type === 'way' && boundaryWayIds.has(e.id)) ||\n (e.type === 'node' && boundaryNodeIds.has(e.id)),\n ),\n };\n\n return { osmData, boundariesData };\n }\n\n // ---------------------------------------------------------------------------\n // Bounding-box computation\n // ---------------------------------------------------------------------------\n\n /**\n * Derives the bounding box from elements already in memory.\n * Uses node lat/lon and way inline geometry produced by `out geom qt`\n * or resolved from a PBF node index.\n */\n computeBboxFromElements(\n elements: OsmElement[],\n ): { south: number; north: number; west: number; east: number } | null {\n let minLat = Infinity, maxLat = -Infinity, minLon = Infinity, maxLon = -Infinity;\n let found = false;\n\n for (const el of elements) {\n if (el.type === 'node' && el.lat !== undefined && el.lon !== undefined) {\n if (el.lat < minLat) minLat = el.lat;\n if (el.lat > maxLat) maxLat = el.lat;\n if (el.lon < minLon) minLon = el.lon;\n if (el.lon > maxLon) maxLon = el.lon;\n found = true;\n }\n if (el.type === 'way' && el.geometry) {\n for (const pt of el.geometry) {\n if (pt.lat < minLat) minLat = pt.lat;\n if (pt.lat > maxLat) maxLat = pt.lat;\n if (pt.lon < minLon) minLon = pt.lon;\n if (pt.lon > maxLon) maxLon = pt.lon;\n found = true;\n }\n }\n }\n\n return found ? { south: minLat, north: maxLat, west: minLon, east: maxLon } : null;\n }\n\n // ---------------------------------------------------------------------------\n // Boundary relation detection\n // ---------------------------------------------------------------------------\n\n getBoundaryRelationIds(elements: OsmElement[], areaNames: string[]): Set<number> {\n const boundaryRelationIds = new Set<number>();\n const requestedAreaNames = new Set(areaNames);\n\n for (const element of elements) {\n if (element.type !== 'relation') continue;\n if (element.tags?.name && requestedAreaNames.has(element.tags.name)) {\n boundaryRelationIds.add(element.id);\n }\n }\n\n if (boundaryRelationIds.size === 0) {\n console.warn(\n `[autk-db] Requested area boundary relations were not found by exact name match: ${areaNames.join(', ')}`,\n );\n }\n\n return boundaryRelationIds;\n }\n\n // ---------------------------------------------------------------------------\n // DuckDB insertion\n // ---------------------------------------------------------------------------\n\n async insertOsmDataUsingJson(\n tableName: string,\n osmData: OverpassApiResponse,\n workspace: string,\n ignoreTags: boolean = false,\n ): Promise<void> {\n if ((osmData.elements?.length ?? 0) === 0) {\n await this.conn.query(CREATE_OSM_TABLE_QUERY(tableName, workspace));\n return;\n }\n\n const formattedElements = this.formatOsmDataForJson(osmData);\n if (formattedElements.length === 0) {\n await this.conn.query(CREATE_OSM_TABLE_QUERY(tableName, workspace));\n return;\n }\n\n const payload = JSON.stringify(formattedElements);\n if (!payload || payload.trim().length === 0) {\n throw new Error(`Failed to serialize OSM JSON payload for table ${tableName}`);\n }\n\n const fileName = `osm_data_${tableName}_${Date.now()}_${Math.random().toString(36).slice(2)}.json`;\n\n await this.db.registerFileText(fileName, payload);\n await this.conn.query(CREATE_OSM_TABLE_QUERY(tableName, workspace));\n await this.conn.query(INSERT_OSM_DATA_QUERY(tableName, fileName, workspace, ignoreTags));\n\n try {\n await this.db.dropFile(fileName);\n } catch (e) {\n console.warn(`Failed to cleanup file ${fileName}:`, e);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Element formatting\n // ---------------------------------------------------------------------------\n\n /**\n * Converts a raw OSM response into the flat record format expected by\n * the DuckDB table schema.\n *\n * Ways with inline `geometry` carry both `nodes` (real OSM node IDs) and\n * `geometry` (lat/lon per node). Synthetic node records are emitted from\n * the inline geometry so the SQL layer queries can join on node ID.\n */\n formatOsmDataForJson(osmData: OverpassApiResponse): Array<{\n kind: 'node' | 'way' | 'relation';\n id: number;\n tags: Array<{ k: string; v: string }>;\n refs: number[];\n lat: number | null;\n lon: number | null;\n ref_roles: string[];\n ref_types: string[];\n }> {\n type FormattedElement = {\n kind: 'node' | 'way' | 'relation';\n id: number;\n tags: Array<{ k: string; v: string }>;\n refs: number[];\n lat: number | null;\n lon: number | null;\n ref_roles: string[];\n ref_types: string[];\n };\n\n const formattedElements: FormattedElement[] = [];\n const emittedNodeIds = new Set<number>();\n\n const emitNode = (id: number, lat: number, lon: number) => {\n if (!emittedNodeIds.has(id)) {\n emittedNodeIds.add(id);\n formattedElements.push({ kind: 'node', id, tags: [], refs: [], lat, lon, ref_roles: [], ref_types: [] });\n }\n };\n\n osmData.elements.forEach((element) => {\n switch (element.type) {\n case 'node':\n if (element.lat !== undefined && element.lon !== undefined) {\n emitNode(element.id, element.lat, element.lon);\n }\n break;\n\n case 'way': {\n const refs: number[] = element.nodes ?? [];\n const tags = this.withDerivedLayerTag(element.tags);\n if (element.geometry && element.geometry.length > 0 && element.nodes) {\n for (let i = 0; i < element.nodes.length; i++) {\n const geo = element.geometry[i];\n if (geo) emitNode(element.nodes[i], geo.lat, geo.lon);\n }\n }\n formattedElements.push({\n kind: 'way',\n id: element.id,\n tags: tags ? Object.entries(tags).map(([k, v]) => ({ k, v })) : [],\n refs,\n lat: null,\n lon: null,\n ref_roles: [],\n ref_types: [],\n });\n break;\n }\n\n case 'relation': {\n const refs: number[] = [];\n const ref_roles: string[] = [];\n const ref_types: ('node' | 'way' | 'relation')[] = [];\n const tags = this.withDerivedLayerTag(element.tags);\n if (element.members) {\n element.members.forEach((member) => {\n refs.push(member.ref);\n ref_roles.push(member.role || '');\n ref_types.push(member.type);\n });\n }\n formattedElements.push({\n kind: 'relation',\n id: element.id,\n tags: tags ? Object.entries(tags).map(([k, v]) => ({ k, v })) : [],\n refs,\n lat: null,\n lon: null,\n ref_roles,\n ref_types,\n });\n break;\n }\n }\n });\n\n return formattedElements;\n }\n\n // ---------------------------------------------------------------------------\n // Derived layer tagging\n // ---------------------------------------------------------------------------\n\n private getDerivedLayerTag(tags?: Record<string, string>): 'parks' | 'water' | 'roads' | 'buildings' | null {\n if (!tags) return null;\n\n if (this.isBuildingTagSet(tags)) {\n return 'buildings';\n }\n\n if (this.isRoadTagSet(tags)) {\n return 'roads';\n }\n\n if (\n this.hasTagValue(tags, 'leisure', PARKS_LEISURE_VALUES) ||\n this.hasTagValue(tags, 'landuse', PARKS_LANDUSE_VALUES) ||\n this.hasTagValue(tags, 'natural', PARKS_NATURAL_VALUES)\n ) {\n return 'parks';\n }\n\n if (\n this.hasTagValue(tags, 'natural', WATER_NATURAL_VALUES) ||\n this.hasTagValue(tags, 'water', WATER_FEATURE_VALUES)\n ) {\n return 'water';\n }\n\n return null;\n }\n\n private isRoadTagSet(tags: Record<string, string>): boolean {\n return (\n tags.highway !== undefined &&\n tags.area !== 'yes' &&\n !this.hasTagValue(tags, 'highway', EXCLUDED_HIGHWAY_VALUES)\n );\n }\n\n private isBuildingTagSet(tags: Record<string, string>): boolean {\n const hasBuildingKind =\n (tags.building !== undefined && !this.hasTagValue(tags, 'building', EXCLUDED_BUILDING_VALUES)) ||\n (tags['building:part'] !== undefined && !this.hasTagValue(tags, 'building:part', EXCLUDED_BUILDING_VALUES)) ||\n tags.type === 'building' ||\n (tags.type === 'multipolygon' && tags.building !== undefined && !this.hasTagValue(tags, 'building', EXCLUDED_BUILDING_VALUES)) ||\n (tags.type === 'multipolygon' && tags['building:part'] !== undefined && !this.hasTagValue(tags, 'building:part', EXCLUDED_BUILDING_VALUES));\n\n return hasBuildingKind;\n }\n\n private hasTagValue(tags: Record<string, string>, key: string, values: readonly string[]): boolean {\n const value = tags[key];\n return value !== undefined && values.includes(value);\n }\n\n private withDerivedLayerTag(tags?: Record<string, string>): Record<string, string> | undefined {\n if (!tags) return tags;\n\n const derivedLayer = this.getDerivedLayerTag(tags);\n if (!derivedLayer) return tags;\n\n return {\n ...tags,\n __autk_layer: derivedLayer,\n };\n }\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { BoundingBox, GridLayerTable } from '../../../shared/interfaces';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\n\nexport interface LoadGridLayerParams {\n boundingBox?: BoundingBox;\n rows: number;\n columns: number;\n outputTableName: string;\n workspace?: string;\n}\n\n/**\n * Creates a grid layer table with evenly spaced cell centroids.\n */\nexport class LoadGridLayerUseCase {\n private conn: AsyncDuckDBConnection;\n\n constructor(conn: AsyncDuckDBConnection) {\n this.conn = conn;\n }\n\n async exec(params: LoadGridLayerParams): Promise<GridLayerTable> {\n const { boundingBox, rows, columns, outputTableName, workspace = 'main' } = params;\n const qualifiedTableName = `${workspace}.${outputTableName}`;\n\n if (!boundingBox) {\n throw new Error('Bounding box is required to load a grid layer.');\n }\n\n if (rows <= 0 || columns <= 0) {\n throw new Error('Rows and columns must be positive integers.');\n }\n\n const { minLon, minLat, maxLon, maxLat } = boundingBox;\n\n // 1. Create (or replace) empty table\n const createTableSql = `CREATE OR REPLACE TABLE ${qualifiedTableName} (\n geometry GEOMETRY,\n properties STRUCT(row INTEGER, \"column\" INTEGER)\n );`;\n\n await this.conn.query(createTableSql);\n\n // 2. Generate grid cell centroids in JS and bulk-insert\n const lonStep = (maxLon - minLon) / columns;\n const latStep = (maxLat - minLat) / rows;\n\n const values: string[] = [];\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < columns; c++) {\n // Calculate the center point of each grid cell\n const centerLon = minLon + (c + 0.5) * lonStep;\n const centerLat = minLat + (r + 0.5) * latStep;\n\n values.push(`(ST_Point(${centerLon}, ${centerLat}), {'row': ${r}, 'column': ${c}})`);\n }\n }\n\n const insertSql = `INSERT INTO ${qualifiedTableName} VALUES ${values.join(',')};`;\n\n await this.conn.query(insertSql);\n\n // 3. Create spatial index on geometry column\n const createIndexSql = `CREATE INDEX idx_${outputTableName}_geometry ON ${qualifiedTableName} USING RTREE (geometry);`;\n await this.conn.query(createIndexSql);\n\n const describeTableResponse = await this.conn.query(`DESCRIBE ${qualifiedTableName}`);\n\n return {\n source: 'user',\n type: 'raster',\n name: outputTableName,\n columns: getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray()),\n };\n }\n}\n","export const THIS_IS_NOT_AN_OBJECT = \"This is not an object\";\nexport const THIS_IS_NOT_A_FLOAT16ARRAY_OBJECT = \"This is not a Float16Array object\";\nexport const THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY =\n \"This constructor is not a subclass of Float16Array\";\nexport const THE_CONSTRUCTOR_PROPERTY_VALUE_IS_NOT_AN_OBJECT =\n \"The constructor property value is not an object\";\nexport const SPECIES_CONSTRUCTOR_DIDNT_RETURN_TYPEDARRAY_OBJECT =\n \"Species constructor didn't return TypedArray object\";\nexport const DERIVED_CONSTRUCTOR_CREATED_TYPEDARRAY_OBJECT_WHICH_WAS_TOO_SMALL_LENGTH =\n \"Derived constructor created TypedArray object which was too small length\";\nexport const ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER =\n \"Attempting to access detached ArrayBuffer\";\nexport const CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT =\n \"Cannot convert undefined or null to object\";\nexport const CANNOT_MIX_BIGINT_AND_OTHER_TYPES =\n \"Cannot mix BigInt and other types, use explicit conversions\";\nexport const ITERATOR_PROPERTY_IS_NOT_CALLABLE = \"@@iterator property is not callable\";\nexport const REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE =\n \"Reduce of empty array with no initial value\";\nexport const THE_COMPARISON_FUNCTION_MUST_BE_EITHER_A_FUNCTION_OR_UNDEFINED =\n \"The comparison function must be either a function or undefined\";\nexport const OFFSET_IS_OUT_OF_BOUNDS = \"Offset is out of bounds\";\n","/* eslint-disable no-restricted-globals, no-restricted-syntax */\n/* global SharedArrayBuffer */\n\nimport { CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT } from \"./messages.mjs\";\n\n/** @type {<T extends (...args: any) => any>(target: T) => (thisArg: ThisType<T>, ...args: any[]) => any} */\nfunction uncurryThis(target) {\n return (thisArg, ...args) => {\n return ReflectApply(target, thisArg, args);\n };\n}\n\n/** @type {(target: any, key: string | symbol) => (thisArg: any, ...args: any[]) => any} */\nfunction uncurryThisGetter(target, key) {\n return uncurryThis(\n ReflectGetOwnPropertyDescriptor(\n target,\n key\n ).get\n );\n}\n\n// Reflect\nexport const {\n apply: ReflectApply,\n construct: ReflectConstruct,\n defineProperty: ReflectDefineProperty,\n get: ReflectGet,\n getOwnPropertyDescriptor: ReflectGetOwnPropertyDescriptor,\n getPrototypeOf: ReflectGetPrototypeOf,\n has: ReflectHas,\n ownKeys: ReflectOwnKeys,\n set: ReflectSet,\n setPrototypeOf: ReflectSetPrototypeOf,\n} = Reflect;\n\n// Proxy\nexport const NativeProxy = Proxy;\n\n// Number\nexport const {\n EPSILON,\n MAX_SAFE_INTEGER,\n isFinite: NumberIsFinite,\n isNaN: NumberIsNaN,\n} = Number;\n\n// Symbol\nexport const {\n iterator: SymbolIterator,\n species: SymbolSpecies,\n toStringTag: SymbolToStringTag,\n for: SymbolFor,\n} = Symbol;\n\n// Object\nexport const NativeObject = Object;\nexport const {\n create: ObjectCreate,\n defineProperty: ObjectDefineProperty,\n freeze: ObjectFreeze,\n is: ObjectIs,\n} = NativeObject;\nconst ObjectPrototype = NativeObject.prototype;\n/** @type {(object: object, key: PropertyKey) => Function | undefined} */\nexport const ObjectPrototype__lookupGetter__ = /** @type {any} */ (ObjectPrototype).__lookupGetter__\n ? uncurryThis(/** @type {any} */ (ObjectPrototype).__lookupGetter__)\n : (object, key) => {\n if (object == null) {\n throw NativeTypeError(\n CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT\n );\n }\n\n let target = NativeObject(object);\n do {\n const descriptor = ReflectGetOwnPropertyDescriptor(target, key);\n if (descriptor !== undefined) {\n if (ObjectHasOwn(descriptor, \"get\")) {\n return descriptor.get;\n }\n\n return;\n }\n } while ((target = ReflectGetPrototypeOf(target)) !== null);\n };\n/** @type {(object: object, key: PropertyKey) => boolean} */\nexport const ObjectHasOwn = /** @type {any} */ (NativeObject).hasOwn ||\n uncurryThis(ObjectPrototype.hasOwnProperty);\n\n// Array\nconst NativeArray = Array;\nexport const ArrayIsArray = NativeArray.isArray;\nconst ArrayPrototype = NativeArray.prototype;\n/** @type {(array: ArrayLike<unknown>, separator?: string) => string} */\nexport const ArrayPrototypeJoin = uncurryThis(ArrayPrototype.join);\n/** @type {<T>(array: T[], ...items: T[]) => number} */\nexport const ArrayPrototypePush = uncurryThis(ArrayPrototype.push);\n/** @type {(array: ArrayLike<unknown>, ...opts: any[]) => string} */\nexport const ArrayPrototypeToLocaleString = uncurryThis(\n ArrayPrototype.toLocaleString\n);\nexport const NativeArrayPrototypeSymbolIterator = ArrayPrototype[SymbolIterator];\n/** @type {<T>(array: T[]) => IterableIterator<T>} */\nexport const ArrayPrototypeSymbolIterator = uncurryThis(NativeArrayPrototypeSymbolIterator);\n\n// Math\nexport const {\n abs: MathAbs,\n trunc: MathTrunc,\n} = Math;\n\n// ArrayBuffer\nexport const NativeArrayBuffer = ArrayBuffer;\nexport const ArrayBufferIsView = NativeArrayBuffer.isView;\nconst ArrayBufferPrototype = NativeArrayBuffer.prototype;\n/** @type {(buffer: ArrayBuffer, begin?: number, end?: number) => number} */\nexport const ArrayBufferPrototypeSlice = uncurryThis(ArrayBufferPrototype.slice);\n/** @type {(buffer: ArrayBuffer) => ArrayBuffer} */\nexport const ArrayBufferPrototypeGetByteLength = uncurryThisGetter(ArrayBufferPrototype, \"byteLength\");\n\n// SharedArrayBuffer\nexport const NativeSharedArrayBuffer = typeof SharedArrayBuffer !== \"undefined\" ? SharedArrayBuffer : null;\n/** @type {(buffer: SharedArrayBuffer) => SharedArrayBuffer} */\nexport const SharedArrayBufferPrototypeGetByteLength = NativeSharedArrayBuffer\n && uncurryThisGetter(NativeSharedArrayBuffer.prototype, \"byteLength\");\n\n// TypedArray\n/** @typedef {Uint8Array|Uint8ClampedArray|Uint16Array|Uint32Array|Int8Array|Int16Array|Int32Array|Float32Array|Float64Array|BigUint64Array|BigInt64Array} TypedArray */\n/** @type {any} */\nexport const TypedArray = ReflectGetPrototypeOf(Uint8Array);\nconst TypedArrayFrom = TypedArray.from;\nexport const TypedArrayPrototype = TypedArray.prototype;\nexport const NativeTypedArrayPrototypeSymbolIterator = TypedArrayPrototype[SymbolIterator];\n/** @type {(typedArray: TypedArray) => IterableIterator<number>} */\nexport const TypedArrayPrototypeKeys = uncurryThis(TypedArrayPrototype.keys);\n/** @type {(typedArray: TypedArray) => IterableIterator<number>} */\nexport const TypedArrayPrototypeValues = uncurryThis(\n TypedArrayPrototype.values\n);\n/** @type {(typedArray: TypedArray) => IterableIterator<[number, number]>} */\nexport const TypedArrayPrototypeEntries = uncurryThis(\n TypedArrayPrototype.entries\n);\n/** @type {(typedArray: TypedArray, array: ArrayLike<number>, offset?: number) => void} */\nexport const TypedArrayPrototypeSet = uncurryThis(TypedArrayPrototype.set);\n/** @type {<T extends TypedArray>(typedArray: T) => T} */\nexport const TypedArrayPrototypeReverse = uncurryThis(\n TypedArrayPrototype.reverse\n);\n/** @type {<T extends TypedArray>(typedArray: T, value: number, start?: number, end?: number) => T} */\nexport const TypedArrayPrototypeFill = uncurryThis(TypedArrayPrototype.fill);\n/** @type {<T extends TypedArray>(typedArray: T, target: number, start: number, end?: number) => T} */\nexport const TypedArrayPrototypeCopyWithin = uncurryThis(\n TypedArrayPrototype.copyWithin\n);\n/** @type {<T extends TypedArray>(typedArray: T, compareFn?: (a: number, b: number) => number) => T} */\nexport const TypedArrayPrototypeSort = uncurryThis(TypedArrayPrototype.sort);\n/** @type {<T extends TypedArray>(typedArray: T, start?: number, end?: number) => T} */\nexport const TypedArrayPrototypeSlice = uncurryThis(TypedArrayPrototype.slice);\n/** @type {<T extends TypedArray>(typedArray: T, start?: number, end?: number) => T} */\nexport const TypedArrayPrototypeSubarray = uncurryThis(\n TypedArrayPrototype.subarray\n);\n/** @type {((typedArray: TypedArray) => ArrayBuffer)} */\nexport const TypedArrayPrototypeGetBuffer = uncurryThisGetter(\n TypedArrayPrototype,\n \"buffer\"\n);\n/** @type {((typedArray: TypedArray) => number)} */\nexport const TypedArrayPrototypeGetByteOffset = uncurryThisGetter(\n TypedArrayPrototype,\n \"byteOffset\"\n);\n/** @type {((typedArray: TypedArray) => number)} */\nexport const TypedArrayPrototypeGetLength = uncurryThisGetter(\n TypedArrayPrototype,\n \"length\"\n);\n/** @type {(target: unknown) => string} */\nexport const TypedArrayPrototypeGetSymbolToStringTag = uncurryThisGetter(\n TypedArrayPrototype,\n SymbolToStringTag\n);\n\n// Uint8Array\nexport const NativeUint8Array = Uint8Array;\n\n// Uint16Array\nexport const NativeUint16Array = Uint16Array;\n/** @type {Uint16ArrayConstructor[\"from\"]} */\nexport const Uint16ArrayFrom = (...args) => {\n return ReflectApply(TypedArrayFrom, NativeUint16Array, args);\n};\n\n// Uint32Array\nexport const NativeUint32Array = Uint32Array;\n\n// Float32Array\nexport const NativeFloat32Array = Float32Array;\n\n// ArrayIterator\n/** @type {any} */\nexport const ArrayIteratorPrototype = ReflectGetPrototypeOf([][SymbolIterator]());\n/** @type {<T>(arrayIterator: IterableIterator<T>) => IteratorResult<T>} */\nexport const ArrayIteratorPrototypeNext = uncurryThis(ArrayIteratorPrototype.next);\n\n// Generator\n/** @type {<T = unknown, TReturn = any, TNext = unknown>(generator: Generator<T, TReturn, TNext>, value?: TNext) => T} */\nexport const GeneratorPrototypeNext = uncurryThis((function* () {})().next);\n\n// Iterator\nexport const IteratorPrototype = ReflectGetPrototypeOf(ArrayIteratorPrototype);\n\n// DataView\nconst DataViewPrototype = DataView.prototype;\n/** @type {(dataView: DataView, byteOffset: number, littleEndian?: boolean) => number} */\nexport const DataViewPrototypeGetUint16 = uncurryThis(\n DataViewPrototype.getUint16\n);\n/** @type {(dataView: DataView, byteOffset: number, value: number, littleEndian?: boolean) => void} */\nexport const DataViewPrototypeSetUint16 = uncurryThis(\n DataViewPrototype.setUint16\n);\n\n// Error\nexport const NativeTypeError = TypeError;\nexport const NativeRangeError = RangeError;\n\n// WeakSet\n/**\n * Do not construct with arguments to avoid calling the \"add\" method\n * @type {{new <T extends {}>(): WeakSet<T>}}\n */\nexport const NativeWeakSet = WeakSet;\nconst WeakSetPrototype = NativeWeakSet.prototype;\n/** @type {<T extends {}>(set: WeakSet<T>, value: T) => Set<T>} */\nexport const WeakSetPrototypeAdd = uncurryThis(WeakSetPrototype.add);\n/** @type {<T extends {}>(set: WeakSet<T>, value: T) => boolean} */\nexport const WeakSetPrototypeHas = uncurryThis(WeakSetPrototype.has);\n\n// WeakMap\n/**\n * Do not construct with arguments to avoid calling the \"set\" method\n * @type {{new <K extends {}, V>(): WeakMap<K, V>}}\n */\nexport const NativeWeakMap = WeakMap;\nconst WeakMapPrototype = NativeWeakMap.prototype;\n/** @type {<K extends {}, V>(weakMap: WeakMap<K, V>, key: K) => V} */\nexport const WeakMapPrototypeGet = uncurryThis(WeakMapPrototype.get);\n/** @type {<K extends {}, V>(weakMap: WeakMap<K, V>, key: K) => boolean} */\nexport const WeakMapPrototypeHas = uncurryThis(WeakMapPrototype.has);\n/** @type {<K extends {}, V>(weakMap: WeakMap<K, V>, key: K, value: V) => WeakMap} */\nexport const WeakMapPrototypeSet = uncurryThis(WeakMapPrototype.set);\n","import {\n ArrayIteratorPrototype,\n ArrayIteratorPrototypeNext,\n ArrayPrototypeSymbolIterator,\n GeneratorPrototypeNext,\n IteratorPrototype,\n NativeArrayPrototypeSymbolIterator,\n NativeWeakMap,\n ObjectCreate,\n ObjectDefineProperty,\n ReflectGetOwnPropertyDescriptor,\n ReflectOwnKeys,\n SymbolIterator,\n WeakMapPrototypeGet,\n WeakMapPrototypeSet,\n} from \"./primordials.mjs\";\n\n/** @type {WeakMap<{}, IterableIterator<any>>} */\nconst arrayIterators = new NativeWeakMap();\n\nconst SafeIteratorPrototype = ObjectCreate(null, {\n next: {\n value: function next() {\n const arrayIterator = WeakMapPrototypeGet(arrayIterators, this);\n return ArrayIteratorPrototypeNext(arrayIterator);\n },\n },\n\n [SymbolIterator]: {\n value: function values() {\n return this;\n },\n },\n});\n\n/**\n * Wrap the Array around the SafeIterator If Array.prototype [@@iterator] has been modified\n * @type {<T>(array: T[]) => Iterable<T>}\n */\nexport function safeIfNeeded(array) {\n if (\n array[SymbolIterator] === NativeArrayPrototypeSymbolIterator &&\n ArrayIteratorPrototype.next === ArrayIteratorPrototypeNext\n ) {\n return array;\n }\n\n const safe = ObjectCreate(SafeIteratorPrototype);\n WeakMapPrototypeSet(arrayIterators, safe, ArrayPrototypeSymbolIterator(array));\n return safe;\n}\n\n/** @type {WeakMap<{}, Generator<any>>} */\nconst generators = new NativeWeakMap();\n\n/** @see https://tc39.es/ecma262/#sec-%arrayiteratorprototype%-object */\nconst DummyArrayIteratorPrototype = ObjectCreate(IteratorPrototype, {\n next: {\n value: function next() {\n const generator = WeakMapPrototypeGet(generators, this);\n return GeneratorPrototypeNext(generator);\n },\n writable: true,\n configurable: true,\n },\n});\n\nfor (const key of ReflectOwnKeys(ArrayIteratorPrototype)) {\n // next method has already defined\n if (key === \"next\") {\n continue;\n }\n\n // Copy ArrayIteratorPrototype descriptors to DummyArrayIteratorPrototype\n ObjectDefineProperty(DummyArrayIteratorPrototype, key, ReflectGetOwnPropertyDescriptor(ArrayIteratorPrototype, key));\n}\n\n/**\n * Wrap the Generator around the dummy ArrayIterator\n * @type {<T>(generator: Generator<T>) => IterableIterator<T>}\n */\nexport function wrap(generator) {\n const dummy = ObjectCreate(DummyArrayIteratorPrototype);\n WeakMapPrototypeSet(generators, dummy, generator);\n return dummy;\n}\n","import {\n EPSILON,\n MathAbs,\n NativeArrayBuffer,\n NativeFloat32Array,\n NativeUint16Array,\n NativeUint32Array,\n NativeUint8Array,\n NumberIsFinite,\n NumberIsNaN,\n} from \"./primordials.mjs\";\n\nconst INVERSE_OF_EPSILON = 1 / EPSILON;\n\n/**\n * rounds to the nearest value;\n * if the number falls midway, it is rounded to the nearest value with an even least significant digit\n * @param {number} num\n * @returns {number}\n */\nfunction roundTiesToEven(num) {\n return (num + INVERSE_OF_EPSILON) - INVERSE_OF_EPSILON;\n}\n\nconst FLOAT16_MIN_VALUE = 6.103515625e-05;\nconst FLOAT16_MAX_VALUE = 65504;\nconst FLOAT16_EPSILON = 0.0009765625;\n\nconst FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE = FLOAT16_EPSILON * FLOAT16_MIN_VALUE;\nconst FLOAT16_EPSILON_DEVIDED_BY_EPSILON = FLOAT16_EPSILON * INVERSE_OF_EPSILON;\n\n/**\n * round a number to a half float number\n * @param {unknown} num - double float\n * @returns {number} half float number\n */\nexport function roundToFloat16(num) {\n const number = +num;\n\n // NaN, Infinity, -Infinity, 0, -0\n if (!NumberIsFinite(number) || number === 0) {\n return number;\n }\n\n // finite except 0, -0\n const sign = number > 0 ? 1 : -1;\n const absolute = MathAbs(number);\n\n // small number\n if (absolute < FLOAT16_MIN_VALUE) {\n return sign * roundTiesToEven(absolute / FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE) * FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE;\n }\n\n const temp = (1 + FLOAT16_EPSILON_DEVIDED_BY_EPSILON) * absolute;\n const result = temp - (temp - absolute);\n\n // large number\n if (result > FLOAT16_MAX_VALUE || NumberIsNaN(result)) {\n return sign * Infinity;\n }\n\n return sign * result;\n}\n\n// base algorithm: http://fox-toolkit.org/ftp/fasthalffloatconversion.pdf\n\nconst buffer = new NativeArrayBuffer(4);\nconst floatView = new NativeFloat32Array(buffer);\nconst uint32View = new NativeUint32Array(buffer);\n\nconst baseTable = new NativeUint16Array(512);\nconst shiftTable = new NativeUint8Array(512);\n\nfor (let i = 0; i < 256; ++i) {\n const e = i - 127;\n\n // very small number (0, -0)\n if (e < -24) {\n baseTable[i] = 0x0000;\n baseTable[i | 0x100] = 0x8000;\n shiftTable[i] = 24;\n shiftTable[i | 0x100] = 24;\n\n // small number (denorm)\n } else if (e < -14) {\n baseTable[i] = 0x0400 >> (-e - 14);\n baseTable[i | 0x100] = (0x0400 >> (-e - 14)) | 0x8000;\n shiftTable[i] = -e - 1;\n shiftTable[i | 0x100] = -e - 1;\n\n // normal number\n } else if (e <= 15) {\n baseTable[i] = (e + 15) << 10;\n baseTable[i | 0x100] = ((e + 15) << 10) | 0x8000;\n shiftTable[i] = 13;\n shiftTable[i | 0x100] = 13;\n\n // large number (Infinity, -Infinity)\n } else if (e < 128) {\n baseTable[i] = 0x7c00;\n baseTable[i | 0x100] = 0xfc00;\n shiftTable[i] = 24;\n shiftTable[i | 0x100] = 24;\n\n // stay (NaN, Infinity, -Infinity)\n } else {\n baseTable[i] = 0x7c00;\n baseTable[i | 0x100] = 0xfc00;\n shiftTable[i] = 13;\n shiftTable[i | 0x100] = 13;\n }\n}\n\n/**\n * round a number to a half float number bits\n * @param {unknown} num - double float\n * @returns {number} half float number bits\n */\nexport function roundToFloat16Bits(num) {\n floatView[0] = roundToFloat16(num);\n const f = uint32View[0];\n const e = (f >> 23) & 0x1ff;\n return baseTable[e] + ((f & 0x007fffff) >> shiftTable[e]);\n}\n\nconst mantissaTable = new NativeUint32Array(2048);\nfor (let i = 1; i < 1024; ++i) {\n let m = i << 13; // zero pad mantissa bits\n let e = 0; // zero exponent\n\n // normalized\n while ((m & 0x00800000) === 0) {\n m <<= 1;\n e -= 0x00800000; // decrement exponent\n }\n\n m &= ~0x00800000; // clear leading 1 bit\n e += 0x38800000; // adjust bias\n\n mantissaTable[i] = m | e;\n}\nfor (let i = 1024; i < 2048; ++i) {\n mantissaTable[i] = 0x38000000 + ((i - 1024) << 13);\n}\n\nconst exponentTable = new NativeUint32Array(64);\nfor (let i = 1; i < 31; ++i) {\n exponentTable[i] = i << 23;\n}\nexponentTable[31] = 0x47800000;\nexponentTable[32] = 0x80000000;\nfor (let i = 33; i < 63; ++i) {\n exponentTable[i] = 0x80000000 + ((i - 32) << 23);\n}\nexponentTable[63] = 0xc7800000;\n\nconst offsetTable = new NativeUint16Array(64);\nfor (let i = 1; i < 64; ++i) {\n if (i !== 32) {\n offsetTable[i] = 1024;\n }\n}\n\n/**\n * convert a half float number bits to a number\n * @param {number} float16bits - half float number bits\n * @returns {number} double float\n */\nexport function convertToNumber(float16bits) {\n const i = float16bits >> 10;\n uint32View[0] = mantissaTable[offsetTable[i] + (float16bits & 0x3ff)] + exponentTable[i];\n return floatView[0];\n}\n","import { safeIfNeeded } from \"./_util/arrayIterator.mjs\";\nimport { convertToNumber, roundToFloat16Bits } from \"./_util/converter.mjs\";\nimport {\n DataViewPrototypeGetUint16,\n DataViewPrototypeSetUint16,\n} from \"./_util/primordials.mjs\";\n\n/**\n * returns an unsigned 16-bit float at the specified byte offset from the start of the DataView\n * @param {DataView} dataView\n * @param {number} byteOffset\n * @param {[boolean]} opts\n * @returns {number}\n */\nexport function getFloat16(dataView, byteOffset, ...opts) {\n return convertToNumber(\n DataViewPrototypeGetUint16(dataView, byteOffset, ...safeIfNeeded(opts))\n );\n}\n\n/**\n * stores an unsigned 16-bit float value at the specified byte offset from the start of the DataView\n * @param {DataView} dataView\n * @param {number} byteOffset\n * @param {number} value\n * @param {[boolean]} opts\n */\nexport function setFloat16(dataView, byteOffset, value, ...opts) {\n return DataViewPrototypeSetUint16(\n dataView,\n byteOffset,\n roundToFloat16Bits(value),\n ...safeIfNeeded(opts)\n );\n}\n","export default function getAttribute(tag, attributeName, options) {\n const debug = (options && options.debug) || false;\n if (debug) console.log(\"[xml-utils] getting \" + attributeName + \" in \" + tag);\n\n const xml = typeof tag === \"object\" ? tag.outer : tag;\n\n // only search for attributes in the opening tag\n const opening = xml.slice(0, xml.indexOf(\">\") + 1);\n\n const quotechars = ['\"', \"'\"];\n for (let i = 0; i < quotechars.length; i++) {\n const char = quotechars[i];\n const pattern = attributeName + \"\\\\=\" + char + \"([^\" + char + \"]*)\" + char;\n if (debug) console.log(\"[xml-utils] pattern:\", pattern);\n\n const re = new RegExp(pattern);\n const match = re.exec(opening);\n if (debug) console.log(\"[xml-utils] match:\", match);\n if (match) return match[1];\n }\n}\n","export default function indexOfMatch(xml, pattern, startIndex) {\n const re = new RegExp(pattern);\n const match = re.exec(xml.slice(startIndex));\n if (match) return startIndex + match.index;\n else return -1;\n}\n","export default function indexOfMatchEnd(xml, pattern, startIndex) {\n const re = new RegExp(pattern);\n const match = re.exec(xml.slice(startIndex));\n if (match) return startIndex + match.index + match[0].length - 1;\n else return -1;\n}\n","export default function countSubstring(string, substring) {\n const pattern = new RegExp(substring, \"g\");\n const match = string.match(pattern);\n return match ? match.length : 0;\n}\n","import indexOfMatch from \"./index-of-match.mjs\";\nimport indexOfMatchEnd from \"./index-of-match-end.mjs\";\nimport countSubstring from \"./count-substring.mjs\";\n\nexport default function findTagByName(xml, tagName, options) {\n const debug = (options && options.debug) || false;\n const nested = !(options && typeof options.nested === false);\n\n const startIndex = (options && options.startIndex) || 0;\n\n if (debug) console.log(\"[xml-utils] starting findTagByName with\", tagName, \" and \", options);\n\n const start = indexOfMatch(xml, `\\<${tagName}[ \\n\\>\\/]`, startIndex);\n if (debug) console.log(\"[xml-utils] start:\", start);\n if (start === -1) return undefined;\n\n const afterStart = xml.slice(start + tagName.length);\n\n let relativeEnd = indexOfMatchEnd(afterStart, \"^[^<]*[ /]>\", 0);\n\n const selfClosing = relativeEnd !== -1 && afterStart[relativeEnd - 1] === \"/\";\n if (debug) console.log(\"[xml-utils] selfClosing:\", selfClosing);\n\n if (selfClosing === false) {\n // check if tag has subtags with the same name\n if (nested) {\n let startIndex = 0;\n let openings = 1;\n let closings = 0;\n while ((relativeEnd = indexOfMatchEnd(afterStart, \"[ /]\" + tagName + \">\", startIndex)) !== -1) {\n const clip = afterStart.substring(startIndex, relativeEnd + 1);\n openings += countSubstring(clip, \"<\" + tagName + \"[ \\n\\t>]\");\n closings += countSubstring(clip, \"</\" + tagName + \">\");\n // we can't have more openings than closings\n if (closings >= openings) break;\n startIndex = relativeEnd;\n }\n } else {\n relativeEnd = indexOfMatchEnd(afterStart, \"[ /]\" + tagName + \">\", 0);\n }\n }\n\n const end = start + tagName.length + relativeEnd + 1;\n if (debug) console.log(\"[xml-utils] end:\", end);\n if (end === -1) return undefined;\n\n const outer = xml.slice(start, end);\n // tag is like <gml:identifier codeSpace=\"OGP\">urn:ogc:def:crs:EPSG::32617</gml:identifier>\n\n let inner;\n if (selfClosing) {\n inner = null;\n } else {\n inner = outer.slice(outer.indexOf(\">\") + 1, outer.lastIndexOf(\"<\"));\n }\n\n return { inner, outer, start, end };\n}\n","import findTagByName from \"./find-tag-by-name.mjs\";\n\nexport default function findTagsByName(xml, tagName, options) {\n const tags = [];\n const debug = (options && options.debug) || false;\n const nested = options && typeof options.nested === \"boolean\" ? options.nested : true;\n let startIndex = (options && options.startIndex) || 0;\n let tag;\n while ((tag = findTagByName(xml, tagName, { debug, startIndex }))) {\n if (nested) {\n startIndex = tag.start + 1 + tagName.length;\n } else {\n startIndex = tag.end;\n }\n tags.push(tag);\n }\n if (debug) console.log(\"findTagsByName found\", tags.length, \"tags\");\n return tags;\n}\n","export function fromWhiteIsZero(raster, max) {\n const { width, height } = raster;\n const rgbRaster = new Uint8Array(width * height * 3);\n let value;\n for (let i = 0, j = 0; i < raster.length; ++i, j += 3) {\n value = 256 - (raster[i] / max) * 256;\n rgbRaster[j] = value;\n rgbRaster[j + 1] = value;\n rgbRaster[j + 2] = value;\n }\n return rgbRaster;\n}\nexport function fromBlackIsZero(raster, max) {\n const { width, height } = raster;\n const rgbRaster = new Uint8Array(width * height * 3);\n let value;\n for (let i = 0, j = 0; i < raster.length; ++i, j += 3) {\n value = (raster[i] / max) * 256;\n rgbRaster[j] = value;\n rgbRaster[j + 1] = value;\n rgbRaster[j + 2] = value;\n }\n return rgbRaster;\n}\nexport function fromPalette(raster, colorMap) {\n const { width, height } = raster;\n const rgbRaster = new Uint8Array(width * height * 3);\n const greenOffset = colorMap.length / 3;\n const blueOffset = (colorMap.length / 3) * 2;\n for (let i = 0, j = 0; i < raster.length; ++i, j += 3) {\n const mapIndex = raster[i];\n rgbRaster[j] = (colorMap[mapIndex] / 65536) * 256;\n rgbRaster[j + 1] = (colorMap[mapIndex + greenOffset] / 65536) * 256;\n rgbRaster[j + 2] = (colorMap[mapIndex + blueOffset] / 65536) * 256;\n }\n return rgbRaster;\n}\nexport function fromCMYK(cmykRaster) {\n const { width, height } = cmykRaster;\n const rgbRaster = new Uint8Array(width * height * 3);\n for (let i = 0, j = 0; i < cmykRaster.length; i += 4, j += 3) {\n const c = cmykRaster[i];\n const m = cmykRaster[i + 1];\n const y = cmykRaster[i + 2];\n const k = cmykRaster[i + 3];\n rgbRaster[j] = 255 * ((255 - c) / 256) * ((255 - k) / 256);\n rgbRaster[j + 1] = 255 * ((255 - m) / 256) * ((255 - k) / 256);\n rgbRaster[j + 2] = 255 * ((255 - y) / 256) * ((255 - k) / 256);\n }\n return rgbRaster;\n}\nexport function fromYCbCr(yCbCrRaster) {\n const { width, height } = yCbCrRaster;\n const rgbRaster = new Uint8ClampedArray(width * height * 3);\n for (let i = 0, j = 0; i < yCbCrRaster.length; i += 3, j += 3) {\n const y = yCbCrRaster[i];\n const cb = yCbCrRaster[i + 1];\n const cr = yCbCrRaster[i + 2];\n rgbRaster[j] = y + 1.402 * (cr - 0x80);\n rgbRaster[j + 1] = y - 0.34414 * (cb - 0x80) - 0.71414 * (cr - 0x80);\n rgbRaster[j + 2] = y + 1.772 * (cb - 0x80);\n }\n return rgbRaster;\n}\nconst Xn = 0.95047;\nconst Yn = 1.0;\nconst Zn = 1.08883;\n// from https://github.com/antimatter15/rgb-lab/blob/master/color.js\nexport function fromCIELab(cieLabRaster) {\n const { width, height } = cieLabRaster;\n const rgbRaster = new Uint8Array(width * height * 3);\n for (let i = 0, j = 0; i < cieLabRaster.length; i += 3, j += 3) {\n const L = cieLabRaster[i + 0];\n const a_ = (cieLabRaster[i + 1] << 24) >> 24; // conversion from uint8 to int8\n const b_ = (cieLabRaster[i + 2] << 24) >> 24; // same\n let y = (L + 16) / 116;\n let x = a_ / 500 + y;\n let z = y - b_ / 200;\n let r;\n let g;\n let b;\n x = Xn * (x * x * x > 0.008856 ? x * x * x : (x - 16 / 116) / 7.787);\n y = Yn * (y * y * y > 0.008856 ? y * y * y : (y - 16 / 116) / 7.787);\n z = Zn * (z * z * z > 0.008856 ? z * z * z : (z - 16 / 116) / 7.787);\n r = x * 3.2406 + y * -1.5372 + z * -0.4986;\n g = x * -0.9689 + y * 1.8758 + z * 0.0415;\n b = x * 0.0557 + y * -0.204 + z * 1.057;\n r = r > 0.0031308 ? 1.055 * r ** (1 / 2.4) - 0.055 : 12.92 * r;\n g = g > 0.0031308 ? 1.055 * g ** (1 / 2.4) - 0.055 : 12.92 * g;\n b = b > 0.0031308 ? 1.055 * b ** (1 / 2.4) - 0.055 : 12.92 * b;\n rgbRaster[j] = Math.max(0, Math.min(1, r)) * 255;\n rgbRaster[j + 1] = Math.max(0, Math.min(1, g)) * 255;\n rgbRaster[j + 2] = Math.max(0, Math.min(1, b)) * 255;\n }\n return rgbRaster;\n}\n//# sourceMappingURL=rgb.js.map","/** @import BaseDecoder, {BaseDecoderParameters} from \"./basedecoder.js\" */\n/**\n * @typedef {Object} RegistryEntry\n * @property {function():Promise<typeof BaseDecoder>} importFn\n * @property {function(import(\"../imagefiledirectory.js\").ImageFileDirectory):Promise<BaseDecoderParameters>} decoderParameterFn\n * @property {boolean} preferWorker\n */\n/** @type {Map<number | undefined, RegistryEntry>} */\nconst registry = new Map();\n/**\n * Default decoder parameter retrieval function\n * @param {import(\"../imagefiledirectory.js\").ImageFileDirectory} fileDirectory\n * @returns {Promise<BaseDecoderParameters>}\n */\nasync function defaultDecoderParameterFn(fileDirectory) {\n const isTiled = !fileDirectory.hasTag('StripOffsets');\n return /** @type {BaseDecoderParameters} */ ({\n tileWidth: isTiled\n ? await fileDirectory.loadValue('TileWidth')\n : await fileDirectory.loadValue('ImageWidth'),\n tileHeight: isTiled\n ? await fileDirectory.loadValue('TileLength')\n : (await fileDirectory.loadValue('RowsPerStrip')\n || await fileDirectory.loadValue('ImageLength')),\n planarConfiguration: await fileDirectory.loadValue('PlanarConfiguration'),\n bitsPerSample: await fileDirectory.loadValue('BitsPerSample'),\n predictor: await fileDirectory.loadValue('Predictor') || 1,\n });\n}\n/**\n * Register a decoder for a specific compression method or a range of compressions\n * @param {(number|undefined|(number|undefined)[])} cases ids of the compression methods to register for\n * @param {function():Promise<typeof BaseDecoder>} importFn the function to import the decoder\n * @param {function(import(\"../imagefiledirectory.js\").ImageFileDirectory):Promise<BaseDecoderParameters>} decoderParameterFn\n * @param {boolean} preferWorker_ Whether to prefer running the decoder in a worker\n */\nexport function addDecoder(cases, importFn, decoderParameterFn = defaultDecoderParameterFn, preferWorker_ = true) {\n if (!Array.isArray(cases)) {\n cases = [cases]; // eslint-disable-line no-param-reassign\n }\n cases.forEach((c) => {\n registry.set(c, { importFn, decoderParameterFn, preferWorker: preferWorker_ });\n });\n}\n/**\n * Get the required decoder parameters for a specific compression method\n * @param {number|undefined} compression\n * @param {import('../imagefiledirectory.js').ImageFileDirectory} fileDirectory\n */\nexport async function getDecoderParameters(compression, fileDirectory) {\n if (!registry.has(compression)) {\n throw new Error(`Unknown compression method identifier: ${compression}`);\n }\n const { decoderParameterFn } = /** @type {RegistryEntry} */ (registry.get(compression));\n return decoderParameterFn(fileDirectory);\n}\n/**\n * Get a decoder for a specific compression and parameters\n * @param {number} compression the compression method identifier\n * @param {BaseDecoderParameters} decoderParameters the parameters for the decoder\n * @returns {Promise<import('./basedecoder.js').default>}\n */\nexport async function getDecoder(compression, decoderParameters) {\n if (!registry.has(compression)) {\n throw new Error(`Unknown compression method identifier: ${compression}`);\n }\n const { importFn } = /** @type {RegistryEntry} */ (registry.get(compression));\n const Decoder = await importFn();\n return new Decoder(decoderParameters);\n}\n/**\n * Whether to prefer running the decoder in a worker\n * @param {number|undefined} compression the compression method identifier\n * @returns {boolean}\n */\nexport function preferWorker(compression) {\n if (!registry.has(compression)) {\n throw new Error(`Unknown compression method identifier: ${compression}`);\n }\n return /** @type {RegistryEntry} */ (registry.get(compression)).preferWorker;\n}\nconst defaultDecoderDefinitions = [\n // No compression\n {\n cases: [undefined, 1],\n importFn: () => import('./raw.js').then((m) => m.default),\n preferWorker: false,\n },\n // LZW\n {\n cases: 5,\n importFn: () => import('./lzw.js').then((m) => m.default),\n },\n // Old-style JPEG\n {\n cases: 6,\n importFn: () => {\n throw new Error('old style JPEG compression is not supported.');\n },\n },\n // JPEG\n {\n cases: 7,\n importFn: () => import('./jpeg.js').then((m) => m.default),\n /**\n * @param {import(\"../imagefiledirectory.js\").ImageFileDirectory} fileDirectory\n */\n decoderParameterFn: async (fileDirectory) => {\n return {\n ...await defaultDecoderParameterFn(fileDirectory),\n JPEGTables: await fileDirectory.loadValue('JPEGTables'),\n };\n },\n },\n // Deflate / Adobe Deflate\n {\n cases: [8, 32946],\n importFn: () => import('./deflate.js').then((m) => m.default),\n },\n // PackBits\n {\n cases: 32773,\n importFn: () => import('./packbits.js').then((m) => m.default),\n },\n // LERC\n {\n cases: 34887,\n importFn: () => import('./lerc.js')\n .then(async (m) => {\n await m.zstd.init();\n return m;\n })\n .then((m) => m.default),\n /**\n * @param {import(\"../imagefiledirectory.js\").ImageFileDirectory} fileDirectory\n */\n decoderParameterFn: async (fileDirectory) => {\n return {\n ...await defaultDecoderParameterFn(fileDirectory),\n LercParameters: await fileDirectory.loadValue('LercParameters'),\n };\n },\n },\n // zstd\n {\n cases: 50000,\n importFn: () => import('./zstd.js')\n .then(async (m) => {\n await m.zstd.init();\n return m;\n })\n .then((m) => m.default),\n },\n // WebP Images\n {\n cases: 50001,\n importFn: () => import('./webimage.js').then((m) => m.default),\n /**\n * @param {import(\"../imagefiledirectory.js\").ImageFileDirectory} fileDirectory\n */\n decoderParameterFn: async (fileDirectory) => {\n return {\n ...await defaultDecoderParameterFn(fileDirectory),\n samplesPerPixel: Number(await fileDirectory.loadValue('SamplesPerPixel')) || 4,\n };\n },\n preferWorker: false,\n },\n];\n// Add default decoders to registry (end-user may override with other implementations)\nfor (const decoderDefinition of defaultDecoderDefinitions) {\n const { cases, importFn, decoderParameterFn, preferWorker: preferWorker_ } = decoderDefinition;\n addDecoder(cases, importFn, decoderParameterFn, preferWorker_);\n}\n//# sourceMappingURL=index.js.map","/**\n * @module resample\n */\n/**\n * @param {import(\"./geotiff.js\").TypedArray} array\n * @param {number} width\n * @param {number} height\n * @param {number} [samplesPerPixel=1]\n */\nfunction copyNewSize(array, width, height, samplesPerPixel = 1) {\n return new (Object.getPrototypeOf(array).constructor)(width * height * samplesPerPixel);\n}\n/**\n * Resample the input arrays using nearest neighbor value selection.\n * @param {import(\"./geotiff.js\").TypedArray[]} valueArrays The input arrays to resample\n * @param {number} inWidth The width of the input rasters\n * @param {number} inHeight The height of the input rasters\n * @param {number} outWidth The desired width of the output rasters\n * @param {number} outHeight The desired height of the output rasters\n * @returns {import(\"./geotiff.js\").TypedArray[]} The resampled rasters\n */\nexport function resampleNearest(valueArrays, inWidth, inHeight, outWidth, outHeight) {\n const relX = inWidth / outWidth;\n const relY = inHeight / outHeight;\n return valueArrays.map((array) => {\n const newArray = copyNewSize(array, outWidth, outHeight);\n for (let y = 0; y < outHeight; ++y) {\n const cy = Math.min(Math.round(relY * y), inHeight - 1);\n for (let x = 0; x < outWidth; ++x) {\n const cx = Math.min(Math.round(relX * x), inWidth - 1);\n const value = array[(cy * inWidth) + cx];\n newArray[(y * outWidth) + x] = value;\n }\n }\n return newArray;\n });\n}\n// simple linear interpolation, code from:\n// https://en.wikipedia.org/wiki/Linear_interpolation#Programming_language_support\n/**\n * @param {number} v0\n * @param {number} v1\n * @param {number} t\n */\nfunction lerp(v0, v1, t) {\n return ((1 - t) * v0) + (t * v1);\n}\n/**\n * Resample the input arrays using bilinear interpolation.\n * @param {import(\"./geotiff.js\").TypedArray[]} valueArrays The input arrays to resample\n * @param {number} inWidth The width of the input rasters\n * @param {number} inHeight The height of the input rasters\n * @param {number} outWidth The desired width of the output rasters\n * @param {number} outHeight The desired height of the output rasters\n * @returns {import(\"./geotiff.js\").TypedArray[]} The resampled rasters\n */\nexport function resampleBilinear(valueArrays, inWidth, inHeight, outWidth, outHeight) {\n const relX = inWidth / outWidth;\n const relY = inHeight / outHeight;\n return valueArrays.map((array) => {\n const newArray = copyNewSize(array, outWidth, outHeight);\n for (let y = 0; y < outHeight; ++y) {\n const rawY = relY * y;\n const yl = Math.floor(rawY);\n const yh = Math.min(Math.ceil(rawY), (inHeight - 1));\n for (let x = 0; x < outWidth; ++x) {\n const rawX = relX * x;\n const tx = rawX % 1;\n const xl = Math.floor(rawX);\n const xh = Math.min(Math.ceil(rawX), (inWidth - 1));\n const ll = array[(yl * inWidth) + xl];\n const hl = array[(yl * inWidth) + xh];\n const lh = array[(yh * inWidth) + xl];\n const hh = array[(yh * inWidth) + xh];\n const value = lerp(lerp(ll, hl, tx), lerp(lh, hh, tx), rawY % 1);\n newArray[(y * outWidth) + x] = value;\n }\n }\n return newArray;\n });\n}\n/**\n * Resample the input arrays using the selected resampling method.\n * @param {import(\"./geotiff.js\").TypedArray[]} valueArrays The input arrays to resample\n * @param {number} inWidth The width of the input rasters\n * @param {number} inHeight The height of the input rasters\n * @param {number} outWidth The desired width of the output rasters\n * @param {number} outHeight The desired height of the output rasters\n * @param {string} [method = 'nearest'] The desired resampling method\n * @returns {import(\"./geotiff.js\").TypedArray[]} The resampled rasters\n */\nexport function resample(valueArrays, inWidth, inHeight, outWidth, outHeight, method = 'nearest') {\n switch (method.toLowerCase()) {\n case 'nearest':\n return resampleNearest(valueArrays, inWidth, inHeight, outWidth, outHeight);\n case 'bilinear':\n case 'linear':\n return resampleBilinear(valueArrays, inWidth, inHeight, outWidth, outHeight);\n default:\n throw new Error(`Unsupported resampling method: '${method}'`);\n }\n}\n/**\n * Resample the pixel interleaved input array using nearest neighbor value selection.\n * @param {import(\"./geotiff.js\").TypedArray} valueArray The input array to resample\n * @param {number} inWidth The width of the input rasters\n * @param {number} inHeight The height of the input rasters\n * @param {number} outWidth The desired width of the output rasters\n * @param {number} outHeight The desired height of the output rasters\n * @param {number} samples The number of samples per pixel for pixel\n * interleaved data\n * @returns {import(\"./geotiff.js\").TypedArray} The resampled raster\n */\nexport function resampleNearestInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples) {\n const relX = inWidth / outWidth;\n const relY = inHeight / outHeight;\n const newArray = copyNewSize(valueArray, outWidth, outHeight, samples);\n for (let y = 0; y < outHeight; ++y) {\n const cy = Math.min(Math.round(relY * y), inHeight - 1);\n for (let x = 0; x < outWidth; ++x) {\n const cx = Math.min(Math.round(relX * x), inWidth - 1);\n for (let i = 0; i < samples; ++i) {\n const value = valueArray[(cy * inWidth * samples) + (cx * samples) + i];\n newArray[(y * outWidth * samples) + (x * samples) + i] = value;\n }\n }\n }\n return newArray;\n}\n/**\n * Resample the pixel interleaved input array using bilinear interpolation.\n * @param {import(\"./geotiff.js\").TypedArray} valueArray The input array to resample\n * @param {number} inWidth The width of the input rasters\n * @param {number} inHeight The height of the input rasters\n * @param {number} outWidth The desired width of the output rasters\n * @param {number} outHeight The desired height of the output rasters\n * @param {number} samples The number of samples per pixel for pixel\n * interleaved data\n * @returns {import(\"./geotiff.js\").TypedArray} The resampled raster\n */\nexport function resampleBilinearInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples) {\n const relX = inWidth / outWidth;\n const relY = inHeight / outHeight;\n const newArray = copyNewSize(valueArray, outWidth, outHeight, samples);\n for (let y = 0; y < outHeight; ++y) {\n const rawY = relY * y;\n const yl = Math.floor(rawY);\n const yh = Math.min(Math.ceil(rawY), (inHeight - 1));\n for (let x = 0; x < outWidth; ++x) {\n const rawX = relX * x;\n const tx = rawX % 1;\n const xl = Math.floor(rawX);\n const xh = Math.min(Math.ceil(rawX), (inWidth - 1));\n for (let i = 0; i < samples; ++i) {\n const ll = valueArray[(yl * inWidth * samples) + (xl * samples) + i];\n const hl = valueArray[(yl * inWidth * samples) + (xh * samples) + i];\n const lh = valueArray[(yh * inWidth * samples) + (xl * samples) + i];\n const hh = valueArray[(yh * inWidth * samples) + (xh * samples) + i];\n const value = lerp(lerp(ll, hl, tx), lerp(lh, hh, tx), rawY % 1);\n newArray[(y * outWidth * samples) + (x * samples) + i] = value;\n }\n }\n }\n return newArray;\n}\n/**\n * Resample the pixel interleaved input array using the selected resampling method.\n * @param {import(\"./geotiff.js\").TypedArray} valueArray The input array to resample\n * @param {number} inWidth The width of the input rasters\n * @param {number} inHeight The height of the input rasters\n * @param {number} outWidth The desired width of the output rasters\n * @param {number} outHeight The desired height of the output rasters\n * @param {number} samples The number of samples per pixel for pixel\n * interleaved data\n * @param {string} [method = 'nearest'] The desired resampling method\n * @returns {import(\"./geotiff.js\").TypedArray} The resampled rasters\n */\nexport function resampleInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples, method = 'nearest') {\n switch (method.toLowerCase()) {\n case 'nearest':\n return resampleNearestInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples);\n case 'bilinear':\n case 'linear':\n return resampleBilinearInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples);\n default:\n throw new Error(`Unsupported resampling method: '${method}'`);\n }\n}\n//# sourceMappingURL=resample.js.map","/** @module geotiffimage */\nimport { getFloat16 } from '@petamoriken/float16';\n// @ts-expect-error\nimport getAttribute from 'xml-utils/get-attribute'; // eslint-disable-line import/extensions\n// @ts-expect-error\nimport findTagsByName from 'xml-utils/find-tags-by-name'; // eslint-disable-line import/extensions\nimport { photometricInterpretations, ExtraSamplesValues } from './globals.js';\nimport { fromWhiteIsZero, fromBlackIsZero, fromPalette, fromCMYK, fromYCbCr, fromCIELab } from './rgb.js';\nimport { getDecoder, getDecoderParameters } from './compression/index.js';\nimport { resample, resampleInterleaved } from './resample.js';\n/** @import {DecoderWorker, TypedArray} from \"./geotiff.js\" */\n/** @import {ReadRasterResult} from \"./geotiff.js\" */\n/** @import {ReadRastersOptions} from \"./geotiff.js\" */\n/** @import {ReadRGBOptions} from \"./geotiff.js\" */\n/**\n * @param {Array<number>|TypedArray} array\n * @param {number} start\n * @param {number} end\n * @returns {number}\n */\nfunction sum(array, start, end) {\n let s = 0;\n for (let i = start; i < end; ++i) {\n s += array[i];\n }\n return s;\n}\n/**\n * @param {1|2|3} format\n * @param {number} bitsPerSample\n * @param {number|ArrayBufferLike} sizeOrData\n * @returns {TypedArray}\n */\nfunction arrayForType(format, bitsPerSample, sizeOrData) {\n let TypedArrayConstructor;\n switch (format) {\n case 1: // unsigned integer data\n if (bitsPerSample <= 8) {\n TypedArrayConstructor = Uint8Array;\n }\n else if (bitsPerSample <= 16) {\n TypedArrayConstructor = Uint16Array;\n }\n else if (bitsPerSample <= 32) {\n TypedArrayConstructor = Uint32Array;\n }\n break;\n case 2: // twos complement signed integer data\n if (bitsPerSample === 8) {\n TypedArrayConstructor = Int8Array;\n }\n else if (bitsPerSample === 16) {\n TypedArrayConstructor = Int16Array;\n }\n else if (bitsPerSample === 32) {\n TypedArrayConstructor = Int32Array;\n }\n break;\n case 3: // floating point data\n switch (bitsPerSample) {\n case 16:\n case 32:\n TypedArrayConstructor = Float32Array;\n break;\n case 64:\n TypedArrayConstructor = Float64Array;\n break;\n default:\n break;\n }\n break;\n default:\n break;\n }\n if (TypedArrayConstructor) {\n if (typeof sizeOrData === 'number') {\n return new TypedArrayConstructor(sizeOrData);\n }\n else if (sizeOrData instanceof ArrayBuffer) {\n return new TypedArrayConstructor(sizeOrData);\n }\n }\n throw Error('Unsupported data format/bitsPerSample');\n}\n/**\n * @param {1|2|3} format\n * @param {number} bitsPerSample\n * @returns {boolean}\n */\nfunction needsNormalization(format, bitsPerSample) {\n if ((format === 1 || format === 2) && bitsPerSample <= 32 && bitsPerSample % 8 === 0) {\n return false;\n }\n else if (format === 3 && (bitsPerSample === 16 || bitsPerSample === 32 || bitsPerSample === 64)) {\n return false;\n }\n return true;\n}\n/**\n * @param {ArrayBufferLike} inBuffer\n * @param {1|2|3} format\n * @param {1|2} planarConfiguration\n * @param {number} samplesPerPixel\n * @param {number} bitsPerSample\n * @param {number} tileWidth\n * @param {number} tileHeight\n * @returns {ArrayBufferLike}\n */\nfunction normalizeArray(inBuffer, format, planarConfiguration, samplesPerPixel, bitsPerSample, tileWidth, tileHeight) {\n // const inByteArray = new Uint8Array(inBuffer);\n const view = new DataView(inBuffer);\n const outSize = planarConfiguration === 2\n ? tileHeight * tileWidth\n : tileHeight * tileWidth * samplesPerPixel;\n const samplesToTransfer = planarConfiguration === 2\n ? 1 : samplesPerPixel;\n const outArray = arrayForType(format, bitsPerSample, outSize);\n // let pixel = 0;\n const bitMask = parseInt('1'.repeat(bitsPerSample), 2);\n if (format === 1) { // unsigned integer\n // translation of https://github.com/OSGeo/gdal/blob/master/gdal/frmts/gtiff/geotiff.cpp#L7337\n let pixelBitSkip;\n // let sampleBitOffset = 0;\n if (planarConfiguration === 1) {\n pixelBitSkip = samplesPerPixel * bitsPerSample;\n // sampleBitOffset = (samplesPerPixel - 1) * bitsPerSample;\n }\n else {\n pixelBitSkip = bitsPerSample;\n }\n // Bits per line rounds up to next byte boundary.\n let bitsPerLine = tileWidth * pixelBitSkip;\n if ((bitsPerLine & 7) !== 0) {\n bitsPerLine = (bitsPerLine + 7) & (~7);\n }\n for (let y = 0; y < tileHeight; ++y) {\n const lineBitOffset = y * bitsPerLine;\n for (let x = 0; x < tileWidth; ++x) {\n const pixelBitOffset = lineBitOffset + (x * samplesToTransfer * bitsPerSample);\n for (let i = 0; i < samplesToTransfer; ++i) {\n const bitOffset = pixelBitOffset + (i * bitsPerSample);\n const outIndex = (((y * tileWidth) + x) * samplesToTransfer) + i;\n const byteOffset = Math.floor(bitOffset / 8);\n const innerBitOffset = bitOffset % 8;\n if (innerBitOffset + bitsPerSample <= 8) {\n outArray[outIndex] = (view.getUint8(byteOffset) >> (8 - bitsPerSample) - innerBitOffset) & bitMask;\n }\n else if (innerBitOffset + bitsPerSample <= 16) {\n outArray[outIndex] = (view.getUint16(byteOffset) >> (16 - bitsPerSample) - innerBitOffset) & bitMask;\n }\n else if (innerBitOffset + bitsPerSample <= 24) {\n const raw = (view.getUint16(byteOffset) << 8) | (view.getUint8(byteOffset + 2));\n outArray[outIndex] = (raw >> (24 - bitsPerSample) - innerBitOffset) & bitMask;\n }\n else {\n outArray[outIndex] = (view.getUint32(byteOffset) >> (32 - bitsPerSample) - innerBitOffset) & bitMask;\n }\n // let outWord = 0;\n // for (let bit = 0; bit < bitsPerSample; ++bit) {\n // if (inByteArray[bitOffset >> 3]\n // & (0x80 >> (bitOffset & 7))) {\n // outWord |= (1 << (bitsPerSample - 1 - bit));\n // }\n // ++bitOffset;\n // }\n // outArray[outIndex] = outWord;\n // outArray[pixel] = outWord;\n // pixel += 1;\n }\n // bitOffset = bitOffset + pixelBitSkip - bitsPerSample;\n }\n }\n }\n else if (format === 3) { // floating point\n // Float16 is handled elsewhere\n // normalize 16/24 bit floats to 32 bit floats in the array\n // console.time();\n // if (bitsPerSample === 16) {\n // for (let byte = 0, outIndex = 0; byte < inBuffer.byteLength; byte += 2, ++outIndex) {\n // outArray[outIndex] = getFloat16(view, byte);\n // }\n // }\n // console.timeEnd()\n }\n return outArray.buffer;\n}\n/**\n * GeoTIFF sub-file image.\n */\nclass GeoTIFFImage {\n /**\n * @constructor\n * @param {import(\"./imagefiledirectory.js\").ImageFileDirectory} fileDirectory The parsed file directory\n * @param {Boolean} littleEndian Whether the file is encoded in little or big endian\n * @param {Boolean} cache Whether or not decoded tiles shall be cached\n * @param {import('./source/basesource.js').BaseSource} source The datasource to read from\n */\n constructor(fileDirectory, littleEndian, cache, source) {\n this.fileDirectory = fileDirectory;\n this.littleEndian = littleEndian;\n /** @type {Array<Promise<ArrayBufferLike>>|null} */\n this.tiles = cache ? [] : null;\n this.isTiled = !fileDirectory.hasTag('StripOffsets');\n const planarConfiguration = fileDirectory.getValue('PlanarConfiguration') ?? 1;\n if (planarConfiguration !== 1 && planarConfiguration !== 2) {\n throw new Error('Invalid planar configuration.');\n }\n /** @type {1 | 2} */\n this.planarConfiguration = planarConfiguration;\n this.source = source;\n }\n /**\n * Returns the associated parsed file directory.\n * @returns {import(\"./imagefiledirectory.js\").ImageFileDirectory} the parsed file directory\n */\n getFileDirectory() {\n return this.fileDirectory;\n }\n /**\n * Returns the associated parsed geo keys.\n * @returns {Partial<Record<import('./globals.js').GeoKeyName, *>>|null} the parsed geo keys\n */\n getGeoKeys() {\n return this.fileDirectory.parseGeoKeyDirectory();\n }\n /**\n * Returns the width of the image.\n * @returns {Number} the width of the image\n */\n getWidth() {\n return this.fileDirectory.getValue('ImageWidth') || 0;\n }\n /**\n * Returns the height of the image.\n * @returns {Number} the height of the image\n */\n getHeight() {\n return this.fileDirectory.getValue('ImageLength') || 0;\n }\n /**\n * Returns the number of samples per pixel.\n * @returns {number} the number of samples per pixel\n */\n getSamplesPerPixel() {\n return this.fileDirectory.getValue('SamplesPerPixel') ?? 1;\n }\n /**\n * Returns the width of each tile.\n * @returns {number} the width of each tile\n */\n getTileWidth() {\n return this.isTiled ? (this.fileDirectory.getValue('TileWidth') || 0) : this.getWidth();\n }\n /**\n * Returns the height of each tile.\n * @returns {number} the height of each tile\n */\n getTileHeight() {\n if (this.isTiled) {\n return this.fileDirectory.getValue('TileLength') || 0;\n }\n const rowsPerStrip = this.fileDirectory.hasTag('RowsPerStrip') && this.fileDirectory.getValue('RowsPerStrip');\n if (rowsPerStrip) {\n return Math.min(rowsPerStrip, this.getHeight());\n }\n return this.getHeight();\n }\n getBlockWidth() {\n return this.getTileWidth();\n }\n /**\n * @param {number} y\n * @returns {number}\n */\n getBlockHeight(y) {\n if (this.isTiled || (y + 1) * this.getTileHeight() <= this.getHeight()) {\n return this.getTileHeight();\n }\n else {\n return this.getHeight() - (y * this.getTileHeight());\n }\n }\n /**\n * Calculates the number of bytes for each pixel across all samples. Only full\n * bytes are supported, an exception is thrown when this is not the case.\n * @returns {Number} the bytes per pixel\n */\n getBytesPerPixel() {\n let bytes = 0;\n // this is a short list, so we assume this is already loaded\n const bitsPerSample = this.fileDirectory.getValue('BitsPerSample') || [];\n for (let i = 0; i < bitsPerSample.length; ++i) {\n bytes += this.getSampleByteSize(i);\n }\n return bytes;\n }\n /**\n * @param {number} i\n * @returns {number}\n */\n getSampleByteSize(i) {\n const bitsPerSample = this.fileDirectory.getValue('BitsPerSample') || [];\n if (i >= bitsPerSample.length) {\n throw new RangeError(`Sample index ${i} is out of range.`);\n }\n return Math.ceil(bitsPerSample[i] / 8);\n }\n /**\n * @param {number} sampleIndex\n * @returns {(this: DataView, byteOffset: number, littleEndian: boolean) => number}\n */\n getReaderForSample(sampleIndex) {\n const sampleFormat = this.fileDirectory.getValue('SampleFormat');\n const format = sampleFormat\n ? sampleFormat[sampleIndex] : 1;\n const bitsPerSample = (this.fileDirectory.getValue('BitsPerSample') || [])[sampleIndex];\n switch (format) {\n case 1: // unsigned integer data\n if (bitsPerSample <= 8) {\n return DataView.prototype.getUint8;\n }\n else if (bitsPerSample <= 16) {\n return DataView.prototype.getUint16;\n }\n else if (bitsPerSample <= 32) {\n return DataView.prototype.getUint32;\n }\n break;\n case 2: // twos complement signed integer data\n if (bitsPerSample <= 8) {\n return DataView.prototype.getInt8;\n }\n else if (bitsPerSample <= 16) {\n return DataView.prototype.getInt16;\n }\n else if (bitsPerSample <= 32) {\n return DataView.prototype.getInt32;\n }\n break;\n case 3:\n switch (bitsPerSample) {\n case 16:\n return function (offset, littleEndian) {\n return getFloat16(this, offset, littleEndian);\n };\n case 32:\n return DataView.prototype.getFloat32;\n case 64:\n return DataView.prototype.getFloat64;\n default:\n break;\n }\n break;\n default:\n break;\n }\n throw Error('Unsupported data format/bitsPerSample');\n }\n getSampleFormat(sampleIndex = 0) {\n const sampleFormat = this.fileDirectory.getValue('SampleFormat');\n return sampleFormat ? sampleFormat[sampleIndex] : 1;\n }\n getBitsPerSample(sampleIndex = 0) {\n const bitsPerSample = this.fileDirectory.getValue('BitsPerSample');\n return bitsPerSample ? bitsPerSample[sampleIndex] : 0;\n }\n /**\n * @param {number} sampleIndex\n * @param {number|ArrayBufferLike} sizeOrData\n * @returns {TypedArray}\n */\n getArrayForSample(sampleIndex, sizeOrData) {\n const format = /** @type {1|2|3} */ (this.getSampleFormat(sampleIndex));\n const bitsPerSample = this.getBitsPerSample(sampleIndex);\n return arrayForType(format, bitsPerSample, sizeOrData);\n }\n /**\n * Returns the decoded strip or tile.\n * @param {Number} x the strip or tile x-offset\n * @param {Number} y the tile y-offset (0 for stripped images)\n * @param {Number} sample the sample to get for separated samples\n * @param {DecoderWorker|import(\"./geotiff.js\").BaseDecoder} poolOrDecoder the decoder or decoder pool\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise.<{x: number, y: number, sample: number, data: ArrayBufferLike}>} the decoded strip or tile\n */\n async getTileOrStrip(x, y, sample, poolOrDecoder, signal) {\n const numTilesPerRow = Math.ceil(this.getWidth() / this.getTileWidth());\n const numTilesPerCol = Math.ceil(this.getHeight() / this.getTileHeight());\n let index;\n const { tiles } = this;\n if (this.planarConfiguration === 1) {\n index = (y * numTilesPerRow) + x;\n }\n else if (this.planarConfiguration === 2) {\n index = (sample * numTilesPerRow * numTilesPerCol) + (y * numTilesPerRow) + x;\n }\n if (index === undefined) {\n throw new Error('Could not determine tile or strip index.');\n }\n let offset;\n let byteCount;\n if (this.isTiled) {\n offset = Number(await this.fileDirectory.loadValueIndexed('TileOffsets', index));\n byteCount = Number(await this.fileDirectory.loadValueIndexed('TileByteCounts', index));\n }\n else {\n offset = Number(await this.fileDirectory.loadValueIndexed('StripOffsets', index));\n byteCount = Number(await this.fileDirectory.loadValueIndexed('StripByteCounts', index));\n }\n if (byteCount === 0) {\n const nPixels = this.getBlockHeight(y) * this.getTileWidth();\n const bytesPerPixel = (this.planarConfiguration === 2) ? this.getSampleByteSize(sample) : this.getBytesPerPixel();\n const data = new ArrayBuffer(nPixels * bytesPerPixel);\n const view = this.getArrayForSample(sample, data);\n view.fill(this.getGDALNoData() || 0);\n return { x, y, sample, data };\n }\n const slice = (await this.source.fetch([{ offset, length: byteCount }], signal))[0];\n let request;\n if (tiles === null || !tiles[index]) {\n // resolve each request by potentially applying array normalization\n request = (async () => {\n let data = await poolOrDecoder.decode(slice);\n const sampleFormat = /** @type {1|2|3} */ (this.getSampleFormat());\n const bitsPerSample = this.getBitsPerSample();\n if (needsNormalization(sampleFormat, bitsPerSample)) {\n data = normalizeArray(data, sampleFormat, this.planarConfiguration, this.getSamplesPerPixel(), bitsPerSample, this.getTileWidth(), this.getBlockHeight(y));\n }\n return data;\n })();\n // set the cache\n if (tiles !== null) {\n tiles[index] = request;\n }\n }\n else {\n // get from the cache\n request = tiles[index];\n }\n // cache the tile request\n return { x, y, sample, data: await request };\n }\n /**\n * Internal read function.\n * @private\n * @param {Array<number>} imageWindow The image window in pixel coordinates\n * @param {Array<number>} samples The selected samples (0-based indices)\n * @param {TypedArray|TypedArray[]} valueArrays The array(s) to write into\n * @param {boolean|undefined} interleave Whether or not to write in an interleaved manner\n * @param {DecoderWorker|import(\"./geotiff.js\").BaseDecoder} poolOrDecoder the decoder or decoder pool\n * @param {number} [width] the width of window to be read into\n * @param {number} [height] the height of window to be read into\n * @param {string} [resampleMethod] the resampling method to be used when interpolating\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<ReadRasterResult>}\n */\n async _readRaster(imageWindow, samples, valueArrays, interleave, poolOrDecoder, width, height, resampleMethod, signal) {\n const tileWidth = this.getTileWidth();\n const tileHeight = this.getTileHeight();\n const imageWidth = this.getWidth();\n const imageHeight = this.getHeight();\n const minXTile = Math.max(Math.floor(imageWindow[0] / tileWidth), 0);\n const maxXTile = Math.min(Math.ceil(imageWindow[2] / tileWidth), Math.ceil(imageWidth / tileWidth));\n const minYTile = Math.max(Math.floor(imageWindow[1] / tileHeight), 0);\n const maxYTile = Math.min(Math.ceil(imageWindow[3] / tileHeight), Math.ceil(imageHeight / tileHeight));\n const windowWidth = imageWindow[2] - imageWindow[0];\n let bytesPerPixel = this.getBytesPerPixel();\n /** @type {Array<number>} */\n const srcSampleOffsets = [];\n /** @type {Array<(this: DataView, byteOffset: number, littleEndian: boolean) => number>} */\n const sampleReaders = [];\n for (let i = 0; i < samples.length; ++i) {\n if (this.planarConfiguration === 1) {\n const bitsPerSample = await this.fileDirectory.loadValue('BitsPerSample');\n if (typeof bitsPerSample !== 'object') {\n throw new Error('Expected BitsPerSample to be an array or typed array.');\n }\n srcSampleOffsets.push(sum(bitsPerSample, 0, samples[i]) / 8);\n }\n else {\n srcSampleOffsets.push(0);\n }\n sampleReaders.push(this.getReaderForSample(samples[i]));\n }\n const promises = [];\n const { littleEndian } = this;\n for (let yTile = minYTile; yTile < maxYTile; ++yTile) {\n for (let xTile = minXTile; xTile < maxXTile; ++xTile) {\n let getPromise;\n if (this.planarConfiguration === 1) {\n getPromise = this.getTileOrStrip(xTile, yTile, 0, poolOrDecoder, signal);\n }\n for (let sampleIndex = 0; sampleIndex < samples.length; ++sampleIndex) {\n const si = sampleIndex;\n const sample = samples[sampleIndex];\n if (this.planarConfiguration === 2) {\n bytesPerPixel = this.getSampleByteSize(sample);\n getPromise = this.getTileOrStrip(xTile, yTile, sample, poolOrDecoder, signal);\n }\n if (!getPromise) {\n throw new Error('Could not get tile or strip data.');\n }\n const promise = getPromise.then((tile) => {\n const buffer = tile.data;\n const dataView = new DataView(buffer);\n const blockHeight = this.getBlockHeight(tile.y);\n const firstLine = tile.y * tileHeight;\n const firstCol = tile.x * tileWidth;\n const lastLine = firstLine + blockHeight;\n const lastCol = (tile.x + 1) * tileWidth;\n const reader = sampleReaders[si];\n const ymax = Math.min(blockHeight, blockHeight - (lastLine - imageWindow[3]), imageHeight - firstLine);\n const xmax = Math.min(tileWidth, tileWidth - (lastCol - imageWindow[2]), imageWidth - firstCol);\n for (let y = Math.max(0, imageWindow[1] - firstLine); y < ymax; ++y) {\n for (let x = Math.max(0, imageWindow[0] - firstCol); x < xmax; ++x) {\n const pixelOffset = ((y * tileWidth) + x) * bytesPerPixel;\n const value = reader.call(dataView, pixelOffset + srcSampleOffsets[si], littleEndian);\n let windowCoordinate;\n if (interleave) {\n windowCoordinate = ((y + firstLine - imageWindow[1]) * windowWidth * samples.length)\n + ((x + firstCol - imageWindow[0]) * samples.length)\n + si;\n valueArrays[windowCoordinate] = value;\n }\n else {\n windowCoordinate = ((y + firstLine - imageWindow[1]) * windowWidth) + x + firstCol - imageWindow[0];\n /** @type {TypedArray} */ (valueArrays[si])[windowCoordinate] = value;\n }\n }\n }\n });\n promises.push(promise);\n }\n }\n }\n await Promise.all(promises);\n if ((width && (imageWindow[2] - imageWindow[0]) !== width)\n || (height && (imageWindow[3] - imageWindow[1]) !== height)) {\n let resampled;\n if (interleave) {\n resampled = resampleInterleaved(\n /** @type {TypedArray} */ (valueArrays), imageWindow[2] - imageWindow[0], imageWindow[3] - imageWindow[1], \n /** @type {number} */ (width), /** @type {number} */ (height), samples.length, resampleMethod);\n }\n else {\n resampled = resample(\n /** @type {TypedArray[]} */ (valueArrays), imageWindow[2] - imageWindow[0], imageWindow[3] - imageWindow[1], \n /** @type {number} */ (width), /** @type {number} */ (height), resampleMethod);\n }\n const resampledWithDimensions = /** @type {ReadRasterResult} */ (resampled);\n resampledWithDimensions.width = width ?? imageWindow[2] - imageWindow[0];\n resampledWithDimensions.height = height ?? imageWindow[3] - imageWindow[1];\n return resampledWithDimensions;\n }\n const valueArraysWithDimensions = /** @type {ReadRasterResult} */ (valueArrays);\n valueArraysWithDimensions.width = width || imageWindow[2] - imageWindow[0];\n valueArraysWithDimensions.height = height || imageWindow[3] - imageWindow[1];\n return valueArraysWithDimensions;\n }\n /**\n * @overload\n * @param {ReadRastersOptions & {interleave: true}} options optional parameters\n * @returns {Promise<import(\"./geotiff.js\").TypedArrayWithDimensions>} the decoded arrays as a promise\n */\n /**\n * @overload\n * @param {ReadRastersOptions & {interleave: false}} options optional parameters\n * @returns {Promise<import(\"./geotiff.js\").TypedArrayArrayWithDimensions>} the decoded arrays as a promise\n */\n /**\n * @overload\n * @param {ReadRastersOptions & {interleave: boolean}} options optional parameters\n * @returns {Promise<ReadRasterResult>} the decoded arrays as a promise\n */\n /**\n * @overload\n * @param {ReadRastersOptions} [options={}] optional parameters\n * @returns {Promise<import(\"./geotiff.js\").TypedArrayArrayWithDimensions>} the decoded arrays as a promise\n */\n /**\n * Reads raster data from the image. This function reads all selected samples\n * into separate arrays of the correct type for that sample or into a single\n * combined array when `interleave` is set. When provided, only a subset\n * of the raster is read for each sample.\n *\n * @param {ReadRastersOptions} [options={}] optional parameters\n * @returns {Promise<ReadRasterResult>} the decoded arrays as a promise\n */\n async readRasters(options = {}) {\n const { window: wnd, samples = [], pool = null, width, height, resampleMethod, fillValue, signal, } = options;\n const interleave = 'interleave' in options && options.interleave;\n const imageWindow = wnd || [0, 0, this.getWidth(), this.getHeight()];\n // check parameters\n if (imageWindow[0] > imageWindow[2] || imageWindow[1] > imageWindow[3]) {\n throw new Error('Invalid subsets');\n }\n const imageWindowWidth = imageWindow[2] - imageWindow[0];\n const imageWindowHeight = imageWindow[3] - imageWindow[1];\n const numPixels = imageWindowWidth * imageWindowHeight;\n const samplesPerPixel = this.getSamplesPerPixel();\n if (!samples || !samples.length) {\n for (let i = 0; i < samplesPerPixel; ++i) {\n samples.push(i);\n }\n }\n else {\n for (let i = 0; i < samples.length; ++i) {\n if (samples[i] >= samplesPerPixel) {\n return Promise.reject(new RangeError(`Invalid sample index '${samples[i]}'.`));\n }\n }\n }\n /** @type {TypedArray|TypedArray[]} */\n let valueArrays;\n if (interleave) {\n const { fileDirectory } = this;\n const sampleFormat = fileDirectory.getValue('SampleFormat');\n const format = sampleFormat\n ? Math.max.apply(null, Array.from(sampleFormat)) : 1;\n if (format !== 1 && format !== 2 && format !== 3) {\n throw new Error('Unsupported sample format for interleaved data. Must be 1, 2, or 3.');\n }\n const bitsPerSample_ = fileDirectory.getValue('BitsPerSample');\n const bitsPerSample = bitsPerSample_\n ? Math.max.apply(null, Array.from(bitsPerSample_)) : 8;\n valueArrays = arrayForType(format, bitsPerSample, numPixels * samples.length);\n if (fillValue) {\n if (Array.isArray(fillValue)) {\n throw new Error('When reading interleaved data, fillValue must be a single number.');\n }\n valueArrays.fill(fillValue);\n }\n }\n else {\n valueArrays = [];\n for (let i = 0; i < samples.length; ++i) {\n const valueArray = this.getArrayForSample(samples[i], numPixels);\n if (Array.isArray(fillValue) && i < fillValue.length) {\n valueArray.fill(fillValue[i]);\n }\n else if (fillValue && !Array.isArray(fillValue)) {\n valueArray.fill(fillValue);\n }\n valueArrays.push(valueArray);\n }\n }\n const compression = this.fileDirectory.getValue('Compression') || 1;\n const decoderParameters = await getDecoderParameters(compression, this.fileDirectory);\n const poolOrDecoder = pool\n ? pool.bindParameters(compression, decoderParameters)\n : await getDecoder(compression, decoderParameters);\n const result = await this._readRaster(imageWindow, samples, valueArrays, interleave, poolOrDecoder, width, height, resampleMethod, signal);\n return result;\n }\n /**\n * @overload\n * @param {ReadRGBOptions & {interleave: true}} options optional parameters\n * @returns {Promise<import(\"./geotiff.js\").TypedArrayWithDimensions>} the RGB array as a Promise\n */\n /**\n * @overload\n * @param {ReadRGBOptions & {interleave: false}} options optional parameters\n * @returns {Promise<import(\"./geotiff.js\").TypedArrayArrayWithDimensions>} the RGB array as a Promise\n */\n /**\n * @overload\n * @param {ReadRGBOptions & {interleave: boolean}} options optional parameters\n * @returns {Promise<ReadRasterResult>} the RGB array as a Promise\n */\n /**\n * @overload\n * @param {ReadRGBOptions} [options={}] optional parameters\n * @returns {Promise<import(\"./geotiff.js\").TypedArrayArrayWithDimensions>} the RGB array as a Promise\n */\n /**\n * Reads raster data from the image as RGB.\n * Colorspaces other than RGB will be transformed to RGB, color maps expanded.\n * When no other method is applicable, the first sample is used to produce a\n * grayscale image.\n * When provided, only a subset of the raster is read for each sample.\n *\n * @param {ReadRGBOptions} [options] optional parameters\n * @returns {Promise<ReadRasterResult>} the RGB array as a Promise\n */\n async readRGB(options = {}) {\n const { window, pool = null, width, height, resampleMethod, enableAlpha = false, signal } = options;\n const interleave = ('interleave' in options && options.interleave) ?? false;\n const imageWindow = window || [0, 0, this.getWidth(), this.getHeight()];\n // check parameters\n if (imageWindow[0] > imageWindow[2] || imageWindow[1] > imageWindow[3]) {\n throw new Error('Invalid subsets');\n }\n const pi = this.fileDirectory.getValue('PhotometricInterpretation');\n if (pi === photometricInterpretations.RGB) {\n let s = [0, 1, 2];\n const extraSamples = this.fileDirectory.getValue('ExtraSamples');\n if (extraSamples && extraSamples[0] !== ExtraSamplesValues.Unspecified && enableAlpha) {\n s = [];\n const bitsPerSample = this.fileDirectory.getValue('BitsPerSample') || [];\n for (let i = 0; i < bitsPerSample.length; i += 1) {\n s.push(i);\n }\n }\n return this.readRasters({\n window,\n interleave,\n samples: s,\n pool,\n width,\n height,\n resampleMethod,\n signal,\n });\n }\n let samples;\n switch (pi) {\n case photometricInterpretations.WhiteIsZero:\n case photometricInterpretations.BlackIsZero:\n case photometricInterpretations.Palette:\n samples = [0];\n break;\n case photometricInterpretations.CMYK:\n samples = [0, 1, 2, 3];\n break;\n case photometricInterpretations.YCbCr:\n case photometricInterpretations.CIELab:\n samples = [0, 1, 2];\n break;\n default:\n throw new Error('Invalid or unsupported photometric interpretation.');\n }\n const subOptions = {\n window: imageWindow,\n /** @type {true} */\n interleave: true,\n samples,\n pool,\n width,\n height,\n resampleMethod,\n signal,\n };\n const { fileDirectory } = this;\n const raster = await this.readRasters(subOptions);\n const max = 2 ** this.getBitsPerSample(0);\n let data;\n switch (pi) {\n case photometricInterpretations.WhiteIsZero:\n data = fromWhiteIsZero(raster, max);\n break;\n case photometricInterpretations.BlackIsZero:\n data = fromBlackIsZero(raster, max);\n break;\n case photometricInterpretations.Palette:\n data = fromPalette(raster, /** @type {Uint16Array} */ (await fileDirectory.loadValue('ColorMap')));\n break;\n case photometricInterpretations.CMYK:\n data = fromCMYK(raster);\n break;\n case photometricInterpretations.YCbCr:\n data = fromYCbCr(raster);\n break;\n case photometricInterpretations.CIELab:\n data = fromCIELab(raster);\n break;\n default:\n throw new Error('Unsupported photometric interpretation.');\n }\n // if non-interleaved data is requested, we must split the channels\n // into their respective arrays\n if (!interleave) {\n const red = new Uint8Array(data.length / 3);\n const green = new Uint8Array(data.length / 3);\n const blue = new Uint8Array(data.length / 3);\n for (let i = 0, j = 0; i < data.length; i += 3, ++j) {\n red[j] = data[i];\n green[j] = data[i + 1];\n blue[j] = data[i + 2];\n }\n data = [red, green, blue];\n }\n const dataWithDimensions = /** @type {import(\"./geotiff.js\").ReadRasterResult} */ (data);\n dataWithDimensions.width = raster.width;\n dataWithDimensions.height = raster.height;\n return dataWithDimensions;\n }\n /**\n * Returns an array of tiepoints.\n * @returns {Promise<Array<{i: number, j: number, k: number, x: number, y: number, z: number}>>} the tiepoints\n */\n async getTiePoints() {\n if (!this.fileDirectory.hasTag('ModelTiepoint')) {\n return [];\n }\n const modelTiePoint = await this.fileDirectory.loadValue('ModelTiepoint');\n if (typeof modelTiePoint !== 'object') {\n throw new Error('Expected ModelTiepoint to be an array or typed array.');\n }\n const tiePoints = [];\n for (let i = 0; i < modelTiePoint.length; i += 6) {\n tiePoints.push({\n i: modelTiePoint[i],\n j: modelTiePoint[i + 1],\n k: modelTiePoint[i + 2],\n x: modelTiePoint[i + 3],\n y: modelTiePoint[i + 4],\n z: modelTiePoint[i + 5],\n });\n }\n return tiePoints;\n }\n /**\n * Returns the parsed GDAL metadata items.\n *\n * If sample is passed to null, dataset-level metadata will be returned.\n * Otherwise only metadata specific to the provided sample will be returned.\n *\n * @param {number|null} [sample=null] The sample index.\n * @returns {Promise<Record<string, unknown>|null>} The GDAL metadata items\n */\n async getGDALMetadata(sample = null) {\n /** @type {Record<string, unknown>} */\n const metadata = {};\n if (!this.fileDirectory.hasTag('GDAL_METADATA')) {\n return null;\n }\n const string = await this.fileDirectory.loadValue('GDAL_METADATA');\n /** @type {Array<{inner: unknown}>} */\n let items = findTagsByName(string, 'Item');\n if (sample === null) {\n items = items.filter((item) => getAttribute(item, 'sample') === undefined);\n }\n else {\n items = items.filter((item) => Number(getAttribute(item, 'sample')) === sample);\n }\n for (let i = 0; i < items.length; ++i) {\n const item = items[i];\n metadata[getAttribute(item, 'name')] = item.inner;\n }\n return metadata;\n }\n /**\n * Returns the GDAL nodata value\n * @returns {number|null}\n */\n getGDALNoData() {\n const string = this.fileDirectory.hasTag('GDAL_NODATA') && this.fileDirectory.getValue('GDAL_NODATA');\n if (!string) {\n return null;\n }\n return Number(string.substring(0, string.length - 1));\n }\n /**\n * Returns the image origin as a XYZ-vector. When the image has no affine\n * transformation, then an exception is thrown.\n * @returns {Array<number>} The origin as a vector\n */\n getOrigin() {\n const tiePoints = this.fileDirectory.getValue('ModelTiepoint');\n const modelTransformation = this.fileDirectory.getValue('ModelTransformation');\n if (tiePoints && tiePoints.length === 6) {\n return [\n tiePoints[3],\n tiePoints[4],\n tiePoints[5],\n ];\n }\n if (modelTransformation) {\n return [\n modelTransformation[3],\n modelTransformation[7],\n modelTransformation[11],\n ];\n }\n throw new Error('The image does not have an affine transformation.');\n }\n /**\n * Returns the image resolution as a XYZ-vector. When the image has no affine\n * transformation, then an exception is thrown.\n * @param {GeoTIFFImage|null} [referenceImage=null] A reference image to calculate the resolution from\n * in cases when the current image does not have the\n * required tags on its own.\n * @returns {Array<number>} The resolution as a vector\n */\n getResolution(referenceImage = null) {\n const modelPixelScale = this.fileDirectory.getValue('ModelPixelScale');\n const modelTransformation = this.fileDirectory.getValue('ModelTransformation');\n if (modelPixelScale) {\n return [\n modelPixelScale[0],\n -modelPixelScale[1],\n modelPixelScale[2],\n ];\n }\n if (modelTransformation) {\n if (modelTransformation[1] === 0 && modelTransformation[4] === 0) {\n return [\n modelTransformation[0],\n -modelTransformation[5],\n modelTransformation[10],\n ];\n }\n return [\n Math.sqrt((modelTransformation[0] * modelTransformation[0])\n + (modelTransformation[4] * modelTransformation[4])),\n -Math.sqrt((modelTransformation[1] * modelTransformation[1])\n + (modelTransformation[5] * modelTransformation[5])),\n modelTransformation[10]\n ];\n }\n if (referenceImage) {\n const [refResX, refResY, refResZ] = referenceImage.getResolution();\n return [\n refResX * referenceImage.getWidth() / this.getWidth(),\n refResY * referenceImage.getHeight() / this.getHeight(),\n refResZ * referenceImage.getWidth() / this.getWidth(),\n ];\n }\n throw new Error('The image does not have an affine transformation.');\n }\n /**\n * Returns whether or not the pixels of the image depict an area (or point).\n * @returns {Boolean} Whether the pixels are a point\n */\n pixelIsArea() {\n return this.getGeoKeys()?.GTRasterTypeGeoKey === 1;\n }\n /**\n * Returns the image bounding box as an array of 4 values: min-x, min-y,\n * max-x and max-y. When the image has no affine transformation, then an\n * exception is thrown.\n * @param {boolean} [tilegrid=false] If true return extent for a tilegrid\n * without adjustment for ModelTransformation.\n * @returns {Array<number>} The bounding box\n */\n getBoundingBox(tilegrid = false) {\n const height = this.getHeight();\n const width = this.getWidth();\n const modelTransformation = this.fileDirectory.getValue('ModelTransformation');\n if (modelTransformation && !tilegrid) {\n const [a, b, , d, e, f, , h] = modelTransformation;\n const corners = [\n [0, 0],\n [0, height],\n [width, 0],\n [width, height],\n ];\n const projected = corners.map(([I, J]) => [\n d + (a * I) + (b * J),\n h + (e * I) + (f * J),\n ]);\n const xs = projected.map((pt) => pt[0]);\n const ys = projected.map((pt) => pt[1]);\n return [\n Math.min(...xs),\n Math.min(...ys),\n Math.max(...xs),\n Math.max(...ys),\n ];\n }\n else {\n const origin = this.getOrigin();\n const resolution = this.getResolution();\n const x1 = origin[0];\n const y1 = origin[1];\n const x2 = x1 + (resolution[0] * width);\n const y2 = y1 + (resolution[1] * height);\n return [\n Math.min(x1, x2),\n Math.min(y1, y2),\n Math.max(x1, x2),\n Math.max(y1, y2),\n ];\n }\n }\n}\nexport default GeoTIFFImage;\n//# sourceMappingURL=geotiffimage.js.map","import { getFloat16 } from '@petamoriken/float16';\nexport default class DataView64 {\n /**\n * @param {ArrayBufferLike} arrayBuffer\n */\n constructor(arrayBuffer) {\n this._dataView = new DataView(arrayBuffer);\n }\n get buffer() {\n return this._dataView.buffer;\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getUint64(offset, littleEndian) {\n const left = this.getUint32(offset, littleEndian);\n const right = this.getUint32(offset + 4, littleEndian);\n let combined;\n if (littleEndian) {\n combined = left + ((2 ** 32) * right);\n if (!Number.isSafeInteger(combined)) {\n throw new Error(`${combined} exceeds MAX_SAFE_INTEGER. `\n + 'Precision may be lost. Please report if you get this message to https://github.com/geotiffjs/geotiff.js/issues');\n }\n return combined;\n }\n combined = ((2 ** 32) * left) + right;\n if (!Number.isSafeInteger(combined)) {\n throw new Error(`${combined} exceeds MAX_SAFE_INTEGER. `\n + 'Precision may be lost. Please report if you get this message to https://github.com/geotiffjs/geotiff.js/issues');\n }\n return combined;\n }\n /**\n * Adapted from https://stackoverflow.com/a/55338384/8060591\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getInt64(offset, littleEndian) {\n let value = 0;\n const isNegative = (this._dataView.getUint8(offset + (littleEndian ? 7 : 0)) & 0x80) > 0;\n let carrying = true;\n for (let i = 0; i < 8; i++) {\n let byte = this._dataView.getUint8(offset + (littleEndian ? i : 7 - i));\n if (isNegative) {\n if (carrying) {\n if (byte !== 0x00) {\n byte = ~(byte - 1) & 0xff;\n carrying = false;\n }\n }\n else {\n byte = ~byte & 0xff;\n }\n }\n value += byte * (256 ** i);\n }\n if (isNegative) {\n value = -value;\n }\n return value;\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n getUint8(offset) {\n return this._dataView.getUint8(offset);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n getInt8(offset) {\n return this._dataView.getInt8(offset);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getUint16(offset, littleEndian) {\n return this._dataView.getUint16(offset, littleEndian);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getInt16(offset, littleEndian) {\n return this._dataView.getInt16(offset, littleEndian);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getUint32(offset, littleEndian) {\n return this._dataView.getUint32(offset, littleEndian);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getInt32(offset, littleEndian) {\n return this._dataView.getInt32(offset, littleEndian);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getFloat16(offset, littleEndian) {\n return getFloat16(this._dataView, offset, littleEndian);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getFloat32(offset, littleEndian) {\n return this._dataView.getFloat32(offset, littleEndian);\n }\n /**\n * @param {number} offset\n * @param {boolean} littleEndian\n * @returns {number}\n */\n getFloat64(offset, littleEndian) {\n return this._dataView.getFloat64(offset, littleEndian);\n }\n}\n//# sourceMappingURL=dataview64.js.map","export default class DataSlice {\n /**\n * @param {ArrayBufferLike} arrayBuffer\n * @param {number} sliceOffset\n * @param {boolean} littleEndian\n * @param {boolean} bigTiff\n */\n constructor(arrayBuffer, sliceOffset, littleEndian, bigTiff) {\n this._dataView = new DataView(arrayBuffer);\n this._sliceOffset = sliceOffset;\n this._littleEndian = littleEndian;\n this._bigTiff = bigTiff;\n }\n get sliceOffset() {\n return this._sliceOffset;\n }\n get sliceTop() {\n return this._sliceOffset + this.buffer.byteLength;\n }\n get littleEndian() {\n return this._littleEndian;\n }\n get bigTiff() {\n return this._bigTiff;\n }\n get buffer() {\n return this._dataView.buffer;\n }\n /**\n * @param {number} offset\n * @param {number} length\n * @returns {boolean}\n */\n covers(offset, length) {\n return this.sliceOffset <= offset && this.sliceTop >= offset + length;\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readUint8(offset) {\n return this._dataView.getUint8(offset - this._sliceOffset);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readInt8(offset) {\n return this._dataView.getInt8(offset - this._sliceOffset);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readUint16(offset) {\n return this._dataView.getUint16(offset - this._sliceOffset, this._littleEndian);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readInt16(offset) {\n return this._dataView.getInt16(offset - this._sliceOffset, this._littleEndian);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readUint32(offset) {\n return this._dataView.getUint32(offset - this._sliceOffset, this._littleEndian);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readInt32(offset) {\n return this._dataView.getInt32(offset - this._sliceOffset, this._littleEndian);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readFloat32(offset) {\n return this._dataView.getFloat32(offset - this._sliceOffset, this._littleEndian);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readFloat64(offset) {\n return this._dataView.getFloat64(offset - this._sliceOffset, this._littleEndian);\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readUint64(offset) {\n const left = this.readUint32(offset);\n const right = this.readUint32(offset + 4);\n let combined;\n if (this._littleEndian) {\n combined = left + ((2 ** 32) * right);\n if (!Number.isSafeInteger(combined)) {\n throw new Error(`${combined} exceeds MAX_SAFE_INTEGER. `\n + 'Precision may be lost. Please report if you get this message to https://github.com/geotiffjs/geotiff.js/issues');\n }\n return combined;\n }\n combined = ((2 ** 32) * left) + right;\n if (!Number.isSafeInteger(combined)) {\n throw new Error(`${combined} exceeds MAX_SAFE_INTEGER. `\n + 'Precision may be lost. Please report if you get this message to https://github.com/geotiffjs/geotiff.js/issues');\n }\n return combined;\n }\n /**\n * Adapted from https://stackoverflow.com/a/55338384/8060591\n * @param {number} offset\n * @returns {number}\n */\n readInt64(offset) {\n let value = 0;\n const isNegative = (this._dataView.getUint8(offset + (this._littleEndian ? 7 : 0)) & 0x80)\n > 0;\n let carrying = true;\n for (let i = 0; i < 8; i++) {\n let byte = this._dataView.getUint8(offset + (this._littleEndian ? i : 7 - i));\n if (isNegative) {\n if (carrying) {\n if (byte !== 0x00) {\n byte = ~(byte - 1) & 0xff;\n carrying = false;\n }\n }\n else {\n byte = ~byte & 0xff;\n }\n }\n value += byte * (256 ** i);\n }\n if (isNegative) {\n value = -value;\n }\n return value;\n }\n /**\n * @param {number} offset\n * @returns {number}\n */\n readOffset(offset) {\n if (this._bigTiff) {\n return this.readUint64(offset);\n }\n return this.readUint32(offset);\n }\n}\n//# sourceMappingURL=dataslice.js.map","/**\n * @typedef {Object} Slice\n * @property {number} offset\n * @property {number} length\n */\n/** @typedef {Slice & {data: ArrayBufferLike}} SliceWithData */\nexport class BaseSource {\n /**\n * @param {Array<Slice>} slices\n * @param {AbortSignal} [signal]\n * @returns {Promise<ArrayBufferLike[]>}\n */\n async fetch(slices, signal) {\n return Promise.all(slices.map(async (slice) => (await this.fetchSlice(slice, signal)).data));\n }\n /**\n * @param {Slice} slice\n * @param {AbortSignal} [_signal]\n * @returns {Promise<SliceWithData>}\n */\n async fetchSlice(slice, _signal) {\n throw new Error(`fetching of slice ${slice} not possible, not implemented`);\n }\n /**\n * Returns the filesize if already determined and null otherwise\n * @returns {number|null}\n */\n get fileSize() {\n return null;\n }\n async close() {\n // no-op by default\n }\n}\n//# sourceMappingURL=basesource.js.map","export function assign(target, source) {\n for (const key in source) {\n if (source.hasOwnProperty(key)) {\n target[key] = source[key];\n }\n }\n return target;\n}\nexport function chunk(iterable, length) {\n const results = [];\n const lengthOfIterable = iterable.length;\n for (let i = 0; i < lengthOfIterable; i += length) {\n const chunked = [];\n for (let ci = i; ci < i + length; ci++) {\n chunked.push(iterable[ci]);\n }\n results.push(chunked);\n }\n return results;\n}\nexport function endsWith(string, expectedEnding) {\n if (string.length < expectedEnding.length) {\n return false;\n }\n const actualEnding = string.substr(string.length - expectedEnding.length);\n return actualEnding === expectedEnding;\n}\nexport function forEach(iterable, func) {\n const { length } = iterable;\n for (let i = 0; i < length; i++) {\n func(iterable[i], i);\n }\n}\nexport function invert(oldObj) {\n const newObj = {};\n for (const key in oldObj) {\n if (oldObj.hasOwnProperty(key)) {\n const value = oldObj[key];\n newObj[value] = key;\n }\n }\n return newObj;\n}\nexport function range(n) {\n const results = [];\n for (let i = 0; i < n; i++) {\n results.push(i);\n }\n return results;\n}\nexport function times(numTimes, func) {\n const results = [];\n for (let i = 0; i < numTimes; i++) {\n results.push(func(i));\n }\n return results;\n}\nexport function toArray(iterable) {\n const results = [];\n const { length } = iterable;\n for (let i = 0; i < length; i++) {\n results.push(iterable[i]);\n }\n return results;\n}\nexport function toArrayRecursively(input) {\n if (isArrayLike(input)) {\n return toArray(input).map(toArrayRecursively);\n }\n return input;\n}\nfunction isArrayLike(v) {\n return Boolean(typeof v === 'object' && v !== null && 'length' in v);\n}\n/** Copied from https://github.com/academia-de-codigo/parse-content-range-header/blob/master/index.js */\nexport function parseContentRange(headerValue) {\n if (!headerValue) {\n return null;\n }\n if (typeof headerValue !== 'string') {\n throw new Error('invalid argument');\n }\n const parseInt = (number) => Number.parseInt(number, 10);\n // Check for presence of unit\n let matches = headerValue.match(/^(\\w*) /);\n const unit = matches && matches[1];\n // check for start-end/size header format\n matches = headerValue.match(/(\\d+)-(\\d+)\\/(\\d+|\\*)/);\n if (matches) {\n return {\n unit,\n first: parseInt(matches[1]),\n last: parseInt(matches[2]),\n length: matches[3] === '*' ? null : parseInt(matches[3]),\n };\n }\n // check for size header format\n matches = headerValue.match(/(\\d+|\\*)/);\n if (matches) {\n return {\n unit,\n first: null,\n last: null,\n length: matches[1] === '*' ? null : parseInt(matches[1]),\n };\n }\n return null;\n}\n/**\n * Promisified wrapper around 'setTimeout' to allow 'await'\n * @param {number} [milliseconds]\n * @returns {Promise<void>}\n */\nexport async function wait(milliseconds) {\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\nexport function zip(a, b) {\n const A = Array.isArray(a) ? a : Array.from(a);\n const B = Array.isArray(b) ? b : Array.from(b);\n return A.map((k, i) => [k, B[i]]);\n}\n// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error\nexport class AbortError extends Error {\n constructor(...args) {\n // Pass remaining arguments (including vendor specific ones) to parent constructor\n super(...args);\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, AbortError);\n }\n this.name = 'AbortError';\n this.signal = undefined;\n }\n}\nexport class CustomAggregateError extends Error {\n constructor(errors, message) {\n super(message);\n this.errors = errors;\n this.message = message;\n this.name = 'AggregateError';\n }\n}\nexport const AggregateError = CustomAggregateError;\nexport function isTypedFloatArray(input) {\n if (ArrayBuffer.isView(input)) {\n const ctr = input.constructor;\n if (ctr === Float32Array || ctr === Float64Array) {\n return true;\n }\n }\n return false;\n}\nexport function isTypedIntArray(input) {\n if (ArrayBuffer.isView(input)) {\n const ctr = input.constructor;\n if (ctr === Int8Array || ctr === Int16Array || ctr === Int32Array) {\n return true;\n }\n }\n return false;\n}\nexport function isTypedUintArray(input) {\n if (ArrayBuffer.isView(input)) {\n const ctr = input.constructor;\n if (ctr === Uint8Array ||\n ctr === Uint16Array ||\n ctr === Uint32Array ||\n ctr === Uint8ClampedArray) {\n return true;\n }\n }\n return false;\n}\nexport const typeMap = {\n Float64Array,\n Float32Array,\n Uint32Array,\n Uint16Array,\n Uint8Array,\n};\n//# sourceMappingURL=utils.js.map","import { BaseSource } from './basesource.js';\nimport { AbortError } from '../utils.js';\nclass ArrayBufferSource extends BaseSource {\n /**\n * @param {ArrayBuffer} arrayBuffer\n */\n constructor(arrayBuffer) {\n super();\n this.arrayBuffer = arrayBuffer;\n }\n /**\n * @param {import('./basesource.js').Slice} slice\n * @param {AbortSignal} [signal]\n * @returns {Promise<import('./basesource.js').SliceWithData>}\n */\n fetchSlice(slice, signal) {\n if (signal && signal.aborted) {\n throw new AbortError('Request aborted');\n }\n return Promise.resolve({\n data: this.arrayBuffer.slice(slice.offset, slice.offset + slice.length),\n offset: slice.offset,\n length: slice.length,\n });\n }\n}\n/** @param {ArrayBuffer} arrayBuffer */\nexport function makeBufferSource(arrayBuffer) {\n return new ArrayBufferSource(arrayBuffer);\n}\n//# sourceMappingURL=arraybuffer.js.map","import DataSlice from './dataslice.js';\nimport { fieldTypes, geoKeyNames, tagDefinitions, resolveTag, getFieldTypeSize, } from './globals.js';\n/**\n * Allocates an appropriate TypedArray based on the TIFF field type.\n * @param {number} fieldType - TIFF field type constant from fieldTypes\n * @param {number} count - Number of elements to allocate\n * @returns {import('./geotiff.js').TypedArray|Array<number>} The allocated typed array for the given field type\n * @throws {RangeError} If the field type is invalid\n */\nfunction getArrayForSamples(fieldType, count) {\n switch (fieldType) {\n case fieldTypes.BYTE:\n case fieldTypes.ASCII:\n case fieldTypes.UNDEFINED:\n return new Uint8Array(count);\n case fieldTypes.SBYTE:\n return new Int8Array(count);\n case fieldTypes.SHORT:\n return new Uint16Array(count);\n case fieldTypes.SSHORT:\n return new Int16Array(count);\n case fieldTypes.LONG:\n case fieldTypes.IFD:\n return new Uint32Array(count);\n case fieldTypes.SLONG:\n return new Int32Array(count);\n case fieldTypes.LONG8:\n case fieldTypes.IFD8:\n return new Array(count);\n case fieldTypes.SLONG8:\n return new Array(count);\n case fieldTypes.RATIONAL:\n return new Uint32Array(count * 2);\n case fieldTypes.SRATIONAL:\n return new Int32Array(count * 2);\n case fieldTypes.FLOAT:\n return new Float32Array(count);\n case fieldTypes.DOUBLE:\n return new Float64Array(count);\n default:\n throw new RangeError(`Invalid field type: ${fieldType}`);\n }\n}\n/**\n * Returns the appropriate DataSlice read method for a given field type.\n * @param {DataSlice} dataSlice - The DataSlice instance to get the reader from\n * @param {number} fieldType - TIFF field type constant from fieldTypes\n * @returns {Function} The bound read method (e.g., readUint16, readFloat32)\n * @throws {RangeError} If the field type is invalid\n */\nfunction getDataSliceReader(dataSlice, fieldType) {\n switch (fieldType) {\n case fieldTypes.BYTE:\n case fieldTypes.ASCII:\n case fieldTypes.UNDEFINED:\n return dataSlice.readUint8;\n case fieldTypes.SBYTE:\n return dataSlice.readInt8;\n case fieldTypes.SHORT:\n return dataSlice.readUint16;\n case fieldTypes.SSHORT:\n return dataSlice.readInt16;\n case fieldTypes.LONG:\n case fieldTypes.IFD:\n return dataSlice.readUint32;\n case fieldTypes.SLONG:\n return dataSlice.readInt32;\n case fieldTypes.LONG8:\n case fieldTypes.IFD8:\n return dataSlice.readUint64;\n case fieldTypes.SLONG8:\n return dataSlice.readInt64;\n case fieldTypes.RATIONAL:\n return dataSlice.readUint32;\n case fieldTypes.SRATIONAL:\n return dataSlice.readInt32;\n case fieldTypes.FLOAT:\n return dataSlice.readFloat32;\n case fieldTypes.DOUBLE:\n return dataSlice.readFloat64;\n default:\n throw new RangeError(`Invalid field type: ${fieldType}`);\n }\n}\n/**\n * @overload\n * @param {import('./geotiff.js').TypedArray|Array<number>|null} outValues - Optional pre-allocated output array\n * @param {Function} readMethod - DataView read method (e.g., getUint16)\n * @param {DataSlice} dataSlice - Source data slice\n * @param {number} fieldType - TIFF field type constant\n * @param {number} count - Number of values to read\n * @param {number} offset - Byte offset to start reading\n * @param {true} isArray - Whether to always return an array (vs single value)\n * @returns {import('./geotiff.js').TypedArray|Array<number>} The decoded value(s)\n */\n/**\n * @overload\n * @param {import('./geotiff.js').TypedArray|Array<number>|null} outValues - Optional pre-allocated output array\n * @param {Function} readMethod - DataView read method (e.g., getUint16)\n * @param {DataSlice} dataSlice - Source data slice\n * @param {number} fieldType - TIFF field type constant\n * @param {number} count - Number of values to read\n * @param {number} offset - Byte offset to start reading\n * @param {boolean} [isArray] - Whether to always return an array (vs single value)\n * @returns {import('./geotiff.js').TypedArray|Array<number>|string|number} The decoded value(s)\n */\n/**\n * Reads field values from a DataSlice.\n * @param {import('./geotiff.js').TypedArray|Array<number>|null} outValues - Optional pre-allocated output array\n * @param {Function} readMethod - DataView read method (e.g., getUint16)\n * @param {DataSlice} dataSlice - Source data slice\n * @param {import('./globals.js').FieldType} fieldType - TIFF field type constant\n * @param {number} count - Number of values to read\n * @param {number} offset - Byte offset to start reading\n * @param {boolean} [isArray] - Whether to always return an array (vs single value)\n * @returns {import('./geotiff.js').TypedArray|Array<number>|string|number} The decoded value(s)\n */\nfunction getValues(outValues = null, readMethod, dataSlice, fieldType, count, offset, isArray = false) {\n const fieldTypeLength = getFieldTypeSize(fieldType);\n const values = outValues || getArrayForSamples(fieldType, count);\n // const readMethod = getDataSliceReader(dataSlice, fieldType);\n const isRational = (fieldType === fieldTypes.RATIONAL || fieldType === fieldTypes.SRATIONAL);\n // normal fields\n if (!isRational) {\n for (let i = 0; i < count; ++i) {\n values[i] = readMethod.call(dataSlice, offset + (i * fieldTypeLength));\n }\n }\n else {\n // RATIONAL or SRATIONAL\n for (let i = 0; i < count; i += 2) {\n values[i] = readMethod.call(dataSlice, offset + (i * fieldTypeLength));\n values[i + 1] = readMethod.call(dataSlice, offset + ((i * fieldTypeLength) + 4));\n }\n }\n if (fieldType === fieldTypes.ASCII) {\n return new TextDecoder('utf-8').decode(/** @type {Uint8Array} */ (values));\n }\n if (count === 1 && !isArray && !isRational) {\n return values[0];\n }\n return values;\n}\n/**\n * Lazily-loaded array for large TIFF field values that are fetched on-demand.\n * Supports loading individual indices or the entire array. Uses a bitmap to track\n * which values have been loaded to avoid redundant fetches.\n */\nclass DeferredArray {\n /**\n * Creates a DeferredArray for lazy-loading of large TIFF field arrays.\n * @param {import(\"./source/basesource.js\").BaseSource} source - Data source for fetching\n * @param {number} arrayOffset - Byte offset where the array data starts\n * @param {boolean} littleEndian - Endianness of the data\n * @param {import('./globals.js').FieldType} fieldType - TIFF field type constant\n * @param {number} length - Number of elements in the array\n */\n constructor(source, arrayOffset, littleEndian, fieldType, length) {\n this.source = source;\n this.arrayOffset = arrayOffset;\n this.littleEndian = littleEndian;\n this.fieldType = fieldType;\n this.length = length;\n this.data = getArrayForSamples(fieldType, length);\n this.itemSize = getFieldTypeSize(fieldType);\n this.maskBitmap = new Uint8Array(Math.ceil(length / 8));\n this.fetchIndexPromises = new Map();\n this.fullFetchPromise = null;\n }\n /**\n * Loads all values in the deferred array at once.\n * Subsequent calls return the same promise to avoid redundant fetches.\n * @returns {Promise<import('./geotiff.js').TypedArray|Array<number>>} Promise resolving to the fully loaded array\n */\n async loadAll() {\n if (!this.fullFetchPromise) {\n this.fullFetchPromise = this.source.fetch([{\n offset: this.arrayOffset,\n length: this.itemSize * this.length,\n }]).then((data) => {\n const dataSlice = new DataSlice(data[0], this.arrayOffset, true, false);\n const result = getValues(this.data, getDataSliceReader(dataSlice, this.fieldType), dataSlice, this.fieldType, this.length, this.arrayOffset, true);\n // Mark all items as loaded in the bitmap\n this.maskBitmap.fill(0xFF);\n // Clean up any pending individual fetch promises since all data is now loaded\n this.fetchIndexPromises.clear();\n return result;\n });\n }\n return this.fullFetchPromise;\n }\n /**\n * Loads and returns a single value at the specified index.\n * If the value is already loaded, returns it immediately. Otherwise, fetches it\n * from the source. Multiple calls for the same index reuse the same promise.\n * @param {number} index - Zero-based index of the value to load\n * @returns {Promise<number|bigint>} Promise resolving to the value at the given index\n * @throws {RangeError} If index is out of bounds\n */\n async get(index) {\n if (index < 0 || index >= this.data.length) {\n throw new RangeError(`Index ${index} out of bounds for length ${this.data.length}`);\n }\n const byteIndex = Math.floor(index / 8);\n const bitMask = 1 << index % 8;\n const offset = this.arrayOffset + (index * this.itemSize);\n if ((this.maskBitmap[byteIndex] & bitMask) === 0) {\n if (!this.fetchIndexPromises.has(index)) {\n const fetchPromise = this.source.fetch([{\n offset,\n length: this.itemSize,\n }]).then((data) => {\n const dataSlice = new DataSlice(data[0], this.arrayOffset + (index * this.itemSize), true, false);\n const readMethod = getDataSliceReader(dataSlice, this.fieldType);\n const value = readMethod.call(dataSlice, offset);\n this.data[index] = value;\n this.maskBitmap[byteIndex] |= bitMask;\n this.fetchIndexPromises.delete(index);\n return value;\n });\n this.fetchIndexPromises.set(index, fetchPromise);\n }\n return this.fetchIndexPromises.get(index);\n }\n return this.data[index];\n }\n}\nexport class ImageFileDirectory {\n /**\n * Create an ImageFileDirectory.\n * @param {Map<string|number, number|string|Array<number|string>>} actualizedFields the file directory,\n * mapping tag names to values\n * @param {Map<string|number, Function>} deferredFields the deferred fields, mapping tag names to async functions\n * @param {Map<string|number, DeferredArray>} deferredArrays the deferred arrays, mapping tag names to\n * DeferredArray objects\n * @param {number} nextIFDByteOffset the byte offset to the next IFD\n */\n constructor(actualizedFields, deferredFields, deferredArrays, nextIFDByteOffset) {\n this.actualizedFields = actualizedFields;\n this.deferredFields = deferredFields;\n this.deferredFieldsBeingResolved = new Map();\n this.deferredArrays = deferredArrays;\n this.nextIFDByteOffset = nextIFDByteOffset;\n }\n /**\n * @param {import('./globals.js').TagName|number} tagIdentifier The field tag ID or name\n * @returns {boolean} whether the field exists (actualized or deferred)\n */\n hasTag(tagIdentifier) {\n const tag = resolveTag(tagIdentifier);\n return this.actualizedFields.has(tag) || this.deferredFields.has(tag) || this.deferredArrays.has(tag);\n }\n /**\n * Synchronously retrieves the value for a given tag. If it is deferred, an error is thrown.\n * @template {import('./globals.js').EagerTagName | import('./globals.js').EagerTag} [T=any]\n * @param {T} tagIdentifier The field tag ID or name\n * @returns {T extends import('./globals.js').TagName ? (import('./globals.js').TagValue<T> | undefined) : any}\n * the field value,\n * or undefined if it does not exist\n * @throws {Error} If the tag is deferred and requires asynchronous loading\n */\n getValue(tagIdentifier) {\n const tag = resolveTag(tagIdentifier);\n if (this.deferredFields.has(tag) || this.deferredArrays.has(tag)) {\n const tagDef = tagDefinitions[tag];\n const tagName = tagDef?.name || `Tag${tag}`;\n throw new Error(`Field '${tagName}' (${tag}) is deferred. Use loadValue() to load it asynchronously.`);\n }\n if (!this.actualizedFields.has(tag)) {\n return /** @type {any} */ (undefined);\n }\n return /** @type {any} */ (this.actualizedFields.get(tag));\n }\n /**\n * Retrieves the value for a given tag. If it is deferred, it will be loaded first.\n * @template {import('./globals.js').TagName} [T=any]\n * @param {T|number} tagIdentifier The field tag ID or name\n * @returns {Promise<T extends import('./globals.js').TagName ? (import('./globals.js').TagValue<T> | undefined) : any>}\n * the field value, or undefined if it does not exist\n */\n async loadValue(tagIdentifier) {\n const tag = resolveTag(tagIdentifier);\n if (this.actualizedFields.has(tag)) {\n return /** @type {any} */ (this.actualizedFields.get(tag));\n }\n if (this.deferredFieldsBeingResolved.has(tag)) {\n return /** @type {any} */ (this.deferredFieldsBeingResolved.get(tag));\n }\n const loaderFn = this.deferredFields.get(tag);\n if (loaderFn) {\n this.deferredFields.delete(tag);\n // Set promise BEFORE starting async work to prevent race conditions\n const valuePromise = (async () => {\n try {\n const value = await loaderFn();\n this.actualizedFields.set(tag, value);\n return value;\n }\n finally {\n this.deferredFieldsBeingResolved.delete(tag);\n }\n })();\n this.deferredFieldsBeingResolved.set(tag, valuePromise);\n return /** @type {any} */ (valuePromise);\n }\n const deferredArray = this.deferredArrays.get(tag);\n if (deferredArray) {\n return /** @type {any} */ (deferredArray.loadAll());\n }\n return /** @type {any} */ (undefined);\n }\n /**\n * Retrieves the value at a given index for a tag that is an array. If it is deferred, it will be loaded first.\n * @param {number|string} tagIdentifier The field tag ID or name\n * @param {number} index The index within the array\n * @returns {Promise<number|string|bigint|undefined>} the field value at the given index, or undefined if it does not exist\n */\n async loadValueIndexed(tagIdentifier, index) {\n const tag = resolveTag(tagIdentifier);\n if (this.actualizedFields.has(tag)) {\n const value = this.actualizedFields.get(tag);\n return /** @type {any} */ (value)[index];\n }\n else if (this.deferredArrays.has(tag)) {\n const deferredArray = /** @type {DeferredArray} */ (this.deferredArrays.get(tag));\n return deferredArray.get(index);\n }\n else if (this.hasTag(tag)) {\n const value = await this.loadValue(tag);\n if (value && typeof value !== 'number') {\n return value[index];\n }\n }\n return undefined;\n }\n /**\n * Parses the GeoTIFF GeoKeyDirectory tag into a structured object.\n * The GeoKeyDirectory is a special TIFF tag that contains geographic metadata\n * in a key-value format as defined by the GeoTIFF specification.\n * @returns {Partial<Record<import('./globals.js').GeoKeyName, *>>|null} Parsed geo key directory\n * mapping key names to values, or null if not present\n * @throws {Error} If a referenced geo key value cannot be retrieved\n */\n parseGeoKeyDirectory() {\n const rawGeoKeyDirectory = this.getValue('GeoKeyDirectory');\n if (!rawGeoKeyDirectory) {\n return null;\n }\n /** @type {Partial<Record<import('./globals.js').GeoKeyName, *>>} */\n const geoKeyDirectory = {};\n for (let i = 4; i <= rawGeoKeyDirectory[3] * 4; i += 4) {\n const key = ( /** @type {Record<number, import('./globals.js').GeoKeyName>} */(geoKeyNames))[rawGeoKeyDirectory[i]];\n const location = /** @type {import('./globals.js').EagerTag} */ (rawGeoKeyDirectory[i + 1]) || null;\n const count = rawGeoKeyDirectory[i + 2];\n const offset = rawGeoKeyDirectory[i + 3];\n let value = null;\n if (!location) {\n value = offset;\n }\n else {\n value = this.getValue(location);\n if (typeof value === 'undefined' || value === null) {\n throw new Error(`Could not get value of geoKey '${key}'.`);\n }\n else if (typeof value === 'string') {\n value = value.substring(offset, offset + count - 1);\n }\n else if (value.subarray) {\n value = value.subarray(offset, offset + count);\n if (count === 1) {\n value = value[0];\n }\n }\n }\n geoKeyDirectory[key] = value;\n }\n return geoKeyDirectory;\n }\n toObject() {\n /** @type {Record<string, unknown>} */\n const obj = {};\n for (const [tag, value] of this.actualizedFields.entries()) {\n const tagDefinition = typeof tag === 'number' ? tagDefinitions[tag] : undefined;\n const tagName = tagDefinition ? tagDefinition.name : `Tag${tag}`;\n obj[tagName] = value;\n }\n return obj;\n }\n}\n/**\n * Parser for Image File Directories (IFDs).\n */\nexport class ImageFileDirectoryParser {\n /**\n * @param {import(\"./source/basesource.js\").BaseSource} source the data source to fetch from\n * @param {boolean} littleEndian the endianness of the file\n * @param {boolean} bigTiff whether the file is a BigTIFF\n * @param {boolean} [eager=false] whether to eagerly fetch deferred fields.\n * When false (default), tags are loaded lazily on-demand.\n * When true, all tags are loaded immediately during parsing.\n */\n constructor(source, littleEndian, bigTiff, eager = false) {\n this.source = source;\n this.littleEndian = littleEndian;\n this.bigTiff = bigTiff;\n this.eager = eager;\n }\n /**\n * Helper function to retrieve a DataSlice from the source.\n * @param {number} offset Byte offset of the slice\n * @param {number} [length] Length of the slice\n * @returns {Promise<DataSlice>}\n */\n async getSlice(offset, length) {\n const fallbackLength = this.bigTiff ? 4048 : 1024;\n return new DataSlice((await this.source.fetch([\n {\n offset,\n length: typeof length !== 'undefined' ? length : fallbackLength,\n },\n ]))[0], offset, this.littleEndian, this.bigTiff);\n }\n /**\n * Instructs to parse an image file directory at the given file offset.\n * As there is no way to ensure that a location is indeed the start of an IFD,\n * this function must be called with caution (e.g only using the IFD offsets from\n * the headers or other IFDs).\n * @param {number} offset the offset to parse the IFD at\n * @returns {Promise<ImageFileDirectory>} the parsed IFD\n */\n async parseFileDirectoryAt(offset) {\n const entrySize = this.bigTiff ? 20 : 12;\n const offsetSize = this.bigTiff ? 8 : 2;\n let dataSlice = await this.getSlice(offset);\n const numDirEntries = this.bigTiff\n ? dataSlice.readUint64(offset)\n : dataSlice.readUint16(offset);\n // if the slice does not cover the whole IFD, request a bigger slice, where the\n // whole IFD fits: num of entries + n x tag length + offset to next IFD\n const byteSize = numDirEntries * (entrySize + (this.bigTiff ? 16 : 6));\n if (!dataSlice.covers(offset, byteSize)) {\n dataSlice = await this.getSlice(offset, byteSize);\n }\n const actualizedFields = new Map();\n const deferredFields = new Map();\n const deferredArrays = new Map();\n // loop over the IFD and create a file directory object\n let i = offset + (this.bigTiff ? 8 : 2);\n for (let entryCount = 0; entryCount < numDirEntries; i += entrySize, ++entryCount) {\n const fieldTag = dataSlice.readUint16(i);\n const fieldType = /** @type {import('./globals.js').FieldType} */ (dataSlice.readUint16(i + 2));\n const typeCount = this.bigTiff\n ? dataSlice.readUint64(i + 4)\n : dataSlice.readUint32(i + 4);\n let fieldValues = null;\n let deferredFieldValues = null;\n let deferredArray = null;\n const fieldTypeLength = getFieldTypeSize(fieldType);\n const valueOffset = i + (this.bigTiff ? 12 : 8);\n const isArray = tagDefinitions[fieldTag]?.isArray;\n const eager = tagDefinitions[fieldTag]?.eager || this.eager;\n // check whether the value is directly encoded in the tag or refers to a\n // different external byte range\n if (fieldTypeLength * typeCount <= (this.bigTiff ? 8 : 4)) {\n fieldValues = getValues(getArrayForSamples(fieldType, typeCount), getDataSliceReader(dataSlice, fieldType), dataSlice, fieldType, typeCount, valueOffset, isArray);\n }\n else {\n // resolve the reference to the actual byte range\n const actualOffset = dataSlice.readOffset(valueOffset);\n const length = getFieldTypeSize(fieldType) * typeCount;\n // check, whether we actually cover the referenced byte range\n if (dataSlice.covers(actualOffset, length)) {\n fieldValues = getValues(getArrayForSamples(fieldType, typeCount), getDataSliceReader(dataSlice, fieldType), dataSlice, fieldType, typeCount, actualOffset, isArray);\n }\n else if (eager) {\n // eager evaluation: fetch the data right now\n // TODO: instead of fetching the slice right here, collect all slices and fetch them together\n // to allow conjoined requests\n const fieldDataSlice = await this.getSlice(actualOffset, length);\n fieldValues = getValues(getArrayForSamples(fieldType, typeCount), getDataSliceReader(fieldDataSlice, fieldType), fieldDataSlice, fieldType, typeCount, actualOffset, isArray);\n }\n else if (isArray) {\n deferredArray = new DeferredArray(this.source, actualOffset, this.littleEndian, fieldType, typeCount);\n }\n else {\n deferredFieldValues = async () => {\n const fieldDataSlice = await this.getSlice(actualOffset, length);\n return getValues(getArrayForSamples(fieldType, typeCount), getDataSliceReader(fieldDataSlice, fieldType), fieldDataSlice, fieldType, typeCount, actualOffset, isArray);\n };\n }\n }\n if (fieldValues !== null) {\n actualizedFields.set(fieldTag, fieldValues);\n }\n else if (deferredFieldValues !== null) {\n deferredFields.set(fieldTag, deferredFieldValues);\n }\n else if (deferredArray !== null) {\n deferredArrays.set(fieldTag, deferredArray);\n }\n }\n const nextIFDByteOffset = dataSlice.readOffset(offset + offsetSize + (entrySize * numDirEntries));\n return new ImageFileDirectory(actualizedFields, deferredFields, deferredArrays, nextIFDByteOffset);\n }\n}\n//# sourceMappingURL=imagefiledirectory.js.map","/** @module geotiff */\nimport GeoTIFFImage from './geotiffimage.js';\nimport DataView64 from './dataview64.js';\nimport DataSlice from './dataslice.js';\nimport Pool from './pool.js';\nimport { makeRemoteSource, makeCustomSource } from './source/remote.js';\nimport { makeBufferSource } from './source/arraybuffer.js';\nimport { makeFileReaderSource } from './source/filereader.js';\nimport { makeFileSource } from './source/file.js';\nimport { BaseClient, BaseResponse } from './source/client/base.js';\nimport { ImageFileDirectoryParser } from './imagefiledirectory.js';\nimport { fieldTypes, getFieldTypeSize, registerTag } from './globals.js';\nimport { writeGeotiff } from './geotiffwriter.js';\nimport * as globals from './globals.js';\nimport * as rgb from './rgb.js';\nimport { getDecoder, addDecoder } from './compression/index.js';\nimport { setLogger } from './logging.js';\n/** @import { BaseSource } from './source/basesource.js' */\nexport { globals };\nexport { registerTag };\nexport { rgb };\nexport { default as BaseDecoder } from './compression/basedecoder.js';\nexport { getDecoder, addDecoder };\nexport { setLogger };\nexport { ImageFileDirectory } from './imagefiledirectory.js';\n/**\n * @typedef {Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array}\n * TypedArray\n */\n/**\n * @typedef {{ height:number, width: number }} Dimensions\n */\n/**\n * The autogenerated docs are a little confusing here. The effective type is:\n *\n * `TypedArray & { height: number; width: number}`\n * @typedef {TypedArray & Dimensions} TypedArrayWithDimensions\n */\n/**\n * The autogenerated docs are a little confusing here. The effective type is:\n *\n * `TypedArray[] & { height: number; width: number}`\n * @typedef {TypedArray[] & Dimensions} TypedArrayArrayWithDimensions\n */\n/**\n * @typedef {Object} GeotiffWriterMetadata\n * @property {number | number[]} [ImageWidth]\n * @property {number | number[]} [ImageLength]\n * @property {number} [width]\n * @property {number} [height]\n * @property {number | number[]} [BitsPerSample]\n * @property {number | number[]} [Compression]\n * @property {number | number[]} [PlanarConfiguration]\n * @property {number | number[]} [ExtraSamples]\n * @property {number | number[]} [PhotometricInterpretation]\n * @property {number | number[]} [SamplesPerPixel]\n * @property {number | number[]} [StripByteCounts]\n * @property {number[]} [ModelPixelScale]\n * @property {number[]} [ModelTransformation]\n * @property {number[]} [ModelTiepoint]\n * @property {number[]} [GeoKeyDirectory]\n * @property {string} [GeoAsciiParams]\n * @property {number[]} [GeoDoubleParams]\n * @property {number | number[]} [Orientation]\n * @property {number | number[]} [ResolutionUnit]\n * @property {number | number[]} [XPosition]\n * @property {number | number[]} [YPosition]\n * @property {number | number[]} [RowsPerStrip]\n * @property {number[]} [SampleFormat]\n * @property {number | number[]} [TileWidth]\n * @property {number | number[]} [TileLength]\n * @property {number[]} [TileOffsets]\n * @property {number[]} [TileByteCounts]\n * @property {string} [GDAL_NODATA]\n * @property {number | number[]} [GeographicTypeGeoKey]\n * @property {number | number[]} [ProjectedCSTypeGeoKey]\n * @property {string} [GeogCitationGeoKey]\n * @property {string} [GTCitationGeoKey]\n * @property {number | number[]} [GTModelTypeGeoKey]\n * @property {number | number[]} [GTRasterTypeGeoKey]\n */\n/**\n * The autogenerated docs are a little confusing here. The effective type is:\n *\n * `(TypedArray | TypedArray[]) & { height: number; width: number}`\n * @typedef {TypedArrayWithDimensions | TypedArrayArrayWithDimensions} ReadRasterResult\n */\n/**\n * @typedef {Object} DecoderWorker\n * Use the {@link Pool.bindParameters} method to get a decoder worker for\n * a specific compression and its parameters.\n *\n * @property {(buffer: ArrayBufferLike) => Promise<ArrayBufferLike>} decode\n * A function that takes a compressed buffer and returns a promise resolving to the decoded buffer.\n */\n/**\n * @typedef {Object} ReadRastersOptions\n * @property {Array<number>} [window] the subset to read data from in pixels. Whole window if not specified.\n * @property {Array<number>} [samples] the selection of samples to read from. Default is all samples.\n * All samples if not specified.\n * @property {Pool|null} [pool=null] The optional decoder pool to use.\n * @property {number} [width] The desired width of the output. When the width is not the\n * same as the images, resampling will be performed.\n * @property {number} [height] The desired height of the output. When the width is not the\n * same as the images, resampling will be performed.\n * @property {string} [resampleMethod='nearest'] The desired resampling method.\n * @property {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @property {number|number[]} [fillValue] The value to use for parts of the image\n * outside of the images extent. When multiple samples are requested and `interleave` is\n * `false`, an array of fill values can be passed.\n * @property {boolean|true|false} [interleave] whether the data shall be read\n * in one single array or separate arrays.\n */\n/**\n * @typedef {Object} ReadRGBOptions\n * @property {Array<number>} [window] the subset to read data from in pixels. Whole window if not specified.\n * @property {Pool|null} [pool=null] The optional decoder pool to use.\n * @property {number} [width] The desired width of the output. When the width is no the\n * same as the images, resampling will be performed.\n * @property {number} [height] The desired height of the output. When the width is no the\n * same as the images, resampling will be performed.\n * @property {string} [resampleMethod='nearest'] The desired resampling method.\n * @property {boolean} [enableAlpha=false] Enable reading alpha channel if present.\n * @property {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @property {boolean|true|false} [interleave] whether the data shall be read\n * in one single array or separate arrays.\n */\n/**\n * @typedef {Object} BlockedSourceOptions\n * @property {number} [blockSize] Block size for a BlockedSource.\n * @property {number} [cacheSize=100] The number of blocks to cache.\n */\n/**\n * @typedef {Object} RemoteSourceOptions\n * @property {Record<string, string>} [headers={}] Additional headers to add to each request\n * @property {number} [maxRanges=0] Maximum number of ranges to request in a single HTTP request. 0 means no multi-range requests.\n * @property {boolean} [allowFullFile=false] Whether to allow full file responses when requesting ranges\n * @property {boolean} [forceXHR=false] When the Fetch API would be used, force using XMLHttpRequest instead.\n */\n/**\n * @overload\n * @param {DataSlice} dataSlice\n * @param {0x0002} fieldType\n * @param {number} count\n * @param {number} offset\n * @returns {string}\n */\n/**\n * @param {DataSlice} dataSlice\n * @param {import('./globals.js').FieldType} fieldType\n * @param {number} count\n * @param {number} offset\n * @returns {TypedArray|Array<number>|string}\n */\nfunction getValues(dataSlice, fieldType, count, offset) {\n /** @type {TypedArray|Array<number>|null} */\n let values = null;\n let readMethod = null;\n const fieldTypeLength = getFieldTypeSize(fieldType);\n switch (fieldType) {\n case fieldTypes.BYTE:\n case fieldTypes.ASCII:\n case fieldTypes.UNDEFINED:\n values = new Uint8Array(count);\n readMethod = dataSlice.readUint8;\n break;\n case fieldTypes.SBYTE:\n values = new Int8Array(count);\n readMethod = dataSlice.readInt8;\n break;\n case fieldTypes.SHORT:\n values = new Uint16Array(count);\n readMethod = dataSlice.readUint16;\n break;\n case fieldTypes.SSHORT:\n values = new Int16Array(count);\n readMethod = dataSlice.readInt16;\n break;\n case fieldTypes.LONG:\n case fieldTypes.IFD:\n values = new Uint32Array(count);\n readMethod = dataSlice.readUint32;\n break;\n case fieldTypes.SLONG:\n values = new Int32Array(count);\n readMethod = dataSlice.readInt32;\n break;\n case fieldTypes.LONG8:\n case fieldTypes.IFD8:\n values = new Array(count);\n readMethod = dataSlice.readUint64;\n break;\n case fieldTypes.SLONG8:\n values = new Array(count);\n readMethod = dataSlice.readInt64;\n break;\n case fieldTypes.RATIONAL:\n values = new Uint32Array(count * 2);\n readMethod = dataSlice.readUint32;\n break;\n case fieldTypes.SRATIONAL:\n values = new Int32Array(count * 2);\n readMethod = dataSlice.readInt32;\n break;\n case fieldTypes.FLOAT:\n values = new Float32Array(count);\n readMethod = dataSlice.readFloat32;\n break;\n case fieldTypes.DOUBLE:\n values = new Float64Array(count);\n readMethod = dataSlice.readFloat64;\n break;\n default:\n // will throw below\n }\n if (values === null || readMethod === null) {\n throw new RangeError(`Invalid field type: ${fieldType}`);\n }\n // normal fields\n if (!(fieldType === fieldTypes.RATIONAL || fieldType === fieldTypes.SRATIONAL)) {\n for (let i = 0; i < count; ++i) {\n values[i] = readMethod.call(dataSlice, offset + (i * fieldTypeLength));\n }\n }\n else { // RATIONAL or SRATIONAL\n for (let i = 0; i < count; i += 2) {\n values[i] = readMethod.call(dataSlice, offset + (i * fieldTypeLength));\n values[i + 1] = readMethod.call(dataSlice, offset + ((i * fieldTypeLength) + 4));\n }\n }\n if (fieldType === fieldTypes.ASCII) {\n return new TextDecoder('utf-8').decode(/** @type {Uint8Array} */ (values));\n }\n return values;\n}\n/**\n * Error class for cases when an IFD index was requested, that does not exist\n * in the file.\n */\nclass GeoTIFFImageIndexError extends Error {\n /**\n * @param {number} index\n */\n constructor(index) {\n super(`No image at index ${index}`);\n this.index = index;\n }\n}\nclass GeoTIFFBase {\n /**\n * @param {number} [_index=0] the index of the image to return.\n * @returns {Promise<GeoTIFFImage>} the image at the given index\n */\n async getImage(_index = 0) {\n throw new Error('Not implemented');\n }\n /**\n * @returns {Promise<number>} the number of internal subfile images\n */\n async getImageCount() {\n throw new Error('Not implemented');\n }\n /**\n * @typedef {Object} ReadRastersWindowOptions\n * @property {number} [resX] desired Y resolution (world units per pixel)\n * @property {number} [resY] desired X resolution (world units per pixel)\n * @property {Array<number>} [bbox] the subset to read data from in\n * geographical coordinates. Whole image if not specified.\n */\n /**\n * (experimental) Reads raster data from the best fitting image. This function uses\n * the image with the lowest resolution that is still a higher resolution than the\n * requested resolution.\n * When specified, the `bbox` option is translated to the `window` option and the\n * `resX` and `resY` to `width` and `height` respectively.\n * Then, the [readRasters]{@link GeoTIFFImage#readRasters} method of the selected\n * image is called and the result returned.\n * @see GeoTIFFImage.readRasters\n * @param {ReadRastersOptions & ReadRastersWindowOptions} options optional parameters\n * @returns {Promise<ReadRasterResult>} the decoded array(s), with `height` and `width`, as a promise\n */\n async readRasters(options = {}) {\n const { window: imageWindow, width, height } = options;\n let { resX, resY, bbox } = options;\n const firstImage = await this.getImage();\n let usedImage = firstImage;\n const imageCount = await this.getImageCount();\n const imgBBox = firstImage.getBoundingBox();\n if (imageWindow && bbox) {\n throw new Error('Both \"bbox\" and \"window\" passed.');\n }\n // if width/height is passed, transform it to resolution\n if (width || height) {\n // if we have an image window (pixel coordinates), transform it to a BBox\n // using the origin/resolution of the first image.\n if (imageWindow) {\n const [oX, oY] = firstImage.getOrigin();\n const [rX, rY] = firstImage.getResolution();\n bbox = [\n oX + (imageWindow[0] * rX),\n oY + (imageWindow[1] * rY),\n oX + (imageWindow[2] * rX),\n oY + (imageWindow[3] * rY),\n ];\n }\n // if we have a bbox (or calculated one)\n const usedBBox = bbox || imgBBox;\n if (width) {\n if (resX) {\n throw new Error('Both width and resX passed');\n }\n resX = (usedBBox[2] - usedBBox[0]) / width;\n }\n if (height) {\n if (resY) {\n throw new Error('Both width and resY passed');\n }\n resY = (usedBBox[3] - usedBBox[1]) / height;\n }\n }\n // if resolution is set or calculated, try to get the image with the worst acceptable resolution\n if (resX || resY) {\n const allImages = [];\n for (let i = 0; i < imageCount; ++i) {\n const image = await this.getImage(i);\n const subfileType = image.fileDirectory.getValue('SubfileType');\n const newSubfileType = image.fileDirectory.getValue('NewSubfileType');\n if (i === 0 || subfileType === 2 || (newSubfileType || 0) & 1) {\n allImages.push(image);\n }\n }\n allImages.sort((a, b) => a.getWidth() - b.getWidth());\n for (let i = 0; i < allImages.length; ++i) {\n const image = allImages[i];\n const imgResX = (imgBBox[2] - imgBBox[0]) / image.getWidth();\n const imgResY = (imgBBox[3] - imgBBox[1]) / image.getHeight();\n usedImage = image;\n if ((resX && resX > imgResX) || (resY && resY > imgResY)) {\n break;\n }\n }\n }\n let wnd = imageWindow;\n if (bbox) {\n const [oX, oY] = firstImage.getOrigin();\n const [imageResX, imageResY] = usedImage.getResolution(firstImage);\n wnd = [\n Math.round((bbox[0] - oX) / imageResX),\n Math.round((bbox[1] - oY) / imageResY),\n Math.round((bbox[2] - oX) / imageResX),\n Math.round((bbox[3] - oY) / imageResY),\n ];\n wnd = [\n Math.min(wnd[0], wnd[2]),\n Math.min(wnd[1], wnd[3]),\n Math.max(wnd[0], wnd[2]),\n Math.max(wnd[1], wnd[3]),\n ];\n }\n return usedImage.readRasters({ ...options, window: wnd });\n }\n}\n/**\n * @typedef {Object} GeoTIFFOptions\n * @property {boolean} [cache=false] whether or not decoded tiles shall be cached.\n */\n/**\n * The abstraction for a whole GeoTIFF file.\n */\nclass GeoTIFF extends GeoTIFFBase {\n /**\n * @constructor\n * @param {BaseSource} source The datasource to read from.\n * @param {boolean} littleEndian Whether the image uses little endian.\n * @param {boolean} bigTiff Whether the image uses bigTIFF conventions.\n * @param {number} firstIFDOffset The numeric byte-offset from the start of the image\n * to the first IFD.\n * @param {GeoTIFFOptions} [options] further options.\n */\n constructor(source, littleEndian, bigTiff, firstIFDOffset, options = {}) {\n super();\n this.source = source;\n this.parser = new ImageFileDirectoryParser(source, littleEndian, bigTiff, false);\n this.littleEndian = littleEndian;\n this.bigTiff = bigTiff;\n this.firstIFDOffset = firstIFDOffset;\n this.cache = options.cache || false;\n /** @type {Array<Promise<import('./imagefiledirectory.js').ImageFileDirectory> | undefined>} */\n this.ifdRequests = [];\n /** @type {Record<string, unknown>|null} */\n this.ghostValues = null;\n }\n /**\n * @param {number} offset\n * @param {number} [size]\n * @returns {Promise<DataSlice>}\n */\n async getSlice(offset, size) {\n const fallbackSize = this.bigTiff ? 4048 : 1024;\n return new DataSlice((await this.source.fetch([{\n offset,\n length: typeof size !== 'undefined' ? size : fallbackSize,\n }]))[0], offset, this.littleEndian, this.bigTiff);\n }\n /**\n * @param {number} index\n * @return {Promise<import('./imagefiledirectory.js').ImageFileDirectory>}\n */\n async requestIFD(index) {\n // see if we already have that IFD index requested.\n if (this.ifdRequests[index]) {\n // attach to an already requested IFD\n return this.ifdRequests[index];\n }\n else if (index === 0) {\n // special case for index 0\n this.ifdRequests[index] = this.parser.parseFileDirectoryAt(this.firstIFDOffset);\n return this.ifdRequests[index];\n }\n else if (!this.ifdRequests[index - 1]) {\n // if the previous IFD was not yet loaded, load that one first\n // this is the recursive call.\n try {\n this.ifdRequests[index - 1] = this.requestIFD(index - 1);\n }\n catch (e) {\n // if the previous one already was an index error, rethrow\n // with the current index\n if (e instanceof GeoTIFFImageIndexError) {\n throw new GeoTIFFImageIndexError(index);\n }\n // rethrow anything else\n throw e;\n }\n }\n // if the previous IFD was loaded, we can finally fetch the one we are interested in.\n // we need to wrap this in an IIFE, otherwise this.ifdRequests[index] would be delayed\n this.ifdRequests[index] = (async () => {\n const previousPromise = this.ifdRequests[index - 1];\n if (!previousPromise) {\n throw new Error('Previous IFD request missing');\n }\n const previousIfd = await previousPromise;\n if (previousIfd.nextIFDByteOffset === 0) {\n throw new GeoTIFFImageIndexError(index);\n }\n return this.parser.parseFileDirectoryAt(previousIfd.nextIFDByteOffset);\n })();\n return this.ifdRequests[index];\n }\n /**\n * Get the n-th internal subfile of an image. By default, the first is returned.\n *\n * @param {number} [index=0] the index of the image to return.\n * @returns {Promise<GeoTIFFImage>} the image at the given index\n */\n async getImage(index = 0) {\n return new GeoTIFFImage(await this.requestIFD(index), this.littleEndian, this.cache, this.source);\n }\n /**\n * Returns the count of the internal subfiles.\n *\n * @returns {Promise<number>} the number of internal subfile images\n */\n async getImageCount() {\n let index = 0;\n // loop until we run out of IFDs\n let hasNext = true;\n while (hasNext) {\n try {\n await this.requestIFD(index);\n ++index;\n }\n catch (e) {\n if (e instanceof GeoTIFFImageIndexError) {\n hasNext = false;\n }\n else {\n throw e;\n }\n }\n }\n return index;\n }\n /**\n * Get the values of the COG ghost area as a parsed map.\n * See https://gdal.org/drivers/raster/cog.html#header-ghost-area for reference\n * @returns {Promise<Record<string, unknown>|null>} the parsed ghost area or null, if no such area was found\n */\n async getGhostValues() {\n const offset = this.bigTiff ? 16 : 8;\n if (this.ghostValues !== null) {\n return this.ghostValues;\n }\n const detectionString = 'GDAL_STRUCTURAL_METADATA_SIZE=';\n const heuristicAreaSize = detectionString.length + 100;\n let slice = await this.getSlice(offset, heuristicAreaSize);\n if (detectionString === getValues(slice, fieldTypes.ASCII, detectionString.length, offset)) {\n const valuesString = getValues(slice, fieldTypes.ASCII, heuristicAreaSize, offset);\n const firstLine = valuesString.split('\\n')[0];\n const metadataSize = Number(firstLine.split('=')[1].split(' ')[0]) + firstLine.length;\n if (metadataSize > heuristicAreaSize) {\n slice = await this.getSlice(offset, metadataSize);\n }\n const fullString = getValues(slice, fieldTypes.ASCII, metadataSize, offset);\n /** @type {Record<string, unknown>} */\n const ghostValues = {};\n fullString\n .split('\\n')\n .filter((line) => line.length > 0)\n .map((line) => line.split('='))\n .forEach(([key, value]) => {\n ghostValues[key] = value;\n });\n this.ghostValues = ghostValues;\n }\n return this.ghostValues;\n }\n /**\n * Parse a (Geo)TIFF file from the given source.\n *\n * @param {BaseSource} source The source of data to parse from.\n * @param {GeoTIFFOptions} [options] Additional options.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n */\n static async fromSource(source, options, signal) {\n const headerData = (await source.fetch([{ offset: 0, length: 1024 }], signal))[0];\n const dataView = new DataView64(headerData);\n const BOM = dataView.getUint16(0, false);\n let littleEndian;\n if (BOM === 0x4949) {\n littleEndian = true;\n }\n else if (BOM === 0x4D4D) {\n littleEndian = false;\n }\n else {\n throw new TypeError('Invalid byte order value.');\n }\n const magicNumber = dataView.getUint16(2, littleEndian);\n let bigTiff;\n if (magicNumber === 42) {\n bigTiff = false;\n }\n else if (magicNumber === 43) {\n bigTiff = true;\n const offsetByteSize = dataView.getUint16(4, littleEndian);\n if (offsetByteSize !== 8) {\n throw new Error('Unsupported offset byte-size.');\n }\n }\n else {\n throw new TypeError('Invalid magic number.');\n }\n const firstIFDOffset = bigTiff\n ? dataView.getUint64(8, littleEndian)\n : dataView.getUint32(4, littleEndian);\n return new GeoTIFF(source, littleEndian, bigTiff, firstIFDOffset, options);\n }\n /**\n * Closes the underlying file buffer\n * N.B. After the GeoTIFF has been completely processed it needs\n * to be closed but only if it has been constructed from a file.\n */\n close() {\n if (typeof this.source.close === 'function') {\n return this.source.close();\n }\n return false;\n }\n}\nexport { GeoTIFF };\nexport default GeoTIFF;\n/**\n * Wrapper for GeoTIFF files that have external overviews.\n * @augments GeoTIFFBase\n */\nclass MultiGeoTIFF extends GeoTIFFBase {\n /**\n * Construct a new MultiGeoTIFF from a main and several overview files.\n * @param {GeoTIFF} mainFile The main GeoTIFF file.\n * @param {GeoTIFF[]} overviewFiles An array of overview files.\n */\n constructor(mainFile, overviewFiles) {\n super();\n this.mainFile = mainFile;\n this.overviewFiles = overviewFiles;\n this.imageFiles = [mainFile].concat(overviewFiles);\n this.fileDirectoriesPerFile = null;\n this.fileDirectoriesPerFileParsing = null;\n this.imageCount = null;\n }\n async parseFileDirectoriesPerFile() {\n const requests = [this.mainFile.parser.parseFileDirectoryAt(this.mainFile.firstIFDOffset)]\n .concat(this.overviewFiles.map((file) => file.parser.parseFileDirectoryAt(file.firstIFDOffset)));\n this.fileDirectoriesPerFile = await Promise.all(requests);\n return this.fileDirectoriesPerFile;\n }\n /**\n * Get the n-th internal subfile of an image. By default, the first is returned.\n *\n * @param {number} [index=0] the index of the image to return.\n * @returns {Promise<GeoTIFFImage>} the image at the given index\n */\n async getImage(index = 0) {\n // Initialize this.imageCounts if not yet done\n await this.getImageCount();\n if (!this.imageCounts) {\n throw new Error('Image counts not available');\n }\n await this.parseFileDirectoriesPerFile();\n let visited = 0;\n let relativeIndex = 0;\n for (let i = 0; i < this.imageFiles.length; i++) {\n const imageFile = this.imageFiles[i];\n for (let ii = 0; ii < this.imageCounts[i]; ii++) {\n if (index === visited) {\n return new GeoTIFFImage(await imageFile.requestIFD(relativeIndex), imageFile.littleEndian, imageFile.cache, imageFile.source);\n }\n visited++;\n relativeIndex++;\n }\n relativeIndex = 0;\n }\n throw new RangeError('Invalid image index');\n }\n /**\n * Returns the count of the internal subfiles.\n *\n * @returns {Promise<number>} the number of internal subfile images\n */\n async getImageCount() {\n if (this.imageCount !== null) {\n return this.imageCount;\n }\n const requests = [this.mainFile.getImageCount()]\n .concat(this.overviewFiles.map((file) => file.getImageCount()));\n this.imageCounts = await Promise.all(requests);\n this.imageCount = this.imageCounts.reduce((count, ifds) => count + ifds, 0);\n return this.imageCount;\n }\n}\nexport { MultiGeoTIFF };\n/**\n * Creates a new GeoTIFF from a remote URL.\n * @param {string} url The URL to access the image from\n * @param {RemoteSourceOptions} [options] Additional options to pass to the source.\n * See {@link makeRemoteSource} for details.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<GeoTIFF>} The resulting GeoTIFF file.\n */\nexport async function fromUrl(url, options = {}, signal) {\n return GeoTIFF.fromSource(makeRemoteSource(url, options), undefined, signal);\n}\n/**\n * Creates a new GeoTIFF from a custom {@link BaseClient}.\n * @param {BaseClient} client The client.\n * @param {RemoteSourceOptions} [options] Additional options to pass to the source.\n * See {@link makeRemoteSource} for details.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<GeoTIFF>} The resulting GeoTIFF file.\n */\nexport async function fromCustomClient(client, options = {}, signal) {\n return GeoTIFF.fromSource(makeCustomSource(client, options), undefined, signal);\n}\n/**\n * Construct a new GeoTIFF from an\n * [ArrayBuffer]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer}.\n * @param {ArrayBuffer} arrayBuffer The data to read the file from.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<GeoTIFF>} The resulting GeoTIFF file.\n */\nexport async function fromArrayBuffer(arrayBuffer, signal) {\n return GeoTIFF.fromSource(makeBufferSource(arrayBuffer), undefined, signal);\n}\n/**\n * Construct a GeoTIFF from a local file path. This uses the node\n * [filesystem API]{@link https://nodejs.org/api/fs.html} and is\n * not available on browsers.\n *\n * N.B. After the GeoTIFF has been completely processed it needs\n * to be closed but only if it has been constructed from a file.\n * @param {string} path The file path to read from.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<GeoTIFF>} The resulting GeoTIFF file.\n */\nexport async function fromFile(path, signal) {\n return GeoTIFF.fromSource(makeFileSource(path), undefined, signal);\n}\n/**\n * Construct a GeoTIFF from an HTML\n * [Blob]{@link https://developer.mozilla.org/en-US/docs/Web/API/Blob} or\n * [File]{@link https://developer.mozilla.org/en-US/docs/Web/API/File}\n * object.\n * @param {Blob|File} blob The Blob or File object to read from.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<GeoTIFF>} The resulting GeoTIFF file.\n */\nexport async function fromBlob(blob, signal) {\n return GeoTIFF.fromSource(makeFileReaderSource(blob), undefined, signal);\n}\n/**\n * Construct a MultiGeoTIFF from the given URLs.\n * @param {string} mainUrl The URL for the main file.\n * @param {string[]} overviewUrls An array of URLs for the overview images.\n * @param {RemoteSourceOptions} [options] Additional options to pass to the source.\n * See [makeRemoteSource]{@link module:source.makeRemoteSource}\n * for details.\n * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is\n * to be aborted\n * @returns {Promise<MultiGeoTIFF>} The resulting MultiGeoTIFF file.\n */\nexport async function fromUrls(mainUrl, overviewUrls = [], options = {}, signal) {\n const mainFile = await GeoTIFF.fromSource(makeRemoteSource(mainUrl, options), undefined, signal);\n const overviewFiles = await Promise.all(overviewUrls.map((url) => GeoTIFF.fromSource(makeRemoteSource(url, options), undefined, signal)));\n return new MultiGeoTIFF(mainFile, overviewFiles);\n}\n/**\n * Main creating function for GeoTIFF files.\n * @param {Array<number>|Array<Array<Array<number>>>|TypedArray} values The pixel values to write.\n * Can be a flat array of all pixels or a 3-dimensional array of shape `[band][row][column]`.\n * @param {GeotiffWriterMetadata} metadata\n * @returns {ArrayBuffer}\n */\nexport function writeArrayBuffer(values, metadata) {\n return writeGeotiff(values, metadata);\n}\nexport { Pool };\nexport { GeoTIFFImage };\nexport { BaseClient, BaseResponse };\n//# sourceMappingURL=geotiff.js.map","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { fromArrayBuffer } from 'geotiff';\n\nimport { GeoTiffTable } from '../../../shared/interfaces';\nimport { LoadGeoTiffParams } from './interfaces';\nimport { DEFALT_COORDINATE_FORMAT } from '../../../shared/consts';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\n\nconst DEFAULT_MAX_PIXELS = 500_000;\n\n/**\n * Loads a GeoTIFF raster file into DuckDB as a spatially-indexed table.\n */\nexport class LoadGeoTiffUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n }\n\n async exec(params: LoadGeoTiffParams): Promise<GeoTiffTable> {\n const {\n geotiffFileUrl,\n geotiffArrayBuffer,\n outputTableName,\n coordinateFormat = DEFALT_COORDINATE_FORMAT,\n sourceCrs,\n workspace = 'main',\n boundingBox,\n maxPixels = DEFAULT_MAX_PIXELS,\n } = params;\n\n if (!geotiffFileUrl && !geotiffArrayBuffer) {\n throw new Error('Either geotiffFileUrl or geotiffArrayBuffer must be provided.');\n }\n if (geotiffFileUrl && geotiffArrayBuffer) {\n throw new Error('Cannot provide both geotiffFileUrl and geotiffArrayBuffer.');\n }\n\n const qualifiedTableName = `${workspace}.${outputTableName}`;\n const csvFile = `_geotiff_${Date.now()}_${Math.random().toString(36).substring(2, 7)}.csv`;\n\n // 1. Obtain the file buffer\n let buffer: ArrayBuffer;\n if (geotiffFileUrl) {\n const response = await fetch(geotiffFileUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch GeoTIFF from ${geotiffFileUrl}: HTTP ${response.status}`);\n }\n buffer = await response.arrayBuffer();\n } else {\n buffer = geotiffArrayBuffer!;\n }\n\n // 2. Parse metadata with geotiff.js\n const tiff = await fromArrayBuffer(buffer);\n const image = await tiff.getImage(0);\n\n const origin = image.getOrigin(); // [originX, originY] — top-left corner in source CRS\n const resolution = image.getResolution(); // [resX, resY] — resY is negative\n const originX = origin[0];\n const originY = origin[1];\n const resX = resolution[0];\n const resY = resolution[1]; // negative\n const fullWidth = Number(image.getWidth());\n const fullHeight = Number(image.getHeight());\n const bandCount = Number(image.getSamplesPerPixel());\n\n // 3. Compute pixel window from optional bounding box\n // Detect 0-360 longitude convention: originX >= 0 and raster spans > 180 degrees\n const rasterMaxX = originX + fullWidth * resX;\n const is0To360 = originX >= 0 && rasterMaxX > 180;\n\n let window: [number, number, number, number] | undefined;\n if (boundingBox) {\n let minLon = boundingBox.minLon;\n let maxLon = boundingBox.maxLon;\n\n // Convert -180/180 bounding box to 0-360 if the raster uses that convention\n if (is0To360) {\n if (minLon < 0) minLon += 360;\n if (maxLon < 0) maxLon += 360;\n }\n\n const xMin = Math.max(0, Math.floor((minLon - originX) / resX));\n const xMax = Math.min(fullWidth, Math.ceil((maxLon - originX) / resX));\n // resY is negative so the lat comparison is inverted\n const yMin = Math.max(0, Math.floor((boundingBox.maxLat - originY) / resY));\n const yMax = Math.min(fullHeight, Math.ceil((boundingBox.minLat - originY) / resY));\n if (xMin >= xMax || yMin >= yMax) {\n console.warn(\n `[LoadGeoTiff] Bounding box does not overlap with raster extent — loading full raster. ` +\n `Computed window [${xMin}, ${yMin}, ${xMax}, ${yMax}] is invalid. ` +\n `Raster uses ${is0To360 ? '0–360' : '-180–180'} longitude convention, ` +\n `origin: (${originX}, ${originY}), size: ${fullWidth}×${fullHeight}.`\n );\n } else {\n window = [xMin, yMin, xMax, yMax];\n }\n }\n\n const windowWidth = window ? window[2] - window[0] : fullWidth;\n const windowHeight = window ? window[3] - window[1] : fullHeight;\n const pixelCount = windowWidth * windowHeight;\n\n if (pixelCount > maxPixels) {\n throw new Error(\n `GeoTIFF region is ${pixelCount.toLocaleString()} pixels, which exceeds the limit of ` +\n `${maxPixels.toLocaleString()}. Supply a 'boundingBox' to clip to a smaller area, ` +\n `or increase 'maxPixels' if your environment can handle it.`\n );\n }\n\n // 4. Decode pixel data (optionally windowed)\n const rasters = await image.readRasters({ window });\n const colOffset = window ? window[0] : 0;\n const rowOffset = window ? window[1] : 0;\n\n // 5. Collect band arrays\n const bandNames: string[] = [];\n const bandData: Array<ArrayLike<number>> = [];\n for (let b = 0; b < bandCount; b++) {\n bandNames.push(`band_${b + 1}`);\n bandData.push((rasters as unknown as Array<ArrayLike<number>>)[b]);\n }\n\n // 6. Build CSV: header + one row per pixel\n const header = ['lon', 'lat', ...bandNames].join(',');\n const lines: string[] = [header];\n for (let row = 0; row < windowHeight; row++) {\n for (let col = 0; col < windowWidth; col++) {\n const idx = row * windowWidth + col;\n const lon = originX + (colOffset + col + 0.5) * resX;\n const lat = originY + (rowOffset + row + 0.5) * resY;\n const bands = bandData.map((b) => { const v = b[idx]; return isNaN(v) ? '' : v; }).join(',');\n lines.push(`${lon},${lat},${bands}`);\n }\n }\n\n await this.db.registerFileText(csvFile, lines.join('\\n'));\n\n try {\n // 7. Build geometry expression with optional CRS reprojection\n const shouldTransform = sourceCrs && sourceCrs !== coordinateFormat;\n const geomExpr = shouldTransform\n ? `ST_Transform(ST_Point(lon, lat), '${sourceCrs}', '${coordinateFormat}', always_xy := true)`\n : `ST_Point(lon, lat)`;\n\n const propertiesExpr =\n bandNames.length > 0\n ? `{${bandNames.map((n) => `'${n}': \"${n}\"`).join(', ')}}`\n : `NULL::JSON`;\n\n // 8. Create the final table from the CSV\n await this.conn.query(`\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT\n ${geomExpr} AS geometry,\n ${propertiesExpr} AS properties\n FROM read_csv('${csvFile}', header=true, delim=',');\n `);\n\n // 9. Spatial index for query performance\n await this.conn.query(\n `CREATE INDEX idx_${outputTableName}_geometry ON ${qualifiedTableName} USING RTREE (geometry);`\n );\n\n const describeResult = await this.conn.query(`DESCRIBE ${qualifiedTableName};`);\n return {\n source: 'geotiff',\n type: 'raster',\n name: outputTableName,\n columns: getColumnsFromDuckDbTableDescribe(describeResult.toArray()),\n };\n } finally {\n await this.db.dropFile(csvFile);\n }\n }\n}\n","/**\n * Custom error types for raw query validation.\n */\n\nexport class NonSelectQueryError extends Error {\n constructor() {\n super('Only SELECT queries are allowed for raw queries.');\n this.name = 'NonSelectQueryError';\n }\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { RawQueryParams, RawQueryOutput } from './interfaces';\nimport { NonSelectQueryError } from './errors';\nimport { Table } from '../../../shared/interfaces';\nimport { getColumnsFromDuckDbTableDescribe, toPlain } from '../../shared/utils';\n\n/**\n * Executes a raw SQL query with safety validation against mutation statements.\n */\nexport class RawQueryUseCase {\n private conn: AsyncDuckDBConnection;\n\n constructor(conn: AsyncDuckDBConnection) {\n this.conn = conn;\n }\n\n async exec(params: RawQueryParams): Promise<Table | RawQueryOutput> {\n this.validateQuery(params.query);\n\n if (params.output.type === 'CREATE_TABLE') {\n if (!params.output.tableName) {\n throw new Error('output.tableName must be provided when output.type is \"CREATE_TABLE\"');\n }\n\n const tableName = params.output.tableName;\n\n const createTableQuery = `CREATE OR REPLACE TABLE ${tableName} AS\\n${params.query};\\n\\nDESCRIBE ${tableName};`;\n\n const describeResult = await this.conn.query(createTableQuery);\n\n const table = {\n source: params.output.source || 'user',\n type: params.output.tableType || 'pointset',\n name: tableName,\n columns: getColumnsFromDuckDbTableDescribe(describeResult.toArray()),\n } as unknown as Table;\n\n return table;\n }\n\n const res = await this.conn.query(params.query);\n return res.toArray().map((row) => toPlain(row.toJSON())) as RawQueryOutput;\n }\n\n private validateQuery(query: string) {\n const q = query.trim().toLowerCase();\n\n // Allow queries that start with SELECT or WITH (CTE followed by SELECT)\n const isSelectLike = q.startsWith('select') || q.startsWith('with');\n\n const forbidden = ['insert', 'update', 'delete', 'create', 'alter', 'drop', 'truncate', 'replace'];\n const hasForbidden = forbidden.some((word) => new RegExp(`\\\\b${word}\\\\b`, 'i').test(q));\n\n if (!isSelectLike || hasForbidden) {\n throw new NonSelectQueryError();\n }\n }\n}\n","export const GET_BOUNDING_BOX_FROM_OSM_QUERY = (osmTableName: string, workspace: string) => {\n const qualifiedTableName = `${workspace}.${osmTableName}`;\n return `\n SELECT \n CAST(MIN(lon) AS DOUBLE) as minLon,\n CAST(MIN(lat) AS DOUBLE) as minLat,\n CAST(MAX(lon) AS DOUBLE) as maxLon,\n CAST(MAX(lat) AS DOUBLE) as maxLat\n FROM ${qualifiedTableName}\n WHERE lat IS NOT NULL AND lon IS NOT NULL;\n `;\n};\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { BoundingBox } from '../../../../shared/interfaces';\nimport { GetBoundingBoxFromOsmParams } from './interfaces';\nimport { GET_BOUNDING_BOX_FROM_OSM_QUERY } from './queries';\n\n/**\n * Computes the geographic bounding box of an OSM boundary table.\n */\nexport class GetBoundingBoxFromOsmUseCase {\n constructor(private conn: AsyncDuckDBConnection) {}\n\n /**\n * Queries the spatial extent of boundary way geometries in an OSM table.\n *\n * @param params.osmTableName Name of the OSM boundaries table.\n * @param params.workspace Optional workspace name (defaults to `main`).\n * @returns Named bounding box.\n * @throws If the table has no coordinates or invalid values.\n */\n async exec(params: GetBoundingBoxFromOsmParams): Promise<BoundingBox> {\n const workspace = params.workspace || 'main';\n const result = await this.conn.query(GET_BOUNDING_BOX_FROM_OSM_QUERY(params.osmTableName, workspace));\n const rows = result.toArray();\n\n if (rows.length === 0) {\n throw new Error(`Could not calculate bounding box - no coordinates found in table ${params.osmTableName}`);\n }\n\n const row = rows[0];\n\n if (row.minLon == null || row.minLat == null || row.maxLon == null || row.maxLat == null) {\n throw new Error(`Could not calculate bounding box - invalid coordinates found in table ${params.osmTableName}`);\n }\n\n return {\n minLon: row.minLon,\n minLat: row.minLat,\n maxLon: row.maxLon,\n maxLat: row.maxLat,\n };\n }\n}\n","export const LOAD_POLYGONIZED_LAYER_QUERY = (\n featureCollectionTableName: string,\n outputTableName: string,\n workspace: string,\n) => {\n const qualifiedFeatureCollectionTableName = `${workspace}.${featureCollectionTableName}`;\n const qualifiedOutputTableName = `${workspace}.${outputTableName}`;\n \n return `\n CREATE OR REPLACE TABLE ${qualifiedOutputTableName} AS\n SELECT\n ST_GeomFromGeoJSON(JSON(feature.geometry)) AS geometry,\n feature.properties AS properties\n FROM (\n SELECT UNNEST(features) AS feature\n FROM ${qualifiedFeatureCollectionTableName}\n );\n\n DROP TABLE ${qualifiedFeatureCollectionTableName};\n\n DESCRIBE ${qualifiedOutputTableName};\n `;\n};\n\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { FeatureCollection, LineString, Polygon } from 'geojson';\nimport { polygonize } from '@turf/turf';\n\nimport { PolygonizeSurfaceLayerParams } from './interfaces';\nimport { LayerTable } from '../../../shared/interfaces';\nimport { GetLayerGeojsonUseCase } from '../get-layer-geojson';\nimport { LOAD_FEATURE_COLLECTION_QUERY } from '../load-custom-layer/queries';\nimport { LOAD_POLYGONIZED_LAYER_QUERY } from './queries';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\n\n/**\n * Polygonizes a surface layer from line geometries into closed polygons.\n */\nexport class PolygonizeSurfaceLayerUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n private getLayerGeojsonUseCase: GetLayerGeojsonUseCase;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n this.getLayerGeojsonUseCase = new GetLayerGeojsonUseCase(conn);\n }\n\n async exec(params: PolygonizeSurfaceLayerParams, surfaceTable: LayerTable): Promise<LayerTable> {\n const { surfaceTableName, workspace = 'main' } = params;\n const qualifiedSurfaceTableName = `${workspace}.${surfaceTableName}`;\n const qualifiedFeatureCollectionTableName = `${workspace}.${surfaceTableName}_feature_collection`;\n\n const geojson = await this.getLayerGeojsonUseCase.exec(surfaceTable, workspace) as FeatureCollection<LineString>;\n const polygonizedGeojson = polygonize(geojson) as FeatureCollection<Polygon>;\n\n await this.conn.query(`DROP TABLE IF EXISTS ${qualifiedSurfaceTableName};`);\n await this.conn.query(`DROP TABLE IF EXISTS ${qualifiedFeatureCollectionTableName};`);\n\n const fileName = `temp_polygonized_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.json`;\n\n await this.db.registerFileText(fileName, JSON.stringify(polygonizedGeojson));\n\n const featureCollectionQuery = LOAD_FEATURE_COLLECTION_QUERY(fileName, `${surfaceTableName}_feature_collection`, workspace);\n await this.conn.query(featureCollectionQuery);\n\n const queryLayer = LOAD_POLYGONIZED_LAYER_QUERY(\n `${surfaceTableName}_feature_collection`,\n surfaceTableName,\n workspace,\n );\n\n const describeTableResponse = await this.conn.query(queryLayer);\n await this.db.dropFile(fileName);\n\n console.log('Loaded polygonized layer!');\n\n return {\n source: 'osm',\n type: 'surface',\n columns: getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray()),\n name: surfaceTableName,\n };\n }\n}\n"," \nimport { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { BuildHeatmapParams } from './interfaces';\nimport { BoundingBox, Table } from '../../../shared/interfaces';\nimport { LoadGridLayerUseCase } from '../load-grid-layer/LoadGridLayerUseCase';\nimport { SpatialJoinUseCase } from '../spatial-join/SpatialJoinUseCase';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\n\n/**\n * Builds a heatmap grid by spatially joining source data into grid cells.\n */\nexport class BuildHeatmapUseCase {\n private loadGridLayerUseCase: LoadGridLayerUseCase;\n private spatialJoinUseCase: SpatialJoinUseCase;\n\n constructor(private conn: AsyncDuckDBConnection) {\n this.loadGridLayerUseCase = new LoadGridLayerUseCase(conn);\n this.spatialJoinUseCase = new SpatialJoinUseCase(conn);\n }\n\n async exec(\n params: BuildHeatmapParams,\n tables: Array<Table>,\n boundingBox?: BoundingBox,\n ): Promise<Table> {\n if (!boundingBox) {\n throw new Error('Bounding box is required to build a heatmap.');\n }\n\n const sourceTable = tables.find((t) => t.name === params.tableJoinName);\n if (!sourceTable) {\n throw new Error(`Table ${params.tableJoinName} not found.`);\n }\n\n const gridTableName = params.outputTableName;\n const gridTable = await this.loadGridLayerUseCase.exec({\n boundingBox,\n rows: params.grid.rows,\n columns: params.grid.columns,\n outputTableName: gridTableName,\n });\n\n const joinResult = await this.spatialJoinUseCase.exec(\n {\n tableRootName: gridTableName,\n tableJoinName: params.tableJoinName,\n joinType: 'LEFT',\n spatialPredicate: 'NEAR',\n nearDistance: params.nearDistance,\n groupBy: params.groupBy,\n output: {\n type: 'MODIFY_ROOT',\n },\n },\n [...tables, gridTable],\n );\n\n await this.transformToRasterFormat(\n gridTableName,\n params.grid.rows,\n params.grid.columns\n );\n\n // Get updated columns after transformation\n const describeTableResponse = await this.conn.query(`DESCRIBE ${gridTableName}`);\n const updatedColumns = getColumnsFromDuckDbTableDescribe(describeTableResponse.toArray());\n\n return {\n ...joinResult.table,\n columns: updatedColumns,\n };\n }\n\n private async transformToRasterFormat(\n tableName: string,\n rows: number,\n columns: number\n ): Promise<void> {\n const transformQuery = `\n CREATE OR REPLACE TABLE ${tableName} AS\n SELECT \n ST_Point(0, 0) AS geometry,\n {\n 'raster': list(properties.sjoin ORDER BY CAST(properties->>'row' AS INTEGER), CAST(properties->>'column' AS INTEGER)),\n 'rasterResX': ${columns},\n 'rasterResY': ${rows}\n } AS properties\n FROM ${tableName};\n `;\n\n await this.conn.query(transformQuery);\n }\n}\n","import { AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { GetTableDataParams, GetTableDataOutput } from './interfaces';\nimport { toPlain } from '../../shared/utils';\n\n/**\n * Reads rows from any table as plain JavaScript objects.\n */\nexport class GetTableDataUseCase {\n private conn: AsyncDuckDBConnection;\n\n constructor(conn: AsyncDuckDBConnection) {\n this.conn = conn;\n }\n\n async exec(params: GetTableDataParams): Promise<GetTableDataOutput> {\n const workspace = params.workspace || 'main';\n const qualifiedTableName = `${workspace}.${params.tableName}`;\n let query = `SELECT * FROM ${qualifiedTableName}`;\n\n if (params.limit !== undefined) {\n query += ` LIMIT ${params.limit}`;\n }\n\n if (params.offset !== undefined) {\n query += ` OFFSET ${params.offset}`;\n }\n\n const result = await this.conn.query(query);\n return result.toArray().map((row) => toPlain(row.toJSON())) as GetTableDataOutput;\n }\n}\n\n","import { FeatureCollection } from 'geojson';\nimport { Table, Column } from '../../../shared/interfaces';\n\nexport type UpdateStrategy = 'replace' | 'update';\n\nexport interface UpdateTableParams {\n tableName: string;\n data: FeatureCollection | Record<string, unknown>[];\n /**\n * Strategy for updating the table:\n * - 'replace': Drop and recreate the entire table with the new data\n * - 'update': Update existing records by ID (does NOT insert new records)\n */\n strategy: UpdateStrategy;\n /**\n * Required when strategy is 'update'.\n * Supports:\n * - Direct column: 'id' → matches on the id column directly\n * - Nested in properties: 'properties.building_id' → matches on properties->>'building_id'\n */\n idColumn?: string;\n workspace?: string;\n}\n\nexport interface UpdateTableResult {\n table: Table;\n updatedColumns: Column[];\n}\n\n/**\n * Parses the idColumn parameter to determine if it's a direct column or nested in properties.\n * @param idColumn - The id column specification (e.g., 'id' or 'properties.building_id')\n * @returns An object with the column expression for SQL and whether it's in properties\n */\nexport function parseIdColumn(idColumn: string): { \n isPropertiesPath: boolean; \n columnName: string;\n sqlExpression: string;\n} {\n if (idColumn.startsWith('properties.')) {\n const propertyKey = idColumn.slice('properties.'.length);\n return {\n isPropertiesPath: true,\n columnName: propertyKey,\n sqlExpression: `properties->>'${propertyKey}'`,\n };\n }\n \n return {\n isPropertiesPath: false,\n columnName: idColumn,\n sqlExpression: idColumn,\n };\n}\n","/**\n * Query to create a temporary table from a GeoJSON file for layer updates.\n * Transforms GeoJSON features into the internal layer format (geometry + properties).\n */\nexport const REPLACE_LAYER_TABLE_QUERY = (\n tempFileName: string,\n tableName: string,\n workspace: string,\n) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n \n return `\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT\n ST_GeomFromGeoJSON(JSON(feature.geometry)) AS geometry,\n CAST(feature.properties AS JSON) AS properties\n FROM (\n SELECT UNNEST(features) AS feature\n FROM read_json_auto('${tempFileName}')\n );\n \n DESCRIBE ${qualifiedTableName};\n `;\n};\n\n/**\n * Query to replace a non-layer table (CSV/JSON) with new data.\n * Data is inserted directly without geometry transformation.\n */\nexport const REPLACE_DATA_TABLE_QUERY = (\n tempFileName: string,\n tableName: string,\n workspace: string,\n) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n \n return `\n CREATE OR REPLACE TABLE ${qualifiedTableName} AS\n SELECT * FROM read_json_auto('${tempFileName}');\n \n DESCRIBE ${qualifiedTableName};\n `;\n};\n\n/**\n * Query to load GeoJSON features into a temporary staging table for upsert operations.\n */\nexport const CREATE_LAYER_STAGING_TABLE_QUERY = (\n tempFileName: string,\n stagingTableName: string,\n) => {\n return `\n CREATE OR REPLACE TEMP TABLE ${stagingTableName} AS\n SELECT\n ST_GeomFromGeoJSON(JSON(feature.geometry)) AS geometry,\n CAST(feature.properties AS JSON) AS properties\n FROM (\n SELECT UNNEST(features) AS feature\n FROM read_json_auto('${tempFileName}')\n );\n `;\n};\n\n/**\n * Query to load JSON array into a temporary staging table for upsert operations.\n */\nexport const CREATE_DATA_STAGING_TABLE_QUERY = (\n tempFileName: string,\n stagingTableName: string,\n) => {\n return `\n CREATE OR REPLACE TEMP TABLE ${stagingTableName} AS\n SELECT * FROM read_json_auto('${tempFileName}');\n `;\n};\n\n/**\n * Query to update existing layer records (geometry and properties) based on ID match.\n * Used for upsert operations on layer tables.\n */\nexport const UPDATE_LAYER_FROM_STAGING_QUERY = (\n tableName: string,\n stagingTableName: string,\n idSqlExpression: string,\n workspace: string,\n) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n \n // Use explicit column references without table alias for the JSON expression\n // to avoid syntax issues with DuckDB's JSON operators\n return `\n UPDATE ${qualifiedTableName}\n SET \n geometry = staging.geometry,\n properties = staging.properties\n FROM ${stagingTableName} AS staging\n WHERE ${qualifiedTableName}.${idSqlExpression} = staging.${idSqlExpression};\n `;\n};\n\n/**\n * Query to delete matching records from target table based on IDs in staging table.\n */\nexport const DELETE_MATCHING_IDS_QUERY = (\n tableName: string,\n stagingTableName: string,\n idSqlExpression: string,\n workspace: string,\n) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n \n return `\n DELETE FROM ${qualifiedTableName}\n WHERE ${idSqlExpression} IN (\n SELECT ${idSqlExpression} FROM ${stagingTableName}\n );\n `;\n};\n\n/**\n * Query to insert all records from staging table into target table.\n * Only works when staging table has same columns as target table.\n */\nexport const INSERT_FROM_STAGING_QUERY = (\n tableName: string,\n stagingTableName: string,\n workspace: string,\n) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n \n return `\n INSERT INTO ${qualifiedTableName}\n SELECT * FROM ${stagingTableName};\n `;\n};\n\n/**\n * Query to insert layer records (geometry, properties) from staging into target.\n * Used for inserting new records that don't exist in target.\n */\nexport const INSERT_LAYER_FROM_STAGING_QUERY = (\n tableName: string,\n stagingTableName: string,\n idSqlExpression: string,\n workspace: string,\n) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n \n return `\n INSERT INTO ${qualifiedTableName} (geometry, properties)\n SELECT staging.geometry, staging.properties\n FROM ${stagingTableName} AS staging\n WHERE NOT EXISTS (\n SELECT 1 FROM ${qualifiedTableName} AS target\n WHERE target.${idSqlExpression} = staging.${idSqlExpression}\n );\n `;\n};\n\n/**\n * Query to drop the staging table after upsert operation.\n */\nexport const DROP_STAGING_TABLE_QUERY = (stagingTableName: string) => {\n return `DROP TABLE IF EXISTS ${stagingTableName};`;\n};\n\n/**\n * Query to describe a table and get its column information.\n */\nexport const DESCRIBE_TABLE_QUERY = (tableName: string, workspace: string) => {\n const qualifiedTableName = `${workspace}.${tableName}`;\n return `DESCRIBE ${qualifiedTableName};`;\n};\n","import { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\nimport { FeatureCollection } from 'geojson';\n\nimport { Table } from '../../../shared/interfaces';\nimport { UpdateTableParams, UpdateTableResult, parseIdColumn } from './interfaces';\nimport { getColumnsFromDuckDbTableDescribe } from '../../shared/utils';\nimport {\n REPLACE_LAYER_TABLE_QUERY,\n REPLACE_DATA_TABLE_QUERY,\n CREATE_LAYER_STAGING_TABLE_QUERY,\n CREATE_DATA_STAGING_TABLE_QUERY,\n DELETE_MATCHING_IDS_QUERY,\n INSERT_FROM_STAGING_QUERY,\n UPDATE_LAYER_FROM_STAGING_QUERY,\n DROP_STAGING_TABLE_QUERY,\n DESCRIBE_TABLE_QUERY,\n} from './queries';\n\n/**\n * Updates an existing table with new data, supporting replace and update-by-id strategies.\n */\nexport class UpdateTableUseCase {\n private db: AsyncDuckDB;\n private conn: AsyncDuckDBConnection;\n\n constructor(db: AsyncDuckDB, conn: AsyncDuckDBConnection) {\n this.db = db;\n this.conn = conn;\n }\n\n async exec(params: UpdateTableParams, existingTable: Table): Promise<UpdateTableResult> {\n const { strategy, workspace = 'main' } = params;\n\n if (strategy === 'update' && !params.idColumn) {\n throw new Error('idColumn is required when using the update strategy');\n }\n\n const isLayerTable = this.isLayerTable(existingTable);\n\n if (strategy === 'replace') {\n return this.executeReplaceStrategy(params, existingTable, isLayerTable, workspace);\n } else {\n return this.executeUpdateStrategy(params, existingTable, isLayerTable, workspace);\n }\n }\n\n /**\n * Determines if a table is a layer table (has geometry) based on its source.\n */\n private isLayerTable(table: Table): boolean {\n return table.source === 'osm' || table.source === 'geojson';\n }\n\n /**\n * Validates that the input data format matches the table type.\n */\n private validateDataFormat(data: FeatureCollection | Record<string, unknown>[], isLayerTable: boolean): void {\n if (isLayerTable) {\n if (!this.isFeatureCollection(data)) {\n throw new Error('Layer tables require a GeoJSON FeatureCollection as input data');\n }\n } else {\n if (this.isFeatureCollection(data)) {\n throw new Error('Non-layer tables (CSV/JSON) require an array of objects as input data');\n }\n }\n }\n\n /**\n * Type guard to check if data is a FeatureCollection.\n */\n private isFeatureCollection(data: unknown): data is FeatureCollection {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'type' in data &&\n (data as FeatureCollection).type === 'FeatureCollection' &&\n 'features' in data &&\n Array.isArray((data as FeatureCollection).features)\n );\n }\n\n /**\n * Creates a temporary file with the data and returns the file name.\n */\n private async createTempFile(data: FeatureCollection | Record<string, unknown>[]): Promise<string> {\n const fileName = `temp_update_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.json`;\n await this.db.registerFileText(fileName, JSON.stringify(data));\n return fileName;\n }\n\n /**\n * Cleans up the temporary file.\n */\n private async cleanupTempFile(fileName: string): Promise<void> {\n try {\n await this.db.dropFile(fileName);\n } catch {\n // Ignore errors during cleanup\n }\n }\n\n /**\n * Executes the replace strategy: drop and recreate the table with new data.\n */\n private async executeReplaceStrategy(\n params: UpdateTableParams,\n existingTable: Table,\n isLayerTable: boolean,\n workspace: string,\n ): Promise<UpdateTableResult> {\n const { tableName, data } = params;\n\n this.validateDataFormat(data, isLayerTable);\n\n const tempFileName = await this.createTempFile(data);\n\n try {\n let query: string;\n if (isLayerTable) {\n query = REPLACE_LAYER_TABLE_QUERY(tempFileName, tableName, workspace);\n } else {\n query = REPLACE_DATA_TABLE_QUERY(tempFileName, tableName, workspace);\n }\n\n const describeResult = await this.conn.query(query);\n const updatedColumns = getColumnsFromDuckDbTableDescribe(describeResult.toArray());\n\n const updatedTable: Table = {\n ...existingTable,\n columns: updatedColumns,\n };\n\n return {\n table: updatedTable,\n updatedColumns,\n };\n } finally {\n await this.cleanupTempFile(tempFileName);\n }\n }\n\n /**\n * Executes the update strategy: update existing records by ID.\n * Does NOT insert new records - only modifies records that already exist.\n */\n private async executeUpdateStrategy(\n params: UpdateTableParams,\n existingTable: Table,\n isLayerTable: boolean,\n workspace: string,\n ): Promise<UpdateTableResult> {\n const { tableName, data, idColumn } = params;\n\n this.validateDataFormat(data, isLayerTable);\n\n const { sqlExpression } = parseIdColumn(idColumn!);\n const stagingTableName = `_staging_${tableName}_${Date.now()}`;\n const tempFileName = await this.createTempFile(data);\n\n try {\n // 1. Create staging table with transformed data\n let createStagingQuery: string;\n if (isLayerTable) {\n createStagingQuery = CREATE_LAYER_STAGING_TABLE_QUERY(tempFileName, stagingTableName);\n } else {\n createStagingQuery = CREATE_DATA_STAGING_TABLE_QUERY(tempFileName, stagingTableName);\n }\n await this.conn.query(createStagingQuery);\n\n if (isLayerTable) {\n // For layer tables: UPDATE existing records only\n // We can't INSERT new records because OSM layers require columns (id, refs)\n // that we don't have in the GeoJSON data\n const updateQuery = UPDATE_LAYER_FROM_STAGING_QUERY(tableName, stagingTableName, sqlExpression, workspace);\n await this.conn.query(updateQuery);\n } else {\n // For non-layer tables: DELETE + INSERT (full row replacement)\n \n // 2. Delete matching records from target table\n const deleteQuery = DELETE_MATCHING_IDS_QUERY(tableName, stagingTableName, sqlExpression, workspace);\n await this.conn.query(deleteQuery);\n\n // 3. Insert all records from staging table\n const insertQuery = INSERT_FROM_STAGING_QUERY(tableName, stagingTableName, workspace);\n await this.conn.query(insertQuery);\n }\n\n // 4. Clean up staging table\n const dropStagingQuery = DROP_STAGING_TABLE_QUERY(stagingTableName);\n await this.conn.query(dropStagingQuery);\n\n // 5. Get updated column information\n const describeQuery = DESCRIBE_TABLE_QUERY(tableName, workspace);\n const describeResult = await this.conn.query(describeQuery);\n const updatedColumns = getColumnsFromDuckDbTableDescribe(describeResult.toArray());\n\n const updatedTable: Table = {\n ...existingTable,\n columns: updatedColumns,\n };\n\n return {\n table: updatedTable,\n updatedColumns,\n };\n } finally {\n await this.cleanupTempFile(tempFileName);\n // Ensure staging table is dropped even on error\n try {\n await this.conn.query(DROP_STAGING_TABLE_QUERY(stagingTableName));\n } catch {\n // Ignore errors during cleanup\n }\n }\n }\n}\n"," \nimport { AsyncDuckDB, AsyncDuckDBConnection } from '@duckdb/duckdb-wasm';\n\nimport { CsvTable, CustomLayerTable, LayerTable, JsonTable, Table } from '../shared/interfaces';\nimport { loadDb } from '../config/duckdb';\nimport { LoadLayerUseCase, LoadLayerParams } from './use-cases/load-layer';\nimport { LoadCsvUseCase, LoadCsvParams } from './use-cases/load-csv';\nimport { LoadJsonUseCase, LoadJsonParams } from './use-cases/load-json';\nimport { GetLayerGeojsonUseCase } from './use-cases/get-layer-geojson';\nimport { FeatureCollection } from 'geojson';\nimport { isLayerType } from 'autk-core';\nimport { LoadCustomLayerParams, LoadCustomLayerUseCase } from './use-cases/load-custom-layer';\nimport { AssignBuildingIdsUseCase } from './use-cases/assign-building-ids/AssignBuildingIdsUseCase';\nimport { SpatialQueryParams } from './use-cases/spatial-join/interfaces';\nimport { SpatialJoinUseCase } from './use-cases/spatial-join/SpatialJoinUseCase';\nimport { DropTableUseCase } from './shared/use-cases/drop-table/DropTableUseCase';\nimport { BoundingBox } from '../shared/interfaces';\nimport { TransformBoundingBoxCoordinatesUseCase } from './shared/use-cases/transform-bounding-box-coordinates/TransformBoundingBoxCoordinatesUseCase';\nimport { GetBoundingBoxFromLayerUseCase } from './shared/use-cases/get-bounding-box-from-layer/GetBoundingBoxFromLayerUseCase';\nimport { LoadOsmParams, LoadOsmFromOverpassApiUseCase } from './use-cases/load-osm-from-overpass-api';\nimport { LoadOsmFromPbfUseCase } from './use-cases/load-osm-from-pbf';\nimport { OsmProcessingPipeline } from './use-cases/osm-processing-pipeline/OsmProcessingPipeline';\nimport type { OsmLoadTimings } from './use-cases/load-osm-from-overpass-api/interfaces';\nimport { LoadGridLayerParams, LoadGridLayerUseCase } from './use-cases/load-grid-layer/LoadGridLayerUseCase';\nimport { GridLayerTable, GeoTiffTable } from '../shared/interfaces';\nimport { LoadGeoTiffUseCase, LoadGeoTiffParams } from './use-cases/load-geotiff';\nimport { RawQueryOutput, RawQueryParams } from './use-cases/raw-query/interfaces';\nimport { RawQueryUseCase } from './use-cases/raw-query';\nimport { GetBoundingBoxFromOsmUseCase } from './shared/use-cases/get-bounding-box-from-osm/GetBoundingBoxFromOsmUseCase';\nimport { PolygonizeSurfaceLayerUseCase } from './use-cases/polygonize-surface-layer';\nimport { BuildHeatmapParams, BuildHeatmapUseCase } from './use-cases/build-heatmap';\nimport { GetTableDataParams, GetTableDataOutput, GetTableDataUseCase } from './use-cases/get-table-data';\nimport { UpdateTableUseCase, UpdateTableParams } from './use-cases/update-table';\nimport { toPlain } from './shared/utils';\n\ninterface WorkspaceData {\n tables: Array<Table>;\n osmBoundingBox?: BoundingBox;\n osmBoundingBoxWgs84?: BoundingBox;\n}\n\n/**\n * SpatialDb class provides methods to interact with a DuckDB database for spatial data operations.\n *\n * It allows loading OSM data, CSV, JSON, custom layers, and grid layers,\n * as well as performing spatial joins and raw queries.\n * DuckDB-backed spatial database for OSM, CSV, JSON, and raster data.\n *\n * Supports multiple isolated workspaces, each with its own schema and tables.\n *\n * @example\n * const db = new AutkSpatialDb();\n * await db.init();\n * const layer = await db.getLayer('osm_buildings');\n */\nexport class AutkSpatialDb {\n private db?: AsyncDuckDB;\n private conn?: AsyncDuckDBConnection;\n private currentWorkspace: string = 'main';\n private workspaces: Map<string, WorkspaceData> = new Map();\n \n public get tables(): Array<Table> {\n return this.getCurrentWorkspaceData().tables;\n }\n \n private osmProcessingPipeline?: OsmProcessingPipeline;\n private loadOsmFromOverpassApiUseCase?: LoadOsmFromOverpassApiUseCase;\n private loadOsmFromPbfUseCase?: LoadOsmFromPbfUseCase;\n private loadCsvUseCase?: LoadCsvUseCase;\n private loadLayerUseCase?: LoadLayerUseCase;\n private loadCustomLayerUseCase?: LoadCustomLayerUseCase;\n private assignBuildingIdsUseCase?: AssignBuildingIdsUseCase;\n private loadJsonUseCase?: LoadJsonUseCase;\n private getLayerGeojsonUseCase?: GetLayerGeojsonUseCase;\n private spatialJoinUseCase?: SpatialJoinUseCase;\n private getBoundingBoxFromLayerUseCase?: GetBoundingBoxFromLayerUseCase;\n private dropTableUseCase?: DropTableUseCase;\n private transformBoundingBoxCoordinatesUseCase?: TransformBoundingBoxCoordinatesUseCase;\n private loadGridLayerUseCase?: LoadGridLayerUseCase;\n private loadGeoTiffUseCase?: LoadGeoTiffUseCase;\n private rawQueryUseCase?: RawQueryUseCase;\n private getBoundingBoxFromOsmUseCase?: GetBoundingBoxFromOsmUseCase;\n private polygonizeSurfaceLayerUseCase?: PolygonizeSurfaceLayerUseCase;\n private buildHeatmapUseCase?: BuildHeatmapUseCase;\n private getTableDataUseCase?: GetTableDataUseCase;\n private updateTableUseCase?: UpdateTableUseCase;\n\n /**\n * Gets the workspace data for the current workspace.\n * @returns The WorkspaceData for the current workspace.\n * @private\n */\n private getCurrentWorkspaceData(): WorkspaceData {\n const data = this.workspaces.get(this.currentWorkspace);\n if (!data) {\n throw new Error(`Workspace '${this.currentWorkspace}' not found. This should not happen.`);\n }\n return data;\n }\n\n /**\n * Initializes DuckDB, loads the spatial extension, and creates use-case instances.\n *\n * @returns A promise that resolves when initialization is complete.\n * @throws If DuckDB WebAssembly fails to load or the spatial extension cannot be installed.\n * @example\n * await db.init();\n */\n async init() {\n this.db = await loadDb();\n this.conn = await this.db.connect();\n\n // Install and load spatial extension\n await this.conn.query('INSTALL spatial; LOAD spatial;');\n\n // Create main schema and initialize default workspace\n await this.conn.query('CREATE SCHEMA IF NOT EXISTS main');\n this.workspaces.set('main', {\n tables: [],\n osmBoundingBox: undefined,\n });\n\n this.osmProcessingPipeline = new OsmProcessingPipeline(this.db, this.conn);\n this.loadOsmFromOverpassApiUseCase = new LoadOsmFromOverpassApiUseCase(this.conn, this.osmProcessingPipeline);\n this.loadOsmFromPbfUseCase = new LoadOsmFromPbfUseCase(this.conn, this.osmProcessingPipeline);\n this.loadCsvUseCase = new LoadCsvUseCase(this.db, this.conn);\n this.loadJsonUseCase = new LoadJsonUseCase(this.db, this.conn);\n this.loadLayerUseCase = new LoadLayerUseCase(this.db, this.conn);\n this.loadCustomLayerUseCase = new LoadCustomLayerUseCase(this.db, this.conn);\n this.assignBuildingIdsUseCase = new AssignBuildingIdsUseCase(this.db, this.conn);\n this.getLayerGeojsonUseCase = new GetLayerGeojsonUseCase(this.conn);\n this.spatialJoinUseCase = new SpatialJoinUseCase(this.conn);\n this.getBoundingBoxFromLayerUseCase = new GetBoundingBoxFromLayerUseCase(this.conn);\n this.dropTableUseCase = new DropTableUseCase(this.conn);\n this.transformBoundingBoxCoordinatesUseCase = new TransformBoundingBoxCoordinatesUseCase(this.conn);\n this.loadGridLayerUseCase = new LoadGridLayerUseCase(this.conn);\n this.loadGeoTiffUseCase = new LoadGeoTiffUseCase(this.db, this.conn);\n this.rawQueryUseCase = new RawQueryUseCase(this.conn);\n this.getBoundingBoxFromOsmUseCase = new GetBoundingBoxFromOsmUseCase(this.conn);\n this.polygonizeSurfaceLayerUseCase = new PolygonizeSurfaceLayerUseCase(this.db, this.conn);\n this.buildHeatmapUseCase = new BuildHeatmapUseCase(this.conn);\n this.getTableDataUseCase = new GetTableDataUseCase(this.conn);\n this.updateTableUseCase = new UpdateTableUseCase(this.db, this.conn);\n }\n\n /**\n * Switches to a workspace, creating it if it doesn't exist.\n *\n * @param name The name of the workspace to switch to.\n * @returns A promise that resolves when the workspace is set.\n * @throws If the database has not been initialized.\n */\n async setWorkspace(name: string): Promise<void> {\n if (!this.conn) {\n throw new Error('Database not initialized. Please call init() first.');\n }\n\n if (!this.workspaces.has(name)) {\n await this.conn.query(`CREATE SCHEMA IF NOT EXISTS ${name}`);\n this.workspaces.set(name, {\n tables: [],\n osmBoundingBox: undefined,\n });\n }\n\n this.currentWorkspace = name;\n }\n\n /**\n * Gets the list of all available workspaces.\n * @returns An array of workspace names.\n */\n getWorkspaces(): string[] {\n return Array.from(this.workspaces.keys());\n }\n\n /**\n * Gets the name of the current active workspace.\n * @returns The current workspace name.\n */\n getCurrentWorkspace(): string {\n return this.currentWorkspace;\n }\n\n /**\n * Registers a table in the current workspace's tables array. If a table with the same name already exists,\n * it will be replaced and a warning will be logged to the console.\n * @param table - The table to register.\n */\n private _registerTable(table: Table): void {\n const workspaceData = this.getCurrentWorkspaceData();\n const existingIndex = workspaceData.tables.findIndex((t) => t.name === table.name);\n \n if (existingIndex !== -1) {\n console.warn(`Table '${table.name}' already exists in workspace '${this.currentWorkspace}'. Overwriting...`);\n workspaceData.tables[existingIndex] = table;\n } else {\n workspaceData.tables.push(table);\n }\n }\n\n // ---- LOAD's methods\n\n private async clipLayerToSurface(\n layerTableName: string,\n surfaceTableName: string,\n workspace: string,\n cropGeometry: boolean = true,\n ): Promise<void> {\n const qualifiedLayer = `${workspace}.${layerTableName}`;\n const qualifiedSurface = `${workspace}.${surfaceTableName}`;\n const geometrySelect = cropGeometry ? 'ST_Intersection(l.geometry, surf.geom)' : 'l.geometry';\n const emptyFilter = cropGeometry ? 'WHERE NOT ST_IsEmpty(geometry)' : '';\n\n await this.conn!.query(`\n CREATE OR REPLACE TABLE ${qualifiedLayer} AS\n WITH surf AS (\n SELECT ST_Union_Agg(geometry) AS geom FROM ${qualifiedSurface}\n ),\n clipped AS (\n SELECT l.* EXCLUDE (geometry),\n ${geometrySelect} AS geometry\n FROM ${qualifiedLayer} l, surf\n WHERE ST_Intersects(l.geometry, surf.geom)\n )\n SELECT * FROM clipped\n ${emptyFilter};\n `);\n }\n\n /**\n * Loads OSM data from the Overpass API and optionally loads layers based on the provided parameters.\n * When autoLoadLayers is enabled, this method will automatically extract and process specific layers\n * (e.g., buildings, roads, surface) from the OSM data, and optionally polygonize the surface layer.\n *\n * @param params - Parameters for loading OSM data and layers.\n * @returns A promise that resolves when the OSM data and layers are fully loaded.\n * @throws Error if the database or connection is not initialized.\n */\n async loadOsm(params: LoadOsmParams): Promise<OsmLoadTimings> {\n if (\n !this.db ||\n !this.conn ||\n !this.loadOsmFromOverpassApiUseCase ||\n !this.loadOsmFromPbfUseCase ||\n !this.dropTableUseCase ||\n !this.getBoundingBoxFromOsmUseCase ||\n !this.transformBoundingBoxCoordinatesUseCase ||\n !this.polygonizeSurfaceLayerUseCase\n )\n throw new Error('Database not initialized. Please call init() first.');\n\n const execResult = params.pbfFileUrl\n ? await this.loadOsmFromPbfUseCase.exec({ ...params, workspace: this.currentWorkspace })\n : await this.loadOsmFromOverpassApiUseCase.exec({ ...params, workspace: this.currentWorkspace });\n for (const table of execResult.tables) {\n this._registerTable(table);\n }\n\n const timings: OsmLoadTimings = {\n osmElementCount: execResult.osmElementCount,\n boundaryElementCount: execResult.boundaryElementCount,\n osmDataProcessingMs: execResult.osmDataProcessingMs,\n boundariesProcessingMs: execResult.boundariesProcessingMs,\n layers: [],\n };\n\n if (params.autoLoadLayers) {\n const boundaryTableName = `${params.outputTableName}_boundaries`;\n const rawBoundingBox = await this.getBoundingBoxFromOsmUseCase.exec({\n osmTableName: boundaryTableName,\n workspace: this.currentWorkspace\n });\n\n const workspaceData = this.getCurrentWorkspaceData();\n workspaceData.osmBoundingBoxWgs84 = rawBoundingBox;\n workspaceData.osmBoundingBox = await this.transformBoundingBoxCoordinatesUseCase.exec({\n boundingBox: rawBoundingBox,\n coordinateFormat: params.autoLoadLayers.coordinateFormat,\n });\n\n let surfaceLayerName: string | null = null;\n const clippableLayerNames: string[] = [];\n\n for (const layer of params.autoLoadLayers.layers) {\n const shouldCropToBbox = layer !== 'buildings';\n\n const layerParams: LoadLayerParams = {\n osmInputTableName: params.outputTableName,\n coordinateFormat: params.autoLoadLayers.coordinateFormat,\n layer,\n };\n\n layerParams.boundingBox = shouldCropToBbox ? workspaceData.osmBoundingBox : undefined;\n\n const t0 = performance.now();\n const layerTable = await this.loadLayer(layerParams);\n const loadMs = performance.now() - t0;\n\n const countResult = await this.conn.query(\n `SELECT COUNT(*) as cnt FROM ${this.currentWorkspace}.${layerTable.name}`\n );\n const featureCount = Number(countResult.toArray()[0].cnt);\n\n timings.layers.push({ layerName: layerTable.name, layerType: layer, loadMs, featureCount });\n\n // Polygonize surface layer\n if (layer === 'surface') {\n const updatedTable = await this.polygonizeSurfaceLayerUseCase.exec(\n { surfaceTableName: layerTable.name, workspace: this.currentWorkspace },\n layerTable\n );\n const tableIndex = workspaceData.tables.findIndex((t) => t.name === layerTable.name);\n if (tableIndex !== -1) workspaceData.tables[tableIndex] = updatedTable;\n surfaceLayerName = layerTable.name;\n } else {\n clippableLayerNames.push(layerTable.name);\n }\n }\n\n // Clip thematic layers to the surface polygon. Buildings are only filtered by overlap.\n if (surfaceLayerName && clippableLayerNames.length > 0) {\n for (const layerName of clippableLayerNames) {\n const cropGeometry = !layerName.endsWith('_buildings');\n await this.clipLayerToSurface(layerName, surfaceLayerName, this.currentWorkspace, cropGeometry);\n }\n }\n\n if (params.autoLoadLayers.dropOsmTable) {\n for (const table of execResult.tables) {\n await this.dropTableUseCase.exec({ tableName: table.name, workspace: this.currentWorkspace });\n workspaceData.tables = workspaceData.tables.filter((t) => t.name !== table.name);\n }\n }\n\n console.log(`OSM data loaded and completed in workspace '${this.currentWorkspace}'!`);\n }\n\n return timings;\n }\n\n /**\n * Loads a CSV file into the database and returns the created CsvTable.\n * @param params - Parameters for loading the CSV file, including file path and table name.\n * @returns A promise that resolves to the created CsvTable.\n * @throws Error if the database or connection is not initialized.\n */\n async loadCsv(params: LoadCsvParams): Promise<CsvTable> {\n if (!this.db || !this.conn || !this.loadCsvUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const table = await this.loadCsvUseCase.exec({ ...params, workspace: this.currentWorkspace });\n this._registerTable(table);\n\n return table;\n }\n\n /**\n * Loads a JSON file into the database and returns the created JsonTable.\n * @param params - Parameters for loading the JSON file, including file path and table name.\n * @returns A promise that resolves to the created JsonTable.\n * @throws Error if the database or connection is not initialized.\n */\n async loadJson(params: LoadJsonParams): Promise<JsonTable> {\n if (!this.db || !this.conn || !this.loadJsonUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const table = await this.loadJsonUseCase.exec({ ...params, workspace: this.currentWorkspace });\n this._registerTable(table);\n\n return table;\n }\n\n /**\n * Loads a layer from an OSM input table and returns the created LayerTable.\n * @param params - Parameters for loading the layer.\n * @returns A promise that resolves to the created LayerTable.\n * @throws Error if the database or connection is not initialized.\n * @throws Error if the OSM input table is not found or is not of the correct type.\n */\n async loadLayer(params: LoadLayerParams): Promise<LayerTable> {\n if (!this.db || !this.conn || !this.loadLayerUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const osmTable = this.tables.find((t) => t.name === params.osmInputTableName);\n if (!osmTable) throw new Error(`Table ${params.osmInputTableName} not found.`);\n if (!(osmTable.source === 'osm' && osmTable.type === 'pointset'))\n throw new Error(`Table ${params.osmInputTableName} is not an OSM table.`);\n\n const table = await this.loadLayerUseCase.exec({ ...params, workspace: this.currentWorkspace });\n this._registerTable(table);\n\n return table;\n }\n\n /**\n * Loads a custom layer from a GeoJSON file and returns the created CustomLayerTable.\n * If OSM bounding box is available, it will be automatically applied to crop the layer.\n * @param params - Parameters for loading the custom layer, including file path, table name, and layer type.\n * @returns A promise that resolves to the created CustomLayerTable.\n * @throws Error if the database or connection is not initialized.\n */\n async loadCustomLayer(params: LoadCustomLayerParams): Promise<CustomLayerTable> {\n if (!this.db || !this.conn || !this.loadCustomLayerUseCase || !this.assignBuildingIdsUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const workspaceData = this.getCurrentWorkspaceData();\n const table = await this.loadCustomLayerUseCase.exec({ \n ...params, \n boundingBox: workspaceData.osmBoundingBox,\n workspace: this.currentWorkspace \n });\n this._registerTable(table);\n\n // When loading as buildings, compute building_id by clustering overlapping geometries\n if (params.layerType === 'buildings') {\n const columns = await this.assignBuildingIdsUseCase.exec({\n tableName: table.name,\n workspace: this.currentWorkspace,\n });\n table.columns = columns;\n }\n\n return table;\n }\n\n /**\n * Loads a grid layer and returns the created GridLayerTable.\n * If no bounding box is provided in params, the OSM bounding box will be used if available.\n * @param params - Parameters for loading the grid layer, including grid size, cell size, and optional bounding box.\n * @returns A promise that resolves to the created GridLayerTable.\n * @throws Error if the database or connection is not initialized.\n */\n async loadGridLayer(params: LoadGridLayerParams): Promise<GridLayerTable> {\n if (!this.db || !this.conn || !this.loadGridLayerUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const workspaceData = this.getCurrentWorkspaceData();\n const table = await this.loadGridLayerUseCase.exec({\n ...params,\n boundingBox: params.boundingBox || workspaceData.osmBoundingBox,\n workspace: this.currentWorkspace\n });\n this._registerTable(table);\n\n return table;\n }\n\n /**\n * Loads a GeoTIFF raster file into the database.\n * Uses DuckDB's spatial extension (GDAL-backed ST_Read) to parse the file.\n * The resulting table has a `geometry` column (cell centroids) and a\n * `properties` struct column containing one field per raster band.\n * @param params - Parameters including the file URL or ArrayBuffer, output table name,\n * and optional coordinate transformation settings.\n * @returns A promise that resolves to the created GeoTiffTable.\n */\n async loadGeoTiff(params: LoadGeoTiffParams): Promise<GeoTiffTable> {\n if (!this.db || !this.conn || !this.loadGeoTiffUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const table = await this.loadGeoTiffUseCase.exec({\n ...params,\n workspace: this.currentWorkspace,\n });\n this._registerTable(table);\n\n return table;\n }\n\n /**\n * Retrieves a loaded GeoTIFF table as a FeatureCollection suitable for rendering with autk-map.\n *\n * The returned collection has a single feature whose `properties.raster` is an array of per-pixel\n * property objects (one per cell, in row-major top-to-bottom order), plus `rasterResX` / `rasterResY`\n * dimensions and a `bbox`.\n *\n * Pass the result directly to `AutkMap.loadRasterCollection()` and supply a `property` callback that\n * extracts the numeric band value you want to visualise, e.g. `(cell) => cell.band_1 ?? 0`.\n *\n * @param tableName - The name of the GeoTiff table (as given to `loadGeoTiff`).\n * @returns A promise that resolves to a packed raster FeatureCollection.\n */\n async getGeoTiffLayer(tableName: string): Promise<FeatureCollection<null>> {\n if (!this.db || !this.conn)\n throw new Error('Database not initialized. Please call init() first.');\n\n const table = this.tables.find((t) => t.name === tableName);\n if (!table || table.source !== 'geotiff')\n throw new Error(`Table ${tableName} is not a GeoTiff table.`);\n\n const qualifiedName = `${this.currentWorkspace}.${tableName}`;\n\n const result = await this.conn.query(`\n WITH pixels AS (\n SELECT\n t.properties AS properties,\n ST_X(t.geometry) AS px,\n ST_Y(t.geometry) AS py\n FROM ${qualifiedName} t\n )\n SELECT\n COUNT(DISTINCT ROUND(px, 8))::INTEGER AS res_x,\n COUNT(DISTINCT ROUND(py, 8))::INTEGER AS res_y,\n MIN(px) AS min_lon,\n MIN(py) AS min_lat,\n MAX(px) AS max_lon,\n MAX(py) AS max_lat,\n list(properties ORDER BY py ASC, px ASC) AS raster\n FROM pixels\n `);\n\n const row = toPlain(result.toArray()[0]?.toJSON());\n if (!row) throw new Error(`No data found in GeoTiff table ${tableName}.`);\n\n const { res_x, res_y, min_lon, min_lat, max_lon, max_lat, raster } = row;\n\n // Expand bbox by half a pixel on each side so single-column/row rasters don't collapse to zero width/height.\n const spacingX = Number(res_x) > 1 ? Math.abs((Number(max_lon) - Number(min_lon)) / (Number(res_x) - 1)) : null;\n const spacingY = Number(res_y) > 1 ? Math.abs((Number(max_lat) - Number(min_lat)) / (Number(res_y) - 1)) : null;\n const halfX = (spacingX ?? spacingY ?? 0) / 2;\n const halfY = (spacingY ?? spacingX ?? 0) / 2;\n\n return {\n type: 'FeatureCollection',\n bbox: [Number(min_lon) - halfX, Number(min_lat) - halfY, Number(max_lon) + halfX, Number(max_lat) + halfY],\n features: [\n {\n type: 'Feature',\n geometry: null,\n properties: {\n rasterResX: res_x,\n rasterResY: res_y,\n raster,\n },\n },\n ],\n };\n }\n\n // GETTER'S\n\n /**\n * Retrieves the GeoJSON representation of a layer by its table name.\n * The returned FeatureCollection will include a bbox property with the layer's bounding box.\n * @param layerTableName - The name of the layer table to retrieve.\n * @returns A promise that resolves to the GeoJSON FeatureCollection of the layer with bbox.\n * @throws Error if the database or connection is not initialized.\n * @throws Error if the layer table is not found or is not a Layer table.\n */\n async getLayer(layerTableName: string): Promise<FeatureCollection> {\n if (!this.db || !this.conn || !this.getLayerGeojsonUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const layerTable = this.tables.find((t) => t.name === layerTableName);\n if (!layerTable) throw new Error(`Table ${layerTableName} not found.`);\n if (!isLayerType(layerTable.type)) throw new Error(`Table ${layerTableName} is not a Layer table.`);\n\n const featureCollection = await this.getLayerGeojsonUseCase.exec(layerTable as LayerTable | CustomLayerTable, this.currentWorkspace);\n\n const osmBoundingBox = this.getOsmBoundingBox();\n if (osmBoundingBox) {\n featureCollection.bbox = osmBoundingBox;\n } else {\n const layerBoundingBox = await this.getBoundingBoxFromLayer(layerTableName);\n featureCollection.bbox = [\n layerBoundingBox.minLon,\n layerBoundingBox.minLat,\n layerBoundingBox.maxLon,\n layerBoundingBox.maxLat,\n ];\n }\n\n return featureCollection;\n }\n\n /**\n * Retrieves the OSM bounding box for the current workspace.\n *\n * @returns The bounding box as `[minLon, minLat, maxLon, maxLat]`, or `null` if no OSM data has been loaded.\n * @throws Never throws.\n */\n getOsmBoundingBox(): [number, number, number, number] | null {\n const workspaceData = this.getCurrentWorkspaceData();\n if (!workspaceData.osmBoundingBox) return null;\n\n return [\n workspaceData.osmBoundingBox.minLon,\n workspaceData.osmBoundingBox.minLat,\n workspaceData.osmBoundingBox.maxLon,\n workspaceData.osmBoundingBox.maxLat,\n ]\n }\n\n /**\n * Returns the OSM bounding box in WGS84 (EPSG:4326) for clipping rasters.\n *\n * @returns The bounding box or `null` if no OSM data has been loaded.\n * @throws Never throws.\n */\n getOsmBoundingBoxWgs84(): BoundingBox | null {\n return this.getCurrentWorkspaceData().osmBoundingBoxWgs84 ?? null;\n }\n\n /**\n * Retrieves the bounding box of a layer by its table name.\n * @param layerName - The name of the layer table to retrieve the bounding box from.\n * @returns A promise that resolves to the bounding box of the layer.\n * @throws Error if the database or connection is not initialized.\n * @throws Error if the layer table is not found.\n * @throws Error if the layer table does not have a geometry column.\n */\n async getBoundingBoxFromLayer(layerName: string): Promise<BoundingBox> {\n if (!this.db || !this.conn || !this.getBoundingBoxFromLayerUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const layerTable = this.tables.find((t) => t.name === layerName);\n if (!layerTable) throw new Error(`Table ${layerName} not found.`);\n\n // Verify the table has a geometry column\n const hasGeometry = layerTable.columns.find((column) => column.type === 'GEOMETRY');\n if (!hasGeometry) {\n throw new Error(\n `Table ${layerName} does not have a geometry column. This method only works with layer tables that contain geometries.`,\n );\n }\n\n return this.getBoundingBoxFromLayerUseCase.exec({\n layerTableName: layerName,\n workspace: this.currentWorkspace,\n });\n }\n\n /**\n * Retrieves all layer tables from the loaded tables.\n *\n * @returns An array of `LayerTable` and `CustomLayerTable` objects.\n * @throws Never throws.\n */\n getLayerTables(): Array<LayerTable | CustomLayerTable> {\n return this.tables.filter((table): table is LayerTable | CustomLayerTable => {\n return (\n (table.source === 'osm' && isLayerType(table.type)) ||\n (table.source === 'geojson' && isLayerType(table.type)) ||\n (table.source === 'user' && isLayerType(table.type)) // TODO: check if this is correct\n );\n });\n }\n\n /**\n * Retrieves the data from any table as an array of plain JavaScript objects.\n * This method works with all table types (CSV, JSON, Layer, Grid, etc.).\n * @param params - Parameters including table name and optional pagination (limit, offset).\n * @returns A promise that resolves to an array of objects representing the table rows.\n * @throws Error if the database or connection is not initialized.\n * @throws Error if the table is not found.\n */\n async getTableData(params: GetTableDataParams): Promise<GetTableDataOutput> {\n if (!this.db || !this.conn || !this.getTableDataUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const table = this.tables.find((t) => t.name === params.tableName);\n if (!table) throw new Error(`Table ${params.tableName} not found.`);\n\n return this.getTableDataUseCase.exec({ ...params, workspace: this.currentWorkspace });\n }\n\n // ---- UPDATE methods\n\n /**\n * Updates an existing table with new data.\n * \n * For layer tables (OSM, GeoJSON), the input data should be a GeoJSON FeatureCollection.\n * For non-layer tables (CSV, JSON), the input data should be an array of objects.\n * \n * @param params - Parameters for updating the table:\n * - tableName: The name of the table to update\n * - data: The new data (FeatureCollection for layers, Record<string, unknown>[] for CSV/JSON)\n * - strategy: 'replace' (drop and recreate) or 'update' (update existing records by ID)\n * - idColumn: Required for 'update' strategy. Supports 'id' or 'properties.attribute_name' format\n * @returns A promise that resolves to the updated Table with refreshed column metadata.\n * @throws Error if the database or connection is not initialized.\n * @throws Error if the table is not found.\n * @throws Error if idColumn is not provided when using 'update' strategy.\n */\n async updateTable(params: Omit<UpdateTableParams, 'workspace'>): Promise<Table> {\n if (!this.db || !this.conn || !this.updateTableUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const table = this.tables.find((t) => t.name === params.tableName);\n if (!table) throw new Error(`Table ${params.tableName} not found.`);\n\n const result = await this.updateTableUseCase.exec(\n { ...params, workspace: this.currentWorkspace },\n table\n );\n\n // Update the table in the workspace\n const workspaceData = this.getCurrentWorkspaceData();\n const tableIndex = workspaceData.tables.findIndex((t) => t.name === params.tableName);\n if (tableIndex !== -1) {\n workspaceData.tables[tableIndex] = result.table;\n }\n\n return result.table;\n }\n\n // CUSTOM QUERIES\n\n /**\n * Performs a spatial join between two tables and returns the resulting table.\n * The method can either create a new table or update an existing one based on the parameters.\n * @param params - Parameters for the spatial join operation, including source and target tables, join type, and output table name.\n * @returns A promise that resolves to the resulting table after the spatial join.\n * @throws Error if the database or connection is not initialized.\n */\n async spatialQuery(params: SpatialQueryParams): Promise<Table> {\n if (!this.db || !this.conn || !this.spatialJoinUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const workspaceData = this.getCurrentWorkspaceData();\n const { created, table } = await this.spatialJoinUseCase.exec(params, workspaceData.tables);\n if (created) this._registerTable(table);\n else workspaceData.tables = workspaceData.tables.map((t) => (t.name === table.name ? table : t));\n\n return table;\n }\n\n /**\n * Executes a raw SQL query and returns the result.\n * @param params - Parameters for the raw query, including the SQL query string and output type.\n * @returns A promise that resolves to a Table if output type is 'CREATE_TABLE', otherwise returns the query result of type T.\n * @throws Error if the database or connection is not initialized.\n */\n async rawQuery<T = RawQueryOutput>(params: RawQueryParams): Promise<T | Table> {\n if (!this.db || !this.conn || !this.rawQueryUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const result = await this.rawQueryUseCase.exec(params);\n\n if (params.output.type === 'CREATE_TABLE') {\n this._registerTable(result as Table);\n return result as Table;\n }\n\n return result as unknown as T;\n }\n\n /**\n * Drops a table from the database and removes it from the current workspace.\n * @param tableName - The name of the table to remove.\n * @returns A promise that resolves when the table has been dropped.\n * @throws Error if the database or connection is not initialized.\n */\n async removeLayer(tableName: string): Promise<void> {\n if (!this.conn || !this.dropTableUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n await this.dropTableUseCase.exec({ tableName, workspace: this.currentWorkspace });\n\n const workspaceData = this.getCurrentWorkspaceData();\n workspaceData.tables = workspaceData.tables.filter((t) => t.name !== tableName);\n }\n\n /**\n * Builds a heatmap from spatial data by creating a grid and aggregating values.\n * The heatmap is generated by creating a grid over the bounding box and aggregating values from the source table into each grid cell.\n * @param params - Parameters for building the heatmap, including source table, grid configuration, and aggregation method.\n * @returns A promise that resolves to the resulting GridLayerTable containing the heatmap data.\n * @throws Error if the database or connection is not initialized.\n */\n async buildHeatmap(params: BuildHeatmapParams): Promise<Table> {\n if (!this.db || !this.conn || !this.buildHeatmapUseCase)\n throw new Error('Database not initialized. Please call init() first.');\n\n const workspaceData = this.getCurrentWorkspaceData();\n const table = await this.buildHeatmapUseCase.exec(params, workspaceData.tables, workspaceData.osmBoundingBox);\n this._registerTable(table);\n\n return table;\n }\n}\n"],"x_google_ignoreList":[5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,40,42,43,44,59,60,61,62,63,64,65,66,67,68,69,70,71,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98],"mappings":"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"}