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
{
VertexHandle::VertexHandle(Manifold& _m, Vidx _idx): m(&_m), idx(_idx){}
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);
}
/*const Vec3f& VertexHandle::pos() const
{
return get().pos;
}
Vec3f& VertexHandle::pos()
{
return get().pos;
}*/
const Vertex& VertexHandle::get() const
{
return m->vertices[idx];
}
Vertex& VertexHandle::get()
{
return m->vertices[idx];
}
bool VertexHandle::operator==(const VertexHandle& v) const
{
return idx == v.get_idx();
}
bool VertexHandle::operator!=(const VertexHandle& v) const
{
return idx != v.get_idx();
}
void VertexHandle::operator++()
{
++idx;
while(idx < m->vertices.size() && !m->vertices.in_use(idx))
++idx;
}
void VertexHandle::operator++(int)
{
++(*this);
}
void VertexHandle::operator--()
{
--idx;
while(!m->vertices.in_use(idx))
--idx;
}
void VertexHandle::operator--(int)
{
--(*this);
}
Vidx VertexHandle::get_idx() const
{
return idx;
}
bool VertexHandle::is_valid() const
{
return idx != NULL_VERTEX_IDX;
}
bool VertexHandle::in_use() const
{
return m->vertices.in_use(idx);
}
/*bool is_used(const VertexHandle& v)
{
if(v.out().is_valid())
return true;
return false;
}*/
bool is_boundary(const VertexHandle& v)
{
return is_boundary(v.out());
}
uint valency(const 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;
// step 1: circle through edges pointing away from vertex until reaching a null face
while(h.face().is_valid()){
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().is_valid()){
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(const 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);
uint N = one_ring.size();
// sum up the normals of each face surrounding the vertex
for(uint 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(const VertexHandle& v0, const VertexHandle& v1)
{
for(VertexCirculator vc(v0); !vc.end(); ++vc){
if(vc.vertex() == v1)
return true;
}
return false;
}
}