Commit ad72f214 by Max Lyon

add vertex vertex iterator to iterate over one-ring of a vertex

parent 82cd0d20
......@@ -61,7 +61,7 @@ VertexOHalfEdgeIter::VertexOHalfEdgeIter(const VertexHandle& _ref_h,
BaseIter(_mesh, _ref_h, _max_laps),
cur_index_(0) {
if(!_mesh->has_vertex_bottom_up_incidences()) {
if(!_mesh->has_vertex_bottom_up_incidences()) {
#ifndef NDEBUG
std::cerr << "This iterator needs bottom-up incidences!" << std::endl;
#endif
......@@ -69,20 +69,20 @@ cur_index_(0) {
return;
}
if((unsigned int)_ref_h.idx() >= BaseIter::mesh()->outgoing_hes_per_vertex_.size()) {
BaseIter::valid(false);
}
if((unsigned int)_ref_h.idx() >= BaseIter::mesh()->outgoing_hes_per_vertex_.size()) {
BaseIter::valid(false);
}
if(BaseIter::valid()) {
if((unsigned int)cur_index_ >= BaseIter::mesh()->outgoing_hes_per_vertex_[_ref_h.idx()].size()) {
BaseIter::valid(false);
}
}
if(BaseIter::valid()) {
if((unsigned int)cur_index_ >= BaseIter::mesh()->outgoing_hes_per_vertex_[_ref_h.idx()].size()) {
BaseIter::valid(false);
}
}
if(BaseIter::valid()) {
BaseIter::cur_handle((
BaseIter::mesh()->outgoing_hes_per_vertex_[_ref_h.idx()])[cur_index_]);
}
if(BaseIter::valid()) {
BaseIter::cur_handle((
BaseIter::mesh()->outgoing_hes_per_vertex_[_ref_h.idx()])[cur_index_]);
}
}
......@@ -102,7 +102,7 @@ VertexOHalfEdgeIter& VertexOHalfEdgeIter::operator--() {
BaseIter::cur_handle((BaseIter::mesh()->outgoing_hes_per_vertex_[BaseIter::ref_handle().idx()])[cur_index_]);
return *this;
return *this;
}
......@@ -121,9 +121,87 @@ VertexOHalfEdgeIter& VertexOHalfEdgeIter::operator++() {
BaseIter::cur_handle((BaseIter::mesh()->outgoing_hes_per_vertex_[BaseIter::ref_handle().idx()])[cur_index_]);
return *this;
return *this;
}
//================================================================================================
// VertexVertexIter
//================================================================================================
VertexVertexIter::VertexVertexIter(const VertexHandle& _ref_h,
const TopologyKernel* _mesh, int _max_laps) :
BaseIter(_mesh, _ref_h, _max_laps),
cur_index_(0) {
if(!_mesh->has_vertex_bottom_up_incidences()) {
#ifndef NDEBUG
std::cerr << "This iterator needs bottom-up incidences!" << std::endl;
#endif
BaseIter::valid(false);
return;
}
if((size_t)_ref_h.idx() >= BaseIter::mesh()->outgoing_hes_per_vertex_.size()) {
BaseIter::valid(false);
}
if(BaseIter::valid()) {
if((size_t)cur_index_ >= BaseIter::mesh()->outgoing_hes_per_vertex_[_ref_h.idx()].size()) {
BaseIter::valid(false);
}
}
if(BaseIter::valid()) {
HalfEdgeHandle heh = BaseIter::mesh()->outgoing_hes_per_vertex_[_ref_h.idx()][cur_index_];
BaseIter::cur_handle(BaseIter::mesh()->halfedge(heh).to_vertex());
}
}
VertexVertexIter& VertexVertexIter::operator--() {
size_t n_outgoing_halfedges = BaseIter::mesh()->outgoing_hes_per_vertex_[BaseIter::ref_handle().idx()].size();
if (cur_index_ == 0) {
cur_index_ = n_outgoing_halfedges-1;
--lap_;
if (lap_ < 0)
BaseIter::valid(false);
}
else {
--cur_index_;
}
HalfEdgeHandle heh = BaseIter::mesh()->outgoing_hes_per_vertex_[BaseIter::ref_handle().idx()][cur_index_];
BaseIter::cur_handle(BaseIter::mesh()->halfedge(heh).to_vertex());
return *this;
}
VertexVertexIter& VertexVertexIter::operator++() {
size_t n_outgoing_halfedges = BaseIter::mesh()->outgoing_hes_per_vertex_[BaseIter::ref_handle().idx()].size();
++cur_index_;
if (cur_index_ == n_outgoing_halfedges) {
cur_index_ = 0;
++lap_;
if (lap_ >= max_laps_)
BaseIter::valid(false);
}
HalfEdgeHandle heh = BaseIter::mesh()->outgoing_hes_per_vertex_[BaseIter::ref_handle().idx()][cur_index_];
BaseIter::cur_handle(BaseIter::mesh()->halfedge(heh).to_vertex());
return *this;
}
////================================================================================================
//// HalfEdgeHalfFaceIter
////================================================================================================
......
......@@ -240,57 +240,120 @@ protected:
class VertexOHalfEdgeIter :
public BaseCirculator<
VertexHandle,
HalfEdgeHandle> {
VertexHandle,
HalfEdgeHandle> {
public:
typedef BaseCirculator<
VertexHandle,
HalfEdgeHandle> BaseIter;
VertexHandle,
HalfEdgeHandle> BaseIter;
VertexOHalfEdgeIter(const VertexHandle& _vIdx,
VertexOHalfEdgeIter(const VertexHandle& _vIdx,
const TopologyKernel* _mesh, int _max_laps = 1);
// Post increment/decrement operator
VertexOHalfEdgeIter operator++(int) {
VertexOHalfEdgeIter cpy = *this;
++(*this);
return cpy;
}
VertexOHalfEdgeIter operator--(int) {
VertexOHalfEdgeIter cpy = *this;
--(*this);
return cpy;
}
VertexOHalfEdgeIter operator+(int _n) {
VertexOHalfEdgeIter cpy = *this;
for(int i = 0; i < _n; ++i) {
++cpy;
}
return cpy;
}
VertexOHalfEdgeIter operator-(int _n) {
VertexOHalfEdgeIter cpy = *this;
for(int i = 0; i < _n; ++i) {
--cpy;
}
return cpy;
}
VertexOHalfEdgeIter& operator+=(int _n) {
for(int i = 0; i < _n; ++i) {
++(*this);
}
return *this;
}
VertexOHalfEdgeIter& operator-=(int _n) {
for(int i = 0; i < _n; ++i) {
--(*this);
}
return *this;
}
// Post increment/decrement operator
VertexOHalfEdgeIter operator++(int) {
VertexOHalfEdgeIter cpy = *this;
++(*this);
return cpy;
}
VertexOHalfEdgeIter operator--(int) {
VertexOHalfEdgeIter cpy = *this;
--(*this);
return cpy;
}
VertexOHalfEdgeIter operator+(int _n) {
VertexOHalfEdgeIter cpy = *this;
for(int i = 0; i < _n; ++i) {
++cpy;
}
return cpy;
}
VertexOHalfEdgeIter operator-(int _n) {
VertexOHalfEdgeIter cpy = *this;
for(int i = 0; i < _n; ++i) {
--cpy;
}
return cpy;
}
VertexOHalfEdgeIter& operator+=(int _n) {
for(int i = 0; i < _n; ++i) {
++(*this);
}
return *this;
}
VertexOHalfEdgeIter& operator-=(int _n) {
for(int i = 0; i < _n; ++i) {
--(*this);
}
return *this;
}
VertexOHalfEdgeIter& operator++();
VertexOHalfEdgeIter& operator--();
private:
size_t cur_index_;
};
//===========================================================================
class VertexVertexIter :
public BaseCirculator<
VertexHandle,
VertexHandle> {
public:
typedef BaseCirculator<
VertexHandle,
VertexHandle> BaseIter;
VertexVertexIter(const VertexHandle& _vIdx,
const TopologyKernel* _mesh, int _max_laps = 1);
// Post increment/decrement operator
VertexVertexIter operator++(int) {
VertexVertexIter cpy = *this;
++(*this);
return cpy;
}
VertexVertexIter operator--(int) {
VertexVertexIter cpy = *this;
--(*this);
return cpy;
}
VertexVertexIter operator+(int _n) {
VertexVertexIter cpy = *this;
for(int i = 0; i < _n; ++i) {
++cpy;
}
return cpy;
}
VertexVertexIter operator-(int _n) {
VertexVertexIter cpy = *this;
for(int i = 0; i < _n; ++i) {
--cpy;
}
return cpy;
}
VertexVertexIter& operator+=(int _n) {
for(int i = 0; i < _n; ++i) {
++(*this);
}
return *this;
}
VertexVertexIter& operator-=(int _n) {
for(int i = 0; i < _n; ++i) {
--(*this);
}
return *this;
}
VertexOHalfEdgeIter& operator++();
VertexOHalfEdgeIter& operator--();
VertexVertexIter& operator++();
VertexVertexIter& operator--();
private:
......
......@@ -85,6 +85,7 @@ public:
//=====================================================================
friend class VertexOHalfEdgeIter;
friend class VertexVertexIter;
friend class HalfEdgeHalfFaceIter;
friend class VertexCellIter;
friend class HalfEdgeCellIter;
......@@ -127,6 +128,15 @@ public:
return std::make_pair(begin, make_end_circulator(begin));
}
VertexVertexIter vv_iter(const VertexHandle& _h, int _max_laps = 1) const {
return VertexVertexIter(_h, this, _max_laps);
}
std::pair<VertexVertexIter, VertexVertexIter> vertex_vertices(const VertexHandle& _h, int _max_laps = 1) const {
VertexVertexIter begin = vv_iter(_h, _max_laps);
return std::make_pair(begin, make_end_circulator(begin));
}
HalfEdgeHalfFaceIter hehf_iter(const HalfEdgeHandle& _h, int _max_laps = 1) const {
return HalfEdgeHalfFaceIter(_h, this, _max_laps);
}
......
......@@ -210,3 +210,19 @@ void HexahedralMeshBase::generateHexahedralMesh(HexahedralMesh& _mesh) {
halffaces.push_back(_mesh.halfface_handle(f9, 0)); halffaces.push_back(_mesh.halfface_handle(f10, 1));
_mesh.add_cell(halffaces);
}
void TetrahedralMeshBase::generateTetrahedralMesh(TetrahedralMesh& _mesh) {
Vec3d p1(0.0, 0.0, 0.0);
Vec3d p2(1.0, 0.0, 0.0);
Vec3d p3(1.0, 1.0, 0.0);
Vec3d p4(0.0, 1.0, 0.0);
VertexHandle v1 = _mesh.add_vertex(p1);
VertexHandle v2 = _mesh.add_vertex(p2);
VertexHandle v3 = _mesh.add_vertex(p3);
VertexHandle v4 = _mesh.add_vertex(p4);
// Add cell
_mesh.add_cell(v1, v2, v3, v4);
}
......@@ -5,6 +5,7 @@
#include <OpenVolumeMesh/Mesh/PolyhedralMesh.hh>
#include <OpenVolumeMesh/Mesh/HexahedralMesh.hh>
#include <OpenVolumeMesh/Mesh/TetrahedralMesh.hh>
#include <OpenVolumeMesh/Geometry/VectorT.hh>
/*
......@@ -83,6 +84,46 @@ protected:
HexahedralMesh mesh_;
};
/*
* Simple test setting for tetrahedral meshes
*/
typedef OpenVolumeMesh::GeometricTetrahedralMeshV3d TetrahedralMesh;
class TetrahedralMeshBase: public testing::Test {
protected:
typedef OpenVolumeMesh::VertexHandle VertexHandle;
typedef OpenVolumeMesh::HalfEdgeHandle HalfEdgeHandle;
typedef OpenVolumeMesh::EdgeHandle EdgeHandle;
typedef OpenVolumeMesh::HalfFaceHandle HalfFaceHandle;
typedef OpenVolumeMesh::FaceHandle FaceHandle;
typedef OpenVolumeMesh::CellHandle CellHandle;
// This function is called before each test is run
virtual void SetUp() {
// Do some initial stuff with the member data here...
mesh_.enable_deferred_deletion(false);
mesh_.enable_fast_deletion(false);
}
// This function is called after all tests are through
virtual void TearDown() {
// Do some final stuff with the member data here...
}
// Generate a basic hexahedral mesh
void generateTetrahedralMesh(TetrahedralMesh& _mesh);
// This member will be accessible in all tests
TetrahedralMesh mesh_;
};
// Printer class (for STL compliance test)
class Print {
public:
......
......@@ -22,6 +22,63 @@ TEST_F(HexahedralMeshBase, HexVertexIterTest) {
EXPECT_EQ(VertexHandle(5), *hv_it);
}
TEST_F(TetrahedralMeshBase, VertexVertexIteratorTest) {
generateTetrahedralMesh(mesh_);
{
VertexVertexIter vv_it = mesh_.vv_iter(VertexHandle(0));
EXPECT_TRUE(vv_it.valid());
std::set<VertexHandle> onering;
int valence = 0;
while (vv_it.valid())
{
++valence;
onering.insert(*vv_it);
++vv_it;
}
// check that there have been three adjacent vertices
EXPECT_EQ(3, valence);
// check that no vertex was visited twice
EXPECT_EQ(3u, onering.size());
// check that no invalid vertex was adjacent
EXPECT_EQ(onering.end(), std::find(onering.begin(), onering.end(), VertexHandle(-1)));
}
#if __cplusplus >= 201103L // C++11
{
std::set<VertexHandle> onering;
int valence = 0;
for (auto vh : mesh_.vertex_vertices(VertexHandle(0)))
{
++valence;
onering.insert(vh);
}
// check that there have been three adjacent vertices
EXPECT_EQ(3, valence);
// check that no vertex was visited twice
EXPECT_EQ(3u, onering.size());
// check that no invalid vertex was adjacent
EXPECT_EQ(onering.end(), std::find(onering.begin(), onering.end(), VertexHandle(-1)));
}
#endif
}
#if __cplusplus >= 201103L // C++11
TEST_F(HexahedralMeshBase, RangeForTest) {
// no EXPECTs here, if it compiles, it'll work.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment