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

Generated on Wed Jun 15 18:12:40 2005 for Sh by  doxygen 1.4.3-20050530