Subversion Repositories gelsvn

Rev

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

#ifndef __HMESH_HALFEDGEHANDLE_H__
#define __HMESH_HALFEDGEHANDLE_H__

#include "entities.h"
#include "Manifold.h"
#include "VertexHandle.h"
#include "FaceHandle.h"

namespace HMesh
{
    /************************************
    * Forward declarations
    *************************************/
    class HalfEdgeHandle;
    class ConstHalfEdgeHandle;
    class VertexHandle;
    class ConstVertexHandle;
    class Facehandle;
    class ConstFacehandle;

    /************************************
    * HalfEdgeHandle + functions
    *************************************/

    class HalfEdgeHandle
    {
    public:
       HalfEdgeHandle();
       HalfEdgeHandle(Manifold& _m, HalfEdgeIndex _idx);

        /// Get a handle to vertex pointed to by this halfedge
        VertexHandle vert();
        /// Get a handle to the next halfedge in face loop
        HalfEdgeHandle next();
        /// Get a handle to the previous halfedge in face loop
        HalfEdgeHandle prev();
        /// Get a handle to the opposite halfedge
        HalfEdgeHandle opp();
        /// Get a handle to the face this halfedge belongs to
        FaceHandle face();

        /// Get a reference to the halfedge
        HalfEdge& get();

        bool operator==(const HalfEdgeHandle& f) const;
        bool operator!=(const HalfEdgeHandle& f) const;

        void operator++();
        void operator++(int);

        /// Get index of halfedge
        HalfEdgeIndex get_idx() const;
    private:
        friend class ConstHalfEdgeHandle;

        /// ID of halfedge
        HalfEdgeIndex idx;
        /// pointer to manifold storing the halfege
        Manifold* m;
    };
    
    inline HalfEdgeHandle::HalfEdgeHandle()
        : m(NULL), idx(NULL_HIDX)
    {}
    inline HalfEdgeHandle::HalfEdgeHandle(Manifold& _m, HalfEdgeIndex _idx)
        : m(&_m), idx(_idx)
    {} 
    inline VertexHandle HalfEdgeHandle::vert()
    { 
        return VertexHandle(*m, m->halfedges[idx].vert_idx); 
    }
    inline HalfEdgeHandle HalfEdgeHandle::next()
    { 
        return HalfEdgeHandle(*m, m->halfedges[idx].next_idx); 
    }
    inline HalfEdgeHandle HalfEdgeHandle::prev()
    { 
        return HalfEdgeHandle(*m, m->halfedges[idx].prev_idx); 
    }
    inline HalfEdgeHandle HalfEdgeHandle::opp()
    { 
        return HalfEdgeHandle(*m, m->halfedges[idx].opp_idx); 
    }
    inline FaceHandle HalfEdgeHandle::face()
    { 
        return FaceHandle(*m, m->halfedges[idx].face_idx); 
    }
    inline HalfEdge& HalfEdgeHandle::get()
    { 
        return m->halfedges[idx]; 
    }
    inline bool HalfEdgeHandle::operator==(const HalfEdgeHandle& h) const
    { 
        return idx == h.get_idx(); 
    }
    inline bool HalfEdgeHandle::operator!=(const HalfEdgeHandle& h) const
    { 
        return idx != h.get_idx(); 
    }
    inline void HalfEdgeHandle::operator++()
    { 
        do{ 
            ++idx; 
        } 
        while(idx < m->halfedges.full_size() && !m->halfedges.in_use(idx)); 
    }
    inline void HalfEdgeHandle::operator++(int)
    { 
        ++(*this); 
    }
    inline HalfEdgeIndex HalfEdgeHandle::get_idx() const
    { 
        return idx; 
    }

#define NULL_HHANDLE HalfEdgeHandle()

    /************************************
    * ConstHalfEdgeHandle + functions
    *************************************/
    class ConstHalfEdgeHandle
    {
    public:
       ConstHalfEdgeHandle();
       ConstHalfEdgeHandle(const Manifold& _m, HalfEdgeIndex _idx);

       ConstHalfEdgeHandle(const ConstHalfEdgeHandle& che);
       ConstHalfEdgeHandle(const HalfEdgeHandle& he);

       ConstHalfEdgeHandle& operator=(const ConstHalfEdgeHandle& che);
       ConstHalfEdgeHandle& operator=(const HalfEdgeHandle& he);

        /// Get a handle to vertex pointed to by this halfedge
        ConstVertexHandle vert() const;
        /// Get a handle to the next halfedge in face loop
        ConstHalfEdgeHandle next() const;
        /// Get a handle to the previous halfedge in face loop
        ConstHalfEdgeHandle prev() const;
        /// Get a handle to the opposite halfedge
        ConstHalfEdgeHandle opp() const;
        /// Get a handle to the face this halfedge belongs to
        ConstFaceHandle face() const; 

        /// Get a const reference to the halfedge
        const HalfEdge& get() const;

        bool operator==(const ConstHalfEdgeHandle& h) const;
        bool operator!=(const ConstHalfEdgeHandle& h) const;

        void operator++();
        void operator++(int);

        /// Get index of halfedge
        HalfEdgeIndex get_idx() const;
    private:
        /// ID of halfedge
        HalfEdgeIndex idx;
        /// pointer to manifold storing the halfege
        const Manifold* m;
    };
#define NULL_CHHANDLE ConstHalfEdgeHandle()

    inline ConstHalfEdgeHandle::ConstHalfEdgeHandle()
        : m(NULL), idx(NULL_HIDX)
    {}
    inline ConstHalfEdgeHandle::ConstHalfEdgeHandle(const Manifold& _m, HalfEdgeIndex _idx)
        : m(&_m), idx(_idx)
    {} 
    inline ConstHalfEdgeHandle::ConstHalfEdgeHandle(const ConstHalfEdgeHandle& ch)
        : m(ch.m), idx(ch.idx)
    {}
    inline ConstHalfEdgeHandle::ConstHalfEdgeHandle(const HalfEdgeHandle& h)
        : m(h.m), idx(h.idx)
    {}
    inline ConstHalfEdgeHandle& ConstHalfEdgeHandle::operator=(const ConstHalfEdgeHandle& ch)
    {
        m = ch.m;
        idx = ch.idx;
        return *this;
    }
    inline ConstHalfEdgeHandle& ConstHalfEdgeHandle::operator=(const HalfEdgeHandle& h)
    {
        m = h.m;
        idx = h.idx;
        return *this;
    }

    inline ConstVertexHandle ConstHalfEdgeHandle::vert() const
    { 
        return ConstVertexHandle(*m, m->halfedges[idx].vert_idx); 
    }
    inline ConstHalfEdgeHandle ConstHalfEdgeHandle::next() const
    { 
        return ConstHalfEdgeHandle(*m, m->halfedges[idx].next_idx); 
    }
    inline ConstHalfEdgeHandle ConstHalfEdgeHandle::prev() const
    { 
        return ConstHalfEdgeHandle(*m, m->halfedges[idx].prev_idx); 
    }
    inline ConstHalfEdgeHandle ConstHalfEdgeHandle::opp() const
    { 
        return ConstHalfEdgeHandle(*m, m->halfedges[idx].opp_idx); 
    }
    inline ConstFaceHandle ConstHalfEdgeHandle::face() const
    { 
        return ConstFaceHandle(*m, m->halfedges[idx].face_idx); 
    }
    inline const HalfEdge& ConstHalfEdgeHandle::get() const
    { 
        return m->halfedges[idx]; 
    }

    inline bool ConstHalfEdgeHandle::operator==(const ConstHalfEdgeHandle& h) const
    { 
        return idx == h.get_idx(); 
    }
    inline bool ConstHalfEdgeHandle::operator!=(const ConstHalfEdgeHandle& h) const
    { 
        return idx != h.get_idx(); 
    }
    inline void ConstHalfEdgeHandle::operator++()
    { 
        do{ 
            ++idx; 
        } 
        while(idx < m->halfedges.full_size() && !m->halfedges.in_use(idx)); 
    }
    inline void ConstHalfEdgeHandle::operator++(int)
    { 
        ++(*this); 
    }
    inline HalfEdgeIndex ConstHalfEdgeHandle::get_idx() const
    { 
        return idx; 
    }

    /** \brief Test for legal HalfEdge collapse.
        The argument h is the halfedge we want to collapse. 
        If this function does not return true, it is illegal to collapse h. 
        The reason is that the collapse would violate the manifold property of the mesh.
        The test is as follows:
        1.  For the two vertices adjacent to the edge, we generate a list of all their neighbouring vertices. 
            We then generate a  list of the vertices that occur in both these lists. 
            That is, we find all vertices connected by edges to both endpoints of the edge and store these in a list.
        2.  For both faces incident on the edge, check whether they are triangular. 
            If this is the case, the face will be removed, and it is ok that the the third vertex is connected to both endpoints. 
            Thus the third vertex in such a face is removed from the list generated in 1.
        3.  If the list is now empty, all is well. 
            Otherwise, there would be a vertex in the new mesh with two edges connecting it to the same vertex. Return false.
        4.  TETRAHEDRON TEST:
            If the valency of both vertices is three, and the incident faces are triangles, we also disallow the operation. 
            Reason: A vertex valency of two and two triangles incident on the adjacent vertices makes the construction collapse.
        5.  VALENCY 4 TEST:
            If a triangle is adjacent to the edge being collapsed, it disappears.
            This means the valency of the remaining edge vertex is decreased by one.
            A valency three vertex reduced to a valency two vertex is considered illegal.
        6.  PREVENT MERGING HOLES:
            Collapsing an edge with boundary endpoints and valid faces results in the creation where two holes meet.
            A non manifold situation.   */
    bool precond_collapse_halfedge(ConstHalfEdgeHandle h);

    /// Returns true if the halfedge is a boundary halfedge.
    bool boundary(ConstHalfEdgeHandle h);

    /// Return the geometric length of a halfedge.
    float length(ConstHalfEdgeHandle h);
}

#endif __HMESH_HALFEDGEHANDLE_H__