halfmesh.hpp

Back to Half-edge structure

pastel/geometry/halfmesh/

#ifndef PASTELGEOMETRY_HALFMESH_HPP
#define PASTELGEOMETRY_HALFMESH_HPP

#include "pastel/geometry/halfmesh/halfmesh.h"
#include "pastel/sys/ensure.h"

#include <unordered_map>

namespace Pastel
{

    template <
        typename Settings, 
        template <typename> class Customization>
    HalfMesh<Settings, Customization>::HalfMesh(
        const HalfMesh& that)
    : HalfMesh()
    {
        std::unordered_map<Vertex_ConstIterator, Vertex_Iterator> vertexMap;

        // Construct vertices along with a vertex map.
        {
            Vertex_ConstIterator thatVertex = that.vertexBegin();
            Vertex_ConstIterator thatEnd = that.vertexEnd();
            while(thatVertex != thatEnd)
            {
                Vertex_Iterator vertex = insertVertex(*thatVertex);
                ASSERT(vertex.isNormal());

                vertexMap.insert(
                    std::make_pair(thatVertex, vertex));

                ++thatVertex;
            }
        }

        // Construct edges.
        {
            Edge_ConstIterator thatEdge = that.edgeBegin();
            Edge_ConstIterator thatEnd = that.edgeEnd();
            while(thatEdge != thatEnd)
            {
                Vertex_ConstIterator origin = 
                    thatEdge->half()->origin();
                ASSERT(vertexMap.count(origin));

                Vertex_ConstIterator destination =
                    thatEdge->half()->destination();
                ASSERT(vertexMap.count(destination));

                Edge_Iterator edge = insertEdgeEdge(insertEdge(
                    vertexMap[origin],
                    vertexMap[destination],
                    *thatEdge));
                ASSERT(edge.isNormal());
                unused(edge);

                ++thatEdge;
            }
        }

        // Construct polygons.
        {
            Polygon_ConstIterator thatPolygon = that.polygonBegin();
            Polygon_ConstIterator thatEnd = that.polygonEnd();
            while(thatPolygon != thatEnd)
            {
                std::vector<Vertex_Iterator> vertexLoop;

                Half_ConstIterator halfBegin = thatPolygon->half();
                Half_ConstIterator half = halfBegin;
                do
                {
                    vertexLoop.push_back(vertexMap[half->origin()]);
                    half = half.next();
                }
                while(half != halfBegin);

                Polygon_Iterator polygon = 
                    insertPolygon(vertexLoop, *thatPolygon);
                ASSERT(polygon.isNormal());
                unused(polygon);

                ++thatPolygon;
            }
        }
    }

    // Modification

    template <
        typename Settings, 
        template <typename> class Customization>
    bool HalfMesh<Settings, Customization>::makeAdjacent(
        const Half_ConstIterator& in, 
        const Half_ConstIterator& out)
    {
        PENSURE(!in.empty());
        PENSURE(!out.empty());
        PENSURE(in->destination() == out->origin());
        PENSURE(in->left().empty());
        PENSURE(out->left().empty());

        if (in->next() == out)
        {
            // Nothing to do.
            return true;
        }

        Half_Iterator b = cast(in)->next();
        Half_Iterator d = cast(out)->previous();

        // Find a free incident half edge
        // after 'd' and before 'in'.
        Half_Iterator g = 
            findFreeIncident(out->origin(), out->pair(), in);
        if (g.empty())
        {
            // There is no such half-edge.
            return false;
        }
        Half_Iterator h = g->next();

        cast(in)->next_ = cast(out);
        cast(out)->previous_ = cast(in);

        g->next_ = b;
        b->previous_ = g;

        d->next_ = h;
        h->previous_ = d;

        return true;
    }

}

#endif