Skip to main content

polyscope_structures/surface_mesh/
quantity_methods.rs

1//! Quantity management methods for surface meshes.
2//!
3//! This module contains methods for adding and accessing quantities on surface meshes:
4//! - Scalar quantities (vertex and face)
5//! - Color quantities (vertex and face, RGB and RGBA)
6//! - Vector quantities (vertex and face)
7//! - Parameterization quantities (vertex and corner UV)
8//! - Intrinsic vector quantities (vertex and face, with tangent basis)
9//! - One-form quantities (edge-based differential forms)
10
11use glam::{Vec2, Vec3, Vec4};
12use polyscope_core::quantity::QuantityKind;
13use polyscope_core::structure::{HasQuantities, Structure};
14
15use super::{
16    MeshCornerParameterizationQuantity, MeshFaceColorQuantity, MeshFaceIntrinsicVectorQuantity,
17    MeshFaceScalarQuantity, MeshFaceVectorQuantity, MeshOneFormQuantity, MeshVertexColorQuantity,
18    MeshVertexIntrinsicVectorQuantity, MeshVertexParameterizationQuantity,
19    MeshVertexScalarQuantity, MeshVertexVectorQuantity, SurfaceMesh,
20};
21
22impl SurfaceMesh {
23    // === Quantity add methods ===
24
25    /// Adds a vertex scalar quantity to this mesh.
26    pub fn add_vertex_scalar_quantity(
27        &mut self,
28        name: impl Into<String>,
29        values: Vec<f32>,
30    ) -> &mut Self {
31        let quantity = MeshVertexScalarQuantity::new(name, self.name.clone(), values);
32        self.add_quantity(Box::new(quantity));
33        self
34    }
35
36    /// Adds a face scalar quantity to this mesh.
37    pub fn add_face_scalar_quantity(
38        &mut self,
39        name: impl Into<String>,
40        values: Vec<f32>,
41    ) -> &mut Self {
42        let quantity = MeshFaceScalarQuantity::new(name, self.name.clone(), values);
43        self.add_quantity(Box::new(quantity));
44        self
45    }
46
47    /// Adds a vertex color quantity to this mesh (RGB, alpha defaults to 1.0).
48    pub fn add_vertex_color_quantity(
49        &mut self,
50        name: impl Into<String>,
51        colors: Vec<Vec3>,
52    ) -> &mut Self {
53        let quantity = MeshVertexColorQuantity::new(name, self.name.clone(), colors);
54        self.add_quantity(Box::new(quantity));
55        self
56    }
57
58    /// Adds a vertex color quantity with explicit per-vertex RGBA alpha values.
59    pub fn add_vertex_color_quantity_with_alpha(
60        &mut self,
61        name: impl Into<String>,
62        colors: Vec<Vec4>,
63    ) -> &mut Self {
64        let quantity = MeshVertexColorQuantity::new_with_alpha(name, self.name.clone(), colors);
65        self.add_quantity(Box::new(quantity));
66        self
67    }
68
69    /// Adds a face color quantity to this mesh (RGB, alpha defaults to 1.0).
70    pub fn add_face_color_quantity(
71        &mut self,
72        name: impl Into<String>,
73        colors: Vec<Vec3>,
74    ) -> &mut Self {
75        let quantity = MeshFaceColorQuantity::new(name, self.name.clone(), colors);
76        self.add_quantity(Box::new(quantity));
77        self
78    }
79
80    /// Adds a face color quantity with explicit per-face RGBA alpha values.
81    pub fn add_face_color_quantity_with_alpha(
82        &mut self,
83        name: impl Into<String>,
84        colors: Vec<Vec4>,
85    ) -> &mut Self {
86        let quantity = MeshFaceColorQuantity::new_with_alpha(name, self.name.clone(), colors);
87        self.add_quantity(Box::new(quantity));
88        self
89    }
90
91    /// Adds a vertex vector quantity to this mesh.
92    ///
93    /// Arrow length and radius are auto-scaled based on mesh extent and vector magnitudes.
94    pub fn add_vertex_vector_quantity(
95        &mut self,
96        name: impl Into<String>,
97        vectors: Vec<Vec3>,
98    ) -> &mut Self {
99        let mut quantity = MeshVertexVectorQuantity::new(name, self.name.clone(), vectors);
100        quantity.auto_scale(self.length_scale());
101        self.add_quantity(Box::new(quantity));
102        self
103    }
104
105    /// Adds a face vector quantity to this mesh.
106    ///
107    /// Arrow length and radius are auto-scaled based on mesh extent and vector magnitudes.
108    pub fn add_face_vector_quantity(
109        &mut self,
110        name: impl Into<String>,
111        vectors: Vec<Vec3>,
112    ) -> &mut Self {
113        let mut quantity = MeshFaceVectorQuantity::new(name, self.name.clone(), vectors);
114        quantity.auto_scale(self.length_scale());
115        self.add_quantity(Box::new(quantity));
116        self
117    }
118
119    /// Adds a vertex parameterization (UV) quantity to this mesh.
120    pub fn add_vertex_parameterization_quantity(
121        &mut self,
122        name: impl Into<String>,
123        coords: Vec<Vec2>,
124    ) -> &mut Self {
125        let quantity = MeshVertexParameterizationQuantity::new(name, self.name.clone(), coords);
126        self.add_quantity(Box::new(quantity));
127        self
128    }
129
130    /// Adds a corner parameterization (UV) quantity to this mesh.
131    pub fn add_corner_parameterization_quantity(
132        &mut self,
133        name: impl Into<String>,
134        coords: Vec<Vec2>,
135    ) -> &mut Self {
136        let quantity = MeshCornerParameterizationQuantity::new(name, self.name.clone(), coords);
137        self.add_quantity(Box::new(quantity));
138        self
139    }
140
141    /// Adds a vertex intrinsic vector quantity with explicit tangent basis.
142    ///
143    /// Arrow length and radius are auto-scaled based on mesh extent and vector magnitudes.
144    pub fn add_vertex_intrinsic_vector_quantity(
145        &mut self,
146        name: impl Into<String>,
147        vectors: Vec<Vec2>,
148        basis_x: Vec<Vec3>,
149        basis_y: Vec<Vec3>,
150    ) -> &mut Self {
151        let mut quantity = MeshVertexIntrinsicVectorQuantity::new(
152            name,
153            self.name.clone(),
154            vectors,
155            basis_x,
156            basis_y,
157        );
158        quantity.auto_scale(self.length_scale());
159        self.add_quantity(Box::new(quantity));
160        self
161    }
162
163    /// Adds a vertex intrinsic vector quantity with auto-computed tangent basis.
164    pub fn add_vertex_intrinsic_vector_quantity_auto(
165        &mut self,
166        name: impl Into<String>,
167        vectors: Vec<Vec2>,
168    ) -> &mut Self {
169        let (bx, by) = self.compute_vertex_tangent_basis();
170        self.add_vertex_intrinsic_vector_quantity(name, vectors, bx, by)
171    }
172
173    /// Adds a face intrinsic vector quantity with explicit tangent basis.
174    ///
175    /// Arrow length and radius are auto-scaled based on mesh extent and vector magnitudes.
176    pub fn add_face_intrinsic_vector_quantity(
177        &mut self,
178        name: impl Into<String>,
179        vectors: Vec<Vec2>,
180        basis_x: Vec<Vec3>,
181        basis_y: Vec<Vec3>,
182    ) -> &mut Self {
183        let mut quantity = MeshFaceIntrinsicVectorQuantity::new(
184            name,
185            self.name.clone(),
186            vectors,
187            basis_x,
188            basis_y,
189        );
190        quantity.auto_scale(self.length_scale());
191        self.add_quantity(Box::new(quantity));
192        self
193    }
194
195    /// Adds a face intrinsic vector quantity with auto-computed tangent basis.
196    pub fn add_face_intrinsic_vector_quantity_auto(
197        &mut self,
198        name: impl Into<String>,
199        vectors: Vec<Vec2>,
200    ) -> &mut Self {
201        let (bx, by) = self.compute_face_tangent_basis();
202        self.add_face_intrinsic_vector_quantity(name, vectors, bx, by)
203    }
204
205    /// Adds a one-form quantity to this mesh.
206    ///
207    /// A one-form assigns a scalar value to each edge, rendered as arrows
208    /// at edge midpoints. The `orientations` array specifies the sign convention
209    /// for each edge (true = canonical low→high vertex direction).
210    /// Arrow length and radius are auto-scaled based on mesh extent and edge flow magnitudes.
211    pub fn add_one_form_quantity(
212        &mut self,
213        name: impl Into<String>,
214        values: Vec<f32>,
215        orientations: Vec<bool>,
216    ) -> &mut Self {
217        let mut quantity = MeshOneFormQuantity::new(name, self.name.clone(), values, orientations);
218        quantity.auto_scale(self.length_scale(), &self.vertices, &self.edges);
219        self.add_quantity(Box::new(quantity));
220        self
221    }
222
223    // === Active quantity accessors ===
224
225    /// Returns the currently active vertex scalar quantity, if any.
226    #[must_use]
227    pub fn active_vertex_scalar_quantity(&self) -> Option<&MeshVertexScalarQuantity> {
228        for q in &self.quantities {
229            if q.is_enabled() && q.kind() == QuantityKind::Scalar {
230                if let Some(sq) = q.as_any().downcast_ref::<MeshVertexScalarQuantity>() {
231                    return Some(sq);
232                }
233            }
234        }
235        None
236    }
237
238    /// Returns the currently active face scalar quantity, if any.
239    #[must_use]
240    pub fn active_face_scalar_quantity(&self) -> Option<&MeshFaceScalarQuantity> {
241        for q in &self.quantities {
242            if q.is_enabled() && q.kind() == QuantityKind::Scalar {
243                if let Some(sq) = q.as_any().downcast_ref::<MeshFaceScalarQuantity>() {
244                    return Some(sq);
245                }
246            }
247        }
248        None
249    }
250
251    /// Returns the currently active vertex color quantity, if any.
252    #[must_use]
253    pub fn active_vertex_color_quantity(&self) -> Option<&MeshVertexColorQuantity> {
254        for q in &self.quantities {
255            if q.is_enabled() && q.kind() == QuantityKind::Color {
256                if let Some(cq) = q.as_any().downcast_ref::<MeshVertexColorQuantity>() {
257                    return Some(cq);
258                }
259            }
260        }
261        None
262    }
263
264    /// Returns the currently active face color quantity, if any.
265    #[must_use]
266    pub fn active_face_color_quantity(&self) -> Option<&MeshFaceColorQuantity> {
267        for q in &self.quantities {
268            if q.is_enabled() && q.kind() == QuantityKind::Color {
269                if let Some(cq) = q.as_any().downcast_ref::<MeshFaceColorQuantity>() {
270                    return Some(cq);
271                }
272            }
273        }
274        None
275    }
276
277    /// Returns the currently active vertex vector quantity (immutable), if any.
278    #[must_use]
279    pub fn active_vertex_vector_quantity(&self) -> Option<&MeshVertexVectorQuantity> {
280        for q in &self.quantities {
281            if q.is_enabled() && q.kind() == QuantityKind::Vector {
282                if let Some(vq) = q.as_any().downcast_ref::<MeshVertexVectorQuantity>() {
283                    return Some(vq);
284                }
285            }
286        }
287        None
288    }
289
290    /// Returns the currently active vertex vector quantity (mutable), if any.
291    pub fn active_vertex_vector_quantity_mut(&mut self) -> Option<&mut MeshVertexVectorQuantity> {
292        for q in &mut self.quantities {
293            if q.is_enabled() && q.kind() == QuantityKind::Vector {
294                if let Some(vq) = q.as_any_mut().downcast_mut::<MeshVertexVectorQuantity>() {
295                    return Some(vq);
296                }
297            }
298        }
299        None
300    }
301
302    /// Returns the currently active face vector quantity (immutable), if any.
303    #[must_use]
304    pub fn active_face_vector_quantity(&self) -> Option<&MeshFaceVectorQuantity> {
305        for q in &self.quantities {
306            if q.is_enabled() && q.kind() == QuantityKind::Vector {
307                if let Some(vq) = q.as_any().downcast_ref::<MeshFaceVectorQuantity>() {
308                    return Some(vq);
309                }
310            }
311        }
312        None
313    }
314
315    /// Returns the currently active face vector quantity (mutable), if any.
316    pub fn active_face_vector_quantity_mut(&mut self) -> Option<&mut MeshFaceVectorQuantity> {
317        for q in &mut self.quantities {
318            if q.is_enabled() && q.kind() == QuantityKind::Vector {
319                if let Some(vq) = q.as_any_mut().downcast_mut::<MeshFaceVectorQuantity>() {
320                    return Some(vq);
321                }
322            }
323        }
324        None
325    }
326
327    /// Computes face centroids (average of face vertices).
328    #[must_use]
329    pub fn face_centroids(&self) -> Vec<Vec3> {
330        self.faces
331            .iter()
332            .map(|face| {
333                if face.is_empty() {
334                    return Vec3::ZERO;
335                }
336                let sum: Vec3 = face.iter().map(|&i| self.vertices[i as usize]).sum();
337                sum / face.len() as f32
338            })
339            .collect()
340    }
341
342    /// Returns the currently active vertex parameterization quantity, if any.
343    #[must_use]
344    pub fn active_vertex_parameterization_quantity(
345        &self,
346    ) -> Option<&MeshVertexParameterizationQuantity> {
347        for q in &self.quantities {
348            if q.is_enabled() && q.kind() == QuantityKind::Parameterization {
349                if let Some(pq) = q
350                    .as_any()
351                    .downcast_ref::<MeshVertexParameterizationQuantity>()
352                {
353                    return Some(pq);
354                }
355            }
356        }
357        None
358    }
359
360    /// Returns the currently active corner parameterization quantity, if any.
361    #[must_use]
362    pub fn active_corner_parameterization_quantity(
363        &self,
364    ) -> Option<&MeshCornerParameterizationQuantity> {
365        for q in &self.quantities {
366            if q.is_enabled() && q.kind() == QuantityKind::Parameterization {
367                if let Some(pq) = q
368                    .as_any()
369                    .downcast_ref::<MeshCornerParameterizationQuantity>()
370                {
371                    return Some(pq);
372                }
373            }
374        }
375        None
376    }
377
378    /// Returns the currently active vertex intrinsic vector quantity (immutable), if any.
379    #[must_use]
380    pub fn active_vertex_intrinsic_vector_quantity(
381        &self,
382    ) -> Option<&MeshVertexIntrinsicVectorQuantity> {
383        for q in &self.quantities {
384            if q.is_enabled() && q.kind() == QuantityKind::Vector {
385                if let Some(iq) = q
386                    .as_any()
387                    .downcast_ref::<MeshVertexIntrinsicVectorQuantity>()
388                {
389                    return Some(iq);
390                }
391            }
392        }
393        None
394    }
395
396    /// Returns the currently active vertex intrinsic vector quantity (mutable), if any.
397    pub fn active_vertex_intrinsic_vector_quantity_mut(
398        &mut self,
399    ) -> Option<&mut MeshVertexIntrinsicVectorQuantity> {
400        for q in &mut self.quantities {
401            if q.is_enabled() && q.kind() == QuantityKind::Vector {
402                if let Some(iq) = q
403                    .as_any_mut()
404                    .downcast_mut::<MeshVertexIntrinsicVectorQuantity>()
405                {
406                    return Some(iq);
407                }
408            }
409        }
410        None
411    }
412
413    /// Returns the currently active face intrinsic vector quantity (immutable), if any.
414    #[must_use]
415    pub fn active_face_intrinsic_vector_quantity(
416        &self,
417    ) -> Option<&MeshFaceIntrinsicVectorQuantity> {
418        for q in &self.quantities {
419            if q.is_enabled() && q.kind() == QuantityKind::Vector {
420                if let Some(iq) = q.as_any().downcast_ref::<MeshFaceIntrinsicVectorQuantity>() {
421                    return Some(iq);
422                }
423            }
424        }
425        None
426    }
427
428    /// Returns the currently active face intrinsic vector quantity (mutable), if any.
429    pub fn active_face_intrinsic_vector_quantity_mut(
430        &mut self,
431    ) -> Option<&mut MeshFaceIntrinsicVectorQuantity> {
432        for q in &mut self.quantities {
433            if q.is_enabled() && q.kind() == QuantityKind::Vector {
434                if let Some(iq) = q
435                    .as_any_mut()
436                    .downcast_mut::<MeshFaceIntrinsicVectorQuantity>()
437                {
438                    return Some(iq);
439                }
440            }
441        }
442        None
443    }
444
445    /// Returns the currently active one-form quantity (immutable), if any.
446    #[must_use]
447    pub fn active_one_form_quantity(&self) -> Option<&MeshOneFormQuantity> {
448        for q in &self.quantities {
449            if q.is_enabled() && q.kind() == QuantityKind::Vector {
450                if let Some(oq) = q.as_any().downcast_ref::<MeshOneFormQuantity>() {
451                    return Some(oq);
452                }
453            }
454        }
455        None
456    }
457
458    /// Returns the currently active one-form quantity (mutable), if any.
459    pub fn active_one_form_quantity_mut(&mut self) -> Option<&mut MeshOneFormQuantity> {
460        for q in &mut self.quantities {
461            if q.is_enabled() && q.kind() == QuantityKind::Vector {
462                if let Some(oq) = q.as_any_mut().downcast_mut::<MeshOneFormQuantity>() {
463                    return Some(oq);
464                }
465            }
466        }
467        None
468    }
469}