use na::{Transform, Identity}; use na; use point::PointQuery; use entities::shape::{BaseMesh, BaseMeshElement, TriMesh, Polyline}; use entities::bounding_volume::AABB; use entities::partitioning::{BVTCostFn, BVTVisitor}; use math::{Point, Vector}; impl PointQuery for BaseMesh where P: Point, M: Transform

, E: BaseMeshElement + PointQuery { #[inline] fn project_point(&self, m: &M, point: &P, _: bool) -> P { let ls_pt = m.inverse_transform(point); let mut cost_fn = BaseMeshPointProjCostFn { mesh: self, point: &ls_pt }; m.transform(&self.bvt().best_first_search(&mut cost_fn).unwrap().1) } #[inline] fn distance_to_point(&self, m: &M, point: &P) -> ::Scalar { na::distance(point, &self.project_point(m, point, true)) } #[inline] fn contains_point(&self, m: &M, point: &P) -> bool { let ls_pt = m.inverse_transform(point); let mut test = PointContainementTest { mesh: self, point: &ls_pt, found: false }; self.bvt().visit(&mut test); test.found } } /* * Costs function. */ struct BaseMeshPointProjCostFn<'a, P: 'a + Point, I: 'a, E: 'a> { mesh: &'a BaseMesh, point: &'a P } impl<'a, P, I, E> BVTCostFn<::Scalar, usize, AABB

> for BaseMeshPointProjCostFn<'a, P, I, E> where P: Point, E: BaseMeshElement + PointQuery { type UserData = P; #[inline] fn compute_bv_cost(&mut self, aabb: &AABB

) -> Option<::Scalar> { Some(aabb.distance_to_point(&Identity::new(), self.point)) } #[inline] fn compute_b_cost(&mut self, b: &usize) -> Option<(::Scalar, P)> { let proj = self.mesh.element_at(*b).project_point(&Identity::new(), self.point, true); Some((na::distance(self.point, &proj), proj)) } } /* * Visitor. */ /// Bounding Volume Tree visitor collecting nodes that may contain a given point. struct PointContainementTest<'a, P: 'a + Point, I: 'a, E: 'a> { mesh: &'a BaseMesh, point: &'a P, found: bool } impl<'a, P, I, E> BVTVisitor> for PointContainementTest<'a, P, I, E> where P: Point, E: BaseMeshElement + PointQuery { #[inline] fn visit_internal(&mut self, bv: &AABB

) -> bool { !self.found && bv.contains_point(&Identity::new(), self.point) } #[inline] fn visit_leaf(&mut self, b: &usize, bv: &AABB

) { if !self.found && bv.contains_point(&Identity::new(), self.point) && self.mesh.element_at(*b).contains_point(&Identity::new(), self.point) { self.found = true; } } } /* * fwd impls to exact meshes. */ impl PointQuery for TriMesh

where P: Point, M: Transform

{ #[inline] fn project_point(&self, m: &M, point: &P, solid: bool) -> P { self.base_mesh().project_point(m, point, solid) } #[inline] fn distance_to_point(&self, m: &M, point: &P) -> ::Scalar { self.base_mesh().distance_to_point(m, point) } #[inline] fn contains_point(&self, m: &M, point: &P) -> bool { self.base_mesh().contains_point(m, point) } } impl PointQuery for Polyline

where P: Point, M: Transform

{ #[inline] fn project_point(&self, m: &M, point: &P, solid: bool) -> P { self.base_mesh().project_point(m, point, solid) } #[inline] fn distance_to_point(&self, m: &M, point: &P) -> ::Scalar { self.base_mesh().distance_to_point(m, point) } #[inline] fn contains_point(&self, m: &M, point: &P) -> bool { self.base_mesh().contains_point(m, point) } }