Program Listing for File HalfEdgeMesh.hpp

Return to documentation for file (include/lvr2/geometry/HalfEdgeMesh.hpp)

/*
 * HalfEdgeMesh.hpp
 *
 *  @date 02.06.2017
 *  @author Lukas Kalbertodt <lukas.kalbertodt@gmail.com>
 *  @author Patrick Hoffmann <pahoffmann@uni-osnabrueck.de>
 *  @author Malte Hillmann <mhillmann@uni-osnabrueck.de>
 */

#ifndef LVR2_GEOMETRY_HALFEDGEMESH_H_
#define LVR2_GEOMETRY_HALFEDGEMESH_H_

#include <cstdint>
#include <utility>
#include "lvr2/attrmaps/StableVector.hpp"
#include <array>
#include <vector>

using std::pair;
using std::array;
using std::vector;
using std::get;
using std::min;

#include "lvr2/geometry/BaseMesh.hpp"
#include "lvr2/geometry/HalfEdge.hpp"
#include "lvr2/geometry/HalfEdgeFace.hpp"
#include "lvr2/geometry/HalfEdgeVertex.hpp"

#include "lvr2/types/MeshBuffer.hpp"

namespace lvr2
{

template<typename BaseVecT>
class HalfEdgeMesh : public BaseMesh<BaseVecT>
{
public:
    using Edge = HalfEdge;
    using Face = HalfEdgeFace;
    using Vertex = HalfEdgeVertex<BaseVecT>;

    HalfEdgeMesh();
    HalfEdgeMesh(MeshBufferPtr ptr);

    // ========================================================================
    // = Implementing the `BaseMesh` interface (see BaseMesh for docs)
    // ========================================================================

    // We declare all methods as `final` to make devirtualization optimizations
    // more likely and effective.
    VertexHandle addVertex(BaseVecT pos) final;
    FaceHandle addFace(VertexHandle v1H, VertexHandle v2H, VertexHandle v3H) final;
    void removeFace(FaceHandle handle) final;
    EdgeCollapseResult collapseEdge(EdgeHandle edgeH) final;
    VertexSplitResult splitVertex(VertexHandle vertexToBeSplitH);
    EdgeSplitResult splitEdge(EdgeHandle edgeH);
    void fillHoles(size_t maxSize);
    void laplacianSmoothing(float smoothFactor, int numSmooths=1);
    vector<VertexHandle> findCommonNeigbours(VertexHandle vH1, VertexHandle vH2);
    void flipEdge(EdgeHandle edgeH) final;
    void splitVertex(EdgeHandle eH, VertexHandle vH, BaseVecT pos1, BaseVecT pos2);
    std::pair<BaseVecT, float> triCircumCenter(FaceHandle faceH);


    size_t numVertices() const final;
    size_t numFaces() const final;
    size_t numEdges() const final;

    bool containsVertex(VertexHandle vH) const;
    bool containsFace(FaceHandle fH) const;
    bool containsEdge(EdgeHandle eH) const;

    bool isBorderEdge(EdgeHandle handle) const;
    bool isFlippable(EdgeHandle handle) const;

    Index nextVertexIndex() const;
    Index nextFaceIndex() const;
    Index nextEdgeIndex() const;

    BaseVecT getVertexPosition(VertexHandle handle) const final;
    BaseVecT& getVertexPosition(VertexHandle handle) final;

    array<VertexHandle, 3> getVerticesOfFace(FaceHandle handle) const final;
    array<EdgeHandle, 3> getEdgesOfFace(FaceHandle handle) const final;
    void getNeighboursOfFace(FaceHandle handle, vector<FaceHandle>& facesOut) const final;
    array<VertexHandle, 2> getVerticesOfEdge(EdgeHandle edgeH) const final;
    array<OptionalFaceHandle, 2> getFacesOfEdge(EdgeHandle edgeH) const final;
    void getFacesOfVertex(VertexHandle handle, vector<FaceHandle>& facesOut) const final;
    void getEdgesOfVertex(VertexHandle handle, vector<EdgeHandle>& edgesOut) const final;
    void getNeighboursOfVertex(VertexHandle handle, vector<VertexHandle>& verticesOut) const final;
    OptionalFaceHandle getOppositeFace(FaceHandle faceH, VertexHandle vertexH) const;
    OptionalEdgeHandle getOppositeEdge(FaceHandle faceH, VertexHandle vertexH) const;
    OptionalVertexHandle getOppositeVertex(FaceHandle faceH, EdgeHandle edgeH) const;

    // Make sure all default methods from `BaseMesh` are visible
    using BaseMesh<BaseVecT>::getFacesOfVertex;
    using BaseMesh<BaseVecT>::getEdgesOfVertex;
    using BaseMesh<BaseVecT>::getNeighboursOfVertex;


    MeshHandleIteratorPtr<VertexHandle> verticesBegin() const final;
    MeshHandleIteratorPtr<VertexHandle> verticesEnd() const final;
    MeshHandleIteratorPtr<FaceHandle> facesBegin() const final;
    MeshHandleIteratorPtr<FaceHandle> facesEnd() const final;
    MeshHandleIteratorPtr<EdgeHandle> edgesBegin() const final;
    MeshHandleIteratorPtr<EdgeHandle> edgesEnd() const final;


    // ========================================================================
    // = Other public methods
    // ========================================================================

    bool debugCheckMeshIntegrity() const;

private:
    StableVector<HalfEdgeHandle, Edge> m_edges;
    StableVector<FaceHandle, Face> m_faces;
    StableVector<VertexHandle, Vertex> m_vertices;

    // ========================================================================
    // = Private helper methods
    // ========================================================================
    Edge& getE(HalfEdgeHandle handle);
    const Edge& getE(HalfEdgeHandle handle) const;
    Face& getF(FaceHandle handle);
    const Face& getF(FaceHandle handle) const;
    Vertex& getV(VertexHandle handle);
    const Vertex& getV(VertexHandle handle) const;

    EdgeHandle halfToFullEdgeHandle(HalfEdgeHandle handle) const;

    OptionalHalfEdgeHandle edgeBetween(VertexHandle fromH, VertexHandle toH);

    HalfEdgeHandle findOrCreateEdgeBetween(VertexHandle fromH, VertexHandle toH);

    HalfEdgeHandle findOrCreateEdgeBetween(VertexHandle fromH, VertexHandle toH, bool& added);

    pair<HalfEdgeHandle, HalfEdgeHandle> addEdgePair(VertexHandle v1H, VertexHandle v2H);


    template <typename Visitor>
    void circulateAroundVertex(VertexHandle vH, Visitor visitor) const;

    template <typename Visitor>
    void circulateAroundVertex(HalfEdgeHandle startEdgeH, Visitor visitor) const;

    template <typename Pred>
    OptionalHalfEdgeHandle findEdgeAroundVertex(VertexHandle vH, Pred pred) const;

    template <typename Pred>
    OptionalHalfEdgeHandle findEdgeAroundVertex(HalfEdgeHandle startEdgeH, Pred pred) const;

    array<HalfEdgeHandle, 3> getInnerEdges(FaceHandle handle) const;

    // ========================================================================
    // = Friends
    // ========================================================================
    template<typename> friend class HemEdgeIterator;
};

template<typename HandleT, typename ElemT>
class HemFevIterator : public MeshHandleIterator<HandleT>
{
public:
    HemFevIterator(StableVectorIterator<HandleT, ElemT> iterator) : m_iterator(iterator) {};
    HemFevIterator& operator++();
    bool operator==(const MeshHandleIterator<HandleT>& other) const;
    bool operator!=(const MeshHandleIterator<HandleT>& other) const;
    HandleT operator*() const;

private:
    StableVectorIterator<HandleT, ElemT> m_iterator;
};

template<typename BaseVecT>
class HemEdgeIterator : public MeshHandleIterator<EdgeHandle>
{
public:
    HemEdgeIterator(
        StableVectorIterator<HalfEdgeHandle, HalfEdge> iterator,
        const HalfEdgeMesh<BaseVecT>& mesh
    ) : m_iterator(iterator), m_mesh(mesh) {};

    HemEdgeIterator& operator++();
    bool operator==(const MeshHandleIterator<EdgeHandle>& other) const;
    bool operator!=(const MeshHandleIterator<EdgeHandle>& other) const;
    EdgeHandle operator*() const;

private:
    StableVectorIterator<HalfEdgeHandle, HalfEdge> m_iterator;
    const HalfEdgeMesh<BaseVecT>& m_mesh;
};

} // namespace lvr2

#include "lvr2/geometry/HalfEdgeMesh.tcc"

#endif /* LVR2_GEOMETRY_HALFEDGEMESH_H_ */