ORTS

se_mesh_import.cpp

Go to the documentation of this file.
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 


Generated on Fri May 18 2012 03:02:45 for ORTS by Doxygen1.7.3