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}