00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <algorithm>
00022 #include <float.h>
00023 #include "polyhedron.h"
00024 #include "polyhedron_gl.h"
00025 #include "util.h"
00026
00027 using namespace std;
00028 using namespace HE;
00029 using namespace Geometry;
00030
00031 Polyhedron::Polyhedron(const char* filename)
00032 : _gl(0), _type(FT_OFF)
00033 {
00034 if (!load(filename))
00035 throw HE_exception("Cannot load input file", filename);
00036 }
00037
00038 Polyhedron::Polyhedron()
00039 : _gl(0), _type(FT_OFF)
00040 {
00041 }
00042
00043 Polyhedron::Polyhedron(const std::vector<Vertex*>& verts, const std::vector<std::vector<int> >& faces)
00044 : _gl(0), _type(FT_OFF)
00045 {
00046 _vertices.resize(verts.size());
00047 for (unsigned v=0 ; v<verts.size() ; v++)
00048 _vertices[v] = new Vertex(verts[v]->position(), v);
00049 loadFaces( faces );
00050 }
00051
00052 Polyhedron::~Polyhedron()
00053 {
00054 for (face_iterator fit=fBegin() ; fit!=fEnd() ; ++fit)
00055 delete *fit;
00056 _faces.clear();
00057
00058 for (edge_iterator eit=eBegin() ; eit!=eEnd() ; ++eit)
00059 delete *eit;
00060 _halfEdges.clear();
00061
00062 for (vertex_iterator vit=vBegin() ; vit!=vEnd() ; ++vit)
00063 delete *vit;
00064 _vertices.clear();
00065 }
00066
00067
00072 Polyhedron* Polyhedron::refine() const
00073 {
00074 Polyhedron* P = new Polyhedron;
00075 cerr << P->numFaces() << " faces in initial mesh\n";
00076 P->_vertices.reserve(_vertices.size() + _halfEdges.size()/2 + 1);
00077 for (unsigned i=0 ; i<_vertices.size() ; i++)
00078 P->_vertices.push_back( new Vertex(_vertices[i]->position(), _vertices[i]->index()) );
00079
00080 map<const HalfEdge*, const Vertex*> edge2midpoints;
00081 for (const_face_iterator it=fBegin() ; it!=fEnd() ; ++it)
00082 {
00083 const Face* f = *it;
00084
00085 if (f->hole())
00086 continue;
00087 const HalfEdge* sentinel = f->edge();
00088 const HalfEdge* he = sentinel;
00089 const Vertex* V(0), *V2(0);
00090 vector<int> verts;
00091
00092 do
00093 {
00094 if (edge2midpoints.end() == edge2midpoints.find(he))
00095 {
00096 V2 = P->addVertex(he->midpoint());
00097 edge2midpoints[he] = edge2midpoints[he->twin()] = V2;
00098 }
00099 else
00100 {
00101 V2 = edge2midpoints[he];
00102 }
00103 verts.push_back(V2->index());
00104
00105
00106 if (V)
00107 {
00108 Face* f2 = P->addFace(V->index(), he->src()->index(), V2->index());
00109 f2->hole(f->hole());
00110 }
00111
00112 V = V2;
00113 he = he->next();
00114 } while (he != sentinel) ;
00115
00116 assert(verts.size() >= 3);
00117 Face* f2 = P->addFace(verts.back(), sentinel->src()->index(), verts.front());
00118 f2->hole(f->hole());
00119 f2 = P->addFace(verts);
00120 f2->hole(f->hole());
00121 }
00122
00123 cerr << P->numFaces() << " in new Polyhedron\n";
00124 P->finalize();
00125 cerr << P->numFaces() << " in refined Polyhedron\n";
00126 cerr << numVertices() << " vertices in original Polyhedron\n";
00127 cerr << P->numVertices() << " vertices in refined Polyhedron\n";
00128 return P;
00129 }
00130
00131
00132 Vertex* Polyhedron::addVertex(const Vector3Df& v)
00133 {
00134 Vertex* V = new Vertex(v, _vertices.size());
00135 _vertices.push_back(V);
00136 return V;
00137 }
00138
00139 void Polyhedron::clearData()
00140 {
00141 _faces.clear();
00142 _holes.clear();
00143 _halfEdges.clear();
00144 _vertices.clear();
00145 }
00146
00147 bool Polyhedron::load(const char* filename)
00148 {
00149 filetype_e format = fileFormat(filename);
00150
00151 clearData();
00152 bool success = false;
00153 switch( format )
00154 {
00155 case FT_PLY_ASCII:
00156 success = readPly(filename);
00157 type(FT_PLY_ASCII);
00158 break;
00159
00160 case FT_OFF:
00161 success = readOff(filename);
00162 type(FT_OFF);
00163 break;
00164
00165 case FT_TRI:
00166 success = readTri(filename);
00167 type(FT_TRI);
00168 break;
00169
00170 case FT_PLY_BIN:
00171 throw HE_exception("Cannot read binary PLY format yet", filename);
00172 type(FT_PLY_BIN);
00173 break;
00174
00175 case FT_OBJ:
00176 throw HE_exception("Cannot read OBJ format yet", filename);
00177 type(FT_OBJ);
00178 break;
00179
00180 case FT_NONE:
00181 throw HE_exception("Unknown input file format", filename);
00182 type(FT_NONE);
00183 break;
00184 }
00185
00186 packVertices();
00187 return success;
00188 }
00189
00190
00191 void Polyhedron::finalize()
00192 {
00193 assert(check(false));
00194
00195
00196 map<pair<int,int>, HalfEdge*> connections;
00197 for (edge_iterator it=eBegin() ; it!=eEnd() ; ++it)
00198 {
00199 HalfEdge* he = *it;
00200 if (!he->twin())
00201 {
00202 int a = he->prev()->dst()->index();
00203 int b = he->dst()->index();
00204 pair<int,int> idx(a, b);
00205 if (connections.end() != connections.find(idx))
00206 throw HE_exception("Repeated half-edge: This is a non-manifold mesh, not supported by half-edge data structures.");
00207
00208 pair<int,int> idx2(b, a);
00209 map<pair<int,int>, HalfEdge*>::iterator cit = connections.find(idx2);
00210 if (connections.end() == cit)
00211 {
00212 connections[idx] = he;
00213 }
00214 else
00215 {
00216 HalfEdge*& he2 = cit->second;
00217 he->twin(he2);
00218 he2->twin(he);
00219 connections.erase(cit);
00220 }
00221
00222 }
00223 else
00224 {
00225 assert(he->twin()->twin() == he);
00226 }
00227 }
00228
00229 assert(check(false));
00230 closeSurface(connections);
00231 assert(check());
00232 }
00233
00234
00239 void Polyhedron::closeSurface(map<pair<int,int>, HalfEdge*>& connections)
00240 {
00241
00242 map<pair<int,int>, HalfEdge*>& endPoints = connections;
00243 map<int,vector<pair<int,int> > >v2e;
00244 for (map<pair<int,int>, HalfEdge*>::const_iterator it=endPoints.begin() ; it!=endPoints.end() ; ++it)
00245 {
00246 HalfEdge* e = it->second;
00247 assert(!e->twin());
00248
00249 int src = e->prev()->dst()->index();
00250 int dst = e->dst()->index();
00251 pair<int,int> pts(src, dst);
00252 v2e[dst].push_back(pts);
00253 assert(find(v2e[pts.second].begin(), v2e[pts.second].end(), pts) != v2e[pts.second].end());
00254
00255
00256 }
00257
00258
00259 while (!endPoints.empty())
00260 {
00261 map<pair<int,int>, HalfEdge*>::iterator pit = endPoints.begin();
00262 pair<int,int> pts = pit->first;
00263 HalfEdge* e = pit->second;
00264 HalfEdge* e2;
00265 Face* f = new Face(0, true);
00266 _faces.push_back(f);
00267 _holes.insert(f);
00268
00269
00270 int start = pts.second;
00271 int v = start;
00272 vector<HalfEdge*> bdry;
00273 do
00274 {
00275 e2 = new HalfEdge(_vertices[pts.first], f, e, 0);
00276 _halfEdges.push_back(e2);
00277 e->twin(e2);
00278 assert(e2->twin() == e);
00279 assert(e->dst() == e2->src());
00280 assert(e->src() == e2->dst());
00281 bdry.push_back(e2);
00282 assert(endPoints.end() != endPoints.find(pts));
00283 endPoints.erase(pit);
00284 assert(endPoints.end() == endPoints.find(pts));
00285
00286
00287
00288
00289 int idx = pts.first;
00290 pts = v2e[idx].back();
00291 v2e[idx].pop_back();
00292 assert(pts.second == idx);
00293
00294 pit = endPoints.find(pts);
00295 if(endPoints.end() == pit)
00296 break;
00297 assert(pit->first == pts);
00298
00299 e = pit->second;
00300 v = pts.second;
00301 assert(start != v);
00302 } while(start != v);
00303 f->edge(e2);
00304
00305
00306
00307 for (unsigned i=0 ; i<bdry.size() ; i++)
00308 {
00309
00310
00311 bdry[i]->next( bdry[(i+1)%bdry.size()] );
00312 }
00313
00314
00315 #ifndef NDEBUG
00316 for (unsigned i=0 ; i<bdry.size() ; i++)
00317 {
00318 const HalfEdge* e = bdry[i];
00319 const HalfEdge* e2 = e->twin();
00320 assert(e->prev()->dst() == e->src());
00321 assert(e2->prev()->dst() == e2->src());
00322 }
00323 #endif
00324 }
00325 }
00326
00327
00328
00329 HalfEdge* Polyhedron::edge(int from, int to) const
00330 {
00331 return _vertices[from]->edgeTo(to);
00332 }
00333
00334
00335 void Polyhedron::boundingBox(Geometry::Vector3Df& m, Geometry::Vector3Df& M) const
00336 {
00337 m = Vector3Df(FLT_MAX, FLT_MAX, FLT_MAX);
00338 M = -m;
00339
00340
00341 for (const_vertex_iterator vit=vBegin() ; vit!=vEnd() ; ++vit)
00342 {
00343 const Vector3Df& v = (*vit)->position();
00344 for (int i=0 ; i<3 ; i++)
00345 {
00346 if (v[i] > M[i])
00347 M[i] = v[i];
00348 if (v[i] < m[i])
00349 m[i] = v[i];
00350 }
00351 }
00352 }
00353
00354
00355 void Polyhedron::scaleAndCenter(float radius)
00356 {
00357 Geometry::Vector3Df m, M;
00358 boundingBox(m, M);
00359 Geometry::Vector3Df ctr = (m+M) / 2;
00360 float diff = 0;
00361 for (int i=0 ; i<3 ; i++)
00362 {
00363 assert(M[i] >= m[i]);
00364 if (diff < M[i]-m[i])
00365 diff = M[i]-m[i];
00366 }
00367
00368 for (vertex_iterator vit=vBegin() ; vit!=vEnd() ; ++vit)
00369 {
00370 Vector3Df v = (*vit)->position() - ctr;
00371 v *= radius / diff;
00372 (*vit)->position(v);
00373 }
00374
00375 if (_gl)
00376 _gl->recomputeNormals();
00377 }
00378
00379
00380 void Polyhedron::invertNormals()
00381 {
00382
00383 map<const HalfEdge*, HalfEdge*> next;
00384 map<const HalfEdge*, Vertex*> dst;
00385 for (edge_iterator eit=eBegin() ; eit!=eEnd() ; ++eit)
00386 {
00387 HalfEdge* e = *eit;
00388
00389 assert(next.end() == next.find(e->next()));
00390 next[e->next()] = e;
00391
00392 assert(dst.end() == dst.find(e));
00393 dst[e] = e->src();
00394 }
00395
00396
00397 for (edge_iterator eit=eBegin() ; eit!=eEnd() ; ++eit)
00398 {
00399 HalfEdge* e = *eit;
00400 e->next( next[e] );
00401
00402 Vertex* v = e->dst();
00403 e->dst( dst[e] );
00404 v->edge(e);
00405 }
00406
00407 if (_gl)
00408 _gl->recomputeNormals();
00409
00410 assert(check());
00411 }
00412
00413
00414 bool faceIsHole(const Face* f) { return f->hole(); }
00415
00416 int Polyhedron::numHoles() const
00417 {
00418 return count_if(fBegin(), fEnd(), faceIsHole);
00419 }
00420
00421
00422 bool Polyhedron::check(bool holesFilled) const
00423 {
00424 #if 0
00425 for (Polyhedron::const_vertex_iterator it=vBegin() ; it!=vEnd() ; ++it)
00426 {
00427 assert((*it)->edge() != 0);
00428 }
00429 #endif
00430
00431 for (Polyhedron::const_edge_iterator it=eBegin() ; it!=eEnd() ; ++it)
00432 {
00433 if (holesFilled)
00434 {
00435 assert((*it)->twin() != 0);
00436 assert((*it)->twin()->twin() == (*it));
00437 }
00438 assert((*it)->next() != 0);
00439 assert((*it)->face() != 0);
00440 assert((*it)->dst() != 0);
00441 assert(!(*(*it)->dst() == *(*it)->prev()->dst()));
00442
00443
00444 {
00445 set<const HalfEdge*> visited;
00446 const HalfEdge* e = *it;
00447 const HalfEdge* sentinel = e;
00448 do
00449 {
00450 assert(visited.end() == visited.find(e));
00451 visited.insert(e);
00452 e = e->next();
00453 } while(e != sentinel);
00454 }
00455
00456 assert((*it)->prev()->next() == *it);
00457 if (holesFilled)
00458 {
00459 assert((*it)->prev()->dst() == (*it)->src());
00460 }
00461 }
00462
00463 for (Polyhedron::const_face_iterator it=fBegin() ; it!=fEnd() ; ++it)
00464 {
00465 set<const HalfEdge*> visited;
00466 const Face* f = *it;
00467 Face::const_edge_circulator eit = f->begin();
00468 Face::const_edge_circulator sentinel = eit;
00469 do
00470 {
00471 assert(visited.end() == visited.find(*eit));
00472 visited.insert(*eit);
00473 ++eit;
00474 } while(eit != sentinel);
00475 }
00476
00477 return true;
00478 }
00479
00480
00481 void Polyhedron::packVertices()
00482 {
00483 int n = 0;
00484 for (int v=0 ; v<numVertices() ; v++)
00485 {
00486 if (_vertices[v]->edge())
00487 {
00488 _vertices[v]->index(n);
00489 _vertices[n++] = _vertices[v];
00490 }
00491 }
00492
00493
00494 _vertices.resize(n);
00495 }
00496
00497
00498 bool Polyhedron::adjacent(const Vertex* v1, const Vertex* v2) const
00499 {
00500 Vertex::const_edge_circulator eit = v1->begin();
00501 Vertex::const_edge_circulator sentinel = eit;
00502 do
00503 {
00504 if ((*eit)->dst() == v2)
00505 return true;
00506 ++eit;
00507 } while(eit != sentinel);
00508 return false;
00509 }
00510
00511 bool Polyhedron::adjacent(const Face* f1, const Face* f2) const
00512 {
00513 Face::const_edge_circulator eit = f1->begin();
00514 Face::const_edge_circulator sentinel = eit;
00515 do
00516 {
00517 if ((*eit)->twin()->face() == f2)
00518 return true;
00519 ++eit;
00520 } while(eit != sentinel);
00521 return false;
00522 }
00523