Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ShMeshImpl.hpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory
00004 // Project administrator: Michael D. McCool
00005 // Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
00006 //          Michael D. McCool
00007 // 
00008 // This software is provided 'as-is', without any express or implied
00009 // warranty. In no event will the authors be held liable for any damages
00010 // arising from the use of this software.
00011 // 
00012 // Permission is granted to anyone to use this software for any purpose,
00013 // including commercial applications, and to alter it and redistribute it
00014 // freely, subject to the following restrictions:
00015 // 
00016 // 1. The origin of this software must not be misrepresented; you must
00017 // not claim that you wrote the original software. If you use this
00018 // software in a product, an acknowledgment in the product documentation
00019 // would be appreciated but is not required.
00020 // 
00021 // 2. Altered source versions must be plainly marked as such, and must
00022 // not be misrepresented as being the original software.
00023 // 
00024 // 3. This notice may not be removed or altered from any source
00025 // distribution.
00027 #ifndef SHUTIL_SHMESHIMPL_HPP
00028 #define SHUTIL_SHMESHIMPL_HPP
00029 
00030 #include <iostream>
00031 #include <string>
00032 #include <map>
00033 #include "ShError.hpp"
00034 #include "ShException.hpp"
00035 #include "ShDebug.hpp"
00036 #include "ShMesh.hpp"
00037 
00038 namespace ShUtil {
00039 
00041 template<typename M>
00042 ShMeshVertex<M>::ShMeshVertex()
00043   : edge(0) {}
00044 
00045 template<typename M>
00046 ShMeshVertex<M>::ShMeshVertex(const ShMeshVertex<M> &other)
00047   : edge(0) {}
00048 
00049 template<typename M>
00050 ShMeshFace<M>::ShMeshFace()
00051   : edge(0) {}
00052 
00053 template<typename M>
00054 ShMeshFace<M>::ShMeshFace(const ShMeshFace<M> &other)
00055   : edge(0) {}
00056 
00058 template<typename M>
00059 ShMeshEdge<M>::ShMeshEdge()
00060   : start(0), end(0), face(0), sym(0), next(0), prev(0) {}
00061 
00062 template<typename M>
00063 ShMeshEdge<M>::ShMeshEdge(const ShMeshEdge<M> &other)
00064   : start(0), end(0), face(0), sym(0), next(0), prev(0) {} 
00065 
00066 template<typename M>
00067 void ShMeshEdge<M>::setLinks(Vertex *s, Vertex *e, Face *f,
00068     Edge *next, Edge *prev, Edge *sym) {
00069   // TODO Figure out what to do here instead of shellacking
00070   // the user with a dumb error message.
00071   if(start || end) {
00072     SH_DEBUG_WARN("Changing start/end vertex of an edge.  "
00073       << "This is probably not a good idea.");
00074   }
00075 
00076   start = s;
00077   end = e;
00078   face = f;
00079   setNext(next);
00080   setPrev(prev);
00081   setSym(sym);
00082 } 
00083 
00084 template<typename M>
00085 void ShMeshEdge<M>::setNext(Edge *n) {
00086   if( next ) next->prev = 0;
00087   next = n;
00088   if( next ) next->prev = reinterpret_cast<Edge*>(this);
00089 }
00090 
00091 template<typename M>
00092 void ShMeshEdge<M>::setPrev(Edge *p) {
00093   if( prev ) prev->next = 0;
00094   prev = p;
00095   if( prev ) prev->next = reinterpret_cast<Edge*>(this);
00096 }
00097 
00098 template<typename M>
00099 void ShMeshEdge<M>::setSym(Edge *e) {
00100   if( sym ) sym->sym = 0;
00101   sym = e;
00102   if( sym ) sym->sym = reinterpret_cast<Edge*>(this);
00103 }
00104 
00105 /* ShMesh method definitions */
00106 template<typename M>
00107 ShMesh<M>::ShMesh() {}
00108 
00109 template<typename M>
00110 ShMesh<M>::ShMesh(const ShMesh<M> &other) {
00111   *this = other;
00112 }
00113 
00114 template<typename M>
00115 ShMesh<M>::~ShMesh() {
00116   clear();
00117 }
00118 
00119 template<typename M>
00120 ShMesh<M>& ShMesh<M>::operator=(const ShMesh<M> &other) {
00121   // TODO switch to hash_maps for O(V + E + F) runtime instead of
00122   // O(VlogV + ElogE + FlogF) run-time.
00123   VertexMap vmap;
00124   EdgeMap emap;
00125   FaceMap fmap;
00126 
00127   SH_DEBUG_WARN("Assignment");
00128   clear();
00129 
00130   // mappings for null pointers
00131   vmap[0] = 0;
00132   emap[0] = 0;
00133   fmap[0] = 0;
00134 
00135   // make copies
00136   for(typename EdgeSet::const_iterator J = other.edges.begin(); J != other.edges.end(); ++J) {
00137     Edge* newedge = new Edge(**J); 
00138     edges.insert(newedge);
00139     emap[*J] = newedge; 
00140   }
00141 
00142   for(typename VertexSet::const_iterator I = other.verts.begin(); I != other.verts.end(); ++I) {
00143     Vertex* newvert = new Vertex(**I); 
00144     verts.insert(newvert);
00145     vmap[*I] = newvert;
00146     newvert->edge = emap[(*I)->edge];
00147   }
00148 
00149   for(typename FaceSet::const_iterator K = other.faces.begin(); K != other.faces.end(); ++K) {
00150     Face* newface = new Face(**K); 
00151     faces.insert(newface);
00152     fmap[*K] = newface; 
00153     newface->edge = emap[(*K)->edge]; 
00154   }
00155 
00156   for(typename EdgeSet::const_iterator J = other.edges.begin(); J != other.edges.end(); ++J) {
00157     Edge *e = emap[*J];
00158     e->start = vmap[(*J)->start]; 
00159     e->end = vmap[(*J)->end]; 
00160     e->face = fmap[(*J)->face]; 
00161     e->sym = emap[(*J)->sym]; 
00162     e->prev = emap[(*J)->prev]; 
00163     e->next  = emap[(*J)->next]; 
00164     m_incidences.insert(Incidence(e->start, e));
00165   }
00166 
00167   return *this;
00168 }
00169 
00170 template<typename M>
00171 void ShMesh<M>::clear() {
00172   for(typename VertexSet::iterator I = verts.begin(); I != verts.end(); ++I) {
00173     delete (*I);
00174   }
00175   verts.clear();
00176 
00177   for(typename FaceSet::iterator K = faces.begin(); K != faces.end(); ++K) {
00178     delete (*K);
00179   }
00180   faces.clear();
00181 
00182   for(typename EdgeSet::iterator J = edges.begin(); J != edges.end(); ++J) {
00183     delete (*J);
00184   }
00185   edges.clear();
00186 
00187   m_incidences.clear();
00188 }
00189 
00190 template<typename M>
00191 typename ShMesh<M>::Face* 
00192 ShMesh<M>::addFace(const typename ShMesh<M>::VertexList &vl) {
00193   verts.insert(vl.begin(), vl.end());  
00194 
00195   if( vl.size() < 1 ) {
00196     SH::shError(SH::ShException("ShMesh::addFace can only handle faces with >= 1 vertices")); 
00197   }
00198   Face *newf = new Face();
00199   faces.insert(newf);
00200 
00201   Edge *newe = 0, *olde = 0;
00202   Vertex *first = vl.front();
00203   for(typename VertexList::const_iterator I = vl.begin(); I != vl.end();) {
00204     Vertex *start = *(I++);
00205     Vertex *end = (I == vl.end() ? first : *I); 
00206 
00207     SH_DEBUG_ASSERT(start);
00208 
00209     newe = new Edge();
00210     newe->setLinks(start, end, newf, 0, olde, 0);
00211     olde = newe;
00212 
00213     if( !newf->edge ) newf->edge = newe; // assign first edge to newf->edge
00214     insertHalfEdge(newe);
00215   }
00216   newf->edge->setPrev(newe); // close the loop
00217   return newf;
00218 }
00219 
00220 
00221 template<typename M>
00222 void ShMesh<M>::removeFace(Face *f) {
00223   Edge *olde, *e;
00224   e = f->edge;
00225   //TODO this may fail if != is redefined to 
00226   //access pointer contents 
00227   //In that case, might need to store a list of edges to be deleted
00228   //instead of deleting as we traverse the next pointers...
00229   do {
00230     olde = e;
00231     e = e->next;
00232     removeHalfEdge(e);
00233   } while( e != f->edge );
00234   faces.erase(f);
00235   delete f;
00236 }
00237 
00238 template<typename M>
00239 template<typename VertLess>
00240 void ShMesh<M>::mergeVertices() {
00241   typedef std::map<Vertex*, Vertex*, VertLess> MergedVertMap;
00242   MergedVertMap mvmap;
00243 
00244   // keep only the first occurrence of a similar vertex
00245   for(typename VertexSet::iterator I = verts.begin(); I != verts.end(); ++I) {
00246     if( mvmap.count(*I) == 0 ) mvmap[*I] = *I;
00247   }
00248 
00249   for(typename EdgeSet::iterator J = edges.begin(); J != edges.end(); ++J) {
00250     (*J)->start = mvmap[(*J)->start];
00251     (*J)->end = mvmap[(*J)->end];
00252   }
00253 
00254   /* Go through and erase dead vertices 
00255    * (keep the first occurence which is the mvmap key,
00256    * later occurences can be safely deleted since they do not occur
00257    * as a key or value in the mvmap)*/ 
00258   for(typename VertexSet::iterator I = verts.begin(); I != verts.end();) {
00259     if( mvmap[*I] != *I ) {
00260       typename VertexSet::iterator deadI = I; 
00261       ++I;
00262       Vertex *deadVert = *deadI;
00263       verts.erase(deadI);
00264 
00265       // fix incidence map
00266       IncidenceRange ir = m_incidences.equal_range(deadVert);
00267       for(IncidenceIterator K = ir.first; K != ir.second; ++K) {
00268         m_incidences.insert(Incidence(mvmap[K->first], K->second));
00269       }
00270       m_incidences.erase(ir.first, ir.second);
00271 
00272       delete deadVert;
00273     } else {
00274       ++I;;
00275     }
00276   }
00277 }
00278 
00279 template<typename M>
00280 void ShMesh<M>::mergeEdges() {
00281   typedef std::map<Vertex*, std::map<Vertex*, Edge*> > EdgeMatchMap;
00282 
00283   EdgeMatchMap edgeMatch;
00284 
00285   for(typename EdgeSet::iterator J = edges.begin(); J != edges.end(); ++J) {
00286     Edge *e = (*J);
00287     Edge *match = edgeMatch[e->end][e->start]; 
00288 
00289     if(match) match->setSym(e);
00290 
00291     if( edgeMatch[e->start][e->end] != 0 ) {
00292       SH_DEBUG_WARN("Duplicate edge found in mesh");
00293     }
00294     edgeMatch[e->start][e->end] = e;
00295   }
00296 }
00297 
00298 template<typename M>
00299 bool ShMesh<M>::earTriangulate() {
00300   bool changed = false;
00301   for(typename FaceSet::iterator I = faces.begin(); I != faces.end(); ++I) {
00302     Edge *e = (*I)->edge;
00303 
00304     if( e->next->next->next == e ) continue;  // ignore 3-sided faces
00305 
00306     changed = true;
00307     if( e->next == e || e->next->next == e ) { // remove 1-sided and 2-sided faces
00308       removeFace(*(I++));
00309       continue;
00310     }
00311 
00312     // triangulate face
00313     Face *lastface = *I;
00314     Edge *e0 = e; // first edge in face
00315     Edge *en = e0->prev; // last edge in face 
00316     for(e = e->next->next; e != en; e = e->next) {
00317       Face *newf = new Face();
00318       newf->edge = e;
00319 
00320       // make edges from e-> start to e0 and e0-> start to e->start
00321       Edge *ee0 = new Edge(*e);
00322       ee0->setLinks(e->start, e0->start, lastface, e->prev->prev, e->prev, 0); 
00323 
00324       Edge *e0e = new Edge(*e0);
00325       e0e->setLinks(e0->start, e->start, newf, e, en, 0); 
00326 
00327       ee0->setSym(e0e);
00328 
00329       insertHalfEdge(ee0);
00330       insertHalfEdge(e0e);
00331       faces.insert(newf);
00332 
00333       lastface = newf;
00334     }
00335     e->face = lastface;
00336   }
00337   return changed;
00338 }
00339 
00340 template<typename M>
00341 void ShMesh<M>::removeHalfEdge(Edge *e) {
00342   edges.erase(e);
00343   e->setNext(0);
00344   e->setPrev(0);
00345   e->setSym(0);
00346 
00347   // Update incidence map and e->start
00348   IncidenceRange ir = m_incidences.equal_range(e->start);
00349   for(IncidenceIterator I = ir.first; I != ir.second; ++I) {
00350     if(I->second == e) {
00351       m_incidences.erase(I);
00352       break;
00353     }
00354   }
00355   if(e->start->edge == e)  {
00356     if(m_incidences.count(e->start) > 0) {
00357       e->start->edge = m_incidences.find(e->start)->second;
00358     } else {
00359       e->start->edge = 0; 
00360     }
00361   }
00362   delete e;
00363 }
00364 
00365 template<typename M>
00366 void ShMesh<M>::insertHalfEdge(Edge *e) {
00367   edges.insert(e);
00368   SH_DEBUG_ASSERT(e->start);
00369   m_incidences.insert(Incidence(e->start, e));
00370 }
00371 
00372 }
00373 
00374 #endif

Generated on Mon Jan 24 18:36:33 2005 for Sh by  doxygen 1.4.1