modify the internal do_intersect Ray_3 vs Triangle_3 function

to be able to known whether the endpoint of the ray lies inside the
plane of the triangle. The running time is the public do_intersect function
should remain the same.
This commit is contained in:
Sébastien Loriot 2012-03-21 18:20:04 +00:00
parent e9372eb7ae
commit b058a2a4f3
1 changed files with 119 additions and 62 deletions

View File

@ -25,15 +25,45 @@ namespace CGAL {
namespace internal { namespace internal {
template <class K> struct r3t3_do_intersect_empty_visitor{
bool do_intersect_coplanar(const typename K::Triangle_3 &t, typedef bool result_type;
const typename K::Ray_3 &r, result_type result(bool b){return b;}
const K & k ); void update(Orientation){}
};
template <class K> struct r3t3_do_intersect_endpoint_position_visitor{
bool do_intersect(const typename K::Triangle_3 &t, bool m_endpoint_outside_triangle_plane;
const typename K::Ray_3 &r, r3t3_do_intersect_endpoint_position_visitor():
const K & k) m_endpoint_outside_triangle_plane(true){}
typedef std::pair<bool,bool> result_type;
result_type result(bool b){return std::make_pair(b,m_endpoint_outside_triangle_plane);}
void update(Orientation orient)
{
m_endpoint_outside_triangle_plane &= orient!=ZERO;
}
};
//the template parameter Visitor here is used to offer the posibility to use
//r3t3_do_intersect_endpoint_position_visitor to track whether the endpoint of
//the ray lies inside the plane of the triangle or not. It is used for example
//in the function that checks whether a point is inside a polyhedron; if the ray
//is on an edge of the triangle, we should try with another random ray as this case does
//happen often in practise.
//By default an empty visitor is used to avoid penalizing the running time.
template <class K,class Visitor>
typename Visitor::result_type
do_intersect_coplanar(const typename K::Triangle_3 &t,
const typename K::Ray_3 &r,
const K & k,
Visitor visitor);
template <class K,class Visitor>
typename Visitor::result_type
do_intersect(const typename K::Triangle_3 &t,
const typename K::Ray_3 &r,
const K & k,
Visitor visitor)
{ {
CGAL_kernel_precondition( ! k.is_degenerate_3_object()(t) ) ; CGAL_kernel_precondition( ! k.is_degenerate_3_object()(t) ) ;
@ -70,8 +100,8 @@ bool do_intersect(const typename K::Triangle_3 &t,
if (ray_direction == COPLANAR ) { if (ray_direction == COPLANAR ) {
if (orientation(a,b,c,p) == COPLANAR) if (orientation(a,b,c,p) == COPLANAR)
return do_intersect_coplanar(t,r,k); return do_intersect_coplanar(t,r,k,visitor);
else return false; else return visitor.result(false);
} }
const Orientation abcp = orientation(a,b,c,p); const Orientation abcp = orientation(a,b,c,p);
@ -82,73 +112,98 @@ bool do_intersect(const typename K::Triangle_3 &t,
case POSITIVE: case POSITIVE:
// the ray lies in the positive open halfspaces defined by the // the ray lies in the positive open halfspaces defined by the
// triangle's supporting plane // triangle's supporting plane
return false; return visitor.result(false);
case NEGATIVE: case NEGATIVE:{
// The ray straddles the triangle's plane // The ray straddles the triangle's plane
// p sees the triangle in counterclockwise order // p sees the triangle in counterclockwise order
Orientation
return orientation(p,q,a,b) != POSITIVE orient=orientation(p,q,a,b);
&& orientation(p,q,b,c) != POSITIVE if (orient == POSITIVE ) return visitor.result(false);
&& orientation(p,q,c,a) != POSITIVE; visitor.update(orient);
orient=orientation(p,q,b,c);
// case COPLANAR: should not happen if (orient == POSITIVE ) return visitor.result(false);
visitor.update(orient);
orient=orientation(p,q,c,a);
if (orient == POSITIVE ) return visitor.result(false);
visitor.update(orient);
return visitor.result(true);
}
// case COPLANAR: should not happen
default: // should not happen. default: // should not happen.
CGAL_kernel_assertion(false); CGAL_kernel_assertion(false);
return false; return visitor.result(false);
} }
case NEGATIVE: case NEGATIVE:
switch ( ray_direction ) { switch ( ray_direction ) {
case POSITIVE: case POSITIVE:{
// The ray straddles the triangle's plane // The ray straddles the triangle's plane
// q sees the triangle in counterclockwise order // q sees the triangle in counterclockwise order
Orientation
orient=orientation(q,p,a,b);
if (orient == POSITIVE ) return visitor.result(false);
visitor.update(orient);
orient=orientation(q,p,b,c);
if (orient == POSITIVE ) return visitor.result(false);
visitor.update(orient);
orient=orientation(q,p,c,a);
if (orient == POSITIVE ) return visitor.result(false);
visitor.update(orient);
return visitor.result(true);
return orientation(q,p,a,b) != POSITIVE }
&& orientation(q,p,b,c) != POSITIVE
&& orientation(q,p,c,a) != POSITIVE;
case NEGATIVE: case NEGATIVE:
// the ray lies in the negative open halfspaces defined by the // the ray lies in the negative open halfspaces defined by the
// triangle's supporting plane // triangle's supporting plane
return false; return visitor.result(false);
// case COPLANAR: should not happen // case COPLANAR: should not happen
default: // should not happen. default: // should not happen.
CGAL_kernel_assertion(false); CGAL_kernel_assertion(false);
return false; return visitor.result(false);
} }
case COPLANAR: // p belongs to the triangle's supporting plane case COPLANAR: // p belongs to the triangle's supporting plane
visitor.update(ZERO);
switch ( ray_direction ) { switch ( ray_direction ) {
case POSITIVE: case POSITIVE:
// q sees the triangle in counterclockwise order // q sees the triangle in counterclockwise order
return orientation(q,p,a,b) != POSITIVE return visitor.result(
orientation(q,p,a,b) != POSITIVE
&& orientation(q,p,b,c) != POSITIVE && orientation(q,p,b,c) != POSITIVE
&& orientation(q,p,c,a) != POSITIVE; && orientation(q,p,c,a) != POSITIVE);
case NEGATIVE: case NEGATIVE:
// q sees the triangle in clockwise order // q sees the triangle in clockwise order
return orientation(p,q,a,b) != POSITIVE return visitor.result(
orientation(p,q,a,b) != POSITIVE
&& orientation(p,q,b,c) != POSITIVE && orientation(p,q,b,c) != POSITIVE
&& orientation(p,q,c,a) != POSITIVE; && orientation(p,q,c,a) != POSITIVE);
// case COPLANAR: should not happen // case COPLANAR: should not happen
default: // should not happen. default: // should not happen.
CGAL_kernel_assertion(false); CGAL_kernel_assertion(false);
return false; return visitor.result(false);
} }
default: // should not happen. default: // should not happen.
CGAL_kernel_assertion(false); CGAL_kernel_assertion(false);
return false; return visitor.result(false);
} }
} }
template <class K>
bool do_intersect(const typename K::Triangle_3 &t,
const typename K::Ray_3 &r,
const K & k)
{
return do_intersect(t,r,k,r3t3_do_intersect_empty_visitor());
}
template <class K> template <class K>
inline inline
@ -160,12 +215,14 @@ bool do_intersect(const typename K::Ray_3 &r,
} }
template <class K> template <class K,class Visitor>
bool do_intersect_coplanar(const typename K::Triangle_3 &t, typename Visitor::result_type
const typename K::Ray_3 &r, do_intersect_coplanar(const typename K::Triangle_3 &t,
const K & k ) const typename K::Ray_3 &r,
const K & k,
Visitor visitor)
{ {
visitor.update(ZERO);
CGAL_kernel_precondition( ! k.is_degenerate_3_object()(t) ) ; CGAL_kernel_precondition( ! k.is_degenerate_3_object()(t) ) ;
CGAL_kernel_precondition( ! k.is_degenerate_3_object()(r) ) ; CGAL_kernel_precondition( ! k.is_degenerate_3_object()(r) ) ;
@ -217,81 +274,81 @@ bool do_intersect_coplanar(const typename K::Triangle_3 &t,
if (pqc == POSITIVE) if (pqc == POSITIVE)
// the triangle lies in the positive halfspace // the triangle lies in the positive halfspace
// defined by the ray's supporting line. // defined by the ray's supporting line.
return false; return visitor.result(false);
// c is isolated on the negative side // c is isolated on the negative side
return coplanar_orientation(*a,*c,p) != POSITIVE ; return visitor.result( coplanar_orientation(*a,*c,p) != POSITIVE );
case NEGATIVE: case NEGATIVE:
if (pqc == POSITIVE) // b is isolated on the negative side if (pqc == POSITIVE) // b is isolated on the negative side
return coplanar_orientation(*c,*b,p) != POSITIVE ; return visitor.result( coplanar_orientation(*c,*b,p) != POSITIVE );
// a is isolated on the positive side // a is isolated on the positive side
return coplanar_orientation(*a,*c,p) != POSITIVE ; return visitor.result( coplanar_orientation(*a,*c,p) != POSITIVE );
case COLLINEAR: case COLLINEAR:
if (pqc == POSITIVE) // b is isolated on the negative side if (pqc == POSITIVE) // b is isolated on the negative side
return coplanar_orientation(*c,*b,p) != POSITIVE ; return visitor.result( coplanar_orientation(*c,*b,p) != POSITIVE );
// a is isolated on the positive side // a is isolated on the positive side
return coplanar_orientation(*a,*c,p) != POSITIVE ; return visitor.result( coplanar_orientation(*a,*c,p) != POSITIVE );
default: // should not happen. default: // should not happen.
CGAL_kernel_assertion(false); CGAL_kernel_assertion(false);
return false; return visitor.result(false);
} }
case NEGATIVE: case NEGATIVE:
switch ( pqb ) { switch ( pqb ) {
case POSITIVE: case POSITIVE:
if (pqc == POSITIVE) // a is isolated on the negative side if (pqc == POSITIVE) // a is isolated on the negative side
return coplanar_orientation(*b,*a,p) != POSITIVE ; return visitor.result( coplanar_orientation(*b,*a,p) != POSITIVE );
// b is isolated on the positive side // b is isolated on the positive side
return coplanar_orientation(*b,*a,p) != POSITIVE ; return visitor.result( coplanar_orientation(*b,*a,p) != POSITIVE );
case NEGATIVE: case NEGATIVE:
if (pqc == NEGATIVE) if (pqc == NEGATIVE)
// the triangle lies in the negative halfspace // the triangle lies in the negative halfspace
// defined by the ray's supporting line. // defined by the ray's supporting line.
return false; return visitor.result( false );
// c is isolated on the positive side // c is isolated on the positive side
return coplanar_orientation(*c,*b,p) != POSITIVE ; return visitor.result( coplanar_orientation(*c,*b,p) != POSITIVE );
case COLLINEAR: case COLLINEAR:
if (pqc == NEGATIVE) // b is isolated on the positive side if (pqc == NEGATIVE) // b is isolated on the positive side
return coplanar_orientation(*b,*a,p) != POSITIVE ; return visitor.result( coplanar_orientation(*b,*a,p) != POSITIVE );
// a is isolated on the negative side // a is isolated on the negative side
return coplanar_orientation(*b,*a,p) != POSITIVE ; return visitor.result( coplanar_orientation(*b,*a,p) != POSITIVE );
default: // should not happen. default: // should not happen.
CGAL_kernel_assertion(false); CGAL_kernel_assertion(false);
return false; return visitor.result(false);
} }
case COLLINEAR: case COLLINEAR:
switch ( pqb ) { switch ( pqb ) {
case POSITIVE: case POSITIVE:
if (pqc == POSITIVE) // a is isolated on the negative side if (pqc == POSITIVE) // a is isolated on the negative side
return coplanar_orientation(*b,*a,p) != POSITIVE ; return visitor.result( coplanar_orientation(*b,*a,p) != POSITIVE );
// b is isolated on the positive side // b is isolated on the positive side
return coplanar_orientation(*b,*a,p) != POSITIVE ; return visitor.result( coplanar_orientation(*b,*a,p) != POSITIVE );
case NEGATIVE: case NEGATIVE:
if (pqc == NEGATIVE) // a is isolated on the positive side if (pqc == NEGATIVE) // a is isolated on the positive side
return coplanar_orientation(*a,*c,p) != POSITIVE ; return visitor.result( coplanar_orientation(*a,*c,p) != POSITIVE );
// b is isolated on the negative side // b is isolated on the negative side
return coplanar_orientation(*c,*b,p) != POSITIVE ; return visitor.result( coplanar_orientation(*c,*b,p) != POSITIVE );
case COLLINEAR: case COLLINEAR:
if (pqc == POSITIVE) // c is isolated on the positive side if (pqc == POSITIVE) // c is isolated on the positive side
return coplanar_orientation(*c,*b,p) != POSITIVE ; return visitor.result( coplanar_orientation(*c,*b,p) != POSITIVE );
// c is isolated on the negative side // c is isolated on the negative side
return coplanar_orientation(*a,*c,p) != POSITIVE ; return visitor.result( coplanar_orientation(*a,*c,p) != POSITIVE );
// case pqc == COLLINEAR is imposiible // case pqc == COLLINEAR is imposiible
default: // should not happen. default: // should not happen.
CGAL_kernel_assertion(false); CGAL_kernel_assertion(false);
return false; return visitor.result(false);
} }
default: // should not happen. default: // should not happen.
CGAL_kernel_assertion(false); CGAL_kernel_assertion(false);
return false; return visitor.result(false);
} }
} }