Skip to main content

polyscope_rs/
point_cloud.rs

1//! Point cloud registration and manipulation.
2//!
3//! Point clouds are sets of points in 3D space, rendered as spheres.
4//! This module provides functions to register point clouds and add
5//! quantities (scalar, vector, color) to them.
6//!
7//! # Example
8//!
9//! ```no_run
10//! use polyscope_rs::*;
11//!
12//! fn main() -> Result<()> {
13//!     init()?;
14//!
15//!     let points = vec![
16//!         Vec3::new(0.0, 0.0, 0.0),
17//!         Vec3::new(1.0, 0.0, 0.0),
18//!         Vec3::new(0.5, 1.0, 0.0),
19//!     ];
20//!
21//!     let pc = register_point_cloud("my points", points);
22//!     pc.add_scalar_quantity("height", vec![0.0, 0.0, 1.0]);
23//!
24//!     show();
25//!     Ok(())
26//! }
27//! ```
28
29use crate::{PointCloud, Vec3, with_context_mut};
30
31/// Registers a point cloud with polyscope.
32///
33/// Creates a new point cloud structure from the given points and registers
34/// it with the global state. Returns a handle for adding quantities and
35/// configuring appearance.
36///
37/// # Arguments
38///
39/// * `name` - Unique name for this point cloud
40/// * `points` - Vector of 3D point positions
41///
42/// # Panics
43///
44/// Panics if a structure with the same name already exists.
45///
46/// # Example
47///
48/// ```no_run
49/// use polyscope_rs::*;
50///
51/// init().unwrap();
52/// let pc = register_point_cloud("my points", vec![Vec3::ZERO, Vec3::X, Vec3::Y]);
53/// pc.add_scalar_quantity("values", vec![0.0, 0.5, 1.0]);
54/// ```
55pub fn register_point_cloud(name: impl Into<String>, points: Vec<Vec3>) -> PointCloudHandle {
56    let name = name.into();
57    let point_cloud = PointCloud::new(name.clone(), points);
58
59    with_context_mut(|ctx| {
60        ctx.registry
61            .register(Box::new(point_cloud))
62            .expect("failed to register point cloud");
63        ctx.update_extents();
64    });
65
66    PointCloudHandle { name }
67}
68
69impl_structure_accessors! {
70    get_fn = get_point_cloud,
71    with_fn = with_point_cloud,
72    with_ref_fn = with_point_cloud_ref,
73    handle = PointCloudHandle,
74    type_name = "PointCloud",
75    rust_type = PointCloud,
76    doc_name = "point cloud"
77}
78
79/// Handle for a registered point cloud.
80///
81/// This handle provides methods to add quantities and configure the
82/// appearance of a point cloud. Methods return `&Self` to allow chaining.
83///
84/// # Example
85///
86/// ```no_run
87/// use polyscope_rs::*;
88///
89/// init().unwrap();
90/// register_point_cloud("pts", vec![Vec3::ZERO, Vec3::X])
91///     .add_scalar_quantity("height", vec![0.0, 1.0])
92///     .add_vector_quantity("velocity", vec![Vec3::X, Vec3::Y]);
93/// ```
94#[derive(Clone)]
95pub struct PointCloudHandle {
96    name: String,
97}
98
99impl PointCloudHandle {
100    /// Returns the name of this point cloud.
101    #[must_use]
102    pub fn name(&self) -> &str {
103        &self.name
104    }
105
106    /// Adds a scalar quantity to this point cloud.
107    ///
108    /// Scalar quantities assign a single value to each point, visualized
109    /// using a colormap. The values vector must have the same length as
110    /// the number of points.
111    ///
112    /// # Arguments
113    ///
114    /// * `name` - Name for this quantity (shown in UI)
115    /// * `values` - One scalar value per point
116    pub fn add_scalar_quantity(&self, name: &str, values: Vec<f32>) -> &Self {
117        with_context_mut(|ctx| {
118            if let Some(pc) = ctx.registry.get_mut("PointCloud", &self.name) {
119                if let Some(pc) = (pc as &mut dyn std::any::Any).downcast_mut::<PointCloud>() {
120                    pc.add_scalar_quantity(name, values);
121                }
122            }
123        });
124        self
125    }
126
127    /// Adds a vector quantity to this point cloud.
128    ///
129    /// Vector quantities display an arrow at each point. Vectors are
130    /// automatically scaled based on scene size. The vectors array must
131    /// have the same length as the number of points.
132    ///
133    /// # Arguments
134    ///
135    /// * `name` - Name for this quantity (shown in UI)
136    /// * `vectors` - One 3D vector per point
137    pub fn add_vector_quantity(&self, name: &str, vectors: Vec<Vec3>) -> &Self {
138        with_context_mut(|ctx| {
139            if let Some(pc) = ctx.registry.get_mut("PointCloud", &self.name) {
140                if let Some(pc) = (pc as &mut dyn std::any::Any).downcast_mut::<PointCloud>() {
141                    pc.add_vector_quantity(name, vectors);
142                }
143            }
144        });
145        self
146    }
147
148    /// Adds a color quantity to this point cloud.
149    ///
150    /// Color quantities assign an RGB color to each point. The colors
151    /// vector must have the same length as the number of points.
152    /// Components should be in range [0, 1].
153    ///
154    /// # Arguments
155    ///
156    /// * `name` - Name for this quantity (shown in UI)
157    /// * `colors` - One RGB color (Vec3) per point
158    pub fn add_color_quantity(&self, name: &str, colors: Vec<Vec3>) -> &Self {
159        with_context_mut(|ctx| {
160            if let Some(pc) = ctx.registry.get_mut("PointCloud", &self.name) {
161                if let Some(pc) = (pc as &mut dyn std::any::Any).downcast_mut::<PointCloud>() {
162                    pc.add_color_quantity(name, colors);
163                }
164            }
165        });
166        self
167    }
168}