ncollide3d/query/point/
point_compound.rs

1use crate::bounding_volume::AABB;
2use crate::math::{Isometry, Point};
3use crate::partitioning::{BestFirstVisitStatus, BestFirstVisitor, BVH};
4use crate::query::{visitors::CompositePointContainmentTest, PointProjection, PointQuery};
5use crate::shape::{CompositeShape, Compound, FeatureId};
6use na::{self, RealField};
7
8impl<N: RealField + Copy> PointQuery<N> for Compound<N> {
9    // XXX: if solid == false, this might return internal projection.
10    #[inline]
11    fn project_point(&self, m: &Isometry<N>, point: &Point<N>, solid: bool) -> PointProjection<N> {
12        let ls_pt = m.inverse_transform_point(point);
13        let mut visitor = CompoundPointProjVisitor {
14            compound: self,
15            point: &ls_pt,
16            solid: solid,
17        };
18
19        let mut proj = self.bvt().best_first_search(&mut visitor).unwrap().1;
20        proj.point = m * proj.point;
21
22        proj
23    }
24
25    #[inline]
26    fn project_point_with_feature(
27        &self,
28        _: &Isometry<N>,
29        _: &Point<N>,
30    ) -> (PointProjection<N>, FeatureId) {
31        // XXX Properly propagate the feature id.
32        unimplemented!()
33        // (self.project_point(m, point), FeatureId::Unknown)
34    }
35
36    #[inline]
37    fn contains_point(&self, m: &Isometry<N>, point: &Point<N>) -> bool {
38        let ls_pt = m.inverse_transform_point(point);
39        let mut visitor = CompositePointContainmentTest {
40            shape: self,
41            point: &ls_pt,
42            found: false,
43        };
44
45        self.bvt().visit(&mut visitor);
46
47        visitor.found
48    }
49}
50
51/*
52 * Visitors
53 */
54struct CompoundPointProjVisitor<'a, N: 'a + RealField + Copy> {
55    compound: &'a Compound<N>,
56    point: &'a Point<N>,
57    solid: bool,
58}
59
60impl<'a, N: RealField + Copy> BestFirstVisitor<N, usize, AABB<N>>
61    for CompoundPointProjVisitor<'a, N>
62{
63    type Result = PointProjection<N>;
64
65    #[inline]
66    fn visit(
67        &mut self,
68        best: N,
69        aabb: &AABB<N>,
70        data: Option<&usize>,
71    ) -> BestFirstVisitStatus<N, Self::Result> {
72        let dist = aabb.distance_to_point(&Isometry::identity(), self.point, true);
73
74        let mut res = BestFirstVisitStatus::Continue {
75            cost: dist,
76            result: None,
77        };
78
79        if let Some(b) = data {
80            if dist < best {
81                self.compound
82                    .map_part_at(*b, &Isometry::identity(), &mut |objm, obj| {
83                        let proj = obj.project_point(objm, self.point, self.solid);
84
85                        res = BestFirstVisitStatus::Continue {
86                            cost: na::distance(self.point, &proj.point),
87                            result: Some(proj),
88                        };
89                    });
90            }
91        }
92
93        res
94    }
95}