rust_3d/
searchable_mesh.rs

1/*
2Copyright 2017 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//! SearchableMesh, transforms IsMesh to IsSearchableMesh
24
25use crate::*;
26
27use std::marker::PhantomData;
28
29//------------------------------------------------------------------------------
30
31/// SearchableMesh, transforms IsMesh to IsSearchableMesh
32#[derive(Clone)]
33pub struct SearchableMesh<M, T, IC>
34where
35    M: IsMesh<T, Face3>,
36    IC: IsIndexContainer,
37{
38    mesh: M,
39    he: HalfEdge<IC>,
40    phantomt: PhantomData<T>,
41}
42
43impl<M, T, IC> SearchableMesh<M, T, IC>
44where
45    M: IsMesh<T, Face3>,
46    IC: IsIndexContainer,
47{
48    /// Creates a new SearchableMesh3D from an IsMesh3D
49    /// This only stays valid if IMesh3D is not changed after creation
50    /// The mesh must be manifold
51    pub fn new(mesh: M) -> Self {
52        let he = HalfEdge::new(&mesh);
53
54        SearchableMesh {
55            mesh,
56            he,
57            phantomt: PhantomData,
58        }
59    }
60
61    /// Fails if the vertex ID is out of bounds
62    pub fn ensure_face_id(&self, id: FId) -> Result<()> {
63        if id.val >= self.mesh.num_faces() {
64            return Err(ErrorKind::IncorrectFaceID);
65        }
66        Ok(())
67    }
68
69    /// Returns a reference to the held mesh
70    pub fn mesh(&self) -> &M {
71        &self.mesh
72    }
73}
74
75impl<M, T, IC> IsMesh<T, Face3> for SearchableMesh<M, T, IC>
76where
77    M: IsMesh<T, Face3>,
78    IC: IsIndexContainer,
79{
80    fn num_faces(&self) -> usize {
81        self.mesh.num_faces()
82    }
83
84    fn num_vertices(&self) -> usize {
85        self.mesh.num_vertices()
86    }
87
88    fn face_vertex_ids(&self, faceid: FId) -> Result<Face3> {
89        self.mesh.face_vertex_ids(faceid)
90    }
91
92    fn face_vertices(&self, faceid: FId) -> Result<[T; 3]> {
93        self.mesh.face_vertices(faceid)
94    }
95
96    fn vertex(&self, vertexid: VId) -> Result<T> {
97        self.mesh.vertex(vertexid)
98    }
99}
100
101impl<M, T, IC> IsVertexEditableMesh<T, Face3> for SearchableMesh<M, T, IC>
102where
103    M: IsMesh<T, Face3> + IsVertexEditableMesh<T, Face3>,
104    T: IsEditable3D + IsBuildable3D + Clone,
105    IC: IsIndexContainer,
106{
107    fn add_vertex(&mut self, vertex: T) -> VId {
108        self.mesh.add_vertex(vertex)
109    }
110
111    fn change_vertex(&mut self, vid: VId, vertex: T) -> Result<()> {
112        self.mesh.change_vertex(vid, vertex)
113    }
114
115    fn reserve_vertices(&mut self, n: usize) {
116        self.mesh.reserve_vertices(n)
117    }
118}
119
120impl<M, T, IC> IsSearchableMesh<T, Face3> for SearchableMesh<M, T, IC>
121where
122    M: IsMesh<T, Face3>,
123    IC: IsIndexContainer,
124{
125    fn num_edges(&self) -> usize {
126        self.mesh.num_faces() * 3
127    }
128
129    fn edges_of_face(&self, faceid: FId) -> Result<(EId, EId, EId)> {
130        self.ensure_face_id(faceid)?;
131        Ok((
132            EId {
133                val: faceid.val * 3 + 0,
134            },
135            EId {
136                val: faceid.val * 3 + 1,
137            },
138            EId {
139                val: faceid.val * 3 + 2,
140            },
141        ))
142    }
143
144    fn edges_originating_from_vertex(&self, vertexid: VId, result: &mut Vec<EId>) -> Result<()> {
145        self.he.edges_originating(vertexid, result)
146    }
147
148    fn edges_ending_at_vertex(
149        &self,
150        vertexid: VId,
151        cache: &mut Vec<EId>,
152        result: &mut Vec<EId>,
153    ) -> Result<()> {
154        self.he.edges_ending(vertexid, cache, result)
155    }
156
157    fn edges_of_vertex(
158        &self,
159        vertexid: VId,
160        cache: &mut Vec<EId>,
161        result: &mut Vec<EId>,
162    ) -> Result<()> {
163        self.he.edges_all(vertexid, cache, result)
164    }
165
166    fn edge_tail(&self, edgeid: EId) -> Result<VId> {
167        self.he.tail(edgeid)
168    }
169
170    fn edge_head(&self, edgeid: EId) -> Result<VId> {
171        self.he.next(edgeid).and_then(|next| self.he.tail(next))
172    }
173
174    fn edge_next(&self, edgeid: EId) -> Result<EId> {
175        self.he.next(edgeid)
176    }
177
178    fn edge_prev(&self, edgeid: EId) -> Result<EId> {
179        self.he.prev(edgeid)
180    }
181
182    fn edge_twin(&self, edgeid: EId) -> Result<Option<EId>> {
183        self.he.twin(edgeid)
184    }
185
186    fn edge_face(&self, edgeid: EId) -> Result<FId> {
187        self.he.face(edgeid)
188    }
189}
190
191impl<M, T, IC> HasBoundingBox3DMaybe for SearchableMesh<M, T, IC>
192where
193    M: IsMesh<T, Face3> + HasBoundingBox3DMaybe,
194    IC: IsIndexContainer,
195{
196    fn bounding_box_maybe(&self) -> Result<BoundingBox3D> {
197        self.mesh.bounding_box_maybe()
198    }
199}
200
201impl<M, T, IC> HasCenterOfGravity3D for SearchableMesh<M, T, IC>
202where
203    M: IsMesh<T, Face3> + HasCenterOfGravity3D,
204    IC: IsIndexContainer,
205{
206    fn center_of_gravity(&self) -> Result<Point3D> {
207        self.mesh.center_of_gravity()
208    }
209}
210
211impl<M, T, IC> IsScalable for SearchableMesh<M, T, IC>
212where
213    M: IsMesh<T, Face3> + IsScalable,
214    IC: IsIndexContainer,
215{
216    fn scale(&mut self, factor: Positive) {
217        self.mesh.scale(factor);
218    }
219}
220
221impl<M, T, IC> AsRef<M> for SearchableMesh<M, T, IC>
222where
223    M: IsMesh<T, Face3>,
224    IC: IsIndexContainer,
225{
226    fn as_ref(&self) -> &M {
227        &self.mesh
228    }
229}
230
231impl<M, T, IC> Into<(M, HalfEdge<IC>)> for SearchableMesh<M, T, IC>
232where
233    M: IsMesh<T, Face3>,
234    IC: IsIndexContainer,
235{
236    fn into(self) -> (M, HalfEdge<IC>) {
237        (self.mesh, self.he)
238    }
239}
240
241impl<M, T, IC> From<(M, HalfEdge<IC>)> for SearchableMesh<M, T, IC>
242where
243    M: IsMesh<T, Face3>,
244    IC: IsIndexContainer,
245{
246    fn from(me: (M, HalfEdge<IC>)) -> Self {
247        Self {
248            mesh: me.0,
249            he: me.1,
250            phantomt: PhantomData::default(),
251        }
252    }
253}