1use crate::*;
26
27use std::marker::PhantomData;
28
29#[derive(Default, Debug, PartialEq, PartialOrd, Ord, Eq, Clone, Hash)]
32pub struct Mesh3D<P, ID, IC>
34where
35 P: Is3D,
36 ID: IsDataContainer<P>,
37 IC: IsIndexContainer,
38{
39 pc: ID,
40 topology: IC,
41 _phantom: PhantomData<P>,
42}
43
44impl<P, ID, IC> IsMesh<P, Face3> for Mesh3D<P, ID, IC>
45where
46 P: Is3D + Clone,
47 ID: IsDataContainer<P>,
48 IC: IsIndexContainer,
49{
50 fn num_faces(&self) -> usize {
51 self.topology.len() / 3
52 }
53
54 fn num_vertices(&self) -> usize {
55 self.pc.len_d()
56 }
57
58 fn face_vertex_ids(&self, faceid: FId) -> Result<Face3> {
59 let id1 = 3 * faceid.val + 0;
60 let id2 = 3 * faceid.val + 1;
61 let id3 = 3 * faceid.val + 2;
62
63 if id3 >= self.topology.len() {
64 return Err(ErrorKind::IncorrectFaceID);
65 }
66
67 Ok(Face3::new(
68 VId {
69 val: self.topology.get(id1),
70 },
71 VId {
72 val: self.topology.get(id2),
73 },
74 VId {
75 val: self.topology.get(id3),
76 },
77 ))
78 }
79
80 fn face_vertices(&self, faceid: FId) -> Result<[P; 3]> {
81 let face = self.face_vertex_ids(faceid)?;
82 if let (Ok(v1), Ok(v2), Ok(v3)) = (
83 self.vertex(face.a),
84 self.vertex(face.b),
85 self.vertex(face.c),
86 ) {
87 return Ok([v1, v2, v3]);
88 }
89 Err(ErrorKind::IncorrectVertexID)
90 }
91
92 fn vertex(&self, vertexid: VId) -> Result<P> {
93 if vertexid.val >= self.pc.len_d() {
94 return Err(ErrorKind::IncorrectVertexID);
95 }
96 Ok(self.pc.get_d(vertexid.val))
97 }
98}
99
100impl<P, ID, IC> IsFaceEditableMesh<P, Face3> for Mesh3D<P, ID, IC>
101where
102 P: IsEditable3D + IsBuildable3D + Clone,
103 ID: IsDataContainer<P>,
104 IC: IsIndexContainer,
105{
106 fn add_face(&mut self, v1: P, v2: P, v3: P) -> FId {
107 let vid1 = self.add_vertex(v1);
108 let vid2 = self.add_vertex(v2);
109 let vid3 = self.add_vertex(v3);
110 self.topology.push(vid1.val);
111 self.topology.push(vid2.val);
112 self.topology.push(vid3.val);
113 FId {
114 val: self.topology.len() / 3 - 1,
115 }
116 }
117
118 fn try_add_connection(&mut self, vid1: VId, vid2: VId, vid3: VId) -> Result<FId> {
119 if vid1.val >= self.pc.len_d()
120 || vid2.val >= self.pc.len_d()
121 || vid3.val >= self.pc.len_d()
122 || vid1 == vid2
123 || vid1 == vid3
124 || vid2 == vid3
125 {
126 return Err(ErrorKind::IncorrectVertexID);
127 }
128 self.topology.push(vid1.val);
129 self.topology.push(vid2.val);
130 self.topology.push(vid3.val);
131 Ok(FId {
132 val: self.topology.len() / 3 - 1,
133 })
134 }
135
136 fn reserve_faces(&mut self, n: usize) {
137 self.topology.reserve(3 * n)
138 }
139}
140
141impl<P, ID, IC> IsVertexEditableMesh<P, Face3> for Mesh3D<P, ID, IC>
142where
143 P: IsEditable3D + IsBuildable3D + Clone,
144 ID: IsDataContainer<P>,
145 IC: IsIndexContainer,
146{
147 fn add_vertex(&mut self, vertex: P) -> VId {
148 self.pc.push_d(vertex);
149 VId {
150 val: self.pc.len_d() - 1,
151 }
152 }
153
154 fn change_vertex(&mut self, vid: VId, vertex: P) -> Result<()> {
155 if vid.val < self.pc.len_d() {
156 self.pc.set_d(vid.val, vertex);
157 Ok(())
158 } else {
159 Err(ErrorKind::IncorrectVertexID)
160 }
161 }
162
163 fn reserve_vertices(&mut self, n: usize) {
164 self.pc.reserve_d(n)
165 }
166}
167
168impl<P, ID, IC> HasBoundingBox3DMaybe for Mesh3D<P, ID, IC>
169where
170 P: Is3D,
171 ID: IsDataContainer<P> + HasBoundingBox3DMaybe,
172 IC: IsIndexContainer,
173{
174 fn bounding_box_maybe(&self) -> Result<BoundingBox3D> {
175 self.pc.bounding_box_maybe()
176 }
177}
178
179impl<P, ID, IC> HasCenterOfGravity3D for Mesh3D<P, ID, IC>
180where
181 P: Is3D,
182 ID: IsDataContainer<P> + HasCenterOfGravity3D,
183 IC: IsIndexContainer,
184{
185 fn center_of_gravity(&self) -> Result<Point3D> {
186 self.pc.center_of_gravity()
187 }
188}
189
190impl<P, ID, IC> IsScalable for Mesh3D<P, ID, IC>
191where
192 P: IsEditable3D,
193 ID: IsDataContainer<P> + IsScalable,
194 IC: IsIndexContainer,
195{
196 fn scale(&mut self, factor: Positive) {
197 self.pc.scale(factor);
198 }
199}
200
201impl<P, ID, IC> IsMatrix4Transformable for Mesh3D<P, ID, IC>
202where
203 P: Is3D + IsMatrix4Transformable + Clone,
204 ID: IsDataContainer<P> + IsMatrix4Transformable + Clone,
205 IC: IsIndexContainer,
206{
207 fn transformed(&self, m: &Matrix4) -> Self {
208 let mut new = self.clone();
209 new.transform(m);
210 new
211 }
212
213 fn transform(&mut self, m: &Matrix4) {
214 self.pc.transform(m);
215 }
216}
217
218impl<P, ID, IC> IsMovable3D for Mesh3D<P, ID, IC>
219where
220 P: Is3D + IsMovable3D,
221 ID: IsDataContainer<P> + IsMovable3D,
222 IC: IsIndexContainer,
223{
224 fn move_by(&mut self, x: f64, y: f64, z: f64) {
225 self.pc.move_by(x, y, z)
226 }
227}
228
229impl<P, ID, IC> From<(ID, IC)> for Mesh3D<P, ID, IC>
230where
231 P: Is3D,
232 ID: IsDataContainer<P>,
233 IC: IsIndexContainer,
234{
235 fn from(pt: (ID, IC)) -> Self {
236 Self {
237 pc: pt.0,
238 topology: pt.1,
239 _phantom: PhantomData::default(),
240 }
241 }
242}
243
244impl<P, ID, IC> Into<(ID, IC)> for Mesh3D<P, ID, IC>
245where
246 P: Is3D,
247 ID: IsDataContainer<P>,
248 IC: IsIndexContainer,
249{
250 fn into(self) -> (ID, IC) {
251 (self.pc, self.topology)
252 }
253}