57 #define OPENMESH_MULTIPLE_CHOICE_DECIMATER_DECIMATERT_CC
64 #if defined(OM_CC_MIPS)
71 # include <OpenMesh/Core/Utils/RandomNumberGenerator.hh>
84 mesh_(_mesh), randomSamples_(10) {
87 mesh_.request_vertex_status();
88 mesh_.request_halfedge_status();
89 mesh_.request_edge_status();
90 mesh_.request_face_status();
99 mesh_.release_vertex_status();
100 mesh_.release_edge_status();
101 mesh_.release_halfedge_status();
102 mesh_.release_face_status();
110 if (!this->is_initialized())
113 unsigned int n_collapses(0);
115 bool collapsesUnchanged =
false;
117 unsigned int oldCollapses = 0;
120 unsigned int noCollapses = 0;
126 const bool update_normals = mesh_.has_face_normals();
128 while ( n_collapses < _n_collapses) {
130 if (noCollapses > 20) {
131 omlog() <<
"[McDecimater] : no collapses performed in over 20 iterations in a row\n";
136 typename Mesh::HalfedgeHandle bestHandle(-1);
137 typename Mesh::HalfedgeHandle tmpHandle(-1);
138 double bestEnergy = FLT_MAX;
139 double energy = FLT_MAX;
142 for (
int i = 0; i < (int)randomSamples_; ++i) {
146 tmpHandle =
typename Mesh::HalfedgeHandle(
int(randGen.getRand() * double(mesh_.n_halfedges() - 1.0)) );
148 tmpHandle =
typename Mesh::HalfedgeHandle( (
double(rand()) /
double(RAND_MAX) ) *
double(mesh_.n_halfedges()-1) );
152 if ( ! mesh_.status(tmpHandle).deleted() ) {
157 if (this->is_collapse_legal(ci)) {
158 energy = this->collapse_priority(ci);
162 if ( energy < bestEnergy ) {
164 bestHandle = tmpHandle;
175 if ( bestEnergy != FLT_MAX ) {
181 if (!this->is_collapse_legal(ci))
185 this->preprocess_collapse(ci);
188 mesh_.collapse(bestHandle);
192 oldCollapses = n_collapses;
194 collapsesUnchanged =
false;
200 for (; vf_it.is_valid(); ++vf_it)
201 if (!mesh_.status(*vf_it).deleted())
206 this->postprocess_collapse(ci);
209 if (!this->notify_observer(n_collapses))
213 if (oldCollapses == n_collapses) {
214 if (collapsesUnchanged ==
false) {
216 collapsesUnchanged =
true;
234 if (!this->is_initialized())
238 if ( (_nv == 0) && (_nf == 1) )
239 return decimate_constraints_only(1.0);
241 size_t nv = mesh_.n_vertices();
242 size_t nf = mesh_.n_faces();
243 unsigned int n_collapses(0);
246 bool collapsesUnchanged =
false;
248 unsigned int oldCollapses = 0;
251 unsigned int noCollapses = 0;
257 const bool update_normals = mesh_.has_face_normals();
259 while ((_nv < nv) && (_nf < nf)) {
261 if (noCollapses > 20) {
262 omlog() <<
"[McDecimater] : no collapses performed in over 20 iterations in a row\n";
267 typename Mesh::HalfedgeHandle bestHandle(-1);
268 typename Mesh::HalfedgeHandle tmpHandle(-1);
269 double bestEnergy = FLT_MAX;
270 double energy = FLT_MAX;
273 for (
int i = 0; i < (int) randomSamples_; ++i) {
277 tmpHandle =
typename Mesh::HalfedgeHandle(
int(randGen.getRand() * double(mesh_.n_halfedges() - 1.0)) );
279 tmpHandle =
typename Mesh::HalfedgeHandle( (
double(rand()) /
double(RAND_MAX) ) *
double(mesh_.n_halfedges() - 1));
283 if (!mesh_.status(tmpHandle).deleted()) {
288 if (this->is_collapse_legal(ci)) {
289 energy = this->collapse_priority(ci);
293 if (energy < bestEnergy) {
295 bestHandle = tmpHandle;
306 if ( bestEnergy != FLT_MAX ) {
312 if (!this->is_collapse_legal(ci))
322 if (mesh_.is_boundary(ci.
v0v1) || mesh_.is_boundary(ci.
v1v0))
328 this->preprocess_collapse(ci);
331 mesh_.collapse(bestHandle);
335 oldCollapses = n_collapses;
337 collapsesUnchanged =
false;
343 for (; vf_it.is_valid(); ++vf_it)
344 if (!mesh_.status(*vf_it).deleted())
349 this->postprocess_collapse(ci);
352 if (!this->notify_observer(n_collapses))
356 if (oldCollapses == n_collapses) {
357 if (collapsesUnchanged ==
false) {
359 collapsesUnchanged =
true;
377 if (!this->is_initialized())
381 this->set_error_tolerance_factor(_factor);
383 unsigned int n_collapses(0);
384 size_t nv = mesh_.n_vertices();
385 size_t nf = mesh_.n_faces();
387 bool lastCollapseIllegal =
false;
389 unsigned int illegalCollapses = 0;
391 bool collapsesUnchanged =
false;
393 unsigned int oldCollapses = 0;
396 unsigned int noCollapses = 0;
398 double energy = FLT_MAX;
399 double bestEnergy = FLT_MAX;
405 while ((noCollapses <= 50) && (illegalCollapses <= 50) && (nv > 0) && (nf > 1)) {
408 typename Mesh::HalfedgeHandle bestHandle(-1);
409 typename Mesh::HalfedgeHandle tmpHandle(-1);
410 bestEnergy = FLT_MAX;
414 const double randomNormalizer = (1.0 / RAND_MAX) * (mesh_.n_halfedges() - 1);
418 for (
int i = 0; i < (int) randomSamples_; ++i) {
422 tmpHandle =
typename Mesh::HalfedgeHandle(
int(randGen.getRand() * double(mesh_.n_halfedges() - 1.0)) );
424 tmpHandle =
typename Mesh::HalfedgeHandle(
int(rand() * randomNormalizer ) );
428 if (!mesh_.status(mesh_.edge_handle(tmpHandle)).deleted()) {
433 if (this->is_collapse_legal(ci)) {
435 energy = this->collapse_priority(ci);
438 if (lastCollapseIllegal) {
441 illegalCollapses = 1;
442 lastCollapseIllegal =
true;
446 illegalCollapses = 0;
447 lastCollapseIllegal =
false;
450 if (energy < bestEnergy) {
452 bestHandle = tmpHandle;
466 if ( bestEnergy != FLT_MAX ) {
472 if (!this->is_collapse_legal(ci))
482 if (mesh_.is_boundary(ci.
v0v1) || mesh_.is_boundary(ci.
v1v0))
488 this->preprocess_collapse(ci);
491 mesh_.collapse(bestHandle);
495 oldCollapses = n_collapses;
497 collapsesUnchanged =
false;
502 for (; vf_it.is_valid(); ++vf_it)
503 if (!mesh_.status(*vf_it).deleted())
507 this->postprocess_collapse(ci);
510 if (!this->notify_observer(n_collapses))
514 if (oldCollapses == n_collapses) {
515 if (collapsesUnchanged ==
false) {
517 collapsesUnchanged =
true;
527 this->set_error_tolerance_factor(1.0);
Mesh::VertexHandle v1
Remaining vertex.
size_t decimate_to_faces(size_t _n_vertices=0, size_t _n_faces=0)
~McDecimaterT()
Destructor.
size_t decimate(size_t _n_collapses)
size_t decimate_constraints_only(float _factor)
Mesh::HalfedgeHandle v1v0
Reverse halfedge.
McDecimaterT(Mesh &_mesh)
Constructor.
Normal calc_face_normal(FaceHandle _fh) const
Kernel::VertexFaceIter VertexFaceIter
Circulator.
Mesh::HalfedgeHandle v0v1
Halfedge to be collapsed.