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"
00027
00028 namespace MeshLib{
00029
00044 template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
00045 class CBaseMesh
00046 {
00047 public:
00048
00049 typedef CVertex * tVertex;
00050 typedef CHalfEdge * tHalfEdge;
00051 typedef CEdge * tEdge;
00052 typedef CFace * tFace;
00053
00054
00058 CBaseMesh(){};
00062 ~CBaseMesh();
00063
00064
00068 void copy( CBaseMesh & mesh );
00069
00070
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
00101 int numVertices();
00103 int numEdges();
00105 int numFaces();
00106
00107
00111 bool isBoundary( tVertex v );
00115 bool isBoundary( tEdge e );
00119 bool isBoundary( tHalfEdge he );
00120
00121
00127 tVertex idVertex( int id );
00133 int vertexId( tVertex v );
00134
00135
00141 tFace idFace( int id );
00147 int faceId( tFace f );
00148
00149
00156 tEdge vertexEdge( tVertex v0, tVertex v1 );
00157
00158
00166 tHalfEdge vertexHalfedge( tVertex v0, tVertex v1 );
00173 tHalfEdge corner( tVertex v, tFace f);
00174
00175
00181 tFace halfedgeFace( tHalfEdge he );
00182
00188 tVertex halfedgeVertex( tHalfEdge he );
00189
00195 tVertex halfedgeTarget( tHalfEdge he );
00196
00202 tVertex halfedgeSource( tHalfEdge he );
00203
00204
00211 tHalfEdge halfedgeNext( tHalfEdge he );
00212
00218 tHalfEdge halfedgePrev( tHalfEdge he );
00219
00225 tHalfEdge halfedgeSym( tHalfEdge he );
00226
00233 tEdge halfedgeEdge( tHalfEdge he );
00234
00240 tHalfEdge vertexHalfedge( tVertex v );
00241
00242
00248 tVertex edgeVertex1( tEdge e );
00254 tVertex edgeVertex2( tEdge e );
00255
00256
00262 tFace edgeFace1( tEdge e );
00268 tFace edgeFace2( tEdge e );
00269
00270
00278 tHalfEdge edgeHalfedge( tEdge e, int id);
00279
00280
00287 tHalfEdge faceHalfedge( tFace f );
00288
00289
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
00391
00392
00393 protected:
00394
00396 std::list<tEdge> m_edges;
00398 std::list<tVertex> m_verts;
00400 std::list<tFace> m_faces;
00401
00402
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 );
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
01072
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
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
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
01125 for(int i = 0; i < 3; i ++ )
01126 {
01127 hes[i]->face() = f;
01128 f->halfedge() = hes[i];
01129 }
01130
01131
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
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
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
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
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
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
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
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
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
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
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
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
01479
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
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
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
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
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
01720
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
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
01746 CHalfEdge * pH = hes[i];
01747
01748
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 );
01757 pV->halfedge() = pH->he_sym()->he_prev();
01758 }
01759 }
01760 }
01761
01762 for(int i = 0; i < 3; i ++ )
01763 {
01764
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
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
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
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
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
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
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
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
01947
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 }
01969
01970 #endif //_MESHLIB_BASE_MESH_H_ defined