00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00046
00047
00048
00049
00050
00051
00052 #define OPENMESH_DECIMATER_DECIMATERT_CC
00053
00054
00055
00056
00057 #include <OpenMesh/Tools/Decimater/DecimaterT.hh>
00058
00059 #include <vector>
00060 #if defined(OM_CC_MIPS)
00061 # include <float.h>
00062 #else
00063 # include <cfloat>
00064 #endif
00065
00066
00067
00068
00069
00070 namespace OpenMesh {
00071 namespace Decimater {
00072
00073
00074
00075
00076
00077
00078 template <class Mesh>
00079 DecimaterT<Mesh>::
00080 DecimaterT( Mesh& _mesh )
00081 : mesh_(_mesh),
00082 heap_(NULL),
00083 cmodule_(NULL),
00084 initialized_(false)
00085 {
00086
00087 mesh_.request_vertex_status();
00088 mesh_.request_edge_status();
00089 mesh_.request_face_status();
00090 mesh_.request_face_normals();
00091
00092
00093 mesh_.add_property( collapse_target_ );
00094 mesh_.add_property( priority_ );
00095 mesh_.add_property( heap_position_ );
00096 }
00097
00098
00099
00100
00101
00102 template <class Mesh>
00103 DecimaterT<Mesh>::
00104 ~DecimaterT()
00105 {
00106
00107 mesh_.release_vertex_status();
00108 mesh_.release_edge_status();
00109 mesh_.release_face_status();
00110 mesh_.release_face_normals();
00111
00112
00113 mesh_.remove_property(collapse_target_);
00114 mesh_.remove_property(priority_);
00115 mesh_.remove_property(heap_position_);
00116
00117
00118 {
00119 set_uninitialized();
00120 typename ModuleList::iterator m_it, m_end = all_modules_.end();
00121 for( m_it=all_modules_.begin(); m_it!=m_end; ++m_it)
00122 delete *m_it;
00123 all_modules_.clear();
00124 }
00125 }
00126
00127
00128
00129
00130
00131 template <class Mesh>
00132 void
00133 DecimaterT<Mesh>::
00134 info( std::ostream& _os )
00135 {
00136 if(initialized_)
00137 {
00138 _os << "initialized : yes" << std::endl;
00139 _os << "binary modules: " << bmodules_.size() << std::endl;
00140 for( ModuleListIterator m_it=bmodules_.begin(); m_it!=bmodules_.end(); ++m_it)
00141 {
00142 _os << " " << (*m_it)->name() << std::endl;
00143 }
00144 _os << "priority module: " << cmodule_->name().c_str() << std::endl;
00145 }
00146 else {
00147 _os << "initialized : no" << std::endl;
00148 _os << "available modules: " << all_modules_.size() << std::endl;
00149 for( ModuleListIterator m_it=all_modules_.begin(); m_it!=all_modules_.end(); ++m_it)
00150 {
00151 _os << " " << (*m_it)->name() << " : ";
00152 if((*m_it)->is_binary()) {
00153 _os << "binary";
00154 if((*m_it)->name() == "Quadric") {
00155 _os << " and priority (special treatment)";
00156 }
00157 } else {
00158 _os << "priority";
00159 }
00160 _os << std::endl;
00161 }
00162 }
00163 }
00164
00165
00166
00167
00168
00169 template <class Mesh>
00170 bool
00171 DecimaterT<Mesh>::
00172 initialize()
00173 {
00174 if(initialized_)
00175 {
00176 return true;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 Module *quadric=NULL;
00191 Module *pmodule=NULL;
00192 for (ModuleListIterator m_it=all_modules_.begin(), m_end=all_modules_.end(); m_it != m_end; ++m_it)
00193 {
00194 if ( (*m_it)->name() == "Quadric")
00195 quadric = *m_it;
00196
00197 if ( !(*m_it)->is_binary() )
00198 {
00199 if(pmodule)
00200 {
00201
00202 set_uninitialized();
00203 return false;
00204 }
00205 pmodule = *m_it;
00206 }
00207 }
00208
00209
00210 if(!pmodule && quadric) {
00211 pmodule = quadric;
00212 }
00213
00214 if(!pmodule) {
00215
00216 set_uninitialized();
00217 return false;
00218 }
00219
00220
00221 cmodule_ = pmodule;
00222
00223 for(ModuleListIterator m_it=all_modules_.begin(), m_end=all_modules_.end(); m_it != m_end; ++m_it)
00224 {
00225
00226 (*m_it)->initialize();
00227
00228 if(*m_it != pmodule) {
00229
00230 bmodules_.push_back(*m_it);
00231 }
00232 }
00233
00234 return initialized_ = true;
00235 }
00236
00237
00238
00239
00240 template <class Mesh>
00241 bool
00242 DecimaterT<Mesh>::is_collapse_legal(const CollapseInfo& _ci)
00243 {
00244
00245
00246
00247 if (mesh_.status(_ci.v0).locked() ||
00248 mesh_.status(_ci.v0).deleted())
00249 return false;
00250
00251
00252
00253
00254
00255
00256 if (_ci.vl.is_valid() && _ci.vr.is_valid() &&
00257 mesh_.find_halfedge(_ci.vl, _ci.vr).is_valid() &&
00258 mesh_.valence(_ci.vl) == 3 && mesh_.valence(_ci.vr) == 3)
00259 {
00260 return false;
00261 }
00262
00263
00264 if (mesh_.status(_ci.v0).feature() &&
00265 !mesh_.status(mesh_.edge_handle(_ci.v0v1)).feature())
00266 return false;
00267
00268
00269
00270
00271
00272 typename Mesh::VertexVertexIter vv_it;
00273
00274 for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it)
00275 mesh_.status(vv_it).set_tagged(false);
00276
00277 for (vv_it = mesh_.vv_iter(_ci.v1); vv_it; ++vv_it)
00278 mesh_.status(vv_it).set_tagged(true);
00279
00280 for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it)
00281 if (mesh_.status(vv_it).tagged() &&
00282 vv_it.handle() != _ci.vl &&
00283 vv_it.handle() != _ci.vr)
00284 return false;
00285
00286
00287 if (_ci.vl == _ci.vr) return false;
00288
00289
00290
00291 if (mesh_.is_boundary(_ci.v0))
00292 {
00293 if (!mesh_.is_boundary(_ci.v1))
00294 {
00295 return false;
00296 }
00297 else
00298 {
00299 if (!(mesh_.is_boundary(_ci.v0v1) || mesh_.is_boundary(_ci.v1v0)))
00300 return false;
00301 }
00302
00303 if (_ci.vl.is_valid() && _ci.vr.is_valid())
00304 return false;
00305 }
00306
00307
00308 if (_ci.vl.is_valid() &&
00309 mesh_.is_boundary(_ci.vlv1) &&
00310 mesh_.is_boundary(_ci.v0vl))
00311 return false;
00312
00313
00314 if (_ci.vr.is_valid() &&
00315 mesh_.is_boundary(_ci.vrv0) &&
00316 mesh_.is_boundary(_ci.v1vr))
00317 return false;
00318
00319
00320 if (mesh_.cw_rotated_halfedge_handle(
00321 mesh_.cw_rotated_halfedge_handle(_ci.v0v1)) == _ci.v0v1)
00322 return false;
00323
00324
00325
00326 return true;
00327 }
00328
00329
00330
00331
00332
00333 template <class Mesh>
00334 float
00335 DecimaterT<Mesh>::collapse_priority(const CollapseInfo& _ci)
00336 {
00337 typename ModuleList::iterator m_it, m_end = bmodules_.end();
00338
00339 for (m_it = bmodules_.begin(); m_it != m_end; ++m_it)
00340 {
00341 if ( (*m_it)->collapse_priority(_ci) < 0.0)
00342 return ModBaseT<DecimaterT<Mesh> >::ILLEGAL_COLLAPSE;
00343 }
00344 return cmodule_->collapse_priority(_ci);
00345 }
00346
00347
00348
00349
00350
00351 template <class Mesh>
00352 void
00353 DecimaterT<Mesh>::heap_vertex(VertexHandle _vh)
00354 {
00355
00356
00357 float prio, best_prio(FLT_MAX);
00358 typename Mesh::HalfedgeHandle heh, collapse_target;
00359
00360
00361
00362 typename Mesh::VertexOHalfedgeIter voh_it(mesh_, _vh);
00363 for (; voh_it; ++voh_it)
00364 {
00365 heh = voh_it.handle();
00366 CollapseInfo ci(mesh_, heh);
00367
00368 if (is_collapse_legal(ci))
00369 {
00370 prio = collapse_priority(ci);
00371 if (prio >= 0.0 && prio < best_prio)
00372 {
00373 best_prio = prio;
00374 collapse_target = heh;
00375 }
00376 }
00377 }
00378
00379
00380 if (collapse_target.is_valid())
00381 {
00382
00383 mesh_.property(collapse_target_, _vh) = collapse_target;
00384 mesh_.property(priority_, _vh) = best_prio;
00385
00386 if (heap_->is_stored(_vh)) heap_->update(_vh);
00387 else heap_->insert(_vh);
00388 }
00389
00390
00391 else
00392 {
00393
00394 if (heap_->is_stored(_vh)) heap_->remove(_vh);
00395
00396 mesh_.property(collapse_target_, _vh) = collapse_target;
00397 mesh_.property(priority_, _vh) = -1;
00398 }
00399 }
00400
00401
00402
00403
00404
00405 template <class Mesh>
00406 void
00407 DecimaterT<Mesh>::
00408 postprocess_collapse(CollapseInfo& _ci)
00409 {
00410 typename ModuleList::iterator m_it, m_end = bmodules_.end();
00411
00412 for (m_it = bmodules_.begin(); m_it != m_end; ++m_it)
00413 (*m_it)->postprocess_collapse(_ci);
00414
00415 cmodule_->postprocess_collapse(_ci);
00416 }
00417
00418
00419
00420
00421
00422 template <class Mesh>
00423 size_t
00424 DecimaterT<Mesh>::decimate( size_t _n_collapses )
00425 {
00426 if ( !is_initialized() )
00427 return 0;
00428
00429 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
00430 typename Mesh::VertexHandle vp;
00431 typename Mesh::HalfedgeHandle v0v1;
00432 typename Mesh::VertexVertexIter vv_it;
00433 typename Mesh::VertexFaceIter vf_it;
00434 unsigned int n_collapses(0);
00435
00436 typedef std::vector<typename Mesh::VertexHandle> Support;
00437 typedef typename Support::iterator SupportIterator;
00438
00439 Support support(15);
00440 SupportIterator s_it, s_end;
00441
00442
00443
00444 if (!_n_collapses) _n_collapses = mesh_.n_vertices();
00445
00446
00447
00448 HeapInterface HI(mesh_, priority_, heap_position_);
00449 heap_ = std::auto_ptr<DeciHeap>(new DeciHeap(HI));
00450 heap_->reserve(mesh_.n_vertices());
00451
00452
00453 for (v_it = mesh_.vertices_begin(); v_it != v_end; ++v_it)
00454 {
00455 heap_->reset_heap_position( v_it.handle() );
00456 if (!mesh_.status(v_it).deleted())
00457 heap_vertex( v_it.handle() );
00458 }
00459
00460
00461
00462 while ((!heap_->empty()) && (n_collapses < _n_collapses))
00463 {
00464
00465 vp = heap_->front();
00466 v0v1 = mesh_.property(collapse_target_, vp);
00467 heap_->pop_front();
00468
00469
00470
00471 CollapseInfo ci(mesh_, v0v1);
00472
00473
00474
00475 if (!is_collapse_legal(ci))
00476 continue;
00477
00478
00479
00480 vv_it = mesh_.vv_iter(ci.v0);
00481 support.clear();
00482 for (; vv_it; ++vv_it)
00483 support.push_back(vv_it.handle());
00484
00485
00486
00487 mesh_.collapse(v0v1);
00488 ++n_collapses;
00489
00490
00491
00492 vf_it = mesh_.vf_iter(ci.v1);
00493 for (; vf_it; ++vf_it)
00494 if (!mesh_.status(vf_it).deleted())
00495 mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle()));
00496
00497
00498
00499 postprocess_collapse(ci);
00500
00501
00502
00503 for (s_it = support.begin(), s_end = support.end();
00504 s_it != s_end; ++s_it)
00505 {
00506 assert(!mesh_.status(*s_it).deleted());
00507 heap_vertex(*s_it);
00508 }
00509 }
00510
00511
00512
00513 heap_.reset();
00514
00515
00516
00517 return n_collapses;
00518 }
00519
00520
00521
00522 }
00523 }
00524
00525