ncollide3d/query/distance/
distance_composite_shape_shape.rs1use crate::bounding_volume::AABB;
2use crate::math::{Isometry, Point, Vector};
3use crate::partitioning::{BestFirstVisitStatus, BestFirstVisitor};
4use crate::query::{self, PointQuery};
5use crate::shape::{CompositeShape, Shape};
6use na::{self, RealField};
7
8pub fn distance_composite_shape_shape<N, G1: ?Sized>(
10 m1: &Isometry<N>,
11 g1: &G1,
12 m2: &Isometry<N>,
13 g2: &dyn Shape<N>,
14) -> N
15where
16 N: RealField + Copy,
17 G1: CompositeShape<N>,
18{
19 let ls_m2 = m1.inverse() * m2.clone();
20 let ls_aabb2 = g2.aabb(&ls_m2);
21
22 let mut visitor = CompositeShapeAgainstAnyDistanceVisitor {
23 msum_shift: -ls_aabb2.center().coords,
24 msum_margin: ls_aabb2.half_extents(),
25 m1: m1,
26 g1: g1,
27 m2: m2,
28 g2: g2,
29 };
30
31 g1.bvh()
32 .best_first_search(&mut visitor)
33 .expect("The composite shape must not be empty.")
34 .1
35}
36
37pub fn distance_shape_composite_shape<N, G2: ?Sized>(
39 m1: &Isometry<N>,
40 g1: &dyn Shape<N>,
41 m2: &Isometry<N>,
42 g2: &G2,
43) -> N
44where
45 N: RealField + Copy,
46 G2: CompositeShape<N>,
47{
48 distance_composite_shape_shape(m2, g2, m1, g1)
49}
50
51struct CompositeShapeAgainstAnyDistanceVisitor<'a, N: 'a + RealField + Copy, G1: ?Sized + 'a> {
52 msum_shift: Vector<N>,
53 msum_margin: Vector<N>,
54
55 m1: &'a Isometry<N>,
56 g1: &'a G1,
57 m2: &'a Isometry<N>,
58 g2: &'a dyn Shape<N>,
59}
60
61impl<'a, N, G1: ?Sized> BestFirstVisitor<N, usize, AABB<N>>
62 for CompositeShapeAgainstAnyDistanceVisitor<'a, N, G1>
63where
64 N: RealField + Copy,
65 G1: CompositeShape<N>,
66{
67 type Result = N;
68
69 fn visit(
70 &mut self,
71 best: N,
72 bv: &AABB<N>,
73 data: Option<&usize>,
74 ) -> BestFirstVisitStatus<N, Self::Result> {
75 let msum = AABB::new(
77 bv.mins + self.msum_shift + (-self.msum_margin),
78 bv.maxs + self.msum_shift + self.msum_margin,
79 );
80
81 let dist = msum.distance_to_point(&Isometry::identity(), &Point::origin(), true);
82
83 let mut res = BestFirstVisitStatus::Continue {
84 cost: dist,
85 result: None,
86 };
87
88 if let Some(b) = data {
89 if dist < best {
90 self.g1.map_part_at(*b, self.m1, &mut |m1, g1| {
91 let distance = query::distance(m1, g1, self.m2, self.g2);
92 res = BestFirstVisitStatus::Continue {
93 cost: distance,
94 result: Some(distance),
95 }
96 });
97 }
98 }
99
100 res
101 }
102}