Loading...
Searching...
No Matches
DecimaterT_impl.hh
Go to the documentation of this file.
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2025, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
//=============================================================================
//
// CLASS DecimaterT - IMPLEMENTATION
//
//=============================================================================
#define OPENMESH_DECIMATER_DECIMATERT_CC
//== INCLUDES =================================================================
#include <OpenMesh/Tools/Decimater/DecimaterT.hh>
#include <vector>
#if defined(OM_CC_MIPS)
# include <float.h>
#else
# include <cfloat>
#endif
//== NAMESPACE ===============================================================
namespace OpenMesh {
namespace Decimater {
//== IMPLEMENTATION ==========================================================
template<class Mesh>
DecimaterT<Mesh>::DecimaterT(Mesh& _mesh) :
BaseDecimaterT<Mesh>(_mesh),
mesh_(_mesh),
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
heap_(nullptr)
#else
heap_(nullptr)
#endif
{
// private vertex properties
mesh_.add_property(collapse_target_);
mesh_.add_property(priority_);
mesh_.add_property(heap_position_);
}
//-----------------------------------------------------------------------------
template<class Mesh>
DecimaterT<Mesh>::~DecimaterT() {
// private vertex properties
mesh_.remove_property(collapse_target_);
mesh_.remove_property(priority_);
mesh_.remove_property(heap_position_);
}
//-----------------------------------------------------------------------------
template<class Mesh>
void DecimaterT<Mesh>::heap_vertex(VertexHandle _vh) {
// std::clog << "heap_vertex: " << _vh << std::endl;
float prio, best_prio(FLT_MAX);
typename Mesh::HalfedgeHandle heh, collapse_target;
// find best target in one ring
typename Mesh::VertexOHalfedgeIter voh_it(mesh_, _vh);
for (; voh_it.is_valid(); ++voh_it) {
heh = *voh_it;
CollapseInfo ci(mesh_, heh);
if (this->is_collapse_legal(ci)) {
prio = this->collapse_priority(ci);
if (prio >= 0.0 && prio < best_prio) {
best_prio = prio;
collapse_target = heh;
}
}
}
// target found -> put vertex on heap
if (collapse_target.is_valid()) {
// std::clog << " added|updated" << std::endl;
mesh_.property(collapse_target_, _vh) = collapse_target;
mesh_.property(priority_, _vh) = best_prio;
if (heap_->is_stored(_vh))
heap_->update(_vh);
else
heap_->insert(_vh);
}
// not valid -> remove from heap
else {
// std::clog << " n/a|removed" << std::endl;
if (heap_->is_stored(_vh))
heap_->remove(_vh);
mesh_.property(collapse_target_, _vh) = collapse_target;
mesh_.property(priority_, _vh) = -1;
}
}
//-----------------------------------------------------------------------------
template<class Mesh>
size_t DecimaterT<Mesh>::decimate(size_t _n_collapses, bool _only_selected) {
if (!this->is_initialized())
return 0;
typename Mesh::VertexHandle vp;
typename Mesh::HalfedgeHandle v0v1;
typename Mesh::VertexVertexIter vv_it;
typename Mesh::VertexFaceIter vf_it;
unsigned int n_collapses(0);
typedef std::vector<typename Mesh::VertexHandle> Support;
typedef typename Support::iterator SupportIterator;
Support support(15);
SupportIterator s_it, s_end;
// check _n_collapses
if (!_n_collapses)
_n_collapses = mesh_.n_vertices();
// initialize heap
HeapInterface HI(mesh_, priority_, heap_position_);
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
heap_ = std::unique_ptr<DeciHeap>(new DeciHeap(HI));
#else
heap_ = std::auto_ptr<DeciHeap>(new DeciHeap(HI));
#endif
heap_->reserve(mesh_.n_vertices());
for ( auto v_it : mesh_.vertices() ) {
heap_->reset_heap_position(v_it);
if (!mesh_.status(v_it).deleted()) {
if (!_only_selected || mesh_.status(v_it).selected() ) {
heap_vertex(v_it);
}
}
}
const bool update_normals = mesh_.has_face_normals();
// process heap
while ((!heap_->empty()) && (n_collapses < _n_collapses)) {
// get 1st heap entry
vp = heap_->front();
v0v1 = mesh_.property(collapse_target_, vp);
heap_->pop_front();
// setup collapse info
CollapseInfo ci(mesh_, v0v1);
// check topological correctness AGAIN !
if (!this->is_collapse_legal(ci))
continue;
// store support (= one ring of *vp)
vv_it = mesh_.vv_iter(ci.v0);
support.clear();
for (; vv_it.is_valid(); ++vv_it)
support.push_back(*vv_it);
// pre-processing
this->preprocess_collapse(ci);
// perform collapse
mesh_.collapse(v0v1);
++n_collapses;
if (update_normals)
{
// update triangle normals
vf_it = mesh_.vf_iter(ci.v1);
for (; vf_it.is_valid(); ++vf_it)
if (!mesh_.status(*vf_it).deleted())
mesh_.set_normal(*vf_it, mesh_.calc_face_normal(*vf_it));
}
// post-process collapse
this->postprocess_collapse(ci);
// update heap (former one ring of decimated vertex)
for (s_it = support.begin(), s_end = support.end(); s_it != s_end; ++s_it) {
assert(!mesh_.status(*s_it).deleted());
if (!_only_selected || mesh_.status(*s_it).selected() )
heap_vertex(*s_it);
}
// notify observer and stop if the observer requests it
if (!this->notify_observer(n_collapses))
return n_collapses;
}
// delete heap
heap_.reset();
// DON'T do garbage collection here! It's up to the application.
return n_collapses;
}
//-----------------------------------------------------------------------------
template<class Mesh>
size_t DecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf, bool _only_selected) {
if (!this->is_initialized())
return 0;
if (_nv >= mesh_.n_vertices() || _nf >= mesh_.n_faces())
return 0;
typename Mesh::VertexHandle vp;
typename Mesh::HalfedgeHandle v0v1;
typename Mesh::VertexVertexIter vv_it;
typename Mesh::VertexFaceIter vf_it;
size_t nv = mesh_.n_vertices();
size_t nf = mesh_.n_faces();
unsigned int n_collapses = 0;
typedef std::vector<typename Mesh::VertexHandle> Support;
typedef typename Support::iterator SupportIterator;
Support support(15);
SupportIterator s_it, s_end;
// initialize heap
HeapInterface HI(mesh_, priority_, heap_position_);
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
heap_ = std::unique_ptr<DeciHeap>(new DeciHeap(HI));
#else
heap_ = std::auto_ptr<DeciHeap>(new DeciHeap(HI));
#endif
heap_->reserve(mesh_.n_vertices());
for ( auto v_it : mesh_.vertices() ) {
heap_->reset_heap_position(v_it);
if (!mesh_.status(v_it).deleted()) {
if (!_only_selected || mesh_.status(v_it).selected() ) {
heap_vertex(v_it);
}
}
}
const bool update_normals = mesh_.has_face_normals();
// process heap
while ((!heap_->empty()) && (_nv < nv) && (_nf < nf)) {
// get 1st heap entry
vp = heap_->front();
v0v1 = mesh_.property(collapse_target_, vp);
heap_->pop_front();
// setup collapse info
CollapseInfo ci(mesh_, v0v1);
// check topological correctness AGAIN !
if (!this->is_collapse_legal(ci))
continue;
// store support (= one ring of *vp)
vv_it = mesh_.vv_iter(ci.v0);
support.clear();
for (; vv_it.is_valid(); ++vv_it)
support.push_back(*vv_it);
// adjust complexity in advance (need boundary status)
++n_collapses;
--nv;
if (mesh_.is_boundary(ci.v0v1) || mesh_.is_boundary(ci.v1v0))
--nf;
else
nf -= 2;
// pre-processing
this->preprocess_collapse(ci);
// perform collapse
mesh_.collapse(v0v1);
// update triangle normals
if (update_normals)
{
vf_it = mesh_.vf_iter(ci.v1);
for (; vf_it.is_valid(); ++vf_it)
if (!mesh_.status(*vf_it).deleted())
mesh_.set_normal(*vf_it, mesh_.calc_face_normal(*vf_it));
}
// post-process collapse
this->postprocess_collapse(ci);
// update heap (former one ring of decimated vertex)
for (s_it = support.begin(), s_end = support.end(); s_it != s_end; ++s_it) {
assert(!mesh_.status(*s_it).deleted());
if (!_only_selected || mesh_.status(*s_it).selected() )
heap_vertex(*s_it);
}
// notify observer and stop if the observer requests it
if (!this->notify_observer(n_collapses))
return n_collapses;
}
// delete heap
heap_.reset();
// DON'T do garbage collection here! It's up to the application.
return n_collapses;
}
//=============================================================================
}// END_NS_DECIMATER
} // END_NS_OPENMESH
//=============================================================================
DecimaterT.hh
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition MeshItems.hh:59
OpenMesh::VertexHandle
Handle for a vertex entity.
Definition Handles.hh:121
OpenMesh::PolyMeshT::VertexHandle
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition PolyMeshT.hh:136
OpenMesh::PolyMeshT::VertexFaceIter
Kernel::VertexFaceIter VertexFaceIter
Circulator.
Definition PolyMeshT.hh:166
OpenMesh::PolyMeshT::VertexOHalfedgeIter
Kernel::VertexOHalfedgeIter VertexOHalfedgeIter
Circulator.
Definition PolyMeshT.hh:163
OpenMesh::PolyMeshT::HalfedgeHandle
Kernel::HalfedgeHandle HalfedgeHandle
Scalar type.
Definition PolyMeshT.hh:137
OpenMesh::PolyMeshT::VertexVertexIter
Kernel::VertexVertexIter VertexVertexIter
Circulator.
Definition PolyMeshT.hh:162
OpenMesh::Decimater::BaseDecimaterT
Definition BaseDecimaterT.hh:86
OpenMesh::Decimater::CollapseInfoT
Stores information about a halfedge collapse.
Definition CollapseInfoT.hh:74
OpenMesh::Decimater::CollapseInfoT::v0v1
Mesh::HalfedgeHandle v0v1
Halfedge to be collapsed.
Definition CollapseInfoT.hh:80
OpenMesh::Decimater::CollapseInfoT::v1v0
Mesh::HalfedgeHandle v1v0
Reverse halfedge.
Definition CollapseInfoT.hh:81
OpenMesh::Decimater::CollapseInfoT::v1
Mesh::VertexHandle v1
Remaining vertex.
Definition CollapseInfoT.hh:83
OpenMesh::Decimater::CollapseInfoT::v0
Mesh::VertexHandle v0
Vertex to be removed.
Definition CollapseInfoT.hh:82
OpenMesh::Decimater::DecimaterT
Decimater framework.
Definition DecimaterT.hh:79
OpenMesh::Decimater::DecimaterT::decimate
size_t decimate(size_t _n_collapses=0, bool _only_selected=false)
Perform a number of collapses on the mesh.
Definition DecimaterT_impl.hh:150
OpenMesh::Decimater::DecimaterT::decimate_to_faces
size_t decimate_to_faces(size_t _n_vertices=0, size_t _n_faces=0, bool _only_selected=false)
Attempts to decimate the mesh until a desired vertex or face complexity is achieved.
Definition DecimaterT_impl.hh:259
OpenMesh::Decimater::DecimaterT::~DecimaterT
~DecimaterT()
Destructor.
Definition DecimaterT_impl.hh:92
OpenMesh::Decimater::DecimaterT::DecimaterT
DecimaterT(Mesh &_mesh)
Constructor.
Definition DecimaterT_impl.hh:72
OpenMesh::Decimater::DecimaterT::HeapInterface
Heap interface.
Definition DecimaterT.hh:149
OpenMesh::Utils::HeapT
An efficient, highly customizable heap.
Definition HeapT.hh:139