Subversion Repositories gelsvn

Rev

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

#include "VertexHandle.h"

#include <vector>
#include <CGLA/Vec3f.h>

#include "entities.h"
#include "Manifold.h"
#include "HalfEdgeHandle.h"
#include "FaceHandle.h"
#include "VertexCirculator.h"

using namespace std;
using namespace CGLA;

namespace HMesh
{
    const HalfEdgeHandle VertexHandle::out() const{ return m->halfedge_handle(m->vertices[idx].out_idx); }
    HalfEdgeHandle VertexHandle::out(){ return m->halfedge_handle(m->vertices[idx].out_idx); }

    void VertexHandle::operator++()
    {
        ++idx;
        while(idx < m->vertices.full_size() && !m->vertices.in_use(idx))
            ++idx;

    }
    void VertexHandle::operator++(int)
    {
        ++(*this);
    }

    bool is_boundary(VertexHandle v)
    {
        return is_boundary(v.out());
    }

    size_t valency(VertexHandle v)
    {
        // perform full circulation to get valency 
        VertexCirculator vc(v);
        while(!vc.end()) ++vc;
        return vc.no_steps();
    }

    void check_boundary_consistency(VertexHandle v)
    {
        // boundary consistency check by performing two vertex circulations
        HalfEdgeHandle h = v.out();
        HalfEdgeHandle last = h;

        int flaf = 0;
        
        // step 1: circle through edges pointing away from vertex until reaching a null face
        while(h.face() != NULL_FACE_HANDLE){
            h = h.prev().opp();
            //std::cout << h.get_idx() << std::endl;
            if(h == last) 
                return;
        }
        // null face encountered, we update our vertex with half edge index and prepare for step 2
        v.get().out_idx = h.get_idx();
        HalfEdgeHandle h_opp = h.opp();

        // step 2: circle through edges pointing towards vertex until reaching a null face
        while(h_opp.face() != NULL_FACE_HANDLE){
            h_opp = h_opp.next().opp();
        }
        // null face encountered again, we update our edge with vertex index
        h_opp.get().vert_idx = v.get_idx();

        // remaining step is to make the in and out going edges link to each other
        link(h_opp, h);
    }

    CGLA::Vec3f normal(VertexHandle v)
    {
        Vec3f p0 = v.get().pos;
        vector<Vec3f> one_ring;

        // run through outgoing edges, and store them normalized
        for(VertexCirculator vc(v); !vc.end(); ++vc){
            Vec3f edge = p0 - vc.vertex().get().pos;
            float l = length(edge);
            if(l > 0.0f) one_ring.push_back(edge/l);
        }
        
        Vec3f n(0);
        size_t N = one_ring.size();

        // sum up the normals of each face surrounding the vertex
        for(size_t i = 0; i < N; ++i){
            Vec3f e1 = one_ring[i];
            Vec3f e0 = one_ring[(i+1) % N];

            Vec3f n_part = normalize(cross(e0, e1));
            n += n_part * acos(max(-1.0f, min(1.0f, dot(e0, e1))));
        }

        // normalize and return the normal
        float sqr_l = sqr_length(n);  
        if(sqr_l > 0.0f) return n / sqrt(sqr_l);
        
        return n;
    }

    bool is_connected(VertexHandle v0, VertexHandle v1)
    {
        for(VertexCirculator vc(v0); !vc.end(); ++vc){
            if(vc.vertex() == v1) 
                return true;
        }
        return false;
    }

}