/** * Selection (picking) state — spec: "Runtime Context API / Selection". * Converts a deck.gl PickingInfo into the documented, deck.gl-independent * ctx.selection shape (HU2: ctx never leaks deck.gl internals). */ import { type Tile3DPickMetadata } from "./tile3d-metadata"; export interface Selection { layerId: string; object: unknown; /** * The picked row's index in the layer's data. Columnar layers pick with NO * object (deck.gl's non-iterable data path only knows the index) — the * runtime materializes `object` from the columns at this index (om-map's * onSelectionChange), so downstream consumers still always see an object. */ index: number; /** * `[lng, lat]`, or `[lng, lat, z]` when deck actually ran the depth-pick * pass for this pick (some pickable layer in the scene has `pickable: * '3d'` — see terrain.ts and BIMLayer's own hover picking). Without that * pass deck's `info.coordinate` is the ray∩z=0-plane intersection, not a * real surface point, so a 2-length coordinate here is not "z=0 at this * point" — it's "no z was ever computed," and callers (the hover-tooltip * z field, this session's own concrete use) must treat it as absent, not * zero. */ coordinate: [number, number] | [number, number, number] | null; pixel: [number, number]; type: "hover" | "click"; /** * BIM feature-picking epic. Undefined for every pick except a * Tile3DLayer pick that resolved SOME metadata; `class`/`properties` * follow the same "ctx never leaks deck.gl internals" normalization as * the rest of this shape, `rawMetadata` is the deliberate escape hatch. * Two sources, most-specific-wins: * - Phase 1 (tile granularity, always active): 3D-Tiles-native * tileset/group/tile/content entities, merged with a single-feature * glTF EXT_structural_metadata property table when the content * resolves to exactly one feature. See src/tile3d-metadata.ts. * - Phase 2 (per-feature, only when `pick-features` resolved a specific * vertex-level feature): overrides Phase 1's properties/class/guid * with the picked feature's own row from the same property table, * still layered on top of Phase 1's broader tile-level context. See * src/layers/feature-mesh-layer.ts. */ properties?: Record; class?: string | null; /** Best-effort identity (IFC GlobalId / gml:id / guid), from either Phase 1's tile-granularity merge or Phase 2's per-feature row — see tile3d-metadata.ts's findGuidLike. Undefined when nothing matched. */ guid?: string | null; /** The picked vertex-level feature ID — only set by Phase 2's per-vertex picking; undefined for a Phase 1 tile-granularity pick. TILE-LOCAL: each tile's property table indexes 0..n-1, so the same number exists in every tile of a grid-tiled model — use `featureKey` to identify an element across tiles/models. */ featureId?: number; /** Stable cross-tile identity for a Phase 2 pick: the element's own guid when the table carries one (IFC GlobalId / gml:id), else `#`. Undefined when no per-feature pick resolved. */ featureKey?: string; rawMetadata?: Tile3DPickMetadata["rawMetadata"]; } interface PickingInfoLike { layer?: { id: string; } | null; object?: unknown; index?: number; coordinate?: number[]; x: number; y: number; /** Tile3DLayer's own getPickingInfo always sets this (undefined on a miss) — see tile3d-metadata.ts. */ sourceTile?: unknown; /** Set by src/layers/feature-mesh-layer.ts's SinglePrimitiveFeatureLayer.getPickingInfo when pick-features resolved a specific vertex-level feature — takes precedence over the tile-granularity fallback below. */ featureId?: number; properties?: Record; class?: string | null; guid?: string | null; } export declare function toSelection(info: PickingInfoLike, type: "hover" | "click", resolveLayerId?: (renderedId: string) => string): Selection | null; export {};