51 #include "RemesherPlugin.hh" 53 #include "Algorithms/AdaptiveRemesherT.hh" 54 #include "Algorithms/UniformRemesherT.hh" 64 RemesherPlugin::RemesherPlugin() :
67 if ( OpenFlipper::Options::gui() ) {
70 connect(progress_, SIGNAL(signalJobState(QString,
int)),
this, SIGNAL(setJobState(QString,
int)), Qt::QueuedConnection);
71 connect(progress_, SIGNAL(changeDescription(QString,QString)),
this, SIGNAL(setJobDescription(QString,QString)), Qt::QueuedConnection);
77 RemesherPlugin::~RemesherPlugin() {
78 if ( OpenFlipper::Options::gui() ) {
88 emit setSlotDescription(
"adaptiveRemeshing(int,double,double,double,uint,bool)",
"Adaptive Remeshing with vertex 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(
"adaptiveRemeshing(int,double,double,double,uint)",
"Adaptive Remeshing with vertex 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(
","));
95 emit setSlotDescription(
"adaptiveRemeshingFaceSelection(int,double,double,double,uint,bool)",
"Adaptive Remeshing with face selection",
96 QString(
"object_id,error,min_edge_length,max_edge_length,iterations,use_projection").split(
","),
97 QString(
"id of an object,error,minimal target edge length,maximal target edge length,iterations,use projection method").split(
","));
98 emit setSlotDescription(
"adaptiveRemeshingFaceSelection(int,double,double,double,uint)",
"Adaptive Remeshing with face selection and projection method",
99 QString(
"object_id,error,min_edge_length,max_edge_length,iterations").split(
","),
100 QString(
"id of an object,error,minimal target edge length,maximal target edge length,iterations").split(
","));
103 emit setSlotDescription(
"uniformRemeshing(int,double,uint,uint,bool)",
"Uniform Remeshing with vertex 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(
"uniformRemeshing(int,double,uint,uint)",
"Uniform Remeshing with vertex 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(
","));
110 emit setSlotDescription(
"uniformRemeshingFaceSelection(int,double,uint,uint,bool)",
"Uniform Remeshing with face selection",
111 QString(
"object_id,edge_length,iterations,area_iterations,use_projection").split(
","),
112 QString(
"id of an object,target edge length,iterations,area iterations,use projection method").split(
","));
113 emit setSlotDescription(
"uniformRemeshingFaceSelection(int,double,uint,uint)",
"Uniform Remeshing with face selection and projection method",
114 QString(
"object_id,edge_length,iterations,area_iterations").split(
","),
115 QString(
"id of an object,target edge length,iterations,area iterations").split(
","));
123 if ( OpenFlipper::Options::gui() ) {
127 connect(tool_->adaptive_button, SIGNAL(clicked()),
this, SLOT(adaptiveRemeshingButtonClicked()) );
129 connect(tool_->uniform_button, SIGNAL(clicked()),
this, SLOT(uniformRemeshingButtonClicked()) );
131 connect(tool_->adaptive_initial_values, SIGNAL(clicked()),
this, SLOT(computeInitValues()));
132 connect(tool_->uniform_initial_values, SIGNAL(clicked()),
this, SLOT(computeInitValues()));
134 tool_->tabWidget->setCurrentIndex(0);
136 toolIcon_ =
new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"remesher.png");
137 emit addToolbox( tr(
"Remesher") , tool_ , toolIcon_);
140 connect(
this, SIGNAL( finishJob(QString)),
this, SLOT(threadFinished(QString)), Qt::QueuedConnection);
145 void RemesherPlugin::threadFinished(QString _jobId) {
150 if ( operation_ == REMESH_ADAPTIVE ) {
153 }
else if ( operation_ == REMESH_UNIFORM ) {
160 progress_->detachJob();
167 if(OpenFlipper::Options::nogui())
return;
169 double mean_edge = 0.0;
170 double max_feature_angle = 0.0;
183 for(TriMesh::EdgeIter e_it = mesh->edges_begin(); e_it != mesh->edges_end(); ++e_it) {
185 TriMesh::HalfedgeHandle he = mesh->halfedge_handle(*e_it, 0);
187 ACG::Vec3d vec_e = mesh->point(mesh->to_vertex_handle(he)) - mesh->point(mesh->from_vertex_handle(he));
189 mean_edge += vec_e.
length();
192 TriMesh::FaceHandle fh1 = mesh->face_handle(he);
193 TriMesh::FaceHandle fh2 = mesh->face_handle(mesh->opposite_halfedge_handle(he));
196 if ( !fh1.is_valid() || !fh2.is_valid() )
202 double feature_angle = (1.0 - (n1 | n2));
204 if(feature_angle > max_feature_angle) max_feature_angle = feature_angle;
207 mean_edge /= (double)mesh->n_edges();
217 for(PolyMesh::EdgeIter e_it = mesh->edges_begin(); e_it != mesh->edges_end(); ++e_it) {
219 PolyMesh::HalfedgeHandle he = mesh->halfedge_handle(*e_it, 0);
221 ACG::Vec3d vec_e = mesh->point(mesh->to_vertex_handle(he)) - mesh->point(mesh->from_vertex_handle(he));
223 mean_edge += vec_e.
length();
226 PolyMesh::FaceHandle fh1 = mesh->face_handle(he);
227 PolyMesh::FaceHandle fh2 = mesh->face_handle(mesh->opposite_halfedge_handle(he));
230 if ( !fh1.is_valid() || !fh2.is_valid() )
236 double feature_angle = (1.0 - (n1 | n2));
238 if(feature_angle > max_feature_angle) max_feature_angle = feature_angle;
241 mean_edge /= (double)mesh->n_edges();
245 max_feature_angle = max_feature_angle * (M_PI / 2.0);
248 tool_->adaptive_error->setValue(mean_edge * 0.1);
249 tool_->adaptive_min_edge->setValue(mean_edge - (mean_edge * 0.1));
250 tool_->adaptive_max_edge->setValue(mean_edge + (mean_edge * 0.1));
253 tool_->uniform_edge_length->setValue(mean_edge);
261 void RemesherPlugin::adaptiveRemeshingButtonClicked() {
263 QString jobId = name() +
"AdaptiveRemeshing";
266 connect(thread, SIGNAL( finished(QString)),
this, SIGNAL(finishJob(QString)));
267 connect(thread, SIGNAL(
function() ),
this, SLOT(adaptiveRemeshing()),Qt::DirectConnection);
270 emit startJob( jobId,
"Adaptive remeshing" , 0 , 100 ,
true);
273 progress_->attachJob(jobId);
282 void RemesherPlugin::adaptiveRemeshing() {
284 if(OpenFlipper::Options::nogui())
return;
297 double error = tool_->adaptive_error->value();
298 double min_edge = tool_->adaptive_min_edge->value();
299 double max_edge = tool_->adaptive_max_edge->value();
300 unsigned int iters = tool_->adaptive_iters->text().toInt();
301 bool projection = tool_->adaptive_projection->isChecked();
302 bool vertexSelection = (tool_->adaptive_selection->currentIndex() == 0);
304 slotAdaptiveRemeshing(o_it->id(), error, min_edge, max_edge, iters, projection,vertexSelection);
311 void RemesherPlugin::slotAdaptiveRemeshing(
int _objectID,
313 double _min_edge_length,
314 double _max_edge_length,
316 bool _use_projection,
317 bool _vertex_selection) {
319 operation_ = REMESH_ADAPTIVE;
334 remesher.remesh(_error, _min_edge_length, _max_edge_length, _iters, _use_projection, selection);
339 QString projectionString =
"\"FALSE\"";
341 projectionString =
"\"TRUE\"";
343 emit scriptInfo(
"adaptiveRemeshing(" + QString::number(_objectID) +
", " 344 + QString::number(_error) +
", " 345 + QString::number(_min_edge_length) +
", " 346 + QString::number(_max_edge_length) +
", " 347 + QString::number(_iters) +
", " 348 + projectionString +
")");
357 void RemesherPlugin::uniformRemeshingButtonClicked() {
361 connect(thread, SIGNAL( state(QString,
int)),
this, SIGNAL(setJobState(QString,
int)));
362 connect(thread, SIGNAL( finished(QString)),
this, SIGNAL(finishJob(QString)));
363 connect(thread, SIGNAL(
function() ),
this, SLOT(uniformRemeshing()),Qt::DirectConnection);
365 emit startJob( name() +
"UniformRemeshing",
"Uniform remeshing" , 0 , 100 ,
true);
374 void RemesherPlugin::uniformRemeshing(){
376 if(OpenFlipper::Options::nogui())
return;
379 double edge_length = tool_->uniform_edge_length->value();
380 unsigned int iters = tool_->uniform_iters->text().toInt();
381 unsigned int area_iters = tool_->uniform_area_iters->text().toInt();
382 bool projection = tool_->uniform_projection->isChecked();
383 bool vertex_selection = (tool_->uniform_selection->currentIndex() == 0);
392 for(TriMesh::EdgeIter e_it = mesh->edges_begin(); e_it != mesh->edges_end(); ++e_it) {
393 if(mesh->status(*e_it).feature()) {
394 mesh->status(mesh->to_vertex_handle(mesh->halfedge_handle(*e_it, 0))).set_feature(
true);
395 mesh->status(mesh->from_vertex_handle(mesh->halfedge_handle(*e_it, 0))).set_feature(
true);
405 slotUniformRemeshing(o_it->id(), edge_length, iters, area_iters, projection,vertex_selection);
411 void RemesherPlugin::slotUniformRemeshing(
int _objectID,
414 unsigned int _area_iters,
415 bool _use_projection,
416 bool _vertex_selection) {
418 operation_ = REMESH_UNIFORM;
433 remesher.remesh(_edge_length, _iters, _area_iters, _use_projection, selection);
437 QString projectionString =
"\"FALSE\"";
439 projectionString =
"\"TRUE\"";
441 emit scriptInfo(
"uniformRemeshing(" + QString::number(_objectID) +
", " 442 + QString::number(_edge_length) +
", " 443 + QString::number(_iters) +
", " 444 + QString::number(_area_iters) +
", " 445 + QString::number(_iters) +
", " 446 + projectionString +
")");
456 void RemesherPlugin::adaptiveRemeshing(
int _objectID,
458 double _min_edge_length,
459 double _max_edge_length,
461 bool _use_projection) {
463 slotAdaptiveRemeshing(_objectID,_error,_min_edge_length,_max_edge_length,_iters,_use_projection);
471 void RemesherPlugin::uniformRemeshing(
int _objectID,
474 unsigned int _area_iters,
475 bool _use_projection) {
477 slotUniformRemeshing(_objectID,_edge_length,_iters,_area_iters,_use_projection);
485 void RemesherPlugin::adaptiveRemeshingFaceSelection(
int _objectID,
487 double _min_edge_length,
488 double _max_edge_length,
490 bool _use_projection) {
492 slotAdaptiveRemeshing(_objectID,_error,_min_edge_length,_max_edge_length,_iters,_use_projection,
false);
500 void RemesherPlugin::uniformRemeshingFaceSelection(
int _objectID,
503 unsigned int _area_iters,
504 bool _use_projection) {
506 slotUniformRemeshing(_objectID,_edge_length,_iters,_area_iters,_use_projection,
false);
514 #if QT_VERSION < 0x050000 void computeInitValues()
Compute mean edge length and set values.
auto length() const -> decltype(std::declval< VectorT< S, DIM >>().norm())
compute squared euclidean norm
void pluginsInitialized()
Initialize the plugin.
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(1)<< 3)
Topology updated.
void update_normals()
Compute normals for all primitives.
bool getObject(int _identifier, BSplineCurveObject *&_object)
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
bool dataType(DataType _type) const
const QStringList TARGET_OBJECTS("target")
Iterable object range.
void startProcessing()
start processing
Thread handling class for OpenFlipper.
Kernel::Normal Normal
Normal type.
void update_face_normals()
Update normal vectors for all faces.
void initializePlugin()
init the Toolbox
#define DATA_TRIANGLE_MESH
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.