From b62635e181f646d04dfdd28ad4f40877ae44c087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Tayeb?= Date: Tue, 15 Jun 2010 16:40:57 +0000 Subject: [PATCH] First step towards run of mesh optimization process in a separated thread. --- Mesh_3/demo/Mesh_3/CMakeLists.txt | 2 + .../Mesh_3/Mesh_3_optimization_plugin.cpp | 105 ++++++----- .../Mesh_3_optimization_plugin_cgal_code.cpp | 178 ++++++++++-------- Mesh_3/demo/Mesh_3/Optimizer_thread.cpp | 39 ++++ Mesh_3/demo/Mesh_3/Optimizer_thread.h | 62 ++++++ 5 files changed, 264 insertions(+), 122 deletions(-) create mode 100644 Mesh_3/demo/Mesh_3/Optimizer_thread.cpp create mode 100644 Mesh_3/demo/Mesh_3/Optimizer_thread.h diff --git a/Mesh_3/demo/Mesh_3/CMakeLists.txt b/Mesh_3/demo/Mesh_3/CMakeLists.txt index c957a99c93a..e0240bddb69 100644 --- a/Mesh_3/demo/Mesh_3/CMakeLists.txt +++ b/Mesh_3/demo/Mesh_3/CMakeLists.txt @@ -104,6 +104,7 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) qt4_automoc( Scene_segmented_image_item.cpp ) qt4_automoc( Scene_c3t3_item.cpp ) qt4_automoc( Scene_implicit_function_item.cpp ) + qt4_automoc( Optimizer_thread.cpp ) # put plugins (which are shared libraries) at the same location as # executable files @@ -237,6 +238,7 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) polyhedron_demo_plugin(mesh_3_optimization_plugin Mesh_3_optimization_plugin Mesh_3_optimization_plugin_cgal_code.cpp + Optimizer_thread.cpp Scene_c3t3_item.moc ${optimUI_FILES}) 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 86bb9f5ce9d..daee3bd1184 100644 --- a/Mesh_3/demo/Mesh_3/Mesh_3_optimization_plugin.cpp +++ b/Mesh_3/demo/Mesh_3/Mesh_3_optimization_plugin.cpp @@ -9,6 +9,8 @@ #include "Scene_c3t3_item.h" #include "C3t3_type.h" +#include "Optimizer_thread.h" + #include #include #include @@ -27,33 +29,29 @@ // declare the CGAL function -Scene_c3t3_item* cgal_code_odt_mesh_3(Scene_c3t3_item& c3t3_item, - const double time_limit, - const double convergence_ratio, - const double freeze_ratio, - const int max_iteration_number, - const bool create_new_item, - CGAL::Mesh_optimization_return_code& return_code); +Optimizer_thread* cgal_code_odt_mesh_3(Scene_c3t3_item& c3t3_item, + const double time_limit, + const double convergence_ratio, + const double freeze_ratio, + const int max_iteration_number, + const bool create_new_item); -Scene_c3t3_item* cgal_code_lloyd_mesh_3(Scene_c3t3_item& c3t3_item, - const double time_limit, - const double convergence_ratio, - const double freeze_ratio, - const int max_iteration_number, - const bool create_new_item, - CGAL::Mesh_optimization_return_code& return_code); +Optimizer_thread* cgal_code_lloyd_mesh_3(Scene_c3t3_item& c3t3_item, + const double time_limit, + const double convergence_ratio, + const double freeze_ratio, + const int max_iteration_number, + const bool create_new_item); -Scene_c3t3_item* cgal_code_perturb_mesh_3(Scene_c3t3_item& c3t3_item, - const double time_limit, - const double sliver_bound, - const bool create_new_item, - CGAL::Mesh_optimization_return_code& return_code); +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); -Scene_c3t3_item* cgal_code_exude_mesh_3(Scene_c3t3_item& c3t3_item, - const double time_limit, - const double sliver_bound, - const bool create_new_item, - CGAL::Mesh_optimization_return_code& return_code); +Optimizer_thread* cgal_code_exude_mesh_3(Scene_c3t3_item& c3t3_item, + const double time_limit, + const double sliver_bound, + const bool create_new_item); std::string translate(CGAL::Mesh_optimization_return_code rc); @@ -192,21 +190,24 @@ Mesh_3_optimization_plugin::odt() QTime timer; timer.start(); - CGAL::Mesh_optimization_return_code return_code; - Scene_c3t3_item* result_item = cgal_code_odt_mesh_3(*item, + Optimizer_thread* opt_thread = cgal_code_odt_mesh_3(*item, max_time, convergence, freeze, max_iteration_nb, - create_new_item, - return_code); + create_new_item); - if ( NULL == result_item ) + if ( NULL == opt_thread ) { QApplication::restoreOverrideCursor(); 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
" @@ -285,20 +286,23 @@ Mesh_3_optimization_plugin::lloyd() QTime timer; timer.start(); - CGAL::Mesh_optimization_return_code return_code; - Scene_c3t3_item* result_item = cgal_code_lloyd_mesh_3(*item, + Optimizer_thread* opt_thread = cgal_code_lloyd_mesh_3(*item, max_time, convergence, freeze, max_iteration_nb, - create_new_item, - return_code); + create_new_item); - if ( NULL == result_item ) + if ( NULL == opt_thread ) { QApplication::restoreOverrideCursor(); 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 " @@ -372,20 +376,23 @@ Mesh_3_optimization_plugin::perturb() QTime timer; timer.start(); - CGAL::Mesh_optimization_return_code return_code; - Scene_c3t3_item* result_item = cgal_code_perturb_mesh_3(*item, + Optimizer_thread* opt_thread = cgal_code_perturb_mesh_3(*item, max_time, sliver_bound, - create_new_item, - return_code); + create_new_item); - if ( NULL == result_item ) + if ( NULL == opt_thread ) { QApplication::restoreOverrideCursor(); 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
" @@ -450,18 +457,21 @@ Mesh_3_optimization_plugin::exude() QTime timer; timer.start(); - CGAL::Mesh_optimization_return_code return_code; - Scene_c3t3_item* result_item = cgal_code_exude_mesh_3(*item, + Optimizer_thread* opt_thread = cgal_code_exude_mesh_3(*item, max_time, sliver_bound, - create_new_item, - return_code); + create_new_item); - if ( NULL == result_item ) + if ( NULL == opt_thread ) { QApplication::restoreOverrideCursor(); 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 " @@ -494,6 +504,11 @@ treat_result(Scene_c3t3_item& source_item, if ( new_item_created ) { + const Scene_item::Bbox& bbox = result_item.bbox(); + result_item.setPosition((bbox.xmin + bbox.xmax)/2.f, + (bbox.ymin + bbox.ymax)/2.f, + (bbox.zmin + bbox.zmax)/2.f); + result_item.setColor(Qt::magenta); result_item.setRenderingMode(source_item.renderingMode()); result_item.set_data_item(source_item.data_item()); @@ -508,6 +523,8 @@ treat_result(Scene_c3t3_item& source_item, } else { + result_item.update_histogram(); + const Scene_interface::Item_id index = scene->mainSelectionIndex(); scene->itemChanged(index); } 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 cb1ec0fc570..e8c5d5269ae 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 @@ -6,6 +6,7 @@ #include "Scene_implicit_function_item.h" #include "implicit_functions/Implicit_function_interface.h" +#include "Optimizer_thread.h" #include #include @@ -15,18 +16,49 @@ #include namespace cgp = CGAL::parameters; -void treat_new_item(Scene_c3t3_item& new_item, const bool create_new_item); +// ----------------------------------- +// Optimization_function template class +// ----------------------------------- +template +class Optimization_function + : 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) {} + + virtual ~Optimization_function() + { + delete domain_; + } + + virtual CGAL::Mesh_optimization_return_code launch() const + { + return function_(item_->c3t3(), *domain_); + } + + virtual Scene_c3t3_item* item() const + { + return item_; + } + +private: + Scene_c3t3_item* item_; + Domain* domain_; + Function function_; +}; + // ----------------------------------- // Optimization generic function (responsible of dynamic casting) // ----------------------------------- template -Scene_c3t3_item* cgal_code_optimization(Scene_c3t3_item& c3t3_item, +Optimizer_thread* cgal_code_optimization(Scene_c3t3_item& c3t3_item, const Function& f, - const bool create_new_item, - CGAL::Mesh_optimization_return_code& return_code) + const bool create_new_item) { // Create result item Scene_c3t3_item* p_result_item = create_new_item ? @@ -54,14 +86,13 @@ Scene_c3t3_item* cgal_code_optimization(Scene_c3t3_item& c3t3_item, return NULL; } - Image_mesh_domain domain(*p_image, 1e-6); + Image_mesh_domain* p_domain = new Image_mesh_domain(*p_image, 1e-6); - // Launch - return_code = f(p_result_item, domain); + // Create thread + typedef Optimization_function Opt_function; + Opt_function* p_opt_function = new Opt_function(p_result_item, p_domain, f); - // Treat new item and exit - treat_new_item(*p_result_item, create_new_item); - return p_result_item; + return new Optimizer_thread(p_opt_function); } @@ -78,14 +109,13 @@ Scene_c3t3_item* cgal_code_optimization(Scene_c3t3_item& c3t3_item, return NULL; } - Mesh_domain domain(*p_poly); + Mesh_domain* p_domain = new Mesh_domain(*p_poly); - // Launch - return_code = f(p_result_item, domain); + // Create thread + typedef Optimization_function Opt_function; + Opt_function* p_opt_function = new Opt_function(p_result_item, p_domain, f); - // Treat new item and exit - treat_new_item(*p_result_item, create_new_item); - return p_result_item; + return new Optimizer_thread(p_opt_function); } // Function @@ -98,23 +128,21 @@ Scene_c3t3_item* cgal_code_optimization(Scene_c3t3_item& c3t3_item, const Implicit_function_interface* p_function = function_item->function(); if ( NULL == p_function ) { return NULL; } - CGAL::Bbox_3 domain_bbox (p_function->bbox().xmin, - p_function->bbox().ymin, - p_function->bbox().zmin, - p_function->bbox().xmax, - p_function->bbox().ymax, - p_function->bbox().zmax); + CGAL::Bbox_3 dom_bbox (p_function->bbox().xmin, + p_function->bbox().ymin, + p_function->bbox().zmin, + p_function->bbox().xmax, + p_function->bbox().ymax, + p_function->bbox().zmax); - Function_mesh_domain domain(Function_wrapper(*p_function), - domain_bbox, - 1e-7); + Function_mesh_domain* p_domain = + new Function_mesh_domain(Function_wrapper(*p_function), dom_bbox, 1e-7); - // Launch - return_code = f(p_result_item, domain); + // Create thread + typedef Optimization_function Opt_function; + Opt_function* p_opt_function = new Opt_function(p_result_item, p_domain, f); - // Treat new item and exit - treat_new_item(*p_result_item, create_new_item); - return p_result_item; + return new Optimizer_thread(p_opt_function); } return NULL; @@ -134,10 +162,10 @@ struct Odt_function template CGAL::Mesh_optimization_return_code - operator()(Scene_c3t3_item* p_item, const Domain& domain) const + operator()(C3t3& c3t3, const Domain& domain) const { // Odt - return CGAL::odt_optimize_mesh_3(p_item->c3t3(), + return CGAL::odt_optimize_mesh_3(c3t3, domain, cgp::time_limit = time_limit, cgp::convergence = convergence_ratio, @@ -147,14 +175,13 @@ struct Odt_function }; -Scene_c3t3_item* +Optimizer_thread* cgal_code_odt_mesh_3(Scene_c3t3_item& c3t3_item, const double time_limit, const double convergence_ratio, const double freeze_ratio, const int max_iteration_number, - const bool create_new_item, - CGAL::Mesh_optimization_return_code& return_code) + const bool create_new_item) { Odt_function f; f.time_limit = time_limit; @@ -162,7 +189,7 @@ cgal_code_odt_mesh_3(Scene_c3t3_item& c3t3_item, f.freeze_ratio = freeze_ratio; f.max_iteration_nb = max_iteration_number; - return cgal_code_optimization(c3t3_item, f, create_new_item, return_code); + return cgal_code_optimization(c3t3_item, f, create_new_item); } @@ -179,10 +206,10 @@ struct Lloyd_function template CGAL::Mesh_optimization_return_code - operator()(Scene_c3t3_item* p_item, const Domain& domain) const + operator()(C3t3& c3t3, const Domain& domain) const { // Lloyd - return CGAL::lloyd_optimize_mesh_3(p_item->c3t3(), + return CGAL::lloyd_optimize_mesh_3(c3t3, domain, cgp::time_limit = time_limit, cgp::convergence = convergence_ratio, @@ -192,14 +219,13 @@ struct Lloyd_function }; -Scene_c3t3_item* +Optimizer_thread* cgal_code_lloyd_mesh_3(Scene_c3t3_item& c3t3_item, const double time_limit, const double convergence_ratio, const double freeze_ratio, const int max_iteration_number, - const bool create_new_item, - CGAL::Mesh_optimization_return_code& return_code) + const bool create_new_item) { Lloyd_function f; f.time_limit = time_limit; @@ -207,7 +233,7 @@ cgal_code_lloyd_mesh_3(Scene_c3t3_item& c3t3_item, f.freeze_ratio = freeze_ratio; f.max_iteration_nb = max_iteration_number; - return cgal_code_optimization(c3t3_item, f, create_new_item, return_code); + return cgal_code_optimization(c3t3_item, f, create_new_item); } @@ -222,10 +248,10 @@ struct Perturb_function template CGAL::Mesh_optimization_return_code - operator()(Scene_c3t3_item* p_item, const Domain& domain) const + operator()(C3t3& c3t3, const Domain& domain) const { // Perturbation - return CGAL::perturb_mesh_3(p_item->c3t3(), + return CGAL::perturb_mesh_3(c3t3, domain, cgp::sliver_bound = sliver_bound, cgp::time_limit = time_limit); @@ -233,30 +259,44 @@ struct Perturb_function }; -Scene_c3t3_item* +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, - CGAL::Mesh_optimization_return_code& return_code) + const bool create_new_item) { Perturb_function f; f.sliver_bound = sliver_bound; f.time_limit = time_limit; - return cgal_code_optimization(c3t3_item, f, create_new_item, return_code); + return cgal_code_optimization(c3t3_item, f, create_new_item); } // ----------------------------------- // Exudation // ----------------------------------- -Scene_c3t3_item* +struct Exude_function +{ + double time_limit; + double sliver_bound; + + CGAL::Mesh_optimization_return_code + operator()(C3t3& c3t3, int) const + { + // Perturbation + return CGAL::exude_mesh_3(c3t3, + cgp::sliver_bound = sliver_bound, + cgp::time_limit = time_limit); + } +}; + + +Optimizer_thread* cgal_code_exude_mesh_3(Scene_c3t3_item& c3t3_item, const double time_limit, const double sliver_bound, - const bool create_new_item, - CGAL::Mesh_optimization_return_code& return_code) + const bool create_new_item) { // Create result item Scene_c3t3_item* p_result_item = create_new_item ? @@ -268,31 +308,13 @@ cgal_code_exude_mesh_3(Scene_c3t3_item& c3t3_item, } // Exudation - return_code = CGAL::exude_mesh_3(p_result_item->c3t3(), - cgp::sliver_bound = sliver_bound, - cgp::time_limit = time_limit); + Exude_function f; + f.sliver_bound = sliver_bound; + f.time_limit = time_limit; + + // Create thread + typedef Optimization_function Opt_function; + Opt_function* p_opt_function = new Opt_function(p_result_item, NULL, f); - // Treat result and exit - treat_new_item(*p_result_item, create_new_item); - return p_result_item; -} - - - -// ----------------------------------- -// Helper functions -// ----------------------------------- -void treat_new_item(Scene_c3t3_item& new_item, const bool create_new_item) -{ - if ( create_new_item ) - { - const Scene_item::Bbox& bbox = new_item.bbox(); - new_item.setPosition((bbox.xmin + bbox.xmax)/2.f, - (bbox.ymin + bbox.ymax)/2.f, - (bbox.zmin + bbox.zmax)/2.f); - } - else - { - new_item.update_histogram(); - } -} + return new Optimizer_thread(p_opt_function); +} \ 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 new file mode 100644 index 00000000000..87677db643e --- /dev/null +++ b/Mesh_3/demo/Mesh_3/Optimizer_thread.cpp @@ -0,0 +1,39 @@ +// Copyright (c) 2010 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Stephane Tayeb +// +//****************************************************************************** +// File Description : +//****************************************************************************** + +#include "Optimizer_thread.h" + +Optimizer_thread::~Optimizer_thread() +{ + delete f_; +} + + +void +Optimizer_thread:: +run() +{ + rc_ = f_->launch(); +} + +#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 new file mode 100644 index 00000000000..b9b5069eeb2 --- /dev/null +++ b/Mesh_3/demo/Mesh_3/Optimizer_thread.h @@ -0,0 +1,62 @@ +// Copyright (c) 2010 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Stephane Tayeb +// +//****************************************************************************** +// File Description : +//****************************************************************************** + +#ifndef DEMO_MESH_3_OPTIMIZER_THREAD_H +#define DEMO_MESH_3_OPTIMIZER_THREAD_H + +#include +#include + +#include + +class Scene_c3t3_item; + +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; +}; + +class Optimizer_thread : public QThread +{ + Q_OBJECT +public: + Optimizer_thread(Optimization_function_interface* f) + : f_(f), rc_() {} + + virtual ~Optimizer_thread(); + + Scene_c3t3_item* item() const { return f_->item(); } + CGAL::Mesh_optimization_return_code return_code() const { return rc_; } + +protected: + void run(); + +private: + Optimization_function_interface* f_; + CGAL::Mesh_optimization_return_code rc_; +}; + +#endif // DEMO_MESH_3_OPTIMIZER_THREAD_H