parry2d/query/contact/
contact_support_map_support_map.rs1use crate::math::{Pose, Real, Vector};
2use crate::query::epa::EPA;
3use crate::query::gjk::{self, CsoPoint, GJKResult, VoronoiSimplex};
4use crate::query::Contact;
5use crate::shape::SupportMap;
6
7pub fn contact_support_map_support_map<G1, G2>(
9 pos12: &Pose,
10 g1: &G1,
11 g2: &G2,
12 prediction: Real,
13) -> Option<Contact>
14where
15 G1: ?Sized + SupportMap,
16 G2: ?Sized + SupportMap,
17{
18 let simplex = &mut VoronoiSimplex::new();
19 match contact_support_map_support_map_with_params(pos12, g1, g2, prediction, simplex, None) {
20 GJKResult::ClosestPoints(point1, point2_1, normal1) => {
21 let dist = (point2_1 - point1).dot(normal1);
22 let point2 = pos12.inverse_transform_point(point2_1);
23 let normal2 = pos12.rotation.inverse() * -normal1;
24 Some(Contact::new(point1, point2, normal1, normal2, dist))
25 }
26 GJKResult::NoIntersection(_) => None,
27 GJKResult::Intersection => unreachable!(),
28 GJKResult::Proximity(_) => unreachable!(),
29 }
30}
31
32pub fn contact_support_map_support_map_with_params<G1, G2>(
39 pos12: &Pose,
40 g1: &G1,
41 g2: &G2,
42 prediction: Real,
43 simplex: &mut VoronoiSimplex,
44 init_dir: Option<Vector>,
45) -> GJKResult
46where
47 G1: ?Sized + SupportMap,
48 G2: ?Sized + SupportMap,
49{
50 let dir = if let Some(init_dir) = init_dir {
51 init_dir
52 } else if let Some(init_dir) = (pos12.translation).try_normalize() {
53 init_dir
54 } else {
55 Vector::X
56 };
57
58 simplex.reset(CsoPoint::from_shapes(pos12, g1, g2, dir));
59
60 let cpts = gjk::closest_points(pos12, g1, g2, prediction, true, simplex);
61 if cpts != GJKResult::Intersection {
62 return cpts;
63 }
64
65 let mut epa = EPA::new();
67 if let Some((p1, p2, n)) = epa.closest_points(pos12, g1, g2, simplex) {
68 return GJKResult::ClosestPoints(p1, p2, n);
69 }
70
71 GJKResult::NoIntersection(Vector::X)
73}