00001 #ifndef shape_ssi_dsearch_hpp
00002 #define shape_ssi_dsearch_hpp
00003 #include <shape/ssi/ssi_def.hpp>
00004 #include <shape/ssi/ssi_qsegment.hpp>
00005 #include <list>
00006 #include <queue>
00007 #include <shape/ssi/ssi_ordered_pair.hpp>
00008 #include <shape/ssi/ssi_tri_tri.hpp>
00009 #include <shape/ssi/ssi_math.hpp>
00010
00011 #define TMPL template<class C,class V>
00012
00013 #define SHIFT 3
00014 #define __up__ 0
00015 #define __down__ 1
00016
00017 #define __up__triangle__(q) q[0],q[3],q[2]
00018
00019 #define __down__triangle__(q) q[0],q[1],q[2]
00020
00021 #define __up__param_triangle__(q) q[3],q[2],q[0]
00022
00023 #define __down__param_triangle__(q) q[1],q[0],q[2]
00024 #define __convert_order__(i,point) { point[(i+1)%2] = 1.0-point[(i+1)%2]; }
00025
00026 #define __triangle_triangle_case__(trig0,trig1) \
00027 { \
00028 if ( geom::intersectp_triangles3_isegment \
00029 ( coplanar, seg[0], seg[1], \
00030 trig0##triangle__(a), \
00031 trig1##triangle__(b), point3::value_type(1e-12) )) \
00032 { \
00033 if ( !coplanar ) \
00034 { \
00035 space2prm( \
00036 seg0[0], seg0[1], \
00037 \
00038 seg[0], seg[1], \
00039 \
00040 trig0##param_triangle__(a) \
00041 ); \
00042 space2prm( seg1[0], seg1[1], \
00043 seg[0], seg[1], \
00044 trig1##param_triangle__(b) ); \
00045 \
00046 __convert_order__(trig0,seg0[0]); \
00047 __convert_order__(trig0,seg0[1]); \
00048 __convert_order__(trig1,seg1[0]); \
00049 __convert_order__(trig1,seg1[1]); \
00050 } \
00051 else \
00052 {\
00053 seg0[0][0] = 1.0/3.0; seg0[0][1] = 1.0/3.0; \
00054 seg0[1][0] = 1.0/3.0; seg0[1][0] = 1.0/3.0; \
00055 seg1[0][0] = 1.0/3.0; seg1[0][1] = 1.0/3.0; \
00056 seg1[1][0] = 1.0/3.0; seg1[1][1] = 1.0/3.0; \
00057 __convert_order__(trig0,seg0[0]); \
00058 __convert_order__(trig0,seg0[1]); \
00059 __convert_order__(trig1,seg1[0]); \
00060 __convert_order__(trig1,seg1[1]); \
00061 }; \
00062 { \
00063 f->convert(seg0,this,2); \
00064 s->convert(seg1,this,2); \
00065 push( seg0[0], seg0[1], seg1[0], seg1[1], seg[0],seg[1] ); \
00066 } \
00067 }; \
00068 } \
00069
00070
00071
00072
00073 namespace mmx {
00074 namespace ssi {
00075
00076 void space2prm( vector2 & pa,
00077 vector2 & pb,
00078 const vector3& sa,
00079 const vector3& sb,
00080 const vector3& base,
00081 const vector3& pu,
00082 const vector3& pv );
00083
00084 typedef std::list< point2 > list2_t;
00085 typedef std::list< point3 > list3_t;
00086 typedef list2_t::iterator p2ref_t;
00087
00088 struct dcurve
00089 {
00090 unsigned size;
00091 dcurve * owner;
00092 list2_t left,right;
00093 list3_t inter;
00094 dcurve( const point2& l, const point2& r, const point3& i ) ;
00095 dcurve( const point2& l0, const point2& l1, const point2& r0, const point2& r1, const point3& i0, const point3& i1 );
00096 };
00097
00098 template<class DPoint>
00099 struct dim_cmp
00100 {
00101 unsigned dim;
00102 dim_cmp(unsigned d = 0): dim(d) {};
00103 dim_cmp next() const { return dim_cmp((dim+1)%4); };
00104 bool operator()( DPoint*const& a, DPoint *const& b ) const { return (*a)[dim] < (*b)[dim]; };
00105 bool operator()( const DPoint& a, const DPoint& b ) const { return a[dim] < b[dim]; };
00106 };
00107
00108 template<class DP>
00109 inline double distance( DP * pa, DP * pb )
00110 {
00111 double acc = 0.0;
00112 for ( unsigned i = 0; i < 4; i++ )
00113 acc += ((*pa)[i]-(*pb)[i])*((*pa)[i]-(*pb)[i]);
00114 return acc;
00115 };
00116
00117 struct sdpoint_t
00118 {
00119 typedef double value_type;
00120 dcurve * curve;
00121 p2ref_t idl;
00122 p2ref_t idr;
00123
00124 inline const double& operator[]( unsigned i ) const
00125 {
00126 if ( i < 2 ) return (*idl)[i];
00127 return (*idr)[i-2];
00128 };
00129
00130 inline double& operator[]( unsigned i )
00131 {
00132 if ( i < 2 ) return (*idl)[i];
00133 return (*idr)[i-2];
00134 };
00135 };
00136
00137 struct pdpoint_t
00138 {
00139 typedef double value_type;
00140 dcurve * curve;
00141 p2ref_t ref;
00142 pdpoint_t * a;
00143
00144 inline value_type& operator[]( unsigned i )
00145 {
00146 if ( i < 2 ) return (*ref)[i];
00147 return (*(a->ref))[i-2];
00148 };
00149 inline const value_type& operator[]( unsigned i ) const
00150 {
00151 if ( i < 2 ) return (*ref)[i];
00152 return (*(a->ref))[i-2];
00153 };
00154 };
00155
00156 void append( dcurve * a, dcurve * b ) ;
00157 void prepend( dcurve * a, dcurve * b ) ;
00158 void reverse( dcurve * c ) ;
00159
00160
00161 struct sdknode
00162 {
00163 sdpoint_t * data;
00164 sdknode * l, * r;
00165 sdknode( sdpoint_t * d, sdknode * _l, sdknode * _r ) : data(d), l(_l), r(_r){};
00166 ~sdknode() { if ( l ) delete l; if ( r ) delete r; };
00167 };
00168
00169 struct pdknode
00170 {
00171 pdpoint_t * data;
00172 pdknode * l, * r;
00173 pdknode( pdpoint_t * d, pdknode * _l, pdknode * _r ) : data(d), l(_l), r(_r){};
00174 ~pdknode() { if ( l ) delete l; if ( r ) delete r; };
00175 };
00176
00177
00178
00179 inline bool empty( dcurve * c ) { return c->owner != c; };
00180 inline pdpoint_t * sibble( pdpoint_t * p ) { return p->a; };
00181
00182 void extremums( sdpoint_t* dst, dcurve* src );
00183 void extremums( pdpoint_t * dst, dcurve * c );
00184 dcurve * curve( pdpoint_t * p );
00185 dcurve * curve( sdpoint_t * p );
00186
00187 inline bool isfirst ( sdpoint_t* p ) { return curve(p)->left.begin() == p->idl; };
00188 inline bool islast ( sdpoint_t* p ) { return (--(curve(p)->left.end())) == p->idl; };
00189
00190 inline bool isfirst ( pdpoint_t* p ) { return curve(p)->left.begin() == p->ref || curve(p)->right.begin() == p->ref; };
00191 inline bool islast ( pdpoint_t* p ) { return (--(curve(p)->left.end())) == p->ref ||(--(curve(p)->right.end())) == p->ref;};
00192
00193 inline bool isextrem( pdpoint_t* p ) { return isfirst(p) || islast(p); };
00194 inline bool isextrem( sdpoint_t* p ) { return isfirst(p) || islast(p); };
00195
00196 void link( sdpoint_t* a, sdpoint_t* b);
00197 void link( pdpoint_t* a, pdpoint_t* b);
00198
00199 inline void swap( dcurve * c ) { c->left.swap( c->right ); };
00200
00201 inline bool isright( pdpoint_t* p )
00202 { return p->ref == curve(p)->right.begin() || p->ref == --(curve(p)->right.end());};
00203
00204
00205 template<class DPoint>
00206 inline void _link( DPoint* a, DPoint* b )
00207 {
00208 if ( islast(a) )
00209 {
00210 if( islast(b) )
00211 reverse(curve(b));
00212
00213 append(curve(a),curve(b));
00214 }
00215 else
00216 {
00217 if ( isfirst(b) )
00218 reverse(curve(b));
00219
00220 prepend(curve(a),curve(b));
00221 };
00222 };
00223
00224
00225 sdknode * make( sdpoint_t * first, sdpoint_t * last, const dim_cmp<sdpoint_t>& f ) ;
00226 pdknode * make( pdpoint_t ** first, pdpoint_t ** last, const dim_cmp<pdpoint_t>& f ) ;
00227
00228
00229
00230 template<class DPoint>
00231 struct assoc_t
00232 {
00233 std::pair<DPoint*,DPoint*> pp;
00234 double d;
00235
00236 struct pair_cmp
00237 { bool operator()( const assoc_t& a1, const assoc_t& a2 ) const { return a1.pp < a2.pp; }; };
00238
00239 struct dist_cmp
00240 { bool operator()( const assoc_t& a1, const assoc_t& a2 ) const { return a1.d > a2.d; }; };
00241 assoc_t(){};
00242 assoc_t( DPoint * a, DPoint * b, double _d ):
00243 pp(a,b), d(_d){};
00244 };
00245
00246 typedef std::priority_queue< assoc_t<pdpoint_t>,
00247 std::vector< assoc_t<pdpoint_t> >,
00248 assoc_t< pdpoint_t>::dist_cmp > pheap_t;
00249 typedef std::priority_queue< assoc_t<sdpoint_t>,
00250 std::vector< assoc_t<sdpoint_t> >,
00251 assoc_t< sdpoint_t>::dist_cmp > sheap_t;
00252
00253 typedef std::set< assoc_t< pdpoint_t > , assoc_t<pdpoint_t>::pair_cmp > pset_t;
00254
00255 typedef assoc_t<sdpoint_t> sdassc_t;
00256 typedef assoc_t<pdpoint_t> pdassc_t;
00257
00258 void solve_sheap( sheap_t& h );
00259 void solve_pheap( pheap_t& h );
00260
00261 typedef std::pair<pdpoint_t*,pdpoint_t*> ppair_t;
00262 typedef std::list< ppair_t > links_t;
00263 typedef std::map< dcurve*, links_t > curves_links_t;
00264 typedef ordered_pair<dcurve*> cpair_t;
00265
00266 template <class A, class B>
00267 inline void container_add( A& h, const B& a ) { h.push(a); };
00268 inline void container_add( pset_t& s, const pdassc_t& a ) { s.insert(a); };
00269 inline cpair_t curves( const pdassc_t& ass ) { return cpair_t(curve(ass.pp.first),curve(ass.pp.second)); };
00270 inline pdassc_t sibbles( const pdassc_t& ass )
00271 {
00272 pdpoint_t * a = sibble(ass.pp.first);
00273 pdpoint_t * b = sibble(ass.pp.second);
00274 if ( a < b )
00275 return pdassc_t(a,b,0);
00276 else
00277 return pdassc_t(b,a,0);
00278 };
00279
00280 void satisfy_links( curves_links_t::iterator it );
00281 void solve_pset( curves_links_t& links, pset_t& s );
00282 std::list<dcurve*> * reduce2( std::vector< dcurve * > * conflicts );
00283 typedef pset_t::iterator pset_iterator;
00284
00285 void build_sheap( sheap_t& h, sdpoint_t * first, sdpoint_t * last, double prec );
00286
00287 TMPL
00288 struct dsearch : qsegment<C,V>
00289 {
00290 typedef typename qsegment<C,V>::ParametricSurface ParametricSurface;
00291 typedef qnode<C,V>* qtree;
00292 bool m_cnf;
00293
00294
00295 std::vector< dcurve * > * curr_config;
00296 std::list < dcurve * > ** _branches;
00297
00298 void cnfpush( qtree f, qtree s );
00299 void push( qtree f, qtree s );
00300 inline std::list < dcurve * > *& branches( unsigned i, unsigned j )
00301 { return _branches[i*this->regions.size()+j]; };
00302
00303 void push ( const point2& l0, const point2& l1,
00304 const point2& r0, const point2& r1,
00305 const point3& i0, const point3& i1 )
00306 {
00307 curr_config->push_back( new dcurve( l0,l1,r0, r1, i0, i1 ) );
00308 };
00309
00310
00311 #define push_s push
00312 #define push_f push
00313
00314 void search_f( qtree f, qtree const s );
00315
00316 void search_s( qtree const f, qtree s );
00317
00318 void search(qtree f, qtree s );
00319
00320
00321 void search( rid_t i, rid_t j );
00322
00323
00324 std::list<dcurve*> * reduce( std::vector< dcurve * > * conflicts );
00325 inline void find_branches( rid_t id0, rid_t id1 )
00326 {
00327 branches( id0, id1 ) = reduce( curr_config );
00328 delete curr_config;
00329 };
00330
00331
00332 struct
00333 {
00334 double search_time;
00335 double recons_time;
00336 } stats;
00337
00338 std::list< dcurve * > *result;
00339
00340 point2 ** lefts;
00341 point2 ** rights;
00342
00343 unsigned * sizes;
00344 unsigned nbcurves;
00345 unsigned nbpoints;
00346 unsigned conflict_count;
00347
00348 void GnuPlotOutput( char * name );
00349
00350 std::vector< point3 > cnfdata3;
00351 std::vector< point2 > cnfdata2;
00352
00353
00354 double _st;
00355 dsearch( const ParametricSurface * s , unsigned w, unsigned h, bool cnf = false );
00356 ~dsearch();
00357 };
00358
00359 TMPL
00360 dsearch<C,V>::dsearch( const ParametricSurface * s , unsigned w, unsigned h, bool cnf ) : qsegment<C,V>(s, w, h )
00361 {
00362 m_cnf = cnf;
00363
00364 unsigned i,j;
00365 conflict_count = 0;
00366 nbpoints = 0;
00367 _branches = new std::list< dcurve * > *[this->regions.size()*this->regions.size()];
00368 memset(_branches,0,sizeof( std::list< dcurve * > * )*
00369 this->regions.size()*this->regions.size() );
00370
00371 for ( i = 0; i < this->regions.size() ; i++ )
00372 for ( j = i+1; j < this->regions.size() ; j++ )
00373 {
00374 #define VOISINS_AUSSI
00375 #ifndef VOISINS_AUSSI
00376 if ( !this->grp->neighbors(i,j) )
00377 #endif
00378 {
00379
00380 search(i,j);
00381 find_branches(i,j);
00382 };
00383 };
00384
00385
00386 std::vector< dcurve * > * tmp = new std::vector<dcurve*>();
00387
00388 for ( i = 0; i < this->regions.size(); i++ )
00389 for ( j = i+1; j < this->regions.size(); j++ )
00390 {
00391 if ( branches(i,j) )
00392 {
00393 for ( std::list<dcurve*>::iterator it = branches(i,j)->begin(); it != branches(i,j)->end(); it ++ )
00394 {
00395 tmp->push_back( *it );
00396 };
00397 delete branches(i,j);
00398 }
00399 };
00400
00401 result = reduce2( tmp );
00402 delete tmp;
00403 nbcurves = 0;
00404 lefts = rights = 0;
00405 sizes = 0;
00406 if ( result )
00407 {
00408 nbpoints = 0;
00409 std::list<dcurve *>::iterator it;
00410 nbcurves = result->size();
00411
00412 sizes = new unsigned[nbcurves];
00413
00414 for ( i = 0, it = result->begin(); it != result->end(); it++ , i++ )
00415 {
00416 sizes[i] = (*it)->left.size();
00417 nbpoints+= sizes[i];
00418 };
00419
00420 lefts = new point2*[nbcurves];
00421 rights = new point2*[nbcurves];
00422 unsigned c_n = 0;
00423 unsigned k;
00424 for ( it = result->begin(); it != result->end(); it ++, c_n++ )
00425 {
00426 lefts[c_n] = new point2[sizes[c_n]];
00427 rights[c_n] = new point2[sizes[c_n]];
00428 list2_t::iterator itcr, itcl;
00429 for ( k = 0, itcl = (*it)->left.begin(), itcr = (*it)->right.begin();
00430 itcl != (*it)->left.end();
00431 itcl++ , itcr++, k++ )
00432 {
00433
00434 lefts[c_n][k] = *itcl;
00435 rights[c_n][k] = *itcr;
00436 };
00437 };
00438
00439 for ( std::list<dcurve*>::iterator it = result->begin(); it!= result->end(); it++ )
00440 {
00441 delete *it;
00442 };
00443 delete result;
00444 };
00445 delete[] _branches;
00446
00447
00448
00449
00450
00451 };
00452
00453 TMPL
00454 dsearch<C,V>::~dsearch()
00455 {
00456 if ( sizes ) delete[] sizes;
00457 if ( lefts )
00458 {
00459 for ( unsigned i = 0; i < nbcurves; i++ )
00460 delete[] lefts[i];
00461 delete[] lefts;
00462 };
00463 if ( rights )
00464 {
00465 for ( unsigned i = 0; i < nbcurves; i++ )
00466 delete[] rights[i];
00467 delete[] rights;
00468 };
00469
00470 };
00471
00472 TMPL
00473 void dsearch<C,V>::GnuPlotOutput( char * name )
00474 {
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 }
00496
00497 TMPL
00498 void dsearch<C,V>::cnfpush( qtree f, qtree s )
00499 {
00500 point3 a[4],b[4];
00501 f->fill(a,this);
00502 s->fill(b,this);
00503 cnfdata3.push_back( ((double)(1.0/4.0))*(a[0]+a[1]+a[2]+a[3]) );
00504 };
00505
00506
00507
00508 TMPL
00509 void dsearch<C,V>::push( qtree f, qtree s )
00510 {
00511 if ( std::abs(f->umin-s->umin)+std::abs(f->vmin-s->vmin) < SHIFT ) return;
00512 conflict_count ++;
00513 point3 a[4],b[4];
00514 qsegment<C,V>::scale_conflict(a,b,f,s);
00515 {
00516 point3 seg[2];
00517 point2 seg0[2], seg1[2];
00518 bool coplanar;
00519 __triangle_triangle_case__(__up__,__up__);
00520 __triangle_triangle_case__(__up__,__down__);
00521 __triangle_triangle_case__(__down__,__down__);
00522 __triangle_triangle_case__(__down__,__up__);
00523 }
00524 };
00525
00526 TMPL
00527 void dsearch<C,V>::search_f( qtree f, qtree const s )
00528 {
00529
00530 if (intersectp(f->box,s->box))
00531 {
00532 f->split(this);
00533 if ( leaf(f) ){ push_f(f,s); return; };
00534 search_f(f->l,s);
00535 search_f(f->r,s);
00536 };
00537 };
00538
00539
00540 TMPL
00541 void dsearch<C,V>::search_s( qtree const f, qtree s )
00542 {
00543
00544 if ( intersectp( f->box, s->box ) )
00545 {
00546 s->split(this);
00547 if ( leaf(s) ) { push_s(f,s); return; };
00548 search_s(f,s->l);
00549 search_s(f,s->r);
00550 };
00551 };
00552
00553
00554 TMPL
00555 void dsearch<C,V>::search( qtree f, qtree s )
00556 {
00557
00558
00559
00560 if ( intersectp(f->box,s->box) )
00561 {
00562
00563 f->split(this);
00564 s->split(this);
00565
00566 if ( !(f->leaf()) && !(s->leaf()) )
00567 {
00568
00569 search(f->l,s->l), search(f->l,s->r);
00570 search(f->r,s->l), search(f->r,s->r);
00571 return;
00572 };
00573
00574
00575 if ( !leaf(f) )
00576 {
00577 search_f(f->l,s);
00578 search_f(f->r,s);
00579 return;
00580 };
00581
00582 if ( !leaf(s) )
00583 {
00584 search_s(f,s->l);
00585 search_s(f,s->r);
00586 return;
00587 };
00588
00589
00590 push(f,s);
00591 };
00592 };
00593
00594
00595 TMPL
00596 void dsearch<C,V>::search( rid_t i, rid_t j )
00597 {
00598 curr_config = new std::vector< dcurve* >();
00599 search( this->trees[i], this->trees[j] );
00600 };
00601
00602
00603 TMPL
00604 std::list<dcurve*> * dsearch<C,V>::reduce( std::vector< dcurve * > * conflicts )
00605 {
00606 unsigned i;
00607 if ( conflicts->size() == 0 ) return 0;
00608
00609 unsigned endsize = 2*conflicts->size();
00610 sdpoint_t * ends = new sdpoint_t[endsize];
00611
00612 for ( i = 0; i < endsize; i+= 2 )
00613 extremums( ends + i, (*conflicts)[i/2] );
00614
00615 sheap_t h;
00616 build_sheap(h,ends, ends + endsize, 0.04 );
00617 solve_sheap(h);
00618 delete[] ends;
00619 std::list< dcurve* > * result = new std::list< dcurve * >();
00620 for ( i = 0; i < conflicts->size() ; i++ )
00621 {
00622 if ( empty((*conflicts)[i]) ) delete (*conflicts)[i];
00623 else result->push_front( (*conflicts)[i] );
00624 };
00625 return result;
00626 };
00627
00628
00629 }
00630
00631 }
00632 # undef ParametricSurface
00633 # undef TMPL
00634 # endif