Skip to Content.
Sympa Menu

cgal-discuss - Re: [cgal-discuss] Failing call of Triangle_3.has_on

Subject: CGAL users discussion list

List archive

Re: [cgal-discuss] Failing call of Triangle_3.has_on


Chronological Thread 
  • From: Pierre Alliez <>
  • To:
  • Subject: Re: [cgal-discuss] Failing call of Triangle_3.has_on
  • Date: Thu, 10 Dec 2009 09:47:18 -0800
  • Organization: INRIA

hi Nikolas,

take a look at the attached file
we are working on moving it into the kernel - but in the meantime you can use it.

if you have a bunch of triangles to intersect against then you can use the AABB tree data structure.
Pierre Alliez
INRIA Sophia Antipolis - Mediterranee 
Project-team GEOMETRICA 
http://www-sop.inria.fr/members/Pierre.Alliez/
Tel: +33 4 92 38 76 77
Fax: +33 4 97 15 53 95


Nikolas Engelhard a écrit :

Hello

I'm writing a little raycasting-Program and have a problem with intersection a Triangle with a Ray. 
Since this intersection is not yet supported, I intersect the ray with the supporting plane of the Triangle
and check if the point is within the triangle. 

Here are my Definitions:

#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
typedef  CGAL::Exact_predicates_exact_constructions_kernel K;
typedef  CGAL::Point_3<K> P;
typedef  CGAL::Triangle_3<K>  Tri;
typedef  CGAL::Ray_3<K> R;
typedef  CGAL::Vector_3<K> V;

and a little sample:

P t(0,0,0);
P q(10,0,0);
P r(0,10,0);


Tri tri(t,q,r);



P s(1,1,1);
V v(0,0,-1);
R ray(s,v);



P is(5,4.5,0);


cout << is << "      " << tri <<  endl;
if (tri.has_on(is)){
cout << "intersection" << endl;
}
else
cout <<"no intersection" << endl;


I would expect to find an intersection ( "is" lies on tri) but I get 


"Program received signal:  “EXC_BAD_ACCESS”."


after calling has_on. Other functions like intersection(ray,plane) work well und in some cases also this call works 

(with different values), so I have no idea, what to do. 


Does anyone has an idea?


Nikolas

// Copyright (c) 2009 GeometryFactory (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the
software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL:
https://scm.gforge.inria.fr/svn/cgal/trunk/AABB_tree/include/CGAL/internal/AABB_Intersections_3/Triangle_3_Ray_3_intersection.h
$
// $Id: Triangle_3_Ray_3_intersection.h 53154 2009-11-24 13:07:45Z stayeb $
//
//
// Author(s) : Laurent Rineau, Stephane Tayeb
//
//******************************************************************************
// File Description : Implements triangle_3 ray_3 intersection construction.
//
// This implementation is adapted from Triangle_3_Ray_3_do_intersect.h.
//******************************************************************************

#ifndef CGAL_INTERNAL_INTERSECTIONS_3_TRIANGLE_3_RAY_3_INTERSECTION_H
#define CGAL_INTERNAL_INTERSECTIONS_3_TRIANGLE_3_RAY_3_INTERSECTION_H

#include <CGAL/kernel_basic.h>
#include <CGAL/intersections.h>

namespace CGAL {
namespace internal {


template <class K>
typename K::Point_3
t3r3_intersection_coplanar_aux(const typename K::Point_3& p,
const typename K::Vector_3& v,
const typename K::Point_3& a,
const typename K::Point_3& b,
const K& k)
{
// Returns the intersection point between line (p,v) and line (a,b)
//
// preconditions:
// + p,v,a,b are coplanar

typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typedef typename K::FT FT;

typename K::Construct_vector_3 vector =
k.construct_vector_3_object();

typename K::Construct_cross_product_vector_3 cross_product =
k.construct_cross_product_vector_3_object();

typename K::Compute_scalar_product_3 scalar_product =
k.compute_scalar_product_3_object();

typename K::Compute_squared_length_3 sq_length =
k.compute_squared_length_3_object();

const Vector_3 ab = vector(a,b);
const Vector_3 pa = vector(p,a);

const Vector_3 pa_ab = cross_product(pa,ab);
const Vector_3 v_ab = cross_product(v,ab);

const FT t = scalar_product(pa_ab,v_ab) / sq_length(v_ab);

return ( p + t*v );
}


template <class K>
Object
t3r3_intersection_coplanar_aux(const typename K::Point_3& a,
const typename K::Point_3& b,
const typename K::Point_3& c,
const typename K::Ray_3& r,
const bool negative_side,
const K& k)
{
// This function is designed to clip r into the triangle abc.
// Point configuration should be as follows
//
//
// p+ +b
// |
// +c | +a
// |
// |r
//
// We know that c is isolated on the negative side of r
// but we don't know p position wrt [bc]&[ca]

typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;

typename K::Coplanar_orientation_3 coplanar_orientation =
k.coplanar_orientation_3_object();

typename K::Construct_segment_3 segment =
k.construct_segment_3_object();

typename K::Construct_point_on_3 point_on =
k.construct_point_on_3_object();

const Point_3& p = point_on(r,0);

// A ray is not symetric, 2 cases depending on isolated side of c
Orientation cap;
if ( negative_side )
cap = coplanar_orientation(c,a,p);
else
cap = coplanar_orientation(b,c,p);

switch ( cap ) {

case NEGATIVE:
// p is bellow [c,a]
return Object();

case COLLINEAR:
return make_object(p);

case POSITIVE:
{
// Compute the intersection points between ray and [b,c],[c,a]
Vector_3 v = r.to_vector();

// Get intersection point at p side
Point_3 p_side_end_point(p);
Point_3 q_side_end_point;

// A ray is not symetric, 2 cases depending on isolated side of c
if ( negative_side )
{
if ( NEGATIVE == coplanar_orientation(b,c,p) )
p_side_end_point = t3r3_intersection_coplanar_aux(p,v,b,c,k);

// Get other end point (always intersection computation on the
unbounded
// side of the ray)
q_side_end_point = t3r3_intersection_coplanar_aux(p,v,c,a,k);
}
else
{
if ( NEGATIVE == coplanar_orientation(c,a,p) )
p_side_end_point = t3r3_intersection_coplanar_aux(p,v,c,a,k);

// Get other end point (always intersection computation on the
unbounded
// side of the ray)
q_side_end_point = t3r3_intersection_coplanar_aux(p,v,b,c,k);
}

// Build result
return make_object(segment(p_side_end_point, q_side_end_point));
}

default: // should not happen.
CGAL_kernel_assertion(false);
return Object();
}

CGAL_kernel_assertion(false);
return Object();
}







template <class K>
Object
intersection_coplanar(const typename K::Triangle_3 &t,
const typename K::Ray_3 &r,
const K & k )
{
CGAL_kernel_precondition( ! k.is_degenerate_3_object()(t) ) ;
CGAL_kernel_precondition( ! k.is_degenerate_3_object()(r) ) ;

typedef typename K::Point_3 Point_3;


typename K::Construct_point_on_3 point_on =
k.construct_point_on_3_object();

typename K::Construct_vertex_3 vertex_on =
k.construct_vertex_3_object();

typename K::Coplanar_orientation_3 coplanar_orientation =
k.coplanar_orientation_3_object();

typename K::Construct_line_3 line =
k.construct_line_3_object();

typename K::Construct_segment_3 segment =
k.construct_segment_3_object();

typename K::Collinear_are_ordered_along_line_3 collinear_ordered =
k.collinear_are_ordered_along_line_3_object();


const Point_3 & p = point_on(r,0);
const Point_3 & q = point_on(r,1);

const Point_3 & A = vertex_on(t,0);
const Point_3 & B = vertex_on(t,1);
const Point_3 & C = vertex_on(t,2);

int k0 = 0;
int k1 = 1;
int k2 = 2;

// Determine the orientation of the triangle in the common plane
if (coplanar_orientation(A,B,C) != POSITIVE)
{
// The triangle is not counterclockwise oriented
// swap two vertices.
std::swap(k1,k2);
}

const Point_3& a = vertex_on(t,k0);
const Point_3& b = vertex_on(t,k1);
const Point_3& c = vertex_on(t,k2);

// Test whether the ray's supporting line intersects the
// triangle in the common plane
const Orientation pqa = coplanar_orientation(p,q,a);
const Orientation pqb = coplanar_orientation(p,q,b);
const Orientation pqc = coplanar_orientation(p,q,c);

switch ( pqa ) {
// -----------------------------------
// pqa POSITIVE
// -----------------------------------
case POSITIVE:
switch ( pqb ) {
case POSITIVE:
switch ( pqc ) {
case POSITIVE:
// the triangle lies in the positive halfspace
// defined by the segment's supporting line.
return Object();

case NEGATIVE:
// c is isolated on the negative side
return t3r3_intersection_coplanar_aux(a,b,c,r,true,k);

case COLLINEAR:
// p,q,c are collinear
if ( collinear_ordered(p,c,q) || collinear_ordered(p,q,c) )
return make_object(c);
else
return Object();
}

case NEGATIVE:
if ( POSITIVE == pqc )
// b is isolated on the negative side
return t3r3_intersection_coplanar_aux(c,a,b,r,true,k);
else
// a is isolated on the positive side (here mb c could be use as
// an endpoint instead of computing an intersection is some cases)
return t3r3_intersection_coplanar_aux(b,c,a,r,false,k);

case COLLINEAR:
switch ( pqc ) {
case POSITIVE:
// p,q,b are collinear
if ( collinear_ordered(p,b,q) || collinear_ordered(p,q,b) )
return make_object(b);
else
return Object();

case NEGATIVE:
// a is isolated on the positive side (here mb b could be use as
// an endpoint instead of computing an intersection)
return t3r3_intersection_coplanar_aux(b,c,a,r,false,k);

case COLLINEAR:
// b,c,p,q are aligned, [p,q]&[b,c] have the same direction
if ( collinear_ordered(p,b,c) )
return make_object(segment(b,c));
else
return make_object(segment(p,c));
}

default: // should not happen.
CGAL_kernel_assertion(false);
return Object();
}

// -----------------------------------
// pqa NEGATIVE
// -----------------------------------
case NEGATIVE:
switch ( pqb ) {
case POSITIVE:
if ( POSITIVE == pqc )
// a is isolated on the negative side
return t3r3_intersection_coplanar_aux(b,c,a,r,true,k);
else
// b is isolated on the positive side (here mb c could be use as
// an endpoint instead of computing an intersection, in some
cases)
return t3r3_intersection_coplanar_aux(c,a,b,r,false,k);

case NEGATIVE:
switch ( pqc ) {
case POSITIVE:
// c is isolated on the positive side
return t3r3_intersection_coplanar_aux(a,b,c,r,false,k);

case NEGATIVE:
// the triangle lies in the negative halfspace
// defined by the segment's supporting line.
return Object();

case COLLINEAR:
// p,q,c are collinear
if ( collinear_ordered(p,c,q) || collinear_ordered(p,q,c) )
return make_object(c);
else
return Object();
}

case COLLINEAR:
switch ( pqc ) {
case POSITIVE:
// a is isolated on the negative side (here mb b could be use as
// an endpoint instead of computing an intersection)
return t3r3_intersection_coplanar_aux(b,c,a,r,true,k);

case NEGATIVE:
// p,q,b are collinear
if ( collinear_ordered(p,b,q) || collinear_ordered(p,q,b) )
return make_object(b);
else
return Object();

case COLLINEAR:
// b,c,p,q are aligned, [p,q]&[c,b] have the same direction
if ( collinear_ordered(p,c,b) )
return make_object(segment(c,b));
else
return make_object(segment(p,b));
}

default: // should not happen.
CGAL_kernel_assertion(false);
return Object();
}

// -----------------------------------
// pqa COLLINEAR
// -----------------------------------
case COLLINEAR:
switch ( pqb ) {
case POSITIVE:
switch ( pqc ) {
case POSITIVE:
// p,q,a are collinear
if ( collinear_ordered(p,a,q) || collinear_ordered(p,q,a) )
return make_object(a);
else
return Object();

case NEGATIVE:
// b is isolated on the positive side (here mb a could be use as
// an endpoint instead of computing an intersection)
return t3r3_intersection_coplanar_aux(c,a,b,r,false,k);

case COLLINEAR:
// a,c,p,q are aligned, [p,q]&[c,a] have the same direction
if ( collinear_ordered(p,c,a) )
return make_object(segment(c,a));
else
return make_object(segment(p,a));
}

case NEGATIVE:
switch ( pqc ) {
case POSITIVE:
// b is isolated on the negative side (here mb a could be use as
// an endpoint instead of computing an intersection)
return t3r3_intersection_coplanar_aux(c,a,b,r,true,k);

case NEGATIVE:
// p,q,a are collinear
if ( collinear_ordered(p,a,q) || collinear_ordered(p,q,a) )
return make_object(a);
else
return Object();

case COLLINEAR:
// a,c,p,q are aligned, [p,q]&[a,c] have the same direction
if ( collinear_ordered(p,a,c) )
return make_object(segment(a,c));
else
return make_object(segment(p,c));
}

case COLLINEAR:
switch ( pqc ) {
case POSITIVE:
// a,b,p,q are aligned, [p,q]&[a,b] have the same direction
if ( collinear_ordered(p,a,b) )
return make_object(segment(a,b));
else
return make_object(segment(p,b));

case NEGATIVE:
// a,b,p,q are aligned, [p,q]&[b,a] have the same direction
if ( collinear_ordered(p,b,a) )
return make_object(segment(b,a));
else
return make_object(segment(p,a));

case COLLINEAR:
// case pqc == COLLINEAR is impossible since the triangle is
// assumed to be non flat
CGAL_kernel_assertion(false);
return Object();
}

default: // should not happen.
CGAL_kernel_assertion(false);
return Object();

}

default:// should not happen.
CGAL_kernel_assertion(false);
return Object();

}
}



template <class K>
inline
Object
t3r3_intersection_aux(const typename K::Triangle_3 &t,
const typename K::Ray_3 &r,
const K& k)
{
typename K::Intersect_3 intersection =
k.intersect_3_object();

Object obj = intersection(r.supporting_line(),t.supporting_plane());

// Intersection should be a point (because of orientation test done before)
if ( NULL == object_cast<typename K::Line_3>(&obj) )
return obj;
else
return Object();
}

template <class K>
Object
intersection(const typename K::Triangle_3 &t,
const typename K::Ray_3 &r,
const K& k)
{
CGAL_kernel_precondition( ! k.is_degenerate_3_object()(t) ) ;
CGAL_kernel_precondition( ! k.is_degenerate_3_object()(r) ) ;

typedef typename K::Point_3 Point_3;

typename K::Construct_vertex_3 vertex_on =
k.construct_vertex_3_object();

typename K::Orientation_3 orientation =
k.orientation_3_object();

typename K::Construct_ray_3 ray =
k.construct_ray_3_object();

typename K::Construct_point_on_3 point_on =
k.construct_point_on_3_object();


const Point_3& a = vertex_on(t,0);
const Point_3& b = vertex_on(t,1);
const Point_3& c = vertex_on(t,2);
const Point_3& p = point_on(r,0);
const Point_3& q = point_on(r,1);

Point_3 d = point_on(ray(a,r.to_vector()),1);

const Orientation ray_direction = orientation(a,b,c,d);
const Orientation abcp = orientation(a,b,c,p);

switch ( abcp ) {
case POSITIVE:
switch ( ray_direction ) {
case POSITIVE:
// the ray lies in the positive open halfspaces defined by the
// triangle's supporting plane
return Object();

case NEGATIVE:
// The ray straddles the triangle's plane
// p sees the triangle in counterclockwise order
if ( orientation(p,q,a,b) != POSITIVE
&& orientation(p,q,b,c) != POSITIVE
&& orientation(p,q,c,a) != POSITIVE )
return t3r3_intersection_aux(t,r,k);
else
return Object();

case COPLANAR:
// The ray lie in a plane parallel to a,b,c support plane
return Object();

default: // should not happen.
CGAL_kernel_assertion(false);
return Object();
}

case NEGATIVE:
switch ( ray_direction ) {
case POSITIVE:
// The ray straddles the triangle's plane
// q sees the triangle in counterclockwise order

if ( orientation(q,p,a,b) != POSITIVE
&& orientation(q,p,b,c) != POSITIVE
&& orientation(q,p,c,a) != POSITIVE )
return t3r3_intersection_aux(t,r,k);
else
return Object();

case NEGATIVE:
// the ray lies in the negative open halfspaces defined by the
// triangle's supporting plane
return Object();

case COPLANAR:
// The ray lie in a plane parallel to a,b,c support plane
return Object();

default: // should not happen.
CGAL_kernel_assertion(false);
return Object();
}

case COPLANAR: // p belongs to the triangle's supporting plane
switch ( ray_direction ) {
case POSITIVE:
// q sees the triangle in counterclockwise order
if ( orientation(q,p,a,b) != POSITIVE
&& orientation(q,p,b,c) != POSITIVE
&& orientation(q,p,c,a) != POSITIVE )
return t3r3_intersection_aux(t,r,k);
else
return Object();

case NEGATIVE:
// q sees the triangle in clockwise order
if ( orientation(p,q,a,b) != POSITIVE
&& orientation(p,q,b,c) != POSITIVE
&& orientation(p,q,c,a) != POSITIVE )
return t3r3_intersection_aux(t,r,k);
else
return Object();

case COPLANAR:
// The ray lie in triangle supporting plane
return intersection_coplanar(t,r,k);

default: // should not happen.
CGAL_kernel_assertion(false);
return Object();
}

default: // should not happen.
CGAL_kernel_assertion(false);
return Object();

}

CGAL_kernel_assertion(false);
return Object();
}

} // end namespace internal

template <class K>
inline
Object
intersection(const Triangle_3<K> &t, const Ray_3<K> &r)
{
return typename K::Intersect_3()(t, r);
}

template <class K>
inline
Object
intersection(const Ray_3<K> &r, const Triangle_3<K> &t)
{
return typename K::Intersect_3()(t, r);
}

} // end namespace CGAL

#endif // CGAL_INTERNAL_INTERSECTIONS_3_TRIANGLE_3_RAY_3_INTERSECTION_H
// Copyright (c) 2008 INRIA Sophia-Antipolis (France), ETH Zurich
(Switzerland).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the
software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL:
https://scm.gforge.inria.fr/svn/cgal/trunk/AABB_tree/include/CGAL/internal/AABB_Intersections_3/Bbox_3_Ray_3_do_intersect.h
$
// $Id: Bbox_3_Ray_3_do_intersect.h 53127 2009-11-20 17:02:39Z stayeb $
//
//
// Author(s) : Camille Wormser, Jane Tournois, Pierre Alliez, Stephane
Tayeb

#ifndef CGAL_INTERNAL_INTERSECTIONS_3_BBOX_3_RAY_3_DO_INTERSECT_H
#define CGAL_INTERNAL_INTERSECTIONS_3_BBOX_3_RAY_3_DO_INTERSECT_H

#include <CGAL/Ray_3.h>
#include <CGAL/Bbox_3.h>

// inspired from http://cag.csail.mit.edu/~amy/papers/box-jgt.pdf

CGAL_BEGIN_NAMESPACE

namespace internal {

template <typename FT>
inline
bool
bbox_ray_do_intersect_aux(const FT& px, const FT& py, const FT& pz,
const FT& qx, const FT& qy, const FT& qz,
const FT& bxmin, const FT& bymin, const FT& bzmin,
const FT& bxmax, const FT& bymax, const FT& bzmax)
{
// (px, py, pz) is the source
// -----------------------------------
// treat x coord
// -----------------------------------
FT dmin, tmin, tmax;
if ( qx >= px )
{
tmin = bxmin - px;
tmax = bxmax - px;
dmin = qx - px;
if ( tmax < FT(0) )
return false;
}
else
{
tmin = px - bxmax;
tmax = px - bxmin;
dmin = px - qx;
if ( tmax < FT(0) )
return false;
}

FT dmax = dmin;
if ( tmin > FT(0) )
{
if ( dmin == FT(0) )
return false;
}
else
{
tmin = FT(0);
dmin = FT(1);
}

// -----------------------------------
// treat y coord
// -----------------------------------
FT d_, tmin_, tmax_;
if ( qy >= py )
{
tmin_ = bymin - py;
tmax_ = bymax - py;
d_ = qy - py;
}
else
{
tmin_ = py - bymax;
tmax_ = py - bymin;
d_ = py - qy;
}

if ( (dmin*tmax_) < (d_*tmin) || (dmax*tmin_) > (d_*tmax) )
return false;

if( (dmin*tmin_) > (d_*tmin) )
{
tmin = tmin_;
dmin = d_;
}

if( (dmax*tmax_) < (d_*tmax) )
{
tmax = tmax_;
dmax = d_;
}


// -----------------------------------
// treat z coord
// -----------------------------------
if ( qz >= pz )
{
tmin_ = bzmin - pz;
tmax_ = bzmax - pz;
d_ = qz - pz;
}
else
{
tmin_ = pz - bzmax;
tmax_ = pz - bzmin;
d_ = pz - qz;
}

return ( (dmin*tmax_) >= (d_*tmin) && (dmax*tmin_) <= (d_*tmax) );
}

template <class K>
bool do_intersect(const typename K::Ray_3& ray,
const CGAL::Bbox_3& bbox,
const K&)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;

const Point_3 source = ray.source();
const Point_3 point_on_ray = ray.point(1);

return bbox_ray_do_intersect_aux(
source.x(), source.y(), source.z(),
point_on_ray.x(), point_on_ray.y(),
point_on_ray.z(),
FT(bbox.xmin()), FT(bbox.ymin()), FT(bbox.zmin()),
FT(bbox.xmax()), FT(bbox.ymax()), FT(bbox.zmax()) );
}

} // namespace internal

template <class K>
bool do_intersect(const CGAL::Ray_3<K>& ray,
const CGAL::Bbox_3& bbox)
{
return typename K::Do_intersect_3()(ray, bbox);
}

template <class K>
bool do_intersect(const CGAL::Bbox_3& bbox,
const CGAL::Ray_3<K>& ray)
{
return typename K::Do_intersect_3()(ray, bbox);
}

CGAL_END_NAMESPACE

#endif // CGAL_INTERNAL_INTERSECTIONS_3_BBOX_3_RAY_3_DO_INTERSECT_H





Archive powered by MHonArc 2.6.16.

Top of Page