First step towards run of mesh optimization process in a separated thread.

This commit is contained in:
Stéphane Tayeb 2010-06-15 16:40:57 +00:00
parent 35f93ec7fb
commit b62635e181
5 changed files with 264 additions and 122 deletions

View File

@ -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})

View File

@ -9,6 +9,8 @@
#include "Scene_c3t3_item.h"
#include "C3t3_type.h"
#include "Optimizer_thread.h"
#include <QObject>
#include <QAction>
#include <QMainWindow>
@ -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<br>"
@ -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<br>"
@ -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);
}

View File

@ -6,6 +6,7 @@
#include "Scene_implicit_function_item.h"
#include "implicit_functions/Implicit_function_interface.h"
#include "Optimizer_thread.h"
#include <CGAL/optimize_mesh_3.h>
#include <CGAL/Bbox_3.h>
@ -15,18 +16,49 @@
#include <CGAL/Timer.h>
namespace cgp = CGAL::parameters;
void treat_new_item(Scene_c3t3_item& new_item, const bool create_new_item);
// -----------------------------------
// Optimization_function template class
// -----------------------------------
template <typename Domain, typename Function>
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 <typename Function>
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<Image_mesh_domain,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<Mesh_domain,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<Function_mesh_domain,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 <typename Domain>
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 <typename Domain>
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 <typename Domain>
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<int,Exude_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);
}

View File

@ -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"

View File

@ -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 <QThread>
#include <QObject>
#include <CGAL/Mesh_optimization_return_code.h>
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