Skip to main content

polyscope_rs/
volume_grid.rs

1//! Volume grid registration and manipulation.
2//!
3//! Volume grids are regular 3D grids for visualizing scalar fields. They support
4//! node-centered and cell-centered data, with visualization modes including
5//! gridcubes (voxels) and isosurfaces (marching cubes).
6//!
7//! # Example
8//!
9//! ```no_run
10//! use polyscope_rs::*;
11//!
12//! fn main() -> Result<()> {
13//!     init()?;
14//!
15//!     // Create a 10x10x10 grid
16//!     let grid = register_volume_grid(
17//!         "my grid",
18//!         glam::UVec3::new(10, 10, 10),
19//!         Vec3::new(-1.0, -1.0, -1.0),
20//!         Vec3::new(1.0, 1.0, 1.0),
21//!     );
22//!
23//!     // Add a scalar field (e.g., signed distance to sphere)
24//!     let mut values = Vec::new();
25//!     for k in 0..10 {
26//!         for j in 0..10 {
27//!             for i in 0..10 {
28//!                 let p = Vec3::new(i as f32, j as f32, k as f32) / 9.0 * 2.0 - 1.0;
29//!                 values.push(p.length() - 0.5); // sphere SDF
30//!             }
31//!         }
32//!     }
33//!     grid.add_node_scalar_quantity("sdf", values);
34//!     grid.set_quantity_enabled("sdf", true);
35//!
36//!     show();
37//!     Ok(())
38//! }
39//! ```
40
41use crate::{Vec3, VolumeGrid, with_context_mut};
42use polyscope_core::structure::HasQuantities;
43use polyscope_structures::volume_grid::{
44    VolumeGridCellScalarQuantity, VolumeGridNodeScalarQuantity, VolumeGridVizMode,
45};
46
47/// Registers a volume grid with polyscope.
48pub fn register_volume_grid(
49    name: impl Into<String>,
50    node_dim: glam::UVec3,
51    bound_min: Vec3,
52    bound_max: Vec3,
53) -> VolumeGridHandle {
54    let name = name.into();
55    let grid = VolumeGrid::new(name.clone(), node_dim, bound_min, bound_max);
56
57    with_context_mut(|ctx| {
58        ctx.registry
59            .register(Box::new(grid))
60            .expect("failed to register volume grid");
61        ctx.update_extents();
62    });
63
64    VolumeGridHandle { name }
65}
66
67/// Registers a volume grid with uniform dimensions.
68pub fn register_volume_grid_uniform(
69    name: impl Into<String>,
70    dim: u32,
71    bound_min: Vec3,
72    bound_max: Vec3,
73) -> VolumeGridHandle {
74    register_volume_grid(name, glam::UVec3::splat(dim), bound_min, bound_max)
75}
76
77impl_structure_accessors! {
78    get_fn = get_volume_grid,
79    with_fn = with_volume_grid,
80    with_ref_fn = with_volume_grid_ref,
81    handle = VolumeGridHandle,
82    type_name = "VolumeGrid",
83    rust_type = VolumeGrid,
84    doc_name = "volume grid"
85}
86
87/// Handle for a registered volume grid.
88#[derive(Clone)]
89pub struct VolumeGridHandle {
90    name: String,
91}
92
93impl VolumeGridHandle {
94    /// Returns the name of this volume grid.
95    #[must_use]
96    pub fn name(&self) -> &str {
97        &self.name
98    }
99
100    /// Sets the edge color.
101    pub fn set_edge_color(&self, color: Vec3) -> &Self {
102        with_volume_grid(&self.name, |vg| {
103            vg.set_edge_color(color);
104        });
105        self
106    }
107
108    /// Sets the edge width.
109    pub fn set_edge_width(&self, width: f32) -> &Self {
110        with_volume_grid(&self.name, |vg| {
111            vg.set_edge_width(width);
112        });
113        self
114    }
115
116    /// Adds a node scalar quantity.
117    pub fn add_node_scalar_quantity(&self, name: &str, values: Vec<f32>) -> &Self {
118        with_volume_grid(&self.name, |vg| {
119            vg.add_node_scalar_quantity(name, values);
120        });
121        self
122    }
123
124    /// Adds a cell scalar quantity.
125    pub fn add_cell_scalar_quantity(&self, name: &str, values: Vec<f32>) -> &Self {
126        with_volume_grid(&self.name, |vg| {
127            vg.add_cell_scalar_quantity(name, values);
128        });
129        self
130    }
131
132    /// Sets the cube size factor (0 = no cubes, 1 = full size).
133    pub fn set_cube_size_factor(&self, factor: f32) -> &Self {
134        with_volume_grid(&self.name, |vg| {
135            vg.set_cube_size_factor(factor);
136        });
137        self
138    }
139
140    /// Enables a quantity by name.
141    pub fn set_quantity_enabled(&self, quantity_name: &str, enabled: bool) -> &Self {
142        with_volume_grid(&self.name, |vg| {
143            if let Some(q) = vg.get_quantity_mut(quantity_name) {
144                q.set_enabled(enabled);
145            }
146        });
147        self
148    }
149
150    /// Sets the visualization mode for a node scalar quantity.
151    pub fn set_node_scalar_viz_mode(&self, quantity_name: &str, mode: VolumeGridVizMode) -> &Self {
152        with_volume_grid(&self.name, |vg| {
153            if let Some(q) = vg.get_quantity_mut(quantity_name) {
154                if let Some(nsq) = q
155                    .as_any_mut()
156                    .downcast_mut::<VolumeGridNodeScalarQuantity>()
157                {
158                    nsq.set_viz_mode(mode);
159                }
160            }
161        });
162        self
163    }
164
165    /// Sets the isosurface level for a node scalar quantity.
166    pub fn set_isosurface_level(&self, quantity_name: &str, level: f32) -> &Self {
167        with_volume_grid(&self.name, |vg| {
168            if let Some(q) = vg.get_quantity_mut(quantity_name) {
169                if let Some(nsq) = q
170                    .as_any_mut()
171                    .downcast_mut::<VolumeGridNodeScalarQuantity>()
172                {
173                    nsq.set_isosurface_level(level);
174                }
175            }
176        });
177        self
178    }
179
180    /// Sets the isosurface color for a node scalar quantity.
181    pub fn set_isosurface_color(&self, quantity_name: &str, color: Vec3) -> &Self {
182        with_volume_grid(&self.name, |vg| {
183            if let Some(q) = vg.get_quantity_mut(quantity_name) {
184                if let Some(nsq) = q
185                    .as_any_mut()
186                    .downcast_mut::<VolumeGridNodeScalarQuantity>()
187                {
188                    nsq.set_isosurface_color(color);
189                }
190            }
191        });
192        self
193    }
194
195    /// Sets the color map for a quantity (node or cell scalar).
196    pub fn set_color_map(&self, quantity_name: &str, color_map: &str) -> &Self {
197        with_volume_grid(&self.name, |vg| {
198            if let Some(q) = vg.get_quantity_mut(quantity_name) {
199                if let Some(nsq) = q
200                    .as_any_mut()
201                    .downcast_mut::<VolumeGridNodeScalarQuantity>()
202                {
203                    nsq.set_color_map(color_map);
204                } else if let Some(csq) = q
205                    .as_any_mut()
206                    .downcast_mut::<VolumeGridCellScalarQuantity>()
207                {
208                    csq.set_color_map(color_map);
209                }
210            }
211        });
212        self
213    }
214}