shape_doc 0.1
/Users/mourrain/Devel/mmx/shape/src/ssiqtsl.cpp
Go to the documentation of this file.
00001 # include <cmath>
00002 # include <fstream>
00003 # include <shape/ssiqtsl.hpp>
00004 # include <shape/ssiqts_tri_tri.hpp>
00005 # define  ParametricSurface shape::surface_parametric<double>
00006 
00007 namespace mmx {
00008 #include <shape/ssiqts_offsets.hpp>
00009 void POLYLINE( std::ostream& o, double * src, int nv, float * colors, int nc )
00010 {
00011   o << "{ = VECT\n";
00012   o << 1 << " " << nv << " " << nc << std::endl;
00013   o << nv << std::endl;
00014   o << nc << std::endl;
00015   for ( int i = 0; i < nv; i++, src += 3 )
00016     o << src[0] << " " << src[1] << " " << src[2] << std::endl;
00017   for ( int i = 0; i < nc; i++ )
00018     o << colors[i*4] << " " << colors[i*4+1] << " " << colors[i*4+2] << " " << colors[i*4+3] << std::endl;
00019   o << "}\n";
00020 };
00021 
00022 void UVSMP( std::ostream& o, double * src, unsigned m, unsigned n )
00023 {
00024 #define _ij_(i,j) (i)*n+j
00025   o << " { = MESH\n";
00026   o << m << " " << n << std::endl;
00027   for ( unsigned i = 0; i < m*n; i ++ )
00028     o << (src+i*3)[0] << " " <<  (src+i*3)[1] << " " << (src+i*3)[2] << std::endl;
00029   o << " }\n";
00030 };
00031 
00032 #define __up__   0
00033 #define __down__ 1
00034     /* return the up triangle of quad q */
00035 #define __up__triangle__(q)         q[0],q[3],q[2]
00036     /* return the down triangle of quad q */
00037 #define __down__triangle__(q)       q[0],q[1],q[2]
00038     /* return the parametric plane of up triangle of q */
00039 #define __up__param_triangle__(q)   q[3],q[2],q[0]
00040     /* return the parametric plane of down triangle of q */
00041 #define __down__param_triangle__(q) q[1],q[0],q[2]
00042 #define __convert_order__(i,point) { point[(i+1)%2] = 1.0-point[(i+1)%2]; }
00043 
00044     /* check for the intersection beetween {UP,DOWN}/{UP,DOWN} triangles */
00045 #define __triangle_triangle_case__(trig0,trig1)                            \
00046 {                                                                          \
00047    intersection =                                                          \
00048         intersectp_triangles3_isegment                                     \
00049        ( coplanar, seg[0], seg[1],                                         \
00050          trig0##triangle__(qa),                                            \
00051    trig1##triangle__(qb), double(1e-9) );                            \
00052     if ( intersection )                                                \
00053     {                                                                      \
00054       if ( !coplanar )                                                     \
00055         {                                                                  \
00056           space2prm(/* points in parameter space */                        \
00057                    seg0[0], seg0[1],                                       \
00058                    /* corresponding points in R3 */                        \
00059                    seg[0],  seg[1],                                        \
00060                    /* parametric plane = base + 2 vectors  */              \
00061                    trig0##param_triangle__(qa)                             \
00062                    );                                                      \
00063           space2prm( seg1[0], seg1[1],                                     \
00064                      seg[0], seg[1],                                       \
00065                     trig1##param_triangle__(qb) );                         \
00066           /* retrieve the correct offset coordinates in quad */            \
00067           __convert_order__(trig0,seg0[0]);                                \
00068           __convert_order__(trig0,seg0[1]);                                \
00069           __convert_order__(trig1,seg1[0]);                                \
00070           __convert_order__(trig1,seg1[1]);                                \
00071                                                                            \
00072           double * left_uvals = ssi.smpa->m_uvals;                         \
00073           double * left_vvals = ssi.smpa->m_vvals;                         \
00074           double * righ_uvals = ssi.smpb->m_uvals;                         \
00075           double * righ_vvals = ssi.smpb->m_vvals;                         \
00076           for ( int i = 0; i < 2; i ++ )                                   \
00077             {                                                              \
00078               seg0[i][0] = left_uvals[a/ssi.m] + seg0[i][0] * (left_uvals[a/ssi.m+1]-left_uvals[a/ssi.m]);\
00079               seg0[i][1] = left_vvals[a%ssi.m] + seg0[i][1] * (left_vvals[a%ssi.m+1]-left_vvals[a%ssi.m]);\
00080             };                                                             \
00081           for ( int i = 0; i < 2; i ++ )                                   \
00082             {                                                              \
00083               seg1[i][0] = righ_uvals[b/ssi.m] + seg1[i][0] * (righ_uvals[b/ssi.m+1]-righ_uvals[b/ssi.m]);\
00084               seg1[i][1] = righ_vvals[b%ssi.m] + seg1[i][1] * (righ_vvals[b%ssi.m+1]-righ_vvals[b%ssi.m]);\
00085             };                                                             \
00086           ssi.lpts.push_back(seg0[0]);                                     \
00087           ssi.lpts.push_back(seg0[1]);                                     \
00088           ssi.rpts.push_back(seg1[0]);                                     \
00089           ssi.rpts.push_back(seg1[1]);                                     \
00090         }                                                                  \
00091     }                                                                      \
00092 }
00093 
00094 
00095 static void space2prm( SSIQTSL::vector2 & pa, 
00096                        SSIQTSL::vector2 & pb,
00097                        const SSIQTSL::vector3& sa, 
00098                        const SSIQTSL::vector3& sb,
00099                        const SSIQTSL::vector3& base, 
00100                        const SSIQTSL::vector3& pu, 
00101                        const SSIQTSL::vector3& pv )
00102 {
00103   /* T(u,v) = base + u*bu +v*bv
00104      => 
00105      spc[0] - base[0] = delta[0]  = / bu[0] bv[0]\  / u \
00106      spc[1] - base[1] = delta[1]  = | bu[1] bv[1]|  |   |
00107      spc[2] - base[2] = delta[2]  = \ bu[2] bv[2]/  \ v /
00108   */
00109   SSIQTSL::vector3 bu;
00110   for ( int i = 0; i < 3; i ++ ) bu[i] = pu[i]-base[i];
00111   SSIQTSL::vector3 bv;
00112   for ( int i = 0; i < 3; i ++ ) bv[i] = pv[i]-base[i];
00113   double muu, mvv, muv;
00114   muu = 0;
00115   for ( int i = 0; i < 3; i ++ ) muu += bu[i]*bu[i];
00116   mvv = 0;
00117   for ( int i = 0; i < 3; i ++ ) mvv += bv[i]*bv[i];
00118   muv = 0; 
00119   for ( int i = 0; i < 3; i ++ ) muv += bu[i]*bv[i];
00120   double detm = muu*mvv - muv*muv;
00121   SSIQTSL::vector3 delta;
00122   double x, y;
00123   for ( int k = 0; k < 3; k ++ ) delta[k] = sa[k]-base[k];
00124   x = 0;
00125   for ( int k = 0; k < 3; k ++ ) x += bu[k]*delta[k];
00126   y = 0; 
00127   for ( int k = 0; k < 3; k ++ ) y += bv[k]*delta[k];
00128   pa[0] = (mvv * x - muv * y)/detm;
00129   pa[1] = (muu * y - muv * x)/detm;
00130   for ( int k = 0; k < 3; k ++ ) delta[k] = sb[k]-base[k];
00131   x = 0;
00132   for ( int k = 0; k < 3; k ++ ) x += bu[k]*delta[k];
00133   y = 0; 
00134   for ( int k = 0; k < 3; k ++ ) y += bv[k]*delta[k];
00135   pb[0] = (mvv * x - muv * y)/detm;
00136   pb[1] = (muu * y - muv * x)/detm;
00137 };
00138 
00139 
00140 static void merge( SSIQTS::aabb3 & box, const SSIQTS::aabb3& a, const SSIQTS::aabb3 & b )
00141 {
00142   for ( unsigned i = 0; i < 3; i ++ )
00143     {
00144       box[i][0] = std::min(a[i][0],b[i][0]);
00145       box[i][1] = std::max(a[i][1],b[i][1]);
00146     };
00147 };
00148 
00149 static void solve_cf( SSIQTSL::vector3 ** qpa, SSIQTSL::vector3 ** qpb, int a, int b, SSIQTSL & ssi  )
00150 {
00151   // scaling 
00152   SSIQTSL::aabb3 zoom;
00153   double mx = 0;
00154   merge(zoom,ssi.boxa[a],ssi.boxb[b]);
00155   /*
00156   std::cout << "boxa\n";
00157   for ( int i = 0; i < 3; i ++ )
00158     std::cout << boxa[a][i][0] << " " << boxa[a][i][1] << std::endl;
00159   std::cout << "boxb\n";
00160   for ( int i = 0; i < 3; i ++ )
00161     std::cout << boxb[b][i][0] << " " << boxb[b][i][1] << std::endl;
00162   */
00163     for ( int k = 0; k < 3; k ++ ) { 
00164     zoom[k][1] -= zoom[k][0];
00165     if ( zoom[k][1] > mx ) mx = zoom[k][1];
00166   };
00167 
00168   double sc = double(1.0)/mx;
00169   SSIQTSL::vector3 qa[4];
00170   SSIQTSL::vector3 qb[4];
00171 
00172   for ( int i = 0; i < 4; i ++ )
00173     for ( int k = 0; k < 3; k ++ )
00174       {
00175         qa[i][k] = ((*(qpa[i]))[k] - zoom[k][0]) * sc;
00176         qb[i][k] = ((*(qpb[i]))[k] - zoom[k][0]) * sc;
00177       };
00178   
00179   SSIQTSL::vector3 seg [2];
00180   SSIQTSL::vector2 seg0[2];
00181   SSIQTSL::vector2 seg1[2];
00182   bool coplanar = false;
00183   bool intersection;
00184   __triangle_triangle_case__(__up__,__up__);
00185   __triangle_triangle_case__(__up__,__down__);
00186   __triangle_triangle_case__(__down__,__up__);
00187   __triangle_triangle_case__(__down__,__down__);
00188 };
00189 
00190 
00191 void solve( SSIQTSL & ssi )
00192 {
00193   SSIQTSL::vector3 * sleft  = (SSIQTSL::vector3*)(&(ssi.smpa->m_svals)[0]);
00194   SSIQTSL::vector3 * sright = (SSIQTSL::vector3*)(&(ssi.smpb->m_svals)[0]);
00195   
00196   
00197   for( int * cf = ssi.m_bcf; cf != ssi.m_ecf; cf += *cf )
00198     {
00199       if ( cf[cfbg_] != -1 )
00200       {
00201         int lu = cf[cflq_]/ssi.m;
00202         int lv = cf[cflq_]%ssi.m;
00203         SSIQTSL::vector3 * qpl[4];
00204         qpl[0] = sleft  + lu*(ssi.m+1)+lv;
00205         qpl[1] = sleft  + (lu+1)*(ssi.m+1)+lv;
00206         qpl[2] = qpl[1] + 1;
00207         qpl[3] = qpl[0] + 1;
00208         int * rpq = cf+cfbg_;
00209         while ( *rpq != -1 && rpq != cf+*cf ) 
00210           {
00211             int ru = (*rpq/ssi.m);
00212             int rv = (*rpq%ssi.m);
00213             SSIQTSL::vector3 * qpr[4];
00214             qpr[0] = sright + ru*(ssi.m+1)+rv;
00215             qpr[1] = sright + (ru+1)*(ssi.m+1)+rv;
00216             qpr[2] = qpr[1] + 1;
00217             qpr[3] = qpr[0] + 1;
00218             solve_cf(qpl,qpr,cf[cflq_],*rpq,ssi);
00219             rpq++;
00220           };
00221         }
00222     };
00223 };
00224                                  
00225 
00226                  
00227 void SSIQTSL::gpdump()
00228 {
00229   std::ofstream gpl("SSIQTSL-L.dat");
00230   std::ofstream gpr("SSIQTSL-R.dat");
00231 
00232   for ( unsigned i = 0; i < lpts.size(); i ++ )
00233     gpl << lpts[i][0] << " " << lpts[i][1] << std::endl;
00234   for ( unsigned i = 0; i < rpts.size(); i ++ )
00235     gpr << rpts[i][0] << " " << rpts[i][1] << std::endl;
00236 };
00237 
00238 
00239 void SSIQTSL::gmvdump()
00240 {
00241   std::ofstream o("SSIQTSL.gmv");
00242   o << "LIST\n";
00243   float colora[] = { 0.0, 0.0, 1.0 };
00244   float colorb[] = { 0.0, 1.0, 0.0 };
00245   o << "appearance {\n material{\n diffuse " <<  
00246     colora[0] << " " <<  colora[1] << " " << colora[2] << "\n";
00247   o << "}\n}\n";
00248   UVSMP(o,&(smpa->m_svals[0][0]),m+1,m+1);
00249   o << "appearance {\n material{\n diffuse " <<  
00250     colorb[0] << " " <<  colorb[1] << " " << colorb[2] << "\n";
00251   o << "}\n}\n";
00252   UVSMP(o,&(smpb->m_svals[0][0]),m+1,m+1);
00253   float color[] = { 1.0, 0.0, 0.0, 1.0 };
00254   for ( unsigned i = 0; i < spcs.size(); i += 2 )
00255     {
00256       color[1] = double(i % 2);
00257       color[2] = double((i+1)%2);
00258       POLYLINE(o,&(spcs[i][0]),2,color,1);
00259     };
00260 };                
00261 
00262 
00263 void sample_curve3d( ParametricSurface * srfa, 
00264                      ParametricSurface * srfb, SSIQTSL& ssi )
00265 {
00266   //  std::cout << " left = " << ssi.lpts.size() << std::endl;
00267   int nl = ssi.lpts.size();
00268   //  std::cout << " right = " << ssi.rpts.size() << std::endl;
00269   ssi.spcs.resize( nl );
00270   std::vector<SSIQTSL::vector3> srfb_samples(nl);
00271   srfa->eval( (double*)(&(ssi.spcs[0])), (const double*)(&ssi.lpts[0]), ssi.lpts.size() );
00272   srfb->eval( (double*)(&(srfb_samples[0])), (const double*)(&ssi.rpts[0]), ssi.rpts.size() );
00273   //  std::vector<double> errs;
00274   //  ssi.errs.resize( ssi.lpts.size() );
00275   ssi.errmax = 0;
00276   for ( unsigned i = 0; i < ssi.lpts.size(); i ++ )
00277     {
00278 
00279       //      int lk0, lk1, stat;
00280       //      SSIQTSL::vector3 pa,pb;
00281       SSIQTSL::vector3 delta;
00282       double s = 0;
00283       //      std::cout << ssi.spcs[i] << std::endl;
00284       //      std::cout << srfb_samples[i] << std::endl;
00285       for ( int k =0; k < 3; k ++ )
00286         delta[k] = ssi.spcs[i][k]-srfb_samples[i][k];
00287       s = max_abs( delta );
00288       for ( int k = 0; k < 3; k ++ )
00289         ssi.spcs[i][k] = (ssi.spcs[i][k]+srfb_samples[i][k])/2;
00290       if ( s > ssi.errmax ) ssi.errmax = s;
00291     };
00292 };
00293 
00294 SSIQTSL::SSIQTSL( ParametricSurface *  srfa, 
00295                   ParametricSurface *  srfb, 
00296                   int n ) : SSIQTS(srfa,srfb,n,1,1)
00297 {
00298   solve(*this);
00299   sample_curve3d( srfa, srfb, *this );
00300   //  std::cout << errmax << std::endl;
00301   // gmvdump();
00302 };
00303 
00304 
00305 // gmv::stream & operator<<( gmv::stream & o, 
00306 //                        const ssi_linear & ssi )
00307 // {
00308 //   float colora[] = { 0.0, 0.0, 1.0 };
00309 //   float colorb[] = { 0.0, 1.0, 0.0 };
00310 //   o.matcolor(colora);
00311 //   o << (*ssi.smpa);
00312 //   o << (*ssi.smpb);
00313 //   float color[] = { 1.0, 0.0, 0.0, 1.0 };
00314 //   for ( int i = 0; i < ssi.spcs.size(); i += 2 )
00315 //     {
00316 //       //    color[1] = double(i % 2);
00317 //       //      color[2] = double((i+1)%2);
00318 //       o.polyline( &(ssi.spcs[i][0]), 2, color, 1);
00319 //     };
00320 //   return o;
00321 // };
00322 
00323 } //namespace mmx
00324 
00325 # undef ParametricSurface