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