Commit 267a04bd authored by Max Lyon's avatar Max Lyon
Browse files

implemented fast and deferred deletion of entities

fast: swap deleted entity with last in vector, resize vector
deferred: only mark entity as deleted, keep deleted entity in vector
parent 4ebfee6c
......@@ -67,6 +67,8 @@ public:
virtual void delete_element(size_t _idx) = 0;
virtual void swap_elements(size_t _idx0, size_t _idx1) = 0;
virtual void serialize(std::ostream& _ostr) const = 0;
virtual void deserialize(std::istream& _istr) = 0;
......
......@@ -95,11 +95,41 @@ public:
VertexIter nV = TopologyKernelT::delete_vertex(_h);
if (TopologyKernelT::deferred_deletion_enabled())
{
}
else
vertices_.erase(vertices_.begin() + _h.idx());
return nV;
}
virtual void collect_garbage()
{
TopologyKernelT::collect_garbage();
for (unsigned int i = vertices_.size(); i > 0; --i)
if (TopologyKernelT::is_deleted(VertexHandle(i-1)))
{
vertices_.erase(vertices_.begin() + (i-1));
}
}
virtual void swap_vertices(VertexHandle _h1, VertexHandle _h2)
{
assert(_h1.idx() >= 0 && _h1.idx() < (int)vertices_.size());
assert(_h2.idx() >= 0 && _h2.idx() < (int)vertices_.size());
if (_h1 == _h2)
return;
std::swap(vertices_[_h1.idx()], vertices_[_h2.idx()]);
TopologyKernelT::swap_vertices(_h1, _h2);
}
protected:
virtual void delete_multiple_vertices(const std::vector<bool>& _tag) {
......
......@@ -240,6 +240,10 @@ BaseIter(_mesh, _ref_h, _max_laps) {
std::sort(cells_.begin(), cells_.end());
cells_.resize(std::unique(cells_.begin(), cells_.end()) - cells_.begin());
// Remove invalid handles
if ((cells_.size() > 0) && !cells_.front().is_valid())
cells_.erase(cells_.begin());
cur_index_ = 0;
BaseIter::valid(cells_.size()>0);
if(BaseIter::valid()) {
......@@ -386,8 +390,9 @@ CellVertexIter::CellVertexIter(const CellHandle& _ref_h,
const TopologyKernel* _mesh, int _max_laps) :
BaseIter(_mesh, _ref_h, _max_laps) {
std::vector<HalfFaceHandle>::const_iterator hf_iter = BaseIter::mesh()->cell(_ref_h).halffaces().begin();
for(; hf_iter != BaseIter::mesh()->cell(_ref_h).halffaces().end(); ++hf_iter) {
OpenVolumeMeshCell c = BaseIter::mesh()->cell(_ref_h);
std::vector<HalfFaceHandle>::const_iterator hf_iter = c.halffaces().begin();
for(; hf_iter != c.halffaces().end(); ++hf_iter) {
const OpenVolumeMeshFace& halfface = BaseIter::mesh()->halfface(*hf_iter);
const std::vector<HalfEdgeHandle>& hes = halfface.halfedges();
for(std::vector<HalfEdgeHandle>::const_iterator he_iter = hes.begin(); he_iter != hes.end(); ++he_iter) {
......@@ -661,7 +666,8 @@ bf_it_(_mesh->faces_begin()) {
}
while(bf_it_ != BaseIter::mesh()->faces_end() &&
!BaseIter::mesh()->is_boundary(*bf_it_)) {
!BaseIter::mesh()->is_boundary(*bf_it_) &&
BaseIter::mesh()->is_deleted(bf_it_.cur_handle())){
++bf_it_;
}
BaseIter::valid(bf_it_ != BaseIter::mesh()->faces_end());
......@@ -675,7 +681,8 @@ BoundaryFaceIter& BoundaryFaceIter::operator--() {
--bf_it_;
while(bf_it_ >= BaseIter::mesh()->faces_begin() &&
!BaseIter::mesh()->is_boundary(*bf_it_)) {
!BaseIter::mesh()->is_boundary(*bf_it_) &&
BaseIter::mesh()->is_deleted(bf_it_.cur_handle())){
--bf_it_;
}
if(bf_it_ >= BaseIter::mesh()->faces_begin()) {
......@@ -691,7 +698,8 @@ BoundaryFaceIter& BoundaryFaceIter::operator++() {
++bf_it_;
while(bf_it_ != BaseIter::mesh()->faces_end() &&
!BaseIter::mesh()->is_boundary(*bf_it_)) {
!BaseIter::mesh()->is_boundary(*bf_it_) &&
BaseIter::mesh()->is_deleted(bf_it_.cur_handle())){
++bf_it_;
}
if(bf_it_ != BaseIter::mesh()->faces_end()) {
......@@ -711,18 +719,20 @@ VertexIter::VertexIter(const TopologyKernel* _mesh, const VertexHandle& _vh) :
BaseIter(_mesh, _vh),
cur_index_(_vh.idx()) {
while ((unsigned int)cur_index_ < BaseIter::mesh()->n_vertices() && BaseIter::mesh()->is_deleted(VertexHandle(cur_index_)))
++cur_index_;
if((unsigned int)cur_index_ >= BaseIter::mesh()->n_vertices()) {
BaseIter::valid(false);
}
if(BaseIter::valid()) {
BaseIter::cur_handle(VertexHandle(cur_index_));
}
}
VertexIter& VertexIter::operator--() {
--cur_index_;
while (cur_index_ >= 0 && BaseIter::mesh()->is_deleted(VertexHandle(cur_index_)))
--cur_index_;
if(cur_index_ < 0) {
BaseIter::valid(false);
}
......@@ -733,6 +743,8 @@ VertexIter& VertexIter::operator--() {
VertexIter& VertexIter::operator++() {
++cur_index_;
while ((unsigned int)cur_index_ < BaseIter::mesh()->n_vertices() && BaseIter::mesh()->is_deleted(VertexHandle(cur_index_)))
++cur_index_;
if((unsigned int)cur_index_ >= BaseIter::mesh()->n_vertices()) {
BaseIter::valid(false);
......@@ -750,18 +762,20 @@ EdgeIter::EdgeIter(const TopologyKernel* _mesh, const EdgeHandle& _eh) :
BaseIter(_mesh, _eh),
cur_index_(_eh.idx()) {
while ((unsigned int)cur_index_ < BaseIter::mesh()->edges_.size() && BaseIter::mesh()->is_deleted(EdgeHandle(cur_index_)))
++cur_index_;
if((unsigned int)cur_index_ >= BaseIter::mesh()->edges_.size()) {
BaseIter::valid(false);
}
if(BaseIter::valid()) {
BaseIter::cur_handle(EdgeHandle(cur_index_));
}
}
EdgeIter& EdgeIter::operator--() {
--cur_index_;
while (cur_index_ >= 0 && BaseIter::mesh()->is_deleted(EdgeHandle(cur_index_)))
--cur_index_;
if(cur_index_ < 0) {
BaseIter::valid(false);
}
......@@ -773,6 +787,8 @@ EdgeIter& EdgeIter::operator--() {
EdgeIter& EdgeIter::operator++() {
++cur_index_;
while ((unsigned int)cur_index_ < BaseIter::mesh()->edges_.size() && BaseIter::mesh()->is_deleted(EdgeHandle(cur_index_)))
++cur_index_;
if((unsigned int)cur_index_ >= BaseIter::mesh()->edges_.size()) {
BaseIter::valid(false);
}
......@@ -789,18 +805,20 @@ HalfEdgeIter::HalfEdgeIter(const TopologyKernel* _mesh, const HalfEdgeHandle& _h
BaseIter(_mesh, _heh),
cur_index_(_heh.idx()) {
while ((unsigned int)cur_index_ < BaseIter::mesh()->edges_.size() * 2 && BaseIter::mesh()->is_deleted(HalfEdgeHandle(cur_index_)))
++cur_index_;
if((unsigned int)cur_index_ >= BaseIter::mesh()->edges_.size() * 2) {
BaseIter::valid(false);
}
if(BaseIter::valid()) {
BaseIter::cur_handle(HalfEdgeHandle(cur_index_));
}
}
HalfEdgeIter& HalfEdgeIter::operator--() {
--cur_index_;
while (cur_index_ >= 0 && BaseIter::mesh()->is_deleted(HalfEdgeHandle(cur_index_)))
--cur_index_;
if(cur_index_ < 0) {
BaseIter::valid(false);
}
......@@ -812,6 +830,8 @@ HalfEdgeIter& HalfEdgeIter::operator--() {
HalfEdgeIter& HalfEdgeIter::operator++() {
++cur_index_;
while ((unsigned int)cur_index_ < BaseIter::mesh()->edges_.size() * 2 && BaseIter::mesh()->is_deleted(HalfEdgeHandle(cur_index_)))
++cur_index_;
if((unsigned int)cur_index_ >= BaseIter::mesh()->edges_.size() * 2) {
BaseIter::valid(false);
}
......@@ -828,18 +848,20 @@ FaceIter::FaceIter(const TopologyKernel* _mesh, const FaceHandle& _fh) :
BaseIter(_mesh, _fh),
cur_index_(_fh.idx()) {
while ((unsigned int)cur_index_ < BaseIter::mesh()->faces_.size() && BaseIter::mesh()->is_deleted(FaceHandle(cur_index_)))
++cur_index_;
if((unsigned int)cur_index_ >= BaseIter::mesh()->faces_.size()) {
BaseIter::valid(false);
}
if(BaseIter::valid()) {
BaseIter::cur_handle(FaceHandle(cur_index_));
}
}
FaceIter& FaceIter::operator--() {
--cur_index_;
while (cur_index_ >= 0 && BaseIter::mesh()->is_deleted(FaceHandle(cur_index_)))
--cur_index_;
if(cur_index_ < 0) {
BaseIter::valid(false);
}
......@@ -851,6 +873,8 @@ FaceIter& FaceIter::operator--() {
FaceIter& FaceIter::operator++() {
++cur_index_;
while ((unsigned int)cur_index_ < BaseIter::mesh()->faces_.size() && BaseIter::mesh()->is_deleted(FaceHandle(cur_index_)))
++cur_index_;
if((unsigned int)cur_index_ >= BaseIter::mesh()->faces_.size()) {
BaseIter::valid(false);
}
......@@ -867,18 +891,20 @@ HalfFaceIter::HalfFaceIter(const TopologyKernel* _mesh, const HalfFaceHandle& _h
BaseIter(_mesh, _hfh),
cur_index_(_hfh.idx()) {
while ((unsigned int)cur_index_ < BaseIter::mesh()->faces_.size() * 2 && BaseIter::mesh()->is_deleted(HalfFaceHandle(cur_index_)))
++cur_index_;
if((unsigned int)cur_index_ >= BaseIter::mesh()->faces_.size() * 2) {
BaseIter::valid(false);
}
if(BaseIter::valid()) {
BaseIter::cur_handle(HalfFaceHandle(cur_index_));
}
}
HalfFaceIter& HalfFaceIter::operator--() {
--cur_index_;
while (cur_index_ >= 0 && BaseIter::mesh()->is_deleted(HalfFaceHandle(cur_index_)))
--cur_index_;
if(cur_index_ < 0) {
BaseIter::valid(false);
}
......@@ -890,6 +916,8 @@ HalfFaceIter& HalfFaceIter::operator--() {
HalfFaceIter& HalfFaceIter::operator++() {
++cur_index_;
while ((unsigned int)cur_index_ < BaseIter::mesh()->faces_.size() * 2 && BaseIter::mesh()->is_deleted(HalfFaceHandle(cur_index_)))
++cur_index_;
if((unsigned int)cur_index_ >= BaseIter::mesh()->faces_.size() * 2) {
BaseIter::valid(false);
}
......@@ -906,18 +934,20 @@ CellIter::CellIter(const TopologyKernel* _mesh, const CellHandle& _ch) :
BaseIter(_mesh, _ch),
cur_index_(_ch.idx()) {
while ((unsigned int)cur_index_ < BaseIter::mesh()->cells_.size() && BaseIter::mesh()->is_deleted(CellHandle(cur_index_)))
++cur_index_;
if((unsigned int)cur_index_ >= BaseIter::mesh()->cells_.size()) {
BaseIter::valid(false);
}
if(BaseIter::valid()) {
BaseIter::cur_handle(CellHandle(cur_index_));
}
}
CellIter& CellIter::operator--() {
--cur_index_;
while (cur_index_ >= 0 && BaseIter::mesh()->is_deleted(CellHandle(cur_index_)))
--cur_index_;
if(cur_index_ < 0) {
BaseIter::valid(false);
}
......@@ -929,6 +959,8 @@ CellIter& CellIter::operator--() {
CellIter& CellIter::operator++() {
++cur_index_;
while ((unsigned int)cur_index_ < BaseIter::mesh()->cells_.size() && BaseIter::mesh()->is_deleted(CellHandle(cur_index_)))
++cur_index_;
if((unsigned int)cur_index_ >= BaseIter::mesh()->cells_.size()) {
BaseIter::valid(false);
}
......
......@@ -83,6 +83,8 @@ public:
virtual void delete_element(size_t _idx);
virtual void swap_elements(size_t _idx0, size_t _idx1);
const_iterator begin() const { return ptr::shared_ptr<PropT>::get()->begin(); }
iterator begin() { return ptr::shared_ptr<PropT>::get()->begin(); }
......
......@@ -83,6 +83,11 @@ void PropertyPtr<PropT,HandleT>::delete_element(size_t _idx) {
ptr::shared_ptr<PropT>::get()->delete_element(_idx);
}
template <class PropT, class HandleT>
void PropertyPtr<PropT,HandleT>::swap_elements(size_t _idx0, size_t _idx1) {
ptr::shared_ptr<PropT>::get()->swap(_idx0, _idx1);
}
template <class PropT, class HandleT>
void PropertyPtr<PropT,HandleT>::set_handle(const OpenVolumeMeshHandle& _handle) {
return ptr::shared_ptr<PropT>::get()->set_handle(_handle);
......
......@@ -106,6 +106,36 @@ void ResourceManager::cell_deleted(const CellHandle& _h) {
entity_deleted(cell_props_, _h);
}
void ResourceManager::swap_cell_properties(CellHandle _h1, CellHandle _h2){
swap_property_elements(cell_props_begin(), cell_props_end(), _h1, _h2);
}
void ResourceManager::swap_face_properties(FaceHandle _h1, FaceHandle _h2){
swap_property_elements(face_props_begin(), face_props_end(), _h1, _h2);
}
void ResourceManager::swap_halfface_properties(HalfFaceHandle _h1, HalfFaceHandle _h2){
swap_property_elements(halfface_props_begin(), halfface_props_end(), _h1, _h2);
}
void ResourceManager::swap_edge_properties(EdgeHandle _h1, EdgeHandle _h2){
swap_property_elements(edge_props_begin(), edge_props_end(), _h1, _h2);
}
void ResourceManager::swap_halfedge_properties(HalfEdgeHandle _h1, HalfEdgeHandle _h2){
swap_property_elements(halfedge_props_begin(), halfedge_props_end(), _h1, _h2);
}
void ResourceManager::swap_vertex_properties(VertexHandle _h1, VertexHandle _h2){
swap_property_elements(vertex_props_begin(), vertex_props_end(), _h1, _h2);
}
void ResourceManager::release_property(VertexPropHandle _handle) {
remove_property(vertex_props_, _handle.idx());
......
......@@ -102,6 +102,27 @@ protected:
void cell_deleted(const CellHandle& _h);
void swap_cell_properties(CellHandle _h1, CellHandle _h2);
void swap_face_properties(FaceHandle _h1, FaceHandle _h2);
void swap_halfface_properties(HalfFaceHandle _h1, HalfFaceHandle _h2);
void swap_edge_properties(EdgeHandle _h1, EdgeHandle _h2);
void swap_halfedge_properties(HalfEdgeHandle _h1, HalfEdgeHandle _h2);
void swap_vertex_properties(VertexHandle _h1, VertexHandle _h2);
template <typename PropIterator, typename Handle>
void swap_property_elements(PropIterator _begin, PropIterator _end, Handle _h1, Handle _h2)
{
PropIterator p_iter = _begin;
for (; p_iter != _end; ++p_iter)
(*p_iter)->swap_elements(_h1, _h2);
}
public:
void clear_vertex_props() { clearVec(vertex_props_); }
......
......@@ -63,8 +63,10 @@ TopologyKernel::TopologyKernel() :
n_vertices_(0u),
v_bottom_up_(true),
e_bottom_up_(true),
f_bottom_up_(true) {
f_bottom_up_(true),
deferred_deletion(true),
fast_deletion(true)
{
}
TopologyKernel::~TopologyKernel() {
......@@ -75,6 +77,7 @@ TopologyKernel::~TopologyKernel() {
VertexHandle TopologyKernel::add_vertex() {
++n_vertices_;
vertex_deleted_.push_back(false);
// Create item for vertex bottom-up incidences
if(v_bottom_up_) {
......@@ -128,6 +131,7 @@ EdgeHandle TopologyKernel::add_edge(const VertexHandle& _fromVertex,
// Store edge locally
edges_.push_back(e);
edge_deleted_.push_back(false);
// Resize props
resize_eprops(n_edges());
......@@ -209,6 +213,7 @@ FaceHandle TopologyKernel::add_face(const std::vector<HalfEdgeHandle>& _halfedge
OpenVolumeMeshFace face(_halfedges);
faces_.push_back(face);
face_deleted_.push_back(false);
// Get added face's handle
FaceHandle fh(faces_.size() - 1);
......@@ -329,6 +334,9 @@ void TopologyKernel::reorder_incident_halffaces(const EdgeHandle& _eh) {
// End when we're through
if(cur_hf == start_hf) break;
// if one of the faces of the cell was already incident to another cell we need this check
// to prevent running into an infinite loop.
if(std::find(new_halffaces.begin(), new_halffaces.end(), cur_hf) != new_halffaces.end()) break;
}
// First direction has terminated
......@@ -350,6 +358,9 @@ void TopologyKernel::reorder_incident_halffaces(const EdgeHandle& _eh) {
if(cur_hf != InvalidHalfFaceHandle)
new_halffaces.insert(new_halffaces.begin(), cur_hf);
else break;
// if one of the faces of the cell was already incident to another cell we need this check
// to prevent running into an infinite loop.
if(std::find(new_halffaces.begin(), new_halffaces.end(), cur_hf) != new_halffaces.end()) break;
}
}
......@@ -412,6 +423,7 @@ CellHandle TopologyKernel::add_cell(const std::vector<HalfFaceHandle>& _halfface
OpenVolumeMeshCell cell(_halffaces);
cells_.push_back(cell);
cell_deleted_.push_back(false);
// Resize props
resize_cprops(n_cells());
......@@ -702,6 +714,49 @@ CellIter TopologyKernel::delete_cell(const CellHandle& _h) {
return delete_cell_core(_h);
}
/**
* \brief Delete all entities that are marked as deleted
*/
void TopologyKernel::collect_garbage()
{
if (!deferred_deletion_enabled())
return; // nothing todo
enable_deferred_deletion(false);
for (unsigned int i = n_cells(); i > 0; --i)
if (is_deleted(CellHandle(i-1)))
{
cell_deleted_[i-1] = false;
delete_cell_core(CellHandle(i-1));
}
for (unsigned int i = n_faces(); i > 0; --i)
if (is_deleted(FaceHandle(i-1)))
{
face_deleted_[i-1] = false;
delete_face_core(FaceHandle(i-1));
}
for (unsigned int i = n_edges(); i > 0; --i)
if (is_deleted(EdgeHandle(i-1)))
{
edge_deleted_[i-1] = false;
delete_edge_core(EdgeHandle(i-1));
}
for (unsigned int i = n_vertices(); i > 0; --i)
if (is_deleted(VertexHandle(i-1)))
{
vertex_deleted_[i-1] = false;
delete_vertex_core(VertexHandle(i-1));
}
enable_deferred_deletion();
}
//========================================================================================
template <class ContainerT>
......@@ -852,13 +907,32 @@ void TopologyKernel::get_incident_cells(const ContainerT& _fs,
*/
VertexIter TopologyKernel::delete_vertex_core(const VertexHandle& _h) {
assert(_h.is_valid() && (size_t)_h.idx() < n_vertices());
VertexHandle h = _h;
assert(h.is_valid() && (size_t)h.idx() < n_vertices());
if (fast_deletion_enabled() && !deferred_deletion_enabled()) // for fast deletion swap handle with last not deleted vertex
{
VertexHandle last_undeleted_vertex = VertexHandle(n_vertices()-1);
swap_vertices(h, last_undeleted_vertex);
h = last_undeleted_vertex;
}
if (deferred_deletion_enabled())
{
vertex_deleted_[h.idx()] = true;
// deleted_vertices_.push_back(h);
// Iterator to next element in vertex list
// return (vertices_begin() + h.idx()+1);
return VertexIter(this, VertexHandle(h.idx()+1));
}
else
{
// 1)
if(v_bottom_up_) {
// Decrease all vertex handles >= _h in all edge definitions
for(int i = _h.idx(), end = n_vertices(); i < end; ++i) {
for(int i = h.idx(), end = n_vertices(); i < end; ++i) {
const std::vector<HalfEdgeHandle>& hes = outgoing_hes_per_vertex_[i];
for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
he_end = hes.end(); he_it != he_end; ++he_it) {
......@@ -880,29 +954,37 @@ VertexIter TopologyKernel::delete_vertex_core(const VertexHandle& _h) {
e_it != e_end; ++e_it) {
// Decrease all vertex handles in edge definitions that are greater than _h
if(edge(*e_it).from_vertex() > _h) {
if(edge(*e_it).from_vertex() > h) {
edge(*e_it).set_from_vertex(VertexHandle(edge(*e_it).from_vertex().idx() - 1));
}
if(edge(*e_it).to_vertex() > _h) {
if(edge(*e_it).to_vertex() > h) {
edge(*e_it).set_to_vertex(VertexHandle(edge(*e_it).to_vertex().idx() - 1));
}
}
}
// 2)
if(v_bottom_up_) {
assert((size_t)_h.idx() < outgoing_hes_per_vertex_.size());
outgoing_hes_per_vertex_.erase(outgoing_hes_per_vertex_.begin() + _h.idx());
assert((size_t)h.idx() < outgoing_hes_per_vertex_.size());
outgoing_hes_per_vertex_.erase(outgoing_hes_per_vertex_.begin() + h.idx());
}
// 3)
--n_vertices_;
vertex_deleted_.erase(vertex_deleted_.begin() + h.idx());
// 4)
vertex_deleted(_h);
vertex_deleted(h);
// Iterator to next element in vertex list
return (vertices_begin() + _h.idx());
// return (vertices_begin() + h.idx());
return VertexIter(this, h);
}
}
//========================================================================================
......@@ -928,40 +1010,64 @@ VertexIter TopologyKernel::delete_vertex_core(const VertexHandle& _h) {
*/
EdgeIter TopologyKernel::delete_edge_core(const EdgeHandle& _h) {
assert(_h.is_valid() && (size_t)_h.idx() < edges_.size());
EdgeHandle h = _h;
assert(h.is_valid() && (size_t)h.idx() < edges_.size());
if (fast_deletion_enabled() && !deferred_deletion_enabled()) // for fast deletion swap handle with last one
{
EdgeHandle last_edge = EdgeHandle(edges_.size()-1);
swap_edges(h, last_edge);
h = last_edge;
}
// 1)
if(v_bottom_up_) {
VertexHandle v0 = edge(_h).from_vertex();
VertexHandle v1 = edge(_h).to_vertex();
VertexHandle v0 = edge(h).from_vertex();
VertexHandle v1 = edge(h).to_vertex();
assert(v0.is_valid() && (size_t)v0.idx() < outgoing_hes_per_vertex_.size());
assert(v1.is_valid() && (size_t)v1.idx() < outgoing_hes_per_vertex_.size());
outgoing_hes_per_vertex_[v0.idx()].erase(
std::remove(outgoing_hes_per_vertex_[v0.idx()].begin(),