|
ORTS
|
00001 00002 # ifdef WIN32 00003 # include <sr_tree.h> 00004 # include <se_mesh_import.h> 00005 # else 00006 # include <SR/sr_tree.h> 00007 # include <SE/se_mesh_import.h> 00008 # endif 00009 00010 00011 //# define SR_USE_TRACE1 // basic messages 00012 //# define SR_USE_TRACE2 // more messages 00013 //# define SR_USE_TRACE4 // active contour 00014 //# define SR_USE_TRACE5 // tree 00015 # ifdef WIN32 00016 # include <sr_trace.h> 00017 # else 00018 # include <SR/sr_trace.h> 00019 # endif 00020 00021 00022 //======================= static data ============================================= 00023 00024 // Question: Could I substitute EdgeTree by an EdgeHashTable ...? 00025 00026 class Edge : public SrTreeNode 00027 { public : 00028 int a, b; // Edge vertices, not oriented 00029 int v; // The other vertex of the adjacent face 00030 int f; // The index of the edge's face 00031 Edge *sym; // The other edge, belonging to the other face sharing this edge 00032 Edge *e2, *e3; // The other two edges of this face 00033 public : 00034 Edge ( int i1=0, int i2=0, int i3=0 ) : f(0), sym(0), e2(0), e3(0) { a=i1; b=i2; v=i3; } 00035 void set_fac_elems ( Edge *b, Edge *c, int fac ) { e2=b; e3=c; f=fac; } 00036 void swap() { int tmp=a; a=b; b=tmp; } 00037 00038 friend SrOutput& operator<< ( SrOutput& o, const Edge& e ) 00039 { return o<<'['<<e.a<<' '<<e.b<<' '<<e.v<<"]"; } 00040 00041 friend SrInput& operator>> ( SrInput& i, Edge& /*e*/ ) { return i; } 00042 00043 friend int sr_compare ( const Edge* e1, const Edge* e2 ); 00044 }; 00045 00046 int sr_compare ( const Edge *e1, const Edge *e2 ) 00047 { 00048 if ( e1->a<e2->a ) return -1; 00049 if ( e1->a>e2->a ) return 1; 00050 if ( e1->b<e2->b ) return -1; 00051 if ( e1->b>e2->b ) return 1; 00052 return 0; 00053 } 00054 00055 /* 00056 # ifdef SE_USR_TRACE4 00057 struct PFace { SeBase *e; SeMeshBase *m; } PFaceInst; 00058 FgOutput &operator << ( FgOutput &o, PFace &f ) 00059 { 00060 o << '['; 00061 SeBase *e=f.e; 00062 while ( true ) 00063 { o<<(int)f.m->index(e->vtx()); 00064 e = e->nxt(); 00065 if ( e!=f.e ) o<<' '; else break; 00066 } 00067 return o<<']'; 00068 } 00069 # define SR_TRACE_CONTOUR(x,s) { PFaceInst.e=x; PFaceInst.m=s; SR_TRACE4 ( "Active Contour = "<< PFaceInst ); } 00070 # else 00071 # define SR_TRACE_CONTOUR(x,s) 00072 # endif 00073 */ 00074 00075 # define SR_TRACE_CONTOUR(x,s) 00076 00077 //=========================== EdgeTree ======================================== 00078 00079 class EdgeTree : public SrTree<Edge> 00080 { public : 00081 // EdgeTree() {} 00082 public : 00083 Edge *insert_edge ( int a, int b, int v ); 00084 bool insert_face ( int a, int b, int c, int f ); 00085 Edge* search_edge ( int a, int b ); 00086 void remove_face ( Edge *e ); 00087 }; 00088 00089 Edge *EdgeTree::insert_edge ( int a, int b, int v ) 00090 { 00091 Edge *e = new Edge ( a, b, v ); 00092 if ( !insert(e) ) 00093 { Edge *x = cur(); 00094 e->swap(); 00095 if ( !insert(e) ) 00096 { SR_TRACE2 ( "Could not insert edge ("<<a<<','<<b<<")!!" ); 00097 delete e; 00098 return 0; 00099 } 00100 x->sym = e; 00101 e->sym = x; 00102 } 00103 else // search if the sym edge is there and set sym pointers 00104 { // (to try: sort (a,b) to avoid checking if the sym exists...) 00105 Edge eba ( b, a, v ); 00106 Edge *esym = search ( &eba ); 00107 if ( esym ) 00108 { esym->sym = e; 00109 e->sym = esym; 00110 } 00111 } 00112 return e; 00113 } 00114 00115 bool EdgeTree::insert_face ( int a, int b, int c, int f ) 00116 { 00117 Edge *e1 = insert_edge ( a, b, c ); 00118 Edge *e2 = insert_edge ( b, c, a ); 00119 Edge *e3 = insert_edge ( c, a, b ); 00120 00121 if (e1) e1->set_fac_elems ( e2, e3, f ); 00122 if (e2) e2->set_fac_elems ( e1, e3, f ); 00123 if (e3) e3->set_fac_elems ( e1, e2, f ); 00124 00125 return e1&&e2&&e3? true:false; 00126 } 00127 00128 Edge* EdgeTree::search_edge ( int a, int b ) 00129 { 00130 Edge key(a,b,0); 00131 00132 Edge *e = search(&key); 00133 if ( !e ) 00134 { key.swap(); 00135 e=search(&key); 00136 } 00137 00138 return e; 00139 } 00140 00141 void EdgeTree::remove_face ( Edge *e ) 00142 { 00143 if (!e) return; 00144 00145 // e2 and/or e3 can be null in case non-manifold edges were found during the 00146 // construction of the edge tree with start() 00147 Edge *e2 = e->e2; 00148 Edge *e3 = e->e3; 00149 00150 extract ( e ); 00151 if ( e->sym ) e->sym->sym=0; 00152 00153 if (e2) 00154 { if ( e2->sym ) e2->sym->sym=0; 00155 remove ( e2 ); 00156 } 00157 00158 if (e3) 00159 { if ( e3->sym ) e3->sym->sym=0; 00160 remove ( e3 ); 00161 } 00162 } 00163 00164 //======================= internal data ================================== 00165 00166 static SeBase* init ( SeMeshImport *self, SeMeshBase* m, int a, int b ) 00167 { 00168 SeBase *s = m->init (); 00169 m->index(s->vtx(),(semeshindex)b); 00170 m->index(s->nxt()->vtx(),(semeshindex)a); 00171 self->attach_vtx_info ( s->vtx(), b ); 00172 self->attach_vtx_info ( s->nxt()->vtx(), a ); 00173 self->attach_edg_info ( s->edg(), b, a ); 00174 return s; 00175 } 00176 00177 static SeBase* mev ( SeMeshImport *self, SeMeshBase* m, SeBase* s, int ev, int v ) 00178 { 00179 s = m->mev ( s ); 00180 self->attach_edg_info ( s->edg(), ev, v ); 00181 self->attach_vtx_info ( s->vtx(), v ); 00182 m->index ( s->vtx(), (semeshindex)v ); 00183 return s; 00184 } 00185 00186 static SeBase* mef ( SeMeshImport *self, SeMeshBase* m, SeBase* s1, SeBase* s2, int a, int b, int f ) 00187 { 00188 s2 = m->mef ( s1, s2 ); 00189 self->attach_edg_info ( s2->edg(), a, b ); 00190 self->attach_fac_info ( s2->fac(), f ); 00191 return s2; 00192 } 00193 00194 class SeMeshImport::Data 00195 { public : 00196 SeMeshImport *self; 00197 EdgeTree tree; 00198 SrArray<SeBase*> active_contours; // stack of contours 00199 SrArray<SeBase*> contours_to_solve; // keep contours that will result in genus or holes 00200 SrArray<SeBase*> vtxsymedges; // keep pointer for vertices already inserted 00201 public : 00202 Data ( SeMeshImport *x ); 00203 SeMeshBase *init_shell (); 00204 int start ( const int *triangles, int numtris, int numvtx ); 00205 void solve_lasting_contours ( SeMeshBase *m ); 00206 void glue_face_on_one_edge ( SeMeshBase *m, SeBase *&s, Edge *e ); 00207 void glue_face_on_two_edges ( SeMeshBase *m, SeBase *&s, Edge *e ); 00208 void glue_face_on_three_edges ( SeMeshBase *m, SeBase *s, Edge *e ); 00209 }; 00210 00211 SeMeshImport::Data::Data ( SeMeshImport *x ) 00212 { 00213 vtxsymedges.size(0); 00214 vtxsymedges.capacity(256); 00215 active_contours.size(0); 00216 active_contours.capacity(32); 00217 self = x; 00218 } 00219 00220 SeMeshBase *SeMeshImport::Data::init_shell () 00221 { 00222 SR_TRACE1 ( "Getting new shell..." ); 00223 SeMeshBase *m = self->get_new_shell (); 00224 if ( !m ) return 0; 00225 00226 SR_TRACE1 ( "Getting seed face from the root of the tree..." ); 00227 00228 Edge *e = tree.root(); 00229 int a=e->a; int b=e->b; int c=e->v; // the order of the vertices is random 00230 int f=e->f; 00231 tree.remove_face ( e ); 00232 delete e; 00233 00234 SR_TRACE1 ( "Creating seed face = ["<<a<<" "<<b<<" "<<c<<"]" ); 00235 00236 m->begin_indexing (); 00237 00238 SeBase *s; 00239 00240 s = init ( self, m, a, b ); 00241 s = mev ( self, m, s, b, c ); 00242 mef ( self, m, s, s->nxt()->nxt(), a, c, f ); 00243 00244 vtxsymedges[c] = s; 00245 vtxsymedges[b] = s->nxt(); 00246 vtxsymedges[a] = s->nxt()->nxt(); 00247 00248 active_contours.push() = s; 00249 00250 SR_TRACE2 ("seed face info: "<<(int)s->sym()->fac()<<", active face info: "<<(int)s->fac() ); 00251 00252 return m; 00253 } 00254 00255 int SeMeshImport::Data::start ( const int *triangles, int numtris, int numvtx ) 00256 { 00257 int i; 00258 00259 active_contours.size(0); 00260 00261 SR_TRACE1 ( "Initializing vertices table with size "<<numvtx<<"..." ); 00262 vtxsymedges.size(numvtx); 00263 for ( i=0; i<vtxsymedges.size(); i++ ) vtxsymedges[i]=0; 00264 00265 SR_TRACE1 ( "Creating edge tree..." ); 00266 00267 const int *tri=triangles; 00268 int faces_with_edges_not_inserted=0; 00269 for ( i=0; i<numtris; i++ ) 00270 { if ( !tree.insert_face(tri[0],tri[1],tri[2],i) ) 00271 faces_with_edges_not_inserted++; 00272 tri += 3; 00273 } 00274 00275 return faces_with_edges_not_inserted; 00276 } 00277 00278 static SeBase* coincident_contour ( SeBase *s1, SeBase *s2 ) 00279 { 00280 SeBase *x = s2; 00281 while ( s1->vtx() != x->nxt()->vtx() ) 00282 { x = x->nxt(); 00283 if ( x==s2 ) return 0; // not coincident 00284 } 00285 00286 // a common starting vertex was found, so that the contours will be coincident 00287 // or we'll have non-manifold vertices. Let's verify : 00288 s2 = x; 00289 do { if ( s1->vtx() != s2->nxt()->vtx() ) 00290 { printf("Non-manifold vertex detected!\n"); return 0; } 00291 s1 = s1->nxt(); 00292 s2 = s2->pri(); 00293 } while ( s2!=x ); 00294 00295 return x; 00296 } 00297 00298 // should finished the contours by detecting loops to join or holes info to attach 00299 void SeMeshImport::Data::solve_lasting_contours ( SeMeshBase *m ) 00300 { 00301 int i; 00302 bool genus_increased; 00303 SeBase *s, *c; 00304 00305 while ( !contours_to_solve.empty() ) 00306 { genus_increased = false; 00307 s = contours_to_solve.pop(); 00308 SR_TRACE_CONTOUR(s,m); 00309 for ( i=0; i<contours_to_solve.size(); i++ ) 00310 { c = coincident_contour(s,contours_to_solve[i]); 00311 if ( c ) 00312 { SR_TRACE1 ( "Making one genus..." ); 00313 SR_TRACE_CONTOUR(c,m); 00314 contours_to_solve.remove(i);//[i]=contours_to_solve.pop(); 00315 genus_increased = true; 00316 m->mg ( s, c ); 00317 break; 00318 } 00319 } 00320 if ( !genus_increased ) 00321 { SR_TRACE1 ( "Closing last contour as a hole..." ); 00322 self->attach_hole_info ( s->fac() ); 00323 } 00324 } 00325 } 00326 00327 void SeMeshImport::Data::glue_face_on_one_edge ( SeMeshBase *m, SeBase *&s, Edge *e ) 00328 { 00329 tree.remove_face ( e ); 00330 00331 SeBase *snxt = s->nxt(); 00332 00333 s = mev ( self, m, s, e->a, e->v ); 00334 s = mef ( self, m, snxt, s, e->b, e->v, e->f ); 00335 00336 vtxsymedges[e->a] = s->nxt()->sym(); 00337 vtxsymedges[e->b] = snxt; 00338 vtxsymedges[e->v] = snxt->pri(); 00339 s = snxt; 00340 00341 delete e; 00342 } 00343 00344 void SeMeshImport::Data::glue_face_on_two_edges ( SeMeshBase* m, SeBase*& s, Edge* e ) 00345 { 00346 tree.remove_face ( e ); 00347 SeElement *ve = vtxsymedges[e->v]->vtx(); 00348 SeBase *s1, *s2; 00349 00350 if ( s->pri()->vtx()==ve ) 00351 { s1=s->nxt(); s2=s->pri(); } 00352 else 00353 { s1=s->nxt()->nxt(); s2=s; } 00354 00355 mef ( self, m, s1, s2, m->index(s1->vtx()), m->index(s2->vtx()), e->f ); 00356 s = s1->pri(); 00357 00358 vtxsymedges[(int)m->index(s->vtx())] = s; 00359 vtxsymedges[(int)m->index(s1->vtx())] = s1; 00360 delete e; 00361 } 00362 00363 void SeMeshImport::Data::glue_face_on_three_edges ( SeMeshBase* /*m*/, SeBase* s, Edge* e ) 00364 { 00365 tree.remove_face ( e ); 00366 self->attach_fac_info ( s->fac(), e->f ); 00367 delete e; 00368 } 00369 00370 //======================== SeMeshImport ======================================== 00371 00372 SeMeshImport::SeMeshImport () 00373 { 00374 _data = new Data ( this ); 00375 } 00376 00377 SeMeshImport::~SeMeshImport () 00378 { 00379 for ( int i=0; i<shells.size(); i++ ) delete shells[i]; 00380 delete _data; 00381 } 00382 00383 void SeMeshImport::compress_buffers () 00384 { 00385 shells.compress(); 00386 _data->vtxsymedges.capacity(0); 00387 _data->active_contours.capacity(0); 00388 } 00389 00390 SeMeshImport::Msg SeMeshImport::start ( const int *triangles, int numtris, int numvtxs ) 00391 { 00392 SR_TRACE1 ( "Start :" ); 00393 00394 int not_inserted = _data->start ( triangles, numtris, numvtxs ); 00395 00396 shells.size(0); 00397 SeMeshBase *m = _data->init_shell (); // will push something in active_contours 00398 if ( !m ) return MsgNullShell; 00399 shells.push()=m; 00400 00401 SR_TRACE_CONTOUR(_data->active_contours.top(),m); 00402 SR_TRACE4 ( "Face info of active contour = " << (int)(_data->active_contours.top()->fac()) ); 00403 SR_TRACE5 ( "Tree = "<<_data->tree ); 00404 SR_TRACE1 ( "Start finished !" ); 00405 SR_TRACE1 ( "Faces Lost: "<<not_inserted ); 00406 00407 return not_inserted>0? MsgNonManifoldFacesLost : MsgOk; 00408 } 00409 00410 static SeBase* in_same_face ( SeBase *e, SeElement *v ) 00411 { 00412 SeBase *x = e; 00413 do { if ( x->vtx()==v ) return x; 00414 x = x->nxt(); 00415 } while ( x!=e ); 00416 return 0; 00417 } 00418 00419 SeMeshImport::Msg SeMeshImport::next_step () 00420 { 00421 int a, b; 00422 Edge *e; 00423 SeBase *ini, *s, *sv; 00424 00425 int edges_found = 0; 00426 00427 SR_TRACE2 ( " " ); 00428 SR_TRACE2 ( "Next step :" ); 00429 00430 EdgeTree &tree = _data->tree; 00431 SrArray<SeBase*> &active_contours = _data->active_contours; 00432 SrArray<SeBase*> &contours_to_solve = _data->contours_to_solve; 00433 SrArray<SeBase*> &vtxsymedges = _data->vtxsymedges; 00434 00435 SR_TRACE2 ( "Active contours : "<<active_contours.size() ); 00436 00437 if ( tree.empty() ) 00438 { SR_TRACE1 ( "Empty tree: no more faces to glue." ); 00439 if ( !active_contours.empty() ) 00440 { while ( !active_contours.empty() ) contours_to_solve.push()=active_contours.pop(); 00441 SR_TRACE1 ( "Solving "<<contours_to_solve.size()<<" open contour(s)..." ); 00442 _data->solve_lasting_contours ( shells.top() ); 00443 } 00444 for ( int i=0; i<shells.size(); i++ ) shells[i]->end_indexing(); 00445 SR_TRACE1 ( "Finished : "<<shells.size()<<" shell(s), last shell V-E+F="<<shells.top()->euler() ); 00446 return MsgFinished; 00447 } 00448 else if ( active_contours.empty() ) 00449 { SR_TRACE1 ( "Starting new shell "<<shells.size()<<"... " ); 00450 shells.push() = _data->init_shell(); 00451 return MsgOk; // return now to cope with degenerated data (a shell with a single triangle). 00452 } 00453 00454 s = ini = active_contours.top(); 00455 00456 while ( true ) 00457 { 00458 a = (int) shells.top()->index(s->vtx()); 00459 b = (int) shells.top()->index(s->nxt()->vtx()); 00460 SR_TRACE2 ( "Searching edge "<<a<<" "<<b<<"... " ); 00461 e = tree.search_edge ( a, b ); // will search {a,b} or {b,a} 00462 00463 if ( e ) 00464 { edges_found++; 00465 00466 sv = 0; 00467 if ( vtxsymedges[e->v] ) // the other vertex is already in the mesh 00468 sv = in_same_face ( s, vtxsymedges[e->v]->vtx() ); 00469 00470 if ( !vtxsymedges[e->v] || !sv ) // if the other vertex is free or is in another contour 00471 { SR_TRACE1 ( "Gluing face "<<a<<" "<<b<<" "<<e->v<<" on one edge... " ); 00472 _data->glue_face_on_one_edge ( shells.top(), s, e ); 00473 active_contours.top() = s; 00474 SR_TRACE_CONTOUR(s,shells.top()); 00475 SR_TRACE5 ( "Tree = "<<tree ); 00476 return MsgOk; 00477 } 00478 else if ( s->nxt()->nxt()->nxt()==s ) // trying to close the active contour that is a triangle 00479 { SR_TRACE1 ( "Gluing last face "<<a<<" "<<b<<" "<<e->v<<" of current active contour..." ); 00480 _data->glue_face_on_three_edges ( shells.top(), s, e ); 00481 active_contours.pop(); 00482 SR_TRACE1 ( "Active contour popped... " ); 00483 SR_TRACE5 ( "Tree = "<<tree ); 00484 return MsgOk; 00485 } 00486 else if ( s->nxt()->nxt()->vtx()==vtxsymedges[e->v]->vtx() || 00487 s->pri()->vtx()==vtxsymedges[e->v]->vtx() ) 00488 { SR_TRACE1 ( "Gluing face "<<a<<" "<<b<<" "<<e->v<<" on two edges... " ); 00489 _data->glue_face_on_two_edges ( shells.top(), s, e ); 00490 active_contours.top() = s; 00491 SR_TRACE_CONTOUR(s,shells.top()); 00492 SR_TRACE5 ( "Tree = "<<tree ); 00493 return MsgOk; 00494 } 00495 else if ( sv ) 00496 { SR_TRACE1 ( "Connecting one edge, and pushing one active contour... " ); 00497 shells.top()->mef ( s, sv ); 00498 attach_edg_info ( s->edg(), shells.top()->index(s->vtx()), shells.top()->index(sv->vtx()) ); 00499 active_contours.push()=sv; 00500 return MsgOk; 00501 } 00502 else 00503 { SR_TRACE1 ( "XXXXXXXXXXXXXXXXXX undef situation!! XXXXXXXXXXXXXXXXXXXXXXXXXXXX" ); 00504 SR_TRACE_CONTOUR(active_contours.top(),shells.top()); 00505 SR_TRACE1 ( "s = ["<<a<<","<<b<<"] v="<<e->v); 00506 SR_TRACE1 ( "s.fac="<<(int)s->fac()<<", vfac="<<(int)vtxsymedges[e->v]->fac() ); 00507 } 00508 } 00509 else 00510 { // e not in the edge tree: input data is not fully connected! 00511 } 00512 00513 s = s->nxt(); 00514 if ( s==ini ) break;// already passed all edges of the active contour 00515 } 00516 00517 // At this point we looked into all edges of the active_contour, 00518 // but no faces were glued and the tree is not empty. 00519 00520 SR_TRACE1 ( "No more faces could be glued to the actual contour!" ); 00521 contours_to_solve.push() = active_contours.pop(); 00522 00523 return MsgOk; 00524 } 00525 00526 //============================== virtuals ================================== 00527 00528 void SeMeshImport::attach_vtx_info ( SeVertex* /*v*/, int /*vi*/ ) 00529 { 00530 } 00531 00532 void SeMeshImport::attach_edg_info ( SeEdge* /*e*/, int /*a*/, int /*b*/ ) 00533 { 00534 } 00535 00536 void SeMeshImport::attach_fac_info ( SeFace* /*f*/, int /*fi*/ ) 00537 { 00538 } 00539 00540 void SeMeshImport::attach_hole_info ( SeFace* /*f*/ ) 00541 { 00542 } 00543 00544 //============================== end of file =============================== 00545