use std::marker::PhantomData; use na::{Identity, Translate, Translation}; use na; use entities::bounding_volume::{self, HasBoundingVolume, AABB}; use entities::partitioning::BVTCostFn; use entities::shape::CompositeShape; use entities::inspection::Repr; use point::PointQuery; use geometry::distance_internal; use math::{Point, Vector, Isometry}; /// Smallest distance between a composite shape and any other shape. pub fn composite_shape_against_any(m1: &M, g1: &G1, m2: &M, g2: &G2) -> ::Scalar where P: Point, P::Vect: Translate

, M: Isometry + Translation, G1: CompositeShape, G2: Repr + HasBoundingVolume> { let mut cost_fn = CompositeShapeAgainstAnyDistCostFn::new(m1, g1, m2, g2); g1.bvt().best_first_search(&mut cost_fn).map(|(_, res)| res).expect("The composite shape must not be empty.") } /// Smallest distance between a shape and a composite shape. pub fn any_against_composite_shape(m1: &M, g1: &G1, m2: &M, g2: &G2) -> ::Scalar where P: Point, P::Vect: Translate

, M: Isometry + Translation, G1: Repr + HasBoundingVolume>, G2: CompositeShape { composite_shape_against_any(m2, g2, m1, g1) } struct CompositeShapeAgainstAnyDistCostFn<'a, P: 'a + Point, M: 'a, G1: ?Sized + 'a, G2: ?Sized + 'a> { msum_shift: P::Vect, msum_margin: P::Vect, m1: &'a M, g1: &'a G1, m2: &'a M, g2: &'a G2, point_type: PhantomData

} impl<'a, P, M, G1: ?Sized, G2: ?Sized> CompositeShapeAgainstAnyDistCostFn<'a, P, M, G1, G2> where P: Point, M: Isometry, G1: CompositeShape, G2: Repr + HasBoundingVolume> { pub fn new(m1: &'a M, g1: &'a G1, m2: &'a M, g2: &'a G2) -> CompositeShapeAgainstAnyDistCostFn<'a, P, M, G1, G2> { let ls_m2 = na::inverse(m1).expect("The transformation `m1` must be inversible.") * *m2; let ls_aabb2 = bounding_volume::aabb(g2, &ls_m2); CompositeShapeAgainstAnyDistCostFn { msum_shift: -ls_aabb2.center().to_vector(), msum_margin: ls_aabb2.half_extents(), m1: m1, g1: g1, m2: m2, g2: g2, point_type: PhantomData } } } impl<'a, P, M, G1: ?Sized, G2: ?Sized> BVTCostFn<::Scalar, usize, AABB

> for CompositeShapeAgainstAnyDistCostFn<'a, P, M, G1, G2> where P: Point, P::Vect: Translate

, M: Isometry + Translation, G1: CompositeShape, G2: Repr + HasBoundingVolume> { type UserData = ::Scalar; #[inline] fn compute_bv_cost(&mut self, bv: &AABB

) -> Option<::Scalar> { // Compute the minkowski sum of the two AABBs. let msum = AABB::new(*bv.mins() + self.msum_shift + (-self.msum_margin), *bv.maxs() + self.msum_shift + self.msum_margin); // Compute the distance to the origin. Some(msum.distance_to_point(&Identity::new(), &na::origin())) } #[inline] fn compute_b_cost(&mut self, b: &usize) -> Option<(::Scalar, ::Scalar)> { let mut res = None; self.g1.map_transformed_part_at(*b, self.m1, &mut |m1, g1| { let distance = distance_internal::distance(m1, g1, self.m2, self.g2); res = Some((distance, distance)) }); res } }