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,