1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//! Reusable geospatial visualization primitives.
//!
//! This module provides map-coupled, simulation-agnostic data structures
//! and layer implementations for scientific and analytical overlays:
//!
//! - [`GeoGrid`] -- georeferenced regular grid descriptor
//! - [`ScalarField2D`] -- grid-aligned scalar values with generation tracking
//! - [`ColorRamp`] / [`ColorStop`] -- interpolated colour transfer function
//! - [`LegendSpec`] / [`LabeledStop`] -- legend metadata for client-side UI
//! - [`ColumnInstance`] / [`ColumnInstanceSet`] -- instanced column descriptors
//! - [`PointInstance`] / [`PointInstanceSet`] -- point-cloud / scatter descriptors
//! - [`VisualizationOverlay`] -- tagged enum for `FrameOutput` integration
//! - [`GridScalarLayer`] -- flat colour grid overlay (`impl Layer`)
//! - [`GridExtrusionLayer`] -- extruded grid overlay (`impl Layer`)
//! - [`InstancedColumnLayer`] -- instanced column overlay (`impl Layer`)
//! - [`PointCloudLayer`] -- point-cloud / scatter overlay (`impl Layer`)
//!
//! ## Design
//!
//! All types are pure Rust data models with no Bevy or WGPU dependencies.
//! Renderers consume these via [`FrameOutput::visualization`] or by
//! downcasting through [`Layer::as_any`].
//!
//! ## Client ownership model
//!
//! Rustial provides the **rendering** and **geo-anchoring** side of the
//! visualization stack. The following concerns belong in the **host
//! application**, not in the map engine:
//!
//! | Concern | Belongs in |
//! |---------|-----------|
//! | Domain-specific data transforms (aggregation, filtering, binning) | Host application |
//! | Simulation adapters (CFD, traffic, weather model connectors) | Host application |
//! | Legend / colour-bar UI rendering | Host application (use [`LegendSpec`] metadata) |
//! | Time-series animation orchestration | Host application (`update_values()` per frame) |
//! | KPI dashboards and non-geographic widgets | Host application |
//! | Colour ramp presets for specific domains | Host application (construct [`ColorRamp`]) |
//!
//! Rustial provides:
//!
//! | Concern | Provided by engine |
//! |---------|-------------------|
//! | Geo-referenced grid/column/point placement | [`GeoGrid`], [`ColumnInstance`], [`PointInstance`] |
//! | GPU-accelerated rendering (flat grid, extruded grid, instanced columns, point cloud) | Both WGPU and Bevy renderers |
//! | Value-only retained updates (no GPU resource rebuild) | [`ScalarField2D::update_values`], [`ColumnInstanceSet`] / [`PointInstanceSet`] generation tracking |
//! | CPU picking with stable pick IDs | [`GeoGrid::cell_at_geo`], nearest-column/point picking |
//! | Legend metadata for host UI | [`LegendSpec`] |
//! | Colour transfer functions | [`ColorRamp`] / [`ColorStop`] |
//!
//! ## Retained-update contract
//!
//! The visualization pipeline distinguishes two update paths:
//!
//! - **Value-only update**: call [`ScalarField2D::update_values`] or replace
//! the [`ColumnInstanceSet`]/[`PointInstanceSet`] with a new generation.
//! Renderers detect the generation bump and update only the data texture
//! or instance buffer -- no vertex/index/bind-group rebuild.
//!
//! - **Structural update**: change grid geometry, colour ramp, or layer
//! identity. This triggers a full GPU resource rebuild.
//!
//! For large datasets, prefer value-only updates to stay within the 60 FPS
//! frame budget. Structural updates are amortised across frames but may
//! cause a one-frame stall for very large grids.
//!
//! ## Async preprocessing
//!
//! For very large visualization structural updates (>100k cells or >50k
//! instances), use [`AsyncVisualizationPipeline`](crate::AsyncVisualizationPipeline)
//! to offload heavy data preparation (binning, normalisation, colour ramp
//! evaluation) to a background thread. The pipeline integrates with the
//! existing [`DataTaskPool`](crate::DataTaskPool) infrastructure.
//!
//! ## Picking
//!
//! Grid layers support CPU-based picking via [`GeoGrid::cell_at_geo`].
//! Column layers support nearest-column picking. Both integrate with
//! [`MapState::pick`](crate::MapState::pick) through the standard
//! [`Layer`] trait.
pub use ;
pub use ;
pub use GeoGrid;
pub use GridExtrusionLayer;
pub use GridScalarLayer;
pub use InstancedColumnLayer;
pub use ;
pub use ;
pub use ;
pub use PointCloudLayer;
pub use ScalarField2D;