BaseMesh.h

Go to the documentation of this file.
00001 
00011 #ifndef _MESHLIB_BASE_MESH_H_
00012 #define _MESHLIB_BASE_MESH_H_
00013 
00014 #define MAX_LINE 2048
00015 
00016 #include <math.h>
00017 #include <assert.h>
00018 #include <iostream>
00019 #include <fstream>
00020 #include <list>
00021 #include <map>
00022 
00023 #include "../Geometry/Point.h"
00024 #include "../Geometry/Point2.h"
00025 #include "../Parser/StrUtil.h"
00026 #include "edge.h" //for CEdgeKey class definition
00027 
00028 namespace MeshLib{
00029 
00044 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00045 class CBaseMesh
00046 {
00047 public:
00048         // pointer to Vertices, Halfedges, Edges, Face and Solid
00049         typedef CVertex   * tVertex;
00050         typedef CHalfEdge * tHalfEdge;
00051         typedef CEdge     * tEdge;
00052         typedef CFace     * tFace;
00053 
00054         //constructor and destructor
00058         CBaseMesh(){};
00062         ~CBaseMesh();
00063 
00064         //copy operator
00068         void copy( CBaseMesh & mesh );
00069 
00070         //file io
00075         void read_obj(  const char * filename );
00080         void write_obj( const char * output);
00081 
00086         void read_m(  const char * input );
00091         void write_m( const char * output);
00092         
00097         void read_off( const char * input );
00098 
00099         //number of vertices, faces, edges
00101         int  numVertices();
00103         int  numEdges();
00105         int  numFaces();
00106 
00107         //is boundary
00111         bool    isBoundary( tVertex  v );
00115         bool    isBoundary( tEdge    e );
00119         bool    isBoundary( tHalfEdge  he );
00120 
00121         //acess vertex - id
00127         tVertex idVertex( int id );
00133         int     vertexId( tVertex  v );
00134 
00135         //access face - id
00141         tFace   idFace( int id );
00147         int     faceId( tFace  f );
00148 
00149         //access edge - edge key, vertex
00156         tEdge   vertexEdge( tVertex v0, tVertex v1 );
00157 
00158         //access halfedge - halfedge key, vertex
00166         tHalfEdge   vertexHalfedge( tVertex v0, tVertex v1 );
00173         tHalfEdge   corner( tVertex v, tFace f);
00174 
00175         //halfedge->face
00181         tFace   halfedgeFace( tHalfEdge he );
00182         //halfedge->vertex
00188         tVertex halfedgeVertex( tHalfEdge he );
00189         //halfedge->vertex
00195         tVertex halfedgeTarget( tHalfEdge he );
00196         //halfedge->vertex
00202         tVertex halfedgeSource( tHalfEdge he );
00203 
00204         //halfedge->next
00211         tHalfEdge   halfedgeNext( tHalfEdge he );
00212         //halfedge->prev
00218         tHalfEdge   halfedgePrev( tHalfEdge he );
00219         //halfedge->sym
00225         tHalfEdge   halfedgeSym( tHalfEdge he );
00226         //halfedge->edge
00233         tEdge       halfedgeEdge( tHalfEdge he );
00234         //v->halfedge
00240         tHalfEdge   vertexHalfedge( tVertex v );
00241 
00242         //edge->vertex
00248         tVertex edgeVertex1( tEdge  e );
00254         tVertex edgeVertex2( tEdge  e );
00255 
00256         //edge->face
00262         tFace edgeFace1( tEdge  e );
00268         tFace edgeFace2( tEdge  e );
00269 
00270         //edge->halfedge
00278         tHalfEdge edgeHalfedge( tEdge  e, int id);
00279 
00280         //face->halfedge
00287         tHalfEdge faceHalfedge( tFace f );
00288 
00289         //Euler operations
00295         tHalfEdge vertexMostClwOutHalfEdge( tVertex  v );
00302         tHalfEdge vertexNextCcwOutHalfEdge( tHalfEdge  he );
00303 
00309         tHalfEdge vertexMostCcwOutHalfEdge( tVertex  v );
00315         tHalfEdge vertexNextClwOutHalfEdge( tHalfEdge  he );
00316 
00322         tHalfEdge vertexMostClwInHalfEdge( tVertex  v );
00328         tHalfEdge vertexNextCcwInHalfEdge( tHalfEdge  he );
00329 
00335         tHalfEdge vertexMostCcwInHalfEdge( tVertex  v );
00341         tHalfEdge vertexNextClwInHalfEdge( tHalfEdge  he );
00342 
00349         tHalfEdge faceMostClwHalfEdge( tFace  face );
00355         tHalfEdge faceMostCcwHalfEdge( tFace  face );
00361         tHalfEdge faceNextCcwHalfEdge( tHalfEdge  he );
00367         tHalfEdge faceNextClwHalfEdge( tHalfEdge  he );
00368 
00369 
00375         double edgeLength( tEdge e );
00376 
00380         std::list<tEdge>   & edges()            { return m_edges; };
00384         std::list<tFace>   & faces()            { return m_faces; };
00388         std::list<tVertex> & vertices() { return m_verts; };
00389 /*
00390         bool with_uv() { return m_with_texture; };
00391         bool with_normal() { return m_with_normal; };
00392 */
00393 protected:
00394 
00396   std::list<tEdge>                          m_edges;
00398   std::list<tVertex>                        m_verts;
00400   std::list<tFace>                                                      m_faces;
00401 
00402   //maps
00403 
00405   std::map<int, tVertex>                    m_map_vert;
00407   std::map<int, tFace>                                          m_map_face;
00409   std::map<CEdgeKey, tEdge>                                     m_map_edge;
00410 
00411 
00412 public:
00417         tVertex   createVertex(   int id = 0 );
00423         tEdge     createEdge(   tVertex v1, tVertex v2 );
00429         tFace     createFace(   tVertex  v[], int id ); //create a triangle
00430 
00434         void      deleteFace( tFace  pFace );
00435         
00437         bool      m_with_texture;
00439         bool      m_with_normal;
00440 
00441 };
00442 
00443 
00444 
00450 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00451 CVertex * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::edgeVertex1( tEdge   e )
00452 {
00453         assert( e->halfedge(0 ) != NULL );
00454         return (CVertex*)e->halfedge(0)->source();
00455 };
00456 
00463 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00464 CVertex *  CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::edgeVertex2( tEdge   e )
00465 {
00466         assert( e->halfedge(0 ) != NULL );
00467         return (CVertex*)e->halfedge(0)->target();
00468 };
00469 
00476 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00477 CFace * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::edgeFace1( tEdge   e )
00478 {
00479         assert( e->halfedge(0) != NULL );
00480         return (CFace*) e->halfedge(0)->face();
00481 };
00482 
00483 //access he->f
00491 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00492 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::edgeHalfedge( tEdge   e, int id )
00493 {
00494         return (CHalfEdge*)e->halfedge(id);
00495 };
00496 
00497 //access e->f
00504 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00505 CFace * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::edgeFace2( tEdge   e )
00506 {
00507         assert( e->halfedge(1) != NULL );
00508         return (CFace*) e->halfedge(1)->face();
00509 };
00510 
00511 //access he->f
00517 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00518 CFace * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::halfedgeFace( tHalfEdge   he )
00519 {
00520         return (CFace*)he->face();
00521 };
00522 
00523 //access f->he
00530 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00531 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::faceHalfedge( tFace   f )
00532 {
00533         return (CHalfEdge*)f->halfedge();
00534 };
00535 
00536 
00537 //access he->next
00544 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00545 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::halfedgeNext( tHalfEdge   he )
00546 {
00547         return (CHalfEdge*)he->he_next();
00548 };
00549 
00550 //access he->prev
00556 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00557 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::halfedgePrev( tHalfEdge  he )
00558 {
00559         return (CHalfEdge*)he->he_prev();
00560 };
00561 
00562 //access he->sym
00568 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00569 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::halfedgeSym( tHalfEdge   he )
00570 {
00571         return (CHalfEdge*)he->he_sym();
00572 };
00573 
00574 //access he->edge
00580 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00581 CEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::halfedgeEdge( tHalfEdge  he )
00582 {
00583         return (CEdge*)he->edge();
00584 };
00585 
00586 //access he->v
00592 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00593 CVertex * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::halfedgeVertex( tHalfEdge  he )
00594 {
00595         return (CVertex*)he->vertex();
00596 };
00597 
00598 //access he->v
00604 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00605 CVertex * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::halfedgeTarget( tHalfEdge   he )
00606 {
00607         return (CVertex*)he->vertex();
00608 };
00609 
00610 //access he->v
00616 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00617 CVertex * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::halfedgeSource( tHalfEdge   he )
00618 {
00619         return (CVertex*)he->he_prev()->vertex();
00620 };
00624 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00625 bool CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::isBoundary( tVertex   v )
00626 {
00627         return v->boundary();
00628 };
00632 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00633 bool CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::isBoundary( tEdge   e )
00634 {
00635         if( e->halfedge(0) == NULL || e->halfedge(1) == NULL ) return true;
00636         return false;
00637 };
00641 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00642 bool CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::isBoundary( tHalfEdge   he )
00643 {
00644         if( he->he_sym() == NULL ) return true;
00645         return false;
00646 };
00647 
00650 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00651 int CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::numVertices() 
00652 {
00653         return (int) m_verts.size();
00654 };
00655 
00658 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00659 int CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::numEdges() 
00660 {
00661         return (int) m_edges.size();
00662 };
00663 
00667 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00668 int CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::numFaces() 
00669 {
00670         return (int) m_faces.size();
00671 };
00672 
00673 
00674 //Euler operation
00680 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00681 CHalfEdge *  CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::vertexMostClwOutHalfEdge( tVertex   v )
00682 {
00683         return (CHalfEdge*)v->most_clw_out_halfedge();
00684 };
00690 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00691 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::vertexMostCcwOutHalfEdge( tVertex   v )
00692 {
00693         return (CHalfEdge*)v->most_ccw_out_halfedge();
00694 };
00695 
00702 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00703 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::corner( tVertex  v, tFace  f)
00704 {
00705         CHalfEdge * he = faceMostCcwHalfEdge( f );
00706         do{
00707                 if( he->vertex() == v )
00708                         return (CHalfEdge*) he;
00709                 he = faceNextCcwHalfEdge( he );
00710         }while( he != faceMostCcwHalfEdge(f) );
00711         return NULL;
00712 };
00718 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00719 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::vertexNextCcwOutHalfEdge( tHalfEdge  he )
00720 {
00721         return (CHalfEdge*) he->ccw_rotate_about_source();
00722 };
00728 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00729 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::vertexNextClwOutHalfEdge( tHalfEdge   he )
00730 {
00731         assert( he->he_sym() != NULL );
00732         return (CHalfEdge*)he->clw_rotate_about_source();
00733 };
00740 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00741 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::vertexMostClwInHalfEdge( tVertex   v )
00742 {
00743         return (CHalfEdge*)v->most_clw_in_halfedge();
00744 };
00751 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00752 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::vertexMostCcwInHalfEdge( tVertex   v )
00753 {
00754         return (CHalfEdge*)v->most_ccw_in_halfedge();
00755 };
00756 
00763 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00764 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::vertexNextCcwInHalfEdge( tHalfEdge   he )
00765 {
00766         assert( he->he_sym() != NULL );
00767         return (CHalfEdge*)he->ccw_rotate_about_target();
00768 };
00774 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00775 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::vertexNextClwInHalfEdge( tHalfEdge   he )
00776 {
00777         return (CHalfEdge*)he->clw_rotate_about_target();
00778 };
00784 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00785 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::faceNextClwHalfEdge( tHalfEdge   he )
00786 {
00787         return (CHalfEdge*)he->he_prev();
00788 };
00794 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00795 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::faceNextCcwHalfEdge( tHalfEdge   he )
00796 {
00797         return (CHalfEdge*)he->he_next();
00798 };
00799 
00805 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00806 CHalfEdge *  CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::faceMostCcwHalfEdge( tFace   face )
00807 {
00808         return (CHalfEdge*)face->halfedge();
00809 };template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00815 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::faceMostClwHalfEdge( tFace   face )
00816 {
00817         return (CHalfEdge*)face->halfedge()->he_next();
00818 };
00822 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00823 CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::~CBaseMesh()
00824 {
00825         //remove vertices
00826 
00827   for( std::list<CVertex*>::iterator viter = m_verts.begin(); viter != m_verts.end(); viter ++ )
00828   {
00829       CVertex * pV = *viter;
00830       delete pV;
00831   }
00832   m_verts.clear();
00833 
00834         //remove faces
00835 
00836   for( std::list<CFace*>::iterator fiter = m_faces.begin(); fiter != m_faces.end(); fiter ++ )
00837   {
00838       CFace * pF = *fiter;
00839 
00840       tHalfEdge he = faceHalfedge( pF );
00841  
00842       std::list<CHalfEdge*> hes;
00843       do{
00844         he = halfedgeNext( he );
00845         hes.push_back( he );
00846       }while( he != pF->halfedge() );
00847 
00848       for( std::list<CHalfEdge*>::iterator hiter = hes.begin(); hiter != hes.end(); hiter ++)
00849       {
00850           CHalfEdge * pH = *hiter;
00851           delete pH;
00852       }
00853       hes.clear();
00854 
00855       delete pF;
00856   }
00857   m_faces.clear();
00858         
00859   //remove edges
00860   for( std::list<CEdge*>::iterator eiter = m_edges.begin(); eiter != m_edges.end(); eiter ++ )
00861   {
00862       CEdge * pE = *eiter;
00863       delete pE;
00864   }
00865 
00866   m_edges.clear();
00867         
00868   //clear all the maps
00869   m_map_vert.clear();
00870   m_map_face.clear();
00871   m_map_edge.clear();
00872 };
00873 
00877 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00878 double CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::edgeLength( tEdge  e )
00879 {
00880         CVertex * v1 = edgeVertex1(e);
00881         CVertex * v2 = edgeVertex2(e);
00882 
00883         return ( v1->point() - v2->point() ).norm();
00884 }
00885 
00886 
00887 //create new gemetric simplexes
00893 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00894 CVertex * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::createVertex( int id )
00895 {
00896         CVertex * v = new CVertex();
00897         assert( v != NULL );
00898         v->id() = id;
00899         m_verts.push_back( v );
00900         m_map_vert.insert( std::pair<int,CVertex*>(id,v));
00901         return v;
00902 };
00903 
00904 
00910 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00911 void CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::read_obj( const char * filename )
00912 {
00913 
00914         std::fstream f(filename, std::fstream::in);
00915         if( f.fail() ) return;
00916 
00917         char cmd[1024];
00918 
00919         int  vid = 1;
00920         int  fid = 1;
00921         
00922         bool with_uv = false;
00923         bool with_normal = false;
00924 
00925         std::vector<CPoint2> uvs;
00926         std::vector<CPoint> normals;
00927 
00928 
00929         while ( f.getline( cmd, 1024) )
00930     {
00931                 std::string line( cmd );
00932                 line = strutil::trim( line );
00933 
00934                 strutil::Tokenizer stokenizer( line, " \t\r\n" );
00935 
00936                 stokenizer.nextToken();
00937                 std::string token = stokenizer.getToken();
00938                 
00939                 if( token == "v" )
00940                 {
00941                         CPoint p;
00942                         for( int i = 0; i < 3; i ++ )
00943                         {
00944                                 stokenizer.nextToken();
00945                                 token = stokenizer.getToken();
00946                                 p[i] = strutil::parseString<float>(token);
00947                         }
00948                         
00949                         CVertex * v = createVertex( vid);
00950                         v->point() = p;
00951                         vid ++;
00952                         continue;
00953                 }
00954 
00955 
00956                 if( token == "vt" )
00957                 {
00958                         with_uv = true;
00959                         CPoint2 uv;
00960                         for( int i = 0; i < 2; i ++ )
00961                         {
00962                                 stokenizer.nextToken();
00963                                 token = stokenizer.getToken();
00964                                 uv[i] = strutil::parseString<float>(token);
00965                         }
00966                         uvs.push_back( uv );
00967                         continue;
00968                 }
00969 
00970 
00971                 if ( token ==  "vn" )
00972                 {
00973                         with_normal = true;
00974 
00975                         CPoint n;
00976                         for( int i = 0; i < 3; i ++ )
00977                         {
00978                                 stokenizer.nextToken();
00979                                 token = stokenizer.getToken();
00980                                 n[i] = strutil::parseString<float>(token);
00981                         }
00982                         normals.push_back( n );
00983                         continue;
00984                 }
00985 
00986 
00987 
00988 
00989                 if ( token == "f" )
00990                 {
00991                         CVertex* v[3];
00992                         for( int i = 0 ; i < 3; i ++ )
00993                         {
00994                                 stokenizer.nextToken();
00995                                 token = stokenizer.getToken();
00996                                 
00997                                 
00998                                 strutil::Tokenizer tokenizer( token, " /\t\r\n" );
00999                                 
01000                                 int ids[3];
01001                                 int k = 0;
01002                                 while( tokenizer.nextToken() )
01003                                 {
01004                                         std::string token = tokenizer.getToken();
01005                                         ids[k] = strutil::parseString<int>(token);
01006                                         k ++;
01007                                 }
01008 
01009                                 
01010                                 v[i] = m_map_vert[ ids[0] ];
01011                                 if( with_uv )
01012                                         v[i]->uv() = uvs[ ids[1]-1 ];
01013                                 if( with_normal )
01014                                         v[i]->normal() = normals[ ids[2]-1 ];
01015                         }
01016                         createFace( v, fid++ );
01017                 }
01018         }
01019 
01020         f.close();
01021 
01022         //Label boundary edges
01023         for(std::list<CEdge*>::iterator eiter= m_edges.begin() ; eiter != m_edges.end() ; ++ eiter )
01024         {
01025                 CEdge *     edge = *eiter;
01026                 CHalfEdge * he[2];
01027 
01028                 he[0] = edge->halfedge(0);
01029                 he[1] = edge->halfedge(1);
01030                 
01031                 assert( he[0] != NULL );
01032                 
01033 
01034                 if( he[1] != NULL )
01035                 {
01036                         assert( he[0]->target() == he[1]->source() && he[0]->source() == he[1]->target() );
01037 
01038                         if( he[0]->target()->id() < he[0]->source()->id() )
01039                         {
01040                                 edge->halfedge(0 ) = he[1];
01041                                 edge->halfedge(1 ) = he[0];
01042                         }
01043 
01044                         assert( edgeVertex1(edge)->id() < edgeVertex2(edge)->id() );
01045                 }
01046                 else
01047                 {
01048                         he[0]->vertex()->boundary() = true;
01049                         he[0]->he_prev()->vertex()->boundary()  = true;
01050                 }
01051 
01052         }
01053 
01054         std::list<CVertex*> dangling_verts;
01055         //Label boundary edges
01056         for(std::list<CVertex*>::iterator viter = m_verts.begin();  viter != m_verts.end() ; ++ viter )
01057         {
01058                 tVertex     v = *viter;
01059                 if( v->halfedge() != NULL ) continue;
01060                 dangling_verts.push_back( v );
01061         }
01062 
01063         for( std::list<CVertex*>::iterator  viter = dangling_verts.begin() ; viter != dangling_verts.end(); ++ viter )
01064         {
01065                 tVertex v = *viter;
01066                 m_verts.remove( v );
01067                 delete v;
01068                 v = NULL;
01069         }
01070 
01071         //Arrange the boundary half_edge of boundary vertices, to make its halfedge
01072         //to be the most ccw in half_edge
01073 
01074         for(std::list<CVertex*>::iterator viter = m_verts.begin();  viter != m_verts.end() ; ++ viter )
01075         {
01076                 tVertex     v = *viter;
01077                 if( !v->boundary() ) continue;
01078 
01079                 CHalfEdge * he = v->halfedge();
01080                 while( he->he_sym() != NULL )
01081                 {
01082                         he = vertexNextCcwInHalfEdge( he );
01083                 }
01084 
01085                 v->halfedge() = he;
01086         }
01087 
01088 }
01089 
01096 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01097 CFace * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::createFace( tVertex  v[] , int id )
01098 {
01099           CFace * f = new CFace();
01100           assert( f != NULL );
01101           f->id() = id;
01102           m_faces.push_back( f );
01103           m_map_face.insert( std::pair<int,tFace>(id,f) );
01104 
01105                 //create halfedges
01106                 tHalfEdge hes[3];
01107 
01108                 for(int i = 0; i < 3; i ++ )
01109                 {
01110                         hes[i] = new CHalfEdge;
01111                         assert( hes[i] );
01112                         CVertex * vert =  v[i];
01113                         hes[i]->vertex() = vert;
01114                         vert->halfedge() = hes[i];
01115                 }
01116 
01117                 //linking to each other
01118                 for(int i = 0; i < 3; i ++ )
01119                 {
01120                         hes[i]->he_next() = hes[(i+1)%3];
01121                         hes[i]->he_prev() = hes[(i+2)%3];
01122                 }
01123 
01124                 //linking to face
01125                 for(int i = 0; i < 3; i ++ )
01126                 {
01127                         hes[i]->face()   = f;
01128                         f->halfedge()    = hes[i];
01129                 }
01130 
01131                 //connecting with edge
01132                 for(int i = 0; i < 3; i ++ )
01133                 {
01134                         tEdge e = createEdge( v[i], v[(i+2)%3] );
01135                         if( e->halfedge(0)  == NULL )
01136                         {
01137                                 e->halfedge(0) = hes[i];
01138                         }
01139                         else
01140                         {
01141                                 assert( e->halfedge(1) == NULL );
01142                                 e->halfedge(1) = hes[i];
01143                         }
01144                         hes[i]->edge() = e;
01145                 }
01146 
01147                 return f;
01148 };
01149 
01150 
01151 //access id->v
01157 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01158 CVertex * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::idVertex( int id ) 
01159 {
01160         return m_map_vert[id];
01161 };
01162 
01163 //access v->id
01169 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01170 int CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::vertexId( tVertex   v )
01171 {
01172         return v->id();
01173 };
01174 
01175 //access id->f
01181 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01182 CFace * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::idFace( int id )
01183 {
01184         return m_map_face[id];
01185 };
01186 
01187 //acess f->id
01193 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01194 int CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::faceId( tFace   f )
01195 {
01196         return f->id();
01197 };
01198 
01204 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01205 CEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::createEdge( tVertex  v1, tVertex  v2 )
01206 {
01207         CEdgeKey key(v1->id(),v2->id());
01208 
01209         CEdge * e = NULL;
01210 
01211         if( m_map_edge.find( key ) != m_map_edge.end() )
01212         {
01213                 e = m_map_edge[key];
01214                 assert( e!= NULL );
01215                 return e;
01216         }
01217 
01218         e = new CEdge;
01219         assert( e != NULL );
01220 
01221         assert( e != NULL );
01222         m_map_edge.insert( std::pair<CEdgeKey,CEdge *>(key,e) );
01223         m_edges.push_back( e );
01224         return e;
01225 
01226 };
01227 
01228 
01229 
01230 //access vertex->edge
01237 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01238 CEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::vertexEdge( tVertex  v0, tVertex  v1 )
01239 {
01240         CEdgeKey key(v0->id(),v1->id());
01241         return m_map_edge[key];
01242 };
01243 
01251 //access vertex->edge
01252 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01253 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::vertexHalfedge( tVertex  v0, tVertex  v1 )
01254 {
01255         CEdge * e = vertexEdge( v0, v1 );
01256         assert( e != NULL );
01257         CHalfEdge * he = (CHalfEdge*) e->halfedge(0);
01258         if( he->vertex() == v1 && he->he_prev()->vertex() == v0 ) return he;
01259         he = (CHalfEdge*) e->halfedge(1);
01260         assert( he->vertex() == v1 && he->he_prev()->vertex() == v0 );
01261         return he;
01262 };
01263 
01264 //access vertex->edge
01270 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01271 CHalfEdge * CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::vertexHalfedge( tVertex  v  )
01272 {
01273         return (CHalfEdge*) v->halfedge();
01274 };
01275 
01280 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01281 void CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::read_m( const char * input )
01282 {
01283         std::fstream is( input, std::fstream::in );
01284 
01285         if( is.fail() )
01286         {
01287                 fprintf(stderr,"Error in opening file %s\n", input );
01288                 return;
01289         }
01290 
01291         char buffer[MAX_LINE];
01292         int id;
01293 
01294         while( is.getline(buffer, MAX_LINE )  )
01295         {               
01296         
01297                 std::string line( buffer );
01298                 line = strutil::trim( line );
01299 
01300                 strutil::Tokenizer stokenizer( line, " \r\n" );
01301 
01302                 stokenizer.nextToken();
01303                 std::string token = stokenizer.getToken();
01304         
01305                 if( token == "Vertex"  ) 
01306                 {
01307                         stokenizer.nextToken();
01308                         token = stokenizer.getToken();
01309                         id = strutil::parseString<int>(token);
01310 
01311                         CPoint p;
01312                         for( int i = 0 ; i < 3; i ++ )
01313                         {
01314                                 stokenizer.nextToken();
01315                                 token = stokenizer.getToken();
01316                                 p[i] = strutil::parseString<float>(token);
01317                         }
01318                 
01319                         tVertex v  = createVertex( id );
01320                         v->point() = p;
01321                         v->id()    = id;
01322 
01323                         if( ! stokenizer.nextToken("\t\r\n") ) continue;
01324                         token = stokenizer.getToken();
01325 
01326                         int sp = (int) token.find("{");
01327                         int ep = (int) token.find("}");
01328 
01329                         if( sp >= 0 && ep >= 0 )
01330                         {
01331                                 v->string() = token.substr( sp+1, ep-sp-1 );
01332                         }
01333                         continue;
01334                 }
01335                 
01336 
01337                 if( token == "Face" ) 
01338                 {
01339 
01340                         stokenizer.nextToken();
01341                         token = stokenizer.getToken();
01342                         id = strutil::parseString<int>(token);
01343         
01344                         CVertex * v[3];
01345                         for( int i = 0; i < 3; i ++ )
01346                         {
01347                                 stokenizer.nextToken();
01348                                 token = stokenizer.getToken();
01349                                 int vid = strutil::parseString<int>(token);
01350                                 v[i] = idVertex( vid );
01351                         }
01352 
01353                         tFace f = createFace( v, id );
01354 
01355                         if( !stokenizer.nextToken() ) continue;
01356                         token = stokenizer.getToken();  
01357 
01358                         int sp = (int) token.find("{");
01359                         int ep = (int) token.find("}");
01360 
01361                         if( sp >= 0 && ep >= 0 )
01362                         {
01363                                 f->string() = token.substr( sp+1, ep-sp-1 );
01364                         }
01365                         continue;
01366                 }
01367 
01368                 //read in edge attributes
01369                 if( token == "Edge" )
01370                 {
01371                         stokenizer.nextToken();
01372                         token = stokenizer.getToken();
01373                         int id0 = strutil::parseString<int>( token );
01374 
01375                         stokenizer.nextToken();
01376                         token = stokenizer.getToken();
01377                         int id1 = strutil::parseString<int>( token );
01378 
01379 
01380                         CVertex * v0 = idVertex( id0 );
01381                         CVertex * v1 = idVertex( id1 );
01382 
01383                         tEdge edge = vertexEdge( v0, v1 );
01384 
01385                         if( !stokenizer.nextToken("\t\r\n") ) continue;
01386                         token = stokenizer.getToken();  
01387 
01388                         int sp = (int) token.find("{");
01389                         int ep = (int) token.find("}");
01390 
01391                         if( sp >= 0 && ep >= 0 )
01392                         {
01393                                   edge->string() = token.substr( sp+1, ep-sp-1 );
01394                         }
01395                         continue;
01396                 }
01397 
01398                 //read in edge attributes
01399                 if( token == "Corner" ) 
01400                 {
01401                         stokenizer.nextToken();
01402                         token = stokenizer.getToken();
01403                         int vid = strutil::parseString<int>( token );
01404 
01405                         stokenizer.nextToken();
01406                         token = stokenizer.getToken();
01407                         int fid = strutil::parseString<int>( token );
01408 
01409 
01410                         CVertex * v = idVertex( vid );
01411                         CFace   * f = idFace( fid );
01412                         tHalfEdge he = corner( v, f );
01413 
01414 
01415                         if( !stokenizer.nextToken("\t\r\n") ) continue;
01416                         token = stokenizer.getToken();  
01417 
01418                         int sp = (int) token.find("{");
01419                         int ep = (int) token.find("}");
01420 
01421                         if( sp >= 0 && ep >= 0 )
01422                         {
01423                                 he->string() = token.substr( sp+1, ep-sp-1 );
01424                         }
01425                         continue;
01426                 }
01427         }
01428 
01429         //Label boundary edges
01430         for(std::list<CEdge*>::iterator eiter= m_edges.begin() ; eiter != m_edges.end() ; ++ eiter )
01431         {
01432                 CEdge *     edge = *eiter;
01433                 CHalfEdge * he[2];
01434 
01435                 he[0] = edgeHalfedge( edge, 0 );
01436                 he[1] = edgeHalfedge( edge, 1 );
01437                 
01438                 assert( he[0] != NULL );
01439                 
01440 
01441                 if( he[1] != NULL )
01442                 {
01443                         assert( he[0]->target() == he[1]->source() && he[0]->source() == he[1]->target() );
01444 
01445                         if( he[0]->target()->id() < he[0]->source()->id() )
01446                         {
01447                                 edge->halfedge(0 ) = he[1];
01448                                 edge->halfedge(1 ) = he[0];
01449                         }
01450 
01451                         assert( edgeVertex1(edge)->id() < edgeVertex2(edge)->id() );
01452                 }
01453                 else
01454                 {
01455                         he[0]->vertex()->boundary() = true;
01456                         he[0]->he_prev()->vertex()->boundary()  = true;
01457                 }
01458 
01459         }
01460 
01461         std::list<CVertex*> dangling_verts;
01462         //Label boundary edges
01463         for(std::list<CVertex*>::iterator viter = m_verts.begin();  viter != m_verts.end() ; ++ viter )
01464         {
01465                 CVertex *     v = *viter;
01466                 if( v->halfedge() != NULL ) continue;
01467                 dangling_verts.push_back( v );
01468         }
01469 
01470         for( std::list<CVertex*>::iterator  viter = dangling_verts.begin() ; viter != dangling_verts.end(); ++ viter )
01471         {
01472                 CVertex * v = *viter;
01473                 m_verts.remove( v );
01474                 delete v;
01475                 v = NULL;
01476         }
01477 
01478         //Arrange the boundary half_edge of boundary vertices, to make its halfedge
01479         //to be the most ccw in half_edge
01480 
01481         for(std::list<CVertex*>::iterator viter = m_verts.begin();  viter != m_verts.end() ; ++ viter )
01482         {
01483                 CVertex *     v = *viter;
01484                 if( !v->boundary() ) continue;
01485 
01486                 CHalfEdge * he = vertexMostCcwInHalfEdge( v );
01487                 while( he->he_sym() != NULL )
01488                 {
01489                         he =  vertexNextCcwInHalfEdge ( he );
01490                 }
01491                 v->halfedge() = he;
01492         }
01493 
01494         //read in the traits
01495 
01496         for(std::list<CVertex*>::iterator viter = m_verts.begin();  viter != m_verts.end() ; ++ viter )
01497         {
01498                 CVertex *     v = *viter;
01499                 v->_from_string();
01500         }
01501 
01502         for(std::list<CEdge*>::iterator eiter = m_edges.begin();  eiter != m_edges.end() ; ++ eiter )
01503         {
01504                 CEdge *     e = *eiter;
01505                 e->_from_string();
01506         }
01507 
01508         for(std::list<CFace*>::iterator fiter = m_faces.begin();  fiter != m_faces.end() ; ++ fiter )
01509         {
01510                 CFace *     f = *fiter;
01511                 f->_from_string();
01512         }
01513 
01514         for( std::list<CFace*>::iterator fiter=m_faces.begin(); fiter != m_faces.end(); fiter ++ )
01515         {
01516                 CFace * pF = *fiter;
01517 
01518                 CHalfEdge * pH  = faceMostCcwHalfEdge( pF );
01519                 do{
01520                         pH->_from_string();
01521                         pH = faceNextCcwHalfEdge( pH );
01522                 }while( pH != faceMostCcwHalfEdge(pF ) );
01523         }
01524 
01525 };
01526 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01531 void CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::write_m( const char * output )
01532 {
01533         //write traits to string
01534         for( std::list<CVertex*>::iterator viter=m_verts.begin(); viter != m_verts.end(); viter ++ )
01535         {
01536                 CVertex * pV = *viter;
01537                 pV->_to_string();
01538         }
01539 
01540         for( std::list<CEdge*>::iterator eiter=m_edges.begin(); eiter != m_edges.end(); eiter ++ )
01541         {
01542                 CEdge * pE = *eiter;
01543                 pE->_to_string();
01544         }
01545 
01546         for( std::list<CFace*>::iterator fiter=m_faces.begin(); fiter != m_faces.end(); fiter ++ )
01547         {
01548                 CFace * pF = *fiter;
01549                 pF->_to_string();
01550         }
01551 
01552         for( std::list<CFace*>::iterator fiter=m_faces.begin(); fiter != m_faces.end(); fiter ++ )
01553         {
01554                 CFace * pF = *fiter;
01555                 CHalfEdge * pH  = faceMostCcwHalfEdge( pF );
01556                 do{
01557                         pH->_to_string();
01558                         pH = faceNextCcwHalfEdge( pH );
01559                 }while( pH != faceMostCcwHalfEdge(pF ) );
01560         }
01561 
01562 
01563         std::fstream _os( output, std::fstream::out );
01564         if( _os.fail() )
01565         {
01566                 fprintf(stderr,"Error is opening file %s\n", output );
01567                 return;
01568         }
01569 
01570 
01571         //remove vertices
01572   for( std::list<CVertex*>::iterator viter = m_verts.begin(); viter != m_verts.end(); viter ++)
01573   {
01574                 tVertex v = *viter;
01575 
01576                 _os << "Vertex " << v->id();
01577                 
01578                 for( int i = 0; i < 3; i ++ )
01579                 {
01580                         _os << " " << v->point()[i];
01581                 }
01582                 if( v->string().size() > 0 )
01583                 {
01584                         _os << " " <<"{"<< v->string() << "}";
01585                 }
01586                 _os << std::endl;
01587         }
01588 
01589   for( std::list<CFace*>::iterator fiter = m_faces.begin(); fiter != m_faces.end(); fiter ++ )
01590         {
01591                 tFace f = *fiter;
01592 
01593                 _os << "Face " << f->id();
01594                 tHalfEdge he = faceHalfedge( f );
01595                 do{
01596                         _os << " " <<  he->target()->id();
01597                         he = halfedgeNext( he );
01598                 }while( he != f->halfedge() );
01599 
01600                 if( f->string().size() > 0 )
01601                 {
01602                         _os << "{"<< f->string() << "}";
01603                 }
01604                 _os << std::endl;
01605         }
01606 
01607   for( std::list<CEdge*>::iterator eiter = m_edges.begin(); eiter != m_edges.end(); eiter ++ )
01608         {
01609                 tEdge e = *eiter;
01610                 if( e->string().size() > 0 )
01611                 {
01612                         _os << "Edge "<<  edgeVertex1(e)->id() <<" " << edgeVertex2(e)->id() << " ";
01613                         _os << "{" << e->string() << "}" << std::endl;
01614                 }
01615         }
01616 
01617   for( std::list<CFace*>::iterator fiter = m_faces.begin(); fiter != m_faces.end(); fiter ++  )
01618         {
01619                 tFace f = *fiter;
01620 
01621                 tHalfEdge he = faceHalfedge( f );
01622 
01623     do{
01624                         if( he->string().size() > 0 )
01625                           {
01626                                   _os << "Corner "<< he->vertex()->id() << " " << f->id() << " ";
01627                                   _os << "{" << he->string() << "}" << std::endl;
01628                           }
01629                           he = halfedgeNext( he );
01630                 }while( he != f->halfedge() );
01631 
01632   }
01633 
01634         _os.close();
01635 };
01636 
01637 
01638 //assume the mesh is with uv coordinates and normal vector for each vertex
01643 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01644 void CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::write_obj( const char * output )
01645 {
01646         std::fstream _os( output, std::fstream::out );
01647         if( _os.fail() )
01648         {
01649                 fprintf(stderr,"Error is opening file %s\n", output );
01650                 return;
01651         }
01652 
01653         int vid = 1;
01654         for( std::list<CVertex*>::iterator viter = m_verts.begin(); viter != m_verts.end(); viter ++)
01655         {
01656                 tVertex v = *viter;
01657                 v->id() = vid ++;
01658         }
01659 
01660         for( std::list<CVertex*>::iterator viter = m_verts.begin(); viter != m_verts.end(); viter ++)
01661         {
01662                 tVertex v = *viter;
01663 
01664                 _os << "v";
01665                 
01666                 for( int i = 0; i < 3; i ++ )
01667                 {
01668                         _os << " " << v->point()[i];
01669                 }
01670                 _os << std::endl;
01671         }
01672 
01673         for( std::list<CVertex*>::iterator viter = m_verts.begin(); viter != m_verts.end(); viter ++)
01674         {
01675                 tVertex v = *viter;
01676 
01677                 _os << "vt";
01678                 
01679                 for( int i = 0; i < 2; i ++ )
01680                 {
01681                         _os << " " << v->uv()[i];
01682                 }
01683                 _os << std::endl;
01684         }
01685 
01686         for( std::list<CVertex*>::iterator viter = m_verts.begin(); viter != m_verts.end(); viter ++)
01687         {
01688                 tVertex v = *viter;
01689 
01690                 _os << "vn";
01691                 
01692                 for( int i = 0; i < 3; i ++ )
01693                 {
01694                         _os << " " << v->normal()[i];
01695                 }
01696                 _os << std::endl;
01697         }
01698 
01699 
01700   for( std::list<CFace*>::iterator fiter = m_faces.begin(); fiter != m_faces.end(); fiter ++ )
01701         {
01702                 tFace f = *fiter;
01703 
01704                 _os << "f";
01705 
01706                 tHalfEdge he = f->halfedge();
01707                 
01708                 do{
01709                         int vid = he->target()->id();
01710                         _os << " " <<  vid << "/" << vid << "/" << vid;
01711                         he = he->he_next();
01712                 }while( he != f->halfedge() );
01713                 _os << std::endl;
01714         }
01715 
01716         _os.close();
01717 };
01718 
01719 //template pointer converting to base class pointer is OK (BasePointer) = (TemplatePointer)
01720 //(TemplatePointer)=(BasePointer) is incorrect
01725 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01726 void CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::deleteFace( tFace  pFace )
01727 {         
01728           std::map<int,tFace>::iterator fiter = m_map_face.find( pFace->id() );
01729           if( fiter != m_map_face.end() )
01730           {
01731                   m_map_face.erase( fiter );
01732           }     
01733           m_faces.remove( pFace );
01734 
01735                 
01736          //create halfedges
01737          tHalfEdge hes[3];
01738 
01739          hes[0] = faceHalfedge( pFace );
01740          hes[1] = faceNextCcwHalfEdge( hes[0] );
01741          hes[2] = faceNextCcwHalfEdge( hes[1] );
01742 
01743          for(int i = 0; i < 3; i ++ )
01744          {
01745                 //connection with edge
01746                 CHalfEdge * pH = hes[i];
01747 
01748                 //connection to target
01749                 CVertex * pV = halfedgeTarget( pH );
01750                 if( pV->halfedge() == pH )
01751                 {
01752                         if( pH->he_next()->he_sym() != NULL )
01753                                 pV->halfedge() = pH->he_next()->he_sym();
01754                         else
01755                         {
01756                                 assert( pH->he_sym() != NULL ); //otherwise the mesh is not a manifold
01757                                 pV->halfedge() = pH->he_sym()->he_prev();
01758                         }
01759                 }
01760          }
01761 
01762                 for(int i = 0; i < 3; i ++ )
01763                 {
01764                         //connection with edge
01765                         CHalfEdge * pH = hes[i];
01766                         CHalfEdge * pS = halfedgeSym( pH );
01767                         CEdge * pE = halfedgeEdge( pH );
01768 
01769                         pE->halfedge(0) = pS;
01770                         pE->halfedge(1) = NULL;
01771 
01772                         if( pS == NULL )
01773                         {
01774                                 //assert(0);
01775                                 m_edges.remove( pE );
01776                                 CVertex * v0 = halfedgeSource( pH );
01777                                 CVertex * v1 = halfedgeTarget( pH );
01778                                 CEdgeKey key(v0->id(),v1->id());
01779                                 std::map<CEdgeKey,tEdge>::iterator eiter = m_map_edge.find(key);
01780                                 if( eiter != m_map_edge.end() )
01781                                         m_map_edge.erase( eiter );
01782                                 delete pE;
01783                         }
01784 
01785                         
01786                 }
01787                 
01788                 //remove half edges
01789                 for(int i = 0; i < 3; i ++ )
01790                 {
01791                         delete hes[i];
01792                 }
01793                 
01794                 delete pFace;
01795 };
01796 
01801 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
01802 void CBaseMesh<CVertex,CEdge,CFace,CHalfEdge>::read_off( const char * input )
01803 {
01804         std::fstream is( input, std::fstream::in );
01805 
01806         if( is.fail() )
01807         {
01808                 fprintf(stderr,"Error is opening file %s\n", input );
01809                 return;
01810         }
01811 
01812         char buffer[MAX_LINE];
01813 
01814         //read in the first line "OFF"
01815 
01816         while( is.getline(buffer, MAX_LINE )  )
01817         {               
01818                 std::string line( buffer );
01819         
01820                 strutil::Tokenizer stokenizer( line, " \r\n" );
01821 
01822                 stokenizer.nextToken();
01823                 std::string token = stokenizer.getToken();
01824                 if( token == "OFF"  ) break;
01825         }
01826 
01827         int nVertices, nFaces, nEdges;
01828 
01829         //read in Vertex Number, Face Number, Edge Number
01830 
01831                 is.getline(buffer, MAX_LINE );
01832                 std::string line( buffer );
01833         
01834                 strutil::Tokenizer stokenizer( line, " \r\n" );
01835 
01836                 stokenizer.nextToken();
01837                 std::string token = stokenizer.getToken();
01838                 nVertices = strutil::parseString<int>( token );
01839 
01840                 stokenizer.nextToken();
01841                 token = stokenizer.getToken();
01842                 nFaces = strutil::parseString<int>( token );
01843 
01844                 stokenizer.nextToken();
01845                 token = stokenizer.getToken();
01846                 nEdges = strutil::parseString<int>( token );
01847 
01848                 //printf("V %d F %d E %d\n" , nVertices, nFaces, nEdges);
01849         
01850 
01851         for( int id = 0; id < nVertices; id ++ )
01852         {
01853                 is.getline(buffer, MAX_LINE );
01854                 std::string line( buffer );
01855                 
01856                 strutil::Tokenizer stokenizer( line, " \r\n" );
01857                 CPoint p;
01858                 for( int j = 0; j < 3; j ++ )
01859                 {
01860                         stokenizer.nextToken();
01861                         std::string token = stokenizer.getToken();
01862                         p[j] = strutil::parseString<float>( token );
01863                 }
01864 
01865                         CVertex * v = createVertex( id + 1 );
01866                         v->point() = p;
01867         }
01868 
01869 
01870         for( int id = 0; id < nFaces; id ++ )
01871         {
01872 
01873                 is.getline(buffer, MAX_LINE );
01874                 std::string line( buffer );
01875                 
01876                 strutil::Tokenizer stokenizer( line, " \r\n" );
01877                 stokenizer.nextToken();
01878                 std::string token = stokenizer.getToken();
01879                 
01880                 int n = strutil::parseString<int>(token);
01881                 assert( n == 3 );
01882 
01883                 CVertex * v[3];
01884                 for( int j = 0; j < 3; j ++ )
01885                 {
01886                         stokenizer.nextToken();
01887                         std::string token = stokenizer.getToken();
01888                         int vid = strutil::parseString<int>( token );
01889                         v[j] = idVertex( vid + 1);
01890                 }
01891                 
01892                 createFace( v, id + 1 );
01893         }
01894 
01895         is.close();
01896 
01897         //Label boundary edges
01898         for(std::list<CEdge*>::iterator eiter= m_edges.begin() ; eiter != m_edges.end() ; ++ eiter )
01899         {
01900                 CEdge *     edge = *eiter;
01901                 CHalfEdge * he[2];
01902 
01903                 he[0] = edge->halfedge(0);
01904                 he[1] = edge->halfedge(1);
01905                 
01906                 assert( he[0] != NULL );
01907                 
01908 
01909                 if( he[1] != NULL )
01910                 {
01911                         assert( he[0]->target() == he[1]->source() && he[0]->source() == he[1]->target() );
01912 
01913                         if( he[0]->target()->id() < he[0]->source()->id() )
01914                         {
01915                                 edge->halfedge(0 ) = he[1];
01916                                 edge->halfedge(1 ) = he[0];
01917                         }
01918 
01919                         assert( edgeVertex1(edge)->id() < edgeVertex2(edge)->id() );
01920                 }
01921                 else
01922                 {
01923                         he[0]->vertex()->boundary() = true;
01924                         he[0]->he_prev()->vertex()->boundary()  = true;
01925                 }
01926 
01927         }
01928 
01929         std::list<CVertex*> dangling_verts;
01930         //Label boundary edges
01931         for(std::list<CVertex*>::iterator viter = m_verts.begin();  viter != m_verts.end() ; ++ viter )
01932         {
01933                 tVertex     v = *viter;
01934                 if( v->halfedge() != NULL ) continue;
01935                 dangling_verts.push_back( v );
01936         }
01937 
01938         for( std::list<CVertex*>::iterator  viter = dangling_verts.begin() ; viter != dangling_verts.end(); ++ viter )
01939         {
01940                 tVertex v = *viter;
01941                 m_verts.remove( v );
01942                 delete v;
01943                 v = NULL;
01944         }
01945 
01946         //Arrange the boundary half_edge of boundary vertices, to make its halfedge
01947         //to be the most ccw in half_edge
01948 
01949         for(std::list<CVertex*>::iterator viter = m_verts.begin();  viter != m_verts.end() ; ++ viter )
01950         {
01951                 tVertex     v = *viter;
01952                 if( !v->boundary() ) continue;
01953 
01954                 CHalfEdge * he = v->halfedge();
01955                 while( he->he_sym() != NULL )
01956                 {
01957                         he = he->ccw_rotate_about_target();
01958                 }
01959                 v->halfedge() = he;
01960         }
01961 
01962 
01963 };
01964 
01965 
01966 
01967 
01968 }//name space MeshLib
01969 
01970 #endif //_MESHLIB_BASE_MESH_H_ defined
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Defines