Mesh Class Reference

#include <Mesh.h>

List of all members.


Detailed Description

Implementation of the half edge datastructure.

Definition at line 20 of file Mesh.h.

Public Types

typedef std::multiset< Edge *,
Mesh::edge_comp
EdgeSet
typedef std::vector< Face * > FaceSet
typedef std::vector< Vertex * > VertexSet

Public Member Functions

 Mesh (void)
 ~Mesh (void)
void clear ()
VertexaddVertex (const Vector3 &p)
FaceaddFace (std::vector< int > faceVerts)
EdgeaddEdge (int i, int j)
EdgeaddEdge (Edge *e)
bool cutAlongEdge (Edge *forward)
 Cuts the mesh along single edge while maintaining all the connectivity of the mesh.
VertexvertexAt (int i)
FacefaceAt (int i)
int numFaces ()
int numVertices ()
int numEdges ()
int numBoundary ()
void linkBoundary ()
 Called after the mesh is created to link boundary edges.
bool checkManifold ()
 Manifoldness check: only one disk should be adjusted on any vertex.
bool checkVertexConection ()
 Check if all the vertices in the mesh have at least on edge coming out of them.
void checkGaussianCurvature ()
 Compute total Gaussian curvature that cone singularities allow and check if it satisfy Gauss-Bonet theorem.
void computeMeshInfo ()
 Computes number of connected components, number of boundary loops and genus of the mesh.
void computeLengths ()
 Compute edge lengths based on vertex positions.
void computeInitAngles ()
 Compute initial alpha angles in the mesh.
void readOBJ (const char *obj_file)
 Loads mesh from obj file.
void readCON (const char *conn_file)
 Loads mesh from con (connectivity and edge length) file.
void readCONE_VERT (const char *vert_file)
 Reads cone singularities allowed by the user.
void readCUT_EDGES (const char *edge_file)
 Reads edge cuts from the input file and cuts the mesh over those edges.
void writeOBJ (const char *obj_file)
void writeVT (const char *vt_file)
void writeCON (const char *conn_file)
 Write out the result parameterization in "connectivity" format.
void finishMesh ()
FaceIterator faceIterator ()
VertexIterator vertexIterator ()
HalfEdgeIterator halfEdgeIterator ()
EdgeIterator edgeIterator ()

Public Attributes

int numBoundaryVertices
 Number of vertices (or also edges) at the boundary of the mesh.
int numBoundaryLoops
 Number of boundary loops in the mesh.
int numConnectedComponents
 Number of connected components.
int numGenus
 Genus of the mesh.

Private Attributes

std::vector< Vertex * > vertices
std::vector< Face * > faces
std::multiset< Edge *, Mesh::edge_compedges

Classes

struct  edge_comp
 Comparison functions for edge sets. More...
class  EdgeIterator
class  FaceIterator
class  HalfEdgeIterator
class  VertexIterator


Member Typedef Documentation

typedef std::multiset<Edge*, Mesh::edge_comp> Mesh::EdgeSet
 

Definition at line 63 of file Mesh.h.

typedef std::vector<Face *> Mesh::FaceSet
 

Definition at line 64 of file Mesh.h.

typedef std::vector<Vertex *> Mesh::VertexSet
 

Definition at line 65 of file Mesh.h.


Constructor & Destructor Documentation

Mesh::Mesh void   ) 
 

Definition at line 16 of file Mesh.cpp.

00017 {
00018    numBoundaryVertices = 0;
00019 }

Mesh::~Mesh void   ) 
 

Definition at line 21 of file Mesh.cpp.

00022 {
00023    clear();
00024 }


Member Function Documentation

Edge* Mesh::addEdge Edge e  )  [inline]
 

Definition at line 74 of file Mesh.h.

00074                             {
00075       edges.insert(e);
00076       return e;
00077    }

Edge * Mesh::addEdge int  i,
int  j
 

Definition at line 91 of file Mesh.cpp.

00091                                   {
00092    Edge eTmp;
00093    eTmp.vertex = vertices[i];
00094 
00095    Edge eTmpPair;
00096    eTmpPair.vertex = vertices[j];
00097    eTmp.pair = &eTmpPair;
00098 
00099    Mesh::EdgeSet::iterator eIn = edges.find(&eTmp);
00100    Edge * e;
00101 
00102    if (eIn != edges.end()){
00103       e = *eIn;
00104       if (e->face != NULL)
00105           return NULL;
00106    }
00107    else {
00108       e = new Edge();
00109       Edge * pair = new Edge();
00110 
00111       e->vertex = vertices[i];
00112       pair->vertex = vertices[j];
00113 
00114       pair->pair = e;
00115       e->pair = pair;
00116 
00117       edges.insert(e);
00118       edges.insert(pair);
00119 
00120       pair->vertex->edge = pair;
00121    }   
00122    return e;
00123 }

Face * Mesh::addFace std::vector< int >  faceVerts  ) 
 

Definition at line 53 of file Mesh.cpp.

00053                                              {
00054    Face * f = new Face();
00055    f->ID = (int)faces.size();
00056 
00057    Edge * firstEdge = NULL;
00058    Edge * last = NULL;
00059    Edge * current = NULL;
00060 
00061    unsigned int i;
00062 
00063    for (i = 0; i < faceVerts.size()-1; i++) {
00064       current = addEdge(faceVerts[i], faceVerts[i+1]);
00065    
00066       check_error (!current, "Problem while parsing mesh faces.");
00067 
00068       current->face = f;
00069 
00070       if (last)
00071           last->next = current;
00072       else
00073           firstEdge = current;
00074       last = current;
00075    }
00076 
00077    current = addEdge (faceVerts[i], faceVerts[0]);
00078    check_error (!current, "Problem while parsing mesh faces.");
00079    
00080    current->face = f;
00081 
00082    last->next = current;
00083    current->next = firstEdge;
00084 
00085    f->edge = firstEdge;
00086    faces.push_back(f);
00087       
00088    return f;
00089 }

Vertex * Mesh::addVertex const Vector3 p  ) 
 

Definition at line 45 of file Mesh.cpp.

00045                                            {
00046    Vertex * v = new Vertex();
00047    v->p = _p;
00048    v->ID = (int)vertices.size();
00049    vertices.push_back(v);
00050    return v;
00051 }

void Mesh::checkGaussianCurvature  ) 
 

Compute total Gaussian curvature that cone singularities allow and check if it satisfy Gauss-Bonet theorem.

Definition at line 711 of file Mesh.cpp.

00711                                   {
00712    double minConeGC = 0; 
00713    double maxConeGC = 0;
00714   
00715    for (int i = 0; i < numVertices(); i++)   {
00716       if (vertices[i]->constrained) {
00717           if (vertices[i]->isBoundary()) {
00718              maxConeGC += (M_PI - vertices[i]->min_cone_angle*M_PI);
00719              minConeGC += (M_PI - vertices[i]->max_cone_angle*M_PI);
00720           }
00721           else {
00722              maxConeGC += (2*M_PI - vertices[i]->min_cone_angle*M_PI);
00723              minConeGC += (2*M_PI - vertices[i]->max_cone_angle*M_PI);
00724           }
00725       }
00726       else if (vertices[i]->isBoundary()) {
00727           maxConeGC +=  M_PI;
00728           minConeGC += -M_PI;;
00729       }
00730    }
00731 
00732    double eNum1 = minConeGC / (2*M_PI);
00733    double eNum2 = maxConeGC / (2*M_PI);
00734    double eNumCurr = (double)(2 - 2*numGenus - numBoundaryLoops)/(double)numConnectedComponents;
00735    cout << "Checking Gauss-Bonet Theorem:" << endl;
00736    cout << "Minimum euler number for this set up is " << eNum1 << endl;
00737    cout << "Maximum euler number for this set up is " << eNum2 << endl;
00738    cout << "Euler number of the mesh is " << eNumCurr << "\n" << endl;
00739 
00740    check_warn((eNumCurr < eNum1) || (eNumCurr > eNum2), 
00741       "The mesh cannot be developed with current set of cone singularities.\n");
00742 }

bool Mesh::checkManifold  ) 
 

Manifoldness check: only one disk should be adjusted on any vertex.

Definition at line 324 of file Mesh.cpp.

00324                          {
00325    Mesh::HalfEdgeIterator eIter = halfEdgeIterator();
00326    Mesh::VertexIterator vIter = vertexIterator();
00327    bool manifold = true;
00328 
00329    for (;!eIter.end(); eIter++)
00330       eIter.half_edge()->check = false;
00331 
00332    for (vIter.reset(); !vIter.end(); vIter++) {
00333       Vertex::EdgeAroundIterator around = vIter.vertex()->iterator();
00334       for (;!around.end();around++)
00335           around.edge_out()->check = true;
00336    }
00337 
00338    for (eIter.reset(); !eIter.end(); eIter++) {
00339       if (!eIter.half_edge()->check) {
00340           cerr << "Mesh is not manifold - more then one disk at vertex " 
00341              << eIter.half_edge()->vertex->ID << endl;
00342           manifold = false;
00343           break;
00344       }
00345    }
00346 
00347    return manifold;
00348 }

bool Mesh::checkVertexConection  ) 
 

Check if all the vertices in the mesh have at least on edge coming out of them.

Definition at line 300 of file Mesh.cpp.

00300                                 {
00301    Mesh::FaceIterator fIter = faceIterator();
00302    Mesh::VertexIterator vIter = vertexIterator();
00303    bool conectedVert = true;
00304 
00305    for (;!vIter.end(); vIter++)
00306       vIter.vertex()->check = false;
00307 
00308    for (fIter.reset(); !fIter.end(); fIter++) {
00309       Face::EdgeAroundIterator around = fIter.face()->iterator();
00310       for (;!around.end();around++)
00311           around.vertex()->check = true;
00312    }
00313    for (vIter.reset(); !vIter.end(); vIter++) {
00314       if (!vIter.vertex()->check) {
00315           cerr << "Vertex " << vIter.vertex()->ID << " is not connected." << endl;
00316           conectedVert = false;
00317       }
00318    }
00319 
00320    return conectedVert;
00321 }

void Mesh::clear  ) 
 

Definition at line 26 of file Mesh.cpp.

00026                  {
00027    VertexIterator vIter = vertexIterator();
00028    FaceIterator fIter = faceIterator();
00029    HalfEdgeIterator eIter = halfEdgeIterator();
00030 
00031    while (!vIter.end()) {
00032       delete vIter.vertex();
00033       vIter++;
00034    }
00035    while (!fIter.end()) {
00036       delete fIter.face();
00037       fIter++;
00038    }
00039    while (!eIter.end()) {
00040       delete eIter.half_edge();
00041       eIter++;
00042    }
00043 }

void Mesh::computeInitAngles  ) 
 

Compute initial alpha angles in the mesh.

This function assumes that the mesh is triangular. Alpha angels are stored at each edge and correspond to an angle opposite to this edge.

Definition at line 356 of file Mesh.cpp.

00356                              {
00357    Mesh::HalfEdgeIterator eIter = halfEdgeIterator();
00358    for (; !eIter.end(); eIter++) {
00359       Edge * e = eIter.half_edge();
00360       if (e->face) {
00361           double l1 = e->length;
00362           double l2 = e->next->length;
00363           double l3 = e->next->next->length;
00364           e->alphaOposite = acos((l2*l2 + l3*l3 - l1*l1)/(2.0*l2*l3));
00365       }
00366       else {
00367           e->alphaOposite = 0;
00368       }
00369    }
00370    for (eIter.reset(); !eIter.end(); eIter++) {
00371       Edge * e = eIter.half_edge();
00372       e->setTheta(M_PI - e->alphaOposite - e->pair->alphaOposite);
00373    }
00374 }

void Mesh::computeLengths  ) 
 

Compute edge lengths based on vertex positions.

Definition at line 202 of file Mesh.cpp.

00202                           {
00203    for (Mesh::EdgeIterator eIter = edgeIterator(); !eIter.end(); eIter++) {
00204       Edge * e = eIter.edge();
00205       e->length = (e->vertex->p - e->next->vertex->p).abs();
00206       e->pair->length = e->length;
00207    }
00208 }

void Mesh::computeMeshInfo  ) 
 

Computes number of connected components, number of boundary loops and genus of the mesh.

Uses variation of Euler Formula: V - E + F = 2 (c - g) Where V - number of vertices. E - number of edges. F - number of faces. c - number of connected components.

Definition at line 245 of file Mesh.cpp.

00245                            {
00246    cout << "Topological information about the mesh:" << endl;
00247    // Number of boundary loops
00248    Mesh::HalfEdgeIterator hIter = halfEdgeIterator();
00249    for (; !hIter.end(); hIter++) {
00250       hIter.half_edge()->check = false;
00251    }
00252    numBoundaryLoops = 0;
00253    for (hIter.reset(); !hIter.end(); hIter++) {
00254       Edge * e = hIter.half_edge();
00255       if (e->face)
00256           e->check = true;
00257       else if (!e->check) {
00258           Edge * beg = NULL;
00259           while (e != beg) {
00260              if (!beg) beg = e;
00261              check_error(!e, "Building the mesh failed, probem with input format.");
00262              e->check = true;
00263              e = e->next;
00264           }
00265           numBoundaryLoops++;
00266       }
00267    }
00268    cout << "Mesh has " << numBoundaryLoops << " boundary loops." << endl;
00269    // Number of connected components
00270    numConnectedComponents = 0;
00271    Mesh::FaceIterator fIter = faceIterator();
00272    for (; !fIter.end(); fIter++) {
00273       fIter.face()->check = false;
00274    }
00275    stack<Edge *> toVisit;
00276    for (fIter.reset(); !fIter.end(); fIter++) {
00277       if (!fIter.face()->check) {
00278           numConnectedComponents++;
00279           toVisit.push(fIter.face()->edge);
00280           while (!toVisit.empty()) {
00281              Face * fIn = toVisit.top()->face; 
00282              toVisit.pop();
00283              fIn->check = true;     
00284              Face::EdgeAroundIterator iter = fIn->iterator();
00285              for (; !iter.end(); iter++) 
00286                 if (iter.edge()->pair->face && !iter.edge()->pair->face->check)
00287                     toVisit.push(iter.edge()->pair);
00288           }
00289       }
00290    }
00291    cout << "Mesh has " << numConnectedComponents << " connected components." << endl;
00292    // Genus number
00293    check_error(numConnectedComponents == 0, "The mesh read is empty.");
00294    numGenus = 
00295       (1 - (numVertices() - numEdges() + numFaces() + numBoundaryLoops ) / 2) / numConnectedComponents;
00296    cout << "Mesh is genus " << numGenus << "." << endl;
00297 }

bool Mesh::cutAlongEdge Edge forward  ) 
 

Cuts the mesh along single edge while maintaining all the connectivity of the mesh.

Returns false if the mesh is boundary or NULL.

Note that after the mesh the cut is done, the sorting order of edges in the set is not updated. This could be done after all the cuts are performed.

Definition at line 134 of file Mesh.cpp.

00134                                       {
00135    if (!forward) return false;
00136    if (forward->isBoundary()) return false;
00137 
00138    Edge * backward = forward->pair;
00139    
00140    Edge * backwardPair = new Edge();
00141    Edge * forwardPair = new Edge();
00142 
00143    backwardPair->pair = backward;
00144    forwardPair->pair = forward;
00145    backwardPair->assignData(*backward);
00146    forwardPair->assignData(*forward);
00147    
00148    Vertex * v = forward->vertex;
00149    Vertex * endV = backward->vertex;
00150 
00151    if (v->isBoundary()) {
00152       Vertex * newV = addVertex(v->p);
00153       newV->assignData(*v);
00154       Vertex::EdgeAroundIterator aroundV = v->iterator(forward);
00155       do {
00156           aroundV++;
00157           aroundV.vertex() = newV;
00158       }
00159       while (aroundV.edge_out()->pair->face);
00160 
00161       forwardPair->next = aroundV.edge_out()->pair->next;
00162       aroundV.edge_out()->pair->next = backwardPair;
00163 
00164       backwardPair->vertex = newV;
00165       newV->edge = backwardPair;
00166    }
00167    else {
00168       forwardPair->next = backwardPair;
00169       backwardPair->vertex = v;
00170       v->edge = backwardPair;
00171    }
00172 
00173    if (endV->isBoundary()) {
00174       Vertex * newV = addVertex(endV->p);
00175       newV->assignData(*endV);
00176       Vertex::EdgeAroundIterator aroundV = endV->iterator(backward);
00177       do {
00178           aroundV++;
00179           aroundV.vertex() = newV;
00180       }
00181       while (aroundV.edge_out()->pair->face);
00182 
00183       backwardPair->next = aroundV.edge_out()->pair->next;
00184       aroundV.edge_out()->pair->next = forwardPair;
00185 
00186       forwardPair->vertex = newV;
00187       newV->edge = forwardPair;
00188    }
00189    else {
00190       backwardPair->next = forwardPair;
00191       forwardPair->vertex = endV;
00192       endV->edge = forwardPair;
00193    }
00194 
00195    forward->pair = forwardPair;
00196    backward->pair = backwardPair;
00197 
00198    return (addEdge(forwardPair) && addEdge(backwardPair));
00199 }

EdgeIterator Mesh::edgeIterator  )  [inline]
 

Definition at line 277 of file Mesh.h.

00277 {return EdgeIterator(&edges);}

Face* Mesh::faceAt int  i  )  [inline]
 

Definition at line 82 of file Mesh.h.

00082 {return faces[i];}

FaceIterator Mesh::faceIterator  )  [inline]
 

Definition at line 274 of file Mesh.h.

00274 {return FaceIterator(&faces);}

void Mesh::finishMesh  )  [inline]
 

Definition at line 116 of file Mesh.h.

00116                      {
00117       linkBoundary();
00118       checkManifold();
00119       checkVertexConection();
00120       std::cout << "*--------------------*" << std::endl;               
00121       std::cout << "* Faces:    " << numFaces() << std::endl;           
00122       std::cout << "* Edges:    " << numEdges() << std::endl;           
00123       std::cout << "* Vertices: " << numVertices() << std::endl;                 
00124       std::cout << "*--------------------*\n" << std::endl;             
00125    }

HalfEdgeIterator Mesh::halfEdgeIterator  )  [inline]
 

Definition at line 276 of file Mesh.h.

00276 {return HalfEdgeIterator(&edges);}

void Mesh::linkBoundary  ) 
 

Called after the mesh is created to link boundary edges.

Definition at line 211 of file Mesh.cpp.

00211                         {
00212    HalfEdgeIterator hIter = halfEdgeIterator();
00213 
00214    for (; !hIter.end(); hIter++) {
00215       if (!hIter.half_edge()->face) 
00216           hIter.half_edge()->vertex->edge = hIter.half_edge();
00217    }
00218 
00219    VertexIterator vIter = vertexIterator();
00220    Edge *next, *beg;
00221    while (!vIter.end()) {
00222       if (vIter.vertex()->isBoundary()) {
00223           beg = vIter.vertex()->edge;
00224           next = beg;
00225           while (beg->pair->face)
00226              beg = beg->pair->next;
00227           beg = beg->pair;
00228           beg->next = next;
00229           numBoundaryVertices++;
00230       }
00231       vIter++;
00232    }
00233 
00234 }

int Mesh::numBoundary  )  [inline]
 

Definition at line 87 of file Mesh.h.

00087 { return numBoundaryVertices;  }

int Mesh::numEdges  )  [inline]
 

Definition at line 86 of file Mesh.h.

00086 { return (int)edges.size()/2;  }

int Mesh::numFaces  )  [inline]
 

Definition at line 84 of file Mesh.h.

00084 { return (int)faces.size();    }

int Mesh::numVertices  )  [inline]
 

Definition at line 85 of file Mesh.h.

00085 { return (int)vertices.size(); }

void Mesh::readCON const char *  conn_file  ) 
 

Loads mesh from con (connectivity and edge length) file.

Format for CON file is

int (number of vertices)

int (number of faces)

f int int int

double double double

f int int int

double double double

Where first double in each line if edge length from first vertex to second one, second double is edge length from second vertex to the third one, and the third double is an edge length from third vertex to the first one.

Definition at line 528 of file Mesh.cpp.

00528                                          {
00529    string front;
00530    string v = "v", f = "f";
00531    Vector3 vert;
00532    vector<int> verts;
00533    int id;
00534 
00535    ifstream in(conn_file);
00536 
00537    check_error(!in, "Cannot find input obj file.");
00538 
00539    int NumFaces, NumVertices;
00540 
00541    in >> NumVertices;
00542    in >> NumFaces;
00543 
00544    for (int i = 0; i < NumVertices; i++) {
00545       addVertex(vert);
00546    }
00547    while(!in.eof() || in.peek() != EOF) {
00548       in >> ws;
00549       if (in.eof() || in.peek() == EOF)
00550           break;
00551       if (in.peek() == '#') {
00552           in.ignore(300, '\n');
00553       }
00554       else {
00555           in >> front;
00556           if (front == f) {
00557              verts.clear();
00558              
00559              for (int i = 0; i < 3; i++) {
00560                 in >> id;
00561                 check_error(id > numVertices(), "Problem with input CON file.");
00562                 verts.push_back(id-1);
00563              }
00564              in.clear(in.rdstate() & ~ios::failbit);
00565              Face * f = addFace(verts);
00566 
00567              for (Face::EdgeAroundIterator e = f->iterator(); !e.end(); e++) {
00568                 in >> e.edge()->length;
00569              }
00570           }
00571           else {
00572              string line;
00573              getline(in, line);
00574              cout << "Warning, line: " << line << " ignored." << endl;  
00575           }
00576       }
00577    }
00578 
00579    in.close();
00580    // Finnish building the mesh, should be called after each parse.
00581    finishMesh();
00582 }

void Mesh::readCONE_VERT const char *  vert_file  ) 
 

Reads cone singularities allowed by the user.

Format of the file is list of follwing lines:

vertex_id min_val_for_singularity max_val_for_singularity

Values for singularities are expected as multiples of Pi. Minimum and maximum values for singularities can be equal.

Definition at line 684 of file Mesh.cpp.

00684                                                {
00685    ifstream in(vert_file);
00686    check_error(!in, "Cannot find input file for cone singularities.");
00687 
00688    int id = 0;
00689    double minC = 0, maxC = 0;
00690 
00691    while (in >> id) {
00692       in >> minC >> maxC;
00693       if ((id < 0) || (id >= numVertices()))
00694           cout << "ID of a vertex in the cone singularities file is out of bounds." << endl;
00695       else {
00696           id--;
00697          double valenceAlow = (double)vertices[id]->getValence();
00698           check_warn ( maxC <=0, "Invalid cone angle. Cone angle read is less or equal to zero.");
00699           check_warn ( minC >= valenceAlow, 
00700              "Invalid cone angle. Cone angle read is greater or equal to what valence of vertex allows.");
00701           vertices[id]->min_cone_angle = minC;
00702           vertices[id]->max_cone_angle = maxC;
00703           vertices[id]->constrained = true;
00704       }
00705    }
00706 }

void Mesh::readCUT_EDGES const char *  edge_file  ) 
 

Reads edge cuts from the input file and cuts the mesh over those edges.

Format of the file is list of the follwing lines:

vert_from_id vert__to_id face

The information in the file is somewhat redundant, but as we allow for non-regular meshes, there are might be two half edges with same end points).

After the mesh is cut it should be a set of developable surfaces, so that UV coordinates can be assigned properly.

Definition at line 624 of file Mesh.cpp.

00624                                                {
00625    ifstream in(edge_file);
00626    check_error(!in, "Cannot find input file for edge cuts.");
00627 
00628    vector<Edge *> edges_to_cut;
00629 
00630    int i, j, f;
00631    while (in >> i) {
00632       in >> j >> f;
00633 
00634       if ((i < 0) || (i >= numVertices()) || (j < 0) || (j >= numVertices()))
00635           cout << "ID of a vertex in the edges to cut file is out of bounds." << endl;
00636       else {
00637 
00638           i--; j--; f--;
00639    
00640           Edge eTmp;
00641          eTmp.vertex = vertices[i];          
00642           Edge eTmpPair;
00643           eTmpPair.vertex = vertices[j];
00644          eTmp.pair = &eTmpPair;
00645          eTmpPair.pair = &eTmp;
00646 
00647          Edge * e = NULL;
00648           Mesh::EdgeSet::iterator eIn = edges.find(&eTmp);
00649           if (eIn != edges.end())
00650              e = *eIn;
00651           while (eIn != edges.end()) {
00652              if ((*eIn)->face && (*eIn)->face->ID == f) {
00653                 e = *eIn;
00654                 break;
00655              }
00656              eIn++;
00657           }
00658           if (e)
00659              edges_to_cut.push_back(e);
00660       }
00661    }
00662 
00663    while (!edges_to_cut.empty()) {
00664       Edge * e = edges_to_cut.back();
00665       if (e) {
00666              cutAlongEdge(e);
00667       }
00668       edges_to_cut.pop_back();
00669    }
00670 
00671    EdgeSet newedges(edges.begin(), edges.end());
00672    edges = newedges;
00673 }

void Mesh::readOBJ const char *  obj_file  ) 
 

Loads mesh from obj file.

Standard format for OBJ file is

v double double double

v double double double

f int int int

f int int int

Files with vt tags also can be parsed

Definition at line 390 of file Mesh.cpp.

00390                                         {
00391    string front;
00392    string v = "v", vt = "vt", f = "f";
00393    Vector3 vert;
00394    vector<int> verts;
00395    vector<Vector3> uvVec;
00396    vector<int> uvs;
00397    char etc;
00398    int id;
00399 
00400    ifstream in(obj_file);
00401 
00402    check_error(!in, "Cannot find input obj file.");
00403 
00404    bool hasUV = false;
00405 
00406    while(!in.eof() || in.peek() != EOF) {
00407       in >> ws;
00408       if (in.eof() || in.peek() == EOF)
00409           break;
00410       if (in.peek() == '#') {
00411           in.ignore(300, '\n');
00412       }
00413       else {
00414           in >> front;
00415           if (front == v) {
00416              in >> vert.x() >> vert.y() >> vert.z();
00417              addVertex(vert);
00418           }
00419           else if (front == vt){
00420              in >> vert.x() >> vert.y();
00421              vert.z() = 0;
00422              uvVec.push_back(vert);
00423              hasUV = true;
00424           }
00425           else if (front == f) {
00426              verts.clear();
00427              uvs.clear();
00428              while (in >> id) {
00429 
00430                 check_error(id > numVertices(), "Problem with input OBJ file.");
00431 
00432                 verts.push_back(id-1);
00433                 bool vtNow = true;
00434                 if (in.peek() == '/'){
00435                     in >> etc;
00436                     if (in.peek() != '/') {
00437                        in >> id;
00438                        check_warn(id > numVertices(), "Texture coordinate index is greater then number of vertices.");
00439                        if (id < numVertices() && hasUV) {
00440                            uvs.push_back(id-1);
00441                            vtNow = false;
00442                        }
00443                     }
00444                 }
00445                 if (in.peek() == '/'){
00446                     int tmp;
00447                     in >> etc;
00448                     in >> tmp;
00449                 }
00450                 if (hasUV && vtNow) {
00451                     uvs.push_back(id-1);
00452                 }
00453              }
00454              in.clear(in.rdstate() & ~ios::failbit);
00455              Face * f = addFace(verts);
00456 
00457              if (hasUV && uvs.size() != 0){
00458                 int k = 0;
00459                 for (Face::EdgeAroundIterator e = f->iterator(); !e.end(); e++, k++)
00460                     e.vertex()->uv = uvVec[uvs[k]];
00461              }
00462           }
00463           else {
00464              string line;
00465              getline(in, line);
00466              cout << "Warning, line: " << line << " ignored." << endl;  
00467           }
00468       }
00469    }
00470 
00471    in.close();
00472 
00473    // Finnish building the mesh, should be called after each parse.
00474    finishMesh();
00475 }

Vertex* Mesh::vertexAt int  i  )  [inline]
 

Definition at line 81 of file Mesh.h.

00081 {return vertices[i];}

VertexIterator Mesh::vertexIterator  )  [inline]
 

Definition at line 275 of file Mesh.h.

00275 {return VertexIterator(&vertices);}

void Mesh::writeCON const char *  conn_file  ) 
 

Write out the result parameterization in "connectivity" format.

The edge lengths in the result file correspond to edge lengths of the final parameterization.

Definition at line 588 of file Mesh.cpp.

00588                                           {
00589    ofstream out(conn_file);
00590    check_error (!out, "Cannot find output file.");
00591 
00592    out << numVertices() << endl;
00593    out << numFaces() << endl;
00594 
00595    Mesh::FaceIterator fItr = faceIterator();
00596    for (fItr.reset(); !fItr.end(); fItr++) {
00597       Face::EdgeAroundIterator around = fItr.face()->iterator();
00598       out << "f";
00599       for ( ; !around.end(); around++)
00600           out << " " << (around.vertex()->ID + 1);
00601       out << endl;
00602 
00603       for (around.reset() ; !around.end(); around++) 
00604           out << " " << setprecision(8) << around.edge()->length;
00605       out << endl;
00606    }
00607 
00608    out.close();
00609 }

void Mesh::writeOBJ const char *  obj_file  ) 
 

Definition at line 478 of file Mesh.cpp.

00478                                          {
00479    ofstream out(obj_file);
00480    check_error (!out, "Cannot find output file.");
00481 
00482    Mesh::VertexIterator vItr = vertexIterator();
00483    for (vItr.reset(); !vItr.end(); vItr++)
00484       out << "v " << vItr.vertex()->p << endl;
00485 
00486    for (vItr.reset(); !vItr.end(); vItr++)
00487       out << "vt " << vItr.vertex()->uv.x() << " " << vItr.vertex()->uv.y() << endl;
00488 
00489    Mesh::FaceIterator fItr = faceIterator();
00490    for (fItr.reset(); !fItr.end(); fItr++) {
00491       Face::EdgeAroundIterator around = fItr.face()->iterator();
00492       out << "f";
00493       for ( ; !around.end(); around++)
00494           out << " " << (around.vertex()->ID + 1) << "/" << (around.vertex()->ID + 1);
00495       out << endl;
00496    }
00497 }

void Mesh::writeVT const char *  vt_file  ) 
 

Definition at line 500 of file Mesh.cpp.

00500                                        {
00501    ofstream out(vt_file);
00502    check_error (!out, "Cannot find output file.");
00503 
00504    Mesh::VertexIterator vItr = vertexIterator();
00505    for (vItr.reset(); !vItr.end(); vItr++)
00506       out << "vt " << vItr.vertex()->uv.x() << " " << vItr.vertex()->uv.y() << endl;
00507 }


Member Data Documentation

std::multiset<Edge*, Mesh::edge_comp> Mesh::edges [private]
 

Definition at line 48 of file Mesh.h.

std::vector<Face *> Mesh::faces [private]
 

Definition at line 47 of file Mesh.h.

int Mesh::numBoundaryLoops
 

Number of boundary loops in the mesh.

Definition at line 56 of file Mesh.h.

int Mesh::numBoundaryVertices
 

Number of vertices (or also edges) at the boundary of the mesh.

Definition at line 53 of file Mesh.h.

int Mesh::numConnectedComponents
 

Number of connected components.

Definition at line 58 of file Mesh.h.

int Mesh::numGenus
 

Genus of the mesh.

Definition at line 61 of file Mesh.h.

std::vector<Vertex *> Mesh::vertices [private]
 

Definition at line 46 of file Mesh.h.


The documentation for this class was generated from the following files:
Generated on Sat Jun 3 13:33:43 2006 for CirclePatterns by  doxygen 1.4.5