44#include "RemesherPlugin.hh"
46#include "Algorithms/AdaptiveRemesherT.hh"
47#include "Algorithms/UniformRemesherT.hh"
57RemesherPlugin::RemesherPlugin() :
61 if ( OpenFlipper::Options::gui() ) {
64 connect(progress_, SIGNAL(signalJobState(QString,
int)),
this, SIGNAL(setJobState(QString,
int)), Qt::QueuedConnection);
65 connect(progress_, SIGNAL(changeDescription(QString,QString)),
this, SIGNAL(setJobDescription(QString,QString)), Qt::QueuedConnection);
71RemesherPlugin::~RemesherPlugin() {
72 if ( OpenFlipper::Options::gui() ) {
83 emit setSlotDescription(
"adaptiveRemeshing(int,double,double,double,uint,bool)",
"Adaptive Remeshing with vertex selection",
84 QString(
"object_id,error,min_edge_length,max_edge_length,iterations,use_projection").split(
","),
85 QString(
"id of an object,error,minimal target edge length,maximal target edge length,iterations,use projection method").split(
","));
86 emit setSlotDescription(
"adaptiveRemeshing(int,double,double,double,uint)",
"Adaptive Remeshing with vertex selection and projection method",
87 QString(
"object_id,error,min_edge_length,max_edge_length,iterations").split(
","),
88 QString(
"id of an object,error,minimal target edge length,maximal target edge length,iterations").split(
","));
90 emit setSlotDescription(
"adaptiveRemeshingFaceSelection(int,double,double,double,uint,bool)",
"Adaptive Remeshing with face selection",
91 QString(
"object_id,error,min_edge_length,max_edge_length,iterations,use_projection").split(
","),
92 QString(
"id of an object,error,minimal target edge length,maximal target edge length,iterations,use projection method").split(
","));
93 emit setSlotDescription(
"adaptiveRemeshingFaceSelection(int,double,double,double,uint)",
"Adaptive Remeshing with face selection and projection method",
94 QString(
"object_id,error,min_edge_length,max_edge_length,iterations").split(
","),
95 QString(
"id of an object,error,minimal target edge length,maximal target edge length,iterations").split(
","));
98 emit setSlotDescription(
"uniformRemeshing(int,double,uint,uint,bool)",
"Uniform Remeshing with vertex selection",
99 QString(
"object_id,edge_length,iterations,area_iterations,use_projection").split(
","),
100 QString(
"id of an object,target edge length,iterations,area iterations,use projection method").split(
","));
101 emit setSlotDescription(
"uniformRemeshing(int,double,uint,uint)",
"Uniform Remeshing with vertex selection and projection method",
102 QString(
"object_id,edge_length,iterations,area_iterations").split(
","),
103 QString(
"id of an object,target edge length,iterations,area iterations").split(
","));
105 emit setSlotDescription(
"uniformRemeshingFaceSelection(int,double,uint,uint,bool)",
"Uniform Remeshing with face selection",
106 QString(
"object_id,edge_length,iterations,area_iterations,use_projection").split(
","),
107 QString(
"id of an object,target edge length,iterations,area iterations,use projection method").split(
","));
108 emit setSlotDescription(
"uniformRemeshingFaceSelection(int,double,uint,uint)",
"Uniform Remeshing with face selection and projection method",
109 QString(
"object_id,edge_length,iterations,area_iterations").split(
","),
110 QString(
"id of an object,target edge length,iterations,area iterations").split(
","));
118 if ( OpenFlipper::Options::gui() ) {
122 connect(tool_->adaptive_button, SIGNAL(clicked()),
this, SLOT(adaptiveRemeshingButtonClicked()) );
124 connect(tool_->uniform_button, SIGNAL(clicked()),
this, SLOT(uniformRemeshingButtonClicked()) );
126 connect(tool_->adaptive_initial_values, SIGNAL(clicked()),
this, SLOT(
computeInitValues()));
127 connect(tool_->uniform_initial_values, SIGNAL(clicked()),
this, SLOT(
computeInitValues()));
129 tool_->tabWidget->setCurrentIndex(0);
131 toolIcon_ =
new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"remesher.png");
132 emit addToolbox( tr(
"Remesher") , tool_ , toolIcon_);
135 connect(
this, SIGNAL( finishJob(QString)),
this, SLOT(threadFinished(QString)), Qt::QueuedConnection);
140void RemesherPlugin::threadFinished(QString _jobId) {
145 if ( operation_ == REMESH_ADAPTIVE ) {
148 }
else if ( operation_ == REMESH_UNIFORM ) {
155 progress_->detachJob();
162 if(OpenFlipper::Options::nogui())
return;
164 double mean_edge = 0.0;
165 double max_feature_angle = 0.0;
178 for(
auto e_it : mesh->edges()) {
184 mean_edge += vec_e.
length();
191 if ( !fh1.is_valid() || !fh2.is_valid() )
197 double feature_angle = (1.0 - (n1 | n2));
199 if(feature_angle > max_feature_angle) max_feature_angle = feature_angle;
202 mean_edge /= (double)mesh->n_edges();
212 for(
auto e_it : mesh->edges()) {
218 mean_edge += vec_e.
length();
225 if ( !fh1.is_valid() || !fh2.is_valid() )
231 double feature_angle = (1.0 - (n1 | n2));
233 if(feature_angle > max_feature_angle) max_feature_angle = feature_angle;
236 mean_edge /= (double)mesh->n_edges();
243 tool_->adaptive_error->setValue(mean_edge * 0.1);
244 tool_->adaptive_min_edge->setValue(mean_edge - (mean_edge * 0.1));
245 tool_->adaptive_max_edge->setValue(mean_edge + (mean_edge * 0.1));
248 tool_->uniform_edge_length->setValue(mean_edge);
256void RemesherPlugin::adaptiveRemeshingButtonClicked() {
258 QString jobId =
name() +
"AdaptiveRemeshing";
261 connect(thread, SIGNAL( finished(QString)),
this, SIGNAL(finishJob(QString)));
262 connect(thread, SIGNAL( function() ),
this, SLOT(adaptiveRemeshing()),Qt::DirectConnection);
265 emit startJob( jobId,
"Adaptive remeshing" , 0 , 100 ,
true);
268 progress_->attachJob(jobId);
277void RemesherPlugin::adaptiveRemeshing() {
279 if(OpenFlipper::Options::nogui())
return;
292 double error = tool_->adaptive_error->value();
293 double min_edge = tool_->adaptive_min_edge->value();
294 double max_edge = tool_->adaptive_max_edge->value();
295 unsigned int iters = tool_->adaptive_iters->text().toInt();
296 bool projection = tool_->adaptive_projection->isChecked();
297 bool vertexSelection = (tool_->adaptive_selection->currentIndex() == 0);
299 slotAdaptiveRemeshing(o_it->id(), error, min_edge, max_edge, iters, projection,vertexSelection);
306void RemesherPlugin::slotAdaptiveRemeshing(
int _objectID,
308 double _min_edge_length,
309 double _max_edge_length,
311 bool _use_projection,
312 bool _vertex_selection) {
314 operation_ = REMESH_ADAPTIVE;
329 remesher.remesh(_error, _min_edge_length, _max_edge_length, _iters, _use_projection, selection);
334 QString projectionString =
"\"FALSE\"";
336 projectionString =
"\"TRUE\"";
338 emit scriptInfo(
"adaptiveRemeshing(" + QString::number(_objectID) +
", "
339 + QString::number(_error) +
", "
340 + QString::number(_min_edge_length) +
", "
341 + QString::number(_max_edge_length) +
", "
342 + QString::number(_iters) +
", "
343 + projectionString +
")");
352void RemesherPlugin::uniformRemeshingButtonClicked() {
356 connect(thread, SIGNAL( state(QString,
int)),
this, SIGNAL(setJobState(QString,
int)));
357 connect(thread, SIGNAL( finished(QString)),
this, SIGNAL(finishJob(QString)));
358 connect(thread, SIGNAL( function() ),
this, SLOT(uniformRemeshing()),Qt::DirectConnection);
360 emit startJob(
name() +
"UniformRemeshing",
"Uniform remeshing" , 0 , 100 ,
true);
369void RemesherPlugin::uniformRemeshing(){
371 if(OpenFlipper::Options::nogui())
return;
374 double edge_length = tool_->uniform_edge_length->value();
375 unsigned int iters = tool_->uniform_iters->text().toInt();
376 unsigned int area_iters = tool_->uniform_area_iters->text().toInt();
377 bool projection = tool_->uniform_projection->isChecked();
378 bool vertex_selection = (tool_->uniform_selection->currentIndex() == 0);
387 for(
auto e_it : mesh->edges()) {
388 if(mesh->status(e_it).feature()) {
389 mesh->status(e_it.h0().to()).set_feature(
true);
390 mesh->status(e_it.h0().from()).set_feature(
true);
400 slotUniformRemeshing(o_it->id(), edge_length, iters, area_iters, projection,vertex_selection);
406void RemesherPlugin::slotUniformRemeshing(
int _objectID,
409 unsigned int _area_iters,
410 bool _use_projection,
411 bool _vertex_selection) {
413 operation_ = REMESH_UNIFORM;
428 remesher.remesh(_edge_length, _iters, _area_iters, _use_projection, selection);
432 QString projectionString =
"\"FALSE\"";
434 projectionString =
"\"TRUE\"";
436 emit scriptInfo(
"uniformRemeshing(" + QString::number(_objectID) +
", "
437 + QString::number(_edge_length) +
", "
438 + QString::number(_iters) +
", "
439 + QString::number(_area_iters) +
", "
440 + QString::number(_iters) +
", "
441 + projectionString +
")");
451void RemesherPlugin::adaptiveRemeshing(
int _objectID,
453 double _min_edge_length,
454 double _max_edge_length,
456 bool _use_projection) {
458 slotAdaptiveRemeshing(_objectID,_error,_min_edge_length,_max_edge_length,_iters,_use_projection);
466void RemesherPlugin::uniformRemeshing(
int _objectID,
469 unsigned int _area_iters,
470 bool _use_projection) {
472 slotUniformRemeshing(_objectID,_edge_length,_iters,_area_iters,_use_projection);
480void RemesherPlugin::adaptiveRemeshingFaceSelection(
int _objectID,
482 double _min_edge_length,
483 double _max_edge_length,
485 bool _use_projection) {
487 slotAdaptiveRemeshing(_objectID,_error,_min_edge_length,_max_edge_length,_iters,_use_projection,
false);
495void RemesherPlugin::uniformRemeshingFaceSelection(
int _objectID,
498 unsigned int _area_iters,
499 bool _use_projection) {
501 slotUniformRemeshing(_objectID,_edge_length,_iters,_area_iters,_use_projection,
false);
#define DATA_TRIANGLE_MESH
bool dataType(DataType _type) const
Thread handling class for OpenFlipper.
void startProcessing()
start processing
Kernel::Normal Normal
Normal type.
void update_face_normals()
Update normal vectors for all faces.
void update_normals()
Compute normals for all primitives.
Kernel::FaceHandle FaceHandle
Scalar type.
auto length() const -> decltype(std::declval< VectorT< S, DIM > >().norm())
compute squared euclidean norm
void pluginsInitialized()
Initialize the plugin.
QString name()
Return a name for the plugin.
void computeInitValues()
Compute mean edge length and set values.
void initializePlugin()
init the Toolbox
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(8))
Topology updated.
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
const QStringList TARGET_OBJECTS("target")
Iterable object range.
SmartFaceHandle face() const
Returns incident face of halfedge.
SmartVertexHandle from() const
Returns vertex at start of halfedge.
SmartHalfedgeHandle opp() const
Returns opposite halfedge handle.
SmartVertexHandle to() const
Returns vertex pointed to by halfedge.