parry2d/query/point/
point_support_map.rs1use crate::math::{Pose, Vector};
2#[cfg(feature = "alloc")]
3use crate::query::epa::EPA;
4use crate::query::gjk::{self, ConstantOrigin, CsoPoint, VoronoiSimplex};
5use crate::query::{PointProjection, PointQuery};
6#[cfg(feature = "dim2")]
7#[cfg(feature = "alloc")]
8use crate::shape::ConvexPolygon;
9#[cfg(feature = "dim3")]
10#[cfg(feature = "alloc")]
11use crate::shape::ConvexPolyhedron;
12use crate::shape::{FeatureId, SupportMap};
13
14pub fn local_point_projection_on_support_map<G>(
16 shape: &G,
17 simplex: &mut VoronoiSimplex,
18 point: Vector,
19 solid: bool,
20) -> PointProjection
21where
22 G: SupportMap,
23{
24 #[cfg(feature = "dim2")]
25 let m = Pose::new(-point, 0.0);
26 #[cfg(feature = "dim3")]
27 let m = Pose::new(-point, Vector::ZERO);
28 #[cfg(feature = "dim2")]
29 let m_inv = Pose::new(point, 0.0);
30 #[cfg(feature = "dim3")]
31 let m_inv = Pose::new(point, Vector::ZERO);
32 let dir = (-m.translation).try_normalize().unwrap_or(Vector::X);
33 let support_point = CsoPoint::from_shapes(&m_inv, shape, &ConstantOrigin, dir);
34
35 simplex.reset(support_point);
36
37 if let Some(proj) = gjk::project_origin(&m, shape, simplex) {
38 PointProjection::new(false, proj)
39 } else if solid {
40 PointProjection::new(true, point)
41 } else {
42 let mut epa = EPA::new();
43 if let Some(pt) = epa.project_origin(&m, shape, simplex) {
44 PointProjection::new(true, pt)
45 } else {
46 PointProjection::new(true, point)
53 }
54 }
55}
56
57#[cfg(feature = "dim3")]
58impl PointQuery for ConvexPolyhedron {
59 #[inline]
60 fn project_local_point(&self, point: Vector, solid: bool) -> PointProjection {
61 local_point_projection_on_support_map(self, &mut VoronoiSimplex::new(), point, solid)
62 }
63
64 #[inline]
65 fn project_local_point_and_get_feature(&self, point: Vector) -> (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) = (local_dir).try_normalize() {
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: Vector, 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(&self, point: Vector) -> (PointProjection, FeatureId) {
88 let proj = self.project_local_point(point, false);
89 let dpt = point - proj.point;
90 let local_dir = if proj.is_inside { -dpt } else { dpt };
91
92 if let Some(local_dir) = (local_dir).try_normalize() {
93 let feature = self.support_feature_id_toward(local_dir);
94 (proj, feature)
95 } else {
96 (proj, FeatureId::Unknown)
97 }
98 }
99}