Subversion Repositories gelsvn

Rev

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

#include "FaceHandle.h"

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

#include "HalfEdgeHandle.h"
#include "VertexHandle.h"
#include "Manifold.h"
#include "FaceCirculator.h"

using namespace std;
using namespace CGLA;

namespace HMesh
{

    FaceHandle::FaceHandle(Manifold& _m, Fidx _idx): m(&_m), idx(_idx){}

    const HalfEdgeHandle FaceHandle::last() const 
    { 
        return m->halfedge_handle(m->faces[idx].last_idx);
    }
    HalfEdgeHandle FaceHandle::last()
    { 
        return m->halfedge_handle(m->faces[idx].last_idx);
    }

    const Face& FaceHandle::get() const
    {
        return m->faces[idx];
    }
    Face& FaceHandle::get()
    {
        return m->faces[idx];
    }

    bool FaceHandle::operator==(const FaceHandle& f) const
    {
        return idx == f.get_idx();
    }
    bool FaceHandle::operator!=(const FaceHandle& f) const
    {
        return idx != f.get_idx();
    }
    void FaceHandle::operator++()
    {
        ++idx;
        while(idx < m->faces.full_size() && !m->faces.in_use(idx))
            ++idx;

    }
    void FaceHandle::operator++(int)
    {
        ++(*this);
    }
    void FaceHandle::operator--()
    {
        --idx;
        while(!m->faces.in_use(idx))
            --idx;

    }
    void FaceHandle::operator--(int)
    {
        --(*this);
    }

    bool FaceHandle::is_valid() const
    {
        return idx != NULL_FACE_IDX;
    }

    bool FaceHandle::in_use() const
    {
        return m->faces.in_use(idx);
    }

    Fidx FaceHandle::get_idx() const 
    { 
        return idx; 
    }
    Manifold* FaceHandle::get_manifold() const
    {
        return m;
    }

    /*bool is_used(const FaceHandle& f)
    {
        if(f.last().is_valid())
            return true;
        return false;
    }*/

    uint no_edges(FaceHandle f)
        {
                // perform full circulation to get valency 
        FaceCirculator fc(f);
                for(; !fc.end(); ++fc);
                return fc.no_steps();
        }

    CGLA::Vec3f normal(FaceHandle f)
        {
                vector<Vec3f> vertices;
                FaceCirculator fc(f);
                
                // Assuming that a face is valid, i.e. consisting of AT LEAST 3 vertices...
                for(uint i = 0; i < 3; ++i, ++fc) vertices.push_back(fc.vertex().get().pos);
                
                Vec3f n = cross(vertices[0] - vertices[1], vertices[2] - vertices[1]);
                
                float l = n.length();
                if(l > 0.0f) return n/l;
                
                return n;
        }

    float area(FaceHandle f)
    {
                FaceCirculator fc(f);
                uint k;
                
                // M is a matrix that projects a vector onto the orthogonal
                // complement of the face normal
                Vec3f n =normal(f);
                Vec3f a,b;
                orthogonal(n, a, b);
                Mat3x3f M(a, b, n);
                
                // Get all projected vertices
                vector<Vec2f> v;                
                for(k = 0; !fc.end(); ++fc, ++k){
                        Vec3f p = M * fc.vertex().get().pos;
                        v.push_back(Vec2f(p[0], p[1]));
                }
                float area = 0;
                for(uint i = 0; i < k; ++i) area += 0.5 * cross(v[i], v[(i+1 )% k]);
                
                return abs(area);
        }

    CGLA::Vec3f centre(FaceHandle f)
        {
                Vec3f c(0);
                FaceCirculator fc(f);
                
                for(; !fc.end(); ++fc) c += fc.vertex().get().pos;
                
                c /= fc.no_steps();
                return c;
        }
}