- decimater modules doesn't need a decimater type as template argument
- add decimater base class git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@645 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
@@ -69,12 +69,8 @@ namespace Decimater {
|
||||
|
||||
template<class Mesh>
|
||||
DecimaterT<Mesh>::DecimaterT(Mesh& _mesh) :
|
||||
mesh_(_mesh), heap_(NULL), cmodule_(NULL), initialized_(false) {
|
||||
// default properties
|
||||
mesh_.request_vertex_status();
|
||||
mesh_.request_edge_status();
|
||||
mesh_.request_face_status();
|
||||
mesh_.request_face_normals();
|
||||
BaseDecimaterT<Mesh>(_mesh),
|
||||
mesh_(_mesh), heap_(NULL) {
|
||||
|
||||
// private vertex properties
|
||||
mesh_.add_property(collapse_target_);
|
||||
@@ -86,208 +82,12 @@ DecimaterT<Mesh>::DecimaterT(Mesh& _mesh) :
|
||||
|
||||
template<class Mesh>
|
||||
DecimaterT<Mesh>::~DecimaterT() {
|
||||
// default properties
|
||||
mesh_.release_vertex_status();
|
||||
mesh_.release_edge_status();
|
||||
mesh_.release_face_status();
|
||||
mesh_.release_face_normals();
|
||||
|
||||
// private vertex properties
|
||||
mesh_.remove_property(collapse_target_);
|
||||
mesh_.remove_property(priority_);
|
||||
mesh_.remove_property(heap_position_);
|
||||
|
||||
// dispose of modules
|
||||
{
|
||||
set_uninitialized();
|
||||
typename ModuleList::iterator m_it, m_end = all_modules_.end();
|
||||
for (m_it = all_modules_.begin(); m_it != m_end; ++m_it)
|
||||
delete *m_it;
|
||||
all_modules_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class Mesh>
|
||||
void DecimaterT<Mesh>::info(std::ostream& _os) {
|
||||
if (initialized_) {
|
||||
_os << "initialized : yes" << std::endl;
|
||||
_os << "binary modules: " << bmodules_.size() << std::endl;
|
||||
for (ModuleListIterator m_it = bmodules_.begin(); m_it != bmodules_.end();
|
||||
++m_it) {
|
||||
_os << " " << (*m_it)->name() << std::endl;
|
||||
}
|
||||
_os << "priority module: " << cmodule_->name().c_str() << std::endl;
|
||||
} else {
|
||||
_os << "initialized : no" << std::endl;
|
||||
_os << "available modules: " << all_modules_.size() << std::endl;
|
||||
for (ModuleListIterator m_it = all_modules_.begin();
|
||||
m_it != all_modules_.end(); ++m_it) {
|
||||
_os << " " << (*m_it)->name() << " : ";
|
||||
if ((*m_it)->is_binary()) {
|
||||
_os << "binary";
|
||||
if ((*m_it)->name() == "Quadric") {
|
||||
_os << " and priority (special treatment)";
|
||||
}
|
||||
} else {
|
||||
_os << "priority";
|
||||
}
|
||||
_os << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class Mesh>
|
||||
bool DecimaterT<Mesh>::initialize() {
|
||||
if (initialized_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: quadric module shouldn't be treated specially.
|
||||
// Q: Why?
|
||||
// A: It isn't generic and breaks encapsulation. Also, using string
|
||||
// name comparison is not reliable, since you can't guarantee that
|
||||
// no one else will name their custom module "Quadric".
|
||||
// Q: What should be done instead?
|
||||
// A: ModBaseT API should support modules that can be both binary
|
||||
// and priority, or BETTER YET, let the DecimaterT API specify the
|
||||
// priority module explicitly.
|
||||
|
||||
// find the priority module: either the only non-binary module in the list, or "Quadric"
|
||||
Module *quadric = NULL;
|
||||
Module *pmodule = NULL;
|
||||
for (ModuleListIterator m_it = all_modules_.begin(), m_end =
|
||||
all_modules_.end(); m_it != m_end; ++m_it) {
|
||||
if ((*m_it)->name() == "Quadric")
|
||||
quadric = *m_it;
|
||||
|
||||
if (!(*m_it)->is_binary()) {
|
||||
if (pmodule) {
|
||||
// only one priority module allowed!
|
||||
set_uninitialized();
|
||||
return false;
|
||||
}
|
||||
pmodule = *m_it;
|
||||
}
|
||||
}
|
||||
|
||||
// Quadric is used as default priority module (even if it is set to be binary)
|
||||
if (!pmodule && quadric) {
|
||||
pmodule = quadric;
|
||||
}
|
||||
|
||||
if (!pmodule) {
|
||||
// At least one priority module required
|
||||
set_uninitialized();
|
||||
return false;
|
||||
}
|
||||
|
||||
// set pmodule as the current priority module
|
||||
cmodule_ = pmodule;
|
||||
|
||||
for (ModuleListIterator m_it = all_modules_.begin(), m_end =
|
||||
all_modules_.end(); m_it != m_end; ++m_it) {
|
||||
// every module gets initialized
|
||||
(*m_it)->initialize();
|
||||
|
||||
if (*m_it != pmodule) {
|
||||
// all other modules are binary, and go into bmodules_ list
|
||||
bmodules_.push_back(*m_it);
|
||||
}
|
||||
}
|
||||
|
||||
return initialized_ = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class Mesh>
|
||||
bool DecimaterT<Mesh>::is_collapse_legal(const CollapseInfo& _ci) {
|
||||
// std::clog << "DecimaterT<>::is_collapse_legal()\n";
|
||||
|
||||
// locked ? deleted ?
|
||||
if (mesh_.status(_ci.v0).locked() || mesh_.status(_ci.v0).deleted())
|
||||
return false;
|
||||
|
||||
if (!mesh_.is_collapse_ok(_ci.v0v1))
|
||||
return false;
|
||||
|
||||
if (_ci.vl.is_valid() && _ci.vr.is_valid()
|
||||
&& mesh_.find_halfedge(_ci.vl, _ci.vr).is_valid()
|
||||
&& mesh_.valence(_ci.vl) == 3 && mesh_.valence(_ci.vr) == 3) {
|
||||
return false;
|
||||
}
|
||||
//--- feature test ---
|
||||
|
||||
if (mesh_.status(_ci.v0).feature()
|
||||
&& !mesh_.status(mesh_.edge_handle(_ci.v0v1)).feature())
|
||||
return false;
|
||||
|
||||
//--- test one ring intersection ---
|
||||
|
||||
typename Mesh::VertexVertexIter vv_it;
|
||||
|
||||
for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it)
|
||||
mesh_.status(vv_it).set_tagged(false);
|
||||
|
||||
for (vv_it = mesh_.vv_iter(_ci.v1); vv_it; ++vv_it)
|
||||
mesh_.status(vv_it).set_tagged(true);
|
||||
|
||||
for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it)
|
||||
if (mesh_.status(vv_it).tagged() && vv_it.handle() != _ci.vl
|
||||
&& vv_it.handle() != _ci.vr)
|
||||
return false;
|
||||
|
||||
// if both are invalid OR equal -> fail
|
||||
if (_ci.vl == _ci.vr)
|
||||
return false;
|
||||
|
||||
//--- test boundary cases ---
|
||||
if (mesh_.is_boundary(_ci.v0)) {
|
||||
if (!mesh_.is_boundary(_ci.v1)) { // don't collapse a boundary vertex to an inner one
|
||||
return false;
|
||||
} else { // edge between two boundary vertices has to be a boundary edge
|
||||
if (!(mesh_.is_boundary(_ci.v0v1) || mesh_.is_boundary(_ci.v1v0)))
|
||||
return false;
|
||||
}
|
||||
// only one one ring intersection
|
||||
if (_ci.vl.is_valid() && _ci.vr.is_valid())
|
||||
return false;
|
||||
}
|
||||
|
||||
// v0vl and v1vl must not both be boundary edges
|
||||
if (_ci.vl.is_valid() && mesh_.is_boundary(_ci.vlv1)
|
||||
&& mesh_.is_boundary(_ci.v0vl))
|
||||
return false;
|
||||
|
||||
// v0vr and v1vr must not be both boundary edges
|
||||
if (_ci.vr.is_valid() && mesh_.is_boundary(_ci.vrv0)
|
||||
&& mesh_.is_boundary(_ci.v1vr))
|
||||
return false;
|
||||
|
||||
// there have to be at least 2 incident faces at v0
|
||||
if (mesh_.cw_rotated_halfedge_handle(
|
||||
mesh_.cw_rotated_halfedge_handle(_ci.v0v1)) == _ci.v0v1)
|
||||
return false;
|
||||
|
||||
// collapse passed all tests -> ok
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class Mesh>
|
||||
float DecimaterT<Mesh>::collapse_priority(const CollapseInfo& _ci) {
|
||||
typename ModuleList::iterator m_it, m_end = bmodules_.end();
|
||||
|
||||
for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) {
|
||||
if ((*m_it)->collapse_priority(_ci) < 0.0)
|
||||
return ModBaseT<DecimaterT<Mesh> >::ILLEGAL_COLLAPSE;
|
||||
}
|
||||
return cmodule_->collapse_priority(_ci);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -305,8 +105,8 @@ void DecimaterT<Mesh>::heap_vertex(VertexHandle _vh) {
|
||||
heh = voh_it.handle();
|
||||
CollapseInfo ci(mesh_, heh);
|
||||
|
||||
if (is_collapse_legal(ci)) {
|
||||
prio = collapse_priority(ci);
|
||||
if (this->is_collapse_legal(ci)) {
|
||||
prio = this->collapse_priority(ci);
|
||||
if (prio >= 0.0 && prio < best_prio) {
|
||||
best_prio = prio;
|
||||
collapse_target = heh;
|
||||
@@ -337,34 +137,10 @@ void DecimaterT<Mesh>::heap_vertex(VertexHandle _vh) {
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class Mesh>
|
||||
void DecimaterT<Mesh>::postprocess_collapse(CollapseInfo& _ci) {
|
||||
typename ModuleList::iterator m_it, m_end = bmodules_.end();
|
||||
|
||||
for (m_it = bmodules_.begin(); m_it != m_end; ++m_it)
|
||||
(*m_it)->postprocess_collapse(_ci);
|
||||
|
||||
cmodule_->postprocess_collapse(_ci);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class Mesh>
|
||||
void DecimaterT<Mesh>::preprocess_collapse(CollapseInfo& _ci) {
|
||||
typename ModuleList::iterator m_it, m_end = bmodules_.end();
|
||||
|
||||
for (m_it = bmodules_.begin(); m_it != m_end; ++m_it)
|
||||
(*m_it)->preprocess_collapse(_ci);
|
||||
|
||||
cmodule_->preprocess_collapse(_ci);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template<class Mesh>
|
||||
size_t DecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
||||
if (!is_initialized())
|
||||
if (!this->is_initialized())
|
||||
return 0;
|
||||
|
||||
typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
|
||||
@@ -406,7 +182,7 @@ size_t DecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
||||
CollapseInfo ci(mesh_, v0v1);
|
||||
|
||||
// check topological correctness AGAIN !
|
||||
if (!is_collapse_legal(ci))
|
||||
if (!this->is_collapse_legal(ci))
|
||||
continue;
|
||||
|
||||
// store support (= one ring of *vp)
|
||||
@@ -426,7 +202,7 @@ size_t DecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
||||
mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle()));
|
||||
|
||||
// post-process collapse
|
||||
postprocess_collapse(ci);
|
||||
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) {
|
||||
@@ -446,7 +222,7 @@ size_t DecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
||||
|
||||
template<class Mesh>
|
||||
size_t DecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
|
||||
if (!is_initialized())
|
||||
if (!this->is_initialized())
|
||||
return 0;
|
||||
|
||||
if (_nv >= mesh_.n_vertices() || _nf >= mesh_.n_faces())
|
||||
|
||||
Reference in New Issue
Block a user