diff --git a/Algorithms/AdaptiveRemesherT.cc b/Algorithms/AdaptiveRemesherT.cc index 461fdd1b36213c246a08959174bbf440913d8e54..73e70e5c295a2bbb3519c90c10a910108d12bca7 100644 --- a/Algorithms/AdaptiveRemesherT.cc +++ b/Algorithms/AdaptiveRemesherT.cc @@ -166,7 +166,8 @@ remesh(Scalar _error, Scalar _emin, Scalar _emax, unsigned int _iters, - bool _use_projection) + bool _use_projection, + Selection _selection) { // set thesholds error_ = _error; @@ -174,7 +175,7 @@ remesh(Scalar _error, emax_ = _emax; // do it - Base::remesh(_iters, 0, _use_projection); + Base::remesh(_iters, 0, _use_projection, _selection); // free curvature property (refmesh has been deleted already) Base::mesh_.remove_property(curvature_); diff --git a/Algorithms/AdaptiveRemesherT.hh b/Algorithms/AdaptiveRemesherT.hh index d42be0b7b5eeb8652343f561f451a7e6b653cf7c..ad0011eb862f35067b8da36cf946f95475265f41 100644 --- a/Algorithms/AdaptiveRemesherT.hh +++ b/Algorithms/AdaptiveRemesherT.hh @@ -70,6 +70,7 @@ namespace Remeshing { template class AdaptiveRemesherT : public BaseRemesherT { + typedef typename BaseRemesherT::Selection Selection; public: typedef BaseRemesherT Base; @@ -85,7 +86,8 @@ public: Scalar _min_edge_length, Scalar _max_edge_length, unsigned int _iters, - bool _use_projection = true); + bool _use_projection = true, + Selection _selection=BaseRemesherT::SELECT_VERTEX); diff --git a/Algorithms/BaseRemesherT.cc b/Algorithms/BaseRemesherT.cc index 777692a51c050806fb8f61ce07faab36c72343d3..a8daad19bd998e906cffd480fc7442b821b1cfda 100644 --- a/Algorithms/BaseRemesherT.cc +++ b/Algorithms/BaseRemesherT.cc @@ -231,11 +231,15 @@ void BaseRemesherT:: remesh(unsigned int _iters, unsigned int _area_iters, - bool _use_projection) { + bool _use_projection, + Selection _selection) { try { - prepare(); + if (_selection == VERTEX_SELECTION) + prepare_vertex_selection(); + else if (_selection == FACE_SELECTION) + prepare_face_selection(); remeshh(_iters, _area_iters, _use_projection); } catch (std::bad_alloc&) @@ -247,14 +251,12 @@ remesh(unsigned int _iters, cleanup(); } - //----------------------------------------------------------------------------- - template void BaseRemesherT:: -prepare() +prepare_vertex_selection() { typename Mesh::EIter e_it, e_end; typename Mesh::VIter v_it, v_end; @@ -281,7 +283,7 @@ prepare() if (nothing_selected_) for (v_it=mesh_.vertices_begin(), v_end=mesh_.vertices_end(); - v_it!=v_end; ++v_it) + v_it!=v_end; ++v_it) mesh_.status(*v_it).set_selected(true); @@ -297,11 +299,115 @@ prepare() v0 = mesh_.to_vertex_handle(mesh_.halfedge_handle(*e_it, 0)); v1 = mesh_.to_vertex_handle(mesh_.halfedge_handle(*e_it, 1)); mesh_.status(*e_it).set_locked(mesh_.status(v0).locked() || - mesh_.status(v1).locked()); + mesh_.status(v1).locked()); + } + + + + // handle feature corners: + // lock corner vertices (>2 feature edges) and endpoints + // of feature lines (1 feature edge) + for (v_it=mesh_.vertices_begin(), v_end=mesh_.vertices_end(); + v_it!=v_end; ++v_it) + { + if (mesh_.status(*v_it).feature()) + { + int c=0; + for (vh_it=mesh_.cvoh_iter(*v_it); vh_it.is_valid(); ++vh_it) + if (mesh_.status(mesh_.edge_handle(*vh_it)).feature()) + ++c; + if (c!=2) mesh_.status(*v_it).set_locked(true); + } } + // build reference mesh + init_reference(); +// if (emit_progress_) Progress().step(5); + + + // add properties + mesh_.add_property(valences_); + mesh_.add_property(update_); + mesh_.add_property(area_); +} + +//----------------------------------------------------------------------------- + + +template +void +BaseRemesherT:: +prepare_face_selection() +{ + typename Mesh::EIter e_it, e_end; + typename Mesh::VIter v_it, v_end; + typename Mesh::FIter f_it, f_end; + typename Mesh::CFVIter fv_it; + typename Mesh::CVOHIter vh_it; + typename Mesh::VHandle v0, v1; + typename Mesh::FHandle f0, f1; + + + // need vertex and edge status + mesh_.request_vertex_status(); + mesh_.request_edge_status(); + mesh_.request_face_status(); + + // if nothing selected -> select all + nothing_selected_ = true; + for (f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); f_it != f_end; + ++f_it) + { + if (mesh_.status(*f_it).selected()) + { + nothing_selected_ = false; + break; + } + } + + if (nothing_selected_) + MeshSelection::selectAllFaces(&mesh_); + + + + // lock un-selected vertices & edges + for (v_it = mesh_.vertices_begin(), v_end = mesh_.vertices_end(); + v_it != v_end; ++v_it) + { + bool all_faces_selected = true; + + for (typename Mesh::ConstVertexFaceIter vf_it = mesh_.cvf_iter(*v_it); + vf_it.is_valid(); ++vf_it) + { + if (!mesh_.status(*vf_it).selected()) + { + all_faces_selected = false; + break; + } + } + mesh_.status(*v_it).set_locked(!all_faces_selected); + } + + for (e_it = mesh_.edges_begin(), e_end = mesh_.edges_end(); + e_it != e_end; ++e_it) + { + if (mesh_.is_boundary(*e_it)) + { + mesh_.status(*e_it).set_locked(true); + } + else + { + f0 = mesh_.face_handle(mesh_.halfedge_handle(*e_it, 0)); + f1 = mesh_.face_handle(mesh_.halfedge_handle(*e_it, 1)); + + mesh_.status(*e_it).set_locked(!(mesh_.status(f0).selected() && mesh_.status(f1).selected())); + } + } + + MeshSelection::clearFaceSelection(&mesh_); + // handle feature corners: // lock corner vertices (>2 feature edges) and endpoints // of feature lines (1 feature edge) diff --git a/Algorithms/BaseRemesherT.hh b/Algorithms/BaseRemesherT.hh index 77dfe7f92972f883e58cd57dac98fcbaf856bd7e..ff7eb5a16c74db586d66bc39c3677c5975daf8b5 100644 --- a/Algorithms/BaseRemesherT.hh +++ b/Algorithms/BaseRemesherT.hh @@ -50,6 +50,12 @@ #ifndef BASE_REMESHERT_HH #define BASE_REMESHERT_HH +/** + * BaseRemesher implements a modified version of a remesher approach presented by Mario Botsch and Leif Kobbelt in + * "A Remeshing Approach to Multiresolution Modeling" published at Symposium on Geometry Processing 2004 p. 189-196 + * Paper can found at: http://www.graphics.rwth-aachen.de/publications/0000/37/ + */ + //== INCLUDES ================================================================= @@ -74,6 +80,12 @@ class BaseRemesherT { public: + enum Selection + { + VERTEX_SELECTION, + FACE_SELECTION + }; + typedef typename Mesh::Scalar Scalar; typedef typename Mesh::Point Point; typedef typename Mesh::EdgeHandle EdgeHandle; @@ -85,13 +97,17 @@ public: void remesh(unsigned int _iters, unsigned int _area_iters, - bool _use_projection = true); + bool _use_projection = true, + Selection _selection=VERTEX_SELECTION); protected: - void prepare(); + /// prepare for remeshing only selected vertices (if no vertex was selected, remesh whole mesh) + void prepare_vertex_selection(); + /// prepare for remeshing only vertices which are fully surrounded by selected faces (if no face was selected, remesh whole mesh) + void prepare_face_selection(); void remeshh(unsigned int _iters, unsigned int _aiters, bool _proj); void cleanup(); diff --git a/Algorithms/UniformRemesherT.hh b/Algorithms/UniformRemesherT.hh index e62785d7a696b277e00c3f14d21f03b3922027bc..428d26929ca8dfe310c525d44f6c07397d862f9f 100644 --- a/Algorithms/UniformRemesherT.hh +++ b/Algorithms/UniformRemesherT.hh @@ -67,6 +67,7 @@ namespace Remeshing { template class UniformRemesherT : public BaseRemesherT { + typedef typename BaseRemesherT::Selection Selection; public: typedef BaseRemesherT Base; @@ -82,13 +83,14 @@ public: void remesh(Scalar _edge_length, unsigned int _iters, unsigned int _area_iters, - bool _use_projection = true) + bool _use_projection = true, + Selection _selection = BaseRemesherT::VERTEX_SELECTION) { // emin_ = 4.0/5.0 * _edge_length; sqr_emin_ = emin_ * emin_; // emax_ = 4.0/3.0 * _edge_length; sqr_emax_ = emax_ * emax_; emin_ = 0.7 * _edge_length; sqr_emin_ = emin_ * emin_; emax_ = 1.4 * _edge_length; sqr_emax_ = emax_ * emax_; - Base::remesh(_iters, _area_iters, _use_projection); + Base::remesh(_iters, _area_iters, _use_projection,_selection); } diff --git a/RemesherPlugin.cc b/RemesherPlugin.cc index b52aff3aeb4add5c7161c8fc2ee9c83beb0e8a33..44e4065b98d79eddcfbea46b7bee208123afa311 100644 --- a/RemesherPlugin.cc +++ b/RemesherPlugin.cc @@ -79,12 +79,34 @@ RemesherPlugin::~RemesherPlugin() { /// Initialize the plugin void RemesherPlugin::pluginsInitialized(){ - emit setSlotDescription("adaptiveRemeshing(int,double,double,double,int,bool)", "Adaptive Remeshing", + emit setSlotDescription("adaptiveRemeshing(int,double,double,double,uint,bool)", "Adaptive Remeshing with vertex selection", QString("object_id,error,min_edge_length,max_edge_length,iterations,use_projection").split(","), QString("id of an object,error,minimal target edge length,maximal target edge length,iterations,use projection method").split(",")); - emit setSlotDescription("uniformRemeshing(int,double,unsigned int,unsigned int,bool)", "Uniform Remeshing", + emit setSlotDescription("adaptiveRemeshing(int,double,double,double,uint)", "Adaptive Remeshing with vertex selection and projection method", + QString("object_id,error,min_edge_length,max_edge_length,iterations").split(","), + QString("id of an object,error,minimal target edge length,maximal target edge length,iterations").split(",")); + + emit setSlotDescription("adaptiveRemeshingFaceSelection(int,double,double,double,uint,bool)", "Adaptive Remeshing with face selection", + QString("object_id,error,min_edge_length,max_edge_length,iterations,use_projection").split(","), + QString("id of an object,error,minimal target edge length,maximal target edge length,iterations,use projection method").split(",")); + emit setSlotDescription("adaptiveRemeshingFaceSelection(int,double,double,double,uint)", "Adaptive Remeshing with face selection and projection method", + QString("object_id,error,min_edge_length,max_edge_length,iterations").split(","), + QString("id of an object,error,minimal target edge length,maximal target edge length,iterations").split(",")); + + + emit setSlotDescription("uniformRemeshing(int,double,uint,uint,bool)", "Uniform Remeshing with vertex selection", QString("object_id,edge_length,iterations,area_iterations,use_projection").split(","), QString("id of an object,target edge length,iterations,area iterations,use projection method").split(",")); + emit setSlotDescription("uniformRemeshing(int,double,uint,uint)", "Uniform Remeshing with vertex selection and projection method", + QString("object_id,edge_length,iterations,area_iterations").split(","), + QString("id of an object,target edge length,iterations,area iterations").split(",")); + + emit setSlotDescription("uniformRemeshingFaceSelection(int,double,uint,uint,bool)", "Uniform Remeshing with face selection", + QString("object_id,edge_length,iterations,area_iterations,use_projection").split(","), + QString("id of an object,target edge length,iterations,area iterations,use projection method").split(",")); + emit setSlotDescription("uniformRemeshingFaceSelection(int,double,uint,uint)", "Uniform Remeshing with face selection and projection method", + QString("object_id,edge_length,iterations,area_iterations").split(","), + QString("id of an object,target edge length,iterations,area iterations").split(",")); } // ---------------------------------------------------------------------------------------- @@ -271,8 +293,9 @@ void RemesherPlugin::adaptiveRemeshing() { double max_edge = tool_->adaptive_max_edge->value(); unsigned int iters = tool_->adaptive_iters->text().toInt(); bool projection = tool_->adaptive_projection->isChecked(); + bool vertexSelection = (tool_->adaptive_selection->currentIndex() == 0); - slotAdaptiveRemeshing(o_it->id(), error, min_edge, max_edge, iters, projection); + slotAdaptiveRemeshing(o_it->id(), error, min_edge, max_edge, iters, projection,vertexSelection); } } @@ -284,7 +307,8 @@ void RemesherPlugin::slotAdaptiveRemeshing(int _objectID, double _min_edge_length, double _max_edge_length, unsigned int _iters, - bool _use_projection) { + bool _use_projection, + bool _vertex_selection) { operation_ = REMESH_ADAPTIVE; @@ -299,7 +323,9 @@ void RemesherPlugin::slotAdaptiveRemeshing(int _objectID, Remeshing::AdaptiveRemesherT remesher(*mesh, progress_); - remesher.remesh(_error, _min_edge_length, _max_edge_length, _iters, _use_projection); + Remeshing::BaseRemesherT::Selection selection = (_vertex_selection) ? Remeshing::BaseRemesherT::VERTEX_SELECTION : Remeshing::BaseRemesherT::FACE_SELECTION; + + remesher.remesh(_error, _min_edge_length, _max_edge_length, _iters, _use_projection, selection); mesh->update_normals(); @@ -348,6 +374,7 @@ void RemesherPlugin::uniformRemeshing(){ unsigned int iters = tool_->uniform_iters->text().toInt(); unsigned int area_iters = tool_->uniform_area_iters->text().toInt(); bool projection = tool_->uniform_projection->isChecked(); + bool vertex_selection = (tool_->uniform_selection->currentIndex() == 0); //read one target objects for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DataType(DATA_TRIANGLE_MESH)) ; @@ -369,7 +396,7 @@ void RemesherPlugin::uniformRemeshing(){ // on edge flips which are only defined // for triangle configurations. - slotUniformRemeshing(o_it->id(), edge_length, iters, area_iters, projection); + slotUniformRemeshing(o_it->id(), edge_length, iters, area_iters, projection,vertex_selection); } } @@ -379,7 +406,8 @@ void RemesherPlugin::slotUniformRemeshing(int _objectID, double _edge_length, unsigned int _iters, unsigned int _area_iters, - bool _use_projection) { + bool _use_projection, + bool _vertex_selection) { operation_ = REMESH_UNIFORM; @@ -394,7 +422,9 @@ void RemesherPlugin::slotUniformRemeshing(int _objectID, Remeshing::UniformRemesherT remesher(*mesh, progress_); - remesher.remesh(_edge_length, _iters, _area_iters, _use_projection); + Remeshing::BaseRemesherT::Selection selection = (_vertex_selection) ? Remeshing::BaseRemesherT::VERTEX_SELECTION : Remeshing::BaseRemesherT::FACE_SELECTION; + + remesher.remesh(_edge_length, _iters, _area_iters, _use_projection, selection); mesh->update_normals(); @@ -446,6 +476,35 @@ void RemesherPlugin::uniformRemeshing(int _objectID, // ---------------------------------------------------------------------------------------- +void RemesherPlugin::adaptiveRemeshingFaceSelection(int _objectID, + double _error, + double _min_edge_length, + double _max_edge_length, + unsigned int _iters, + bool _use_projection) { + + slotAdaptiveRemeshing(_objectID,_error,_min_edge_length,_max_edge_length,_iters,_use_projection,false); + emit updatedObject(_objectID, UPDATE_TOPOLOGY ); + emit createBackup(_objectID, "Adaptive remeshing", UPDATE_TOPOLOGY); + +} + +// ---------------------------------------------------------------------------------------- + +void RemesherPlugin::uniformRemeshingFaceSelection(int _objectID, + double _edge_length, + unsigned int _iters, + unsigned int _area_iters, + bool _use_projection) { + + slotUniformRemeshing(_objectID,_edge_length,_iters,_area_iters,_use_projection,false); + emit updatedObject(_objectID, UPDATE_TOPOLOGY ); + emit createBackup(_objectID, "Uniform remeshing", UPDATE_TOPOLOGY); + +} + +// ---------------------------------------------------------------------------------------- + #if QT_VERSION < 0x050000 Q_EXPORT_PLUGIN2( remesherplugin, RemesherPlugin ); #endif diff --git a/RemesherPlugin.hh b/RemesherPlugin.hh index fa2e25968a418c2317b87c6008a73c6ad940c895..684e03a721a5e867a50cf8a867b228f5803272ce 100644 --- a/RemesherPlugin.hh +++ b/RemesherPlugin.hh @@ -85,7 +85,7 @@ signals: void updatedObject(int _id, const UpdateType& _type); void setSlotDescription(QString _slotName, QString _slotDescription, - QStringList _parameters, QStringList _descriptions); + QStringList _parameters, QStringList _descriptions); //LoggingInterface: void log( Logtype _type, QString _message ); @@ -166,13 +166,15 @@ private slots: double _min_edge_length, double _max_edge_length, unsigned int _iters, - bool _use_projection = true); + bool _use_projection = true, + bool _vertex_selection = true); void slotUniformRemeshing(int _objectId, double _edge_length, unsigned int _iters, unsigned int _area_iters, - bool _use_projection = true); + bool _use_projection = true, + bool _vertex_selection = true); //scripting functions @@ -185,12 +187,25 @@ public slots: unsigned int _iters, bool _use_projection = true); + void adaptiveRemeshingFaceSelection(int _objectId, + double _error, + double _min_edge_length, + double _max_edge_length, + unsigned int _iters, + bool _use_projection = true); + void uniformRemeshing(int _objectId, double _edge_length, unsigned int _iters, unsigned int _area_iters, bool _use_projection = true); + void uniformRemeshingFaceSelection(int _objectId, + double _edge_length, + unsigned int _iters, + unsigned int _area_iters, + bool _use_projection = true); + public slots: QString version() { return QString("1.0"); }; }; diff --git a/toolbox.ui b/toolbox.ui index 33eaa07995a688f3490fe59ea4cc7003d746e3a0..3d258b5e54a4bad4658d83b62ace4dadcf30b0d4 100644 --- a/toolbox.ui +++ b/toolbox.ui @@ -22,6 +22,15 @@ true + + <html><head/><body><p>Give the selection mode which will be used.</p><p>If nothing of the specified is selected, the whole mesh will be remeshed.</p><p><span style=" font-weight:600;">Vertex Selection: </span>Remesh all selected vertices.</p><p><span style=" font-weight:600;">Face Selection: </span>Remesh all vertices surrounded by the selected face.</p></body></html> + + + Give the selection mode which will be used. If nothing of the specified is selected, the whole mesh will be remeshed. Vertex Selection: Remesh all selected vertices. Face Selection: Remesh all vertices surrounded by the selected face. + + + <html><head/><body><p>Give the selection mode which will be used.</p><p>If nothing of the specified is selected, the whole mesh will be remeshed.</p><p><span style=" font-weight:600;">Vertex Selection: </span>Remesh all selected vertices.</p><p><span style=" font-weight:600;">Face Selection: </span>Remesh all vertices surrounded by the selected face.</p></body></html> + 1 @@ -75,13 +84,13 @@ - Start remeshing + <html><head/><body><p><span style=" font-weight:600;">Start remeshing</span></p><p>Remesher based on an approach presented by Mario Botsch and Leif Kobbelt in &quot;<span style=" font-weight:600;">A Remeshing Approach to Multiresolution Modeling</span>&quot; published at Symposium on Geometry Processing 2004 on page 189-196.</p></body></html> - Start remeshing + Start remeshing Remesher based on an approach presented by Mario Botsch and Leif Kobbelt in "A Remeshing Approach to Multiresolution Modeling" published at Symposium on Geometry Processing 2004 on page 189-196. - Start remeshing + <html><head/><body><p><span style=" font-weight:600;">Start remeshing</span></p><p>Remesher based on an approach presented by Mario Botsch and Leif Kobbelt in &quot;<span style=" font-weight:600;">A Remeshing Approach to Multiresolution Modeling</span>&quot; published at Symposium on Geometry Processing 2004 on page 189-196.</p></body></html> Remesh @@ -241,6 +250,32 @@ + + + + <html><head/><body><p>Give the selection mode which will be used.</p><p>If nothing of the specified is selected, the whole mesh will be remeshed.</p><p><span style=" font-weight:600;">Vertex Selection: </span>Remesh all selected vertices.</p><p><span style=" font-weight:600;">Face Selection: </span>Remesh all vertices which are fully surrounded by selected faces.</p></body></html> + + + Give the selection mode which will be used. If nothing of the specified is selected, the whole mesh will be remeshed. Vertex Selection: Remesh all selected vertices. Face Selection: Remesh all vertices which are fully surrounded by selected faces. + + + <html><head/><body><p>Give the selection mode which will be used.</p><p>If nothing of the specified is selected, the whole mesh will be remeshed.</p><p><span style=" font-weight:600;">Vertex Selection: </span>Remesh all selected vertices.</p><p><span style=" font-weight:600;">Face Selection: </span>Remesh all vertices which are fully surrounded by selected faces.</p></body></html> + + + 0 + + + + Vertex Selection + + + + + Face Selection + + + + @@ -285,13 +320,13 @@ - Start remeshing + <html><head/><body><p><span style=" font-weight:600;">Start remeshing</span></p><p>Remesher based on an approach presented by Mario Botsch and Leif Kobbelt in &quot;<span style=" font-weight:600;">A Remeshing Approach to Multiresolution Modeling</span>&quot; published at Symposium on Geometry Processing 2004 on page 189-196.</p></body></html> - Start remeshing + Start remeshing Remesher based on an approach presented by Mario Botsch and Leif Kobbelt in "A Remeshing Approach to Multiresolution Modeling" published at Symposium on Geometry Processing 2004 on page 189-196. - Start remeshing + <html><head/><body><p><span style=" font-weight:600;">Start remeshing</span></p><p>Remesher based on an approach presented by Mario Botsch and Leif Kobbelt in &quot;<span style=" font-weight:600;">A Remeshing Approach to Multiresolution Modeling</span>&quot; published at Symposium on Geometry Processing 2004 on page 189-196.</p></body></html> Remesh @@ -417,6 +452,29 @@ + + + + <html><head/><body><p>Give the selection mode which will be used.</p><p>If nothing of the specified is selected, the whole mesh will be remeshed.</p><p><span style=" font-weight:600;">Vertex Selection: </span>Remesh all selected vertices.</p><p><span style=" font-weight:600;">Face Selection: </span>Remesh all vertices which are fully surrounded by selected faces.</p></body></html> + + + Give the selection mode which will be used. If nothing of the specified is selected, the whole mesh will be remeshed. Vertex Selection: Remesh all selected vertices. Face Selection: Remesh all vertices which are fully surrounded by selected faces. + + + <html><head/><body><p>Give the selection mode which will be used.</p><p>If nothing of the specified is selected, the whole mesh will be remeshed.</p><p><span style=" font-weight:600;">Vertex Selection: </span>Remesh all selected vertices.</p><p><span style=" font-weight:600;">Face Selection: </span>Remesh all vertices which are fully surrounded by selected faces.</p></body></html> + + + + Vertex Selection + + + + + Face Selection + + + +