shape_doc 0.1
/Users/mourrain/Devel/mmx/shape/src/ssi_qsegment.cpp
Go to the documentation of this file.
00001 #include <shape/ssi_qsegment.hpp>
00002 //#include <shape/ssi/chrono.h>
00003 
00004 #define ParametricSurface shape::surface_parametric<double>
00005 
00006 namespace mmx {
00007 namespace  shape_ssi {
00008 
00009   std::ostream & operator<<( std::ostream& o, const lrnode& l )
00010   {
00011     o << l.lmin << " " << l.lmax << " " << l.rmin << " " << l.rmax << std::endl;
00012     return o;
00013   };
00014 
00015   lrnode * lrnode::alloc( unsigned size )
00016     {
00017       unsigned i, acc;
00018       i = size, acc =0;
00019       do { acc += i, i = i / 2 + i % 2; } while ( i > 1 );
00020       return new lrnode[acc+1];
00021     };
00022   
00023   lrnode * lrnode::make( lrnode * data, unsigned size )
00024   {
00025 #define Mmin(a,b) std::min(a,b)
00026 #define Mmax(a,b) std::max(a,b)
00027     
00028     unsigned bsize = size;
00029     bool     right = true;
00030     lrnode * built = data;
00031     lrnode * curr  = data + size;
00032     unsigned i,j;
00033     do
00034       {
00035         if ( right )
00036           { 
00037             for ( i = 0, j = 0; i < bsize-(bsize%2); i += 2, j++ ) 
00038               {
00039                 curr[j].umin = built[i].umin;
00040                 curr[j].umax = built[i+1].umax;
00041                 curr[j].lmin = Mmin(built[i].lmin,
00042                                     built[i+1].lmin);
00043                 curr[j].lmax = Mmax(built[i].lmax,
00044                                     built[i+1].lmax);
00045                 curr[j].rmin = Mmin(built[i].rmin,
00046                                     built[i+1].rmin);
00047                 curr[j].rmax = Mmax(built[i].rmax,
00048                                     built[i+1].rmax);
00049                 curr[j].ls   = built + i;
00050                 curr[j].rs   = built + i + 1;
00051               };
00052             
00053             if ( bsize%2 ) { curr[j++] = built[bsize-1];  };
00054             built = curr;
00055             curr += j;
00056           }
00057         else
00058           {
00059             unsigned next_size = bsize/2 + bsize % 2;
00060             built += bsize-1;
00061             curr  += next_size-1;
00062             for ( i = 0, j = 0; i < bsize-(bsize%2); i += 2, j++ ) 
00063               {
00064                 curr[-j].umin = built[-i-1].umin;
00065                 curr[-j].umax = built[-i].umax;
00066                 curr[-j].lmin = Mmin(built[-i].lmin,
00067                                      built[-i-1].lmin);
00068                 curr[-j].lmax = Mmax(built[-i].lmax,
00069                                            built[-i-1].lmax);
00070                 curr[-j].rmin = Mmin(built[-i].rmin,
00071                                                built[-i-1].rmin);
00072                 curr[-j].rmax = Mmax(built[-i].rmax,
00073                                      built[-i-1].rmax);
00074                 curr[-j].ls   = built - i - 1;
00075                 curr[-j].rs   = built - i;
00076               };
00077             
00078             if ( bsize%2 ) { curr[-j] = built[-bsize+1];  };
00079             built = curr - next_size+1;
00080             curr++;
00081           };
00082         right = !right;
00083         bsize = bsize/2 + bsize%2;
00084       }
00085     while( bsize > 1 );
00086     return --curr;
00087   };
00088 
00089   
00090   void shiftm( vector3 * v, unsigned sz, const aabb3 & box )
00091   {
00092     //    double m,M;
00093     for ( vector3 * src = v; src != v+sz; src ++ )
00094       for ( int i = 0; i < 3; (*src)[i] -= box[i].m, i ++ );
00095   };
00096 
00097     
00098   void scale( vector3 * p, double s ){ 
00099     for ( int i = 0; i < 4; i ++ )
00100       for ( int d = 0; d < 3; d ++ )
00101       p[i][d] *= s;
00102   };
00103 
00104   void qsegment::scale_conflict( vector3 * a, vector3 * b, qtree qa, qtree qb )
00105   {
00106 
00107     aabb3 h;
00108     hull(h,qa->box,qb->box);
00109     double s = 1.0/lmax(h);
00110     qa->fill(a,this);
00111     qb->fill(b,this);
00112     shiftm(a,4,h);
00113     shiftm(b,4,h);
00114     scale(a,s);
00115     scale(b,s);
00116   };
00117   
00118   void print( std::ostream& o, qtree q )
00119   {
00120     o << *q << std::endl;
00121     if ( q->r) print( o, q->r );
00122     if ( q->l ) print( o, q->l );
00123   };
00124   qnode * qsegment::make( rid_t id, coord_t vmin, coord_t vmax, lrnode * lr )
00125   { 
00126     qnode * curr, * l, * r;
00127     curr = l = r = 0;
00128     
00129     if (  vmax  <=  lr->lmin || vmin >=  lr->rmax ) return 0; 
00130     if (  vmin  <   lr->lmax || vmax >  lr->rmin  )
00131       {
00132         if ( lr->umax-lr->umin > vmax-vmin)
00133           {
00134             l = make( id, vmin, vmax, lr->ls );
00135             r = make( id, vmin, vmax, lr->rs );
00136           }
00137         else 
00138           {
00139             unsigned m = (vmin + vmax)/2;
00140             l = make( id, vmin, m, lr );
00141             r = make( id, m, vmax, lr );
00142           };
00143         
00144         if ( l && r ) 
00145           { 
00146             curr = new qnode();
00147             curr->umin = lr->umin;
00148             curr->umax = lr->umax;
00149             curr->vmin = vmin;
00150             curr->vmax = vmax;
00151             hull(curr->box,l->box,r->box);
00152             curr->l = l;
00153             curr->r = r;
00154             l->father = curr;
00155             r->father = curr;
00156             return curr;
00157           };
00158         
00159         if ( l ) { return l; };
00160         if ( r ) { return r; };
00161       }
00162     else 
00163       {
00164         curr = new qnode();
00165         curr->l    = 0;
00166         curr->r    = 0;
00167         curr->umin = lr->umin;
00168         curr->umax = lr->umax;
00169         curr->vmin = vmin;
00170         curr->vmax = vmax;
00171         curr->mbox(this);
00172 
00173         return curr;
00174       };
00175     return curr;
00176   };
00177   
00178   qsegment::qsegment( const ParametricSurface * s, unsigned w, unsigned h  ) : lsegment( s, w, h )
00179   {
00180     //    _qt = time();
00181     lrnode * lr_chunk   = lrnode::alloc(h);
00182     for ( unsigned i = 0; i < this->regions.size(); i++ )
00183       {
00184         lr_chunk -= this->regions[i].umin();
00185         for ( coord_t u = this->regions[i].umin(); u < this->regions[i].umax(); u++  )
00186           {
00187             lr_chunk[u].umin =  u;
00188             lr_chunk[u].umax =  u+1;
00189             lr_chunk[u].lmax = (lr_chunk[u].lmin = this->regions[i].min(u));
00190             lr_chunk[u].rmax = (lr_chunk[u].rmin = this->regions[i].max(u));
00191             lr_chunk[u].ls   =  lr_chunk[u].rs   = 0; 
00192           };
00193 
00194         lr_chunk += this->regions[i].umin();
00195         
00196         lrnode * lrt = lrnode::make(lr_chunk,
00197                                     this->regions[i].umax()-this->regions[i].umin());
00198         qtree tmp = make( i, lrt->lmin, lrt->rmax, lrt );
00199         tmp->father = 0;
00200         trees.push_back( tmp  );
00201         
00202       };
00203     delete[] lr_chunk;
00204     //    std::cout << "q = " << (time()-_qt) << std::endl;
00205   };
00206   
00207   qsegment::~qsegment() 
00208   { 
00209     for ( unsigned i = 0; i < size(); delete trees[i], i++ ); 
00210   };
00211   
00212 }
00213 
00214 } //namespace mmx    
00215 
00216 # undef ParametricSurface