1use crate::math::{Point, Real, Vector, DIM};
2use crate::shape::{FeatureId, PackedFeatureId, PolygonalFeature, PolygonalFeatureMap, SupportMap};
3use crate::utils::hashmap::{Entry, HashMap};
5use crate::utils::{self, SortedPair};
6#[cfg(feature = "alloc")]
7use alloc::vec::Vec;
8use core::f64;
9#[cfg(not(feature = "std"))]
10use na::ComplexField; use na::{self, Point2, Unit};
12
13#[cfg(feature = "rkyv")]
14use rkyv::{bytecheck, CheckBytes};
15
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17#[cfg_attr(
18 feature = "rkyv",
19 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, CheckBytes),
20 archive(as = "Self")
21)]
22#[derive(PartialEq, Debug, Copy, Clone)]
23pub struct Vertex {
24 pub first_adj_face_or_edge: u32,
25 pub num_adj_faces_or_edge: u32,
26}
27
28#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
29#[cfg_attr(
30 feature = "rkyv",
31 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, CheckBytes),
32 archive(as = "Self")
33)]
34#[derive(PartialEq, Debug, Copy, Clone)]
35pub struct Edge {
36 pub vertices: Point2<u32>,
37 pub faces: Point2<u32>,
38 pub dir: Unit<Vector<Real>>,
39 deleted: bool,
40}
41
42impl Edge {
43 fn other_triangle(&self, id: u32) -> u32 {
44 if id == self.faces[0] {
45 self.faces[1]
46 } else {
47 self.faces[0]
48 }
49 }
50}
51
52#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
53#[cfg_attr(
54 feature = "rkyv",
55 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, CheckBytes),
56 archive(as = "Self")
57)]
58#[derive(PartialEq, Debug, Copy, Clone)]
59pub struct Face {
60 pub first_vertex_or_edge: u32,
61 pub num_vertices_or_edges: u32,
62 pub normal: Unit<Vector<Real>>,
63}
64
65#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
66#[cfg_attr(
67 feature = "rkyv",
68 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize),
69 archive(check_bytes)
70)]
71#[derive(PartialEq, Debug, Copy, Clone)]
72struct Triangle {
73 vertices: [u32; 3],
74 edges: [u32; 3],
75 normal: Vector<Real>,
76 parent_face: Option<u32>,
77 is_degenerate: bool,
78}
79
80impl Triangle {
81 fn next_edge_id(&self, id: u32) -> u32 {
82 for i in 0..3 {
83 if self.edges[i] == id {
84 return (i as u32 + 1) % 3;
85 }
86 }
87
88 unreachable!()
89 }
90}
91
92#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
93#[cfg_attr(
94 feature = "rkyv",
95 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize),
96 archive(check_bytes)
97)]
98#[derive(PartialEq, Debug, Clone)]
99pub struct ConvexPolyhedron {
101 points: Vec<Point<Real>>,
102 vertices: Vec<Vertex>,
103 faces: Vec<Face>,
104 edges: Vec<Edge>,
105 faces_adj_to_vertex: Vec<u32>,
107 edges_adj_to_vertex: Vec<u32>,
109 edges_adj_to_face: Vec<u32>,
111 vertices_adj_to_face: Vec<u32>,
113}
114
115impl ConvexPolyhedron {
116 pub fn from_convex_hull(points: &[Point<Real>]) -> Option<ConvexPolyhedron> {
121 crate::transformation::try_convex_hull(points)
122 .ok()
123 .and_then(|(vertices, indices)| Self::from_convex_mesh(vertices, &indices))
124 }
125
126 pub fn from_convex_mesh(
135 points: Vec<Point<Real>>,
136 indices: &[[u32; DIM]],
137 ) -> Option<ConvexPolyhedron> {
138 let eps = crate::math::DEFAULT_EPSILON.sqrt();
139
140 let mut vertices = Vec::new();
141 let mut edges = Vec::<Edge>::new();
142 let mut faces = Vec::<Face>::new();
143 let mut triangles = Vec::new();
144 let mut edge_map = HashMap::default();
145
146 let mut faces_adj_to_vertex = Vec::new();
147 let mut edges_adj_to_vertex = Vec::new();
148 let mut edges_adj_to_face = Vec::new();
149 let mut vertices_adj_to_face = Vec::new();
150
151 if points.len() + indices.len() <= 2 {
152 return None;
153 }
154
155 let nedges = points.len() + indices.len() - 2;
157 edges.reserve(nedges);
158
159 for idx in indices {
163 let mut edges_id = [u32::MAX; DIM];
164 let face_id = triangles.len();
165
166 if idx[0] == idx[1] || idx[0] == idx[2] || idx[1] == idx[2] {
167 return None;
168 }
169
170 for i1 in 0..3 {
171 let i2 = (i1 + 1) % 3;
173 let key = SortedPair::new(idx[i1], idx[i2]);
174
175 match edge_map.entry(key) {
176 Entry::Occupied(e) => {
177 let edge = &mut edges[*e.get() as usize];
178 let out_face_id = &mut edge.faces[1];
179
180 if *out_face_id == u32::MAX {
181 edges_id[i1] = *e.get();
182 *out_face_id = face_id as u32
183 } else {
184 return None;
186 }
187 }
188 Entry::Vacant(e) => {
189 edges_id[i1] = *e.insert(edges.len() as u32);
190
191 let dir = Unit::try_new(
192 points[idx[i2] as usize] - points[idx[i1] as usize],
193 crate::math::DEFAULT_EPSILON,
194 );
195
196 edges.push(Edge {
197 vertices: Point2::new(idx[i1], idx[i2]),
198 faces: Point2::new(face_id as u32, u32::MAX),
199 dir: dir.unwrap_or(Vector::x_axis()),
200 deleted: dir.is_none(),
201 });
202 }
203 }
204 }
205
206 let normal = utils::ccw_face_normal([
207 &points[idx[0] as usize],
208 &points[idx[1] as usize],
209 &points[idx[2] as usize],
210 ]);
211 let triangle = Triangle {
212 vertices: *idx,
213 edges: edges_id,
214 normal: normal.map(|n| *n).unwrap_or(Vector::zeros()),
215 parent_face: None,
216 is_degenerate: normal.is_none(),
217 };
218
219 triangles.push(triangle);
220 }
221
222 for e in &mut edges {
225 let tri1 = triangles.get(e.faces[0] as usize)?;
226 let tri2 = triangles.get(e.faces[1] as usize)?;
227 if tri1.normal.dot(&tri2.normal) > 1.0 - eps {
228 e.deleted = true;
229 }
230 }
231
232 for i in 0..triangles.len() {
236 if triangles[i].parent_face.is_none() {
237 for j1 in 0..3 {
238 if !edges[triangles[i].edges[j1] as usize].deleted {
239 let new_face_id = faces.len();
241 let mut new_face = Face {
242 first_vertex_or_edge: edges_adj_to_face.len() as u32,
243 num_vertices_or_edges: 1,
244 normal: Unit::new_unchecked(triangles[i].normal),
245 };
246
247 edges_adj_to_face.push(triangles[i].edges[j1]);
248 vertices_adj_to_face.push(triangles[i].vertices[j1]);
249
250 let j2 = (j1 + 1) % 3;
251 let start_vertex = triangles[i].vertices[j1];
252
253 let mut curr_triangle = i;
257 let mut curr_edge_id = j2;
258
259 while triangles[curr_triangle].vertices[curr_edge_id] != start_vertex {
260 let curr_edge = triangles[curr_triangle].edges[curr_edge_id];
261 let curr_vertex = triangles[curr_triangle].vertices[curr_edge_id];
262 triangles[curr_triangle].parent_face = Some(new_face_id as u32);
268
269 if !edges[curr_edge as usize].deleted {
270 edges_adj_to_face.push(curr_edge);
271 vertices_adj_to_face.push(curr_vertex);
272 new_face.num_vertices_or_edges += 1;
273
274 curr_edge_id = (curr_edge_id + 1) % 3;
275 } else {
276 curr_triangle = edges[curr_edge as usize]
278 .other_triangle(curr_triangle as u32)
279 as usize;
280 curr_edge_id =
281 triangles[curr_triangle].next_edge_id(curr_edge) as usize;
282 assert!(
283 triangles[curr_triangle].vertices[curr_edge_id] == curr_vertex
284 );
285 }
286 }
287
288 if new_face.num_vertices_or_edges > 2 {
289 faces.push(new_face);
295 }
296 break;
297 }
298 }
299 }
300 }
301
302 for e in &mut edges {
304 if let Some(fid) = triangles.get(e.faces[0] as usize)?.parent_face {
305 e.faces[0] = fid;
306 }
307
308 if let Some(fid) = triangles.get(e.faces[1] as usize)?.parent_face {
309 e.faces[1] = fid;
310 }
311 }
312
313 let empty_vertex = Vertex {
317 first_adj_face_or_edge: 0,
318 num_adj_faces_or_edge: 0,
319 };
320
321 vertices.resize(points.len(), empty_vertex);
322
323 for face in &faces {
325 let first_vid = face.first_vertex_or_edge;
326 let last_vid = face.first_vertex_or_edge + face.num_vertices_or_edges;
327
328 for i in &vertices_adj_to_face[first_vid as usize..last_vid as usize] {
329 vertices[*i as usize].num_adj_faces_or_edge += 1;
330 }
331 }
332
333 let mut total_num_adj_faces = 0;
335 for v in &mut vertices {
336 v.first_adj_face_or_edge = total_num_adj_faces;
337 total_num_adj_faces += v.num_adj_faces_or_edge;
338 }
339 faces_adj_to_vertex.resize(total_num_adj_faces as usize, 0);
340 edges_adj_to_vertex.resize(total_num_adj_faces as usize, 0);
341
342 for v in &mut vertices {
346 v.num_adj_faces_or_edge = 0;
347 }
348
349 for (face_id, face) in faces.iter().enumerate() {
350 let first_vid = face.first_vertex_or_edge;
351 let last_vid = face.first_vertex_or_edge + face.num_vertices_or_edges;
352
353 for vid in first_vid..last_vid {
354 let v = &mut vertices[vertices_adj_to_face[vid as usize] as usize];
355 faces_adj_to_vertex
356 [(v.first_adj_face_or_edge + v.num_adj_faces_or_edge) as usize] =
357 face_id as u32;
358 edges_adj_to_vertex
359 [(v.first_adj_face_or_edge + v.num_adj_faces_or_edge) as usize] =
360 edges_adj_to_face[vid as usize];
361 v.num_adj_faces_or_edge += 1;
362 }
363 }
364
365 let res = ConvexPolyhedron {
369 points,
370 vertices,
371 faces,
372 edges,
373 faces_adj_to_vertex,
374 edges_adj_to_vertex,
375 edges_adj_to_face,
376 vertices_adj_to_face,
377 };
378
379 Some(res)
383 }
384
385 #[inline]
387 pub fn check_geometry(&self) {
388 for face in &self.faces {
389 let p0 =
390 self.points[self.vertices_adj_to_face[face.first_vertex_or_edge as usize] as usize];
391
392 for v in &self.points {
393 assert!((v - p0).dot(face.normal.as_ref()) <= crate::math::DEFAULT_EPSILON);
394 }
395 }
396 }
397
398 #[inline]
400 pub fn points(&self) -> &[Point<Real>] {
401 &self.points[..]
402 }
403
404 #[inline]
406 pub fn vertices(&self) -> &[Vertex] {
407 &self.vertices[..]
408 }
409
410 #[inline]
412 pub fn edges(&self) -> &[Edge] {
413 &self.edges[..]
414 }
415
416 #[inline]
418 pub fn faces(&self) -> &[Face] {
419 &self.faces[..]
420 }
421
422 #[inline]
424 pub fn vertices_adj_to_face(&self) -> &[u32] {
425 &self.vertices_adj_to_face[..]
426 }
427
428 #[inline]
430 pub fn edges_adj_to_face(&self) -> &[u32] {
431 &self.edges_adj_to_face[..]
432 }
433
434 #[inline]
436 pub fn faces_adj_to_vertex(&self) -> &[u32] {
437 &self.faces_adj_to_vertex[..]
438 }
439
440 pub fn scaled(mut self, scale: &Vector<Real>) -> Option<Self> {
445 self.points
446 .iter_mut()
447 .for_each(|pt| pt.coords.component_mul_assign(scale));
448
449 for f in &mut self.faces {
450 f.normal = Unit::try_new(f.normal.component_mul(scale), 0.0).unwrap_or(f.normal);
451 }
452
453 for e in &mut self.edges {
454 e.dir = Unit::try_new(e.dir.component_mul(scale), 0.0).unwrap_or(e.dir);
455 }
456
457 Some(self)
458 }
459
460 fn support_feature_id_toward_eps(
461 &self,
462 local_dir: &Unit<Vector<Real>>,
463 eps: Real,
464 ) -> FeatureId {
465 let (seps, ceps) = eps.sin_cos();
466 let support_pt_id = utils::point_cloud_support_point_id(local_dir.as_ref(), &self.points);
467 let vertex = &self.vertices[support_pt_id];
468
469 for i in 0..vertex.num_adj_faces_or_edge {
471 let face_id = self.faces_adj_to_vertex[(vertex.first_adj_face_or_edge + i) as usize];
472 let face = &self.faces[face_id as usize];
473
474 if face.normal.dot(local_dir.as_ref()) >= ceps {
475 return FeatureId::Face(face_id);
476 }
477 }
478
479 for i in 0..vertex.num_adj_faces_or_edge {
481 let edge_id = self.edges_adj_to_vertex[(vertex.first_adj_face_or_edge + i) as usize];
482 let edge = &self.edges[edge_id as usize];
483
484 if edge.dir.dot(local_dir.as_ref()).abs() <= seps {
485 return FeatureId::Edge(edge_id);
486 }
487 }
488
489 FeatureId::Vertex(support_pt_id as u32)
491 }
492
493 pub fn support_feature_id_toward(&self, local_dir: &Unit<Vector<Real>>) -> FeatureId {
495 let eps: Real = na::convert::<f64, Real>(f64::consts::PI / 180.0);
496 self.support_feature_id_toward_eps(local_dir, eps)
497 }
498
499 pub fn feature_normal(&self, feature: FeatureId) -> Option<Unit<Vector<Real>>> {
501 match feature {
502 FeatureId::Face(id) => Some(self.faces[id as usize].normal),
503 FeatureId::Edge(id) => {
504 let edge = &self.edges[id as usize];
505 Some(Unit::new_normalize(
506 *self.faces[edge.faces[0] as usize].normal
507 + *self.faces[edge.faces[1] as usize].normal,
508 ))
509 }
510 FeatureId::Vertex(id) => {
511 let vertex = &self.vertices[id as usize];
512 let first = vertex.first_adj_face_or_edge;
513 let last = vertex.first_adj_face_or_edge + vertex.num_adj_faces_or_edge;
514 let mut normal = Vector::zeros();
515
516 for face in &self.faces_adj_to_vertex[first as usize..last as usize] {
517 normal += *self.faces[*face as usize].normal
518 }
519
520 Some(Unit::new_normalize(normal))
521 }
522 FeatureId::Unknown => None,
523 }
524 }
525}
526
527impl SupportMap for ConvexPolyhedron {
528 #[inline]
529 fn local_support_point(&self, dir: &Vector<Real>) -> Point<Real> {
530 utils::point_cloud_support_point(dir, self.points())
531 }
532}
533
534impl PolygonalFeatureMap for ConvexPolyhedron {
535 fn local_support_feature(&self, dir: &Unit<Vector<Real>>, out_feature: &mut PolygonalFeature) {
536 let mut best_fid = 0;
537 let mut best_dot = self.faces[0].normal.dot(dir);
538
539 for (fid, face) in self.faces[1..].iter().enumerate() {
540 let new_dot = face.normal.dot(dir);
541
542 if new_dot > best_dot {
543 best_fid = fid + 1;
544 best_dot = new_dot;
545 }
546 }
547
548 let face = &self.faces[best_fid];
549 let i1 = face.first_vertex_or_edge;
550 let num_vertices = face.num_vertices_or_edges.min(4);
552 let i2 = i1 + num_vertices;
553
554 for (i, (vid, eid)) in self.vertices_adj_to_face[i1 as usize..i2 as usize]
555 .iter()
556 .zip(self.edges_adj_to_face[i1 as usize..i2 as usize].iter())
557 .enumerate()
558 {
559 out_feature.vertices[i] = self.points[*vid as usize];
560 out_feature.vids[i] = PackedFeatureId::vertex(*vid);
561 out_feature.eids[i] = PackedFeatureId::edge(*eid);
562 }
563
564 out_feature.fid = PackedFeatureId::face(best_fid as u32);
565 out_feature.num_vertices = num_vertices as usize;
566 }
567
568 fn is_convex_polyhedron(&self) -> bool {
569 true
570 }
571}
572
573