@bitruvius/geo-core 0.3.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.
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Rebase **glTF POINTS** primitives (3D Tiles 1.1 point-cloud content) into the
3
+ * shared scene ENU(meters) grid and quantize to the renderer's i32 layout —
4
+ * producing the same `PackedPointTile` the `.pnts` (1.0) path emits, so the
5
+ * `@bitruvius/ptcloud` renderer consumes either version unchanged.
6
+ *
7
+ * Per primitive the transform is `tileToEnu(enuFromEcef, tileTransform, nodeMatrix)`
8
+ * — IDENTICAL to {@link packMeshEnu}, so glTF content (incl. the y-up→z-up flip)
9
+ * lands in exactly the same frame as 3D-Tiles meshes. Two passes: (1) project every
10
+ * point to f64 ENU while tracking the global bbox; the origin is the bbox center so
11
+ * the i32 grid stays small/f32-safe; (2) `i32 = round((enu − origin) / grid)`.
12
+ * Color/intensity/classification are passed through (color is pre-widened to u16 by
13
+ * the decoder). Multiple primitives are concatenated under one origin/scale.
14
+ */
15
+ import type { Mat4 } from './mat4';
16
+ import type { PackedPointTile } from './pack-point-enu';
17
+ /** One glTF POINTS primitive in glb-local meters (the parser's NormalizedPrimitive
18
+ * subset the packer needs). `rgb` is already widened to full-range u16. */
19
+ export interface GltfPointPrimitive {
20
+ /** 3·N positions in glb-local meters. */
21
+ readonly positions: Float32Array;
22
+ /** Column-major 4×4 glTF node transform (glb root → this primitive's node). */
23
+ readonly nodeMatrix: Mat4;
24
+ /** 3·N full-range u16 RGB (pre-widened by the decoder), if colored. */
25
+ readonly rgb?: Uint16Array;
26
+ /** N full-range u16 intensity, if present. */
27
+ readonly intensity?: Uint16Array;
28
+ /** N classification codes, if present. */
29
+ readonly classification?: Uint8Array;
30
+ }
31
+ /** @internal */
32
+ export interface PackGltfPointsContext {
33
+ /** ECEF → shared-scene ENU (meters), column-major 4×4. */
34
+ readonly enuFromEcef: Mat4;
35
+ /** Tile transform: tile-local → ECEF, column-major 4×4. */
36
+ readonly tileTransform: Mat4;
37
+ /** Requantization step (meters) for the i32 grid (e.g. 0.001 = 1 mm). */
38
+ readonly grid: number;
39
+ }
40
+ /** Project + quantize glTF POINTS primitives into the shared ENU grid. @internal */
41
+ export declare function packGltfPointsEnu(prims: readonly GltfPointPrimitive[], ctx: PackGltfPointsContext): PackedPointTile;
@@ -0,0 +1,16 @@
1
+ import type { PackedEdges, PackedMeshPrimitive } from '../contracts/mesh';
2
+ /** Tuning for {@link packMeshEdges}. */
3
+ export interface PackMeshEdgesOptions {
4
+ /** Dihedral angle above which a shared edge is a crease. Default 25°. */
5
+ readonly creaseAngleDeg?: number;
6
+ /** Cap on edges per TILE (not per primitive). Default 400 000. */
7
+ readonly maxEdges?: number;
8
+ }
9
+ /**
10
+ * Extract and merge the hard edges of every primitive in a tile.
11
+ *
12
+ * @param primitives - The tile's packed primitives.
13
+ * @param opts - Extraction tuning ({@link PackMeshEdgesOptions}).
14
+ * @returns One merged line list, or `null` when the tile has no edges worth drawing.
15
+ */
16
+ export declare function packMeshEdges(primitives: readonly PackedMeshPrimitive[], opts?: PackMeshEdgesOptions): PackedEdges | null;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Rebase a `NormalizedMesh` (glb-local) into the shared scene **ENU(meters)**
3
+ * frame and recenter on a per-tile origin so vertex coordinates stay f32-safe —
4
+ * the mesh analog of `packEnu` (splats) / `packPointTileEnu` (points). Per
5
+ * primitive: `world_enu = tileToEnu(enuFromEcef, tileTransform, nodeMatrix) · v`,
6
+ * then `f32 = world_enu − origin`, with `origin` the ENU bbox center of the tile.
7
+ * Normals use the inverse-transpose of the rebase linear part (correct under
8
+ * non-uniform scale) and are renormalized.
9
+ *
10
+ * The hot per-vertex loops are inlined and allocation-free (no per-vertex tuples)
11
+ * — millions of vertices stream through here, so it must not churn the GC.
12
+ */
13
+ import { type Mat4 } from './mat4';
14
+ import { type NormalizedMesh, type PackedMeshTile, type PackedTexture } from '../contracts/mesh';
15
+ /** The transforms packMeshEnu needs (a subset of MeshDecodeContext, with the tile
16
+ * transform possibly already folded with an RTC_CENTER by the decoder). @internal */
17
+ export interface MeshPackContext {
18
+ readonly enuFromEcef: Mat4;
19
+ readonly tileTransform: Mat4;
20
+ /** Also bake each vertex's TRUE web-mercator position (offset from the tile center) — for GLOBAL
21
+ * datasets, so the renderer places every vertex EXACTLY instead of via a single per-tile affine
22
+ * ENU→mercator tangent (which diverges across the tile: the parallax-swim). Cesium does this in
23
+ * `SceneMode2DPipelineStage`. Off (default) → byte-identical to the pure-ENU path. */
24
+ readonly bakeMercator?: boolean;
25
+ /** Up-axis of the glb content — 3D Tiles' `asset.gltfUpAxis`. Default `'y'` (the spec
26
+ * default): the y-up→z-up flip is applied. `'z'` skips it; see {@link tileToEnu}. */
27
+ readonly gltfUpAxis?: 'y' | 'z';
28
+ }
29
+ /** Project + recenter a normalized mesh into the shared ENU grid. `textures` are
30
+ * the decoded GPU textures (indexed by glTF texture index) the material refs
31
+ * point into — decoded by the caller via the codec seams; `[]` for untextured.
32
+ * @internal */
33
+ export declare function packMeshEnu(mesh: NormalizedMesh, ctx: MeshPackContext, textures?: readonly PackedTexture[]): PackedMeshTile;
34
+ /** Pack a `NormalizedMesh` into MODEL space — glTF y-up → z-up baked, but NO scene-ENU rebase
35
+ * and NO origin recenter — the inner-model packing for **instanced** tiles (3D-Tiles i3dm, Esri
36
+ * `ObjectSymbol3DLayer`, user models on points). One shared model; each instance's matrix (see
37
+ * `buildInstanceMatrices`) places a copy. Returns a {@link PackedMeshTile} with `origin:[0,0,0]` and
38
+ * no `instances` — the caller sets `origin` to the instance centroid + attaches the matrices.
39
+ * @internal */
40
+ export declare function packModelSpaceMesh(mesh: NormalizedMesh, textures?: readonly PackedTexture[], opts?: {
41
+ readonly upAxis?: 'y' | 'z';
42
+ readonly scale?: number;
43
+ }): PackedMeshTile;
44
+ /** Collect the transferables of a {@link PackedMeshTile} (for postMessage) — ArrayBuffers plus any decoded
45
+ * texture `bitmap` (ImageBitmap is Transferable). @internal */
46
+ export declare function packedMeshTransferables(tile: PackedMeshTile): Transferable[];
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Rebase a decoded **Cartesian** point tile (OGC 3D-Tiles `.pnts`: positions are
3
+ * tile-local meters relative to `RTC_CENTER`, NOT geodetic lng/lat) into the
4
+ * shared scene ENU(meters) grid and quantize to the renderer's i32 layout. The
5
+ * Cartesian analog of {@link packPointTileEnu} (which takes geographic input).
6
+ *
7
+ * Per point: `enu = enuFromEcef · tileTransform · (rtcCenter + localPos)`, then
8
+ * `i32 = round((enu − origin) / grid)` with `origin` = the ENU of the tile's
9
+ * local origin (`M·0` = the rtc/tile placement), which keeps the i32 coords small
10
+ * because RTC sits near the point cluster. Single inlined pass, allocation-free.
11
+ *
12
+ * No glTF Y-up→Z-up flip here — `.pnts` content is already in the tile (z-up)
13
+ * frame (only glTF content gets that flip; see {@link tileToEnu}).
14
+ */
15
+ import { type Mat4 } from './mat4';
16
+ import type { PackedPointTile } from './pack-point-enu';
17
+ /** A decoded `.pnts` tile in tile-local Cartesian meters (relative to `rtcCenter`). */
18
+ export interface DecodedPointTileEcef {
19
+ /** Point count. */
20
+ readonly count: number;
21
+ /** 3·count interleaved positions in tile-local Cartesian meters. */
22
+ readonly positions: Float32Array;
23
+ /** Optional RTC center (meters) the positions are relative to. */
24
+ readonly rtcCenter?: readonly [number, number, number];
25
+ /** 3·count interleaved full-range u16 RGB, if colored. */
26
+ readonly rgb?: Uint16Array;
27
+ /** count full-range u16 intensity, if present. */
28
+ readonly intensity?: Uint16Array;
29
+ /** count classification codes, if present. */
30
+ readonly classification?: Uint8Array;
31
+ }
32
+ /** @internal */
33
+ export interface PackPointEcefContext {
34
+ /** ECEF → shared-scene ENU (meters), column-major 4×4. */
35
+ readonly enuFromEcef: Mat4;
36
+ /** Tile transform: tile-local → ECEF, column-major 4×4. */
37
+ readonly tileTransform: Mat4;
38
+ /** Requantization step (meters) for the i32 grid (e.g. 0.001 = 1 mm). */
39
+ readonly grid: number;
40
+ }
41
+ /** Project + quantize a Cartesian point tile into the shared ENU grid. @internal */
42
+ export declare function packPointTileEcef(tile: DecodedPointTileEcef, ctx: PackPointEcefContext): PackedPointTile;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Rebase a decoded point tile from geographic (or projected) coordinates into the
3
+ * shared scene **ENU (meters)** frame and requantize it to the renderer's integer
4
+ * grid — the point-cloud analog of `tiles3d`'s `packEnu` for splats.
5
+ *
6
+ * Per point: `(lng,lat,h) → ECEF → ENU(meters) → round((enu − tileOrigin)/grid)`.
7
+ * The tile origin is the node OBB center in ENU, so the i32 coordinates stay small
8
+ * and f32-exact regardless of the dataset's distance from the scene anchor (the
9
+ * renderer dequantizes `world = q·grid + offset` and applies one ENU→mercator
10
+ * placement). Heights are treated as orthometric (vcsWkid 5773): ellipsoidal
11
+ * `h = H + geoidN`. Projected scenes supply a `reproject` hook.
12
+ *
13
+ * Runs INSIDE the decode worker (off the render thread); the ECEF + ENU math is
14
+ * inlined to avoid per-point allocations over millions of points.
15
+ */
16
+ import { type Mat4 } from './mat4';
17
+ /** Decoded point tile in the layer's native coordinates, before ENU rebasing.
18
+ * `position` is 3·N interleaved: geographic `[lng°, lat°, h_m]` (wkid 4326/4979)
19
+ * or projected `[x, y, z]` meters (then a `reproject` hook is required). */
20
+ export interface DecodedPointTileF64 {
21
+ readonly kind: 'pointcloud-f64';
22
+ readonly count: number;
23
+ readonly position: Float64Array;
24
+ /** Already-interleaved full-range u16 RGB (3·N) — passed through ZERO-COPY (LEPCC,
25
+ * whose wasm RGB output is AoS). Takes precedence over the planar r/g/b below; a
26
+ * decoder sets EITHER `rgb` OR `r`/`g`/`b`, never both. */
27
+ readonly rgb?: Uint16Array;
28
+ /** Planar full-range u16 RGB channels (BVC produces separate planes) — re-interleaved
29
+ * into `PackedPointTile.rgb`. Use `rgb` instead when the source is already interleaved. */
30
+ readonly r?: Uint16Array;
31
+ readonly g?: Uint16Array;
32
+ readonly b?: Uint16Array;
33
+ readonly intensity?: Uint16Array;
34
+ readonly classification?: Uint8Array;
35
+ readonly returns?: Uint8Array;
36
+ readonly flags?: Uint8Array;
37
+ readonly pointSourceId?: Uint16Array;
38
+ readonly gpsTime?: Float64Array;
39
+ readonly scanAngle?: Int16Array;
40
+ }
41
+ /** A point tile rebased into the shared ENU frame + requantized, ready for a
42
+ * consumer to upload to GPU buffers. `position`/`rgb` are interleaved (3·N);
43
+ * the rest are per-point planes the renderer binds directly or retains for
44
+ * picking. Dequant in-shader: `world_enu = position · scale + offset`. */
45
+ export interface PackedPointTile {
46
+ readonly count: number;
47
+ /** Interleaved 3·N quantized ENU grid coords `[x0,y0,z0,x1,…]`. */
48
+ readonly position: Int32Array;
49
+ /** Per-axis dequant step (meters); same for every tile (the global grid). */
50
+ readonly scale: readonly [number, number, number];
51
+ /** This tile's ENU origin (meters) — the node OBB center; added in-shader. */
52
+ readonly offset: readonly [number, number, number];
53
+ /** Interleaved 3·N u16 color `[r0,g0,b0,r1,…]` (present iff the node has RGB). */
54
+ readonly rgb?: Uint16Array;
55
+ readonly intensity?: Uint16Array;
56
+ readonly classification?: Uint8Array;
57
+ readonly returns?: Uint8Array;
58
+ readonly flags?: Uint8Array;
59
+ readonly pointSourceId?: Uint16Array;
60
+ readonly gpsTime?: Float64Array;
61
+ readonly scanAngle?: Int16Array;
62
+ /** Absolute ENU bounds (meters) — for the height ramp + bounds debug. */
63
+ readonly enuMin: readonly [number, number, number];
64
+ readonly enuMax: readonly [number, number, number];
65
+ /** Point FEATURE *model mode*: per-point model scale (m) + heading (deg CW from north), derived
66
+ * from per-feature attributes (e.g. tree height → scale, `Rotatie` → heading). Consumed by the
67
+ * instanced-model render path (`buildPointTileInstances`); undefined for point clouds. */
68
+ readonly modelScale?: Float32Array;
69
+ readonly modelHeading?: Float32Array;
70
+ /** Point FEATURE *per-symbol model mode*: per-point `drawingInfo` symbol index (from `selectSymbol`)
71
+ * — which symbol/model each feature uses, for a `uniqueValue`/`classBreaks` renderer that maps
72
+ * different features to DIFFERENT models (e.g. one mesh per tree species). The layer partitions the
73
+ * tile by this index and instances each group into its species' shared template. `0xffff` = no
74
+ * matching symbol (skip). Undefined when one model serves all features (the common single-model case). */
75
+ readonly modelSymbol?: Uint16Array;
76
+ }
77
+ /** Inputs the packer needs from the decode context (a subset of `I3sDecodeContext`).
78
+ * @internal */
79
+ export interface PackPointContext {
80
+ readonly nodeCenterEcef: readonly [number, number, number];
81
+ readonly enuFromEcef: Float64Array;
82
+ readonly geoidN: number;
83
+ readonly grid: number;
84
+ readonly wkid: number;
85
+ readonly reproject?: (x: number, y: number, z: number) => [number, number, number];
86
+ }
87
+ /** Collect the transferable buffers of a `PackedPointTile` (for `postMessage`).
88
+ * @internal */
89
+ export declare function packedPointTransferables(t: PackedPointTile): ArrayBuffer[];
90
+ /** Resident byte cost of a `PackedPointTile` (the quantized positions + every
91
+ * present per-point attribute plane) — the streaming engine's memory-budget signal.
92
+ * @internal */
93
+ export declare function packedPointBytes(t: PackedPointTile): number;
94
+ /** Project + requantize a decoded tile into the shared ENU grid. @internal */
95
+ export declare function packPointTileEnu(tile: DecodedPointTileF64, ctx: PackPointContext): PackedPointTile;
96
+ /** Inputs to {@link packI3sPointsEnu} — the modern I3S **Point feature** node frame.
97
+ * @internal */
98
+ export interface PackI3sPointsContext {
99
+ /** ECEF → shared-scene ENU (meters), column-major 4×4. */
100
+ readonly enuFromEcef: Mat4;
101
+ /** node-local ENU(z-up) → ECEF — the engine builds it from the node center (its `frameFor`). */
102
+ readonly tileTransform: Mat4;
103
+ /** WGS84 meters-per-degree of lng/lat at the node center — I3S global-mode position X/Y are
104
+ * lng/lat DEGREE offsets; multiply to get local ENU east/north meters. */
105
+ readonly lngToMeters: number;
106
+ readonly latToMeters: number;
107
+ /** `i3s-scale_x/y` POSITION metadata (Draco quantization pre-scale; default 1). */
108
+ readonly scaleX: number;
109
+ readonly scaleY: number;
110
+ /** Requantization step (meters) for the i32 position grid. */
111
+ readonly grid: number;
112
+ }
113
+ /**
114
+ * Pack modern I3S **Point feature** geometry — RAW node-local positions (X/Y are lng/lat DEGREE
115
+ * offsets pre-scaled by `i3s-scale`, Z is meters) — into the shared ENU grid as a
116
+ * `PackedPointTile`: the point-cloud analog of `packMeshEnu` for the mesh path.
117
+ *
118
+ * The combined node-local→scene-ENU matrix `M = enuFromEcef · tileTransform` folds the per-axis
119
+ * `scaleX·lngToMeters` / `scaleY·latToMeters` into its X/Y columns (ONE matrix build per tile, not a
120
+ * pass over every point), so the per-point loop is a single mat·vec + quantize — no per-point
121
+ * allocations, runs in the decode worker. The tile origin (offset) is the node center in scene ENU
122
+ * (M's translation column), keeping the i32 grid small + f32-exact regardless of dataset distance.
123
+ *
124
+ * @internal
125
+ */
126
+ export declare function packI3sPointsEnu(positions: Float32Array, count: number, ctx: PackI3sPointsContext): PackedPointTile;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Infinite-plane primitives shared by frustum culling and clipping. A plane is the
3
+ * tuple `[nx, ny, nz, d]` with unit normal `n`; a point `p` is on the KEPT (inside)
4
+ * half-space iff `dot(n, p) + d >= 0` — the same convention the engine frustum
5
+ * planes use. Pure f64 math (no DOM/GL).
6
+ */
7
+ import type { Mat4 } from './mat4';
8
+ import type { Vec3 } from './ecef';
9
+ /**
10
+ * A plane `[nx, ny, nz, d]` in the frame of its consumer (metres). `n` is unit
11
+ * length and points into the kept half-space: `dot(n, p) + d >= 0` is inside.
12
+ */
13
+ export type Plane = readonly [number, number, number, number];
14
+ /**
15
+ * Signed distance (metres) from `p` to `plane` — positive on the kept side.
16
+ * @param plane - The plane (unit normal).
17
+ * @param p - The point, in the plane's frame (metres).
18
+ * @returns `dot(n, p) + d`.
19
+ */
20
+ export declare function planeDistance(plane: Plane, p: Vec3): number;
21
+ /**
22
+ * Build a {@link Plane} through `point` whose kept half-space is the side `normal`
23
+ * points into. `normal` need not be unit length (it is normalized here).
24
+ * @param point - A point on the plane (metres).
25
+ * @param normal - Direction of the kept half-space (any length, not all-zero).
26
+ * @returns The normalized plane `[nx, ny, nz, -dot(n, point)]`.
27
+ */
28
+ export declare function planeFromPointNormal(point: Vec3, normal: Vec3): Plane;
29
+ /**
30
+ * Transform a plane by a RIGID (rotation + translation, no scale/shear) point map
31
+ * `p' = m · p`: the normal rotates with `m`'s upper 3×3 and the offset follows,
32
+ * preserving signed point distances. Use to move planes between metric frames
33
+ * (e.g. ECEF ↔ local ENU via {@link enuFromEcefMatrix}).
34
+ * @param m - Column-major rigid point transform (source frame → target frame).
35
+ * @param plane - The plane in the source frame.
36
+ * @returns The equivalent plane in the target frame.
37
+ */
38
+ export declare function transformPlaneRigid(m: Mat4, plane: Plane): Plane;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @bitruvius/geo-core — the pure-TS geospatial foundation.
3
+ *
4
+ * Contracts (Decoder / Renderer / ViewerAdapter + the splat/point/mesh decode seams),
5
+ * the quantized decoded model types, geo + matrix math (ENU/ECEF/mercator), map-style
6
+ * expressions, and the BVC dequant reference (parity oracle for the shaders). No GPU,
7
+ * wasm, or DOM dependencies live here. Builds on {@link @bitruvius/foundation} (scheduling,
8
+ * capability detection, config, errors), which it re-exports for convenience.
9
+ *
10
+ * @packageDocumentation
11
+ * @group Libraries
12
+ * @category Foundation
13
+ */
14
+ export * from '@bitruvius/foundation';
15
+ export * from './contracts/decoder';
16
+ export * from './contracts/renderer';
17
+ export * from './contracts/viewer-adapter';
18
+ export * from './contracts/gltf-splat-decoder';
19
+ export * from './contracts/i3s-point-decoder';
20
+ export * from './contracts/i3s-mesh-decoder';
21
+ export * from './contracts/cesium-point-decoder';
22
+ export * from './contracts/mesh';
23
+ export * from './contracts/mesh-codecs';
24
+ export * from './contracts/feature-metadata';
25
+ export * from './geo/mat4';
26
+ export * from './geo/model-placement';
27
+ export * from './geo/plane';
28
+ export * from './geo/measure';
29
+ export * from './geo/mercator';
30
+ export * from './geo/ecef';
31
+ export * from './geo/pack-point-enu';
32
+ export * from './geo/pack-point-ecef';
33
+ export * from './geo/pack-mesh-enu';
34
+ export * from './geo/hard-edges';
35
+ export * from './geo/pack-mesh-edges';
36
+ export * from './geo/pack-gltf-points-enu';
37
+ export * from './style/expression';
38
+ export * from './dequant/formulas';
39
+ export * from './dequant/tile-bounds';
40
+ export * from './dequant/stray-cull';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export*from"@bitruvius/foundation";function kQ(J){switch(J.trim().toUpperCase().replace(/[\s-]+/g,"_")){case"ELEVATION":return"ELEVATION";case"INTENSITY":return"INTENSITY";case"RGB":return"RGB";case"CLASS_CODE":case"CLASSIFICATION":return"CLASS_CODE";case"FLAGS":return"FLAGS";case"RETURNS":return"RETURNS";case"USER_DATA":return"USER_DATA";case"POINT_SRC_ID":case"POINT_SOURCE_ID":return"POINT_SRC_ID";case"GPS_TIME":return"GPS_TIME";case"SCAN_ANGLE":return"SCAN_ANGLE";case"NEAR_INFRARED":case"NIR":return"NEAR_INFRARED";default:return"UNKNOWN"}}var fJ={baseColorFactor:[1,1,1,1],alphaMode:"OPAQUE",alphaCutoff:0.5,doubleSided:!1,unlit:!1,metallicFactor:1,roughnessFactor:1,emissiveFactor:[0,0,0]},KQ=Object.freeze([]);function vJ(J){if(J.instanceGroups!==void 0)return J.instanceGroups;let Q=J.instances;if(Q===void 0)return KQ;return[{count:Q.count,matrices:Q.matrices,primitiveRange:[0,J.primitives.length]}]}function vQ(J){return["rgba32","bc7","bc3","bc1","etc2","astc4x4","pvrtc"].indexOf(J)}class yJ{count;names;#J;#Q;constructor(J,Q,$=new Map){this.count=J,this.#J=Q,this.#Q=$,this.names=[...Q.keys()]}value(J,Q){if(J<0||J>=this.count)return null;let $=this.#J.get(Q);if(!$)return null;let K=$.values[J];if(K===void 0)return null;if($.def.type==="enum"&&$.def.enumName!==void 0&&typeof K==="number")return this.#Q.get($.def.enumName)?.values.get(K)??K;return K}record(J){if(J<0||J>=this.count)return null;let Q={};for(let $ of this.names)Q[$]=this.value(J,$);return Q}toData(){return{count:this.count,columns:[...this.#J.values()],enums:[...this.#Q.values()].map((J)=>({name:J.name,entries:[...J.values.entries()]}))}}}function gQ(J){let Q=new Map(J.columns.map((K)=>[K.def.name,K])),$=new Map((J.enums??[]).map((K)=>[K.name,{name:K.name,values:new Map(K.entries)}]));return new yJ(J.count,Q,$)}function bQ(J,Q){return($)=>J.value(Q,$)}function dQ(J){return Float32Array.from(J)}function xQ(J,Q){for(let $=0;$<16;$++)Q[$]=J[$];return Q}function pQ(J){let Q=new Float64Array(16);for(let $=0;$<16;$++)Q[$]=J[$];return Q}function YJ(){let J=new Float64Array(16);return J[0]=J[5]=J[10]=J[15]=1,J}function uQ(J){return new Float64Array(J)}function s(J,Q,$=new Float64Array(16)){for(let K=0;K<4;K++){let V=Q[K*4],W=Q[K*4+1],H=Q[K*4+2],U=Q[K*4+3];for(let C=0;C<4;C++)$[K*4+C]=J[C]*V+J[4+C]*W+J[8+C]*H+J[12+C]*U}return $}function gJ(J,Q=new Float64Array(16)){for(let $=0;$<4;$++)for(let K=0;K<4;K++)Q[K*4+$]=J[$*4+K];return Q}function cQ(J,Q=new Float64Array(9)){return Q[0]=J[0],Q[1]=J[1],Q[2]=J[2],Q[3]=J[4],Q[4]=J[5],Q[5]=J[6],Q[6]=J[8],Q[7]=J[9],Q[8]=J[10],Q}function lQ(J,Q){let[$,K,V,W]=Q;return[J[0]*$+J[4]*K+J[8]*V+J[12]*W,J[1]*$+J[5]*K+J[9]*V+J[13]*W,J[2]*$+J[6]*K+J[10]*V+J[14]*W,J[3]*$+J[7]*K+J[11]*V+J[15]*W]}function QJ(J,Q,$){let K=YJ();return K[12]=J,K[13]=Q,K[14]=$,K}function GJ(J,Q,$){let K=new Float64Array(16);return K[0]=J,K[5]=Q,K[10]=$,K[15]=1,K}function bJ(J,Q=new Float64Array(16)){let $=Math.cos(J),K=Math.sin(J);return Q[0]=1,Q[1]=0,Q[2]=0,Q[3]=0,Q[4]=0,Q[5]=$,Q[6]=K,Q[7]=0,Q[8]=0,Q[9]=-K,Q[10]=$,Q[11]=0,Q[12]=0,Q[13]=0,Q[14]=0,Q[15]=1,Q}function hJ(J,Q=new Float64Array(16)){let $=Math.cos(J),K=Math.sin(J);return Q[0]=$,Q[1]=0,Q[2]=-K,Q[3]=0,Q[4]=0,Q[5]=1,Q[6]=0,Q[7]=0,Q[8]=K,Q[9]=0,Q[10]=$,Q[11]=0,Q[12]=0,Q[13]=0,Q[14]=0,Q[15]=1,Q}function dJ(J,Q=new Float64Array(16)){let $=Math.cos(J),K=Math.sin(J);return Q[0]=$,Q[1]=K,Q[2]=0,Q[3]=0,Q[4]=-K,Q[5]=$,Q[6]=0,Q[7]=0,Q[8]=0,Q[9]=0,Q[10]=1,Q[11]=0,Q[12]=0,Q[13]=0,Q[14]=0,Q[15]=1,Q}function PJ(J,Q=new Float64Array(16)){let $=J[0],K=J[1],V=J[2],W=J[3],H=J[4],U=J[5],C=J[6],F=J[7],O=J[8],G=J[9],R=J[10],B=J[11],Z=J[12],_=J[13],D=J[14],S=J[15],j=$*U-K*H,E=$*C-V*H,X=$*F-W*H,w=K*C-V*U,q=K*F-W*U,P=V*F-W*C,L=O*_-G*Z,N=O*D-R*Z,k=O*S-B*Z,v=G*D-R*_,Y=G*S-B*_,T=R*S-B*D,I=j*T-E*Y+X*v+w*k-q*N+P*L;if(I===0||!Number.isFinite(I))throw Error("mat4.invert: singular matrix");if(I=1/I,!Number.isFinite(I))throw Error("mat4.invert: singular matrix");return Q[0]=(U*T-C*Y+F*v)*I,Q[1]=(V*Y-K*T-W*v)*I,Q[2]=(_*P-D*q+S*w)*I,Q[3]=(R*q-G*P-B*w)*I,Q[4]=(C*k-H*T-F*N)*I,Q[5]=($*T-V*k+W*N)*I,Q[6]=(D*X-Z*P-S*E)*I,Q[7]=(O*P-R*X+B*E)*I,Q[8]=(H*Y-U*k+F*L)*I,Q[9]=(K*k-$*Y-W*L)*I,Q[10]=(Z*q-_*X+S*j)*I,Q[11]=(G*X-O*q-B*j)*I,Q[12]=(U*N-H*v-C*L)*I,Q[13]=($*v-K*N+V*L)*I,Q[14]=(_*E-Z*w-D*j)*I,Q[15]=(O*w-G*E+R*j)*I,Q}function ZJ(J,Q){let $=Q[0],K=Q[1],V=Q[2];return[J[0]*$+J[4]*K+J[8]*V+J[12],J[1]*$+J[5]*K+J[9]*V+J[13],J[2]*$+J[6]*K+J[10]*V+J[14]]}function mQ(J,Q){let $=Q[0],K=Q[1],V=Q[2];return[J[0]*$+J[4]*K+J[8]*V,J[1]*$+J[5]*K+J[9]*V,J[2]*$+J[6]*K+J[10]*V]}function rQ(J,Q,$,K,V,W,H=new Float64Array(16)){let U=1/(J-Q),C=1/($-K),F=1/(V-W);return H[0]=-2*U,H[1]=0,H[2]=0,H[3]=0,H[4]=0,H[5]=-2*C,H[6]=0,H[7]=0,H[8]=0,H[9]=0,H[10]=2*F,H[11]=0,H[12]=(J+Q)*U,H[13]=(K+$)*C,H[14]=(W+V)*F,H[15]=1,H}function xJ(J,Q,$,K,V=new Float64Array(16)){return V[0]=J[0],V[1]=J[1],V[2]=J[2],V[3]=0,V[4]=Q[0],V[5]=Q[1],V[6]=Q[2],V[7]=0,V[8]=$[0],V[9]=$[1],V[10]=$[2],V[11]=0,V[12]=K[0],V[13]=K[1],V[14]=K[2],V[15]=1,V}var XJ=6371008.8,SJ=2*Math.PI*XJ;function NJ(J){return SJ*Math.cos(J*Math.PI/180)}function VQ(J){return(180+J)/360}function HQ(J){return(180-180/Math.PI*Math.log(Math.tan(Math.PI/4+J*Math.PI/360)))/360}function WQ(J,Q){return J/NJ(Q)}function oQ(J){return J*360-180}function iQ(J){return 360/Math.PI*Math.atan(Math.exp((180-J*360)*Math.PI/180))-90}function aQ(J,Q){return J*NJ(Q)}function UQ(J){return 1/NJ(J)}function _J(J,Q=0){return{x:VQ(J.lng),y:HQ(J.lat),z:WQ(Q,J.lat)}}function pJ(J,Q={}){let $=_J(J,J.altitude),K=UQ(J.lat),V=s(QJ($.x,$.y,$.z),GJ(K,K,K));return Q.basis?s(V,Q.basis):V}var GQ=GJ(1,-1,1),qJ=(J)=>J*Math.PI/180,RQ=Object.freeze({z:Float64Array.from([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),y:Float64Array.from([1,0,0,0,0,0,1,0,0,-1,0,0,0,0,0,1]),"-y":Float64Array.from([1,0,0,0,0,0,-1,0,0,1,0,0,0,0,0,1]),x:Float64Array.from([0,0,1,0,0,1,0,0,-1,0,0,0,0,0,0,1]),"-x":Float64Array.from([0,0,-1,0,0,1,0,0,1,0,0,0,0,0,0,1]),"-z":Float64Array.from([1,0,0,0,0,-1,0,0,0,0,-1,0,0,0,0,1])}),uJ={z:{axis:2,sign:1},y:{axis:1,sign:1},"-y":{axis:1,sign:-1},x:{axis:0,sign:1},"-x":{axis:0,sign:-1},"-z":{axis:2,sign:-1}};function Q$(J){let{axis:Q,sign:$}=uJ[J],K=[0,0,0];return K[Q]=$,K}function CQ(J,Q,$){if($==="origin")return[0,0,0];if(typeof $!=="string")return[$[0],$[1],$[2]];let K=(W)=>J.p50?.[W]??(J.min[W]+J.max[W])/2,V=[K(0),K(1),K(2)];if($==="bottom-center"||$==="top-center"){let{axis:W,sign:H}=uJ[Q],U=$==="bottom-center"===H>0;V[W]=U?J.p05?.[W]??J.min[W]:J.p95?.[W]??J.max[W]}return V}function OQ(J={},Q=[0,0,0]){let{upAxis:$="z",heading:K=0,pitch:V=0,roll:W=0,scale:H=1}=J,U=new Float64Array(GQ);if(K!==0)U=s(U,dJ(-qJ(K)));if(V!==0)U=s(U,bJ(qJ(V)));if(W!==0)U=s(U,hJ(qJ(W)));let[C,F,O]=typeof H==="number"?[H,H,H]:H;if(C!==1||F!==1||O!==1)U=s(U,GJ(C,F,O));if($!=="z")U=s(U,RQ[$]);if(Q[0]!==0||Q[1]!==0||Q[2]!==0)U=s(U,QJ(-Q[0],-Q[1],-Q[2]));return U}function $$(J,Q={},$){let K=Q.anchorPoint??"center",W=(K==="center"||K==="bottom-center"||K==="top-center")&&!$?[0,0,0]:CQ($??{min:[0,0,0],max:[0,0,0]},Q.upAxis??"z",K),H={basis:OQ(Q,W)};return pJ(J,H)}function V$(J,Q){return J[0]*Q[0]+J[1]*Q[1]+J[2]*Q[2]+J[3]}function H$(J,Q){let $=Math.hypot(Q[0],Q[1],Q[2]),K=Q[0]/$,V=Q[1]/$,W=Q[2]/$;return[K,V,W,-(K*J[0]+V*J[1]+W*J[2])]}function W$(J,Q){let $=J[0]*Q[0]+J[4]*Q[1]+J[8]*Q[2],K=J[1]*Q[0]+J[5]*Q[1]+J[9]*Q[2],V=J[2]*Q[0]+J[6]*Q[1]+J[10]*Q[2],W=Q[3]-($*J[12]+K*J[13]+V*J[14]);return[$,K,V,W]}var KJ=6378137,IJ=0.0033528106647474805,BJ=IJ*(2-IJ),VJ=KJ*(1-IJ),BQ=(KJ*KJ-VJ*VJ)/(VJ*VJ);function RJ(J,Q,$){let K=J*Math.PI/180,V=Q*Math.PI/180,W=Math.sin(V),H=Math.cos(V),U=KJ/Math.sqrt(1-BJ*W*W);return[(U+$)*H*Math.cos(K),(U+$)*H*Math.sin(K),(U*(1-BJ)+$)*W]}function FJ(J,Q,$){let K=Math.atan2(Q,J),V=Math.hypot(J,Q),W=Math.atan2($*KJ,V*VJ),H=Math.sin(W),U=Math.cos(W),C=Math.atan2($+BQ*VJ*H*H*H,V-BJ*KJ*U*U*U),F=Math.sin(C),O=KJ/Math.sqrt(1-BJ*F*F),G=V/Math.cos(C)-O;return{lng:K*180/Math.PI,lat:C*180/Math.PI,height:G}}function LJ(J,Q,$){let K=Q*Math.PI/180,V=$*Math.PI/180,W=Math.sin(K),H=Math.cos(K),U=Math.sin(V),C=Math.cos(V),F=[-W,H,0],O=[-U*H,-U*W,C],G=[C*H,C*W,U],R=xJ([F[0],O[0],G[0]],[F[1],O[1],G[1]],[F[2],O[2],G[2]],[0,0,0]);return s(R,QJ(-J[0],-J[1],-J[2]))}var FQ=new Float64Array([1,0,0,0,0,0,1,0,0,-1,0,0,0,0,0,1]);function CJ(J,Q,$,K="y"){let V=K==="z"?$:s(FQ,$);return s(J,s(Q,V))}var OJ=Math.PI/180;function TJ(J){return RJ(J.lng,J.lat,J.height??0)}function AJ(J,Q){return ZJ(LJ(TJ(J),J.lng,J.lat),TJ(Q))}function DQ(J,Q){let[$,K,V]=AJ(J,Q);return Math.hypot($,K,V)}function cJ(J,Q){let[$,K]=AJ(J,{lng:Q.lng,lat:Q.lat,height:J.height??0});return Math.hypot($,K)}function F$(J,Q){return(Q.height??0)-(J.height??0)}function D$(J,Q){let[$,K]=AJ(J,Q);return(Math.atan2($,K)*180/Math.PI+360)%360}function Y$(J,Q){let $=J.lat*OJ,K=Q.lat*OJ,V=(Q.lat-J.lat)*OJ,W=(Q.lng-J.lng)*OJ,H=Math.sin(V/2)**2+Math.cos($)*Math.cos(K)*Math.sin(W/2)**2;return 2*XJ*Math.asin(Math.min(1,Math.sqrt(H)))}function P$(J,Q,$){let K=RJ(J.lng,J.lat,0),V=RJ(Q.lng,Q.lat,0),W=K[0]+(V[0]-K[0])*$,H=K[1]+(V[1]-K[1])*$,U=K[2]+(V[2]-K[2])*$,C=FJ(W,H,U),F=(J.height??0)+((Q.height??0)-(J.height??0))*$;return{lng:C.lng,lat:C.lat,height:F}}function Z$(J,Q){let $=0;for(let K=1;K<J.length;K++)$+=Q==="3d"?DQ(J[K-1],J[K]):cJ(J[K-1],J[K]);return $}function YQ(J){let Q=0,$=0;for(let W of J)Q+=W.lng,$+=W.lat;let K={lng:Q/J.length,lat:$/J.length,height:0},V=LJ(TJ(K),K.lng,K.lat);return J.map((W)=>{let[H,U]=ZJ(V,RJ(W.lng,W.lat,0));return[H,U]})}function X$(J){if(J.length<3)return 0;let Q=YQ(J),$=0;for(let K=0;K<Q.length;K++){let[V,W]=Q[K],[H,U]=Q[(K+1)%Q.length];$+=V*U-H*W}return Math.abs($)/2}function PQ(J,Q,$){let K=!1;for(let V=0,W=$.length-1;V<$.length;W=V++){let[H,U]=$[V],[C,F]=$[W];if(U>Q!==F>Q&&J<(C-H)*(Q-U)/(F-U)+H)K=!K}return K}function S$(J,Q=8192){let $={nx:0,ny:0,minLng:0,minLat:0,dLng:0,dLat:0,cellIndex:[]};if(J.length<3)return{centers:[],cellAreaM2:0,grid:$};let K=1/0,V=-1/0,W=1/0,H=-1/0;for(let X of J){if(X.lng<K)K=X.lng;if(X.lng>V)V=X.lng;if(X.lat<W)W=X.lat;if(X.lat>H)H=X.lat}let U=(W+H)/2,C=110540,F=111320*Math.cos(U*OJ),O=(V-K)*F,G=(H-W)*C;if(!(O>0)||!(G>0))return{centers:[],cellAreaM2:0,grid:$};let R=Math.max(Math.max(O,G)/128,0.25),B=Math.max(1,Math.ceil(O/R)),Z=Math.max(1,Math.ceil(G/R));while(B*Z>Q)R*=1.3,B=Math.max(1,Math.ceil(O/R)),Z=Math.max(1,Math.ceil(G/R));let _=R/F,D=R/C,S=J.map((X)=>[X.lng*F,X.lat*C]),j=[],E=[];for(let X=0;X<Z;X++){let w=W+(X+0.5)*D,q=w*C;for(let P=0;P<B;P++){let L=K+(P+0.5)*_;if(PQ(L*F,q,S))j.push({lng:L,lat:w}),E.push(X*B+P)}}return{centers:j,cellAreaM2:R*R,grid:{nx:B,ny:Z,minLng:K,minLat:W,dLng:_,dLat:D,cellIndex:E}}}function N$(J,Q,$,K){let V=[],W=(H,U,C,F)=>{let O=(K-H)/(U-H);return[C[0]+O*(F[0]-C[0]),C[1]+O*(F[1]-C[1])]};for(let H=0;H<$-1;H++)for(let U=0;U<Q-1;U++){let C=J[H*Q+U],F=J[H*Q+U+1],O=J[(H+1)*Q+U+1],G=J[(H+1)*Q+U];if(Number.isNaN(C)||Number.isNaN(F)||Number.isNaN(O)||Number.isNaN(G))continue;let R=[U,H],B=[U+1,H],Z=[U+1,H+1],_=[U,H+1],D=[];if(C<K!==F<K)D.push(W(C,F,R,B));if(F<K!==O<K)D.push(W(F,O,B,Z));if(O<K!==G<K)D.push(W(O,G,Z,_));if(G<K!==C<K)D.push(W(G,C,_,R));if(D.length===2)V.push([D[0],D[1]]);else if(D.length===4)V.push([D[0],D[1]]),V.push([D[2],D[3]])}return V}function _$(J,Q,$=12){let K=[];if(!(J>0)||!(Q>0))return{intervalM:Q,levels:K};let V=[1,2,5,10,20,50,100,200,500,1000],W=Q;for(let H of V)if(W=Q*H,J/W<=$)break;for(let H=W;H<=J+0.000000001;H+=W)K.push(H);return{intervalM:W,levels:K}}function q$(J){if(J.length<2)return 0;let Q=0;for(let $=0;$<J.length;$++)Q+=cJ(J[$],J[($+1)%J.length]);return Q}var lJ=Math.PI/180,ZQ=6378137,mJ=0.0033528106647474805,rJ=mJ*(2-mJ);function T$(J){let Q=[J.position.buffer];for(let $ of[J.rgb,J.intensity,J.classification,J.returns,J.flags,J.pointSourceId,J.gpsTime,J.scanAngle,J.modelScale,J.modelHeading,J.modelSymbol])if($)Q.push($.buffer);return Q}function A$(J){let Q=J.position.byteLength;for(let $ of[J.rgb,J.intensity,J.classification,J.returns,J.flags,J.pointSourceId,J.gpsTime,J.scanAngle,J.modelScale,J.modelHeading,J.modelSymbol])if($)Q+=$.byteLength;return Q}function j$(J,Q){let $=J.count,K=Q.enuFromEcef,V=K[0],W=K[4],H=K[8],U=K[12],C=K[1],F=K[5],O=K[9],G=K[13],R=K[2],B=K[6],Z=K[10],_=K[14],D=Q.nodeCenterEcef,S=V*D[0]+W*D[1]+H*D[2]+U,j=C*D[0]+F*D[1]+O*D[2]+G,E=R*D[0]+B*D[1]+Z*D[2]+_,X=Q.wkid===4326||Q.wkid===4979,w=Q.reproject,q=Q.geoidN,P=1/Q.grid,L=J.position,N=new Int32Array($*3),k=1/0,v=1/0,Y=1/0,T=-1/0,I=-1/0,M=-1/0;for(let A=0;A<$;A++){let z=A*3,y=L[z],f=L[z+1],r=L[z+2];if(!X||w){let DJ=w(y,f,r);y=DJ[0],f=DJ[1],r=DJ[2]}let p=y*lJ,h=f*lJ,x=Math.sin(h),l=Math.cos(h),c=Math.cos(p),d=Math.sin(p),g=r+q,u=ZQ/Math.sqrt(1-rJ*x*x),m=(u+g)*l*c,o=(u+g)*l*d,e=(u*(1-rJ)+g)*x,t=V*m+W*o+H*e+U,JJ=C*m+F*o+O*e+G,a=R*m+B*o+Z*e+_;if(t<k)k=t;if(t>T)T=t;if(JJ<v)v=JJ;if(JJ>I)I=JJ;if(a<Y)Y=a;if(a>M)M=a;N[z]=Math.round((t-S)*P),N[z+1]=Math.round((JJ-j)*P),N[z+2]=Math.round((a-E)*P)}let b;if(J.rgb)b=J.rgb;else if(J.r&&J.g&&J.b){b=new Uint16Array($*3);let{r:A,g:z,b:y}=J;for(let f=0;f<$;f++)b[f*3]=A[f],b[f*3+1]=z[f],b[f*3+2]=y[f]}return{count:$,position:N,scale:[Q.grid,Q.grid,Q.grid],offset:[S,j,E],enuMin:$>0?[k,v,Y]:[0,0,0],enuMax:$>0?[T,I,M]:[0,0,0],...b?{rgb:b}:{},...J.intensity?{intensity:J.intensity}:{},...J.classification?{classification:J.classification}:{},...J.returns?{returns:J.returns}:{},...J.flags?{flags:J.flags}:{},...J.pointSourceId?{pointSourceId:J.pointSourceId}:{},...J.gpsTime?{gpsTime:J.gpsTime}:{},...J.scanAngle?{scanAngle:J.scanAngle}:{}}}function w$(J,Q,$){let K=s($.enuFromEcef,$.tileTransform),V=$.scaleX*$.lngToMeters,W=$.scaleY*$.latToMeters;K[0]*=V,K[1]*=V,K[2]*=V,K[4]*=W,K[5]*=W,K[6]*=W;let H=K[0],U=K[4],C=K[8],F=K[12],O=K[1],G=K[5],R=K[9],B=K[13],Z=K[2],_=K[6],D=K[10],S=K[14],j=F,E=B,X=S,w=1/$.grid,q=new Int32Array(Q*3),P=1/0,L=1/0,N=1/0,k=-1/0,v=-1/0,Y=-1/0;for(let T=0;T<Q;T++){let I=T*3,M=J[I],b=J[I+1],A=J[I+2],z=H*M+U*b+C*A+F,y=O*M+G*b+R*A+B,f=Z*M+_*b+D*A+S;if(z<P)P=z;if(z>k)k=z;if(y<L)L=y;if(y>v)v=y;if(f<N)N=f;if(f>Y)Y=f;q[I]=Math.round((z-j)*w),q[I+1]=Math.round((y-E)*w),q[I+2]=Math.round((f-X)*w)}return{count:Q,position:q,scale:[$.grid,$.grid,$.grid],offset:[j,E,X],enuMin:Q>0?[P,L,N]:[0,0,0],enuMax:Q>0?[k,v,Y]:[0,0,0]}}function k$(J,Q){let $=J.count,K=s(Q.enuFromEcef,Q.tileTransform);if(J.rtcCenter!==void 0)K=s(K,QJ(J.rtcCenter[0],J.rtcCenter[1],J.rtcCenter[2]));let V=K[0],W=K[4],H=K[8],U=K[12],C=K[1],F=K[5],O=K[9],G=K[13],R=K[2],B=K[6],Z=K[10],_=K[14],D=U,S=G,j=_,E=1/Q.grid,X=J.positions,w=new Int32Array($*3),q=1/0,P=1/0,L=1/0,N=-1/0,k=-1/0,v=-1/0;for(let Y=0;Y<$;Y++){let T=Y*3,I=X[T],M=X[T+1],b=X[T+2],A=V*I+W*M+H*b+U,z=C*I+F*M+O*b+G,y=R*I+B*M+Z*b+_;if(A<q)q=A;if(A>N)N=A;if(z<P)P=z;if(z>k)k=z;if(y<L)L=y;if(y>v)v=y;w[T]=Math.round((A-D)*E),w[T+1]=Math.round((z-S)*E),w[T+2]=Math.round((y-j)*E)}return{count:$,position:w,scale:[Q.grid,Q.grid,Q.grid],offset:[D,S,j],enuMin:$>0?[q,P,L]:[D,S,j],enuMax:$>0?[N,k,v]:[D,S,j],...J.rgb!==void 0?{rgb:J.rgb}:{},...J.intensity!==void 0?{intensity:J.intensity}:{},...J.classification!==void 0?{classification:J.classification}:{}}}var WJ=6378137,wJ=0.0033528106647474805,sJ=wJ*(2-wJ),HJ=WJ*(1-wJ),XQ=(WJ*WJ-HJ*HJ)/(HJ*HJ),nJ=1/(2*Math.PI);function SQ(J,Q,$,K,V,W,H,U){let C=Math.atan2(Q,J),F=Math.hypot(J,Q),O=Math.atan2($*WJ,F*HJ),G=Math.sin(O),R=Math.cos(O),B=Math.atan2($+XQ*HJ*G*G*G,F-sJ*WJ*R*R*R),Z=Math.sin(B),_=Math.cos(B),D=F/_-WJ/Math.sqrt(1-sJ*Z*Z);H[U]=C*nJ+0.5-K,H[U+1]=0.5-Math.log(Math.tan(Math.PI/4+B/2))*nJ-V,H[U+2]=D/(SJ*_)-W}function iJ(J){if(J.rgba)return Math.ceil(J.rgba.data.byteLength*4/3);let Q=0;if(J.compressed)for(let $ of J.compressed.levels)Q+=$.data.byteLength;return Q}var jJ=new Float64Array(0);function b$(J,Q,$=[]){let K=J.primitives.length,V=Array(K);for(let L=0;L<K;L++)V[L]=CJ(Q.enuFromEcef,Q.tileTransform,J.primitives[L].nodeMatrix,Q.gltfUpAxis);let W=Array(K),H=1/0,U=1/0,C=1/0,F=-1/0,O=-1/0,G=-1/0;for(let L=0;L<K;L++){let N=V[L],k=J.primitives[L].positions,v=N[0],Y=N[4],T=N[8],I=N[12],M=N[1],b=N[5],A=N[9],z=N[13],y=N[2],f=N[6],r=N[10],p=N[14],h;if(K===1){if(jJ.length<k.length)jJ=new Float64Array(k.length);h=jJ}else h=new Float64Array(k.length);W[L]=h;for(let x=0;x<k.length;x+=3){let l=k[x],c=k[x+1],d=k[x+2],g=v*l+Y*c+T*d+I,u=M*l+b*c+A*d+z,m=y*l+f*c+r*d+p;if(h[x]=g,h[x+1]=u,h[x+2]=m,g<H)H=g;if(g>F)F=g;if(u<U)U=u;if(u>O)O=u;if(m<C)C=m;if(m>G)G=m}}let R=Number.isFinite(H),B=R?(H+F)/2:0,Z=R?(U+O)/2:0,_=R?(C+G)/2:0,D,S,j=0,E=0,X=0;if(Q.bakeMercator&&R){D=PJ(Q.enuFromEcef);let L=D[0]*B+D[4]*Z+D[8]*_+D[12],N=D[1]*B+D[5]*Z+D[9]*_+D[13],k=D[2]*B+D[6]*Z+D[10]*_+D[14],v=FJ(L,N,k),Y=_J({lng:v.lng,lat:v.lat},v.height);j=Y.x,E=Y.y,X=Y.z,S=[j,E,X]}let w=Array(K),q=0,P=-1;for(let L=0;L<K;L++){let N=J.primitives[L],k=V[L],v=W[L],Y=N.positions.length,T=new Float32Array(Y);for(let A=0;A<Y;A+=3)T[A]=v[A]-B,T[A+1]=v[A+1]-Z,T[A+2]=v[A+2]-_;let I;if(D!==void 0){let A=D[0],z=D[4],y=D[8],f=D[12],r=D[1],p=D[5],h=D[9],x=D[13],l=D[2],c=D[6],d=D[10],g=D[14];I=new Float32Array(Y);for(let u=0;u<Y;u+=3){let m=v[u],o=v[u+1],e=v[u+2],t=A*m+z*o+y*e+f,JJ=r*m+p*o+h*e+x,a=l*m+c*o+d*e+g;SQ(t,JJ,a,j,E,X,I,u)}}let M;if(N.normals!==void 0){let A=aJ(k),z=A[0],y=A[4],f=A[8],r=A[1],p=A[5],h=A[9],x=A[2],l=A[6],c=A[10],d=N.normals;M=new Float32Array(d.length);for(let g=0;g<d.length;g+=3){let u=d[g],m=d[g+1],o=d[g+2],e=z*u+y*m+f*o,t=r*u+p*m+h*o,JJ=x*u+l*m+c*o,a=Math.hypot(e,t,JJ)||1;M[g]=e/a,M[g+1]=t/a,M[g+2]=JJ/a}}let b=eJ(J.materials,N.materialIndex);if(w[L]={mode:N.mode,positions:T,material:b,...I!==void 0?{mercatorOffset:I}:{},...M!==void 0?{normals:M}:{},...N.uv0!==void 0?{uv0:N.uv0}:{},...N.color0!==void 0?{color0:N.color0}:{},...N.uvRegion!==void 0?{uvRegion:N.uvRegion}:{},...N.indices!==void 0?{indices:N.indices}:{},...N.featureIds!==void 0?{featureIds:N.featureIds}:{}},q+=T.byteLength+(I?.byteLength??0)+(M?.byteLength??0)+(N.uv0?.byteLength??0)+(N.color0?.byteLength??0)+(N.uvRegion?.byteLength??0)+(N.indices?.byteLength??0)+(N.featureIds?.byteLength??0),N.featureIds!==void 0)for(let A=0;A<N.featureIds.length;A++){let z=N.featureIds[A];if(z>P)P=z}}for(let L of $)q+=iJ(L);return{origin:[B,Z,_],...S!==void 0?{mercatorOrigin:S}:{},primitives:w,textures:$,featureCount:P>=0?P+1:0,bytes:q}}var oJ=YJ();function h$(J,Q=[],$={}){let K=$.upAxis==="z",V=$.scale??1,W=J.primitives.length,H=Array(W),U=0,C=-1;for(let F=0;F<W;F++){let O=J.primitives[F],G=K?O.nodeMatrix:CJ(oJ,oJ,O.nodeMatrix),R=G[0],B=G[4],Z=G[8],_=G[12],D=G[1],S=G[5],j=G[9],E=G[13],X=G[2],w=G[6],q=G[10],P=G[14],L=O.positions,N=new Float32Array(L.length);for(let Y=0;Y<L.length;Y+=3){let T=L[Y],I=L[Y+1],M=L[Y+2];N[Y]=(R*T+B*I+Z*M+_)*V,N[Y+1]=(D*T+S*I+j*M+E)*V,N[Y+2]=(X*T+w*I+q*M+P)*V}let k;if(O.normals!==void 0){let Y=aJ(G),T=Y[0],I=Y[4],M=Y[8],b=Y[1],A=Y[5],z=Y[9],y=Y[2],f=Y[6],r=Y[10],p=O.normals;k=new Float32Array(p.length);for(let h=0;h<p.length;h+=3){let x=p[h],l=p[h+1],c=p[h+2],d=T*x+I*l+M*c,g=b*x+A*l+z*c,u=y*x+f*l+r*c,m=Math.hypot(d,g,u)||1;k[h]=d/m,k[h+1]=g/m,k[h+2]=u/m}}let v=eJ(J.materials,O.materialIndex);if(H[F]={mode:O.mode,positions:N,material:v,...k!==void 0?{normals:k}:{},...O.uv0!==void 0?{uv0:O.uv0}:{},...O.color0!==void 0?{color0:O.color0}:{},...O.uvRegion!==void 0?{uvRegion:O.uvRegion}:{},...O.indices!==void 0?{indices:O.indices}:{},...O.featureIds!==void 0?{featureIds:O.featureIds}:{}},U+=N.byteLength+(k?.byteLength??0)+(O.uv0?.byteLength??0)+(O.color0?.byteLength??0)+(O.uvRegion?.byteLength??0)+(O.indices?.byteLength??0)+(O.featureIds?.byteLength??0),O.featureIds!==void 0)for(let Y=0;Y<O.featureIds.length;Y++){let T=O.featureIds[Y];if(T>C)C=T}}for(let F of Q)U+=iJ(F);return{origin:[0,0,0],primitives:H,textures:Q,featureCount:C>=0?C+1:0,bytes:U}}function aJ(J){let Q=new Float64Array(J);Q[12]=0,Q[13]=0,Q[14]=0;try{return gJ(PJ(Q))}catch{return Q}}function eJ(J,Q){if(Q!==void 0){let $=J[Q];if($!==void 0)return $}return fJ}function d$(J){let Q=[],$=(K)=>{if(K&&K.buffer instanceof ArrayBuffer&&!Q.includes(K.buffer))Q.push(K.buffer)};for(let K of J.primitives)$(K.positions),$(K.mercatorOffset),$(K.normals),$(K.uv0),$(K.color0),$(K.uvRegion),$(K.indices),$(K.featureIds);for(let K of J.textures){if(K.rgba)$(K.rgba.data);if(K.compressed)for(let V of K.compressed.levels)$(V.data);if(K.bitmap&&!Q.includes(K.bitmap))Q.push(K.bitmap)}for(let K of vJ(J))$(K.matrices);if(J.edges)$(J.edges.positions),$(J.edges.mercatorOffsets),$(J.edges.featureIds);return Q}function tJ(J){let{positions:Q,indices:$,featureIds:K}=J,V=$?$.length/3|0:Q.length/9|0;if(V===0)return null;let W=J.maxEdges??400000,H=Math.cos((J.creaseAngleDeg??25)*Math.PI/180),U=new Map,C=[],F=[],O=[],G=[],R=[],B=(Y)=>{let T=Q[Y*3],I=Q[Y*3+1],M=Q[Y*3+2],b=K?K[Y]:0,A=`${Math.round(T*1e4)},${Math.round(I*1e4)},${Math.round(M*1e4)},${b}`,z=U.get(A);if(z!==void 0)return z;let y=C.length;return U.set(A,y),C.push(T),F.push(I),O.push(M),G.push(b),R.push(Y),y},Z=new Map,_=[],D=[],S=[],j=[],E=[],X=[],w=[],q=(Y,T,I,M,b)=>{let A=Y<T?Y:T,z=Y<T?T:Y;if(z>=67108864)return;let y=A*67108864+z,f=Z.get(y);if(f===void 0){Z.set(y,_.length),_.push(A),D.push(z),S.push(I),j.push(M),E.push(b),X.push(1),w.push(!1);return}if(X[f]++,X[f]>2){w[f]=!0;return}if(S[f]*I+j[f]*M+E[f]*b<H)w[f]=!0};for(let Y=0;Y<V;Y++){let T=$?$[Y*3]:Y*3,I=$?$[Y*3+1]:Y*3+1,M=$?$[Y*3+2]:Y*3+2,b=Q[T*3],A=Q[T*3+1],z=Q[T*3+2],y=Q[I*3]-b,f=Q[I*3+1]-A,r=Q[I*3+2]-z,p=Q[M*3]-b,h=Q[M*3+1]-A,x=Q[M*3+2]-z,l=f*x-r*h,c=r*p-y*x,d=y*h-f*p,g=Math.hypot(l,c,d);if(!(g>0))continue;l/=g,c/=g,d/=g;let u=B(T),m=B(I),o=B(M);q(u,m,l,c,d),q(m,o,l,c,d),q(o,u,l,c,d)}let P=[];for(let Y=0;Y<_.length&&P.length<W;Y++)if(X[Y]===1||w[Y])P.push(Y);let L=P.length>=W;if(P.length===0)return null;let N=new Float32Array(P.length*6),k=K?new Uint32Array(P.length):void 0,v=new Uint32Array(P.length*2);for(let Y=0;Y<P.length;Y++){let T=P[Y],I=_[T],M=D[T];if(N[Y*6]=C[I],N[Y*6+1]=F[I],N[Y*6+2]=O[I],N[Y*6+3]=C[M],N[Y*6+4]=F[M],N[Y*6+5]=O[M],v[Y*2]=R[I],v[Y*2+1]=R[M],k)k[Y]=G[I]}return{positions:N,...k?{featureIds:k}:{},endpoints:v,count:P.length,truncated:L}}function c$(J,Q={}){let $=Q.maxEdges??400000,K=[],V=0,W=!1;for(let R of J){if(V>=$){W=!0;break}let B=tJ({positions:R.positions,...R.indices?{indices:R.indices}:{},...R.featureIds?{featureIds:R.featureIds}:{},...Q.creaseAngleDeg!==void 0?{creaseAngleDeg:Q.creaseAngleDeg}:{},maxEdges:$-V});if(!B)continue;W||=B.truncated;let Z;if(R.mercatorOffset){Z=new Float32Array(B.count*6);for(let _=0;_<B.count*2;_++){let D=B.endpoints[_];Z[_*3]=R.mercatorOffset[D*3],Z[_*3+1]=R.mercatorOffset[D*3+1],Z[_*3+2]=R.mercatorOffset[D*3+2]}}K.push({positions:B.positions,...Z?{mercator:Z}:{},...B.featureIds?{featureIds:B.featureIds}:{},count:B.count}),V+=B.count}if(V===0)return null;let H=K.every((R)=>R.mercator),U=K.every((R)=>R.featureIds),C=new Float32Array(V*6),F=H?new Float32Array(V*6):void 0,O=U?new Uint32Array(V):void 0,G=0;for(let R of K){if(C.set(R.positions,G*6),F&&R.mercator)F.set(R.mercator,G*6);if(O&&R.featureIds)O.set(R.featureIds,G);G+=R.count}return{positions:C,...F?{mercatorOffsets:F}:{},...O?{featureIds:O}:{},count:V,truncated:W}}var EJ=new Float64Array(0);function r$(J,Q){let $=0;for(let q of J)$+=q.positions.length/3|0;let K=J.map((q)=>CJ(Q.enuFromEcef,Q.tileTransform,q.nodeMatrix)),V=J.length===1,W=Array(J.length),H=1/0,U=1/0,C=1/0,F=-1/0,O=-1/0,G=-1/0;for(let q=0;q<J.length;q++){let P=K[q],L=J[q].positions,N=P[0],k=P[4],v=P[8],Y=P[12],T=P[1],I=P[5],M=P[9],b=P[13],A=P[2],z=P[6],y=P[10],f=P[14],r;if(V){if(EJ.length<L.length)EJ=new Float64Array(L.length);r=EJ}else r=new Float64Array(L.length);for(let p=0;p<L.length;p+=3){let h=L[p],x=L[p+1],l=L[p+2],c=N*h+k*x+v*l+Y,d=T*h+I*x+M*l+b,g=A*h+z*x+y*l+f;if(r[p]=c,r[p+1]=d,r[p+2]=g,c<H)H=c;if(c>F)F=c;if(d<U)U=d;if(d>O)O=d;if(g<C)C=g;if(g>G)G=g}W[q]=r}let R=$>0&&Number.isFinite(H),B=R?(H+F)/2:0,Z=R?(U+O)/2:0,_=R?(C+G)/2:0,D=1/Q.grid,S=new Int32Array($*3),j=0;for(let q=0;q<J.length;q++){let P=W[q],L=J[q].positions.length;for(let N=0;N<L;N+=3)S[j]=Math.round((P[N]-B)*D),S[j+1]=Math.round((P[N+1]-Z)*D),S[j+2]=Math.round((P[N+2]-_)*D),j+=3}let E=NQ(J,(q)=>q.rgb,$,Uint16Array),X=JQ(J,(q)=>q.intensity,$,Uint16Array),w=JQ(J,(q)=>q.classification,$,Uint8Array);return{count:$,position:S,scale:[Q.grid,Q.grid,Q.grid],offset:[B,Z,_],enuMin:R?[H,U,C]:[B,Z,_],enuMax:R?[F,O,G]:[B,Z,_],...E!==void 0?{rgb:E}:{},...X!==void 0?{intensity:X}:{},...w!==void 0?{classification:w}:{}}}function NQ(J,Q,$,K){if(J.length===0||J.some((H)=>Q(H)===void 0))return;if(J.length===1)return Q(J[0]);let V=new K($*3),W=0;for(let H of J){let U=Q(H);V.set(U,W),W+=U.length}return V}function JQ(J,Q,$,K){if(J.length===0||J.some((H)=>Q(H)===void 0))return;if(J.length===1)return Q(J[0]);let V=new K($),W=0;for(let H of J){let U=Q(H);V.set(U,W),W+=U.length}return V}function $J(J){if(J===null)return!1;if(typeof J==="boolean")return J;if(typeof J==="number")return J!==0&&!Number.isNaN(J);if(typeof J==="string")return J.length>0;return!0}function i(J){if(typeof J==="number")return J;if(typeof J==="boolean")return J?1:0;if(typeof J==="string"){let Q=Number(J);return Number.isNaN(Q)?NaN:Q}return NaN}function MJ(J,Q){if(typeof J==="number"||typeof Q==="number"){let $=i(J),K=i(Q);if(!Number.isNaN($)&&!Number.isNaN(K))return $===K}if(typeof J==="boolean"||typeof Q==="boolean")return $J(J)===$J(Q);return String(J)===String(Q)}function _Q(J,Q,$){if(J==="==")return MJ(Q,$);if(J==="!=")return!MJ(Q,$);let K=i(Q),V=i($),W=!Number.isNaN(K)&&!Number.isNaN(V),[H,U]=W?[K,V]:[String(Q),String($)];switch(J){case"<":return H<U;case"<=":return H<=U;case">":return H>U;case">=":return H>=U}return!1}function qQ(J){let Q="";for(let $ of J)if($==="%")Q+=".*";else if($==="_")Q+=".";else Q+=$.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`^${Q}$`)}function n(J,Q){switch(J.t){case"lit":return J.v;case"prop":return Q(J.name);case"not":return!$J(n(J.x,Q));case"neg":return-i(n(J.x,Q));case"cmp":return _Q(J.op,n(J.l,Q),n(J.r,Q));case"logic":{let $=$J(n(J.l,Q));if(J.op==="&&")return $?$J(n(J.r,Q)):!1;return $?!0:$J(n(J.r,Q))}case"arith":{let $=i(n(J.l,Q)),K=i(n(J.r,Q));switch(J.op){case"+":return $+K;case"-":return $-K;case"*":return $*K;case"/":return $/K;case"%":return $%K}return NaN}case"in":{let $=n(J.x,Q),K=J.items.some((V)=>MJ($,n(V,Q)));return J.neg?!K:K}case"like":{let $=n(J.x,Q),K=qQ(J.pat).test(String($));return J.neg?!K:K}case"isnull":{let $=n(J.x,Q),K=$===null||$===void 0||$==="";return J.neg?!K:K}case"ternary":return $J(n(J.c,Q))?n(J.a,Q):n(J.b,Q);case"color":return TQ(J,Q)}}var IQ={red:[255,0,0],green:[0,128,0],lime:[0,255,0],blue:[0,0,255],white:[255,255,255],black:[0,0,0],gray:[128,128,128],grey:[128,128,128],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255],orange:[255,165,0]};function LQ(J){let Q=J.replace("#",""),$=Q.length===3?Q.split("").map((K)=>K+K).join(""):Q;if($.length!==6||/[^0-9a-fA-F]/.test($))return null;return{r:parseInt($.slice(0,2),16)/255,g:parseInt($.slice(2,4),16)/255,b:parseInt($.slice(4,6),16)/255,a:1}}function TQ(J,Q){let $=J.args.map((K)=>n(K,Q));if(J.fn==="color"){let K=String($[0]??"");if(K.startsWith("#"))return LQ(K)??{r:1,g:1,b:1,a:1};let V=IQ[K.toLowerCase()],W=V?{r:V[0]/255,g:V[1]/255,b:V[2]/255,a:1}:{r:1,g:1,b:1,a:1};return $.length>1?{...W,a:i($[1])}:W}return{r:i($[0]??0)/255,g:i($[1]??0)/255,b:i($[2]??0)/255,a:J.fn==="rgba"?i($[3]??1):1}}function QQ(J){let Q=[],$=0,K=new Set(["AND","OR","NOT","IN","LIKE","IS","NULL","BETWEEN"]);while($<J.length){let V=J[$];if(/\s/.test(V)){$++;continue}if(V==="'"){let H=$+1,U="";while(H<J.length){if(J[H]==="'"&&J[H+1]==="'"){U+="'",H+=2;continue}if(J[H]==="'")break;U+=J[H],H++}Q.push({k:"str",v:U}),$=H+1;continue}if(V==='"'||V==="["){let H=V==='"'?'"':"]",U=$+1,C="";while(U<J.length&&J[U]!==H)C+=J[U],U++;Q.push({k:"id",v:C}),$=U+1;continue}if(/[0-9]/.test(V)||V==="."&&/[0-9]/.test(J[$+1]??"")){let H=$;while(H<J.length&&/[0-9.]/.test(J[H]))H++;Q.push({k:"num",v:J.slice($,H)}),$=H;continue}let W=J.slice($,$+2);if(W==="<="||W===">="||W==="<>"||W==="!="){Q.push({k:"op",v:W}),$+=2;continue}if(V==="="||V==="<"||V===">"){Q.push({k:"op",v:V}),$++;continue}if(V==="-"||V==="+"){Q.push({k:"op",v:V}),$++;continue}if(V==="("||V===")"||V===","){Q.push({k:V,v:V}),$++;continue}if(/[A-Za-z_]/.test(V)){let H=$;while(H<J.length&&/[A-Za-z0-9_]/.test(J[H]))H++;let U=J.slice($,H);$=H,Q.push(K.has(U.toUpperCase())?{k:U.toUpperCase(),v:U}:{k:"id",v:U});continue}throw Error(`sql-expr: unexpected '${V}' in "${J}"`)}return Q}function AQ(J){let Q=QQ(J),$=0,K=()=>Q[$],V=(G)=>{let R=Q[$++];if(G&&(!R||R.k!==G))throw Error(`sql-expr: expected ${G}`);return R},W=()=>{let G=K();if(!G)throw Error("sql-expr: unexpected end");if(G.k==="("){V("(");let R=F();return V(")"),R}if(G.k==="op"&&(G.v==="-"||G.v==="+")){V();let R=W();return G.v==="-"?{t:"neg",x:R}:R}if(G.k==="num")return V(),{t:"lit",v:Number(G.v)};if(G.k==="str")return V(),{t:"lit",v:G.v};if(G.k==="id")return V(),{t:"prop",name:G.v};throw Error(`sql-expr: unexpected '${G.v}'`)},H=()=>{let G=W(),R=K();if(R?.k==="op"&&R.v!=="-"&&R.v!=="+")return V(),{t:"cmp",op:R.v==="="?"==":R.v==="<>"?"!=":R.v,l:G,r:W()};if(R?.k==="IN"||R?.k==="NOT"&&Q[$+1]?.k==="IN"){let B=R.k==="NOT";if(B)V("NOT");V("IN"),V("(");let Z=[W()];while(K()?.k===",")V(","),Z.push(W());return V(")"),{t:"in",x:G,items:Z,neg:B}}if(R?.k==="IS"){V("IS");let B=K()?.k==="NOT";if(B)V("NOT");return V("NULL"),{t:"isnull",x:G,neg:B}}if(R?.k==="BETWEEN"||R?.k==="NOT"&&Q[$+1]?.k==="BETWEEN"){let B=R.k==="NOT";if(B)V("NOT");V("BETWEEN");let Z=W();V("AND");let _=W(),D={t:"logic",op:"&&",l:{t:"cmp",op:">=",l:G,r:Z},r:{t:"cmp",op:"<=",l:G,r:_}};return B?{t:"not",x:D}:D}if(R?.k==="LIKE"||R?.k==="NOT"&&Q[$+1]?.k==="LIKE"){let B=R.k==="NOT";if(B)V("NOT");V("LIKE");let Z=V("str").v;return{t:"like",x:G,pat:Z,neg:B}}return G},U=()=>{if(K()?.k==="NOT")return V("NOT"),{t:"not",x:U()};return H()},C=()=>{let G=U();while(K()?.k==="AND")V("AND"),G={t:"logic",op:"&&",l:G,r:U()};return G},F=()=>{let G=C();while(K()?.k==="OR")V("OR"),G={t:"logic",op:"||",l:G,r:C()};return G},O=F();if($!==Q.length)throw Error(`sql-expr: trailing tokens in "${J}"`);return O}function $Q(J){let Q=[],$=0;while($<J.length){let K=J[$];if(/\s/.test(K)){$++;continue}if(K==="$"&&J[$+1]==="{"){let H=$+2,U="";while(H<J.length&&J[H]!=="}")U+=J[H],H++;Q.push({k:"prop",v:U.trim()}),$=H+1;continue}if(K==="'"||K==='"'){let H=$+1,U="";while(H<J.length&&J[H]!==K)U+=J[H],H++;Q.push({k:"str",v:U}),$=H+1;continue}if(/[0-9]/.test(K)||K==="."&&/[0-9]/.test(J[$+1]??"")){let H=$;while(H<J.length&&/[0-9.]/.test(J[H]))H++;Q.push({k:"num",v:J.slice($,H)}),$=H;continue}let V=J.slice($,$+3);if(V==="==="||V==="!=="){Q.push({k:"op",v:V.slice(0,2)}),$+=3;continue}let W=J.slice($,$+2);if(["==","!=","<=",">=","&&","||"].includes(W)){Q.push({k:"op",v:W}),$+=2;continue}if("<>+-*/%!?:".includes(K)){Q.push({k:"op",v:K}),$++;continue}if(K==="("||K===")"||K===","){Q.push({k:K,v:K}),$++;continue}if(/[A-Za-z_]/.test(K)){let H=$;while(H<J.length&&/[A-Za-z0-9_]/.test(J[H]))H++;Q.push({k:"id",v:J.slice($,H)}),$=H;continue}throw Error(`style-expr: unexpected '${K}' in "${J}"`)}return Q}function jQ(J){let Q=$Q(J),$=0,K=()=>Q[$],V=(S)=>K()?.k==="op"&&K().v===S,W=(S)=>{let j=Q[$++];if(S&&(!j||j.k!==S))throw Error(`style-expr: expected ${S}`);return j},H=()=>{let S=K();if(!S)throw Error("style-expr: unexpected end");if(V("!"))return W(),{t:"not",x:U()};if(V("-"))return W(),{t:"neg",x:U()};if(S.k==="("){W("(");let j=_();return W(")"),j}if(S.k==="num")return W(),{t:"lit",v:Number(S.v)};if(S.k==="str")return W(),{t:"lit",v:S.v};if(S.k==="prop")return W(),{t:"prop",name:S.v};if(S.k==="id"){if(W(),S.v==="true"||S.v==="false")return{t:"lit",v:S.v==="true"};if(S.v==="null"||S.v==="NaN")return{t:"lit",v:S.v==="NaN"?NaN:null};if((S.v==="color"||S.v==="rgb"||S.v==="rgba"||S.v==="hsl")&&K()?.k==="("){W("(");let j=[];if(K()?.k!==")"){j.push(_());while(K()?.k===",")W(","),j.push(_())}return W(")"),{t:"color",fn:S.v,args:j}}return{t:"prop",name:S.v}}throw Error(`style-expr: unexpected '${S.v}'`)},U=()=>H(),C=(S,j)=>()=>{let E=S();while(K()?.k==="op"&&j.includes(K().v)){let X=W("op").v,w=S();E=X==="+"||X==="-"||X==="*"||X==="/"||X==="%"?{t:"arith",op:X,l:E,r:w}:X==="&&"||X==="||"?{t:"logic",op:X,l:E,r:w}:{t:"cmp",op:X,l:E,r:w}}return E},F=C(U,["*","/","%"]),O=C(F,["+","-"]),G=C(O,["<","<=",">",">="]),R=C(G,["==","!="]),B=C(R,["&&"]),Z=C(B,["||"]);function _(){let S=Z();if(V("?")){W("op");let j=_();W("op");let E=_();return{t:"ternary",c:S,a:j,b:E}}return S}let D=_();if($!==Q.length)throw Error(`style-expr: trailing tokens in "${J}"`);return D}function n$(J){let Q=AQ(J);return($)=>$J(n(Q,$))}function o$(J){let Q=jQ(J);return($)=>n(Q,$)}function i$(J,Q){let $=Q==="sql"?QQ(J):$Q(J),K=new Set;for(let V of $)if(Q==="sql"?V.k==="id":V.k==="prop")K.add(V.v);return[...K]}var e$=0.28209479177387814,kJ=1/(Math.SQRT2*511),UJ={sh1:9,sh2:15,sh3:21};function t$(J){switch(J){case 1:return UJ.sh1;case 2:return UJ.sh1+UJ.sh2;case 3:return UJ.sh1+UJ.sh2+UJ.sh3;default:return 0}}function JK(J,Q){return J/2**Q}function QK(J){return Math.exp(J/16-10)}function $K(J){return J/255}function wQ(J){return(J/255-0.5)/0.15}function KK(J){return 0.5+0.28209479177387814*wQ(J)}function VK(J){return(J-128)/128}function HK(J,Q,$,K){let V=Q*kJ,W=$*kJ,H=K*kJ,U=Math.sqrt(Math.max(0,1-V*V-W*W-H*H)),C=new Float32Array(4),F=[V,W,H],O=0;for(let G=0;G<4;G++)C[G]=G===J?U:F[O++];return C}function WK(J,Q,$,K){let V=Math.hypot(J,Q,$,K),W,H,U,C;if(V===0)W=0,H=0,U=0,C=1;else W=J/V,H=Q/V,U=$/V,C=K/V;let F=0,O=Math.abs(W);if(Math.abs(H)>O)F=1,O=Math.abs(H);if(Math.abs(U)>O)F=2,O=Math.abs(U);if(Math.abs(C)>O)F=3;let R=((F===0?W:F===1?H:F===2?U:C)<0?-1:1)*Math.SQRT2*511,B=(S)=>Math.min(511,Math.max(-511,Math.round(S*R))),Z=0,_=0,D=0;switch(F){case 0:Z=B(H),_=B(U),D=B(C);break;case 1:Z=B(W),_=B(U),D=B(C);break;case 2:Z=B(W),_=B(H),D=B(C);break;default:Z=B(W),_=B(H),D=B(U);break}return{rotIdx:F,a:Z,b:_,c:D}}function UK(J,Q,$){return J*Q+$}function GK(J){return J/65535}class EQ{minX=1/0;minY=1/0;minZ=1/0;maxX=-1/0;maxY=-1/0;maxZ=-1/0;hist=null;histBins=0;histCount=0;histMin=[0,0,0];histInv=[0,0,0];histWidth=[0,0,0];add(J){let{count:Q,x:$,y:K,z:V}=J,W=this.minX,H=this.minY,U=this.minZ,C=this.maxX,F=this.maxY,O=this.maxZ;for(let G=0;G<Q;G++){let R=$[G],B=K[G],Z=V[G];if(R<W)W=R;if(R>C)C=R;if(B<H)H=B;if(B>F)F=B;if(Z<U)U=Z;if(Z>O)O=Z}this.minX=W,this.minY=H,this.minZ=U,this.maxX=C,this.maxY=F,this.maxZ=O}get isEmpty(){return this.minX===1/0}beginHistogram(J=2048){if(this.isEmpty)return;this.histBins=J,this.hist=new Uint32Array(3*J),this.histCount=0;let Q=[this.minX,this.minY,this.minZ],$=[this.maxX,this.maxY,this.maxZ];for(let K=0;K<3;K++){let V=$[K]-Q[K]+1;this.histMin[K]=Q[K],this.histInv[K]=V>0?J/V:0,this.histWidth[K]=V/J}}addToHistogram(J){let Q=this.hist;if(!Q)return;let{count:$,x:K,y:V,z:W}=J,H=this.histBins,[U,C,F]=this.histMin,[O,G,R]=this.histInv,B=H-1;for(let Z=0;Z<$;Z++){let _=(K[Z]-U)*O|0,D=(V[Z]-C)*G|0,S=(W[Z]-F)*R|0;if(_>B)_=B;if(D>B)D=B;if(S>B)S=B;Q[_]++,Q[H+D]++,Q[2*H+S]++}this.histCount+=$}histQuantile(J,Q){let $=this.hist,K=this.histBins,V=J*K,W=Math.max(1,Math.ceil(Q*this.histCount)),H=0;for(let U=0;U<K;U++)if(H+=$[V+U],H>=W)return this.histMin[J]+(U+0.5)*this.histWidth[J];return this.histMin[J]+K*this.histWidth[J]}toLocalBounds(J){if(this.isEmpty)return null;let Q=J.kind==="splat"?1/2**J.fractionalBits:0,$=(G)=>J.kind==="splat"?Q:J.scale[G],K=(G)=>J.kind==="splat"?0:J.offset[G],V=[0,0,0],W=[0,0,0],H=[this.minX,this.minY,this.minZ],U=[this.maxX,this.maxY,this.maxZ];for(let G=0;G<3;G++){let R=H[G]*$(G)+K(G),B=U[G]*$(G)+K(G);V[G]=R<=B?R:B,W[G]=R<=B?B:R}if(!this.hist||this.histCount===0)return{min:V,max:W};let C=[0,0,0],F=[0,0,0],O=[0,0,0];for(let G=0;G<3;G++){let R=$(G),B=K(G),Z=this.histQuantile(G,0.05)*R+B,_=this.histQuantile(G,0.5)*R+B,D=this.histQuantile(G,0.95)*R+B;C[G]=Z<=D?Z:D,O[G]=Z<=D?D:Z,F[G]=_}return{min:V,max:W,p05:C,p50:F,p95:O}}reset(){this.minX=1/0,this.minY=1/0,this.minZ=1/0,this.maxX=-1/0,this.maxY=-1/0,this.maxZ=-1/0,this.hist=null,this.histBins=0,this.histCount=0}}function zJ(J){let Q=Float64Array.from(J).sort();return Q[Math.floor(Q.length/2)]}function OK(J,Q,$=1.5){let K=J.filter((X)=>X.kind==="splat"),V=K.reduce((X,w)=>X+w.count,0);if(V===0)return J;let W=Q.kind==="splat"?1/2**Q.fractionalBits:Q.scale[0],H=Q.kind==="splat"?1/2**Q.fractionalBits:Q.scale[1],U=Q.kind==="splat"?1/2**Q.fractionalBits:Q.scale[2],C=new Float64Array(V),F=new Float64Array(V),O=new Float64Array(V),G=0;for(let X of K)for(let w=0;w<X.count;w++,G++)C[G]=X.x[w]*W,F[G]=X.y[w]*H,O[G]=X.z[w]*U;let R=zJ(C),B=zJ(F),Z=zJ(O),_=new Float64Array(V);for(let X=0;X<V;X++){let w=C[X]-R,q=F[X]-B,P=O[X]-Z;_[X]=Math.sqrt(w*w+q*q+P*P)}let D=Float64Array.from(_).sort(),S=$*D[Math.floor(0.9*V)];if(D[V-1]<=S)return J;let j=[],E=0;for(let X of J){if(X.kind!=="splat"){j.push(X);continue}j.push(MQ(X,_,E,S)),E+=X.count}return j}function MQ(J,Q,$,K){let V=0;for(let P=0;P<J.count;P++)if(Q[$+P]<=K)V++;if(V===J.count)return J;let W=new Int32Array(V),H=new Int32Array(V),U=new Int32Array(V),C=new Uint8Array(V),F=new Uint8Array(V),O=new Uint8Array(V),G=new Uint8Array(V),R=new Uint8Array(V),B=new Int16Array(V),Z=new Int16Array(V),_=new Int16Array(V),D=new Uint8Array(V),S=new Uint8Array(V),j=new Uint8Array(V),E=J.sh1?new Uint8Array(V*9):void 0,X=J.sh2?new Uint8Array(V*15):void 0,w=J.sh3?new Uint8Array(V*21):void 0,q=0;for(let P=0;P<J.count;P++){if(Q[$+P]>K)continue;if(W[q]=J.x[P],H[q]=J.y[P],U[q]=J.z[P],C[q]=J.opacity[P],F[q]=J.scaleX[P],O[q]=J.scaleY[P],G[q]=J.scaleZ[P],R[q]=J.rotIdx[P],B[q]=J.rotA[P],Z[q]=J.rotB[P],_[q]=J.rotC[P],D[q]=J.colorR[P],S[q]=J.colorG[P],j[q]=J.colorB[P],E)E.set(J.sh1.subarray(P*9,P*9+9),q*9);if(X)X.set(J.sh2.subarray(P*15,P*15+15),q*15);if(w)w.set(J.sh3.subarray(P*21,P*21+21),q*21);q++}return{kind:"splat",count:V,x:W,y:H,z:U,opacity:C,scaleX:F,scaleY:O,scaleZ:G,rotIdx:R,rotA:B,rotB:Z,rotC:_,colorR:D,colorG:S,colorB:j,shDegree:J.shDegree,...E?{sh1:E}:{},...X?{sh2:X}:{},...w?{sh3:w}:{}}}export{S$ as volumeGridCells,F$ as verticalDelta,Q$ as upAxisVector,gJ as transpose,ZJ as transformPoint,W$ as transformPlaneRigid,mQ as transformDir,xQ as toFloat32Into,dQ as toFloat32,CJ as tileToEnu,VK as splatShCoeff,QK as splatScale,JK as splatPositionToMeters,$K as splatOpacity,wQ as splatColorDc,KK as splatBaseColorChannel,t$ as shCoeffsPerSplat,i$ as referencedProperties,Z$ as polylineLength,q$ as polygonPerimeterM,X$ as polygonAreaM2,UK as pointToWorld,H$ as planeFromPointNormal,V$ as planeDistance,pJ as placementMatrix,OQ as placementBasis,T$ as packedPointTransferables,A$ as packedPointBytes,d$ as packedMeshTransferables,j$ as packPointTileEnu,k$ as packPointTileEcef,h$ as packModelSpaceMesh,b$ as packMeshEnu,c$ as packMeshEdges,w$ as packI3sPointsEnu,r$ as packGltfPointsEnu,rQ as orthoInto,GK as normU16,lQ as multiplyVec4,s as multiply,$$ as modelPlacementMatrix,UQ as meterInMercatorCoordinateUnits,WQ as mercatorZfromAltitude,HQ as mercatorYfromLat,VQ as mercatorXfromLng,_J as mercatorFromLngLat,gQ as materializeFeatureProperties,cQ as mat3FromMat4,oQ as lngFromMercatorX,iQ as latFromMercatorY,PJ as invert,P$ as interpolatePosition,vJ as instanceGroupsOf,YJ as identity,cJ as horizontalDistance,Y$ as haversineDistance,vQ as gpuFormatTag,RJ as geodeticToEcef,QJ as fromTranslation,GJ as fromScaling,dJ as fromRotationZ,hJ as fromRotationY,bJ as fromRotationX,xJ as fromBasis,pQ as fromArrayLike,bQ as featureGetter,tJ as extractHardEdges,AJ as enuOffset,LJ as enuFromEcefMatrix,WK as encodeSmallestThree,FJ as ecefToGeodetic,DQ as distance3d,HK as decodeSmallestThree,OK as cullStraySplats,N$ as contourSegments,_$ as contourLevels,o$ as compileStyleExpression,n$ as compileSqlFilter,uQ as clone,NJ as circumferenceAtLatitude,D$ as bearingDeg,kQ as attributeSemantic,CQ as anchorPointSource,aQ as altitudeFromMercatorZ,FQ as Y_UP_TO_Z_UP,RQ as UP_AXIS_BASIS,e$ as SH_C0,UJ as SH_BAND_SIZES,kJ as ROT_INV,EQ as QuantBoundsAccumulator,GQ as MERCATOR_Y_FLIP,XJ as EARTH_RADIUS,SJ as EARTH_CIRCUMFERENCE,fJ as DEFAULT_MATERIAL,yJ as ColumnFeatureProperties};
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Filter / style **expression** evaluator — one AST + evaluator behind two front-ends:
3
+ * - **BSL SQL** (`compileSqlFilter`): Esri Building Scene Layer `filterExpression`
4
+ * (`Field=val AND Field2 IN (…) AND Field3 LIKE 'x%'`).
5
+ * - **3D Tiles style** (`compileStyleExpression`): the declarative styling language
6
+ * (`${prop} === 'x' && ${n} > 3 ? color('red') : color('gray')`).
7
+ *
8
+ * Both compile ONCE to a closure that's evaluated per feature against a {@link PropertyGetter}
9
+ * — used to drive the per-feature GPU style (show/hide/color) only when the filter changes, never
10
+ * per frame. Safe: a hand-written tokenizer + recursive-descent parser, no `eval`/`Function`.
11
+ */
12
+ /** A value an expression can evaluate to: a number, string, boolean, `null`, or a
13
+ * {@link StyleColor} (from a `color()`/`rgb()`/`rgba()` call). */
14
+ export type ExprValue = number | string | boolean | null | StyleColor;
15
+ /** An RGBA color in **0..1 linear channels** (not 0..255) — the result of a `color()`,
16
+ * `rgb()`, or `rgba()` call in a style expression. */
17
+ export interface StyleColor {
18
+ /** Red, 0..1. */
19
+ readonly r: number;
20
+ /** Green, 0..1. */
21
+ readonly g: number;
22
+ /** Blue, 0..1. */
23
+ readonly b: number;
24
+ /** Alpha, 0..1 (1 = opaque). */
25
+ readonly a: number;
26
+ }
27
+ /**
28
+ * Resolves a property/field name to its (already-decoded) feature value, or `null` when
29
+ * the feature has no such property. This is the per-feature data source a compiled
30
+ * expression is evaluated against.
31
+ *
32
+ * @param name - The property/field name referenced in the expression.
33
+ * @returns The feature's value for `name`, or `null` when absent.
34
+ * @see {@link featureGetter} to build one from a {@link FeatureProperties}.
35
+ */
36
+ export type PropertyGetter = (name: string) => number | string | boolean | null;
37
+ /**
38
+ * Compile an Esri Building Scene Layer (BSL) **SQL `filterExpression`** into a
39
+ * per-feature predicate. Compile once, then evaluate per feature against a
40
+ * {@link PropertyGetter} (only when the filter changes — never per frame).
41
+ *
42
+ * @remarks
43
+ * Supported SQL grammar (case-insensitive keywords):
44
+ * - Comparisons: `=`, `<>` / `!=`, `<`, `<=`, `>`, `>=` (numeric when both sides
45
+ * coerce to numbers, else string compare).
46
+ * - Boolean: `AND`, `OR`, `NOT`, and parentheses.
47
+ * - `Field IN (a, b, …)` and `Field NOT IN (…)`.
48
+ * - `Field LIKE 'pat'` / `NOT LIKE` where `%` matches any run and `_` matches one char.
49
+ * - `Field IS NULL` / `IS NOT NULL`. A published attribute table cannot distinguish an absent
50
+ * string from an empty one, so `''` counts as NULL; use `Field <> ''` when that matters.
51
+ * - `Field BETWEEN lo AND hi` / `NOT BETWEEN` (inclusive of both bounds).
52
+ * - Identifiers may be bare, `"quoted"`, or `[bracketed]`; string literals use single
53
+ * quotes with `''` as an escaped quote.
54
+ *
55
+ * @param expr - The BSL `filterExpression` SQL string.
56
+ * @returns A predicate `(get) => boolean`: `true` when the feature passes the filter.
57
+ * @throws Error on a syntax error (unexpected character / token, trailing tokens).
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * const pass = compileSqlFilter("BldgLevel >= 3 AND Discipline IN ('Architectural','Structural')");
62
+ * const visible = pass((name) => props.value(featureId, name)); // boolean
63
+ * ```
64
+ *
65
+ * @see {@link compileStyleExpression}, {@link referencedProperties}, {@link featureGetter}
66
+ */
67
+ export declare function compileSqlFilter(expr: string): (get: PropertyGetter) => boolean;
68
+ /**
69
+ * Compile a **3D Tiles declarative style expression** (the JS-like styling language)
70
+ * into a per-feature evaluator. Compile once; evaluate per feature against a
71
+ * {@link PropertyGetter}.
72
+ *
73
+ * @remarks
74
+ * Supported grammar:
75
+ * - Property reference: `${PropName}` (or a bare identifier).
76
+ * - Literals: numbers, single/double-quoted strings, `true`, `false`, `null`, `NaN`.
77
+ * - Operators: `+ - * / %`, `=== / == `, `!== / !=`, `< <= > >=`, `&& ||`, unary
78
+ * `! -`, and the `cond ? a : b` ternary, with parentheses.
79
+ * - Color constructors → {@link StyleColor} (0..1 channels): `color('red')`,
80
+ * `color('#rrggbb', alpha)`, `rgb(r,g,b)` and `rgba(r,g,b,a)` with `r/g/b` in 0..255.
81
+ *
82
+ * Use it for a 3D Tiles `show` expression (read the boolean result) or a `color`
83
+ * expression (read the {@link StyleColor}).
84
+ *
85
+ * @param expr - The style-expression source string.
86
+ * @returns An evaluator `(get) => ExprValue`: boolean for a `show` expression,
87
+ * {@link StyleColor} for a `color` expression, number/string otherwise.
88
+ * @throws Error on a syntax error (unexpected character / token, trailing tokens).
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * // show: hide below-grade levels
93
+ * const show = compileStyleExpression('${BldgLevel} >= 0');
94
+ * const visible = show(get) as boolean;
95
+ *
96
+ * // color: residential green, else gray
97
+ * const color = compileStyleExpression("${Use} === 'Residential' ? color('green') : color('#888888')");
98
+ * const { r, g, b, a } = color(get) as StyleColor; // 0..1 channels
99
+ * ```
100
+ *
101
+ * @see {@link compileSqlFilter}, {@link referencedProperties}, {@link StyleColor}
102
+ */
103
+ export declare function compileStyleExpression(expr: string): (get: PropertyGetter) => ExprValue;
104
+ /**
105
+ * List the property/field names an expression references, so a consumer fetches ONLY
106
+ * those columns per tile (a BSL filter on `BldgLevel` should not pull all ~30 BIM
107
+ * fields).
108
+ *
109
+ * @param expr - The expression source (same syntax as {@link compileSqlFilter} when
110
+ * `dialect === 'sql'`, or {@link compileStyleExpression} when `'style'`).
111
+ * @param dialect - `'sql'` collects bare identifiers; `'style'` collects `${prop}`
112
+ * references.
113
+ * @returns The de-duplicated referenced names, in first-seen order.
114
+ * @throws Error if `expr` fails to tokenize.
115
+ *
116
+ * @example
117
+ * ```ts
118
+ * referencedProperties("Discipline='Architectural' AND BldgLevel>2", 'sql');
119
+ * // → ['Discipline', 'BldgLevel']
120
+ * ```
121
+ */
122
+ export declare function referencedProperties(expr: string, dialect: 'sql' | 'style'): string[];
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@bitruvius/geo-core",
3
+ "version": "0.3.1",
4
+ "description": "Bitruvius geospatial SDK core: decoder/renderer/viewer-adapter contracts, geospatial math (ENU/ECEF/mercator), map-style expressions, and the dequantization reference. Builds on @bitruvius/foundation.",
5
+ "type": "module",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "bugs": {
8
+ "url": "https://github.com/bitruvius/support"
9
+ },
10
+ "homepage": "https://dev.bitruvius.com/sdks/js/",
11
+ "keywords": [
12
+ "bitruvius",
13
+ "geospatial",
14
+ "webgl2",
15
+ "sdk",
16
+ "contracts",
17
+ "mercator",
18
+ "ecef"
19
+ ],
20
+ "sideEffects": [
21
+ "./src/index.ts"
22
+ ],
23
+ "engines": {
24
+ "node": ">=18"
25
+ },
26
+ "main": "./dist/index.js",
27
+ "module": "./dist/index.js",
28
+ "types": "./dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js"
33
+ },
34
+ "./package.json": "./package.json"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "LICENSE",
39
+ "README.md"
40
+ ],
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "scripts": {
45
+ "build": "bun build ./src/index.ts --outdir dist --format esm --target browser --minify --external '@bitruvius/*' && tsc --emitDeclarationOnly",
46
+ "test": "bun test"
47
+ },
48
+ "dependencies": {
49
+ "@bitruvius/foundation": "^0.3.1"
50
+ }
51
+ }