use std::any::Any;
use super::overlay::ExtrusionParams;
use super::{ColorRamp, GeoGrid, ScalarField2D};
use crate::layer::{Layer, LayerId, LayerKind};
#[derive(Debug, Clone)]
pub struct GridExtrusionLayer {
id: LayerId,
name: String,
visible: bool,
opacity: f32,
z_index: i32,
pub grid: GeoGrid,
pub field: ScalarField2D,
pub ramp: ColorRamp,
pub params: ExtrusionParams,
}
impl GridExtrusionLayer {
pub fn new(
name: impl Into<String>,
grid: GeoGrid,
field: ScalarField2D,
ramp: ColorRamp,
) -> Self {
Self {
id: LayerId::next(),
name: name.into(),
visible: true,
opacity: 1.0,
z_index: 0,
grid,
field,
ramp,
params: ExtrusionParams::default(),
}
}
pub fn with_params(mut self, params: ExtrusionParams) -> Self {
self.params = params;
self
}
pub fn update_field(&mut self, data: Vec<f32>) {
self.field.update_values(data);
}
}
impl Layer for GridExtrusionLayer {
fn id(&self) -> LayerId {
self.id
}
fn name(&self) -> &str {
&self.name
}
fn kind(&self) -> LayerKind {
LayerKind::Visualization
}
fn visible(&self) -> bool {
self.visible
}
fn set_visible(&mut self, visible: bool) {
self.visible = visible;
}
fn opacity(&self) -> f32 {
self.opacity
}
fn set_opacity(&mut self, opacity: f32) {
self.opacity = opacity.clamp(0.0, 1.0);
}
fn z_index(&self) -> i32 {
self.z_index
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::visualization::ColorStop;
use rustial_math::GeoCoord;
fn test_ramp() -> ColorRamp {
ColorRamp::new(vec![
ColorStop {
value: 0.0,
color: [0.0, 0.0, 1.0, 1.0],
},
ColorStop {
value: 1.0,
color: [1.0, 0.0, 0.0, 1.0],
},
])
}
#[test]
fn grid_extrusion_layer_basics() {
let grid = GeoGrid::new(GeoCoord::from_lat_lon(0.0, 0.0), 4, 4, 100.0, 100.0);
let field = ScalarField2D::from_data(4, 4, vec![0.0; 16]);
let layer = GridExtrusionLayer::new("extrusion", grid, field, test_ramp());
assert_eq!(layer.name(), "extrusion");
assert!((layer.params.height_scale - 1.0).abs() < 1e-9);
assert!((layer.params.base_meters - 0.0).abs() < 1e-9);
}
#[test]
fn grid_extrusion_with_params() {
let grid = GeoGrid::new(GeoCoord::from_lat_lon(0.0, 0.0), 2, 2, 50.0, 50.0);
let field = ScalarField2D::from_data(2, 2, vec![1.0; 4]);
let layer =
GridExtrusionLayer::new("ext", grid, field, test_ramp()).with_params(ExtrusionParams {
height_scale: 10.0,
base_meters: 5.0,
});
assert!((layer.params.height_scale - 10.0).abs() < 1e-9);
assert!((layer.params.base_meters - 5.0).abs() < 1e-9);
}
}