shape_doc 0.1
/Users/mourrain/Devel/mmx/shape/src/ssi_dsearch_triangle.cpp
Go to the documentation of this file.
00001 #include <shape/ssi_dsearch.hpp>
00002 #include <shape/ssi_tri_tri.hpp>
00003 #include <shape/ssi_math.hpp>
00004 
00005 namespace mmx {
00006 #define SHIFT 3
00007 
00008 namespace  shape_ssi {
00009   
00010   static const int up_triangle_[] = { 0, 1, 3 };
00011   static const int dw_triangle_[] = { 2, 3, 1 };
00012 
00013 #define __up__   0
00014 #define __down__ 1
00015     /* return the up triangle of quad q */
00016 #define __up__triangle__(q)         q[0],q[3],q[2]
00017     /* return the down triangle of quad q */
00018 #define __down__triangle__(q)       q[0],q[1],q[2]
00019     /* return the parametric plane of up triangle of q */
00020 #define __up__param_triangle__(q)   q[3],q[2],q[0]
00021     /* return the parametric plane of down triangle of q */
00022 #define __down__param_triangle__(q) q[1],q[0],q[2]
00023 #define __convert_order__(i,point) { point[(i+1)%2] = 1.0-point[(i+1)%2]; }
00024   /* check for the intersection beetween {UP,DOWN}/{UP,DOWN} triangles */
00025 #define __triangle_triangle_case__(trig0,trig1)                           \
00026     {                                                                     \
00027       if ( geom::intersectp_triangles3_isegment                           \
00028            ( coplanar, seg[0], seg[1],                                    \
00029              trig0##triangle__(a),                                        \
00030              trig1##triangle__(b), point3::value_type(1e-12) ))           \
00031         {                                                                 \
00032           if ( !coplanar )                                                \
00033             {                                                             \
00034               space2prm(/* points in parameter space */                    \
00035                      seg0[0], seg0[1],                                    \
00036                      /* corresponding points in R3 */                     \
00037                       seg[0],  seg[1],                                    \
00038                      /* parametric plane = base + 2 vectors  */           \
00039                      trig0##param_triangle__(a)                           \
00040                      );                                                   \
00041               space2prm( seg1[0], seg1[1],                                 \
00042                         seg[0], seg[1],                                   \
00043                         trig1##param_triangle__(b) );                     \
00044               /* retrieve the correct offset coordinates in quad */       \
00045             __convert_order__(trig0,seg0[0]);                             \
00046             __convert_order__(trig0,seg0[1]);                             \
00047             __convert_order__(trig1,seg1[0]);                             \
00048             __convert_order__(trig1,seg1[1]);                             \
00049             }                                                             \
00050         else                                                              \
00051           {\
00052             seg0[0][0] = 1.0/3.0; seg0[0][1] = 1.0/3.0;                   \
00053             seg0[1][0] = 1.0/3.0; seg0[1][0] = 1.0/3.0;                   \
00054             seg1[0][0] = 1.0/3.0; seg1[0][1] = 1.0/3.0;                   \
00055             seg1[1][0] = 1.0/3.0; seg1[1][1] = 1.0/3.0;                   \
00056             __convert_order__(trig0,seg0[0]);                             \
00057             __convert_order__(trig0,seg0[1]);                             \
00058             __convert_order__(trig1,seg1[0]);                             \
00059             __convert_order__(trig1,seg1[1]);                             \
00060           };                                                              \
00061             {                                                             \
00062               f->convert(seg0,this,2);                                    \
00063               s->convert(seg1,this,2);                                    \
00064               push( seg0[0], seg0[1], seg1[0], seg1[1], seg[0],seg[1] );  \
00065             }                                                             \
00066         };                                                                \
00067     }                                                                     \
00068 
00069   //              f->convert(seg0,this,2);
00070   //            s->convert(seg1,this,2);
00071     
00072   
00073 
00074   void space2prm( vector2 & pa, 
00075                   vector2 & pb,
00076                   const vector3& sa, 
00077                   const vector3& sb,
00078                   const vector3& base, 
00079                   const vector3& pu, 
00080                   const vector3& pv )
00081   {
00082   /* T(u,v) = base + u*bu +v*bv
00083      => 
00084      spc[0] - base[0] = delta[0]  = / bu[0] bv[0]\  / u \
00085      spc[1] - base[1] = delta[1]  = | bu[1] bv[1]|  |   |
00086      spc[2] - base[2] = delta[2]  = \ bu[2] bv[2]/  \ v /
00087   */
00088   vector3 bu;
00089   for ( int i = 0; i < 3; i ++ ) bu[i] = pu[i]-base[i];
00090   vector3 bv;
00091   for ( int i = 0; i < 3; i ++ ) bv[i] = pv[i]-base[i];
00092   double muu, mvv, muv;
00093   muu = 0;
00094   for ( int i = 0; i < 3; i ++ ) muu += bu[i]*bu[i];
00095   mvv = 0;
00096   for ( int i = 0; i < 3; i ++ ) mvv += bv[i]*bv[i];
00097   muv = 0; 
00098   for ( int i = 0; i < 3; i ++ ) muv += bu[i]*bv[i];
00099   double detm = muu*mvv - muv*muv;
00100   vector3 delta;
00101   double x, y;
00102   for ( int k = 0; k < 3; k ++ ) delta[k] = sa[k]-base[k];
00103   x = 0;
00104   for ( int k = 0; k < 3; k ++ ) x += bu[k]*delta[k];
00105   y = 0; 
00106   for ( int k = 0; k < 3; k ++ ) y += bv[k]*delta[k];
00107   pa[0] = (mvv * x - muv * y)/detm;
00108   pa[1] = (muu * y - muv * x)/detm;
00109   for ( int k = 0; k < 3; k ++ ) delta[k] = sb[k]-base[k];
00110   x = 0;
00111   for ( int k = 0; k < 3; k ++ ) x += bu[k]*delta[k];
00112   y = 0; 
00113   for ( int k = 0; k < 3; k ++ ) y += bv[k]*delta[k];
00114   pb[0] = (mvv * x - muv * y)/detm;
00115   pb[1] = (muu * y - muv * x)/detm;
00116 };
00117     
00118 void dsearch::cnfpush( qtree f, qtree s )
00119 {
00120   point3 a[4],b[4]; //      point3 a[4]; point3 b[4];
00121   f->fill(a,this);
00122   s->fill(b,this);
00123   cnfdata3.push_back( ((double)(1.0/4.0))*(a[0]+a[1]+a[2]+a[3]) );
00124 };
00125 
00126 // push an quad / quad conflict
00127 // intersection is computed if any and added to the current conflict set of segments
00128 void dsearch::push( qtree f, qtree s )
00129 {
00130   if ( std::abs(f->umin-s->umin)+std::abs(f->vmin-s->vmin) < SHIFT ) return;
00131   conflict_count ++;
00132   point3 a[4],b[4]; 
00133   scale_conflict(a,b,f,s);
00134   {
00135     point3  seg[2];
00136     point2 seg0[2], seg1[2];
00137     bool   coplanar;
00138     __triangle_triangle_case__(__up__,__up__);
00139     __triangle_triangle_case__(__up__,__down__);
00140     __triangle_triangle_case__(__down__,__down__);
00141     __triangle_triangle_case__(__down__,__up__);
00142   }
00143 };
00144 /*
00145   void vector_sub( point3& r, const point3& a, const point3& b )
00146   {
00147   for ( unsigned i = 0; i < d; i++ )
00148   r[i] = a[i]-b[i];
00149   };
00150   
00151   double_t vector_dotprod( const point3& a, const point3& b )
00152   {
00153   double_t tmp = 0;
00154   for ( unsigned i = 0; i < d; i++ )
00155   tmp += a[i]*b[i];
00156   return tmp;
00157   };
00158   
00159   void vector_crossprod( point3& r, const point3& a, const point3& b )
00160     {
00161     r[2] = a[0]*b[1]-a[1]*b[0];
00162     r[0] = a[1]*b[2]-a[2]*b[1];
00163     r[1] = a[2]*b[0]-a[0]*b[2];
00164     };
00165     double_t vector_nmax( const point3& a, const point3& b)
00166     {
00167     double_t m = std::abs(a[0]-b[0]);
00168     for ( unsigned i = 1; i < d; i++ )
00169     {
00170     double_t c = std::abs(a[i]-b[i]);
00171     if ( c > m ) m = c;
00172     };
00173     return m;
00174     };
00175     
00176     struct FirstOrderException{};
00177     
00178     void reachpt( double_t& du, double_t& dv, const point_t& delta, const point_t& Tu, const point_t& Tv )
00179     {
00180     number_t v0,v1;
00181     number_t m00,m11,m01;
00182     v0  = vector_dotprod( delta, Tu );
00183     v1  = vector_dotprod( delta, Tv );
00184     m00 = vector_dotprod( Tu, Tu );
00185     m11 = vector_dotprod( Tv, Tv );
00186     m01 = vector_dotprod( Tu, Tv );
00187     number_t det = m00*m11-m01*m01;
00188     if ( det < 1e-20 )  throw FirstOrderException(); 
00189     du = (m11*v0-m01*v1)/det;
00190     dv = (m00*v1-m01*v0)/det;
00191     };
00192     
00193     bool hosaka_iter( number_t& du, number_t& dv, number_t& ds, number_t& dt, 
00194     point_t& pA, point_t& pB, 
00195     const number_t& u, const number_t& v, const number_t& s, const number_t& t )
00196     {
00197     
00198     point_t tAu,tAv,tBu,tBv;
00199 
00200     m_smp->DiffUEval(tAu,u,v); m_smp->DiffVEval(tAv,u,v);
00201     m_smp->DiffUEval(tBu,s,t); m_smp->DiffVEval(tBv,s,t);
00202     
00203     point_t nA,nB,nD;
00204     
00205     vector_crossprod( nA, tAu, tAv );
00206     vector_crossprod( nB, tBu, tBv );      
00207     vector_crossprod( nD, nA, nB   );
00208     
00209     number_t dA,dB,dD;
00210     
00211     dA = vector_dotprod( nA, pA );
00212     dB = vector_dotprod( nB, pB );
00213     dD = vector_dotprod( nD, pB );
00214     
00215     
00216     number_t d2nD = vector_dotprod( nD, nD ) ;
00217     number_t d2nA = vector_dotprod( nA, nA ) ;
00218     number_t d2nB = vector_dotprod( nB, nB ) ;
00219     
00220     if ( d2nD < 1e-6*d2nA*d2nB ) throw FirstOrderException();
00221     
00222     // plane3
00223     
00224     point_t c0,c1,x;
00225     
00226     vector_crossprod( c0, nB, nD );
00227     vector_crossprod( c1, nD, nA );
00228     
00229     x[0] = c0[0]*dA+c1[0]*dB+nD[0]*dD;
00230     x[1] = c0[1]*dA+c1[1]*dB+nD[1]*dD;
00231     x[2] = c0[2]*dA+c1[2]*dB+nD[2]*dD;
00232     
00233     number_t sc = 1.0/d2nD;
00234     
00235     x[0] *= sc;
00236     x[1] *= sc;
00237     x[2] *= sc;
00238     
00239     
00240     point_t Adelta,Bdelta;
00241     
00242     vector_sub(Adelta,x,pA);
00243     vector_sub(Bdelta,x,pB);
00244     
00245     reachpt( du, dv, Adelta, tAu, tAv );
00246     reachpt( ds, dt, Bdelta, tBu, tBv );
00247     
00248     };
00249     
00250     
00251     bool hosaka( point2& l, point2& r )
00252     {
00253     point3 pA,pB;
00254     number u,v,s,t;
00255     
00256     const number Sdu(m_smp->du()/3.0);
00257     const number Sdv(m_smp->dv()/3.0);
00258     
00259     u = l[0]*this->m_du+this->Fct->umin();
00260     v = l[1]*m_dv+this->Fct->vmin();
00261     
00262     s = r[0]*this->m_du+this->Fct->umin();
00263     t = r[1]*m_dv+this->Fct->vmin(); 
00264     
00265     this->Fct->Eval(pA,u,v);
00266     this->Fct->Eval(pB,s,t);
00267     
00268     number d = vector_nmax(pA,pB);
00269     
00270          #define exiting()\
00271          {\
00272          if ( std::abs(du) > Sdu ) return false;\
00273          if ( std::abs(ds) > Sdu ) return false;\
00274          if ( std::abs(dv) > Sdv ) return false;\
00275          if ( std::abs(dt) > Sdv ) return false;\
00276          l[0] = u;\
00277          l[1] = v;\
00278            r[0] = s;\
00279            r[1] = t;\
00280           }
00281 
00282 
00283       for( int it = 0; it < 8; it++ )
00284         {
00285           number_t du,dv,ds,dt;
00286           try  { hosaka_iter(du,dv,ds,dt,pA,pB,u,v,s,t); }
00287           catch( ... ) 
00288             {
00289               l[0] = u; l[1] = v;
00290               r[0] = s; r[1] = t;
00291               return false;
00292             }
00293 
00294           exiting();
00295 
00296           u += du;
00297           v += dv;
00298           s += ds;
00299           t += dt;
00300           
00301           this->Fct->Eval(pA,u,v);
00302           this->Fct->Eval(pB,s,t);
00303           
00304           number_t err = vector_nmax(pA,pB);
00305 
00306           if (  err  <  d    )  d = err; else return false;
00307           if (  err  <  1e-7 ) 
00308           {
00309             using namespace std;
00310             if ( abs(u-s) < 1e-8 && abs(s-t) < 1e-8 ) return false;
00311             return true;
00312           };
00313         };
00314       return false;
00315     };
00316     */
00317 
00318 };
00319 } //namespace mmx