/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2001-2012 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
* *
* OpenMesh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenMesh is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenMesh. If not, *
* see . *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
// -------------------- STL
#include
#include
#include
// -------------------- OpenMesh
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef OpenMesh::TriMesh_ArrayKernelT<> Mesh;
typedef OpenMesh::Decimater::DecimaterT DecimaterProgMesh;
typedef OpenMesh::Decimater::ModNormalFlippingT ModNormalFlipping;
typedef OpenMesh::Decimater::ModQuadricT ModQuadric;
typedef OpenMesh::Decimater::ModProgMeshT ModProgMesh;
typedef OpenMesh::Decimater::ModIndependentSetsT ModIndependentSets;
// ----------------------------------------------------------------------------
using namespace OpenMesh::Decimater;
template
class ModBalancerT : public OpenMesh::Decimater::ModQuadricT
{
public:
typedef OpenMesh::Decimater::ModQuadricT BaseModQ;
DECIMATING_MODULE( ModBalancerT, D, Balancer );
public:
typedef size_t level_t;
public:
/// Constructor
ModBalancerT( D &_dec )
: BaseModQ( _dec ),
max_level_(0), n_roots_(0), n_vertices_(0)
{
BaseModQ::mesh().add_property( level_ );
}
/// Destructor
virtual ~ModBalancerT()
{
BaseModQ::mesh().remove_property( level_ );
}
public:
static level_t calc_bits_for_roots( size_t _n_vertices )
{
return level_t(std::ceil(std::log((double)_n_vertices)*inv_log2_));
}
public: // inherited
void initialize(void)
{
BaseModQ::initialize();
n_vertices_ = BaseModQ::mesh().n_vertices();
n_roots_ = calc_bits_for_roots(n_vertices_);
}
virtual float collapse_priority(const CollapseInfo& _ci)
{
level_t newlevel = std::max( BaseModQ::mesh().property( level_, _ci.v0 ),
BaseModQ::mesh().property( level_, _ci.v1 ) )+1;
level_t newroots = calc_bits_for_roots(n_vertices_-1);
if ( (newroots + newlevel) < 32 )
{
double err = BaseModQ::collapse_priority( _ci );
if (err!=BaseModQ::ILLEGAL_COLLAPSE)
{
return float(newlevel + err/(err+1.0));
}
}
return BaseModQ::ILLEGAL_COLLAPSE;
}
/// post-process halfedge collapse (accumulate quadrics)
void postprocess_collapse(const CollapseInfo& _ci)
{
BaseModQ::postprocess_collapse( _ci );
BaseModQ::mesh().property( level_, _ci.v1 ) =
std::max( BaseModQ::mesh().property( level_, _ci.v0 ),
BaseModQ::mesh().property( level_, _ci.v1 ) ) + 1;
max_level_ = std::max( BaseModQ::mesh().property( level_, _ci.v1 ), max_level_ );
n_roots_ = calc_bits_for_roots(--n_vertices_);
}
public:
level_t max_level(void) const { return max_level_; }
level_t bits_for_roots(void) const { return n_roots_; }
private:
/// hide this method
void set_binary(bool _b) {}
OpenMesh::VPropHandleT level_;
level_t max_level_; // maximum level reached
level_t n_roots_; // minimum bits for root nodes
size_t n_vertices_;// number of potential root nodes
static const double inv_log2_;
};
template
const double ModBalancerT::inv_log2_ = 1.0/std::log(2.0);
typedef ModBalancerT ModBalancer;
// ----------------------------------------------------------------------------
inline
std::string&
replace_extension( std::string& _s, const std::string& _e )
{
std::string::size_type dot = _s.rfind(".");
if (dot == std::string::npos)
{ _s += "." + _e; }
else
{ _s = _s.substr(0,dot+1)+_e; }
return _s;
}
inline
std::string
basename(const std::string& _f)
{
std::string::size_type dot = _f.rfind("/");
if (dot == std::string::npos)
return _f;
return _f.substr(dot+1, _f.length()-(dot+1));
}
// ----------------------------------------------------------------------------
void usage_and_exit(int xcode)
{
using namespace std;
cout << endl
<< "Usage: mkbalancedpm [-n ] [-o