rust_3d/
point_cloud_3d_f32.rs

1/*
2Copyright 2020 Martin Buck
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"),
6to deal in the Software without restriction, including without limitation the
7rights to use, copy, modify, merge, publish, distribute, sublicense,
8and/or sell copies of the Software, and to permit persons to whom the Software
9is furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall
12be included all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
20OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21*/
22
23//@todo implement as many traits as possible (see point_cloud_3d for reference)
24
25//! PointCloud3Df32, a collection of positions within 3D space stored lossy as f32 vector for easier usage during rendering
26
27use crate::*;
28
29use std::marker::PhantomData;
30
31//------------------------------------------------------------------------------
32
33#[derive(Debug, PartialEq, PartialOrd, Clone, Default)]
34/// PointCloud3Df32, a collection of positions within 3D space stored lossy as f32 vector for easier usage during rendering
35pub struct PointCloud3Df32<P>
36where
37    P: IsBuildable3D,
38{
39    pub data: Vec<f32>,
40    _phantom: PhantomData<P>,
41}
42
43impl<P> PointCloud3Df32<P>
44where
45    P: IsBuildable3D,
46{
47    /// Creates a new, empty point cloud
48    pub fn new() -> PointCloud3Df32<P> {
49        PointCloud3Df32 {
50            data: Vec::new(),
51            _phantom: PhantomData::default(),
52        }
53    }
54    /// Creates a new, empty point cloud with capacity for n points
55    pub fn with_capacity(n: usize) -> PointCloud3Df32<P> {
56        PointCloud3Df32 {
57            data: Vec::with_capacity(3 * n),
58            _phantom: PhantomData::default(),
59        }
60    }
61}
62
63//------------------------------------------------------------------------------
64
65impl<P> IsPushable<P> for PointCloud3Df32<P>
66where
67    P: IsBuildable3D,
68{
69    fn push(&mut self, p: P) {
70        self.data.push(p.x() as f32);
71        self.data.push(p.y() as f32);
72        self.data.push(p.z() as f32);
73    }
74    fn reserve(&mut self, n: usize) {
75        self.data.reserve(3 * n)
76    }
77}
78
79impl<P> IsDataContainer<P> for PointCloud3Df32<P>
80where
81    P: IsBuildable3D,
82{
83    fn reserve_d(&mut self, n: usize) {
84        self.data.reserve(3 * n);
85    }
86
87    fn len_d(&self) -> usize {
88        self.data.len() / 3
89    }
90
91    fn push_d(&mut self, p: P) {
92        self.data.push(p.x() as f32);
93        self.data.push(p.y() as f32);
94        self.data.push(p.z() as f32);
95    }
96
97    fn get_d(&self, index: usize) -> P {
98        P::new(
99            self.data[3 * index + 0] as f64,
100            self.data[3 * index + 1] as f64,
101            self.data[3 * index + 2] as f64,
102        )
103    }
104
105    fn set_d(&mut self, index: usize, p: P) {
106        self.data[3 * index + 0] = p.x() as f32;
107        self.data[3 * index + 1] = p.y() as f32;
108        self.data[3 * index + 2] = p.z() as f32;
109    }
110}
111
112impl<P> IsMovable3D for PointCloud3Df32<P>
113where
114    P: IsBuildable3D,
115{
116    fn move_by(&mut self, x: f64, y: f64, z: f64) {
117        for index in 0..self.data.len() / 3 {
118            self.data[3 * index + 0] += x as f32;
119            self.data[3 * index + 1] += y as f32;
120            self.data[3 * index + 2] += z as f32;
121        }
122    }
123}
124
125impl<P> HasBoundingBox3DMaybe for PointCloud3Df32<P>
126where
127    P: IsBuildable3D,
128{
129    fn bounding_box_maybe(&self) -> Result<BoundingBox3D> {
130        let d = &self.data;
131        let n_p = d.len() / 3;
132
133        if n_p <= 2 {
134            return Err(ErrorKind::TooFewPoints);
135        }
136
137        let mut minx = d[0];
138        let mut miny = d[1];
139        let mut minz = d[2];
140        let mut maxx = d[0];
141        let mut maxy = d[1];
142        let mut maxz = d[2];
143
144        for i in 1..n_p {
145            let [x, y, z] = [d[3 * i + 0], d[3 * i + 1], d[3 * i + 2]];
146            if x < minx {
147                minx = x;
148            }
149            if y < miny {
150                miny = y;
151            }
152            if z < minz {
153                minz = z;
154            }
155            if x > maxx {
156                maxx = x;
157            }
158            if y > maxy {
159                maxy = y;
160            }
161            if z > maxz {
162                maxz = z;
163            }
164        }
165
166        BoundingBox3D::new(
167            &Point3D {
168                x: minx as f64,
169                y: miny as f64,
170                z: minz as f64,
171            },
172            &Point3D {
173                x: maxx as f64,
174                y: maxy as f64,
175                z: maxz as f64,
176            },
177        )
178    }
179}
180
181impl<P> Into<Vec<f32>> for PointCloud3Df32<P>
182where
183    P: IsBuildable3D,
184{
185    fn into(self) -> Vec<f32> {
186        self.data
187    }
188}
189
190impl<P> From<Vec<f32>> for PointCloud3Df32<P>
191where
192    P: IsBuildable3D,
193{
194    fn from(data: Vec<f32>) -> Self {
195        Self {
196            data,
197            _phantom: PhantomData::default(),
198        }
199    }
200}