Move traversal traits to internal file

This commit is contained in:
iyaz 2013-06-11 19:08:30 +03:00
parent c0961890c1
commit 61fbd78bde
2 changed files with 200 additions and 188 deletions

View File

@ -21,200 +21,14 @@
#ifndef CGAL_POINT_INSIDE_POLYHEDRON_H
#define CGAL_POINT_INSIDE_POLYHEDRON_H
#include <CGAL/internal/Point_inside_Polyhedron/Ray_3_Triangle_3_traversal_traits.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_polyhedron_triangle_primitive.h>
#include <CGAL/Random.h>
#include <CGAL/point_generators_3.h>
#include <boost/logic/tribool.hpp>
#include <boost/math/special_functions/round.hpp>
namespace CGAL {
template<typename AABBTraits, class Polyhedron_3, class Kernel,class Tag_ray_is_vertical=Tag_false>
class Ray_3_Triangle_3_traversal_traits
{
protected:
//the status indicates whether the query point is strictly inside the polyhedron, and the number of intersected triangles if yes
std::pair<boost::logic::tribool,std::size_t>& m_status;
bool m_stop;
typedef CGAL::AABB_polyhedron_triangle_primitive<Kernel,Polyhedron_3> Primitive;
public:
Ray_3_Triangle_3_traversal_traits(std::pair<boost::logic::tribool,std::size_t>& status)
:m_status(status),m_stop(false)
{m_status.first=true;}
bool go_further() const { return !m_stop; }
template<class Query>
void intersection(const Query& query, const Primitive& primitive)
{
internal::r3t3_do_intersect_endpoint_position_visitor visitor;
std::pair<bool,internal::R3T3_intersection::type> res=
internal::do_intersect(primitive.datum(),query,Kernel(),visitor);
if (res.first){
switch (res.second){
case internal::R3T3_intersection::CROSS_FACET:
++m_status.second;
break;
case internal::R3T3_intersection::ENDPOINT_IN_TRIANGLE:
m_status.first=false;
m_stop=true;
break;
default:
m_status.first=boost::logic::indeterminate;
m_stop=true;
}
}
}
template<class Query,class Node>
bool do_intersect(const Query& query, const Node& node) const
{
return AABBTraits().do_intersect_object()(query, node.bbox());
}
};
//specialization for vertical ray
template<typename AABBTraits,class Polyhedron_3, class Kernel>
class Ray_3_Triangle_3_traversal_traits<AABBTraits,Polyhedron_3,Kernel,Tag_true>:
public Ray_3_Triangle_3_traversal_traits<AABBTraits,Polyhedron_3,Kernel,Tag_false>
{
typedef Ray_3_Triangle_3_traversal_traits<AABBTraits,Polyhedron_3,Kernel,Tag_false> Base;
typedef typename Kernel::Point_3 Point;
typedef typename Base::Primitive Primitive;
public:
Ray_3_Triangle_3_traversal_traits(std::pair<boost::logic::tribool,std::size_t>& status):Base(status){}
template <class Query>
bool do_intersect(const Query& query, const Bbox_3& bbox) const
{
const Point& source=query.point(0);
const Point& target=query.point(1);
bool inc_z=target.z()>source.z();
//the ray does not intersect the z-slab
if ( ( inc_z && source.z()>bbox.zmax() )|| (!inc_z && source.z()<bbox.zmin()) ) return false;
//the source is not in the x-slab
if (source.x() > bbox.xmax() || source.x()<bbox.xmin()) return false;
//check if the source is not in the y-slab
return source.y() <= bbox.ymax() && source.y()>=bbox.ymin();
}
template <class Query,class Node>
bool do_intersect(const Query& query, const Node& node) const
{
return do_intersect(query,node.bbox());
}
private:
typename Kernel::Point_2 x_project(const typename Kernel::Point_3& p) const{
return typename Kernel::Point_2(p.y(),p.z());
}
typename Kernel::Point_2 y_project(const typename Kernel::Point_3& p) const{
return typename Kernel::Point_2(p.x(),p.z());
}
typename Kernel::Point_2 z_project(const typename Kernel::Point_3& p) const{
return typename Kernel::Point_2(p.x(),p.y());
}
public:
template<class Query>
void intersection(const Query& query, const Primitive& primitive)
{
typename Kernel::Triangle_3 t=primitive.datum();
if ( !do_intersect(query,t.bbox()) ) return;
typename Kernel::Point_2 p0=z_project(t[0]);
typename Kernel::Point_2 p1=z_project(t[1]);
typename Kernel::Point_2 p2=z_project(t[2]);
int indices[3]={0,1,2}; //to track whether triangle points have been swapt
typename Kernel::Point_2 q=z_project( query.source() );
Orientation orient_2=orientation(p0,p1,p2);
//check whether the face has a normal vector in the xy-plane
if (orient_2==COLLINEAR){
//in that case the projection of the triangle along the z-axis is a segment.
const typename Kernel::Point_2& other_point = p0!=p1?p1:p2;
//~ if ( orientation(p0,other_point,q) != COLLINEAR ) return;///no intersection
if ( orientation(p0,other_point,q) != COLLINEAR ) return;///no intersection
//check if the ray source is above or below the triangle and compare it
//with the direction of the ray
//TODO and if yes return
//this is just an optimisation, the current code is valid
this->m_status.first=boost::logic::indeterminate;
this->m_stop=true;
return;
}
//regular case
if (orient_2==NEGATIVE){
std::swap(p1,p2);
std::swap(indices[1],indices[2]);
}
//check whether the ray intersect the supporting plane
Orientation orient_3 = orientation(t[indices[0]],t[indices[1]],t[indices[2]],query.source());
if ( orient_3!=COPLANAR &&
(
//indicates whether the ray is oriented toward the positive side of the plane
( POSITIVE == sign( query.to_vector().z() ) )
==
//indicates whether the source of the ray is in the positive side of the plane
(orient_3==POSITIVE)
)
) return; //no intersection
//position against first segment
switch( orientation(p0,p1,q) ){
case COLLINEAR:
this->m_status.first=boost::logic::indeterminate;
this->m_stop=true;
case NEGATIVE:
return;
default:
{}
}
//position against second segment
switch( orientation(p1,p2,q) ){
case COLLINEAR:
this->m_status.first=boost::logic::indeterminate;
this->m_stop=true;
case NEGATIVE:
return;
default:
{}
}
//position against third segment
switch( orientation(p2,p0,q) ){
case COLLINEAR:
this->m_status.first=boost::logic::indeterminate;
this->m_stop=true;
case NEGATIVE:
return;
default:
{}
}
if (orient_3==COPLANAR){
//the endpoint is inside the triangle
this->m_status.first=false;
this->m_stop=true;
}
else
++(this->m_status.second);
}
};
template <class Polyhedron_3,class Kernel>
class Point_inside_polyhedron_3 {
@ -310,7 +124,7 @@ private:
is_inside_ray_tree_traversal(const Query& query) const {
std::pair<boost::logic::tribool,std::size_t> status(
boost::logic::tribool(boost::logic::indeterminate), 0);
Ray_3_Triangle_3_traversal_traits<Traits,Polyhedron_3,Kernel,Boolean_tag<ray_is_vertical> > traversal_traits(status);
internal::Ray_3_Triangle_3_traversal_traits<Traits,Polyhedron_3,Kernel,Boolean_tag<ray_is_vertical> > traversal_traits(status);
tree.traversal(query, traversal_traits);
if ( !boost::logic::indeterminate(status.first) ){
if (status.first) return (status.second&1) == 1;

View File

@ -0,0 +1,198 @@
#ifndef CGAL_POINT_INSIDE_POLYHEDRON_RAY_3_TRIANGLE_3_TRAVERSAL_TRAITS_H
#define CGAL_POINT_INSIDE_POLYHEDRON_RAY_3_TRIANGLE_3_TRAVERSAL_TRAITS_H
#include <boost/logic/tribool.hpp>
#include <CGAL/AABB_polyhedron_triangle_primitive.h>
namespace CGAL {
namespace internal {
template<typename AABBTraits, class Polyhedron_3, class Kernel,class Tag_ray_is_vertical=Tag_false>
class Ray_3_Triangle_3_traversal_traits
{
protected:
//the status indicates whether the query point is strictly inside the polyhedron, and the number of intersected triangles if yes
std::pair<boost::logic::tribool,std::size_t>& m_status;
bool m_stop;
typedef CGAL::AABB_polyhedron_triangle_primitive<Kernel,Polyhedron_3> Primitive;
public:
Ray_3_Triangle_3_traversal_traits(std::pair<boost::logic::tribool,std::size_t>& status)
:m_status(status),m_stop(false)
{m_status.first=true;}
bool go_further() const { return !m_stop; }
template<class Query>
void intersection(const Query& query, const Primitive& primitive)
{
internal::r3t3_do_intersect_endpoint_position_visitor visitor;
std::pair<bool,internal::R3T3_intersection::type> res=
internal::do_intersect(primitive.datum(),query,Kernel(),visitor);
if (res.first){
switch (res.second){
case internal::R3T3_intersection::CROSS_FACET:
++m_status.second;
break;
case internal::R3T3_intersection::ENDPOINT_IN_TRIANGLE:
m_status.first=false;
m_stop=true;
break;
default:
m_status.first=boost::logic::indeterminate;
m_stop=true;
}
}
}
template<class Query,class Node>
bool do_intersect(const Query& query, const Node& node) const
{
return AABBTraits().do_intersect_object()(query, node.bbox());
}
};
//specialization for vertical ray
template<typename AABBTraits,class Polyhedron_3, class Kernel>
class Ray_3_Triangle_3_traversal_traits<AABBTraits,Polyhedron_3,Kernel,Tag_true>:
public Ray_3_Triangle_3_traversal_traits<AABBTraits,Polyhedron_3,Kernel,Tag_false>
{
typedef Ray_3_Triangle_3_traversal_traits<AABBTraits,Polyhedron_3,Kernel,Tag_false> Base;
typedef typename Kernel::Point_3 Point;
typedef typename Base::Primitive Primitive;
public:
Ray_3_Triangle_3_traversal_traits(std::pair<boost::logic::tribool,std::size_t>& status):Base(status){}
template <class Query>
bool do_intersect(const Query& query, const Bbox_3& bbox) const
{
const Point& source=query.point(0);
const Point& target=query.point(1);
bool inc_z=target.z()>source.z();
//the ray does not intersect the z-slab
if ( ( inc_z && source.z()>bbox.zmax() )|| (!inc_z && source.z()<bbox.zmin()) ) return false;
//the source is not in the x-slab
if (source.x() > bbox.xmax() || source.x()<bbox.xmin()) return false;
//check if the source is not in the y-slab
return source.y() <= bbox.ymax() && source.y()>=bbox.ymin();
}
template <class Query,class Node>
bool do_intersect(const Query& query, const Node& node) const
{
return do_intersect(query,node.bbox());
}
private:
typename Kernel::Point_2 x_project(const typename Kernel::Point_3& p) const{
return typename Kernel::Point_2(p.y(),p.z());
}
typename Kernel::Point_2 y_project(const typename Kernel::Point_3& p) const{
return typename Kernel::Point_2(p.x(),p.z());
}
typename Kernel::Point_2 z_project(const typename Kernel::Point_3& p) const{
return typename Kernel::Point_2(p.x(),p.y());
}
public:
template<class Query>
void intersection(const Query& query, const Primitive& primitive)
{
typename Kernel::Triangle_3 t=primitive.datum();
if ( !do_intersect(query,t.bbox()) ) return;
typename Kernel::Point_2 p0=z_project(t[0]);
typename Kernel::Point_2 p1=z_project(t[1]);
typename Kernel::Point_2 p2=z_project(t[2]);
int indices[3]={0,1,2}; //to track whether triangle points have been swapt
typename Kernel::Point_2 q=z_project( query.source() );
Orientation orient_2=orientation(p0,p1,p2);
//check whether the face has a normal vector in the xy-plane
if (orient_2==COLLINEAR){
//in that case the projection of the triangle along the z-axis is a segment.
const typename Kernel::Point_2& other_point = p0!=p1?p1:p2;
//~ if ( orientation(p0,other_point,q) != COLLINEAR ) return;///no intersection
if ( orientation(p0,other_point,q) != COLLINEAR ) return;///no intersection
//check if the ray source is above or below the triangle and compare it
//with the direction of the ray
//TODO and if yes return
//this is just an optimisation, the current code is valid
this->m_status.first=boost::logic::indeterminate;
this->m_stop=true;
return;
}
//regular case
if (orient_2==NEGATIVE){
std::swap(p1,p2);
std::swap(indices[1],indices[2]);
}
//check whether the ray intersect the supporting plane
Orientation orient_3 = orientation(t[indices[0]],t[indices[1]],t[indices[2]],query.source());
if ( orient_3!=COPLANAR &&
(
//indicates whether the ray is oriented toward the positive side of the plane
( POSITIVE == sign( query.to_vector().z() ) )
==
//indicates whether the source of the ray is in the positive side of the plane
(orient_3==POSITIVE)
)
) return; //no intersection
//position against first segment
switch( orientation(p0,p1,q) ){
case COLLINEAR:
this->m_status.first=boost::logic::indeterminate;
this->m_stop=true;
case NEGATIVE:
return;
default:
{}
}
//position against second segment
switch( orientation(p1,p2,q) ){
case COLLINEAR:
this->m_status.first=boost::logic::indeterminate;
this->m_stop=true;
case NEGATIVE:
return;
default:
{}
}
//position against third segment
switch( orientation(p2,p0,q) ){
case COLLINEAR:
this->m_status.first=boost::logic::indeterminate;
this->m_stop=true;
case NEGATIVE:
return;
default:
{}
}
if (orient_3==COPLANAR){
//the endpoint is inside the triangle
this->m_status.first=false;
this->m_stop=true;
}
else
++(this->m_status.second);
}
};
}// namespace internal
}// namespace CGAL
#endif