00001 #ifndef GRAL_GB_GEOMETRIC_PRIMITIVES_H
00002 #define GRAL_GB_GEOMETRIC_PRIMITIVES_H
00003
00004
00005
00006 #include "Geometry/algebraic-primitives.h"
00007 #include "Utility/pre-post-conditions.h"
00008
00009
00010
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
00021
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
00035 coord_type p_0, p_1, p_2;
00036
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
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
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
00148 typedef point_traits<coord_type> pt;
00149 typedef typename pt::component_type scalar;
00150 typedef scalar 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
00173
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
00184 return false;
00185 }
00186
00187
00188 coord_type intersection() {
00189 REQUIRE(segment_intersects_plane(), "no intersection!\n",1);
00190 if(! t_defined)
00191 segment_intersects_triangle();
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
00211 typedef point_traits<coord_type> pt;
00212 typedef typename pt::component_type scalar;
00213 typedef scalar 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
00227
00228 return 1.0e-6;
00229 }
00230
00231 bool ray_intersects_plane() {
00232 coord_type n = plane_normal(T);
00233
00234
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
00241
00242 return ( fabs(d) >= eps());
00243 }
00244
00245 bool ray_intersects_triangle() {
00246
00247
00248
00249
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
00263 double ray_intersection() {
00264
00265 if(! t_defined)
00266 ray_intersects_triangle();
00267 return t;
00268 }
00269
00270 coord_type intersection() {
00271
00272 if(! t_defined)
00273 ray_intersects_triangle();
00274 return rt::p0(R) + t * rt::dir(R);
00275 }
00276 };
00277
00278 #endif
00279
00280
00281
00282