Commit d2d3162c authored by Mike Kremer's avatar Mike Kremer

Refactored bottom-up adjacencies:

Bottom-up adjacencies are now computed automatically on-the-fly when adding/deleting
entities. For this only a minimal subset of affected entities is recomputed.

Refactored delete functions and normal attrib class.

git-svn-id: http://www.openvolumemesh.org/svnrepo/OpenVolumeMesh/trunk@169 66977474-1d4b-4f09-8fe9-267525286df2
parent 81588995
......@@ -66,7 +66,7 @@ NormalAttrib<GeomKernelT>::~NormalAttrib() {
template <class GeomKernelT>
void NormalAttrib<GeomKernelT>::update_vertex_normals() {
if(!kernel_.has_bottom_up_adjacencies()) {
if(!kernel_.has_face_bottom_up_adjacencies()) {
std::cerr << "Error: update_vertex_normals() needs bottom-up adjacencies!" << std::endl;
return;
}
......@@ -82,6 +82,11 @@ void NormalAttrib<GeomKernelT>::update_vertex_normals() {
template <class GeomKernelT>
void NormalAttrib<GeomKernelT>::update_face_normals() {
if(!kernel_.has_face_bottom_up_adjacencies()) {
std::cerr << "Error: update_normals() needs bottom-up adjacencies!" << std::endl;
return;
}
for(FaceIter f_it = kernel_.f_iter(); f_it.valid(); ++f_it) {
// Assume the face is planar, so just take the
// first two edges
......@@ -134,7 +139,7 @@ void NormalAttrib<GeomKernelT>::compute_face_normal(const FaceHandle& _fh) {
++he_it;
typename GeomKernelT::PointT p3 = kernel_.vertex(kernel_.halfedge(*he_it).to_vertex());
typename GeomKernelT::PointT n = (p3 - p2) % (p1 - p2);
typename GeomKernelT::PointT n = (p1 - p2) % (p3 - p2);
n.normalize();
f_normals_[_fh.idx()] = n;
......
......@@ -112,14 +112,9 @@ void StatusAttrib::garbage_collection(bool _preserveManifoldness) {
}
}
// Step 5
if(kernel_.has_bottom_up_adjacencies()) {
kernel_.update_adjacencies();
}
// Step 6
if(_preserveManifoldness) {
if(kernel_.has_bottom_up_adjacencies()) {
if(kernel_.has_full_bottom_up_adjacencies()) {
// Go over all faces and find those
// that are not incident to any cell
......@@ -135,15 +130,11 @@ void StatusAttrib::garbage_collection(bool _preserveManifoldness) {
f_it = kernel_.delete_face(*f_it);
kernel_.update_face_adjacencies();
} else {
++f_it;
}
}
kernel_.update_edge_adjacencies();
// Go over all edges and find those
// whose half-edges are not incident to any half-face
for(EdgeIter e_it = kernel_.edges_begin(); e_it != kernel_.edges_end();) {
......@@ -160,17 +151,11 @@ void StatusAttrib::garbage_collection(bool _preserveManifoldness) {
e_it = kernel_.delete_edge(*e_it);
kernel_.update_edge_adjacencies();
} else {
++e_it;
}
}
// Vertex caches have to be re-computed because the face/half-face
// indices have changed since the last deletions
kernel_.update_vertex_adjacencies();
// Go over all vertices and find those
// that are not incident to any edge
for(VertexIter v_it = kernel_.vertices_begin(); v_it != kernel_.vertices_end();) {
......@@ -182,10 +167,8 @@ void StatusAttrib::garbage_collection(bool _preserveManifoldness) {
v_it = kernel_.delete_vertex(*v_it);
kernel_.update_vertex_adjacencies();
} else {
++v_it;
++v_it;
}
}
......
......@@ -72,11 +72,8 @@ public:
// Store vertex in list
vertices_.push_back(_p);
// Resize vertex props
KernelT::resize_vprops(vertices_.size());
// Get handle of recently created vertex
return VertexHandle(vertices_.size() - 1);
return KernelT::add_vertex();
}
/// Set the coordinates of point _vh
......
......@@ -59,7 +59,7 @@ VertexOHalfEdgeIter::VertexOHalfEdgeIter(const VertexHandle& _ref_h,
BaseIter(_mesh, _ref_h),
cur_index_(0) {
if(!_mesh->has_vertex_adjacencies()) {
if(!_mesh->has_vertex_bottom_up_adjacencies()) {
std::cerr << "This iterator needs bottom-up adjacencies!" << std::endl;
BaseIter::valid(false);
return;
......@@ -121,7 +121,7 @@ HalfEdgeHalfFaceIter::HalfEdgeHalfFaceIter(const HalfEdgeHandle& _ref_h,
BaseIter(_mesh, _ref_h),
cur_index_(0) {
if(!_mesh->has_edge_adjacencies()) {
if(!_mesh->has_edge_bottom_up_adjacencies()) {
std::cerr << "This iterator needs bottom-up adjacencies!" << std::endl;
BaseIter::valid(false);
return;
......@@ -182,7 +182,7 @@ VertexCellIter::VertexCellIter(const VertexHandle& _ref_h,
const TopologyKernel* _mesh) :
BaseIter(_mesh, _ref_h) {
if(!_mesh->has_bottom_up_adjacencies()) {
if(!_mesh->has_full_bottom_up_adjacencies()) {
std::cerr << "This iterator needs bottom-up adjacencies!" << std::endl;
BaseIter::valid(false);
return;
......@@ -250,7 +250,7 @@ HalfEdgeCellIter::HalfEdgeCellIter(const HalfEdgeHandle& _ref_h,
BaseIter(_mesh, _ref_h),
cur_index_(0) {
if(!_mesh->has_edge_adjacencies() || !_mesh->has_face_adjacencies()) {
if(!_mesh->has_edge_bottom_up_adjacencies() || !_mesh->has_face_bottom_up_adjacencies()) {
std::cerr << "This iterator needs bottom-up adjacencies!" << std::endl;
BaseIter::valid(false);
return;
......@@ -367,7 +367,7 @@ CellCellIter::CellCellIter(const CellHandle& _ref_h,
const TopologyKernel* _mesh) :
BaseIter(_mesh, _ref_h) {
if(!_mesh->has_face_adjacencies()) {
if(!_mesh->has_face_bottom_up_adjacencies()) {
std::cerr << "This iterator needs bottom-up adjacencies!" << std::endl;
BaseIter::valid(false);
return;
......@@ -469,16 +469,20 @@ HalfFaceVertexIter& HalfFaceVertexIter::operator++() {
BoundaryFaceIter::BoundaryFaceIter(const TopologyKernel* _mesh) :
BaseIter(_mesh, TopologyKernel::InvalidFaceHandle) {
BaseIter(_mesh, TopologyKernel::InvalidFaceHandle),
bf_it_(_mesh->faces_begin()) {
if(!_mesh->has_face_adjacencies()) {
if(!_mesh->has_face_bottom_up_adjacencies()) {
std::cerr << "This iterator needs bottom-up adjacencies!" << std::endl;
BaseIter::valid(false);
return;
}
bf_it_ = BaseIter::mesh()->boundary_faces_.begin();
BaseIter::valid(bf_it_ != BaseIter::mesh()->boundary_faces_.end());
while(bf_it_ != BaseIter::mesh()->faces_end() &&
!BaseIter::mesh()->is_boundary(*bf_it_)) {
++bf_it_;
}
BaseIter::valid(bf_it_ != BaseIter::mesh()->faces_end());
if(BaseIter::valid()) {
BaseIter::cur_handle(*bf_it_);
}
......@@ -487,8 +491,12 @@ BaseIter(_mesh, TopologyKernel::InvalidFaceHandle) {
BoundaryFaceIter& BoundaryFaceIter::operator--() {
--bf_it_;
if(bf_it_ >= BaseIter::mesh()->boundary_faces_.begin()) {
--bf_it_;
while(bf_it_ >= BaseIter::mesh()->faces_begin() &&
!BaseIter::mesh()->is_boundary(*bf_it_)) {
--bf_it_;
}
if(bf_it_ >= BaseIter::mesh()->faces_begin()) {
BaseIter::cur_handle(*bf_it_);
} else {
BaseIter::valid(false);
......@@ -500,7 +508,11 @@ BoundaryFaceIter& BoundaryFaceIter::operator--() {
BoundaryFaceIter& BoundaryFaceIter::operator++() {
++bf_it_;
if(bf_it_ != BaseIter::mesh()->boundary_faces_.end()) {
while(bf_it_ != BaseIter::mesh()->faces_end() &&
!BaseIter::mesh()->is_boundary(*bf_it_)) {
++bf_it_;
}
if(bf_it_ != BaseIter::mesh()->faces_end()) {
BaseIter::cur_handle(*bf_it_);
} else {
BaseIter::valid(false);
......
......@@ -567,62 +567,6 @@ private:
//===========================================================================
class BoundaryFaceIter : public BaseIterator<FaceHandle,FaceHandle> {
public:
typedef BaseIterator<
FaceHandle,
FaceHandle> BaseIter;
BoundaryFaceIter(const TopologyKernel* _mesh);
// Post increment/decrement operator
BoundaryFaceIter operator++(int) {
BoundaryFaceIter cpy = *this;
++(*this);
return cpy;
}
BoundaryFaceIter operator--(int) {
BoundaryFaceIter cpy = *this;
--(*this);
return cpy;
}
BoundaryFaceIter operator+(int _n) {
BoundaryFaceIter cpy = *this;
for(int i = 0; i < _n; ++i) {
++cpy;
}
return cpy;
}
BoundaryFaceIter operator-(int _n) {
BoundaryFaceIter cpy = *this;
for(int i = 0; i < _n; ++i) {
--cpy;
}
return cpy;
}
BoundaryFaceIter& operator+=(int _n) {
for(int i = 0; i < _n; ++i) {
++(*this);
}
return *this;
}
BoundaryFaceIter& operator-=(int _n) {
for(int i = 0; i < _n; ++i) {
--(*this);
}
return *this;
}
BoundaryFaceIter& operator++();
BoundaryFaceIter& operator--();
private:
std::vector<FaceHandle>::const_iterator bf_it_;
};
//===========================================================================
class VertexIter : public BaseIterator<
VertexHandle,
VertexHandle> {
......@@ -971,6 +915,62 @@ private:
//===========================================================================
class BoundaryFaceIter : public BaseIterator<FaceHandle,FaceHandle> {
public:
typedef BaseIterator<
FaceHandle,
FaceHandle> BaseIter;
BoundaryFaceIter(const TopologyKernel* _mesh);
// Post increment/decrement operator
BoundaryFaceIter operator++(int) {
BoundaryFaceIter cpy = *this;
++(*this);
return cpy;
}
BoundaryFaceIter operator--(int) {
BoundaryFaceIter cpy = *this;
--(*this);
return cpy;
}
BoundaryFaceIter operator+(int _n) {
BoundaryFaceIter cpy = *this;
for(int i = 0; i < _n; ++i) {
++cpy;
}
return cpy;
}
BoundaryFaceIter operator-(int _n) {
BoundaryFaceIter cpy = *this;
for(int i = 0; i < _n; ++i) {
--cpy;
}
return cpy;
}
BoundaryFaceIter& operator+=(int _n) {
for(int i = 0; i < _n; ++i) {
++(*this);
}
return *this;
}
BoundaryFaceIter& operator-=(int _n) {
for(int i = 0; i < _n; ++i) {
--(*this);
}
return *this;
}
BoundaryFaceIter& operator++();
BoundaryFaceIter& operator--();
private:
FaceIter bf_it_;
};
//===========================================================================
} // Namespace OpenVolumeMesh
#endif /* ITERATORS_HH_ */
......@@ -44,6 +44,9 @@
#define OPENVOLUMEMESHHANDLE_HH_
#include <iostream>
#include <vector>
#include <tr1/functional>
#include <algorithm>
namespace OpenVolumeMesh {
......@@ -90,6 +93,52 @@ class CellHandle : public OpenVolumeMeshHandle { public: CellHandle(int _idx
class HalfEdgeHandle : public OpenVolumeMeshHandle { public: HalfEdgeHandle(int _idx = -1) : OpenVolumeMeshHandle(_idx) {} };
class HalfFaceHandle : public OpenVolumeMeshHandle { public: HalfFaceHandle(int _idx = -1) : OpenVolumeMeshHandle(_idx) {} };
// Helper class that is used to decrease all handles
// exceeding a certain threshold
class VHandleCorrection {
public:
VHandleCorrection(VertexHandle _thld) : thld_(_thld) {}
void correctValue(VertexHandle& _h) {
if(_h > thld_) _h.idx(_h.idx() - 1);
}
private:
VertexHandle thld_;
};
class HEHandleCorrection {
public:
HEHandleCorrection(HalfEdgeHandle _thld) : thld_(_thld) {}
void correctVecValue(std::vector<HalfEdgeHandle>& _vec) {
std::for_each(_vec.begin(), _vec.end(), std::tr1::bind(&HEHandleCorrection::correctValue, this, std::tr1::placeholders::_1));
}
void correctValue(HalfEdgeHandle& _h) {
if(_h > thld_) _h.idx(_h.idx() - 2);
}
private:
HalfEdgeHandle thld_;
};
class HFHandleCorrection {
public:
HFHandleCorrection(HalfFaceHandle _thld) : thld_(_thld) {}
void correctVecValue(std::vector<HalfFaceHandle>& _vec) {
std::for_each(_vec.begin(), _vec.end(), std::tr1::bind(&HFHandleCorrection::correctValue, this, std::tr1::placeholders::_1));
}
void correctValue(HalfFaceHandle& _h) {
if(_h > thld_) _h.idx(_h.idx() - 2);
}
private:
HalfFaceHandle thld_;
};
class CHandleCorrection {
public:
CHandleCorrection(CellHandle _thld) : thld_(_thld) {}
void correctValue(CellHandle& _h) {
if(_h > thld_) _h.idx(_h.idx() - 1);
}
private:
CellHandle thld_;
};
std::ostream& operator<<(std::ostream& _ostr, const OpenVolumeMeshHandle& _handle);
std::istream& operator>>(std::istream& _istr, OpenVolumeMeshHandle& _handle);
......
This diff is collapsed.
This diff is collapsed.
......@@ -80,6 +80,9 @@ bool FileManager::readFile(const std::string& _filename, MeshT& _mesh,
Point v = Point(0.0, 0.0, 0.0);
unsigned int v1 = 0; unsigned int v2 = 0;
_mesh.clear();
_mesh.enable_bottom_up_adjacencies(_computeBottomUpAdjacencies);
/*
* Header
*/
......@@ -276,11 +279,6 @@ bool FileManager::readFile(const std::string& _filename, MeshT& _mesh,
iff.close();
// Compute top-down-adjacencies
if(_computeBottomUpAdjacencies) {
_mesh.update_adjacencies();
}
std::cerr << "######## openvolumemesh info #########" << std::endl;
std::cerr << "#vertices: " << _mesh.n_vertices() << std::endl;
std::cerr << "#edges: " << _mesh.n_edges() << std::endl;
......
......@@ -57,7 +57,7 @@ CellSheetCellIter::CellSheetCellIter(const CellHandle& _ref_h,
const unsigned char _orthDir, const HexahedralMeshTopologyKernel* _mesh) :
BaseIter(_mesh, _ref_h) {
if(!_mesh->has_bottom_up_adjacencies()) {
if(!_mesh->has_face_bottom_up_adjacencies()) {
std::cerr << "This iterator needs bottom-up adjacencies!" << std::endl;
BaseIter::valid(false);
return;
......@@ -117,7 +117,7 @@ HalfFaceSheetHalfFaceIter::HalfFaceSheetHalfFaceIter(const HalfFaceHandle& _ref_
const HexahedralMeshTopologyKernel* _mesh) :
BaseIter(_mesh, _ref_h) {
if(!_mesh->has_bottom_up_adjacencies()) {
if(!_mesh->has_face_bottom_up_adjacencies()) {
std::cerr << "This iterator needs bottom-up adjacencies!" << std::endl;
BaseIter::valid(false);
return;
......@@ -210,7 +210,7 @@ OutsideNeighborHalfFaceIter::OutsideNeighborHalfFaceIter(const HalfFaceHandle& _
const HexahedralMeshTopologyKernel* _mesh) :
BaseIter(_mesh, _ref_h) {
if(!_mesh->has_bottom_up_adjacencies()) {
if(!_mesh->has_face_bottom_up_adjacencies()) {
std::cerr << "This iterator needs bottom-up adjacencies!" << std::endl;
BaseIter::valid(false);
return;
......
......@@ -250,7 +250,7 @@ public:
HalfFaceHandle adjacent_halfface_on_sheet(const HalfFaceHandle& _hfh, const HalfEdgeHandle& _heh) const {
if(!TopologyKernel::has_bottom_up_adjacencies()) {
if(!TopologyKernel::has_face_bottom_up_adjacencies()) {
std::cerr << "No bottom-up adjacencies computed so far, could not get adjacent halfface on sheet!" << std::endl;
return TopologyKernel::InvalidHalfFaceHandle;
}
......@@ -307,7 +307,7 @@ public:
HalfFaceHandle neighboring_outside_halfface(const HalfFaceHandle& _hfh, const HalfEdgeHandle& _heh) const {
if(!TopologyKernel::has_bottom_up_adjacencies()) {
if(!TopologyKernel::has_face_bottom_up_adjacencies()) {
std::cerr << "No bottom-up adjacencies computed so far, could not get neighboring outside halfface!" << std::endl;
return TopologyKernel::InvalidHalfFaceHandle;
}
......
......@@ -16,8 +16,6 @@ using namespace OpenVolumeMesh;
* ====================================================================
*/
/*
*/
TEST_F(PolyhedralMeshBase, CreateSimpleMesh) {
/*
......@@ -497,8 +495,6 @@ TEST_F(PolyhedralMeshBase, VolumeMeshConnectivity) {
EXPECT_EQ(PolyhedralMesh::InvalidCellHandle, i_cell);
mesh_.update_adjacencies();
EXPECT_EQ(CellHandle(0), mesh_.incident_cell(1));
EXPECT_EQ(CellHandle(0), mesh_.incident_cell(2));
EXPECT_EQ(CellHandle(0), mesh_.incident_cell(5));
......@@ -572,9 +568,9 @@ TEST_F(PolyhedralMeshBase, VolumeMeshNormals) {
// Should be positive y-axis
n = normals[FaceHandle(5)];
EXPECT_DOUBLE_EQ(n_y[0], n[0]);
EXPECT_DOUBLE_EQ(n_y[1], n[1]);
EXPECT_DOUBLE_EQ(n_y[2], n[2]);
EXPECT_DOUBLE_EQ(-n_y[0], n[0]);
EXPECT_DOUBLE_EQ(-n_y[1], n[1]);
EXPECT_DOUBLE_EQ(-n_y[2], n[2]);
}
TEST_F(PolyhedralMeshBase, PolyhedralMeshStatusTest) {
......@@ -758,8 +754,6 @@ TEST_F(HexahedralMeshBase, SimpleHexMeshNavigation) {
EXPECT_EQ(12, mesh_.opposite_halfface_handle_in_cell(
HalfFaceHandle(3), CellHandle(1)));
mesh_.update_adjacencies();
EXPECT_EQ(HalfFaceHandle(20), mesh_.adjacent_halfface_on_sheet(
HalfFaceHandle(9), HalfEdgeHandle(12)));
EXPECT_EQ(HalfFaceHandle(21), mesh_.adjacent_halfface_on_sheet(
......@@ -778,8 +772,6 @@ TEST_F(HexahedralMeshBase, GarbageCollectionTest1) {
generateHexahedralMesh(mesh_);
mesh_.update_adjacencies();
EXPECT_EQ(12u, mesh_.n_vertices());
EXPECT_EQ(20u, mesh_.n_edges());
EXPECT_EQ(11u, mesh_.n_faces());
......@@ -808,8 +800,6 @@ TEST_F(HexahedralMeshBase, GarbageCollectionTest2) {
generateHexahedralMesh(mesh_);
mesh_.update_adjacencies();
StatusAttrib status(mesh_);
status[VertexHandle(0)].set_deleted(true);
......@@ -828,8 +818,6 @@ TEST_F(HexahedralMeshBase, GarbageCollectionTest3) {
generateHexahedralMesh(mesh_);
mesh_.update_adjacencies();
StatusAttrib status(mesh_);
status[EdgeHandle(0)].set_deleted(true);
......@@ -846,8 +834,6 @@ TEST_F(HexahedralMeshBase, GarbageCollectionTest4) {
generateHexahedralMesh(mesh_);
mesh_.update_adjacencies();
StatusAttrib status(mesh_);
status[EdgeHandle(5)].set_deleted(true);
......@@ -864,8 +850,6 @@ TEST_F(HexahedralMeshBase, GarbageCollectionTestManifoldness1) {
generateHexahedralMesh(mesh_);
mesh_.update_adjacencies();
StatusAttrib status(mesh_);
status[VertexHandle(0)].set_deleted(true);
......@@ -882,8 +866,6 @@ TEST_F(HexahedralMeshBase, GarbageCollectionTestManifoldness2) {
generateHexahedralMesh(mesh_);
mesh_.update_adjacencies();
StatusAttrib status(mesh_);
status[EdgeHandle(0)].set_deleted(true);
......@@ -900,8 +882,6 @@ TEST_F(HexahedralMeshBase, GarbageCollectionTestManifoldness3) {
generateHexahedralMesh(mesh_);
mesh_.update_adjacencies();
StatusAttrib status(mesh_);
status[FaceHandle(0)].set_deleted(true);
......@@ -918,8 +898,6 @@ TEST_F(HexahedralMeshBase, GarbageCollectionTestManifoldness4) {
generateHexahedralMesh(mesh_);
mesh_.update_adjacencies();
StatusAttrib status(mesh_);
status[CellHandle(0)].set_deleted(true);
......@@ -936,8 +914,6 @@ TEST_F(HexahedralMeshBase, GarbageCollectionTestManifoldness5) {
generateHexahedralMesh(mesh_);
mesh_.update_adjacencies();
StatusAttrib status(mesh_);
status[EdgeHandle(5)].set_deleted(true);
......@@ -961,8 +937,6 @@ TEST_F(HexahedralMeshBase, GarbageCollectionTestProps1) {
generateHexahedralMesh(mesh_);
mesh_.update_adjacencies();
StatusAttrib status(mesh_);
FacePropertyT<int> fprop = mesh_.request_face_property<int>("FProp");
......@@ -1010,8 +984,6 @@ TEST_F(HexahedralMeshBase, GarbageCollectionTestProps2) {
generateHexahedralMesh(mesh_);
mesh_.update_adjacencies();
StatusAttrib status(mesh_);
FacePropertyT<int> fprop = mesh_.request_face_property<int>("FProp");
......
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