Go to Overview over all GrAL packages.
Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Geometry/geometric-primitives.h

Go to the documentation of this file.
00001 #ifndef GRAL_GB_GEOMETRIC_PRIMITIVES_H
00002 #define GRAL_GB_GEOMETRIC_PRIMITIVES_H
00003 
00004 // $LICENSE 
00005 
00006 #include "Geometry/algebraic-primitives.h"
00007 #include "Utility/pre-post-conditions.h"
00008 
00009 // should use C++ <limits>
00010 //#include <limits.h>
00011 
00012 template<class Geom>
00013 struct geom_traits {};
00014 
00015    
00016 template<class P>
00017 class segment {
00018   typedef P coord_type;
00019   typedef coord_type const& const_ref;
00020   //   coord_type const& p_0, p_1;
00021   // coord_type  p_0, p_1;
00022   const_ref  p_0, p_1;
00023 public:
00024   segment(coord_type const& P0, coord_type const& P1)
00025     : p_0(P0), p_1(P1) {}
00026   coord_type const& p0() const { return p_0;}
00027   coord_type const& p1() const { return p_1;}
00028 };
00029 
00030 template<class P>
00031 class triangle {
00032   typedef P coord_type;
00033   typedef coord_type const& const_ref;
00034   // coord_type const& p_0, p_1, p_2;
00035   coord_type  p_0, p_1, p_2;
00036   // const_ref  p_0, p_1, p_2;
00037 public:
00038   triangle(coord_type const& P0, 
00039            coord_type const& P1,
00040            coord_type const& P2)
00041     : p_0(P0), p_1(P1), p_2(P2) {}
00042   coord_type const& p0() const { return p_0;}
00043   coord_type const& p1() const { return p_1;}
00044   coord_type const& p2() const { return p_2;}
00045 };
00046 
00047 
00048 template<class P> class ray {
00049 public:
00050   typedef P coord_type;
00051   P p_0, dir_;
00052 public:
00053   ray() {}
00054   ray(P const& pp0, P const& ddir) : p_0(pp0), dir_(ddir) {}
00055   coord_type const& p0() const { return p_0;}  
00056   coord_type        p1() const { return p_0 + dir_;}
00057   coord_type const& dir() const { return dir_;}
00058   coord_type operator()(double t) const { return p_0 + t*dir_;}
00059 };
00060 
00061 
00062 template<class P> class line
00063 { 
00064 public:
00065   typedef P coord_type;
00066   P p_0, dir_;
00067 
00068   typedef algebraic_primitives<coord_type> ap;
00069 public:
00070   line() {}
00071   line(P const& pp0, P const& ddir) : p_0(pp0), dir_(ddir) {}
00072   line(ray<P> const& r)     : p_0(r.p0()), dir_(r.dir()) {}
00073   line(segment<P> const& s) : p_0(s.p0()), dir_(s.p1() -s.p0()) {}
00074   coord_type const& p0() const { return p_0;}  
00075   coord_type const& dir() const { return dir_;}
00076   coord_type operator()(double t) const { return p_0 + t*dir_;}
00077   
00078   void normalize() { ap::normalize(dir_);}
00079 };
00080 
00081 
00082 template<class P>
00083 struct geom_traits<segment<P> > {
00084   typedef segment<P> segment_t;
00085   typedef typename segment_t::coord_type coord_type;
00086   // typedef segment_t const_ref;
00087   typedef segment_t const& const_ref;
00088   static coord_type const& p0(const_ref S) { return S.p0();}
00089   static coord_type const& p1(const_ref S) { return S.p1();}
00090 };
00091 
00092 template<class P>
00093 struct geom_traits<triangle<P> > {
00094   typedef typename triangle<P>::coord_type coord_type;
00095   // typedef triangle<P>    const_ref;
00096   typedef triangle<P>   const & const_ref;
00097   static coord_type const& p0(const_ref T) { return T.p0();}
00098   static coord_type const& p1(const_ref T) { return T.p1();}
00099   static coord_type const& p2(const_ref T) { return T.p2();}
00100 };
00101 
00102 template<class P>
00103 struct geom_traits<ray<P> > {
00104   typedef typename ray<P>::coord_type coord_type;
00105   typedef ray<P>    const& const_ref;
00106   static coord_type const& p0 (const_ref T) { return T.p0();}
00107   static coord_type const& dir(const_ref T) { return T.dir();}
00108 
00109 };
00110 
00111 template<class P>
00112 struct geom_traits<line<P> > {
00113   typedef typename line<P>::coord_type coord_type;
00114   typedef line<P>   const& const_ref;
00115   static coord_type const& p0 (const_ref T) { return T.p0();}
00116   static coord_type const& dir(const_ref T) { return T.dir();}
00117 
00118 };
00119   
00120 
00123 template<class Triangle>
00124 inline
00125 typename geom_traits<Triangle>::coord_type
00126 plane_normal(Triangle const& T)
00127 {
00128   typedef geom_traits<Triangle> tt;
00129   typedef algebraic_primitives<typename tt::coord_type> ap;
00130   return (ap::normalization
00131           (ap::vectorproduct(tt::p1(T) - tt::p0(T), 
00132                              tt::p2(T) - tt::p0(T))));
00133 }
00134 
00135 
00141 template<class Segment, class Triangle>
00142 class intersection_segment_triangle {
00143   typedef geom_traits<Segment>  st;
00144   typedef geom_traits<Triangle> tt;
00145   typedef typename st::coord_type coord_type; 
00146   typedef algebraic_primitives<coord_type> ap;
00147   // assume tt::coord_type is the same
00148   typedef point_traits<coord_type> pt;
00149   typedef typename pt::component_type scalar;
00150   typedef scalar                      real;// FIXME: should be scalar_traits::real
00151 
00152   typename st::const_ref S;
00153   typename tt::const_ref T;
00154   real t;
00155   bool t_defined;
00156 
00157 public: 
00158   intersection_segment_triangle(Segment const& S_, Triangle const& T_)
00159     : S(S_), T(T_), t_defined(false) 
00160     {}
00161 
00162   bool segment_intersects_plane() {
00163     coord_type n = plane_normal(T);
00164     real       d = ap::dot(n, tt::p0(T));
00165     return ( (ap::dot(st::p0(S), n)-d) 
00166              *(ap::dot(st::p1(S), n)-d)  < 0);
00167   }
00168 
00169   bool segment_intersects_triangle() {
00170     if(segment_intersects_plane()) {
00171       coord_type rst; pt::ConstructWithDim(3,rst);
00172       // solve p0(T) + r*(p1(T)-p0(T)) + s*(p2(T)-p0(T)) 
00173       //    =  p0(S) + t*(p1(S)-p0(S))  for (r,s,t)
00174       ap::solve(tt::p1(T) - tt::p0(T),
00175                 tt::p2(T) - tt::p0(T), 
00176                 st::p0(S) - st::p1(S),
00177                 rst,
00178                 st::p0(S) - tt::p0(T));
00179       t = pt::z(rst); t_defined = true;
00180       real r = pt::x(rst), s = pt::y(rst);
00181       return (r >= 0 && s >= 0 && s+r <= 1);
00182     }
00183     else // no intersection with plane => none with triangle
00184       return false;
00185   }
00186   //  bool lines_does_intersect_plane();
00187 
00188   coord_type intersection() { 
00189     REQUIRE(segment_intersects_plane(), "no intersection!\n",1);
00190     if(! t_defined)
00191       segment_intersects_triangle(); // calculates t      
00192     return st::p0(S) + t * (st::p1(S) - st::p0(S));
00193   }
00194 };
00195 
00196 
00197 
00198 
00204 template<class Ray, class Triangle>
00205 class intersection_ray_triangle {
00206   typedef geom_traits<Ray>      rt;
00207   typedef geom_traits<Triangle> tt;
00208   typedef typename rt::coord_type coord_type; 
00209   typedef algebraic_primitives<coord_type> ap;
00210   // assume tt::coord_type is the same
00211   typedef point_traits<coord_type> pt;
00212   typedef typename pt::component_type scalar;
00213   typedef scalar                      real;// FIXME: should be scalar_traits::real
00214 
00215   typename rt::const_ref R;
00216   typename tt::const_ref T;
00217   real t;
00218   bool t_defined;
00219 
00220 public: 
00221   intersection_ray_triangle(Ray const& R_, Triangle const& T_)
00222     : R(R_), T(T_), t_defined(false) 
00223     {}
00224 
00225   real eps() const { 
00226     // FIXME! return numeric_limits<real>::epsilon();
00227     //  return FLT_EPSILON;
00228     return 1.0e-6;
00229   }
00230 
00231   bool ray_intersects_plane() {
00232     coord_type n = plane_normal(T);
00233 
00234     // if direction of ray points away from plane, no intersection
00235     if(ap::dot(n, rt::dir(R)) * ap::dot(n, rt::p0(R) -tt::p0(T)) > 0)
00236       return false;
00237 
00238     real       d = ap::dot(ap::normalization(n),
00239                            ap::normalization(rt::dir(R)));
00240     // is eps the correct quantity?
00241     // case fabs(d) < eps is considered parallel to plane
00242     return ( fabs(d) >= eps());
00243   }
00244 
00245   bool ray_intersects_triangle() {
00246     // check whether ray is (to) parallel to triangle plane
00247 
00248     // solve p0(T) + r*(p1(T)-p0(T)) + s*(p2(T)-p0(T)) 
00249     //    =  p0(R) + t* dir(R)   for (r,s,t)
00250     if(! ray_intersects_plane())
00251       return false;
00252     coord_type rst; pt::ConstructWithDim(3,rst);
00253     ap::solve(tt::p1(T) - tt::p0(T),
00254               tt::p2(T) - tt::p0(T), 
00255               - rt::dir(R),
00256               rst,
00257               rt::p0(R) - tt::p0(T));
00258       t = pt::z(rst); t_defined = true;
00259       real r = pt::x(rst), s = pt::y(rst);
00260       return (t>= 0 && r >= 0 && s >= 0 && s+r <= 1);
00261   }
00262   //  bool lines_does_intersect_plane();
00263   double ray_intersection() {
00264     //REQUIRE(ray_intersects_plane(), "no intersection!\n",1);
00265     if(! t_defined)
00266       ray_intersects_triangle(); // calculates t      
00267     return t;
00268   }
00269 
00270   coord_type intersection() { 
00271     // REQUIRE(ray_intersects_plane(), "no intersection!\n",1);
00272     if(! t_defined)
00273       ray_intersects_triangle(); // calculates t      
00274     return rt::p0(R) + t * rt::dir(R);
00275   }
00276 };
00277 
00278 #endif
00279 
00280 
00281 
00282 

Copyright (c) Guntram Berti 1997-2002. See the GrAL Homepage for up-to-date information.

Generated at Tue Feb 26 15:57:26 2002 for Geometry by doxygen 1.2.11-20011104 written by Dimitri van Heesch, © 1997-2000