- added the set_error_tolerance_factor function to ModBaseT and implemented it in inherited classes as necessary
- added the set_error_tolerance_factor function to BaseDecimaterT, which calls set_error_tolerance_factor for all loaded Mods - implemented a decimate_constraints_only function for the McDecimater (and adjusted the MixedDecimater accordingly) - implemented stop criterions for the McDecimater - added some OpenMP loops for the sample generation to the McDecimater git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@685 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
@@ -207,6 +207,19 @@ void BaseDecimaterT<Mesh>::preprocess_collapse(CollapseInfo& _ci) {
|
|||||||
cmodule_->preprocess_collapse(_ci);
|
cmodule_->preprocess_collapse(_ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class Mesh>
|
||||||
|
void BaseDecimaterT<Mesh>::set_error_tolerance_factor(double _factor) {
|
||||||
|
if (_factor >= 0.0 && _factor <= 1.0) {
|
||||||
|
typename ModuleList::iterator m_it, m_end = bmodules_.end();
|
||||||
|
|
||||||
|
for (m_it = bmodules_.begin(); m_it != m_end; ++m_it)
|
||||||
|
(*m_it)->set_error_tolerance_factor(_factor);
|
||||||
|
|
||||||
|
cmodule_->set_error_tolerance_factor(_factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -199,6 +199,16 @@ protected: //---------------------------------------------------- private method
|
|||||||
/// Post-process a collapse
|
/// Post-process a collapse
|
||||||
void postprocess_collapse(CollapseInfo& _ci);
|
void postprocess_collapse(CollapseInfo& _ci);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This provides a function that allows the setting of a percentage
|
||||||
|
* of the original contraint of the modules
|
||||||
|
*
|
||||||
|
* Note that some modules might re-initialize in their
|
||||||
|
* set_error_tolerance_factor function as necessary
|
||||||
|
* @param factor_ has to be in the closed interval between 0.0 and 1.0
|
||||||
|
*/
|
||||||
|
void set_error_tolerance_factor(double _factor);
|
||||||
|
|
||||||
private: //------------------------------------------------------- private data
|
private: //------------------------------------------------------- private data
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
||||||
* www.openmesh.org *
|
* www.openmesh.org *
|
||||||
* *
|
* *
|
||||||
*---------------------------------------------------------------------------*
|
*---------------------------------------------------------------------------*
|
||||||
* This file is part of OpenMesh. *
|
* This file is part of OpenMesh. *
|
||||||
* *
|
* *
|
||||||
* OpenMesh is free software: you can redistribute it and/or modify *
|
* OpenMesh is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
* published by the Free Software Foundation, either version 3 of *
|
* published by the Free Software Foundation, either version 3 of *
|
||||||
* the License, or (at your option) any later version with the *
|
* the License, or (at your option) any later version with the *
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision$ *
|
* $Revision$ *
|
||||||
* $Date$ *
|
* $Date$ *
|
||||||
* *
|
* *
|
||||||
@@ -214,6 +214,7 @@ size_t DecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
|||||||
// delete heap
|
// delete heap
|
||||||
heap_.reset();
|
heap_.reset();
|
||||||
|
|
||||||
|
|
||||||
// DON'T do garbage collection here! It's up to the application.
|
// DON'T do garbage collection here! It's up to the application.
|
||||||
return n_collapses;
|
return n_collapses;
|
||||||
}
|
}
|
||||||
@@ -307,6 +308,7 @@ size_t DecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
|
|||||||
// delete heap
|
// delete heap
|
||||||
heap_.reset();
|
heap_.reset();
|
||||||
|
|
||||||
|
|
||||||
// DON'T do garbage collection here! It's up to the application.
|
// DON'T do garbage collection here! It's up to the application.
|
||||||
return n_collapses;
|
return n_collapses;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,9 @@
|
|||||||
#else
|
#else
|
||||||
# include <cfloat>
|
# include <cfloat>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_OPENMP
|
||||||
|
#include <omp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
//== NAMESPACE ===============================================================
|
//== NAMESPACE ===============================================================
|
||||||
|
|
||||||
@@ -103,17 +106,33 @@ size_t McDecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
|||||||
|
|
||||||
unsigned int n_collapses(0);
|
unsigned int n_collapses(0);
|
||||||
|
|
||||||
|
bool collapsesUnchanged = false;
|
||||||
|
// old n_collapses in order to check for convergence
|
||||||
|
unsigned int oldCollapses = 0;
|
||||||
|
// number of iterations where no new collapses where
|
||||||
|
// performed in a row
|
||||||
|
unsigned int noCollapses = 0;
|
||||||
|
|
||||||
while ( n_collapses < _n_collapses) {
|
while ( n_collapses < _n_collapses) {
|
||||||
|
if (noCollapses > 20) {
|
||||||
|
omlog() << "[McDecimater] : no collapses performed in over 20 iterations in a row\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Optimal id and value will be collected during the random sampling
|
// Optimal id and value will be collected during the random sampling
|
||||||
typename Mesh::HalfedgeHandle bestHandle(-1);
|
typename Mesh::HalfedgeHandle bestHandle(-1);
|
||||||
|
typename Mesh::HalfedgeHandle tmpHandle(-1);
|
||||||
double bestEnergy = FLT_MAX;
|
double bestEnergy = FLT_MAX;
|
||||||
|
double energy = FLT_MAX;
|
||||||
|
|
||||||
// Generate random samples for collapses
|
// Generate random samples for collapses
|
||||||
|
#ifdef USE_OPENMP
|
||||||
|
#pragma omp parallel for private(energy,tmpHandle) shared(bestEnergy,bestHandle)
|
||||||
|
#endif
|
||||||
for ( int i = 0; i < (int)randomSamples_; ++i) {
|
for ( int i = 0; i < (int)randomSamples_; ++i) {
|
||||||
|
|
||||||
// Random halfedge handle
|
// Random halfedge handle
|
||||||
typename Mesh::HalfedgeHandle tmpHandle = typename Mesh::HalfedgeHandle((static_cast<double>(rand()) / RAND_MAX) * (mesh_.n_halfedges()-1) );
|
tmpHandle = typename Mesh::HalfedgeHandle((static_cast<double>(rand()) / RAND_MAX) * (mesh_.n_halfedges()-1) );
|
||||||
|
|
||||||
// if it is not deleted, we analyse it
|
// if it is not deleted, we analyse it
|
||||||
if ( ! mesh_.status(tmpHandle).deleted() ) {
|
if ( ! mesh_.status(tmpHandle).deleted() ) {
|
||||||
@@ -122,13 +141,22 @@ size_t McDecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
|||||||
|
|
||||||
// Check if legal we analyze the priority of this collapse operation
|
// Check if legal we analyze the priority of this collapse operation
|
||||||
if (this->is_collapse_legal(ci)) {
|
if (this->is_collapse_legal(ci)) {
|
||||||
double energy = this->collapse_priority(ci);
|
#ifdef USE_OPENMP
|
||||||
|
#pragma omp critical(energyUpdate)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
energy = this->collapse_priority(ci);
|
||||||
|
|
||||||
// Check if the current samples energy is better than any energy before
|
if (energy != ModBaseT<Mesh>::ILLEGAL_COLLAPSE) {
|
||||||
if ( energy < bestEnergy ) {
|
// Check if the current samples energy is better than any energy before
|
||||||
bestEnergy = energy;
|
if ( energy < bestEnergy ) {
|
||||||
bestHandle = tmpHandle;
|
bestEnergy = energy;
|
||||||
|
bestHandle = tmpHandle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef USE_OPENMP
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -153,6 +181,11 @@ size_t McDecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
|||||||
mesh_.collapse(bestHandle);
|
mesh_.collapse(bestHandle);
|
||||||
++n_collapses;
|
++n_collapses;
|
||||||
|
|
||||||
|
// store current collapses state
|
||||||
|
oldCollapses = n_collapses;
|
||||||
|
noCollapses = 0;
|
||||||
|
collapsesUnchanged = false;
|
||||||
|
|
||||||
// update triangle normals
|
// update triangle normals
|
||||||
typename Mesh::VertexFaceIter vf_it = mesh_.vf_iter(ci.v1);
|
typename Mesh::VertexFaceIter vf_it = mesh_.vf_iter(ci.v1);
|
||||||
for (; vf_it; ++vf_it)
|
for (; vf_it; ++vf_it)
|
||||||
@@ -162,6 +195,15 @@ size_t McDecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
|||||||
// post-process collapse
|
// post-process collapse
|
||||||
this->postprocess_collapse(ci);
|
this->postprocess_collapse(ci);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (oldCollapses == n_collapses) {
|
||||||
|
if (collapsesUnchanged == false) {
|
||||||
|
noCollapses = 1;
|
||||||
|
collapsesUnchanged = true;
|
||||||
|
} else {
|
||||||
|
noCollapses++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -177,34 +219,43 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
|
|||||||
if (!this->is_initialized())
|
if (!this->is_initialized())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// check if no vertex or face contraints were set
|
||||||
|
if ( (_nv == 0) && (_nf == 1) )
|
||||||
|
return decimate_constraints_only(1.0);
|
||||||
|
|
||||||
unsigned int nv = mesh_.n_vertices();
|
unsigned int nv = mesh_.n_vertices();
|
||||||
unsigned int nf = mesh_.n_faces();
|
unsigned int nf = mesh_.n_faces();
|
||||||
unsigned int n_collapses(0);
|
unsigned int n_collapses(0);
|
||||||
|
|
||||||
|
|
||||||
// check if no vertex or face contraints were set
|
bool collapsesUnchanged = false;
|
||||||
bool contraintsOnly = (_nv == 0) && (_nf == 1);
|
// old n_collapses in order to check for convergence
|
||||||
|
unsigned int oldCollapses = 0;
|
||||||
|
// number of iterations where no new collapses where
|
||||||
|
// performed in a row
|
||||||
|
unsigned int noCollapses = 0;
|
||||||
|
|
||||||
// check if no legal collapses were found three times in a row
|
while ( (_nv < nv) && (_nf < nf) ) {
|
||||||
// for the sampled halfedges
|
if (noCollapses > 20) {
|
||||||
bool foundNoLegalCollapsesThrice = false;
|
omlog() << "[McDecimater] : no collapses performed in over 20 iterations in a row\n";
|
||||||
|
break;
|
||||||
// store the last two amount of legal collapses found
|
}
|
||||||
int lastLegalCollapses = -1;
|
|
||||||
int beforeLastLegalCollapses = -1;
|
|
||||||
|
|
||||||
while ( !foundNoLegalCollapsesThrice && (_nv < nv) && (_nf < nf) ) {
|
|
||||||
|
|
||||||
// Optimal id and value will be collected during the random sampling
|
// Optimal id and value will be collected during the random sampling
|
||||||
typename Mesh::HalfedgeHandle bestHandle(-1);
|
typename Mesh::HalfedgeHandle bestHandle(-1);
|
||||||
|
typename Mesh::HalfedgeHandle tmpHandle(-1);
|
||||||
double bestEnergy = FLT_MAX;
|
double bestEnergy = FLT_MAX;
|
||||||
|
double energy = FLT_MAX;
|
||||||
|
|
||||||
|
|
||||||
// Generate random samples for collapses
|
// Generate random samples for collapses
|
||||||
unsigned int legalCollapses = 0;
|
#ifdef USE_OPENMP
|
||||||
|
#pragma omp parallel for private(energy,tmpHandle) shared(bestEnergy,bestHandle)
|
||||||
|
#endif
|
||||||
for ( int i = 0; i < (int)randomSamples_; ++i) {
|
for ( int i = 0; i < (int)randomSamples_; ++i) {
|
||||||
|
|
||||||
// Random halfedge handle
|
// Random halfedge handle
|
||||||
typename Mesh::HalfedgeHandle tmpHandle = typename Mesh::HalfedgeHandle((static_cast<double>(rand()) / RAND_MAX) * (mesh_.n_halfedges()-1) );
|
tmpHandle = typename Mesh::HalfedgeHandle((static_cast<double>(rand()) / RAND_MAX) * (mesh_.n_halfedges()-1) );
|
||||||
|
|
||||||
// if it is not deleted, we analyse it
|
// if it is not deleted, we analyse it
|
||||||
if ( ! mesh_.status(tmpHandle).deleted() ) {
|
if ( ! mesh_.status(tmpHandle).deleted() ) {
|
||||||
@@ -213,14 +264,22 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
|
|||||||
|
|
||||||
// Check if legal we analyze the priority of this collapse operation
|
// Check if legal we analyze the priority of this collapse operation
|
||||||
if (this->is_collapse_legal(ci)) {
|
if (this->is_collapse_legal(ci)) {
|
||||||
++legalCollapses;
|
#ifdef USE_OPENMP
|
||||||
double energy = this->collapse_priority(ci);
|
#pragma omp critical(energyUpdate)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
energy = this->collapse_priority(ci);
|
||||||
|
|
||||||
// Check if the current samples energy is better than any energy before
|
if (energy != ModBaseT<Mesh>::ILLEGAL_COLLAPSE) {
|
||||||
if ( energy < bestEnergy ) {
|
// Check if the current samples energy is better than any energy before
|
||||||
bestEnergy = energy;
|
if ( energy < bestEnergy ) {
|
||||||
bestHandle = tmpHandle;
|
bestEnergy = energy;
|
||||||
|
bestHandle = tmpHandle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef USE_OPENMP
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -228,15 +287,6 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contraintsOnly) {
|
|
||||||
// check if no legal collapses were found three times in a row
|
|
||||||
foundNoLegalCollapsesThrice = (beforeLastLegalCollapses == 0) && (lastLegalCollapses == 0) && (legalCollapses == 0);
|
|
||||||
|
|
||||||
// store amount of last legal collapses found
|
|
||||||
beforeLastLegalCollapses = lastLegalCollapses;
|
|
||||||
lastLegalCollapses = legalCollapses;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Found the best energy?
|
// Found the best energy?
|
||||||
if ( bestEnergy != FLT_MAX ) {
|
if ( bestEnergy != FLT_MAX ) {
|
||||||
|
|
||||||
@@ -267,6 +317,11 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
|
|||||||
mesh_.collapse(bestHandle);
|
mesh_.collapse(bestHandle);
|
||||||
++n_collapses;
|
++n_collapses;
|
||||||
|
|
||||||
|
// store current collapses state
|
||||||
|
oldCollapses = n_collapses;
|
||||||
|
noCollapses = 0;
|
||||||
|
collapsesUnchanged = false;
|
||||||
|
|
||||||
// update triangle normals
|
// update triangle normals
|
||||||
typename Mesh::VertexFaceIter vf_it = mesh_.vf_iter(ci.v1);
|
typename Mesh::VertexFaceIter vf_it = mesh_.vf_iter(ci.v1);
|
||||||
for (; vf_it; ++vf_it)
|
for (; vf_it; ++vf_it)
|
||||||
@@ -276,6 +331,15 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
|
|||||||
// post-process collapse
|
// post-process collapse
|
||||||
this->postprocess_collapse(ci);
|
this->postprocess_collapse(ci);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (oldCollapses == n_collapses) {
|
||||||
|
if (collapsesUnchanged == false) {
|
||||||
|
noCollapses = 1;
|
||||||
|
collapsesUnchanged = true;
|
||||||
|
} else {
|
||||||
|
noCollapses++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -284,6 +348,155 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
|
|||||||
return n_collapses;
|
return n_collapses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class Mesh>
|
||||||
|
size_t McDecimaterT<Mesh>::decimate_constraints_only(float _factor) {
|
||||||
|
if (!this->is_initialized())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (_factor < 1.0)
|
||||||
|
this->set_error_tolerance_factor(_factor);
|
||||||
|
|
||||||
|
unsigned int n_collapses(0);
|
||||||
|
unsigned int nv = mesh_.n_vertices();
|
||||||
|
unsigned int nf = mesh_.n_faces();
|
||||||
|
|
||||||
|
bool lastCollapseIllegal = false;
|
||||||
|
// number of illegal collapses that occured in a row
|
||||||
|
unsigned int illegalCollapses = 0;
|
||||||
|
|
||||||
|
bool collapsesUnchanged = false;
|
||||||
|
// old n_collapses in order to check for convergence
|
||||||
|
unsigned int oldCollapses = 0;
|
||||||
|
// number of iterations where no new collapses where
|
||||||
|
// performed in a row
|
||||||
|
unsigned int noCollapses = 0;
|
||||||
|
|
||||||
|
|
||||||
|
while ( (noCollapses <= 20) && (illegalCollapses <= 10) && (nv > 0) && (nf > 1) ) {
|
||||||
|
|
||||||
|
// Optimal id and value will be collected during the random sampling
|
||||||
|
typename Mesh::HalfedgeHandle bestHandle(-1);
|
||||||
|
typename Mesh::HalfedgeHandle tmpHandle(-1);
|
||||||
|
double bestEnergy = FLT_MAX;
|
||||||
|
double energy = FLT_MAX;
|
||||||
|
|
||||||
|
// Generate random samples for collapses
|
||||||
|
#ifdef USE_OPENMP
|
||||||
|
#pragma omp parallel for private(energy,tmpHandle) shared(bestEnergy,bestHandle)
|
||||||
|
#endif
|
||||||
|
for ( int i = 0; i < (int)randomSamples_; ++i) {
|
||||||
|
|
||||||
|
// Random halfedge handle
|
||||||
|
tmpHandle = typename Mesh::HalfedgeHandle((static_cast<double>(rand()) / RAND_MAX) * (mesh_.n_halfedges()-1) );
|
||||||
|
|
||||||
|
// if it is not deleted, we analyse it
|
||||||
|
if ( ! mesh_.status(tmpHandle).deleted() ) {
|
||||||
|
|
||||||
|
CollapseInfo ci(mesh_, tmpHandle);
|
||||||
|
|
||||||
|
// Check if legal we analyze the priority of this collapse operation
|
||||||
|
if (this->is_collapse_legal(ci)) {
|
||||||
|
#ifdef USE_OPENMP
|
||||||
|
#pragma omp critical(energyUpdate)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
energy = this->collapse_priority(ci);
|
||||||
|
|
||||||
|
if (energy == ModBaseT<Mesh>::ILLEGAL_COLLAPSE){
|
||||||
|
if (lastCollapseIllegal) {
|
||||||
|
illegalCollapses++;
|
||||||
|
} else {
|
||||||
|
illegalCollapses = 1;
|
||||||
|
lastCollapseIllegal = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
illegalCollapses = 0;
|
||||||
|
lastCollapseIllegal = false;
|
||||||
|
|
||||||
|
// Check if the current samples energy is better than any energy before
|
||||||
|
if ( energy < bestEnergy ) {
|
||||||
|
bestEnergy = energy;
|
||||||
|
bestHandle = tmpHandle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef USE_OPENMP
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Found the best energy?
|
||||||
|
if ( bestEnergy != FLT_MAX ) {
|
||||||
|
|
||||||
|
// setup collapse info
|
||||||
|
CollapseInfo ci(mesh_, bestHandle);
|
||||||
|
|
||||||
|
// check topological correctness AGAIN !
|
||||||
|
if (!this->is_collapse_legal(ci))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// adjust complexity in advance (need boundary status)
|
||||||
|
|
||||||
|
// One vertex is killed by the collapse
|
||||||
|
--nv;
|
||||||
|
|
||||||
|
// If we are at a boundary, one face is lost,
|
||||||
|
// otherwise two
|
||||||
|
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(bestHandle);
|
||||||
|
++n_collapses;
|
||||||
|
|
||||||
|
// store current collapses state
|
||||||
|
oldCollapses = n_collapses;
|
||||||
|
noCollapses = 0;
|
||||||
|
collapsesUnchanged = false;
|
||||||
|
|
||||||
|
|
||||||
|
// update triangle normals
|
||||||
|
typename Mesh::VertexFaceIter vf_it = mesh_.vf_iter(ci.v1);
|
||||||
|
for (; vf_it; ++vf_it)
|
||||||
|
if (!mesh_.status(vf_it).deleted())
|
||||||
|
mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle()));
|
||||||
|
|
||||||
|
// post-process collapse
|
||||||
|
this->postprocess_collapse(ci);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (oldCollapses == n_collapses) {
|
||||||
|
if (collapsesUnchanged == false) {
|
||||||
|
noCollapses = 1;
|
||||||
|
collapsesUnchanged = true;
|
||||||
|
} else {
|
||||||
|
noCollapses++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_factor < 1.0)
|
||||||
|
this->set_error_tolerance_factor(1.0);
|
||||||
|
|
||||||
|
// DON'T do garbage collection here! It's up to the application.
|
||||||
|
return n_collapses;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
}// END_NS_MC_DECIMATER
|
}// END_NS_MC_DECIMATER
|
||||||
} // END_NS_OPENMESH
|
} // END_NS_OPENMESH
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
||||||
* www.openmesh.org *
|
* www.openmesh.org *
|
||||||
* *
|
* *
|
||||||
*---------------------------------------------------------------------------*
|
*---------------------------------------------------------------------------*
|
||||||
* This file is part of OpenMesh. *
|
* This file is part of OpenMesh. *
|
||||||
* *
|
* *
|
||||||
* OpenMesh is free software: you can redistribute it and/or modify *
|
* OpenMesh is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
* published by the Free Software Foundation, either version 3 of *
|
* published by the Free Software Foundation, either version 3 of *
|
||||||
* the License, or (at your option) any later version with the *
|
* the License, or (at your option) any later version with the *
|
||||||
@@ -30,10 +30,10 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision: 448 $ *
|
* $Revision: 448 $ *
|
||||||
* $Date: 2011-11-04 13:59:37 +0100 (Fr, 04 Nov 2011) $ *
|
* $Date: 2011-11-04 13:59:37 +0100 (Fr, 04 Nov 2011) $ *
|
||||||
* *
|
* *
|
||||||
@@ -111,6 +111,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
size_t decimate_to_faces( size_t _n_vertices=0, size_t _n_faces=0 );
|
size_t decimate_to_faces( size_t _n_vertices=0, size_t _n_faces=0 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decimate only with constraints, while _factor gives the
|
||||||
|
* percentage of the constraints that should be used
|
||||||
|
*/
|
||||||
|
size_t decimate_constraints_only(float _factor);
|
||||||
|
|
||||||
size_t samples(){return randomSamples_;}
|
size_t samples(){return randomSamples_;}
|
||||||
void set_samples(const size_t _value){randomSamples_ = _value;}
|
void set_samples(const size_t _value){randomSamples_ = _value;}
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ size_t MixedDecimaterT<Mesh>::decimate(const size_t _n_collapses, const float _m
|
|||||||
r_collapses = McDecimaterT<Mesh>::decimate(n_collapses_mc);
|
r_collapses = McDecimaterT<Mesh>::decimate(n_collapses_mc);
|
||||||
if (_mc_factor < 1.0)
|
if (_mc_factor < 1.0)
|
||||||
r_collapses += DecimaterT<Mesh>::decimate(n_collapses_inc);
|
r_collapses += DecimaterT<Mesh>::decimate(n_collapses_inc);
|
||||||
|
|
||||||
return r_collapses;
|
return r_collapses;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -106,13 +107,18 @@ size_t MixedDecimaterT<Mesh>::decimate_to_faces(const size_t _n_vertices,const
|
|||||||
std::size_t r_collapses = 0;
|
std::size_t r_collapses = 0;
|
||||||
if (_mc_factor > 0.0)
|
if (_mc_factor > 0.0)
|
||||||
{
|
{
|
||||||
size_t mesh_faces = this->mesh().n_faces();
|
bool constraintsOnly = (_n_vertices == 0) && (_n_faces == 1);
|
||||||
size_t mesh_vertices = this->mesh().n_vertices();
|
if (!constraintsOnly) {
|
||||||
//reduce the mesh only for _mc_factor
|
size_t mesh_faces = this->mesh().n_faces();
|
||||||
size_t n_vertices_mc = static_cast<size_t>(mesh_vertices - _mc_factor * (mesh_vertices - _n_vertices));
|
size_t mesh_vertices = this->mesh().n_vertices();
|
||||||
size_t n_faces_mc = static_cast<size_t>(mesh_faces - _mc_factor * (mesh_faces - _n_faces));
|
//reduce the mesh only for _mc_factor
|
||||||
|
size_t n_vertices_mc = static_cast<size_t>(mesh_vertices - _mc_factor * (mesh_vertices - _n_vertices));
|
||||||
|
size_t n_faces_mc = static_cast<size_t>(mesh_faces - _mc_factor * (mesh_faces - _n_faces));
|
||||||
|
|
||||||
r_collapses = McDecimaterT<Mesh>::decimate_to_faces(n_vertices_mc, n_faces_mc);
|
r_collapses = McDecimaterT<Mesh>::decimate_to_faces(n_vertices_mc, n_faces_mc);
|
||||||
|
} else {
|
||||||
|
r_collapses = McDecimaterT<Mesh>::decimate_constraints_only(_mc_factor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//update the mesh::n_vertices function, otherwise the next Decimater function will delete to much
|
//update the mesh::n_vertices function, otherwise the next Decimater function will delete to much
|
||||||
@@ -122,6 +128,7 @@ size_t MixedDecimaterT<Mesh>::decimate_to_faces(const size_t _n_vertices,const
|
|||||||
if (_mc_factor < 1.0)
|
if (_mc_factor < 1.0)
|
||||||
r_collapses += DecimaterT<Mesh>::decimate_to_faces(_n_vertices,_n_faces);
|
r_collapses += DecimaterT<Mesh>::decimate_to_faces(_n_vertices,_n_faces);
|
||||||
|
|
||||||
|
|
||||||
return r_collapses;
|
return r_collapses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -173,6 +173,20 @@ float ModAspectRatioT<MeshT>::collapse_priority(const CollapseInfo& _ci) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class MeshT>
|
||||||
|
void ModAspectRatioT<MeshT>::set_error_tolerance_factor(double _factor) {
|
||||||
|
if (_factor >= 0.0 && _factor <= 1.0) {
|
||||||
|
// the smaller the factor, the larger min_aspect_ gets
|
||||||
|
// thus creating a stricter constraint
|
||||||
|
// division by (2.0 - error_tolerance_factor_) is for normalization
|
||||||
|
double min_aspect = min_aspect_ * (2.0 - _factor) / (2.0 - this->error_tolerance_factor_);
|
||||||
|
set_aspect_ratio(1.0/min_aspect);
|
||||||
|
this->error_tolerance_factor_ = _factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,6 +118,9 @@ class ModAspectRatioT: public ModBaseT<MeshT> {
|
|||||||
/// update aspect ratio of one-ring
|
/// update aspect ratio of one-ring
|
||||||
void preprocess_collapse(const CollapseInfo& _ci);
|
void preprocess_collapse(const CollapseInfo& _ci);
|
||||||
|
|
||||||
|
/// set percentage of aspect ratio
|
||||||
|
void set_error_tolerance_factor(double _factor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** \brief return aspect ratio (length/height) of triangle
|
/** \brief return aspect ratio (length/height) of triangle
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
||||||
* www.openmesh.org *
|
* www.openmesh.org *
|
||||||
* *
|
* *
|
||||||
*---------------------------------------------------------------------------*
|
*---------------------------------------------------------------------------*
|
||||||
* This file is part of OpenMesh. *
|
* This file is part of OpenMesh. *
|
||||||
* *
|
* *
|
||||||
* OpenMesh is free software: you can redistribute it and/or modify *
|
* OpenMesh is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
* published by the Free Software Foundation, either version 3 of *
|
* published by the Free Software Foundation, either version 3 of *
|
||||||
* the License, or (at your option) any later version with the *
|
* the License, or (at your option) any later version with the *
|
||||||
@@ -30,10 +30,10 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision$ *
|
* $Revision$ *
|
||||||
* $Date$ *
|
* $Date$ *
|
||||||
* *
|
* *
|
||||||
@@ -88,11 +88,11 @@ public:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
ModHandleT() : mod_(NULL) {}
|
ModHandleT() : mod_(NULL) {}
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~ModHandleT() { /* don't delete mod_, since handle is not owner! */ }
|
~ModHandleT() { /* don't delete mod_, since handle is not owner! */ }
|
||||||
|
|
||||||
/// Check handle status
|
/// Check handle status
|
||||||
/// \return \c true, if handle is valid, else \c false.
|
/// \return \c true, if handle is valid, else \c false.
|
||||||
bool is_valid() const { return mod_ != NULL; }
|
bool is_valid() const { return mod_ != NULL; }
|
||||||
@@ -132,13 +132,13 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
/** Convenience macro, to be used in derived modules
|
/** Convenience macro, to be used in derived modules
|
||||||
* The macro defines the types
|
* The macro defines the types
|
||||||
* - \c Handle, type of the module's handle.
|
* - \c Handle, type of the module's handle.
|
||||||
* - \c Base, type of ModBaseT<>.
|
* - \c Base, type of ModBaseT<>.
|
||||||
* - \c Mesh, type of the associated mesh passed by the decimater type.
|
* - \c Mesh, type of the associated mesh passed by the decimater type.
|
||||||
* - \c CollapseInfo, to your convenience
|
* - \c CollapseInfo, to your convenience
|
||||||
* and uses DECIMATER_MODNAME() to define the name of the module.
|
* and uses DECIMATER_MODNAME() to define the name of the module.
|
||||||
*
|
*
|
||||||
* \param Classname The name of the derived class.
|
* \param Classname The name of the derived class.
|
||||||
* \param MeshT Pass here the mesh type, which is the
|
* \param MeshT Pass here the mesh type, which is the
|
||||||
* template parameter passed to ModBaseT.
|
* template parameter passed to ModBaseT.
|
||||||
@@ -160,7 +160,7 @@ private:
|
|||||||
/** Base class for all decimation modules.
|
/** Base class for all decimation modules.
|
||||||
|
|
||||||
Each module has to implement this interface.
|
Each module has to implement this interface.
|
||||||
To build your own module you have to
|
To build your own module you have to
|
||||||
-# derive from this class.
|
-# derive from this class.
|
||||||
-# create the basic settings with DECIMATING_MODULE().
|
-# create the basic settings with DECIMATING_MODULE().
|
||||||
-# override collapse_priority(), if necessary.
|
-# override collapse_priority(), if necessary.
|
||||||
@@ -199,20 +199,20 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
/// \see \ref decimater_docu
|
/// \see \ref decimater_docu
|
||||||
ModBaseT(MeshT& _mesh, bool _is_binary)
|
ModBaseT(MeshT& _mesh, bool _is_binary)
|
||||||
: mesh_(_mesh), is_binary_(_is_binary) {}
|
: error_tolerance_factor_(1.0), mesh_(_mesh), is_binary_(_is_binary) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Virtual desctructor
|
/// Virtual desctructor
|
||||||
virtual ~ModBaseT() { }
|
virtual ~ModBaseT() { }
|
||||||
|
|
||||||
/// Set module's name (using DECIMATER_MODNAME macro)
|
/// Set module's name (using DECIMATER_MODNAME macro)
|
||||||
DECIMATER_MODNAME(ModBase);
|
DECIMATER_MODNAME(ModBase);
|
||||||
|
|
||||||
|
|
||||||
/// Returns true if criteria returns a binary value.
|
/// Returns true if criteria returns a binary value.
|
||||||
bool is_binary(void) const { return is_binary_; }
|
bool is_binary(void) const { return is_binary_; }
|
||||||
@@ -222,11 +222,11 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
public: // common interface
|
public: // common interface
|
||||||
|
|
||||||
/// Initialize module-internal stuff
|
/// Initialize module-internal stuff
|
||||||
virtual void initialize() { }
|
virtual void initialize() { }
|
||||||
|
|
||||||
/** Return collapse priority.
|
/** Return collapse priority.
|
||||||
*
|
*
|
||||||
* In the binary mode collapse_priority() checks a constraint and
|
* In the binary mode collapse_priority() checks a constraint and
|
||||||
* returns LEGAL_COLLAPSE or ILLEGAL_COLLAPSE.
|
* returns LEGAL_COLLAPSE or ILLEGAL_COLLAPSE.
|
||||||
@@ -237,7 +237,7 @@ public: // common interface
|
|||||||
* constraint is violated, collapse_priority() must return
|
* constraint is violated, collapse_priority() must return
|
||||||
* ILLEGAL_COLLAPSE.
|
* ILLEGAL_COLLAPSE.
|
||||||
*
|
*
|
||||||
* \return Collapse priority in the range [0,inf),
|
* \return Collapse priority in the range [0,inf),
|
||||||
* \c LEGAL_COLLAPSE or \c ILLEGAL_COLLAPSE.
|
* \c LEGAL_COLLAPSE or \c ILLEGAL_COLLAPSE.
|
||||||
*/
|
*/
|
||||||
virtual float collapse_priority(const CollapseInfoT<MeshT>& /* _ci */)
|
virtual float collapse_priority(const CollapseInfoT<MeshT>& /* _ci */)
|
||||||
@@ -250,11 +250,23 @@ public: // common interface
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
/** After _from_vh has been collapsed into _to_vh, this method
|
/** After _from_vh has been collapsed into _to_vh, this method
|
||||||
will be called.
|
will be called.
|
||||||
*/
|
*/
|
||||||
virtual void postprocess_collapse(const CollapseInfoT<MeshT>& /* _ci */)
|
virtual void postprocess_collapse(const CollapseInfoT<MeshT>& /* _ci */)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This provides a function that allows the setting of a percentage
|
||||||
|
* of the original contraint.
|
||||||
|
*
|
||||||
|
* Note that the module might need to be re-initialized again after
|
||||||
|
* setting the percentage
|
||||||
|
* @param factor_ has to be in the closed interval between 0.0 and 1.0
|
||||||
|
*/
|
||||||
|
virtual void set_error_tolerance_factor(double _factor) {
|
||||||
|
if (_factor >= 0.0 && _factor <= 1.0)
|
||||||
|
error_tolerance_factor_ = _factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -262,6 +274,9 @@ protected:
|
|||||||
/// Access the mesh associated with the decimater.
|
/// Access the mesh associated with the decimater.
|
||||||
MeshT& mesh() { return mesh_; }
|
MeshT& mesh() { return mesh_; }
|
||||||
|
|
||||||
|
// current percentage of the original constraint
|
||||||
|
double error_tolerance_factor_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// hide copy constructor & assignemnt
|
// hide copy constructor & assignemnt
|
||||||
|
|||||||
@@ -76,6 +76,20 @@ float ModEdgeLengthT<MeshT>::collapse_priority(const CollapseInfo& _ci) {
|
|||||||
return ( (sqr_length <= sqr_edge_length_) ? sqr_length : float(Base::ILLEGAL_COLLAPSE));
|
return ( (sqr_length <= sqr_edge_length_) ? sqr_length : float(Base::ILLEGAL_COLLAPSE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class MeshT>
|
||||||
|
void ModEdgeLengthT<MeshT>::set_error_tolerance_factor(double _factor) {
|
||||||
|
if (_factor >= 0.0 && _factor <= 1.0) {
|
||||||
|
// the smaller the factor, the smaller edge_length_ gets
|
||||||
|
// thus creating a stricter constraint
|
||||||
|
// division by error_tolerance_factor_ is for normalization
|
||||||
|
float edge_length = edge_length_ * _factor / this->error_tolerance_factor_;
|
||||||
|
set_edge_length(edge_length);
|
||||||
|
this->error_tolerance_factor_ = _factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,9 @@ class ModEdgeLengthT: public ModBaseT<MeshT> {
|
|||||||
*/
|
*/
|
||||||
float collapse_priority(const CollapseInfo& _ci);
|
float collapse_priority(const CollapseInfo& _ci);
|
||||||
|
|
||||||
|
/// set the percentage of edge length
|
||||||
|
void set_error_tolerance_factor(double _factor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Mesh& mesh_;
|
Mesh& mesh_;
|
||||||
|
|||||||
@@ -269,9 +269,21 @@ collapse_priority(const CollapseInfo& _ci)
|
|||||||
return ( ok ? Base::LEGAL_COLLAPSE : Base::ILLEGAL_COLLAPSE );
|
return ( ok ? Base::LEGAL_COLLAPSE : Base::ILLEGAL_COLLAPSE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class MeshT>
|
||||||
|
void ModHausdorffT<MeshT>::set_error_tolerance_factor(double _factor) {
|
||||||
|
if (_factor >= 0.0 && _factor <= 1.0) {
|
||||||
|
// the smaller the factor, the smaller tolerance gets
|
||||||
|
// thus creating a stricter constraint
|
||||||
|
// division by error_tolerance_factor_ is for normalization
|
||||||
|
Scalar tolerance = tolerance_ * _factor / this->error_tolerance_factor_;
|
||||||
|
set_tolerance(tolerance);
|
||||||
|
this->error_tolerance_factor_ = _factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <class MeshT>
|
template <class MeshT>
|
||||||
void
|
void
|
||||||
@@ -380,8 +392,11 @@ compute_sqr_error(FaceHandle _fh, const Point& _p) const
|
|||||||
#pragma omp parallel for private(e) shared(emax)
|
#pragma omp parallel for private(e) shared(emax)
|
||||||
for (int i = 0; i < pointsCount; ++i) {
|
for (int i = 0; i < pointsCount; ++i) {
|
||||||
e = distPointTriangleSquared(points[i], p0, p1, p2, dummy);
|
e = distPointTriangleSquared(points[i], p0, p1, p2, dummy);
|
||||||
|
#pragma omp critical(emaxUpdate)
|
||||||
|
{
|
||||||
if (e > emax)
|
if (e > emax)
|
||||||
emax = e;
|
emax = e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
for (; p_it!=p_end; ++p_it) {
|
for (; p_it!=p_end; ++p_it) {
|
||||||
|
|||||||
@@ -124,6 +124,9 @@ class ModHausdorffT: public ModBaseT<MeshT> {
|
|||||||
/// re-distribute points
|
/// re-distribute points
|
||||||
virtual void postprocess_collapse(const CollapseInfo& _ci);
|
virtual void postprocess_collapse(const CollapseInfo& _ci);
|
||||||
|
|
||||||
|
/// set the percentage of tolerance
|
||||||
|
void set_error_tolerance_factor(double _factor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// squared distance from point _p to triangle (_v0, _v1, _v2)
|
/// squared distance from point _p to triangle (_v0, _v1, _v2)
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ template <class MeshT>
|
|||||||
class ModNormalDeviationT : public ModBaseT< MeshT >
|
class ModNormalDeviationT : public ModBaseT< MeshT >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DECIMATING_MODULE( ModNormalDeviationT, MeshT, NormalDeviation );
|
DECIMATING_MODULE( ModNormalDeviationT, MeshT, NormalDeviation );
|
||||||
|
|
||||||
typedef typename Mesh::Scalar Scalar;
|
typedef typename Mesh::Scalar Scalar;
|
||||||
@@ -191,6 +191,18 @@ public:
|
|||||||
return (max_angle < 0.5 * normal_deviation_ ? max_angle : float( Base::ILLEGAL_COLLAPSE ));
|
return (max_angle < 0.5 * normal_deviation_ ? max_angle : float( Base::ILLEGAL_COLLAPSE ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// set the percentage of normal deviation
|
||||||
|
void set_error_tolerance_factor(double _factor) {
|
||||||
|
if (_factor >= 0.0 && _factor <= 1.0) {
|
||||||
|
// the smaller the factor, the smaller normal_deviation_ gets
|
||||||
|
// thus creating a stricter constraint
|
||||||
|
// division by error_tolerance_factor_ is for normalization
|
||||||
|
Scalar normal_deviation = (normal_deviation_ * 180.0/M_PI) * _factor / this->error_tolerance_factor_;
|
||||||
|
set_normal_deviation(normal_deviation);
|
||||||
|
this->error_tolerance_factor_ = _factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void postprocess_collapse(const CollapseInfo& _ci) {
|
void postprocess_collapse(const CollapseInfo& _ci) {
|
||||||
// account for changed normals
|
// account for changed normals
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
||||||
* www.openmesh.org *
|
* www.openmesh.org *
|
||||||
* *
|
* *
|
||||||
*---------------------------------------------------------------------------*
|
*---------------------------------------------------------------------------*
|
||||||
* This file is part of OpenMesh. *
|
* This file is part of OpenMesh. *
|
||||||
* *
|
* *
|
||||||
* OpenMesh is free software: you can redistribute it and/or modify *
|
* OpenMesh is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
* published by the Free Software Foundation, either version 3 of *
|
* published by the Free Software Foundation, either version 3 of *
|
||||||
* the License, or (at your option) any later version with the *
|
* the License, or (at your option) any later version with the *
|
||||||
@@ -30,17 +30,17 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision$ *
|
* $Revision$ *
|
||||||
* $Date$ *
|
* $Date$ *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/** \file ModNormalFlippingT.hh
|
/** \file ModNormalFlippingT.hh
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@@ -67,44 +67,44 @@ namespace Decimater { // BEGIN_NS_DECIMATER
|
|||||||
//== CLASS DEFINITION =========================================================
|
//== CLASS DEFINITION =========================================================
|
||||||
|
|
||||||
/** Decimating module to avoid flipping of faces.
|
/** Decimating module to avoid flipping of faces.
|
||||||
*
|
*
|
||||||
* This module can be used only as a binary module. The criterion
|
* This module can be used only as a binary module. The criterion
|
||||||
* of allowing/disallowing the collapse is the angular deviation between
|
* of allowing/disallowing the collapse is the angular deviation between
|
||||||
* the face normal of the original faces and normals of the faces after the
|
* the face normal of the original faces and normals of the faces after the
|
||||||
* collapse. The collapse will pass the test, if the deviation is below
|
* collapse. The collapse will pass the test, if the deviation is below
|
||||||
* a given threshold.
|
* a given threshold.
|
||||||
*/
|
*/
|
||||||
template <typename MeshT>
|
template <typename MeshT>
|
||||||
class ModNormalFlippingT : public ModBaseT< MeshT >
|
class ModNormalFlippingT : public ModBaseT< MeshT >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DECIMATING_MODULE( ModNormalFlippingT, MeshT, NormalFlipping );
|
DECIMATING_MODULE( ModNormalFlippingT, MeshT, NormalFlipping );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
ModNormalFlippingT( MeshT &_mesh) : Base(_mesh, true)
|
ModNormalFlippingT( MeshT &_mesh) : Base(_mesh, true)
|
||||||
{
|
{
|
||||||
set_max_normal_deviation( 90.0f );
|
set_max_normal_deviation( 90.0f );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
~ModNormalFlippingT()
|
|
||||||
|
~ModNormalFlippingT()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Compute collapse priority due to angular deviation of face normals
|
/** Compute collapse priority due to angular deviation of face normals
|
||||||
* before and after a collapse.
|
* before and after a collapse.
|
||||||
*
|
*
|
||||||
* -# Compute for each adjacent face of \c _ci.v0 the face
|
* -# Compute for each adjacent face of \c _ci.v0 the face
|
||||||
* normal if the collpase would be executed.
|
* normal if the collpase would be executed.
|
||||||
*
|
*
|
||||||
* -# Prevent the collapse, if the cosine of the angle between the
|
* -# Prevent the collapse, if the cosine of the angle between the
|
||||||
* original and the new normal is below a given threshold.
|
* original and the new normal is below a given threshold.
|
||||||
*
|
*
|
||||||
* \param _ci The collapse description
|
* \param _ci The collapse description
|
||||||
* \return LEGAL_COLLAPSE or ILLEGAL_COLLAPSE
|
* \return LEGAL_COLLAPSE or ILLEGAL_COLLAPSE
|
||||||
*
|
*
|
||||||
@@ -114,13 +114,13 @@ public:
|
|||||||
{
|
{
|
||||||
// simulate collapse
|
// simulate collapse
|
||||||
Base::mesh().set_point(_ci.v0, _ci.p1);
|
Base::mesh().set_point(_ci.v0, _ci.p1);
|
||||||
|
|
||||||
// check for flipping normals
|
// check for flipping normals
|
||||||
typename Mesh::ConstVertexFaceIter vf_it(Base::mesh(), _ci.v0);
|
typename Mesh::ConstVertexFaceIter vf_it(Base::mesh(), _ci.v0);
|
||||||
typename Mesh::FaceHandle fh;
|
typename Mesh::FaceHandle fh;
|
||||||
typename Mesh::Scalar c(1.0);
|
typename Mesh::Scalar c(1.0);
|
||||||
|
|
||||||
for (; vf_it; ++vf_it)
|
for (; vf_it; ++vf_it)
|
||||||
{
|
{
|
||||||
fh = vf_it.handle();
|
fh = vf_it.handle();
|
||||||
if (fh != _ci.fl && fh != _ci.fr)
|
if (fh != _ci.fl && fh != _ci.fr)
|
||||||
@@ -129,40 +129,51 @@ public:
|
|||||||
typename Mesh::Normal n2 = Base::mesh().calc_face_normal(fh);
|
typename Mesh::Normal n2 = Base::mesh().calc_face_normal(fh);
|
||||||
|
|
||||||
c = dot(n1, n2);
|
c = dot(n1, n2);
|
||||||
|
|
||||||
if (c < min_cos_)
|
if (c < min_cos_)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// undo simulation changes
|
// undo simulation changes
|
||||||
Base::mesh().set_point(_ci.v0, _ci.p0);
|
Base::mesh().set_point(_ci.v0, _ci.p0);
|
||||||
|
|
||||||
return float( (c < min_cos_) ? Base::ILLEGAL_COLLAPSE : Base::LEGAL_COLLAPSE );
|
return float( (c < min_cos_) ? Base::ILLEGAL_COLLAPSE : Base::LEGAL_COLLAPSE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// set the percentage of maximum normal deviation
|
||||||
|
void set_error_tolerance_factor(double _factor) {
|
||||||
|
if (_factor >= 0.0 && _factor <= 1.0) {
|
||||||
|
// the smaller the factor, the smaller max_deviation_ gets
|
||||||
|
// thus creating a stricter constraint
|
||||||
|
// division by error_tolerance_factor_ is for normalization
|
||||||
|
float max_normal_deviation = (max_deviation_ * 180.0/M_PI) * _factor / this->error_tolerance_factor_;
|
||||||
|
set_max_normal_deviation(max_normal_deviation);
|
||||||
|
this->error_tolerance_factor_ = _factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// get normal deviation
|
/// get normal deviation
|
||||||
float max_normal_deviation() const { return max_deviation_ / M_PI * 180.0; }
|
float max_normal_deviation() const { return max_deviation_ / M_PI * 180.0; }
|
||||||
|
|
||||||
/** Set normal deviation
|
/** Set normal deviation
|
||||||
*
|
*
|
||||||
* Set the maximum angular deviation of the orignal normal and the new
|
* Set the maximum angular deviation of the orignal normal and the new
|
||||||
* normal in degrees.
|
* normal in degrees.
|
||||||
*/
|
*/
|
||||||
void set_max_normal_deviation(float _f) {
|
void set_max_normal_deviation(float _f) {
|
||||||
max_deviation_ = _f / 180.0 * M_PI;
|
max_deviation_ = _f / 180.0 * M_PI;
|
||||||
min_cos_ = cos(max_deviation_);
|
min_cos_ = cos(max_deviation_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// hide this method
|
// hide this method
|
||||||
void set_binary(bool _b) {}
|
void set_binary(bool _b) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// maximum normal deviation
|
// maximum normal deviation
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
||||||
* www.openmesh.org *
|
* www.openmesh.org *
|
||||||
* *
|
* *
|
||||||
*---------------------------------------------------------------------------*
|
*---------------------------------------------------------------------------*
|
||||||
* This file is part of OpenMesh. *
|
* This file is part of OpenMesh. *
|
||||||
* *
|
* *
|
||||||
* OpenMesh is free software: you can redistribute it and/or modify *
|
* OpenMesh is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
* published by the Free Software Foundation, either version 3 of *
|
* published by the Free Software Foundation, either version 3 of *
|
||||||
* the License, or (at your option) any later version with the *
|
* the License, or (at your option) any later version with the *
|
||||||
@@ -30,10 +30,10 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision$ *
|
* $Revision$ *
|
||||||
* $Date$ *
|
* $Date$ *
|
||||||
* *
|
* *
|
||||||
@@ -129,6 +129,23 @@ initialize()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class MeshT>
|
||||||
|
void ModQuadricT<MeshT>::set_error_tolerance_factor(double _factor) {
|
||||||
|
if (this->is_binary()) {
|
||||||
|
if (_factor >= 0.0 && _factor <= 1.0) {
|
||||||
|
// the smaller the factor, the smaller max_err_ gets
|
||||||
|
// thus creating a stricter constraint
|
||||||
|
// division by error_tolerance_factor_ is for normalization
|
||||||
|
double max_err = max_err_ * _factor / this->error_tolerance_factor_;
|
||||||
|
set_max_err(max_err);
|
||||||
|
this->error_tolerance_factor_ = _factor;
|
||||||
|
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
} // END_NS_DECIMATER
|
} // END_NS_DECIMATER
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
||||||
* www.openmesh.org *
|
* www.openmesh.org *
|
||||||
* *
|
* *
|
||||||
*---------------------------------------------------------------------------*
|
*---------------------------------------------------------------------------*
|
||||||
* This file is part of OpenMesh. *
|
* This file is part of OpenMesh. *
|
||||||
* *
|
* *
|
||||||
* OpenMesh is free software: you can redistribute it and/or modify *
|
* OpenMesh is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
* published by the Free Software Foundation, either version 3 of *
|
* published by the Free Software Foundation, either version 3 of *
|
||||||
* the License, or (at your option) any later version with the *
|
* the License, or (at your option) any later version with the *
|
||||||
@@ -30,10 +30,10 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision$ *
|
* $Revision$ *
|
||||||
* $Date$ *
|
* $Date$ *
|
||||||
* *
|
* *
|
||||||
@@ -138,6 +138,9 @@ public: // inherited
|
|||||||
Base::mesh().property(quadrics_, _ci.v0);
|
Base::mesh().property(quadrics_, _ci.v0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// set the percentage of maximum quadric error
|
||||||
|
void set_error_tolerance_factor(double _factor);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public: // specific methods
|
public: // specific methods
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
||||||
* www.openmesh.org *
|
* www.openmesh.org *
|
||||||
* *
|
* *
|
||||||
*---------------------------------------------------------------------------*
|
*---------------------------------------------------------------------------*
|
||||||
* This file is part of OpenMesh. *
|
* This file is part of OpenMesh. *
|
||||||
* *
|
* *
|
||||||
* OpenMesh is free software: you can redistribute it and/or modify *
|
* OpenMesh is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
* published by the Free Software Foundation, either version 3 of *
|
* published by the Free Software Foundation, either version 3 of *
|
||||||
* the License, or (at your option) any later version with the *
|
* the License, or (at your option) any later version with the *
|
||||||
@@ -30,10 +30,10 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision$ *
|
* $Revision$ *
|
||||||
* $Date$ *
|
* $Date$ *
|
||||||
* *
|
* *
|
||||||
@@ -96,7 +96,7 @@ class ModRoundnessT : public ModBaseT<MeshT>
|
|||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
ModRoundnessT( MeshT &_dec ) :
|
ModRoundnessT( MeshT &_dec ) :
|
||||||
Base(_dec, false),
|
Base(_dec, false),
|
||||||
min_r_(-1.0)
|
min_r_(-1.0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@@ -109,14 +109,14 @@ class ModRoundnessT : public ModBaseT<MeshT>
|
|||||||
*
|
*
|
||||||
* The roundness is computed by dividing the radius of the
|
* The roundness is computed by dividing the radius of the
|
||||||
* circumference by the length of the shortest edge. The result is
|
* circumference by the length of the shortest edge. The result is
|
||||||
* normalized.
|
* normalized.
|
||||||
*
|
*
|
||||||
* \return [0:1] or ILLEGAL_COLLAPSE in non-binary mode
|
* \return [0:1] or ILLEGAL_COLLAPSE in non-binary mode
|
||||||
* \return LEGAL_COLLAPSE or ILLEGAL_COLLAPSE in binary mode
|
* \return LEGAL_COLLAPSE or ILLEGAL_COLLAPSE in binary mode
|
||||||
* \see set_min_roundness()
|
* \see set_min_roundness()
|
||||||
*/
|
*/
|
||||||
float collapse_priority(const CollapseInfo& _ci)
|
float collapse_priority(const CollapseInfo& _ci)
|
||||||
{
|
{
|
||||||
// using namespace OpenMesh;
|
// using namespace OpenMesh;
|
||||||
|
|
||||||
typename Mesh::ConstVertexOHalfedgeIter voh_it(Base::mesh(), _ci.v0);
|
typename Mesh::ConstVertexOHalfedgeIter voh_it(Base::mesh(), _ci.v0);
|
||||||
@@ -126,11 +126,11 @@ class ModRoundnessT : public ModBaseT<MeshT>
|
|||||||
Vec3f B,C;
|
Vec3f B,C;
|
||||||
|
|
||||||
if ( min_r_ < 0.0 ) // continues mode
|
if ( min_r_ < 0.0 ) // continues mode
|
||||||
{
|
{
|
||||||
C = vector_cast<Vec3f>(Base::mesh().point( Base::mesh().to_vertex_handle(voh_it)));
|
C = vector_cast<Vec3f>(Base::mesh().point( Base::mesh().to_vertex_handle(voh_it)));
|
||||||
fhC = Base::mesh().face_handle( voh_it.handle() );
|
fhC = Base::mesh().face_handle( voh_it.handle() );
|
||||||
|
|
||||||
for (++voh_it; voh_it; ++voh_it)
|
for (++voh_it; voh_it; ++voh_it)
|
||||||
{
|
{
|
||||||
B = C;
|
B = C;
|
||||||
fhB = fhC;
|
fhB = fhC;
|
||||||
@@ -153,7 +153,7 @@ class ModRoundnessT : public ModBaseT<MeshT>
|
|||||||
C = vector_cast<Vec3f>(Base::mesh().point( Base::mesh().to_vertex_handle(voh_it)));
|
C = vector_cast<Vec3f>(Base::mesh().point( Base::mesh().to_vertex_handle(voh_it)));
|
||||||
fhC = Base::mesh().face_handle( voh_it.handle() );
|
fhC = Base::mesh().face_handle( voh_it.handle() );
|
||||||
|
|
||||||
for (++voh_it; voh_it && (priority==Base::LEGAL_COLLAPSE); ++voh_it)
|
for (++voh_it; voh_it && (priority==Base::LEGAL_COLLAPSE); ++voh_it)
|
||||||
{
|
{
|
||||||
B = C;
|
B = C;
|
||||||
fhB = fhC;
|
fhB = fhC;
|
||||||
@@ -171,6 +171,19 @@ class ModRoundnessT : public ModBaseT<MeshT>
|
|||||||
return (float) priority;
|
return (float) priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// set the percentage of minimum roundness
|
||||||
|
void set_error_tolerance_factor(double _factor) {
|
||||||
|
if (this->is_binary()) {
|
||||||
|
if (_factor >= 0.0 && _factor <= 1.0) {
|
||||||
|
// the smaller the factor, the smaller min_r_ gets
|
||||||
|
// thus creating a stricter constraint
|
||||||
|
// division by error_tolerance_factor_ is for normalization
|
||||||
|
value_type min_roundness = min_r_ * _factor / this->error_tolerance_factor_;
|
||||||
|
set_min_roundness(min_roundness);
|
||||||
|
this->error_tolerance_factor_ = _factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public: // specific methods
|
public: // specific methods
|
||||||
@@ -197,12 +210,12 @@ public: // specific methods
|
|||||||
|
|
||||||
double r2 = roundness(A,B,C);
|
double r2 = roundness(A,B,C);
|
||||||
|
|
||||||
set_min_roundness( value_type(std::min(r1,r2)), true );
|
set_min_roundness( value_type(std::min(r1,r2)), true );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set a minimum roundness value.
|
/** Set a minimum roundness value.
|
||||||
* \param _min_roundness in range (0,1)
|
* \param _min_roundness in range (0,1)
|
||||||
* \param _binary Set true, if the binary mode should be enabled,
|
* \param _binary Set true, if the binary mode should be enabled,
|
||||||
* else false. In latter case the collapse_priority()
|
* else false. In latter case the collapse_priority()
|
||||||
* returns a float value if the constraint does not apply
|
* returns a float value if the constraint does not apply
|
||||||
* and ILLEGAL_COLLAPSE else.
|
* and ILLEGAL_COLLAPSE else.
|
||||||
@@ -230,11 +243,11 @@ public: // specific methods
|
|||||||
//
|
//
|
||||||
// then define
|
// then define
|
||||||
//
|
//
|
||||||
// radius of circumference
|
// radius of circumference
|
||||||
// R := -----------------------
|
// R := -----------------------
|
||||||
// length of shortest edge
|
// length of shortest edge
|
||||||
//
|
//
|
||||||
// ||a|| * ||b|| * ||c||
|
// ||a|| * ||b|| * ||c||
|
||||||
// ---------------------
|
// ---------------------
|
||||||
// 4 * Area ||a|| * ||b|| * ||c||
|
// 4 * Area ||a|| * ||b|| * ||c||
|
||||||
// = ----------------------- = -----------------------------------
|
// = ----------------------- = -----------------------------------
|
||||||
@@ -254,7 +267,7 @@ public: // specific methods
|
|||||||
//
|
//
|
||||||
// At angle 60<36> R has it's minimum for all edge lengths = sqrt(1/3)
|
// At angle 60<36> R has it's minimum for all edge lengths = sqrt(1/3)
|
||||||
//
|
//
|
||||||
// Define normalized roundness
|
// Define normalized roundness
|
||||||
//
|
//
|
||||||
// nR := sqrt(1/3) / R
|
// nR := sqrt(1/3) / R
|
||||||
//
|
//
|
||||||
@@ -266,7 +279,7 @@ public: // specific methods
|
|||||||
{
|
{
|
||||||
const value_type epsilon = value_type(1e-15);
|
const value_type epsilon = value_type(1e-15);
|
||||||
|
|
||||||
static const value_type sqrt43 = value_type(sqrt(4.0/3.0)); // 60<36>,a=b=c, **)
|
static const value_type sqrt43 = value_type(sqrt(4.0/3.0)); // 60<36>,a=b=c, **)
|
||||||
|
|
||||||
Vec3f vecAC = C-A;
|
Vec3f vecAC = C-A;
|
||||||
Vec3f vecAB = B-A;
|
Vec3f vecAB = B-A;
|
||||||
@@ -281,7 +294,7 @@ public: // specific methods
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
double nom = AA * std::min( std::min(aa,bb),cc );
|
double nom = AA * std::min( std::min(aa,bb),cc );
|
||||||
double denom = aa * bb * cc;
|
double denom = aa * bb * cc;
|
||||||
double nR = sqrt43 * sqrt(nom/denom);
|
double nR = sqrt43 * sqrt(nom/denom);
|
||||||
|
|
||||||
return nR;
|
return nR;
|
||||||
|
|||||||
Reference in New Issue
Block a user