Skip to main content

rustial_engine/visualization/
mod.rs

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