1use crate::math::{Isometry, Point, Vector};
2use crate::shape::{ConvexPolygonalFeature, ConvexPolyhedron, FeatureId, SupportMap};
3use crate::transformation;
4use crate::utils::{self, SortedPair};
5use na::{self, Point2, Point3, RealField, Unit};
6use std::collections::hash_map::Entry;
7use std::collections::HashMap;
8use std::f64;
9
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11#[derive(PartialEq, Debug, Copy, Clone)]
12struct Vertex {
13 first_adj_face_or_edge: usize,
14 num_adj_faces_or_edge: usize,
15}
16
17#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18#[derive(PartialEq, Debug, Copy, Clone)]
19struct Edge<N: RealField + Copy> {
20 vertices: Point2<usize>,
21 faces: Point2<usize>,
22 dir: Unit<Vector<N>>,
23 deleted: bool,
24}
25
26impl<N: RealField + Copy> Edge<N> {
27 fn other_triangle(&self, id: usize) -> usize {
28 if id == self.faces[0] {
29 self.faces[1]
30 } else {
31 self.faces[0]
32 }
33 }
34}
35
36#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
37#[derive(PartialEq, Debug, Copy, Clone)]
38struct Face<N: RealField + Copy> {
39 first_vertex_or_edge: usize,
40 num_vertices_or_edges: usize,
41 normal: Unit<Vector<N>>,
42}
43
44#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
45#[derive(PartialEq, Debug, Copy, Clone)]
46struct Triangle<N: RealField + Copy> {
47 vertices: Point3<usize>,
48 edges: Point3<usize>,
49 normal: Unit<Vector<N>>,
50 parent_face: Option<usize>,
51}
52
53impl<N: RealField + Copy> Triangle<N> {
54 fn next_edge_id(&self, id: usize) -> usize {
55 for i in 0..3 {
56 if self.edges[i] == id {
57 return (i + 1) % 3;
58 }
59 }
60
61 unreachable!()
62 }
63}
64
65#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
66#[derive(PartialEq, Debug, Clone)]
67pub struct ConvexHull<N: RealField + Copy> {
69 points: Vec<Point<N>>,
70 vertices: Vec<Vertex>,
71 faces: Vec<Face<N>>,
72 edges: Vec<Edge<N>>,
73 faces_adj_to_vertex: Vec<usize>,
75 edges_adj_to_vertex: Vec<usize>,
77 edges_adj_to_face: Vec<usize>,
79 vertices_adj_to_face: Vec<usize>,
81}
82
83impl<N: RealField + Copy> ConvexHull<N> {
84 pub fn try_from_points(points: &[Point<N>]) -> Option<ConvexHull<N>> {
89 let hull = transformation::convex_hull(points);
90 let indices: Vec<usize> = hull
91 .flat_indices()
92 .into_iter()
93 .map(|i| i as usize)
94 .collect();
95
96 Self::try_new(hull.coords, &indices)
97 }
98 pub fn try_new(points: Vec<Point<N>>, indices: &[usize]) -> Option<ConvexHull<N>> {
110 let eps = N::default_epsilon().sqrt();
111
112 let mut vertices = Vec::new();
113 let mut edges = Vec::<Edge<N>>::new();
114 let mut faces = Vec::<Face<N>>::new();
115 let mut triangles = Vec::new();
116 let mut edge_map = HashMap::<SortedPair<usize>, usize>::new();
117
118 let mut faces_adj_to_vertex = Vec::new();
119 let mut edges_adj_to_vertex = Vec::new();
120 let mut edges_adj_to_face = Vec::new();
121 let mut vertices_adj_to_face = Vec::new();
122
123 let nedges = points.len() + (indices.len() / 3) - 2;
125 edges.reserve(nedges);
126
127 for vtx in indices.chunks(3) {
131 let mut edges_id = Point3::origin();
132 let face_id = triangles.len();
133
134 for i1 in 0..3 {
135 let i2 = (i1 + 1) % 3;
137 let key = SortedPair::new(vtx[i1], vtx[i2]);
138
139 match edge_map.entry(key) {
140 Entry::Occupied(e) => {
141 edges_id[i1] = *e.get();
142 edges[*e.get()].faces[1] = face_id
143 }
144 Entry::Vacant(e) => {
145 edges_id[i1] = *e.insert(edges.len());
146
147 if let Some(dir) =
148 Unit::try_new(points[vtx[i2]] - points[vtx[i1]], N::default_epsilon())
149 {
150 edges.push(Edge {
151 vertices: Point2::new(vtx[i1], vtx[i2]),
152 faces: Point2::new(face_id, 0),
153 dir,
154 deleted: false,
155 })
156 } else {
157 return None;
158 }
159 }
160 }
161 }
162
163 let vertices = Point3::new(vtx[0], vtx[1], vtx[2]);
164 let normal =
165 utils::ccw_face_normal([&points[vtx[0]], &points[vtx[1]], &points[vtx[2]]])?;
166 let triangle = Triangle {
167 vertices,
168 edges: edges_id,
169 normal,
170 parent_face: None,
171 };
172
173 triangles.push(triangle);
174 }
175
176 let mut num_valid_edges = 0;
178
179 for e in &mut edges {
180 let n1 = triangles[e.faces[0]].normal;
181 let n2 = triangles[e.faces[1]].normal;
182 if n1.dot(&*n2) > N::one() - eps {
183 e.deleted = true;
184 } else {
185 num_valid_edges += 1;
186 }
187 }
188
189 for i in 0..triangles.len() {
193 if triangles[i].parent_face.is_none() {
194 for j1 in 0..3 {
195 if !edges[triangles[i].edges[j1]].deleted {
196 let new_face_id = faces.len();
198 let mut new_face = Face {
199 first_vertex_or_edge: edges_adj_to_face.len(),
200 num_vertices_or_edges: 1,
201 normal: triangles[i].normal,
202 };
203
204 edges_adj_to_face.push(triangles[i].edges[j1]);
205 vertices_adj_to_face.push(triangles[i].vertices[j1]);
206
207 let j2 = (j1 + 1) % 3;
208 let start_vertex = triangles[i].vertices[j1];
209
210 let mut curr_triangle = i;
214 let mut curr_edge_id = j2;
215
216 while triangles[curr_triangle].vertices[curr_edge_id] != start_vertex {
217 let curr_edge = triangles[curr_triangle].edges[curr_edge_id];
218 let curr_vertex = triangles[curr_triangle].vertices[curr_edge_id];
219 triangles[curr_triangle].parent_face = Some(new_face_id);
220
221 if !edges[curr_edge].deleted {
222 edges_adj_to_face.push(curr_edge);
223 vertices_adj_to_face.push(curr_vertex);
224 new_face.num_vertices_or_edges += 1;
225
226 curr_edge_id = (curr_edge_id + 1) % 3;
227 } else {
228 curr_triangle = edges[curr_edge].other_triangle(curr_triangle);
230 curr_edge_id = triangles[curr_triangle].next_edge_id(curr_edge);
231 assert!(
232 triangles[curr_triangle].vertices[curr_edge_id] == curr_vertex
233 );
234 }
235 }
236
237 if new_face.num_vertices_or_edges > 2 {
238 faces.push(new_face);
239 }
240 break;
241 }
242 }
243 }
244 }
245
246 for e in &mut edges {
248 if let Some(fid) = triangles[e.faces[0]].parent_face {
249 e.faces[0] = fid;
250 }
251
252 if let Some(fid) = triangles[e.faces[1]].parent_face {
253 e.faces[1] = fid;
254 }
255 }
256
257 let empty_vertex = Vertex {
261 first_adj_face_or_edge: 0,
262 num_adj_faces_or_edge: 0,
263 };
264
265 vertices.resize(points.len(), empty_vertex);
266
267 for face in &faces {
269 let first_vid = face.first_vertex_or_edge;
270 let last_vid = face.first_vertex_or_edge + face.num_vertices_or_edges;
271
272 for i in &vertices_adj_to_face[first_vid..last_vid] {
273 vertices[*i].num_adj_faces_or_edge += 1;
274 }
275 }
276
277 let mut total_num_adj_faces = 0;
279 for v in &mut vertices {
280 v.first_adj_face_or_edge = total_num_adj_faces;
281 total_num_adj_faces += v.num_adj_faces_or_edge;
282 }
283 faces_adj_to_vertex.resize(total_num_adj_faces, 0);
284 edges_adj_to_vertex.resize(total_num_adj_faces, 0);
285
286 for v in &mut vertices {
290 v.num_adj_faces_or_edge = 0;
291 }
292
293 for face_id in 0..faces.len() {
294 let face = &faces[face_id];
295 let first_vid = face.first_vertex_or_edge;
296 let last_vid = face.first_vertex_or_edge + face.num_vertices_or_edges;
297
298 for vid in first_vid..last_vid {
299 let v = &mut vertices[vertices_adj_to_face[vid]];
300 faces_adj_to_vertex[v.first_adj_face_or_edge + v.num_adj_faces_or_edge] = face_id;
301 edges_adj_to_vertex[v.first_adj_face_or_edge + v.num_adj_faces_or_edge] =
302 edges_adj_to_face[vid];
303 v.num_adj_faces_or_edge += 1;
304 }
305 }
306
307 let mut num_valid_vertices = 0;
308
309 for v in &vertices {
310 if v.num_adj_faces_or_edge != 0 {
311 num_valid_vertices += 1;
312 }
313 }
314
315 if num_valid_vertices + faces.len() - num_valid_edges != 2 {
317 None
318 } else {
319 let res = ConvexHull {
320 points,
321 vertices,
322 faces,
323 edges,
324 faces_adj_to_vertex,
325 edges_adj_to_vertex,
326 edges_adj_to_face,
327 vertices_adj_to_face,
328 };
329
330 Some(res)
334 }
335 }
336
337 #[inline]
339 pub fn check_geometry(&self) {
340 for face in &self.faces {
341 let p0 = self.points[self.vertices_adj_to_face[face.first_vertex_or_edge]];
342
343 for v in &self.points {
344 assert!((v - p0).dot(face.normal.as_ref()) <= N::default_epsilon());
345 }
346 }
347 }
348
349 #[inline]
351 pub fn points(&self) -> &[Point<N>] {
352 &self.points[..]
353 }
354
355 pub fn tangent_cone_contains_dir(
357 &self,
358 feature: FeatureId,
359 m: &Isometry<N>,
360 dir: &Unit<Vector<N>>,
361 ) -> bool {
362 let ls_dir = m.inverse_transform_unit_vector(dir);
363
364 match feature {
365 FeatureId::Face(id) => ls_dir.dot(&self.faces[id].normal) <= N::zero(),
366 FeatureId::Edge(id) => {
367 let edge = &self.edges[id];
368 ls_dir.dot(&self.faces[edge.faces[0]].normal) <= N::zero()
369 && ls_dir.dot(&self.faces[edge.faces[1]].normal) <= N::zero()
370 }
371 FeatureId::Vertex(id) => {
372 let vertex = &self.vertices[id];
373 let first = vertex.first_adj_face_or_edge;
374 let last = vertex.first_adj_face_or_edge + vertex.num_adj_faces_or_edge;
375
376 for face in &self.faces_adj_to_vertex[first..last] {
377 if ls_dir.dot(&self.faces[*face].normal) > N::zero() {
378 return false;
379 }
380 }
381
382 true
383 }
384 FeatureId::Unknown => false,
385 }
386 }
387
388 fn support_feature_id_toward_eps(&self, local_dir: &Unit<Vector<N>>, eps: N) -> FeatureId {
389 let (seps, ceps) = eps.sin_cos();
390 let support_pt_id = utils::point_cloud_support_point_id(local_dir.as_ref(), &self.points);
391 let vertex = &self.vertices[support_pt_id];
392
393 for i in 0..vertex.num_adj_faces_or_edge {
395 let face_id = self.faces_adj_to_vertex[vertex.first_adj_face_or_edge + i];
396 let face = &self.faces[face_id];
397
398 if face.normal.dot(local_dir.as_ref()) >= ceps {
399 return FeatureId::Face(face_id);
400 }
401 }
402
403 for i in 0..vertex.num_adj_faces_or_edge {
405 let edge_id = self.edges_adj_to_vertex[vertex.first_adj_face_or_edge + i];
406 let edge = &self.edges[edge_id];
407
408 if edge.dir.dot(local_dir.as_ref()).abs() <= seps {
409 return FeatureId::Edge(edge_id);
410 }
411 }
412
413 FeatureId::Vertex(support_pt_id)
415 }
416}
417
418impl<N: RealField + Copy> SupportMap<N> for ConvexHull<N> {
419 #[inline]
420 fn local_support_point(&self, dir: &Vector<N>) -> Point<N> {
421 utils::point_cloud_support_point(dir, self.points())
422 }
423}
424
425impl<N: RealField + Copy> ConvexPolyhedron<N> for ConvexHull<N> {
426 fn vertex(&self, id: FeatureId) -> Point<N> {
427 self.points[id.unwrap_vertex()]
428 }
429
430 fn edge(&self, id: FeatureId) -> (Point<N>, Point<N>, FeatureId, FeatureId) {
431 let edge = &self.edges[id.unwrap_edge()];
432 let v1 = edge.vertices[0];
433 let v2 = edge.vertices[1];
434
435 (
436 self.points[v1],
437 self.points[v2],
438 FeatureId::Vertex(v1),
439 FeatureId::Vertex(v2),
440 )
441 }
442
443 fn face(&self, id: FeatureId, out: &mut ConvexPolygonalFeature<N>) {
444 out.clear();
445
446 let face = &self.faces[id.unwrap_face()];
447 let first_vertex = face.first_vertex_or_edge;
448 let last_vertex = face.first_vertex_or_edge + face.num_vertices_or_edges;
449
450 for i in first_vertex..last_vertex {
451 let vid = self.vertices_adj_to_face[i];
452 let eid = self.edges_adj_to_face[i];
453 out.push(self.points[vid], FeatureId::Vertex(vid));
454 out.push_edge_feature_id(FeatureId::Edge(eid));
455 }
456
457 out.set_normal(face.normal);
458 out.set_feature_id(id);
459 out.recompute_edge_normals();
460 }
461
462 fn feature_normal(&self, feature: FeatureId) -> Unit<Vector<N>> {
463 match feature {
464 FeatureId::Face(id) => self.faces[id].normal,
465 FeatureId::Edge(id) => {
466 let edge = &self.edges[id];
467 Unit::new_normalize(
468 *self.faces[edge.faces[0]].normal + *self.faces[edge.faces[1]].normal,
469 )
470 }
471 FeatureId::Vertex(id) => {
472 let vertex = &self.vertices[id];
473 let first = vertex.first_adj_face_or_edge;
474 let last = vertex.first_adj_face_or_edge + vertex.num_adj_faces_or_edge;
475 let mut normal = Vector::zeros();
476
477 for face in &self.faces_adj_to_vertex[first..last] {
478 normal += *self.faces[*face].normal
479 }
480
481 Unit::new_normalize(normal)
482 }
483 FeatureId::Unknown => panic!("Invalid feature ID: {:?}", feature),
484 }
485 }
486
487 fn support_face_toward(
488 &self,
489 m: &Isometry<N>,
490 dir: &Unit<Vector<N>>,
491 out: &mut ConvexPolygonalFeature<N>,
492 ) {
493 let ls_dir = m.inverse_transform_vector(dir);
494 let mut best_face = 0;
495 let mut max_dot = self.faces[0].normal.dot(&ls_dir);
496
497 for i in 1..self.faces.len() {
498 let face = &self.faces[i];
499 let dot = face.normal.dot(&ls_dir);
500
501 if dot > max_dot {
502 max_dot = dot;
503 best_face = i;
504 }
505 }
506
507 self.face(FeatureId::Face(best_face), out);
508 out.transform_by(m);
509 }
510
511 fn support_feature_toward(
512 &self,
513 transform: &Isometry<N>,
514 dir: &Unit<Vector<N>>,
515 angle: N,
516 out: &mut ConvexPolygonalFeature<N>,
517 ) {
518 out.clear();
519 let local_dir = transform.inverse_transform_unit_vector(dir);
520 let fid = self.support_feature_id_toward_eps(&local_dir, angle);
521
522 match fid {
523 FeatureId::Vertex(_) => {
524 let v = self.vertex(fid);
525 out.push(v, fid);
526 out.set_feature_id(fid);
527 }
528 FeatureId::Edge(_) => {
529 let edge = self.edge(fid);
530 out.push(edge.0, edge.2);
531 out.push(edge.1, edge.3);
532 out.set_feature_id(fid);
533 out.push_edge_feature_id(fid);
534 }
535 FeatureId::Face(_) => self.face(fid, out),
536 FeatureId::Unknown => unreachable!(),
537 }
538
539 out.transform_by(transform);
540 }
541
542 fn support_feature_id_toward(&self, local_dir: &Unit<Vector<N>>) -> FeatureId {
543 let eps: N = na::convert(f64::consts::PI / 180.0);
544 self.support_feature_id_toward_eps(local_dir, eps)
545 }
546}