intersection3.h
Go to the documentation of this file.
00001 /****************************************************************************
00002  * VCGLib                                                            o o     *
00003  * Visual and Computer Graphics Library                            o     o   *
00004  *                                                                _   O  _   *
00005  * Copyright(C) 2004                                                \/)\/    *
00006  * Visual Computing Lab                                            /\/|      *
00007  * ISTI - Italian National Research Council                           |      *
00008  *                                                                    \      *
00009  * All rights reserved.                                                      *
00010  *                                                                           *
00011  * This program is free software; you can redistribute it and/or modify      *
00012  * it under the terms of the GNU General Public License as published by      *
00013  * the Free Software Foundation; either version 2 of the License, or         *
00014  * (at your option) any later version.                                       *
00015  *                                                                           *
00016  * This program is distributed in the hope that it will be useful,           *
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019  * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020  * for more details.                                                         *
00021  *                                                                           *
00022  ****************************************************************************/
00023 
00024 #ifndef __VCGLIB_INTERSECTION_3
00025 #define __VCGLIB_INTERSECTION_3
00026 
00027 #include <vcg/math/base.h>
00028 #include <vcg/space/point3.h>
00029 #include <vcg/space/line3.h>
00030 #include <vcg/space/ray3.h>
00031 #include <vcg/space/plane3.h>
00032 #include <vcg/space/segment3.h>
00033 #include <vcg/space/sphere3.h>
00034 #include <vcg/space/triangle3.h>
00035 #include <vcg/space/intersection/triangle_triangle3.h>
00036 
00037 
00038 
00039 
00040 namespace vcg {
00047 
00048   template<class T>
00049     inline bool IntersectionLineSphere( const Sphere3<T> & sp, const Line3<T> & li, Point3<T> & p0,Point3<T> & p1 ){
00050 
00051     // Per prima cosa si sposta il sistema di riferimento
00052     // fino a portare il centro della sfera nell'origine
00053     Point3<T> neworig=li.Origin()-sp.Center();
00054     // poi si risolve il sistema di secondo grado (con maple...)
00055     T t1 = li.Direction().X()*li.Direction().X();
00056     T t2 = li.Direction().Y()*li.Direction().Y();
00057     T t3 = li.Direction().Z()*li.Direction().Z();
00058     T t6 = neworig.Y()*li.Direction().Y();
00059     T t7 = neworig.X()*li.Direction().X();
00060     T t8 = neworig.Z()*li.Direction().Z();
00061     T t15 = sp.Radius()*sp.Radius();
00062     T t17 = neworig.Z()*neworig.Z();
00063     T t19 = neworig.Y()*neworig.Y();
00064     T t21 = neworig.X()*neworig.X();
00065     T t28 = T(2.0*t7*t6+2.0*t6*t8+2.0*t7*t8+t1*t15-t1*t17-t1*t19-t2*t21+t2*t15-t2*t17-t3*t21+t3*t15-t3*t19);
00066     if(t28<0) return false;
00067     T t29 = sqrt(t28);
00068     T val0 = 1/(t1+t2+t3)*(-t6-t7-t8+t29);
00069     T val1 = 1/(t1+t2+t3)*(-t6-t7-t8-t29);
00070 
00071     p0=li.P(val0);
00072     p1=li.P(val1);
00073     return true;
00074   }
00075 
00076     /*
00077     * Function computing the intersection between a sphere and a segment.
00078     * @param[in]        sphere                          the sphere
00079     * @param[in]        segment                         the segment
00080     * @param[out]       intersection  the intersection point, meaningful only if the segment intersects the sphere
00081     * \return                   (0, 1 or 2)             the number of intersections between the segment and the sphere.
00082     *                                                                                                           t1 is a valid intersection only if the returned value is at least 1;
00083     *                                                                                                           similarly t2 is valid iff the returned value is 2.
00084     */
00085     template < class SCALAR_TYPE >
00086     inline int IntersectionSegmentSphere(const Sphere3<SCALAR_TYPE>& sphere, const Segment3<SCALAR_TYPE>& segment, Point3<SCALAR_TYPE> & t0, Point3<SCALAR_TYPE> & t1)
00087     {
00088         typedef SCALAR_TYPE                                                                                                     ScalarType;
00089         typedef typename vcg::Point3< ScalarType >      Point3t;
00090 
00091         Point3t s = segment.P0() - sphere.Center();
00092         Point3t r = segment.P1() - segment.P0();
00093 
00094         ScalarType rho2 = sphere.Radius()*sphere.Radius();
00095 
00096         ScalarType sr = s*r;
00097         ScalarType r_squared_norm = r.SquaredNorm();
00098         ScalarType s_squared_norm = s.SquaredNorm();
00099         ScalarType sigma = sr*sr - r_squared_norm*(s_squared_norm-rho2);
00100 
00101         if (sigma<ScalarType(0.0)) // the line containing the edge doesn't intersect the sphere
00102             return 0;
00103 
00104         ScalarType sqrt_sigma = ScalarType(sqrt( ScalarType(sigma) ));
00105         ScalarType lambda1 = (-sr - sqrt_sigma)/r_squared_norm;
00106         ScalarType lambda2 = (-sr + sqrt_sigma)/r_squared_norm;
00107 
00108         int solution_count = 0;
00109         if (ScalarType(0.0)<=lambda1 && lambda1<=ScalarType(1.0))
00110         {
00111       ScalarType t_enter = std::max< ScalarType >(lambda1, ScalarType(0.0));
00112             t0 = segment.P0() + r*t_enter;
00113             solution_count++;
00114         }
00115 
00116         if (ScalarType(0.0)<=lambda2 && lambda2<=ScalarType(1.0))
00117         {
00118             Point3t *pt = (solution_count>0) ? &t1 : &t0;
00119       ScalarType t_exit  = std::min< ScalarType >(lambda2, ScalarType(1.0));
00120             *pt = segment.P0() + r*t_exit;
00121             solution_count++;
00122         }
00123         return solution_count;
00124     }; // end of IntersectionSegmentSphere
00125 
00126 
00136     template < class SCALAR_TYPE, class TRIANGLETYPE >
00137     bool IntersectionSphereTriangle(const vcg::Sphere3	< SCALAR_TYPE >          & sphere  ,
00138                                                                     TRIANGLETYPE                                                                                                                triangle,
00139                                                                     vcg::Point3					< SCALAR_TYPE >             & witness ,
00140                                                                     std::pair< SCALAR_TYPE, SCALAR_TYPE > * res=NULL)
00141     {
00142         typedef SCALAR_TYPE                                                                                                             ScalarType;
00143         typedef typename vcg::Point3< ScalarType >              Point3t;
00144 
00145         bool penetration_detected = false;
00146 
00147         ScalarType radius = sphere.Radius();
00148         Point3t center = sphere.Center();
00149         Point3t p0 = triangle.P(0)-center;
00150         Point3t p1 = triangle.P(1)-center;
00151         Point3t p2 = triangle.P(2)-center;
00152 
00153         Point3t p10 = p1-p0;
00154         Point3t p21 = p2-p1;
00155         Point3t p20 = p2-p0;
00156 
00157         ScalarType delta0_p01 =  p10.dot(p1);
00158         ScalarType delta1_p01 = -p10.dot(p0);
00159         ScalarType delta0_p02 =  p20.dot(p2);
00160         ScalarType delta2_p02 = -p20.dot(p0);
00161         ScalarType delta1_p12 =  p21.dot(p2);
00162         ScalarType delta2_p12 = -p21.dot(p1);
00163 
00164         // the closest point can be one of the vertices of the triangle
00165         if                      (delta1_p01<=ScalarType(0.0) && delta2_p02<=ScalarType(0.0)) { witness = p0; }
00166         else if (delta0_p01<=ScalarType(0.0) && delta2_p12<=ScalarType(0.0)) { witness = p1; }
00167         else if (delta0_p02<=ScalarType(0.0) && delta1_p12<=ScalarType(0.0)) { witness = p2; }
00168         else
00169         {
00170             ScalarType temp = p10.dot(p2);
00171             ScalarType delta0_p012 = delta0_p01*delta1_p12 + delta2_p12*temp;
00172             ScalarType delta1_p012 = delta1_p01*delta0_p02 - delta2_p02*temp;
00173             ScalarType delta2_p012 = delta2_p02*delta0_p01 - delta1_p01*(p20.dot(p1));
00174 
00175             // otherwise, can be a point lying on same edge of the triangle
00176             if (delta0_p012<=ScalarType(0.0))
00177             {
00178                 ScalarType denominator = delta1_p12+delta2_p12;
00179                 ScalarType mu1 = delta1_p12/denominator;
00180                 ScalarType mu2 = delta2_p12/denominator;
00181                 witness = (p1*mu1 + p2*mu2);
00182             }
00183             else if (delta1_p012<=ScalarType(0.0))
00184             {
00185                 ScalarType denominator = delta0_p02+delta2_p02;
00186                 ScalarType mu0 = delta0_p02/denominator;
00187                 ScalarType mu2 = delta2_p02/denominator;
00188                 witness = (p0*mu0 + p2*mu2);
00189             }
00190             else if (delta2_p012<=ScalarType(0.0))
00191             {
00192                 ScalarType denominator = delta0_p01+delta1_p01;
00193                 ScalarType mu0 = delta0_p01/denominator;
00194                 ScalarType mu1 = delta1_p01/denominator;
00195                 witness = (p0*mu0 + p1*mu1);
00196             }
00197             else
00198             {
00199                 // or else can be an point internal to the triangle
00200                 ScalarType denominator =  delta0_p012 + delta1_p012 + delta2_p012;
00201                 ScalarType lambda0 = delta0_p012/denominator;
00202                 ScalarType lambda1 = delta1_p012/denominator;
00203                 ScalarType lambda2 = delta2_p012/denominator;
00204                 witness = p0*lambda0 + p1*lambda1 + p2*lambda2;
00205             }
00206         }
00207 
00208         if (res!=NULL)
00209         {
00210             ScalarType witness_norm = witness.Norm();
00211       res->first  = std::max< ScalarType >( witness_norm-radius, ScalarType(0.0) );
00212       res->second = std::max< ScalarType >( radius-witness_norm, ScalarType(0.0) );
00213         }
00214         penetration_detected = (witness.SquaredNorm() <= (radius*radius));
00215         witness += center;
00216         return penetration_detected;
00217     }; //end of IntersectionSphereTriangle
00218 
00220   template<class T>
00221     inline bool IntersectionPlaneLine( const Plane3<T> & pl, const Line3<T> & li, Point3<T> & po){
00222     const T epsilon = T(1e-8);
00223 
00224     T k = pl.Direction().dot(li.Direction());                                           // Compute 'k' factor
00225     if( (k > -epsilon) && (k < epsilon))
00226       return false;
00227     T r = (pl.Offset() - pl.Direction().dot(li.Origin()))/k;    // Compute ray distance
00228     po = li.Origin() + li.Direction()*r;
00229     return true;
00230   }
00232     template<class T>
00233     inline bool IntersectionLinePlane(const Line3<T> & li, const Plane3<T> & pl, Point3<T> & po){
00234 
00235       return IntersectionPlaneLine(pl,li,po);
00236     }
00237 
00239   template<class T>
00240     inline bool IntersectionPlaneSegment( const Plane3<T> & pl, const Segment3<T> & s, Point3<T> & p0){
00241         T p1_proj = s.P1()*pl.Direction()-pl.Offset();
00242         T p0_proj = s.P0()*pl.Direction()-pl.Offset();
00243     if ( (p1_proj>0)-(p0_proj<0)) return false;
00244 
00245     if(p0_proj == p1_proj) return false;
00246 
00247     // check that we perform the computation in a way that is independent with v0 v1 swaps
00248     if(p0_proj < p1_proj)
00249            p0 =  s.P0() + (s.P1()-s.P0()) * fabs(p0_proj/(p1_proj-p0_proj));
00250     if(p0_proj > p1_proj)
00251            p0 =  s.P1() + (s.P0()-s.P1()) * fabs(p1_proj/(p0_proj-p1_proj));
00252 
00253         return true;
00254   }
00255 
00257   template<class ScalarType>
00258     inline bool IntersectionPlaneSegmentEpsilon(const Plane3<ScalarType> & pl,
00259                                                 const Segment3<ScalarType> & sg,
00260                                                 Point3<ScalarType> & po,
00261                                                 const ScalarType epsilon = ScalarType(1e-8)){
00262 
00263     typedef ScalarType T;
00264     T k = pl.Direction().dot((sg.P1()-sg.P0()));
00265     if( (k > -epsilon) && (k < epsilon))
00266       return false;
00267     T r = (pl.Offset() - pl.Direction().dot(sg.P0()))/k;        // Compute ray distance
00268     if( (r<0) || (r > 1.0))
00269       return false;
00270     po = sg.P0()*(1-r)+sg.P1() * r;
00271     return true;
00272   }
00273 
00275   // not optimal: uses plane-segment intersection (and the fact the two or none edges can be intersected)
00276   // its use is rather dangerous because it can return inconsistent stuff on degenerate cases.
00277   // added assert to underline this danger.
00278   template<typename TRIANGLETYPE>
00279     inline bool IntersectionPlaneTriangle( const Plane3<typename TRIANGLETYPE::ScalarType> & pl,
00280                   const  TRIANGLETYPE & tr,
00281             Segment3<typename TRIANGLETYPE::ScalarType> & sg)
00282     {
00283       typedef typename TRIANGLETYPE::ScalarType T;
00284       if(IntersectionPlaneSegment(pl,Segment3<T>(tr.cP(0),tr.cP(1)),sg.P0()))
00285       {
00286         if(IntersectionPlaneSegment(pl,Segment3<T>(tr.cP(0),tr.cP(2)),sg.P1()))
00287           return true;
00288         else
00289         {
00290           if(IntersectionPlaneSegment(pl,Segment3<T>(tr.cP(1),tr.cP(2)),sg.P1()))
00291             return true;
00292           else assert(0);
00293               return true;
00294         }
00295       }
00296       else
00297       {
00298         if(IntersectionPlaneSegment(pl,Segment3<T>(tr.cP(1),tr.cP(2)),sg.P0()))
00299         {
00300           if(IntersectionPlaneSegment(pl,Segment3<T>(tr.cP(0),tr.cP(2)),sg.P1()))return true;
00301           assert(0);
00302           return true;
00303         }
00304       }
00305       return false;
00306     }
00307 
00309     template<typename TRIANGLETYPE>
00310     inline bool IntersectionTriangleTriangle(const TRIANGLETYPE & t0,const TRIANGLETYPE & t1){
00311       return NoDivTriTriIsect(t0.cP(0),t0.cP(1),t0.cP(2),
00312                               t1.cP(0),t1.cP(1),t1.cP(2));
00313     }
00314 
00315   template<class T>
00316     inline bool IntersectionTriangleTriangle(Point3<T> V0,Point3<T> V1,Point3<T> V2,
00317                  Point3<T> U0,Point3<T> U1,Point3<T> U2){
00318     return NoDivTriTriIsect(V0,V1,V2,U0,U1,U2);
00319   }
00320 #if 0
00321   template<class T>
00322     inline bool Intersection(Point3<T> V0,Point3<T> V1,Point3<T> V2,
00323                  Point3<T> U0,Point3<T> U1,Point3<T> U2,int *coplanar,
00324                  Point3<T> &isectpt1,Point3<T> &isectpt2){
00325 
00326     return tri_tri_intersect_with_isectline(V0,V1,V2,U0,U1,U2,
00327                         coplanar,isectpt1,isectpt2);
00328   }
00329 
00330   template<typename TRIANGLETYPE,typename SEGMENTTYPE >
00331     inline bool Intersection(const TRIANGLETYPE & t0,const TRIANGLETYPE & t1,bool &coplanar,
00332                  SEGMENTTYPE  & sg){
00333     Point3<typename SEGMENTTYPE::PointType> ip0,ip1;
00334     return  tri_tri_intersect_with_isectline(t0.P0(0),t0.P0(1),t0.P0(2),
00335                          t1.P0(0),t1.P0(1),t1.P0(2),
00336                          coplanar,sg.P0(),sg.P1()
00337                          );
00338   }
00339 
00340 #endif
00341 
00342     /*
00343     * Function computing the intersection between a line and a triangle.
00344     * from:
00345     * Tomas Moller and Ben Trumbore,
00346     * ``Fast, Minimum Storage Ray-Triangle Intersection'',
00347     * journal of graphics tools, vol. 2, no. 1, pp. 21-28, 1997
00348     * @param[in]        line
00349     * @param[in]        triangle vertices
00350     * @param[out]=(t,u,v)       the intersection point, meaningful only if the line intersects the triangle
00351     *            t is the line parameter and
00352     *            (u,v) are the baricentric coords of the intersection point
00353     *
00354     *                 Line.Orig + t * Line.Dir = (1-u-v) * Vert0 + u * Vert1 +v * Vert2
00355     *
00356     */
00357 
00358 template<class T>
00359 bool IntersectionLineTriangle( const Line3<T> & line, const Point3<T> & vert0,
00360                   const Point3<T> & vert1, const Point3<T> & vert2,
00361                   T & t ,T & u, T & v)
00362 {
00363     #define EPSIL 0.000001
00364 
00365     vcg::Point3<T> edge1, edge2, tvec, pvec, qvec;
00366     T det,inv_det;
00367 
00368    /* find vectors for two edges sharing vert0 */
00369    edge1 = vert1 - vert0;
00370    edge2 = vert2 - vert0;
00371 
00372    /* begin calculating determinant - also used to calculate U parameter */
00373    pvec =  line.Direction() ^ edge2;
00374 
00375    /* if determinant is near zero, line lies in plane of triangle */
00376    det =  edge1 *  pvec;
00377 
00378    /* calculate distance from vert0 to line origin */
00379    tvec = line.Origin() - vert0;
00380    inv_det = 1.0 / det;
00381 
00382    qvec = tvec ^ edge1;
00383 
00384    if (det > EPSIL)
00385    {
00386       u =  tvec * pvec ;
00387       if ( u < 0.0 ||  u > det)
00388      return 0;
00389 
00390       /* calculate V parameter and test bounds */
00391        v =  line.Direction() * qvec;
00392       if ( v < 0.0 ||  u +  v > det)
00393      return 0;
00394 
00395    }
00396    else if(det < -EPSIL)
00397    {
00398       /* calculate U parameter and test bounds */
00399        u =  tvec * pvec ;
00400       if ( u > 0.0 ||  u < det)
00401      return 0;
00402 
00403       /* calculate V parameter and test bounds */
00404        v =  line.Direction() * qvec  ;
00405       if ( v > 0.0 ||  u +  v < det)
00406      return 0;
00407    }
00408    else return 0;  /* line is parallell to the plane of the triangle */
00409 
00410     t = edge2 *  qvec  * inv_det;
00411    ( u) *= inv_det;
00412    ( v) *= inv_det;
00413 
00414    return 1;
00415 }
00416 
00417 template<class T>
00418 bool IntersectionRayTriangle( const Ray3<T> & ray, const Point3<T> & vert0,
00419                   const Point3<T> & vert1, const Point3<T> & vert2,
00420                   T & t ,T & u, T & v)
00421 {
00422     Line3<T> line(ray.Origin(), ray.Direction());
00423     if (IntersectionLineTriangle(line, vert0, vert1, vert2, t, u, v))
00424     {
00425         if (t < 0) return 0;
00426         else return 1;
00427     }else return 0;
00428 }
00429 
00430 // line-box
00431 template<class T>
00432 bool IntersectionLineBox( const Box3<T> & box, const Line3<T> & r, Point3<T> & coord )
00433 {
00434     const int NUMDIM = 3;
00435     const int RIGHT  = 0;
00436     const int LEFT       = 1;
00437     const int MIDDLE = 2;
00438 
00439     int inside = 1;
00440     char quadrant[NUMDIM];
00441     int i;
00442     int whichPlane;
00443     Point3<T> maxT,candidatePlane;
00444 
00445     // Find candidate planes; this loop can be avoided if
00446     // rays cast all from the eye(assume perpsective view)
00447     for (i=0; i<NUMDIM; i++)
00448     {
00449         if(r.Origin()[i] < box.min[i])
00450         {
00451             quadrant[i] = LEFT;
00452             candidatePlane[i] = box.min[i];
00453             inside = 0;
00454         }
00455         else if (r.Origin()[i] > box.max[i])
00456         {
00457             quadrant[i] = RIGHT;
00458             candidatePlane[i] = box.max[i];
00459             inside = 0;
00460         }
00461         else
00462         {
00463             quadrant[i] = MIDDLE;
00464         }
00465     }
00466 
00467         // Ray origin inside bounding box
00468     if(inside){
00469         coord = r.Origin();
00470         return true;
00471     }
00472 
00473     // Calculate T distances to candidate planes
00474     for (i = 0; i < NUMDIM; i++)
00475     {
00476         if (quadrant[i] != MIDDLE && r.Direction()[i] !=0.)
00477             maxT[i] = (candidatePlane[i]-r.Origin()[i]) / r.Direction()[i];
00478         else
00479             maxT[i] = -1.;
00480     }
00481 
00482     // Get largest of the maxT's for final choice of intersection
00483     whichPlane = 0;
00484     for (i = 1; i < NUMDIM; i++)
00485         if (maxT[whichPlane] < maxT[i])
00486             whichPlane = i;
00487 
00488     // Check final candidate actually inside box
00489     if (maxT[whichPlane] < 0.) return false;
00490     for (i = 0; i < NUMDIM; i++)
00491         if (whichPlane != i)
00492         {
00493             coord[i] = r.Origin()[i] + maxT[whichPlane] *r.Direction()[i];
00494             if (coord[i] < box.min[i] || coord[i] > box.max[i])
00495                 return false;
00496         }
00497         else
00498         {
00499             coord[i] = candidatePlane[i];
00500         }
00501     return true;                        // ray hits box
00502 }
00503 
00504 // ray-box
00505 template<class T>
00506 bool IntersectionRayBox( const Box3<T> & box, const Ray3<T> & r, Point3<T> & coord )
00507 {
00508     Line3<T> l;
00509     l.SetOrigin(r.Origin());
00510     l.SetDirection(r.Direction());
00511   return(IntersectionLineBox<T>(box,l,coord));
00512 }
00513 
00514 // segment-box return fist intersection found  from p0 to p1
00515 template<class ScalarType>
00516 bool IntersectionSegmentBox( const Box3<ScalarType> & box,
00517                               const Segment3<ScalarType> & s,
00518                               Point3<ScalarType> & coord )
00519 {
00520     //as first perform box-box intersection
00521     Box3<ScalarType> test;
00522     test.Add(s.P0());
00523     test.Add(s.P1());
00524     if (!test.Collide(box))
00525         return false;
00526     else
00527     {
00528         Line3<ScalarType> l;
00529         Point3<ScalarType> dir=s.P1()-s.P0();
00530         dir.Normalize();
00531         l.SetOrigin(s.P0());
00532         l.SetDirection(dir);
00533     if(IntersectionLineBox<ScalarType>(box,l,coord))
00534             return (test.IsIn(coord));
00535         return false;
00536     }
00537 }
00538 
00539 // segment-box intersection , return number of intersections and intersection points
00540 template<class ScalarType>
00541 int IntersectionSegmentBox( const Box3<ScalarType> & box,
00542                              const Segment3<ScalarType> & s,
00543                              Point3<ScalarType> & coord0,
00544                              Point3<ScalarType> & coord1 )
00545 {
00546     int num=0;
00547     Segment3<ScalarType> test= s;
00548   if (IntersectionSegmentBox(box,test,coord0 ))
00549     {
00550         num++;
00551         Point3<ScalarType> swap=test.P0();
00552         test.P0()=test.P1();
00553         test.P1()=swap;
00554     if (IntersectionSegmentBox(box,test,coord1 ))
00555             num++;
00556     }
00557     return num;
00558 }
00559 
00570 template<class ScalarType>
00571 bool IntersectionSegmentTriangle( const vcg::Segment3<ScalarType> & seg,
00572                                    const Point3<ScalarType> & vert0,
00573                                     const Point3<ScalarType> & vert1, const
00574                                     Point3<ScalarType> & vert2,
00575                                     ScalarType & a ,ScalarType & b)
00576 {
00577     //control intersection of bounding boxes
00578     vcg::Box3<ScalarType> bb0,bb1;
00579     bb0.Add(seg.P0());
00580     bb0.Add(seg.P1());
00581     bb1.Add(vert0);
00582     bb1.Add(vert1);
00583     bb1.Add(vert2);
00584     Point3<ScalarType> inter;
00585     if (!bb0.Collide(bb1))
00586         return false;
00587   if (!vcg::IntersectionSegmentBox(bb1,seg,inter))
00588         return false;
00589 
00590     //first set both directions of ray
00591   vcg::Line3<ScalarType> line;
00592     vcg::Point3<ScalarType> dir;
00593     ScalarType length=seg.Length();
00594     dir=(seg.P1()-seg.P0());
00595     dir.Normalize();
00596   line.Set(seg.P0(),dir);
00597     ScalarType orig_dist;
00598   if(IntersectionLineTriangle<ScalarType>(line,vert0,vert1,vert2,orig_dist,a,b))
00599     return (orig_dist>=0 && orig_dist<=length);
00600   return false;
00601 }
00606 template<class TriangleType>
00607 bool IntersectionSegmentTriangle( const vcg::Segment3<typename TriangleType::ScalarType> & seg,
00608                   const TriangleType &t,
00609                   typename TriangleType::ScalarType & a ,typename TriangleType::ScalarType & b)
00610 {
00611   return IntersectionSegmentTriangle(seg,t.cP(0),t.cP(1),t.cP(2),a,b);
00612 }
00613 
00614 template<class ScalarType>
00615 bool IntersectionPlaneBox(const vcg::Plane3<ScalarType> &pl,
00616                             vcg::Box3<ScalarType> &bbox)
00617 {
00618     ScalarType dist,dist1;
00619     if(bbox.IsNull()) return false; // intersection with a  null bbox is empty
00620     dist = SignedDistancePlanePoint(pl,bbox.P(0)) ;
00621     for (int i=1;i<8;i++)  if(  SignedDistancePlanePoint(pl,bbox.P(i))*dist<0) return true;
00622     return true;
00623 }
00624 
00625 template<class ScalarType>
00626 bool IntersectionTriangleBox(const vcg::Box3<ScalarType>   &bbox,
00627                                const vcg::Point3<ScalarType> &p0,
00628                                const vcg::Point3<ScalarType> &p1,
00629                                const vcg::Point3<ScalarType> &p2)
00630 {
00631     typedef typename vcg::Point3<ScalarType> CoordType;
00632     CoordType intersection;
00634     vcg::Box3<ScalarType> test;
00635     test.SetNull();
00636     test.Add(p0);
00637     test.Add(p1);
00638     test.Add(p2);
00639     if (!test.Collide(bbox))
00640         return false;
00642     if ((bbox.IsIn(p0))||(bbox.IsIn(p1))||(bbox.IsIn(p2)))
00643         return true;
00644 
00646     //vcg::Plane3<ScalarType> plTri=vcg::Plane3<ScalarType>();
00647     //plTri.Init(p0,p1,p2);
00648   //if (!IntersectionPlaneBox<ScalarType>(plTri,bbox))
00649     //  return false;
00650 
00652   if (IntersectionSegmentBox<ScalarType>(bbox,vcg::Segment3<ScalarType>(p0,p1),intersection)||
00653     IntersectionSegmentBox<ScalarType>(bbox,vcg::Segment3<ScalarType>(p1,p2),intersection)||
00654     IntersectionSegmentBox<ScalarType>(bbox,vcg::Segment3<ScalarType>(p2,p0),intersection))
00655         return true;
00657 
00658     Segment3<ScalarType> diag[4];
00659 
00660     diag[0]=Segment3<ScalarType>(bbox.P(0),bbox.P(7));
00661     diag[1]=Segment3<ScalarType>(bbox.P(1),bbox.P(6));
00662     diag[2]=Segment3<ScalarType>(bbox.P(2),bbox.P(5));
00663     diag[3]=Segment3<ScalarType>(bbox.P(3),bbox.P(4));
00664     ScalarType a,b;
00665     for (int i=0;i<3;i++)
00666     if (IntersectionSegmentTriangle<ScalarType>(diag[i],p0,p1,p2,a,b))
00667             return true;
00668 
00669     return false;
00670 }
00671 
00672 template <class SphereType>
00673 bool IntersectionSphereSphere( const SphereType & s0,const SphereType & s1){
00674     return (s0.Center()-s1.Center()).SquaredNorm() < (s0.Radius()+s1.Radius())*(s0.Radius()+s1.Radius());
00675 }
00676 
00677 template<class T>
00678 bool IntersectionPlanePlane (const Plane3<T> & plane0, const Plane3<T> & plane1,
00679                              Line3<T> & line)
00680 {
00681     // If Cross(N0,N1) is zero, then either planes are parallel and separated
00682     // or the same plane.  In both cases, 'false' is returned.  Otherwise,
00683     // the intersection line is
00684     //
00685     //   L(t) = t*Cross(N0,N1) + c0*N0 + c1*N1
00686     //
00687     // for some coefficients c0 and c1 and for t any real number (the line
00688     // parameter).  Taking dot products with the normals,
00689     //
00690     //   d0 = Dot(N0,L) = c0*Dot(N0,N0) + c1*Dot(N0,N1)
00691     //   d1 = Dot(N1,L) = c0*Dot(N0,N1) + c1*Dot(N1,N1)
00692     //
00693     // which are two equations in two unknowns.  The solution is
00694     //
00695     //   c0 = (Dot(N1,N1)*d0 - Dot(N0,N1)*d1)/det
00696     //   c1 = (Dot(N0,N0)*d1 - Dot(N0,N1)*d0)/det
00697     //
00698     // where det = Dot(N0,N0)*Dot(N1,N1)-Dot(N0,N1)^2.
00699 
00700     T n00 = plane0.Direction()*plane0.Direction();
00701     T n01 = plane0.Direction()*plane1.Direction();
00702     T n11 = plane1.Direction()*plane1.Direction();
00703     T det = n00*n11-n01*n01;
00704 
00705     const T tolerance = (T)(1e-06f);
00706         if ( math::Abs(det) < tolerance )
00707         return false;
00708 
00709     T invDet = 1.0f/det;
00710     T c0 = (n11*plane0.Offset() - n01*plane1.Offset())*invDet;
00711     T c1 = (n00*plane1.Offset() - n01*plane0.Offset())*invDet;
00712 
00713     line.SetDirection(plane0.Direction()^plane1.Direction());
00714     line.SetOrigin(plane0.Direction()*c0+ plane1.Direction()*c1);
00715 
00716     return true;
00717 }
00718 
00719 
00720 // Ray-Triangle Functor
00721 template <bool BACKFACETEST = true>
00722 class RayTriangleIntersectionFunctor {
00723 public:
00724     template <class TRIANGLETYPE, class SCALARTYPE>
00725     inline bool operator () (const TRIANGLETYPE & f, const Ray3<SCALARTYPE> & ray, SCALARTYPE & t) {
00726         typedef SCALARTYPE ScalarType;
00727         ScalarType u;
00728         ScalarType v;
00729 
00730         bool bret = IntersectionRayTriangle(ray, Point3<SCALARTYPE>::Construct(f.cP(0)), Point3<SCALARTYPE>::Construct(f.cP(1)), Point3<SCALARTYPE>::Construct(f.cP(2)), t, u, v);
00731         if (BACKFACETEST) {
00732             if (!bret) {
00733                 bret = IntersectionRayTriangle(ray, Point3<SCALARTYPE>::Construct(f.cP(0)), Point3<SCALARTYPE>::Construct(f.cP(2)), Point3<SCALARTYPE>::Construct(f.cP(1)), t, u, v);
00734             }
00735         }
00736         return (bret);
00737     }
00738 };
00739 
00740 
00744 } // end namespace
00745 #endif


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:32:05