Main Page   Class Hierarchy   Compound List   File List   Compound Members  

geMeshWingedEdge.cpp

00001 //////////////////////////////////////////////////////////////////////
00002 // Copyright (c) 2002-2003 David Pritchard <drpritch@alumni.uwaterloo.ca>
00003 // 
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License
00006 // as published by the Free Software Foundation; either
00007 // version 2 of the License, or (at your option) any later
00008 // version.
00009 // 
00010 // This program 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
00013 // GNU Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 
00019 #include <freecloth/geom/geMeshWingedEdge.imp.h>
00020 #include <freecloth/base/map>
00021 
00022 ////////////////////////////////////////////////////////////////////////////////
00023 // LOCAL DECLARATIONS
00024 
00025 FREECLOTH_NAMESPACE_START
00026 
00027 ////////////////////////////////////////////////////////////////////////////////
00028 // CLASS GeMeshWingedEdge
00029 
00030 //------------------------------------------------------------------------------
00031 
00032 GeMeshWingedEdge::GeMeshWingedEdge( const RCShdPtr<GeMesh>& mesh )
00033   : _mesh( mesh )
00034 {
00035     DGFX_ASSERT( !mesh.isNull() );
00036     build( *mesh );
00037 }
00038 
00039 //------------------------------------------------------------------------------
00040 
00041 void GeMeshWingedEdge::build( const GeMesh& mesh )
00042 {
00043     typedef std::pair< VertexId, VertexId > VertexIdPair;
00044     typedef std::map< VertexIdPair, HalfEdgeId > EdgeMap;
00045     EdgeMap edgeMap;
00046 
00047     GeMesh::FaceConstIterator fi;
00048     _halfEdges.resize( mesh.getNbFaces() * 3 );
00049 
00050     _vertexHalfEdgeIds.resize( mesh.getNbVertices() );
00051     std::fill(
00052         _vertexHalfEdgeIds.begin(),
00053         _vertexHalfEdgeIds.end(),
00054         HalfEdge::ID_INVALID
00055     );
00056     _faceHalfEdgeIds.resize( mesh.getNbFaces() );
00057     std::fill(
00058         _faceHalfEdgeIds.begin(),
00059         _faceHalfEdgeIds.end(),
00060         HalfEdge::ID_INVALID
00061     );
00062 
00063     HalfEdgeId hid;
00064     FaceId fid;
00065     for (
00066         fi = mesh.beginFace(), hid = 0, fid = 0;
00067         fi != mesh.endFace();
00068         hid += fi->getNbVertices(), ++fi, ++fid
00069     ) {
00070         DGFX_ASSERT( fi->getNbVertices() == 3 );
00071         for ( FaceVertexId fvid = 0; fvid < fi->getNbVertices(); ++fvid ) {
00072             // Next face vertex id
00073             FaceVertexId fvid2 = (fvid + 1) % 3;
00074             // Corresponding vertex ids
00075             VertexId vid = fi->getVertexId( fvid );
00076             VertexId vid2 = fi->getVertexId( fvid2 );
00077             // Corresponding halfedge ids
00078             HalfEdgeId heid = hid + fvid;
00079             HalfEdgeId heid2 = hid + fvid2;
00080 
00081 #if 0
00082             if ( vid == 0 ) {
00083                 std::cout << "Face " << fid
00084                     << " vertex ids " << fi->getVertexId( 0 ) << "," << fi->getVertexId( 1 ) << "," << fi->getVertexId( 2 )
00085                     << " vertices " << fi->getVertex( 0 ) << "," << fi->getVertex( 1 ) << "," << fi->getVertex( 2 )
00086                     << std::endl;
00087             }
00088 #endif
00089             _halfEdges[ heid ] = HalfEdge(
00090                 vid,                    // vertex
00091                 HalfEdge::ID_INVALID,   // twin
00092                 fid,                    // face
00093                 heid2                   // next half-edge
00094             );
00095             _vertexHalfEdgeIds[ vid ] = heid;
00096             _faceHalfEdgeIds[ fid ] = heid;
00097             if ( vid < vid2 ) {
00098                 edgeMap[ VertexIdPair( vid, vid2 ) ] = heid;
00099             }
00100         }
00101     }
00102 
00103     // Make another pass and hook twins up together.
00104     EdgeMap::const_iterator ei;
00105     for (
00106         fi = mesh.beginFace(), hid = 0, fid = 0;
00107         fi != mesh.endFace();
00108         hid += fi->getNbVertices(), ++fi, ++fid
00109     ) {
00110         for ( FaceVertexId fvid = 0; fvid < fi->getNbVertices(); ++fvid ) {
00111             FaceVertexId fvid2 = (fvid + 1) % 3;
00112             VertexId vid = fi->getVertexId( fvid );
00113             VertexId vid2 = fi->getVertexId( fvid2 );
00114             if ( vid > vid2 ) {
00115                 ei = edgeMap.find( VertexIdPair( vid2, vid ) );
00116                 if ( ei != edgeMap.end() ) {
00117                     _halfEdges[ hid + fvid ]._twin = ei->second;
00118                     _halfEdges[ ei->second ]._twin = hid + fvid;
00119                 }
00120             }
00121         }
00122     }
00123 
00124     // Make a final pass and fill in vertex half-edge ids
00125     for (
00126         fi = mesh.beginFace(), hid = 0, fid = 0;
00127         fi != mesh.endFace();
00128         hid += fi->getNbVertices(), ++fi, ++fid
00129     ) {
00130         for ( FaceVertexId fvid = 0; fvid < fi->getNbVertices(); ++fvid ) {
00131             // Corresponding vertex ids
00132             VertexId vid = fi->getVertexId( fvid );
00133             // Corresponding halfedge ids
00134             HalfEdgeId heid = hid + fvid;
00135 
00136             // If there's a half-edge with no twin, then that should be the
00137             // first half-edge used for iterating half-edges about vertex.
00138             if ( ! _halfEdges[ heid ].hasTwin() ) {
00139                 _vertexHalfEdgeIds[ vid ] = heid;
00140             }
00141         }
00142     }
00143 }
00144 
00145 //------------------------------------------------------------------------------
00146 
00147 inline const RCShdPtr<GeMesh>& GeMeshWingedEdge::getMeshPtr() const
00148 {
00149     return _mesh;
00150 }
00151 
00152 
00153 ////////////////////////////////////////////////////////////////////////////////
00154 // CLASS GeMeshWingedEdge::VertexFaceIterator
00155 //
00156 
00157 //------------------------------------------------------------------------------
00158 
00159 GeMeshWingedEdge::VertexFaceIterator::VertexFaceIterator()
00160 {
00161 }
00162 
00163 //------------------------------------------------------------------------------
00164 
00165 GeMeshWingedEdge::VertexFaceIterator::VertexFaceIterator(
00166     const GeMeshWingedEdge& meshwe,
00167     VertexId vertexId,
00168     HalfEdgeId halfEdgeId
00169 ) : _wrapper( meshwe, halfEdgeId ),
00170     _vertexId( vertexId )
00171 {
00172     DGFX_ASSERT(
00173         _wrapper.getOriginVertexId() == _vertexId
00174     );
00175 }
00176 
00177 //------------------------------------------------------------------------------
00178 
00179 GeMeshWingedEdge::VertexFaceIterator::VertexFaceIterator(
00180     const HalfEdgeWrapper& wrapper,
00181     VertexId vertexId
00182 ) : _wrapper( wrapper ),
00183     _vertexId( vertexId )
00184 {
00185 }
00186 
00187 //------------------------------------------------------------------------------
00188 
00189 GeMeshWingedEdge::VertexFaceIterator
00190 GeMeshWingedEdge::VertexFaceIterator::begin(
00191     const GeMeshWingedEdge& meshwe,
00192     VertexId vertexId
00193 ) {
00194     DGFX_ASSERT( vertexId < meshwe._vertexHalfEdgeIds.size() );
00195     // Not adjacent to any edges
00196     if ( meshwe._vertexHalfEdgeIds[ vertexId ] == ID_INVALID ) {
00197         return end( meshwe, vertexId );
00198     }
00199     return VertexFaceIterator(
00200         meshwe, vertexId, meshwe._vertexHalfEdgeIds[ vertexId ]
00201     );
00202 }
00203 
00204 //------------------------------------------------------------------------------
00205 
00206 GeMeshWingedEdge::VertexFaceIterator&
00207 GeMeshWingedEdge::VertexFaceIterator::operator++()
00208 {
00209     DGFX_ASSERT( _vertexId != ID_INVALID );
00210 
00211     bool atEnd = false;
00212     if ( _wrapper.getOriginVertexId() != _vertexId ) {
00213         atEnd = true;
00214     }
00215     else if ( _wrapper.getPrevHalfEdge().hasTwin() ) {
00216         _wrapper._halfEdgeId = _wrapper.getPrevHalfEdge().getTwinHalfEdgeId();
00217         DGFX_ASSERT( _wrapper.getOriginVertexId() == _vertexId );
00218         atEnd = (
00219             _wrapper._halfEdgeId ==
00220             _wrapper.getMeshWE()._vertexHalfEdgeIds[ _vertexId ]
00221         );
00222     }
00223     else {
00224         atEnd = true;
00225     }
00226     if ( atEnd ) {
00227         _vertexId = ID_INVALID;
00228         _wrapper._halfEdgeId = ID_INVALID;
00229     }
00230     else {
00231         _faceWrapper = _wrapper.getFace();
00232     }
00233     return *this;
00234 }
00235 
00236 //------------------------------------------------------------------------------
00237 
00238 GeMeshWingedEdge::VertexFaceIterator
00239 GeMeshWingedEdge::VertexFaceIterator::operator++( int )
00240 {
00241     VertexFaceIterator copy( *this );
00242     operator++();
00243     return copy;
00244 }
00245 
00246 
00247 ////////////////////////////////////////////////////////////////////////////////
00248 // GLOBAL FUNCTIONS
00249 //
00250 
00251 //------------------------------------------------------------------------------
00252 
00253 std::ostream& operator<< ( std::ostream& os, const GeMeshWingedEdge& m )
00254 {
00255     os << "GeMeshWingedEdge" << std::endl;
00256     GeMeshWingedEdge::HalfEdgeIterator hei;
00257     UInt32 i;
00258     for( hei = m.beginHalfEdge(), i = 0; hei != m.endHalfEdge(); ++hei, ++i ) {
00259         os << "[" << i << "] " << *hei << std::endl;
00260     }
00261     return os;
00262 }
00263 
00264 //------------------------------------------------------------------------------
00265 
00266 std::ostream& operator<< (
00267     std::ostream& os,
00268     const GeMeshWingedEdge::HalfEdgeWrapper& he
00269 ) {
00270     os << "he( origin_vid=" << he.getOriginVertexId();
00271     os << " twin_heid=";
00272     if ( he.hasTwin() ) {
00273         os << he.getTwinHalfEdgeId();
00274     }
00275     else {
00276         os << "(nil)";
00277     }
00278     os << " face_id=" << he.getFaceId();
00279     os << " next_heid=" << he.getNextHalfEdgeId();
00280 
00281     return os;
00282 }
00283 
00284 ////////////////////////////////////////////////////////////////////////////////
00285 // TEMPLATE INSTANTIATIONS
00286 //
00287 
00288 template class GeMeshWingedEdge::EdgeIteratorBase<false>;
00289 template class GeMeshWingedEdge::EdgeIteratorBase<true>;
00290 template class GeMeshWingedEdge::VertexEdgeIteratorBase<false>;
00291 template class GeMeshWingedEdge::VertexEdgeIteratorBase<true>;
00292 
00293 FREECLOTH_NAMESPACE_END

Generated on Wed Apr 23 15:58:46 2003 for Freecloth by doxygen1.3-rc3