00001 #ifndef SYNAPS_SHAPE_SSIQTS_H
00002 #define SYNAPS_SHAPE_SSIQTS_H
00003
00004 # include <shape/parametric_surface.hpp>
00005 # include <shape/fxv.hpp>
00006 # include <shape/ssi/ssi_def.hpp>
00007 # include <iostream>
00008
00009 #define TMPL template<class C, class V>
00010 #define SSIQTS ssiqts<C,V>
00011
00012
00013 namespace mmx {
00014
00015 template<class C, class V= shape::default_env>
00016 struct ssiqts
00017 {
00018 typedef fxv<double,3> vector3;
00019 typedef double aabb3 [3][2];
00020 typedef double ipoint [7];
00021 typedef typename shape::use<shape::ssi_def,C,V>::ParametricSurface ParametricSurface;
00022
00023 int udeg;
00024 int vdeg;
00025 int m;
00026
00027 struct sample
00028 {
00029
00030 double * m_uvals;
00031 double * m_vvals;
00032 vector3 * m_svals;
00033 int m_nrows;
00034 int m_ncols;
00035 inline vector3& operator[]( int i ) { return m_svals[i]; }
00036 inline const vector3& operator[]( int i ) const { return m_svals[i]; }
00037 sample( ParametricSurface * s, int m, int n );
00038 ~sample();
00039 };
00040
00041 sample * smpa;
00042 sample * smpb;
00043
00044 aabb3 * boxa;
00045 aabb3 * boxb;
00046
00047 int * m_bcf;
00048 int * m_ecf;
00049
00050 void cfprint( std::ostream& gpr, std::ostream& gpl );
00051
00052 ssiqts( ParametricSurface * srfa, ParametricSurface * srfb, int n, int degu, int degv );
00053 ~ssiqts();
00054
00055 static aabb3 * alloc( int& l, int m, int& s );
00056 static void fillpatchbox( aabb3& b, const vector3 * a, SSIQTS& ssi );
00057 static void fillboxes( aabb3 * qta, const vector3 * base, SSIQTS& ssi );
00058 static bool intersectp( const aabb3 & a, const aabb3 & b );
00059 static int cfhunt( aabb3 * lbb, aabb3 * rbb, int * bcf, int * ecf );
00060 static void build( aabb3 * base, const SSIQTS & ssi );
00061 static void merge( aabb3 & box, const aabb3& a, const aabb3 & b );
00062 static void update( aabb3& box, const aabb3& a, const aabb3& b );
00063 static void search( aabb3 * lroot, aabb3 * rroot, SSIQTS & ssi );
00064
00065 };
00066
00067 static bool swap;
00068
00069 TMPL
00070 SSIQTS::sample::sample( ParametricSurface * s, int m, int n )
00071 {
00072 m_uvals = new double[3*m*n+m+n];
00073 m_vvals = m_uvals + m;
00074 m_svals = (fxv<double,3>*)(m_vvals + n);
00075 m_nrows = m;
00076 m_ncols = n;
00077 swap = true;
00078 shape::use<shape::ssi_def,C,V>::sample(s,(double*)m_svals,m,n,m_uvals,m_vvals);
00079
00080 };
00081
00082 TMPL
00083 SSIQTS::sample::~sample() { delete[] m_uvals; };
00084
00085 TMPL
00086
00087 typename SSIQTS::aabb3 * SSIQTS::alloc( int& l, int m, int& s )
00088 {
00089 int c = m*m;
00090 s = 0;
00091 l = 0;
00092 while ( c ) { s += c; c /= 4; l ++; };
00093 return new typename SSIQTS::aabb3[s];
00094 };
00095
00096 TMPL
00097 void SSIQTS::fillpatchbox( typename SSIQTS::aabb3& b, const typename SSIQTS::vector3 * a, SSIQTS& ssi )
00098 {
00099
00100 unsigned ncols = ssi.m*ssi.vdeg+1;
00101
00102 const typename SSIQTS::vector3 * la = a;
00103 const typename SSIQTS::vector3 * ela = a + (ssi.udeg+1)*ncols;
00104 const typename SSIQTS::vector3 * ca;
00105 for ( int d = 0; d < 3; d ++ ) b[d][0] = b[d][1] = (*a)[d];
00106 for ( ca = a+1; ca != la + ssi.vdeg+1; ca++ )
00107 for ( int d = 0; d < 3; d ++ )
00108 {
00109 if ( (*ca)[d] < b[d][0] ) b[d][0] = (*ca)[d];
00110 else if ( (*ca)[d] > b[d][1]) b[d][1] = (*ca)[d];
00111 };
00112
00113 for ( la = a+ncols; la != ela; la += ncols )
00114 for ( ca = la; ca != la + ssi.vdeg+1; ca ++ )
00115 for ( int d = 0; d < 3; d ++ )
00116 {
00117 if ( (*ca)[d] < b[d][0] ) b[d][0] = (*ca)[d];
00118 else if ( (*ca)[d] > b[d][1] ) b[d][1] = (*ca)[d];
00119 };
00120 };
00121
00122
00123 TMPL
00124
00125 void SSIQTS::fillboxes( typename SSIQTS::aabb3 * qta, const typename SSIQTS::vector3 * base, SSIQTS& ssi )
00126 {
00127 unsigned nrows = ssi.m*ssi.udeg+1;
00128 unsigned ncols = ssi.m*ssi.vdeg+1;
00129 unsigned srows = ssi.udeg*ncols;
00130 const typename SSIQTS::vector3 * lptr = base;
00131 const typename SSIQTS::vector3 * cptr;
00132 const typename SSIQTS::vector3 * elptr = base + nrows*(ncols-1);
00133 for ( lptr = base; lptr != elptr; lptr += srows )
00134 for ( cptr = lptr; cptr != lptr + ncols-1; cptr += ssi.vdeg, qta++ )
00135 fillpatchbox( *qta, cptr, ssi );
00136 };
00137
00138 TMPL
00139
00140 bool SSIQTS::intersectp( const typename SSIQTS::aabb3 & a, const typename SSIQTS::aabb3 & b )
00141 {
00142 for ( int i = 0; i < 3; i ++ )
00143 if ( a[i][1] < b[i][0] || b[i][1] < a[i][0] ) return false;
00144 return true;
00145 };
00146
00147 TMPL
00148
00149 void SSIQTS::merge( typename SSIQTS::aabb3 & box, const typename SSIQTS::aabb3& a, const typename SSIQTS::aabb3 & b )
00150 {
00151 for ( unsigned i = 0; i < 3; i ++ )
00152 {
00153 box[i][0] = std::min(a[i][0],b[i][0]);
00154 box[i][1] = std::max(a[i][1],b[i][1]);
00155 };
00156 };
00157
00158 TMPL
00159
00160 void SSIQTS::update( typename SSIQTS::aabb3& box, const typename SSIQTS::aabb3& a, const typename SSIQTS::aabb3& b )
00161 {
00162 double tmp;
00163 for ( int i = 0; i < 3; i ++ )
00164 {
00165 tmp = std::min(a[i][0],b[i][0]);
00166 if ( tmp < box[i][0] ) box[i][0] = tmp;
00167 tmp = std::max(a[i][1],b[i][1]);
00168 if ( tmp > box[i][1] ) box[i][1] = tmp;
00169 };
00170 };
00171
00172 TMPL
00173
00174 void SSIQTS::build( typename SSIQTS::aabb3 * base, const SSIQTS & ssi )
00175 {
00176 int N = ssi.m;
00177 typename SSIQTS::aabb3 * cptr,*eptr,*next,*enext;
00178 cptr = base;
00179 eptr = base + N;
00180 next = base + N*N;
00181 enext = next + (N/2*N/2);
00182
00183 while ( next < enext )
00184 {
00185 base = next;
00186 do
00187 {
00188 for ( ;cptr < eptr; cptr += 2, next++ )
00189 {
00190 merge(*next,*cptr,*(cptr+1));
00191 update(*next,*(cptr+N),*(cptr+1+N));
00192 };
00193
00194 cptr += N;
00195 eptr = cptr + N;
00196 }
00197 while ( next < enext );
00198 cptr = base;
00199 N /= 2;
00200 eptr = cptr + N;
00201 enext = next + (N/2)*(N/2);
00202 };
00203 };
00204
00205
00206
00207 TMPL
00208
00209 int SSIQTS::cfhunt(
00210 typename SSIQTS::aabb3 * lbb,
00211 typename SSIQTS::aabb3 * rbb,
00212 int * bcf,
00213 int * ecf )
00214 {
00215 int s = 0;
00216 int * rqp;
00217 int * cf;
00218 int * lrqp;
00219
00220
00221 for ( cf = bcf; cf != ecf; cf += *cf )
00222 {
00223 const int lq = cf[cflq_];
00224 lrqp = cf+cfbg_;
00225
00226 for ( rqp = lrqp; rqp != cf + *cf; rqp ++ )
00227 {
00228
00229 if ( intersectp(*(lbb+lq),*(rbb+*rqp)) ) { *lrqp++ = *rqp; };
00230 };
00231 if ( lrqp != rqp ) *lrqp = -1;
00232 int nc = lrqp-(cf+cfbg_);
00233 s += (nc)?4*(cfhsz+4*nc):0;
00234 };
00235 return s;
00236 }
00237
00238
00239 static int * cfsimplify( int * bcf, int * ecf )
00240 {
00241 int * necf = bcf;
00242 for ( int * cf = bcf; cf != ecf; )
00243 {
00244 int * rp = cf+cfbg_;
00245
00246 int * dst = necf+cfbg_;
00247 while( *rp != -1 && rp < cf + *cf ) *dst++ = *rp++;
00248 necf[cflq_] = cf[cflq_];
00249
00250 cf += *cf;
00251 *necf = dst-necf;
00252 necf += *necf;
00253 };
00254 return necf;
00255 };
00256
00257 static int * expandcf( int * cf, int * ncf, int m )
00258 {
00259 int * ecf, * rpq, *pncf;
00260 ecf = cf + cf[cfsz_];
00261 rpq = cf + cfbg_;
00262 while ( *rpq != -1 && rpq != ecf ) rpq++;
00263 if ( rpq == cf + cfbg_ ) return ncf;
00264 *ncf = 4*(rpq-(cf+cfbg_))+cfhsz;
00265 rpq = cf + cfbg_;
00266 for ( pncf = ncf + cfbg_; pncf != ncf + *ncf; pncf += 4 , rpq ++ )
00267 {
00268 int i = *rpq / m;
00269 int j = *rpq % m;
00270 int a = i*(4*m)+2*j;
00271 pncf[0] = a;
00272 pncf[1] = a+1;
00273 pncf[2] = a+2*m;
00274 pncf[3] = a+2*m+1;
00275 };
00276
00277 for ( pncf = ncf + *ncf; pncf != ncf + 4**ncf; pncf += *ncf )
00278 std::copy(ncf,ncf+*ncf,pncf);
00279
00280 int i = cf[cflq_]/ m;
00281 int j = cf[cflq_]% m;
00282 int a = i*(4*m)+2*j;
00283 (ncf+0**ncf)[cflq_] = a;
00284 (ncf+1**ncf)[cflq_] = a+1;
00285 (ncf+2**ncf)[cflq_] = a+2*m;
00286 (ncf+3**ncf)[cflq_] = a+2*m+1;
00287 return ncf + 4**ncf;
00288 };
00289
00290 static void cfforward( int * ncf, int * bcf, int * ecf, int m )
00291 {
00292 for ( int * cf = bcf; cf != ecf; ncf = expandcf(cf,ncf,m), cf += *cf );
00293 };
00294
00295
00296 TMPL
00297
00298 void SSIQTS::search( typename SSIQTS::aabb3 * lroot, typename SSIQTS::aabb3 * rroot, SSIQTS & ssi )
00299 {
00300 int S, M;
00301 int * bcf, * ecf, * ncf;
00302
00303
00304
00305 bcf = new int[cfhsz+1];
00306 bcf[cfsz_] = cfhsz+1;
00307 bcf[cflq_] = 0;
00308 bcf[cfbg_] = 0;
00309 ecf = bcf + bcf[cfsz_];
00310 int s = 0;
00311
00312 typename SSIQTS::aabb3 *lbb = lroot;
00313 typename SSIQTS::aabb3 *rbb = rroot;
00314
00315
00316 for ( S = 1, M = 1, lbb = lroot, rbb = rroot; M != ssi.m; M *= 2, S *= 4, lbb -= S, rbb -= S )
00317 {
00318
00319 s = cfhunt( lbb, rbb, bcf, ecf );
00320
00321 if ( !s ) { delete[] bcf; return; };
00322
00323 ncf = new int[ s ];
00324
00325
00326 cfforward(ncf,bcf,ecf,M);
00327
00328 delete[] bcf;
00329 bcf = ncf;
00330 ecf = ncf + s;
00331 };
00332
00333
00334 s = cfhunt(lbb,rbb,bcf,ecf);
00335 ecf = cfsimplify(bcf,ecf);
00336 ssi.m_bcf = bcf;
00337 ssi.m_ecf = ecf;
00338 };
00339
00340
00341 static void cfprint( std::ostream& gp, std::ostream& gpl , int * bcf, int * ecf, int m )
00342 {
00343 for( int * cf = bcf; cf != ecf; cf += *cf )
00344 {
00345 if ( cf[cfbg_] != -1 )
00346 {
00347 gp << (cf[cflq_]/m) << " " << (cf[cflq_]%m) << std::endl;
00348 int * rpq = cf+cfbg_;
00349 while ( *rpq != -1 && rpq != cf+*cf )
00350 {
00351 gpl << (*rpq/m) << " " << (*rpq%m) << std::endl;
00352 rpq++;
00353 };
00354 }
00355 };
00356 };
00357
00358 TMPL
00359 void SSIQTS::cfprint( std::ostream& gp, std::ostream& gpl )
00360 {
00361 mmx::cfprint(gp, gpl, m_bcf, m_ecf, m );
00362 };
00363
00364 TMPL
00365 SSIQTS::ssiqts( ParametricSurface * srfa, ParametricSurface * srfb, int n, int degu, int degv )
00366 {
00367 udeg = degu;
00368 vdeg = degv;
00369 int p = 0;
00370 m = 1;
00371 while( n ) { p++; n/=2; m *= 2; };
00372 smpa = new sample(srfa,m*degu+1,m*degv+1);
00373 smpb = new sample(srfb,m*degu+1,m*degv+1);
00374 int s;
00375 int deep;
00376 boxa = alloc(deep,m,s);
00377
00378 boxb = alloc(deep,m,s);
00379
00380
00381
00382 fillboxes( boxa, smpa->m_svals, *this);
00383 fillboxes( boxb, smpb->m_svals, *this);
00384 build(boxa,*this);
00385 build(boxb,*this);
00386 search(boxa+s-1,boxb+s-1,*this);
00387
00388 };
00389
00390 TMPL
00391 SSIQTS::~SSIQTS()
00392 {
00393 if ( smpa ) delete smpa;
00394 if ( smpb ) delete smpb;
00395 if ( boxa ) delete[] boxa;
00396 if ( boxb ) delete[] boxb;
00397 };
00398
00399 }
00400
00401 # undef TMPL
00402 # undef SSIQTS
00403 # undef ParametricSurface
00404 # endif