spatialrust_core/
capabilities.rs1use crate::{FieldSemantic, PointCloud, SpatialError, SpatialResult};
2
3pub trait HasPositions3 {
5 fn positions3(&self) -> SpatialResult<(&[f32], &[f32], &[f32])>;
7}
8
9pub trait HasNormals3 {
11 fn normals3(&self) -> SpatialResult<(&[f32], &[f32], &[f32])>;
13}
14
15pub trait HasIntensity {
17 fn intensity(&self) -> SpatialResult<&[f32]>;
19}
20
21impl HasPositions3 for PointCloud {
22 fn positions3(&self) -> SpatialResult<(&[f32], &[f32], &[f32])> {
23 self.schema().validate_positions()?;
24 let x = self.field_name_for_semantic(FieldSemantic::PositionX)?;
25 let y = self.field_name_for_semantic(FieldSemantic::PositionY)?;
26 let z = self.field_name_for_semantic(FieldSemantic::PositionZ)?;
27 Ok((self.field(x)?.as_f32()?, self.field(y)?.as_f32()?, self.field(z)?.as_f32()?))
28 }
29}
30
31impl HasNormals3 for PointCloud {
32 fn normals3(&self) -> SpatialResult<(&[f32], &[f32], &[f32])> {
33 let x = self.field_name_for_semantic(FieldSemantic::NormalX)?;
34 let y = self.field_name_for_semantic(FieldSemantic::NormalY)?;
35 let z = self.field_name_for_semantic(FieldSemantic::NormalZ)?;
36 Ok((self.field(x)?.as_f32()?, self.field(y)?.as_f32()?, self.field(z)?.as_f32()?))
37 }
38}
39
40impl HasIntensity for PointCloud {
41 fn intensity(&self) -> SpatialResult<&[f32]> {
42 let name = self.field_name_for_semantic(FieldSemantic::Intensity)?;
43 self.field(name)?.as_f32()
44 }
45}
46
47impl PointCloud {
48 fn field_name_for_semantic(&self, semantic: FieldSemantic) -> SpatialResult<&str> {
49 self.schema()
50 .find_semantic(semantic)
51 .map(|field| field.name.as_str())
52 .ok_or_else(|| SpatialError::MissingField(format!("{semantic:?}")))
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::{HasIntensity, HasNormals3, HasPositions3};
59 use crate::{PointCloudBuilder, StandardSchemas};
60
61 #[test]
62 fn positions3_capability() {
63 let mut builder = PointCloudBuilder::new(StandardSchemas::point_xyz());
64 builder.push_point([1.0, 2.0, 3.0]).unwrap();
65 let cloud = builder.build().unwrap();
66 let (x, y, z) = cloud.positions3().unwrap();
67 assert_eq!(x, &[1.0]);
68 assert_eq!(y, &[2.0]);
69 assert_eq!(z, &[3.0]);
70 }
71
72 #[test]
73 fn normal_and_intensity_capabilities() {
74 let mut builder = PointCloudBuilder::new(StandardSchemas::point_xyzinormal());
75 builder.push_point([0.0, 0.0, 0.0, 0.5, 0.0, 1.0, 0.0]).unwrap();
76 let cloud = builder.build().unwrap();
77 let (_, _, nz) = cloud.normals3().unwrap();
78 assert_eq!(cloud.intensity().unwrap(), &[0.5]);
79 assert_eq!(nz, &[0.0]);
80 }
81}