parry3d/query/point/
point_support_map.rs1use na::Unit;
2
3use crate::math::{Isometry, Point, Real, Vector};
4#[cfg(feature = "alloc")]
5use crate::query::epa::EPA;
6use crate::query::gjk::{self, CSOPoint, ConstantOrigin, VoronoiSimplex};
7use crate::query::{PointProjection, PointQuery};
8#[cfg(feature = "dim2")]
9#[cfg(feature = "alloc")]
10use crate::shape::ConvexPolygon;
11#[cfg(feature = "dim3")]
12#[cfg(feature = "alloc")]
13use crate::shape::ConvexPolyhedron;
14use crate::shape::{FeatureId, SupportMap};
15
16pub fn local_point_projection_on_support_map<G>(
18 shape: &G,
19 simplex: &mut VoronoiSimplex,
20 point: &Point<Real>,
21 solid: bool,
22) -> PointProjection
23where
24 G: SupportMap,
25{
26 let m = Isometry::new(-point.coords, na::zero());
27 let m_inv = Isometry::new(point.coords, na::zero());
28 let dir = Unit::try_new(-m.translation.vector, crate::math::DEFAULT_EPSILON)
29 .unwrap_or(Vector::x_axis());
30 let support_point = CSOPoint::from_shapes(&m_inv, shape, &ConstantOrigin, &dir);
31
32 simplex.reset(support_point);
33
34 if let Some(proj) = gjk::project_origin(&m, shape, simplex) {
35 PointProjection::new(false, proj)
36 } else if solid {
37 PointProjection::new(true, *point)
38 } else {
39 let mut epa = EPA::new();
40 if let Some(pt) = epa.project_origin(&m, shape, simplex) {
41 return PointProjection::new(true, pt);
42 } else {
43 PointProjection::new(true, *point)
50 }
51 }
52}
53
54#[cfg(feature = "dim3")]
55impl PointQuery for ConvexPolyhedron {
56 #[inline]
57 fn project_local_point(&self, point: &Point<Real>, solid: bool) -> PointProjection {
58 local_point_projection_on_support_map(self, &mut VoronoiSimplex::new(), point, solid)
59 }
60
61 #[inline]
62 fn project_local_point_and_get_feature(
63 &self,
64 point: &Point<Real>,
65 ) -> (PointProjection, FeatureId) {
66 let proj = self.project_local_point(point, false);
67 let dpt = *point - proj.point;
68 let local_dir = if proj.is_inside { -dpt } else { dpt };
69
70 if let Some(local_dir) = Unit::try_new(local_dir, crate::math::DEFAULT_EPSILON) {
71 let feature = self.support_feature_id_toward(&local_dir);
72 (proj, feature)
73 } else {
74 (proj, FeatureId::Unknown)
75 }
76 }
77}
78
79#[cfg(feature = "dim2")]
80impl PointQuery for ConvexPolygon {
81 #[inline]
82 fn project_local_point(&self, point: &Point<Real>, solid: bool) -> PointProjection {
83 local_point_projection_on_support_map(self, &mut VoronoiSimplex::new(), point, solid)
84 }
85
86 #[inline]
87 fn project_local_point_and_get_feature(
88 &self,
89 point: &Point<Real>,
90 ) -> (PointProjection, FeatureId) {
91 let proj = self.project_local_point(point, false);
92 let dpt = *point - proj.point;
93 let local_dir = if proj.is_inside { -dpt } else { dpt };
94
95 if let Some(local_dir) = Unit::try_new(local_dir, crate::math::DEFAULT_EPSILON) {
96 let feature = self.support_feature_id_toward(&local_dir);
97 (proj, feature)
98 } else {
99 (proj, FeatureId::Unknown)
100 }
101 }
102}