Subversion Repositories gelsvn

Rev

Rev 444 | Blame | Last modification | View Log | RSS feed

#ifndef __HMESH_ITERS_H
#define __HMESH_ITERS_H


#if (_MSC_VER >= 1400)
#ifdef _DEBUG

#if (_SECURE_SCL != 0)
#pragma message( "Warning : To use HMesh in debug mode _SECURE_SCL must be defined as 0." )
#endif

#if (_HAS_ITERATOR_DEBUGGING != 0)
#pragma message( "Warning : To use HMesh in debug mode _HAS_ITERATOR_DEBUGGING must be defined as 0." )
#endif

#endif
#endif

#include <list>
#include "CGLA/Vec3f.h"

namespace HMesh
{
                /* A nasty template trick:

                The halfedge data structure is based on pointers. Thus, for instance,
                a halfedge contains pointers to several other halfedges, a face, and
                a vertex. However, the entities (faces, edges, vertices) are stored in
                linked lists. This enables easy insertion and removal, but we would
                like to be able to take the halfedge pointer stored in, say, a 
                halfedge and find the position in the linked list in order to remove the
                halfedge from the list. This is not possible since the list is implemented
                using STL and what we need is really an iterator to the list element
                containing the halfedge.

                The solution is, of course, to store iterators instead of pointers, but
                that solution is problematic because we cannot define an iterator to a 
                list of halfedges in the definition of the halfedge class. The solution
                is to let a template argument define the halfedge iterator type.
                 
                Thus the Iters class instantiates HalfEdge_template with itself while it 
                also defines the required iterators etc. Strange but legal C++.

                This is the best solution I could come up with - since I really wanted 
                to use STL to store the elements. The solution is similar to what is 
                used in CGAL and OpenMesh both of which provided inspiration. */


                /** Type used for the touch variables of halfedges, vertices, and faces.
                                The touch variables are used to contain various data such as counters,
                                indices, flags. In some cases it is useful to touch with the value
                                of a pointer cast to an integer. However, this means that the 
                                integer size must be the same as the pointer size. Using "intptr_t"
                                ensures this. */
                typedef intptr_t TouchType;

                /** \struct Vertex
                 */
                template<class R>
                struct Vertex_template
                {
                                typedef typename R::VertexIter VertexIter;
                                typedef typename R::FaceIter FaceIter;
                                typedef typename R::HalfEdgeIter HalfEdgeIter;

                                /// Constructor, argument is vertex position
                                Vertex_template(const CGLA::Vec3f&);

                                /// Outgoing halfedge
                                HalfEdgeIter he;

                                /// Geometric vertex position
                                CGLA::Vec3f pos;

                                /// General purpose integer. Normally used as index or flag.
                                TouchType touched;
                };

                template<class R>
                struct HalfEdge_template
                {
                                typedef typename R::VertexIter VertexIter;
                                typedef typename R::FaceIter FaceIter;
                                typedef typename R::HalfEdgeIter HalfEdgeIter;

                                /// Constructor
                                HalfEdge_template();

                                /// Vertex pointed to by this halfedge.
                                VertexIter   vert;

                                /// Next halfedge in face loop.
                                HalfEdgeIter next;

                                /// Previous halfedge in face loop.
                                HalfEdgeIter prev;

                                /// Face owning this halfedge
                                FaceIter     face;

                                /// Opposite halfedge
                                HalfEdgeIter opp;

                                /// General purpose integer. Normally used as index or flag.
                                TouchType touched;

                };

                template<class R>
                struct Face_template
                {
                                typedef typename R::VertexIter VertexIter;
                                typedef typename R::FaceIter FaceIter;
                                typedef typename R::HalfEdgeIter HalfEdgeIter;

                                /// Constructor
                                Face_template();

                                /// Last is just some halfedge in the face loop.
                                HalfEdgeIter last;

                                /// General purpose integer. Normally used as index or flag.
                                TouchType touched;
                };

                struct Iters
                {
                                typedef Vertex_template<Iters> V;
                                typedef HalfEdge_template<Iters> HE;
                                typedef Face_template<Iters> F;
        
                                typedef std::list<V> VertexList;
                                typedef std::list<HE> HalfEdgeList;
                                typedef std::list<F> FaceList;

                                typedef VertexList::iterator VertexIter;
                                typedef HalfEdgeList::iterator HalfEdgeIter;
                                typedef FaceList::iterator FaceIter;
                };


        typedef Face_template<Iters> Face;
        typedef HalfEdge_template<Iters> HalfEdge;
        typedef Vertex_template<Iters> Vertex;

        typedef Iters::FaceList FaceList;
        typedef Iters::HalfEdgeList HalfEdgeList;
        typedef Iters::VertexList VertexList;

        typedef Iters::FaceIter FaceIter;
        typedef Iters::HalfEdgeIter HalfEdgeIter;
        typedef Iters::VertexIter VertexIter;

        FaceIter get_null_face_iter();
        
        VertexIter get_null_vertex_iter();
        
        HalfEdgeIter get_null_halfedge_iter();
        

#define NULL_FACE_ITER HMesh::get_null_face_iter() 
#define NULL_HALFEDGE_ITER HMesh::get_null_halfedge_iter() 
#define NULL_VERTEX_ITER HMesh::get_null_vertex_iter()


}
#endif