ShMeshImpl.hpp

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

Generated on Wed Nov 9 15:29:37 2005 for Sh by  doxygen 1.4.5