44 #include "RemesherPlugin.hh" 46 #include "Algorithms/AdaptiveRemesherT.hh" 47 #include "Algorithms/UniformRemesherT.hh" 57 RemesherPlugin::RemesherPlugin() :
60 if ( OpenFlipper::Options::gui() ) {
63 connect(progress_, SIGNAL(signalJobState(QString,
int)),
this, SIGNAL(setJobState(QString,
int)), Qt::QueuedConnection);
64 connect(progress_, SIGNAL(changeDescription(QString,QString)),
this, SIGNAL(setJobDescription(QString,QString)), Qt::QueuedConnection);
70 RemesherPlugin::~RemesherPlugin() {
71 if ( OpenFlipper::Options::gui() ) {
81 emit setSlotDescription(
"adaptiveRemeshing(int,double,double,double,uint,bool)",
"Adaptive Remeshing with vertex selection",
82 QString(
"object_id,error,min_edge_length,max_edge_length,iterations,use_projection").split(
","),
83 QString(
"id of an object,error,minimal target edge length,maximal target edge length,iterations,use projection method").split(
","));
84 emit setSlotDescription(
"adaptiveRemeshing(int,double,double,double,uint)",
"Adaptive Remeshing with vertex selection and projection method",
85 QString(
"object_id,error,min_edge_length,max_edge_length,iterations").split(
","),
86 QString(
"id of an object,error,minimal target edge length,maximal target edge length,iterations").split(
","));
88 emit setSlotDescription(
"adaptiveRemeshingFaceSelection(int,double,double,double,uint,bool)",
"Adaptive Remeshing with face selection",
89 QString(
"object_id,error,min_edge_length,max_edge_length,iterations,use_projection").split(
","),
90 QString(
"id of an object,error,minimal target edge length,maximal target edge length,iterations,use projection method").split(
","));
91 emit setSlotDescription(
"adaptiveRemeshingFaceSelection(int,double,double,double,uint)",
"Adaptive Remeshing with face selection and projection method",
92 QString(
"object_id,error,min_edge_length,max_edge_length,iterations").split(
","),
93 QString(
"id of an object,error,minimal target edge length,maximal target edge length,iterations").split(
","));
96 emit setSlotDescription(
"uniformRemeshing(int,double,uint,uint,bool)",
"Uniform Remeshing with vertex selection",
97 QString(
"object_id,edge_length,iterations,area_iterations,use_projection").split(
","),
98 QString(
"id of an object,target edge length,iterations,area iterations,use projection method").split(
","));
99 emit setSlotDescription(
"uniformRemeshing(int,double,uint,uint)",
"Uniform Remeshing with vertex selection and projection method",
100 QString(
"object_id,edge_length,iterations,area_iterations").split(
","),
101 QString(
"id of an object,target edge length,iterations,area iterations").split(
","));
103 emit setSlotDescription(
"uniformRemeshingFaceSelection(int,double,uint,uint,bool)",
"Uniform Remeshing with face selection",
104 QString(
"object_id,edge_length,iterations,area_iterations,use_projection").split(
","),
105 QString(
"id of an object,target edge length,iterations,area iterations,use projection method").split(
","));
106 emit setSlotDescription(
"uniformRemeshingFaceSelection(int,double,uint,uint)",
"Uniform Remeshing with face selection and projection method",
107 QString(
"object_id,edge_length,iterations,area_iterations").split(
","),
108 QString(
"id of an object,target edge length,iterations,area iterations").split(
","));
116 if ( OpenFlipper::Options::gui() ) {
120 connect(tool_->adaptive_button, SIGNAL(clicked()),
this, SLOT(adaptiveRemeshingButtonClicked()) );
122 connect(tool_->uniform_button, SIGNAL(clicked()),
this, SLOT(uniformRemeshingButtonClicked()) );
124 connect(tool_->adaptive_initial_values, SIGNAL(clicked()),
this, SLOT(computeInitValues()));
125 connect(tool_->uniform_initial_values, SIGNAL(clicked()),
this, SLOT(computeInitValues()));
127 tool_->tabWidget->setCurrentIndex(0);
129 toolIcon_ =
new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"remesher.png");
130 emit addToolbox( tr(
"Remesher") , tool_ , toolIcon_);
133 connect(
this, SIGNAL( finishJob(QString)),
this, SLOT(threadFinished(QString)), Qt::QueuedConnection);
138 void RemesherPlugin::threadFinished(QString _jobId) {
143 if ( operation_ == REMESH_ADAPTIVE ) {
146 }
else if ( operation_ == REMESH_UNIFORM ) {
153 progress_->detachJob();
160 if(OpenFlipper::Options::nogui())
return;
162 double mean_edge = 0.0;
163 double max_feature_angle = 0.0;
176 for(TriMesh::EdgeIter e_it = mesh->edges_begin(); e_it != mesh->edges_end(); ++e_it) {
178 TriMesh::HalfedgeHandle he = mesh->halfedge_handle(*e_it, 0);
180 ACG::Vec3d vec_e = mesh->point(mesh->to_vertex_handle(he)) - mesh->point(mesh->from_vertex_handle(he));
182 mean_edge += vec_e.
length();
185 TriMesh::FaceHandle fh1 = mesh->face_handle(he);
186 TriMesh::FaceHandle fh2 = mesh->face_handle(mesh->opposite_halfedge_handle(he));
189 if ( !fh1.is_valid() || !fh2.is_valid() )
195 double feature_angle = (1.0 - (n1 | n2));
197 if(feature_angle > max_feature_angle) max_feature_angle = feature_angle;
200 mean_edge /= (double)mesh->n_edges();
210 for(PolyMesh::EdgeIter e_it = mesh->edges_begin(); e_it != mesh->edges_end(); ++e_it) {
212 PolyMesh::HalfedgeHandle he = mesh->halfedge_handle(*e_it, 0);
214 ACG::Vec3d vec_e = mesh->point(mesh->to_vertex_handle(he)) - mesh->point(mesh->from_vertex_handle(he));
216 mean_edge += vec_e.
length();
219 PolyMesh::FaceHandle fh1 = mesh->face_handle(he);
220 PolyMesh::FaceHandle fh2 = mesh->face_handle(mesh->opposite_halfedge_handle(he));
223 if ( !fh1.is_valid() || !fh2.is_valid() )
229 double feature_angle = (1.0 - (n1 | n2));
231 if(feature_angle > max_feature_angle) max_feature_angle = feature_angle;
234 mean_edge /= (double)mesh->n_edges();
238 max_feature_angle = max_feature_angle * (M_PI / 2.0);
241 tool_->adaptive_error->setValue(mean_edge * 0.1);
242 tool_->adaptive_min_edge->setValue(mean_edge - (mean_edge * 0.1));
243 tool_->adaptive_max_edge->setValue(mean_edge + (mean_edge * 0.1));
246 tool_->uniform_edge_length->setValue(mean_edge);
254 void RemesherPlugin::adaptiveRemeshingButtonClicked() {
256 QString jobId = name() +
"AdaptiveRemeshing";
259 connect(thread, SIGNAL( finished(QString)),
this, SIGNAL(finishJob(QString)));
260 connect(thread, SIGNAL(
function() ),
this, SLOT(adaptiveRemeshing()),Qt::DirectConnection);
263 emit startJob( jobId,
"Adaptive remeshing" , 0 , 100 ,
true);
266 progress_->attachJob(jobId);
275 void RemesherPlugin::adaptiveRemeshing() {
277 if(OpenFlipper::Options::nogui())
return;
290 double error = tool_->adaptive_error->value();
291 double min_edge = tool_->adaptive_min_edge->value();
292 double max_edge = tool_->adaptive_max_edge->value();
293 unsigned int iters = tool_->adaptive_iters->text().toInt();
294 bool projection = tool_->adaptive_projection->isChecked();
295 bool vertexSelection = (tool_->adaptive_selection->currentIndex() == 0);
297 slotAdaptiveRemeshing(o_it->id(), error, min_edge, max_edge, iters, projection,vertexSelection);
304 void RemesherPlugin::slotAdaptiveRemeshing(
int _objectID,
306 double _min_edge_length,
307 double _max_edge_length,
309 bool _use_projection,
310 bool _vertex_selection) {
312 operation_ = REMESH_ADAPTIVE;
327 remesher.remesh(_error, _min_edge_length, _max_edge_length, _iters, _use_projection, selection);
332 QString projectionString =
"\"FALSE\"";
334 projectionString =
"\"TRUE\"";
336 emit scriptInfo(
"adaptiveRemeshing(" + QString::number(_objectID) +
", " 337 + QString::number(_error) +
", " 338 + QString::number(_min_edge_length) +
", " 339 + QString::number(_max_edge_length) +
", " 340 + QString::number(_iters) +
", " 341 + projectionString +
")");
350 void RemesherPlugin::uniformRemeshingButtonClicked() {
354 connect(thread, SIGNAL( state(QString,
int)),
this, SIGNAL(setJobState(QString,
int)));
355 connect(thread, SIGNAL( finished(QString)),
this, SIGNAL(finishJob(QString)));
356 connect(thread, SIGNAL(
function() ),
this, SLOT(uniformRemeshing()),Qt::DirectConnection);
358 emit startJob( name() +
"UniformRemeshing",
"Uniform remeshing" , 0 , 100 ,
true);
367 void RemesherPlugin::uniformRemeshing(){
369 if(OpenFlipper::Options::nogui())
return;
372 double edge_length = tool_->uniform_edge_length->value();
373 unsigned int iters = tool_->uniform_iters->text().toInt();
374 unsigned int area_iters = tool_->uniform_area_iters->text().toInt();
375 bool projection = tool_->uniform_projection->isChecked();
376 bool vertex_selection = (tool_->uniform_selection->currentIndex() == 0);
385 for(TriMesh::EdgeIter e_it = mesh->edges_begin(); e_it != mesh->edges_end(); ++e_it) {
386 if(mesh->status(*e_it).feature()) {
387 mesh->status(mesh->to_vertex_handle(mesh->halfedge_handle(*e_it, 0))).set_feature(
true);
388 mesh->status(mesh->from_vertex_handle(mesh->halfedge_handle(*e_it, 0))).set_feature(
true);
398 slotUniformRemeshing(o_it->id(), edge_length, iters, area_iters, projection,vertex_selection);
404 void RemesherPlugin::slotUniformRemeshing(
int _objectID,
407 unsigned int _area_iters,
408 bool _use_projection,
409 bool _vertex_selection) {
411 operation_ = REMESH_UNIFORM;
426 remesher.remesh(_edge_length, _iters, _area_iters, _use_projection, selection);
430 QString projectionString =
"\"FALSE\"";
432 projectionString =
"\"TRUE\"";
434 emit scriptInfo(
"uniformRemeshing(" + QString::number(_objectID) +
", " 435 + QString::number(_edge_length) +
", " 436 + QString::number(_iters) +
", " 437 + QString::number(_area_iters) +
", " 438 + QString::number(_iters) +
", " 439 + projectionString +
")");
449 void RemesherPlugin::adaptiveRemeshing(
int _objectID,
451 double _min_edge_length,
452 double _max_edge_length,
454 bool _use_projection) {
456 slotAdaptiveRemeshing(_objectID,_error,_min_edge_length,_max_edge_length,_iters,_use_projection);
464 void RemesherPlugin::uniformRemeshing(
int _objectID,
467 unsigned int _area_iters,
468 bool _use_projection) {
470 slotUniformRemeshing(_objectID,_edge_length,_iters,_area_iters,_use_projection);
478 void RemesherPlugin::adaptiveRemeshingFaceSelection(
int _objectID,
480 double _min_edge_length,
481 double _max_edge_length,
483 bool _use_projection) {
485 slotAdaptiveRemeshing(_objectID,_error,_min_edge_length,_max_edge_length,_iters,_use_projection,
false);
493 void RemesherPlugin::uniformRemeshingFaceSelection(
int _objectID,
496 unsigned int _area_iters,
497 bool _use_projection) {
499 slotUniformRemeshing(_objectID,_edge_length,_iters,_area_iters,_use_projection,
false);
bool dataType(DataType _type) const
const QStringList TARGET_OBJECTS("target")
Iterable object range.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
void computeInitValues()
Compute mean edge length and set values.
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Kernel::Normal Normal
Normal type.
void initializePlugin()
init the Toolbox
auto length() const -> decltype(std::declval< VectorT< S, DIM >>().norm())
compute squared euclidean norm
void startProcessing()
start processing
void pluginsInitialized()
Initialize the plugin.
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
void update_face_normals()
Update normal vectors for all faces.
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(1)<< 3)
Topology updated.
Thread handling class for OpenFlipper.
#define DATA_TRIANGLE_MESH
void update_normals()
Compute normals for all primitives.