diff --git a/Mesh_3/demo/Mesh_3/Mesh_3_optimization_plugin.cpp b/Mesh_3/demo/Mesh_3/Mesh_3_optimization_plugin.cpp index daee3bd1184..15b8c23fe47 100644 --- a/Mesh_3/demo/Mesh_3/Mesh_3_optimization_plugin.cpp +++ b/Mesh_3/demo/Mesh_3/Mesh_3_optimization_plugin.cpp @@ -53,7 +53,7 @@ Optimizer_thread* cgal_code_exude_mesh_3(Scene_c3t3_item& c3t3_item, const double sliver_bound, const bool create_new_item); -std::string translate(CGAL::Mesh_optimization_return_code rc); +QString translate(CGAL::Mesh_optimization_return_code rc); // Mesh_3_optimization_plugin class class Mesh_3_optimization_plugin : @@ -72,9 +72,13 @@ public slots: void perturb(); void exude(); + void optimization_done(Optimizer_thread* t); + private: void treat_result(Scene_c3t3_item& source_item, Scene_c3t3_item& result_item, - const QString& name, bool new_item_created) const; + const QString& name) const; + + void launch_thread(Optimizer_thread* thread, const QString& msg); private: QAction* actionOdt; @@ -82,6 +86,9 @@ private: QAction* actionPerturb; QAction* actionExude; Messages_interface* msg; + QMessageBox* message_box_; + + Scene_c3t3_item* source_item_; }; // end class Mesh_3_optimization_plugin @@ -187,8 +194,6 @@ Mesh_3_optimization_plugin::odt() // Launch optimization // ----------------------------------- QApplication::setOverrideCursor(Qt::WaitCursor); - QTime timer; - timer.start(); Optimizer_thread* opt_thread = cgal_code_odt_mesh_3(*item, max_time, @@ -203,27 +208,8 @@ Mesh_3_optimization_plugin::odt() return; } - opt_thread->start(); - opt_thread->wait(); - Scene_c3t3_item* result_item = opt_thread->item(); - CGAL::Mesh_optimization_return_code return_code = opt_thread->return_code(); - - std::stringstream sstr; - sstr << "Odt-smoothing of \"" << qPrintable(item->name()) << "\" done in " - << timer.elapsed()/1000. << "s
" - << "End reason: '" << translate(return_code) << "'
" - << "( max time: " << max_time << " )
" - << "( convergence: " << convergence << " )
" - << "( freeze bound: " << freeze << " )
" - << "( max iteration number: " << max_iteration_nb << " )
"; - msg->information(sstr.str().c_str()); - - // ----------------------------------- - // Treat result - // ----------------------------------- - QString name("odt"); - treat_result(*item, *result_item, name, create_new_item); - + source_item_ = item; + launch_thread(opt_thread, "Odt iterations are running..."); QApplication::restoreOverrideCursor(); } @@ -283,8 +269,6 @@ Mesh_3_optimization_plugin::lloyd() // Launch optimization // ----------------------------------- QApplication::setOverrideCursor(Qt::WaitCursor); - QTime timer; - timer.start(); Optimizer_thread* opt_thread = cgal_code_lloyd_mesh_3(*item, max_time, @@ -299,27 +283,8 @@ Mesh_3_optimization_plugin::lloyd() return; } - opt_thread->start(); - opt_thread->wait(); - Scene_c3t3_item* result_item = opt_thread->item(); - CGAL::Mesh_optimization_return_code return_code = opt_thread->return_code(); - - std::stringstream sstr; - sstr << "Lloyd-smoothing of \"" << qPrintable(item->name()) << "\" done in " - << timer.elapsed()/1000. << "s
" - << "End reason: '" << translate(return_code) << "'
" - << "( max time: " << max_time << " )
" - << "( convergence: " << convergence << " )
" - << "( freeze bound: " << freeze << " )
" - << "( max iteration number: " << max_iteration_nb << " )
"; - msg->information(sstr.str().c_str()); - - // ----------------------------------- - // Treat result - // ----------------------------------- - QString name("lloyd"); - treat_result(*item, *result_item, name, create_new_item); - + source_item_ = item; + launch_thread(opt_thread, "Lloyd iterations are running..."); QApplication::restoreOverrideCursor(); } @@ -373,8 +338,6 @@ Mesh_3_optimization_plugin::perturb() // Launch optimization // ----------------------------------- QApplication::setOverrideCursor(Qt::WaitCursor); - QTime timer; - timer.start(); Optimizer_thread* opt_thread = cgal_code_perturb_mesh_3(*item, max_time, @@ -388,25 +351,8 @@ Mesh_3_optimization_plugin::perturb() return; } - opt_thread->start(); - opt_thread->wait(); - Scene_c3t3_item* result_item = opt_thread->item(); - CGAL::Mesh_optimization_return_code return_code = opt_thread->return_code(); - - std::stringstream sstr; - sstr << "Perturbation of \"" << qPrintable(item->name()) << "\" done in " - << timer.elapsed()/1000. << "s
" - << "End reason: '" << translate(return_code) << "'
" - << "( max time: " << max_time << " )
" - << "( sliver bound: " << sliver_bound << " )
"; - msg->information(sstr.str().c_str()); - - // ----------------------------------- - // Treat result - // ----------------------------------- - QString name("perturb"); - treat_result(*item, *result_item, name, create_new_item); - + source_item_ = item; + launch_thread(opt_thread, "Sliver perturbation is running..."); QApplication::restoreOverrideCursor(); } @@ -454,8 +400,6 @@ Mesh_3_optimization_plugin::exude() // Launch optimization // ----------------------------------- QApplication::setOverrideCursor(Qt::WaitCursor); - QTime timer; - timer.start(); Optimizer_thread* opt_thread = cgal_code_exude_mesh_3(*item, max_time, @@ -468,25 +412,8 @@ Mesh_3_optimization_plugin::exude() return; } - opt_thread->start(); - opt_thread->wait(); - Scene_c3t3_item* result_item = opt_thread->item(); - CGAL::Mesh_optimization_return_code return_code = opt_thread->return_code(); - - std::stringstream sstr; - sstr << "Exudation of \"" << qPrintable(item->name()) << "\" done in " - << timer.elapsed()/1000. << "s
" - << "End reason: '" << translate(return_code) << "'
" - << "( max time: " << max_time << " )
" - << "( sliver bound: " << sliver_bound << " )
"; - msg->information(sstr.str().c_str()); - - // ----------------------------------- - // Treat result - // ----------------------------------- - QString name("exude"); - treat_result(*item, *result_item, name, create_new_item); - + source_item_ = item; + launch_thread(opt_thread, "Sliver exudation is running..."); QApplication::restoreOverrideCursor(); } @@ -496,13 +423,13 @@ void Mesh_3_optimization_plugin:: treat_result(Scene_c3t3_item& source_item, Scene_c3t3_item& result_item, - const QString& name, - bool new_item_created) const + const QString& name) const { result_item.setName(tr("%1 [%2]").arg(source_item.name()) .arg(name)); - if ( new_item_created ) + // If a new item has been created + if ( &source_item != &result_item) { const Scene_item::Bbox& bbox = result_item.bbox(); result_item.setPosition((bbox.xmin + bbox.xmax)/2.f, @@ -530,19 +457,87 @@ treat_result(Scene_c3t3_item& source_item, } } -std::string + +void +Mesh_3_optimization_plugin:: +optimization_done(Optimizer_thread* thread) +{ + CGAL::Mesh_optimization_return_code return_code = thread->return_code(); + QString name = thread->optimizer_name(); + + // Print message in console + QString str = QString("%1 of \"%2\" done in %3s
" + "End reason: '%4'
") + .arg(name) + .arg(source_item_->name()) + .arg(thread->time()) + .arg(translate(return_code)); + + Q_FOREACH( QString param, thread->parameters_log() ) + { + str.append(QString("( %1 )
").arg(param)); + } + + msg->information(qPrintable(str)); + + // Treat new c3t3 item + Scene_c3t3_item* result_item = thread->item(); + treat_result( *source_item_, *result_item, name); + + // close message box + message_box_->close(); + + // free memory + delete thread; +} + + +void +Mesh_3_optimization_plugin:: +launch_thread(Optimizer_thread* opt_thread, const QString& window_text) +{ + // ----------------------------------- + // Create message box with stop button + // ----------------------------------- + message_box_ = new QMessageBox(QMessageBox::NoIcon, + "Optimization...", + window_text, + QMessageBox::Cancel, + mw); + + message_box_->setDefaultButton(QMessageBox::Cancel); + QAbstractButton* cancelButton = message_box_->button(QMessageBox::Cancel); + cancelButton->setText(tr("Stop")); + + QObject::connect(cancelButton, SIGNAL(clicked()), + opt_thread, SLOT(stop())); + + message_box_->show(); + + // ----------------------------------- + // Connect main thread to optimization thread and launch optimizer + // ----------------------------------- + QObject::connect(opt_thread, SIGNAL(done(Optimizer_thread*)), + this, SLOT(optimization_done(Optimizer_thread*))); + + opt_thread->start(); +} + + +QString translate(CGAL::Mesh_optimization_return_code rc) { switch (rc) { - case CGAL::BOUND_REACHED: return std::string("Bound reached"); - case CGAL::TIME_LIMIT_REACHED: return std::string("Time limit reached"); - case CGAL::CANT_IMPROVE_ANYMORE: return std::string("Can't improve anymore"); - case CGAL::CONVERGENCE_REACHED: return std::string("Convergence reached"); - case CGAL::MAX_ITERATION_NUMBER_REACHED: return std::string("Max iteration number reached"); + case CGAL::MESH_OPTIMIZATION_UNKNOWN_ERROR: return QString("Unexpected error"); + case CGAL::BOUND_REACHED: return QString("Bound reached"); + case CGAL::TIME_LIMIT_REACHED: return QString("Time limit reached"); + case CGAL::CANT_IMPROVE_ANYMORE: return QString("Can't improve anymore"); + case CGAL::CONVERGENCE_REACHED: return QString("Convergence reached"); + case CGAL::MAX_ITERATION_NUMBER_REACHED: return QString("Max iteration number reached"); } - return std::string("ERROR"); + return QString("ERROR"); } diff --git a/Mesh_3/demo/Mesh_3/Mesh_3_optimization_plugin_cgal_code.cpp b/Mesh_3/demo/Mesh_3/Mesh_3_optimization_plugin_cgal_code.cpp index e8c5d5269ae..776ac165210 100644 --- a/Mesh_3/demo/Mesh_3/Mesh_3_optimization_plugin_cgal_code.cpp +++ b/Mesh_3/demo/Mesh_3/Mesh_3_optimization_plugin_cgal_code.cpp @@ -9,6 +9,7 @@ #include "Optimizer_thread.h" #include +#include #include #include @@ -19,45 +20,53 @@ namespace cgp = CGAL::parameters; // ----------------------------------- -// Optimization_function template class +// Optimization_function_base template class // ----------------------------------- -template -class Optimization_function +template +class Optimization_function_base : public Optimization_function_interface { public: - // This class takes the responsability of d - Optimization_function(Scene_c3t3_item* i, Domain* d, const Function& f) - : item_(i), domain_(d), function_(f) {} + /// Constructor + /// Takes the responsability of d + explicit + Optimization_function_base(C3t3& c3t3, Domain* d) + : c3t3_(c3t3), domain_(d) {} - virtual ~Optimization_function() + /// Destructor + virtual ~Optimization_function_base() { delete domain_; } - virtual CGAL::Mesh_optimization_return_code launch() const + /// Launch + virtual CGAL::Mesh_optimization_return_code launch() { - return function_(item_->c3t3(), *domain_); + return (*this)(c3t3_, *domain_); } - virtual Scene_c3t3_item* item() const - { - return item_; - } +protected: + /// Virtual operator() which should be overloaded + virtual CGAL::Mesh_optimization_return_code + operator()(C3t3& c3t3, const Domain& domain) = 0; private: - Scene_c3t3_item* item_; + C3t3& c3t3_; Domain* domain_; - Function function_; }; +// Prototype which will be partially specialized for each Parameter class +template < typename Domain, typename Parameters > +class Optimization_function {}; + + // ----------------------------------- // Optimization generic function (responsible of dynamic casting) // ----------------------------------- -template +template Optimizer_thread* cgal_code_optimization(Scene_c3t3_item& c3t3_item, - const Function& f, + const Parameters& param, const bool create_new_item) { // Create result item @@ -89,10 +98,10 @@ Optimizer_thread* cgal_code_optimization(Scene_c3t3_item& c3t3_item, Image_mesh_domain* p_domain = new Image_mesh_domain(*p_image, 1e-6); // Create thread - typedef Optimization_function Opt_function; - Opt_function* p_opt_function = new Opt_function(p_result_item, p_domain, f); + typedef Optimization_function Opt_function; + Opt_function* p_opt_function = new Opt_function(p_result_item->c3t3(), p_domain, param); - return new Optimizer_thread(p_opt_function); + return new Optimizer_thread(p_opt_function, p_result_item); } @@ -112,10 +121,10 @@ Optimizer_thread* cgal_code_optimization(Scene_c3t3_item& c3t3_item, Mesh_domain* p_domain = new Mesh_domain(*p_poly); // Create thread - typedef Optimization_function Opt_function; - Opt_function* p_opt_function = new Opt_function(p_result_item, p_domain, f); + typedef Optimization_function Opt_function; + Opt_function* p_opt_function = new Opt_function(p_result_item->c3t3(), p_domain, param); - return new Optimizer_thread(p_opt_function); + return new Optimizer_thread(p_opt_function, p_result_item); } // Function @@ -139,10 +148,10 @@ Optimizer_thread* cgal_code_optimization(Scene_c3t3_item& c3t3_item, new Function_mesh_domain(Function_wrapper(*p_function), dom_bbox, 1e-7); // Create thread - typedef Optimization_function Opt_function; - Opt_function* p_opt_function = new Opt_function(p_result_item, p_domain, f); + typedef Optimization_function Opt_function; + Opt_function* p_opt_function = new Opt_function(p_result_item->c3t3(), p_domain, param); - return new Optimizer_thread(p_opt_function); + return new Optimizer_thread(p_opt_function, p_result_item); } return NULL; @@ -153,28 +162,93 @@ Optimizer_thread* cgal_code_optimization(Scene_c3t3_item& c3t3_item, // ----------------------------------- // Odt // ----------------------------------- -struct Odt_function +struct Odt_parameters { double time_limit; double convergence_ratio; double freeze_ratio; int max_iteration_nb; - template - CGAL::Mesh_optimization_return_code - operator()(C3t3& c3t3, const Domain& domain) const + QStringList log() const { - // Odt - return CGAL::odt_optimize_mesh_3(c3t3, - domain, - cgp::time_limit = time_limit, - cgp::convergence = convergence_ratio, - cgp::freeze_bound = freeze_ratio, - cgp::max_iteration_number = max_iteration_nb); + return QStringList() + << QString("time limit: %1").arg(time_limit) + << QString("convergence ratio: %1").arg(convergence_ratio) + << QString("freeze ratio: %1").arg(freeze_ratio) + << QString("maximum iterations: %1").arg(max_iteration_nb); } }; +/** + * @class Odt_function + * Partial specialization of class Optimization_function for Odt + * Runs odt global optimization + */ +template +class Optimization_function < Domain, Odt_parameters > + : public Optimization_function_base< Domain > +{ + // Private types + typedef C3t3::Triangulation Tr; + typedef Tr::Geom_traits Gt; + + typedef CGAL::Mesh_3::Mesh_sizing_field Sizing; + typedef CGAL::Mesh_3::Odt_move Move; + + typedef typename CGAL::Mesh_3::Mesh_global_optimizer Odt_optimizer; + + typedef Optimization_function_base< Domain > Base; + +public: + /// Constructor + Optimization_function(C3t3& c3t3, Domain* d, const Odt_parameters& p) + : Base(c3t3,d) + , odt_(NULL) + , p_(p) {} + + /// Destructor + virtual ~Optimization_function() { delete odt_; } + + /// Stops process (set time limit to 1ms) + virtual void stop() { odt_->set_time_limit(0.001); } + + /// Log strings + virtual QString name() const { return QString("Odt"); } + virtual QStringList parameters_log() const { return p_.log(); } + +protected: + /// Launch odt optimization + /// The content of this method is taken from CGAL::odt_optimize_mesh_3() + virtual CGAL::Mesh_optimization_return_code + operator()(C3t3& c3t3, const Domain& domain) + { + if ( NULL != odt_ ) { return CGAL::MESH_OPTIMIZATION_UNKNOWN_ERROR; } + + // Create optimizer + odt_ = new Odt_optimizer(c3t3, domain, p_.freeze_ratio, p_.convergence_ratio); + if ( NULL == odt_ ) { return CGAL::MESH_OPTIMIZATION_UNKNOWN_ERROR; } + + // Set max time + odt_->set_time_limit(p_.time_limit); + + // 1000 iteration max to avoid infinite loops + int max_iteration_nb = ( 0 == p_.max_iteration_nb ) ? 1000 + : p_.max_iteration_nb; + + // Launch optimization + return (*odt_)(max_iteration_nb); + } + +private: + Odt_optimizer* odt_; + Odt_parameters p_; +}; + + +/** + * Global function cgal_code_odt_mesh_3 + */ Optimizer_thread* cgal_code_odt_mesh_3(Scene_c3t3_item& c3t3_item, const double time_limit, @@ -183,13 +257,13 @@ cgal_code_odt_mesh_3(Scene_c3t3_item& c3t3_item, const int max_iteration_number, const bool create_new_item) { - Odt_function f; - f.time_limit = time_limit; - f.convergence_ratio = convergence_ratio; - f.freeze_ratio = freeze_ratio; - f.max_iteration_nb = max_iteration_number; + Odt_parameters p; + p.time_limit = time_limit; + p.convergence_ratio = convergence_ratio; + p.freeze_ratio = freeze_ratio; + p.max_iteration_nb = max_iteration_number; - return cgal_code_optimization(c3t3_item, f, create_new_item); + return cgal_code_optimization(c3t3_item, p, create_new_item); } @@ -197,28 +271,93 @@ cgal_code_odt_mesh_3(Scene_c3t3_item& c3t3_item, // ----------------------------------- // Lloyd // ----------------------------------- -struct Lloyd_function +struct Lloyd_parameters { double time_limit; double convergence_ratio; double freeze_ratio; int max_iteration_nb; - template - CGAL::Mesh_optimization_return_code - operator()(C3t3& c3t3, const Domain& domain) const + QStringList log() const { - // Lloyd - return CGAL::lloyd_optimize_mesh_3(c3t3, - domain, - cgp::time_limit = time_limit, - cgp::convergence = convergence_ratio, - cgp::freeze_bound = freeze_ratio, - cgp::max_iteration_number = max_iteration_nb); + return QStringList() + << QString("time limit: %1").arg(time_limit) + << QString("convergence ratio: %1").arg(convergence_ratio) + << QString("freeze ratio: %1").arg(freeze_ratio) + << QString("maximum iterations: %1").arg(max_iteration_nb); } }; +/** + * @class Lloyd_function + * Partial specialization of class Optimization_function for Lloyd + * Runs lloyd global optimization + */ +template +class Optimization_function < Domain, Lloyd_parameters > + : public Optimization_function_base< Domain > +{ + // Private types + typedef C3t3::Triangulation Tr; + typedef Tr::Geom_traits Gt; + + typedef CGAL::Mesh_3::Mesh_sizing_field Sizing; + typedef CGAL::Mesh_3::Lloyd_move Move; + + typedef typename CGAL::Mesh_3::Mesh_global_optimizer Lloyd_optimizer; + + typedef Optimization_function_base< Domain > Base; + +public: + /// Constructor + Optimization_function(C3t3& c3t3, Domain* d, const Lloyd_parameters& p) + : Base(c3t3,d) + , lloyd_(NULL) + , p_(p) {} + + /// Destructor + virtual ~Optimization_function() { delete lloyd_; } + + /// Stops process (set time limit to 1ms) + virtual void stop() { lloyd_->set_time_limit(0.001); } + + /// Log strings + virtual QString name() const { return QString("Lloyd"); } + virtual QStringList parameters_log() const { return p_.log(); } + +protected: + /// Launch lloyd optimization + /// The content of this method is taken from CGAL::lloyd_optimize_mesh_3() + virtual CGAL::Mesh_optimization_return_code + operator()(C3t3& c3t3, const Domain& domain) + { + if ( NULL != lloyd_ ) { return CGAL::MESH_OPTIMIZATION_UNKNOWN_ERROR; } + + // Create optimizer + lloyd_ = new Lloyd_optimizer(c3t3, domain, p_.freeze_ratio, p_.convergence_ratio); + if ( NULL == lloyd_ ) { return CGAL::MESH_OPTIMIZATION_UNKNOWN_ERROR; } + + // Set max time + lloyd_->set_time_limit(p_.time_limit); + + // 1000 iteration max to avoid infinite loops + int max_iteration_nb = ( 0 == p_.max_iteration_nb ) ? 1000 + : p_.max_iteration_nb; + + // Launch optimization + return (*lloyd_)(max_iteration_nb); + } + +private: + Lloyd_optimizer* lloyd_; + Lloyd_parameters p_; +}; + + +/** + * Global function cgal_code_lloyd_mesh_3 + */ Optimizer_thread* cgal_code_lloyd_mesh_3(Scene_c3t3_item& c3t3_item, const double time_limit, @@ -227,13 +366,13 @@ cgal_code_lloyd_mesh_3(Scene_c3t3_item& c3t3_item, const int max_iteration_number, const bool create_new_item) { - Lloyd_function f; - f.time_limit = time_limit; - f.convergence_ratio = convergence_ratio; - f.freeze_ratio = freeze_ratio; - f.max_iteration_nb = max_iteration_number; + Lloyd_parameters p; + p.time_limit = time_limit; + p.convergence_ratio = convergence_ratio; + p.freeze_ratio = freeze_ratio; + p.max_iteration_nb = max_iteration_number; - return cgal_code_optimization(c3t3_item, f, create_new_item); + return cgal_code_optimization(c3t3_item, p, create_new_item); } @@ -241,57 +380,186 @@ cgal_code_lloyd_mesh_3(Scene_c3t3_item& c3t3_item, // ----------------------------------- // Perturbation // ----------------------------------- -struct Perturb_function +struct Perturb_parameters { double time_limit; double sliver_bound; - template - CGAL::Mesh_optimization_return_code - operator()(C3t3& c3t3, const Domain& domain) const + QStringList log() const { - // Perturbation - return CGAL::perturb_mesh_3(c3t3, - domain, - cgp::sliver_bound = sliver_bound, - cgp::time_limit = time_limit); + return QStringList() + << QString("time limit: %1").arg(time_limit) + << QString("sliver bound: %1").arg(sliver_bound); } }; +/** + * @class Perturb_function + * Partial specialization of class Optimization_function for perturbation + * Runs sliver perturbation + */ +template +class Optimization_function < Domain, Perturb_parameters > + : public Optimization_function_base< Domain > +{ + // Private types + typedef C3t3::Triangulation::Geom_traits Gt; + typedef CGAL::Mesh_3::Min_dihedral_angle_criterion Sc; + + typedef CGAL::Mesh_3::Sliver_perturber Perturber; + + typedef Optimization_function_base< Domain > Base; + +public: + /// Constructor + Optimization_function(C3t3& c3t3, Domain* d, const Perturb_parameters& p) + : Base(c3t3,d) + , perturb_(NULL) + , p_(p) {} + + /// Destructor + ~Optimization_function() { delete perturb_; } + + /// Stops process (set time limit to 1ms) + virtual void stop() { perturb_->set_time_limit(0.001); } + + /// Log strings + virtual QString name() const { return QString("Perturb"); } + virtual QStringList parameters_log() const { return p_.log(); } + +protected: + /// Launch sliver perturbation + /// The content of this method is taken from CGAL::perturb_mesh_3() + virtual CGAL::Mesh_optimization_return_code + operator()(C3t3& c3t3, const Domain& domain) + { + if ( NULL != perturb_ ) { return CGAL::MESH_OPTIMIZATION_UNKNOWN_ERROR; } + + typedef CGAL::Mesh_3::Sq_radius_perturbation Sq_radius; + typedef CGAL::Mesh_3::Volume_perturbation Volume; + typedef CGAL::Mesh_3::Dihedral_angle_perturbation Dihedral_angle; + typedef CGAL::Mesh_3::Li_random_perturbation Li_random; + + // Build perturber + perturb_ = new Perturber(c3t3,domain); + if ( NULL == perturb_ ) { return CGAL::MESH_OPTIMIZATION_UNKNOWN_ERROR; } + + // Add perturbations + perturb_->add_perturbation(new Sq_radius(40,0.02)); + perturb_->add_perturbation(new Volume(40,0.02)); + perturb_->add_perturbation(new Dihedral_angle(40,0.02)); + perturb_->add_perturbation(new Li_random(100,0.05)); + + // Set max time + perturb_->set_time_limit(p_.time_limit); + + // Launch perturber + if ( p_.sliver_bound != 0 ) { return (*perturb_)(p_.sliver_bound); } + else { return (*perturb_)(); } + } + +private: + Perturber* perturb_; + Perturb_parameters p_; +}; + + +/** + * Global function cgal_code_perturb_mesh_3 + */ Optimizer_thread* cgal_code_perturb_mesh_3(Scene_c3t3_item& c3t3_item, const double time_limit, const double sliver_bound, const bool create_new_item) { - Perturb_function f; - f.sliver_bound = sliver_bound; - f.time_limit = time_limit; + Perturb_parameters p; + p.sliver_bound = sliver_bound; + p.time_limit = time_limit; - return cgal_code_optimization(c3t3_item, f, create_new_item); + return cgal_code_optimization(c3t3_item, p, create_new_item); } // ----------------------------------- // Exudation // ----------------------------------- -struct Exude_function +struct Exude_parameters { double time_limit; double sliver_bound; - CGAL::Mesh_optimization_return_code - operator()(C3t3& c3t3, int) const + QStringList log() const { - // Perturbation - return CGAL::exude_mesh_3(c3t3, - cgp::sliver_bound = sliver_bound, - cgp::time_limit = time_limit); + return QStringList() + << QString("time limit: %1").arg(time_limit) + << QString("sliver bound: %1").arg(sliver_bound); } }; +/** + * @class Exude_function + * Partial specialization of class Optimization_function for exudation + * Runs sliver exudation + */ +template +class Optimization_function < Domain, Exude_parameters > + : public Optimization_function_base< Domain > +{ + // Private types + typedef C3t3::Triangulation::Geom_traits Gt; + typedef CGAL::Mesh_3::Min_dihedral_angle_criterion Sc; + typedef CGAL::Mesh_3::Slivers_exuder Exuder; + + typedef Optimization_function_base< Domain > Base; + +public: + // Constructor + Optimization_function(C3t3& c3t3, Domain* d, const Exude_parameters& p) + : Base(c3t3,d) + , exude_(NULL) + , p_(p) {} + + /// Destructor + ~Optimization_function() { delete exude_; } + + /// Stops process (set time limit to 1ms) + virtual void stop() { exude_->set_time_limit(0.001); } + + // Log strings + virtual QString name() const { return QString("Exude"); } + virtual QStringList parameters_log() const { return p_.log(); } + +protected: + /// Launch sliver exudation + /// The content of this method is taken from CGAL::exude_mesh_3() + virtual CGAL::Mesh_optimization_return_code + operator()(C3t3& c3t3, const Domain&) + { + if ( NULL != exude_ ) { return CGAL::MESH_OPTIMIZATION_UNKNOWN_ERROR; } + + // Create exuder + exude_ = new Exuder(c3t3); + if ( NULL == exude_ ) { return CGAL::MESH_OPTIMIZATION_UNKNOWN_ERROR; } + + // Set time_limit + exude_->set_time_limit(p_.time_limit); + + // Launch exudation + return (*exude_)(p_.sliver_bound); + } + +private: + Exuder* exude_; + Exude_parameters p_; +}; + + +/** + * Global function cgal_code_exude_mesh_3 + */ Optimizer_thread* cgal_code_exude_mesh_3(Scene_c3t3_item& c3t3_item, const double time_limit, @@ -308,13 +576,13 @@ cgal_code_exude_mesh_3(Scene_c3t3_item& c3t3_item, } // Exudation - Exude_function f; - f.sliver_bound = sliver_bound; - f.time_limit = time_limit; + Exude_parameters p; + p.sliver_bound = sliver_bound; + p.time_limit = time_limit; // Create thread - typedef Optimization_function Opt_function; - Opt_function* p_opt_function = new Opt_function(p_result_item, NULL, f); + typedef Optimization_function Opt_function; + Opt_function* p_opt_function = new Opt_function(p_result_item->c3t3(), NULL, p); - return new Optimizer_thread(p_opt_function); + return new Optimizer_thread(p_opt_function, p_result_item); } \ No newline at end of file diff --git a/Mesh_3/demo/Mesh_3/Optimizer_thread.cpp b/Mesh_3/demo/Mesh_3/Optimizer_thread.cpp index 87677db643e..a81353cec06 100644 --- a/Mesh_3/demo/Mesh_3/Optimizer_thread.cpp +++ b/Mesh_3/demo/Mesh_3/Optimizer_thread.cpp @@ -21,6 +21,7 @@ // File Description : //****************************************************************************** +#include #include "Optimizer_thread.h" Optimizer_thread::~Optimizer_thread() @@ -33,7 +34,23 @@ void Optimizer_thread:: run() { + QTime timer; + timer.start(); + rc_ = f_->launch(); + + time_ = double(timer.elapsed()) / 1000; + + emit done(this); } + +void +Optimizer_thread:: +stop() +{ + f_->stop(); +} + + #include "Optimizer_thread.moc" \ No newline at end of file diff --git a/Mesh_3/demo/Mesh_3/Optimizer_thread.h b/Mesh_3/demo/Mesh_3/Optimizer_thread.h index b9b5069eeb2..cbff5ef699d 100644 --- a/Mesh_3/demo/Mesh_3/Optimizer_thread.h +++ b/Mesh_3/demo/Mesh_3/Optimizer_thread.h @@ -26,6 +26,8 @@ #include #include +#include +#include #include @@ -35,28 +37,56 @@ class Optimization_function_interface { public: virtual ~Optimization_function_interface() {} - virtual CGAL::Mesh_optimization_return_code launch() const = 0; - virtual Scene_c3t3_item* item() const = 0; + + // Launch + virtual CGAL::Mesh_optimization_return_code launch() = 0; + + // Stop + virtual void stop() = 0; + + // Logs + virtual QString name() const = 0; + virtual QStringList parameters_log() const = 0; }; + class Optimizer_thread : public QThread { Q_OBJECT public: - Optimizer_thread(Optimization_function_interface* f) - : f_(f), rc_() {} + Optimizer_thread(Optimization_function_interface* f, Scene_c3t3_item* item) + : f_(f), item_(item), rc_(), time_(0) {} virtual ~Optimizer_thread(); - Scene_c3t3_item* item() const { return f_->item(); } + // Scene item + Scene_c3t3_item* item() const { return item_; } + + // Infos about optimization CGAL::Mesh_optimization_return_code return_code() const { return rc_; } + double time() const { return time_; } + + // Logs + QString optimizer_name() const { return f_->name(); } + QStringList parameters_log() const { return f_->parameters_log(); } + +public slots: + // Stop + void stop(); + +signals: + // Emitted at the end of the process + void done(Optimizer_thread*); protected: - void run(); + // Overload of QThread function + virtual void run(); private: Optimization_function_interface* f_; + Scene_c3t3_item* item_; CGAL::Mesh_optimization_return_code rc_; + double time_; // in seconds }; -#endif // DEMO_MESH_3_OPTIMIZER_THREAD_H +#endif // DEMO_MESH_3_OPTIMIZER_THREAD_H \ No newline at end of file diff --git a/Mesh_3/include/CGAL/Mesh_optimization_return_code.h b/Mesh_3/include/CGAL/Mesh_optimization_return_code.h index 5e2b6963a95..58ee0ccaf27 100644 --- a/Mesh_3/include/CGAL/Mesh_optimization_return_code.h +++ b/Mesh_3/include/CGAL/Mesh_optimization_return_code.h @@ -28,6 +28,7 @@ namespace CGAL { enum Mesh_optimization_return_code { + MESH_OPTIMIZATION_UNKNOWN_ERROR=-1, BOUND_REACHED=0, TIME_LIMIT_REACHED, CANT_IMPROVE_ANYMORE,