use alga::general::Id; use na; use query::{PointProjection, PointQuery, PointQueryWithLocation}; use shape::{BaseMesh, BaseMeshElement, Polyline, Segment, TriMesh}; use bounding_volume::AABB; use partitioning::{BVTCostFn, BVTVisitor}; use math::{Isometry, Point}; impl
PointQuery
for BaseMesh
where P: Point, M: Isometry
, E: BaseMeshElement + PointQuery
+ PointQueryWithLocation
, { #[inline] fn project_point(&self, m: &M, point: &P, solid: bool) -> PointProjection
{ let (projection, _) = self.project_point_with_location(m, point, solid); projection } #[inline] fn contains_point(&self, m: &M, point: &P) -> bool { let ls_pt = m.inverse_transform_point(point); let mut test = PointContainementTest { mesh: self, point: &ls_pt, found: false, }; self.bvt().visit(&mut test); test.found } } impl
PointQueryWithLocation
for BaseMesh
where P: Point, M: Isometry
, E: BaseMeshElement + PointQueryWithLocation
,
{
type Location = PointProjectionInfo , Self::Location) {
let ls_pt = m.inverse_transform_point(point);
let mut cost_fn = BaseMeshPointProjCostFn {
mesh: self,
point: &ls_pt,
};
let (mut proj, extra_info) = self.bvt().best_first_search(&mut cost_fn).unwrap().1;
proj.point = m.transform_point(&proj.point);
(proj, extra_info)
}
}
/*
* Costs function.
*/
struct BaseMeshPointProjCostFn<'a, P: 'a + Point, I: 'a, E: 'a> {
mesh: &'a BaseMesh ,
point: &'a P,
}
impl<'a, P, I, E> BVTCostFn ,
{
type UserData = (PointProjection , PointProjectionInfo ) -> Option ,
point: &'a P,
found: bool,
}
impl<'a, P, I, E> BVTVisitor ,
{
#[inline]
fn visit_internal(&mut self, bv: &AABB ) -> bool {
!self.found && bv.contains_point(&Id::new(), self.point)
}
#[inline]
fn visit_leaf(&mut self, b: &usize, bv: &AABB ) {
if !self.found && bv.contains_point(&Id::new(), self.point)
&& self.mesh
.element_at(*b)
.contains_point(&Id::new(), self.point)
{
self.found = true;
}
}
}
/// Additional point pojection info for base meshes
#[derive(Debug)]
pub struct PointProjectionInfo for TriMesh {
#[inline]
fn project_point(&self, m: &M, point: &P, solid: bool) -> PointProjection {
self.base_mesh().project_point(m, point, solid)
}
#[inline]
fn distance_to_point(&self, m: &M, point: &P, solid: bool) -> P::Real {
self.base_mesh().distance_to_point(m, point, solid)
}
#[inline]
fn contains_point(&self, m: &M, point: &P) -> bool {
self.base_mesh().contains_point(m, point)
}
}
impl for Polyline {
#[inline]
fn project_point(&self, m: &M, point: &P, solid: bool) -> PointProjection {
let (projection, _) = self.project_point_with_location(m, point, solid);
projection
}
#[inline]
fn distance_to_point(&self, m: &M, point: &P, solid: bool) -> P::Real {
self.base_mesh().distance_to_point(m, point, solid)
}
#[inline]
fn contains_point(&self, m: &M, point: &P) -> bool {
self.base_mesh().contains_point(m, point)
}
}
impl for Polyline {
type Location = PointProjectionInfo< >::Location>;
#[inline]
fn project_point_with_location(
&self,
m: &M,
point: &P,
solid: bool,
) -> (PointProjection , Self::Location) {
self.base_mesh()
.project_point_with_location(m, point, solid)
}
}