Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | 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 Oct 18 14:17:39 2004 for Sh by doxygen 1.3.7