Mesh_3_demo:

+ A window now pops-up during meshing (with a 'stop' button)
This commit is contained in:
Stéphane Tayeb 2010-06-18 13:06:08 +00:00
parent cb510c9856
commit 8e01b3cd32
15 changed files with 761 additions and 448 deletions

View File

@ -64,13 +64,13 @@ public:
}
typedef CGAL::Mesh_3::Robust_intersection_traits_3<Kernel> RKernel;
typedef CGAL::Polyhedral_mesh_domain_3<Polyhedron,RKernel> Mesh_domain;
typedef CGAL::Polyhedral_mesh_domain_3<Polyhedron,RKernel> Polyhedral_mesh_domain;
typedef CGAL::Labeled_image_mesh_domain_3<Image,Kernel> Image_mesh_domain;
typedef Wrapper<Kernel> Function_wrapper;
typedef CGAL::Mesh_3::Labeled_mesh_domain_3<Function_wrapper, Kernel> Function_mesh_domain;
// Triangulation
typedef CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
typedef CGAL::Mesh_triangulation_3<Polyhedral_mesh_domain>::type Tr;
// 3D complex
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;

View File

@ -105,6 +105,7 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
qt4_automoc( Scene_c3t3_item.cpp )
qt4_automoc( Scene_implicit_function_item.cpp )
qt4_automoc( Optimizer_thread.cpp )
qt4_automoc( Meshing_thread.cpp )
# put plugins (which are shared libraries) at the same location as
# executable files
@ -224,6 +225,7 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
Mesh_3_plugin_polyhedron_cgal_code.cpp
Mesh_3_plugin_image_cgal_code.cpp
Mesh_3_plugin_implicit_function_cgal_code.cpp
Meshing_thread.cpp
Scene_c3t3_item.moc
${meshingUI_FILES})

View File

@ -114,10 +114,10 @@ Optimizer_thread* cgal_code_optimization(Scene_c3t3_item& c3t3_item,
return NULL;
}
Mesh_domain* p_domain = new Mesh_domain(*p_poly);
Polyhedral_mesh_domain* p_domain = new Polyhedral_mesh_domain(*p_poly);
// Create thread
typedef Optimization_function<Mesh_domain,Parameters> Opt_function;
typedef Optimization_function<Polyhedral_mesh_domain,Parameters> Opt_function;
Opt_function* p_opt_function = new Opt_function(p_result_item->c3t3(), p_domain, param);
return new Optimizer_thread(p_opt_function, p_result_item);

View File

@ -1,5 +1,5 @@
#include "config.h"
#ifdef CGAL_POLYHEDRON_DEMO_USE_SURFACE_MESHER
#include <CGAL_demo/Plugin_helper.h>
#include <CGAL_demo/Plugin_interface.h>
#include <CGAL_demo/Messages_interface.h>
@ -9,63 +9,54 @@
#include <QAction>
#include <QMainWindow>
#include <QApplication>
#include <QtPlugin>
#include <QMessageBox>
#include <QInputDialog>
#include <QFileDialog>
#include <QTimer>
#include "Scene_polyhedron_item.h"
#include "Scene_segmented_image_item.h"
#include "Scene_implicit_function_item.h"
#include "implicit_functions/Implicit_function_interface.h"
#include "Scene_c3t3_item.h"
#include "Image_type.h"
#include "Polyhedron_type.h"
#include "Scene_c3t3_item.h"
#include "Meshing_thread.h"
#include <iostream>
#include <fstream>
#include <math.h>
// Constants
const QColor default_mesh_color(45,169,70);
// declare the CGAL function
Scene_c3t3_item* cgal_code_mesh_3(const Polyhedron*,
QString filename,
const double angle,
const double sizing,
const double approx,
const double tets_sizing,
const double tet_shape,
const bool lloyd,
const bool odt,
const bool perturb,
const bool exude);
Meshing_thread* cgal_code_mesh_3(const Polyhedron*,
const double angle,
const double sizing,
const double approx,
const double tets_sizing,
const double tet_shape);
Scene_c3t3_item* cgal_code_mesh_3(const Image*,
QString filename,
const double angle,
const double sizing,
const double approx,
const double tets_sizing,
const double tet_shape,
const bool lloyd,
const bool odt,
const bool perturb,
const bool exude);
Meshing_thread* cgal_code_mesh_3(const Image*,
const double angle,
const double sizing,
const double approx,
const double tets_sizing,
const double tet_shape);
Scene_c3t3_item* cgal_code_mesh_3(const Implicit_function_interface*,
QString filename,
const double angle,
const double sizing,
const double approx,
const double tets_sizing,
const double tet_shape,
const bool lloyd,
const bool odt,
const bool perturb,
const bool exude);
Meshing_thread* cgal_code_mesh_3(const Implicit_function_interface*,
const double angle,
const double sizing,
const double approx,
const double tets_sizing,
const double tet_shape);
double get_approximate(double d, int precision, int& decimals);
class Mesh_3_plugin :
public QObject,
protected Plugin_helper
@ -73,6 +64,8 @@ class Mesh_3_plugin :
Q_OBJECT
Q_INTERFACES(Plugin_interface);
public:
Mesh_3_plugin();
virtual void init(QMainWindow* mainWindow,
Scene_interface* scene_interface,
Messages_interface* msg_interface)
@ -92,20 +85,40 @@ public:
{
return QList<QAction*>() << actionMesh_3;
}
public slots:
void mesh_3();
void meshing_done(Meshing_thread* t);
private:
void launch_thread(Meshing_thread* mesh_thread);
void treat_result(Scene_item& source_item, Scene_c3t3_item& result_item) const;
private:
QAction* actionMesh_3;
Messages_interface* msg;
QMessageBox* message_box_;
Scene_item* source_item_;
}; // end class Mesh_3_plugin
Mesh_3_plugin::
Mesh_3_plugin()
: actionMesh_3(NULL)
, msg(NULL)
, message_box_(NULL)
, source_item_(NULL)
{
}
void Mesh_3_plugin::mesh_3()
{
const Scene_interface::Item_id index = scene->mainSelectionIndex();
Scene_item* item = 0;
// -----------------------------------
// Check if selected item is meshable
// -----------------------------------
Scene_polyhedron_item* poly_item =
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
Scene_segmented_image_item* image_item =
@ -113,171 +126,221 @@ void Mesh_3_plugin::mesh_3()
Scene_implicit_function_item* function_item =
qobject_cast<Scene_implicit_function_item*>(scene->item(index));
if(poly_item)
{
item = poly_item;
Polyhedron* pMesh = poly_item->polyhedron();
if(!pMesh) return;
}
else if(image_item)
{
item = image_item;
const Image* image = image_item->image();
if(!image) return;
}
else if(function_item)
{
item = function_item;
const Implicit_function_interface* function = function_item->function();
if(!function) return;
}
// Get item
Scene_item* item = NULL;
if( NULL != poly_item ) { item = poly_item; }
else if( NULL != image_item ) { item = image_item; }
else if( NULL != function_item ) { item = function_item; }
if(item) {
// TODO: get parameters using ONE dialog box
// sizing and approximation parameters should be expressed as ratio of
// scene bbox diagonal.
if ( NULL == item )
{
QMessageBox::critical(mw,tr(""),
tr("Selected object can't be meshed"));
return;
}
// -----------------------------------
// Create Mesh dialog
// -----------------------------------
QDialog dialog(mw);
Ui::Meshing_dialog ui;
ui.setupUi(&dialog);
connect(ui.buttonBox, SIGNAL(accepted()),
&dialog, SLOT(accept()));
connect(ui.buttonBox, SIGNAL(rejected()),
&dialog, SLOT(reject()));
QDialog dialog(mw);
Ui::Meshing_dialog ui;
ui.setupUi(&dialog);
connect(ui.buttonBox, SIGNAL(accepted()),
&dialog, SLOT(accept()));
connect(ui.buttonBox, SIGNAL(rejected()),
&dialog, SLOT(reject()));
Scene_interface::Bbox bbox = item->bbox();
ui.objectName->setText(item->name());
ui.objectNameSize->setText(tr("Object bbox size (w,h,d): <b>%1</b>, <b>%2</b>, <b>%3</b>")
.arg(bbox.width(),0,'g',3)
.arg(bbox.height(),0,'g',3)
.arg(bbox.depth(),0,'g',3) );
double diag = bbox.diagonal_length();
int decimals = 0;
double sizing_default = get_approximate(diag * 0.05, 2, decimals);
ui.facetSizing->setDecimals(-decimals+2);
ui.facetSizing->setSingleStep(std::pow(10.,decimals));
ui.facetSizing->setRange(diag * 10e-6, // min
diag); // max
ui.facetSizing->setValue(sizing_default); // default value
ui.tetSizing->setDecimals(-decimals+2);
ui.tetSizing->setSingleStep(std::pow(10.,decimals));
ui.tetSizing->setRange(diag * 10e-6, // min
Scene_interface::Bbox bbox = item->bbox();
ui.objectName->setText(item->name());
ui.objectNameSize->setText(tr("Object bbox size (w,h,d): <b>%1</b>, <b>%2</b>, <b>%3</b>")
.arg(bbox.width(),0,'g',3)
.arg(bbox.height(),0,'g',3)
.arg(bbox.depth(),0,'g',3) );
double diag = bbox.diagonal_length();
int decimals = 0;
double sizing_default = get_approximate(diag * 0.05, 2, decimals);
ui.facetSizing->setDecimals(-decimals+2);
ui.facetSizing->setSingleStep(std::pow(10.,decimals));
ui.facetSizing->setRange(diag * 10e-6, // min
diag); // max
ui.tetSizing->setValue(sizing_default); // default value
ui.facetSizing->setValue(sizing_default); // default value
ui.tetSizing->setDecimals(-decimals+2);
ui.tetSizing->setSingleStep(std::pow(10.,decimals));
ui.tetSizing->setRange(diag * 10e-6, // min
diag); // max
ui.tetSizing->setValue(sizing_default); // default value
double approx_default = get_approximate(diag * 0.005, 2, decimals);
ui.approx->setDecimals(-decimals+2);
ui.approx->setSingleStep(std::pow(10.,decimals));
ui.approx->setRange(diag * 10e-7, // min
diag); // max
ui.approx->setValue(approx_default);
// -----------------------------------
// Get values
// -----------------------------------
int i = dialog.exec();
if( i == QDialog::Rejected ) { return; }
// 0 means parameter is not considered
const double angle = !ui.noAngle->isChecked() ? 0 : ui.facetAngle->value();
const double approx = !ui.noApprox->isChecked() ? 0 : ui.approx->value();
const double facet_sizing = !ui.noFacetSizing->isChecked() ? 0 : ui.facetSizing->value();
const double radius_edge = !ui.noTetShape->isChecked() ? 0 : ui.tetShape->value();
const double tet_sizing = !ui.noTetSizing->isChecked() ? 0 : ui.tetSizing->value();
double approx_default = get_approximate(diag * 0.005, 2, decimals);
ui.approx->setDecimals(-decimals+2);
ui.approx->setSingleStep(std::pow(10.,decimals));
ui.approx->setRange(diag * 10e-7, // min
diag); // max
ui.approx->setValue(approx_default);
int i = dialog.exec();
if(i == QDialog::Rejected)
return;
// 0 means parameter is not considered
const double angle = !ui.noAngle->isChecked() ? 0 : ui.facetAngle->value();
const double approx = !ui.noApprox->isChecked() ? 0 : ui.approx->value();
const double facet_sizing = !ui.noFacetSizing->isChecked() ? 0 : ui.facetSizing->value();
const double radius_edge = !ui.noTetShape->isChecked() ? 0 : ui.tetShape->value();
const double tet_sizing = !ui.noTetSizing->isChecked() ? 0 : ui.tetSizing->value();
const bool lloyd = ui.lloydCBox->isChecked();
const bool odt = ui.odtCBox->isChecked();
const bool perturb = ui.perturbCBox->isChecked();
const bool exude = ui.exudeCBox->isChecked();
// Controls
if ( lloyd && odt )
// -----------------------------------
// Dispatch mesh process
// -----------------------------------
QApplication::setOverrideCursor(Qt::WaitCursor);
Meshing_thread* thread = NULL;
// Polyhedron
if ( NULL != poly_item )
{
Polyhedron* pMesh = poly_item->polyhedron();
if( NULL == pMesh )
{
QMessageBox::critical(mw,tr(""),
tr("Wrong parameters: Odt and Lloyd can't be run at the same time"));
QMessageBox::critical(mw,tr(""),tr("ERROR: no data in selected item"));
return;
}
QApplication::setOverrideCursor(Qt::WaitCursor);
QTime timer;
timer.start();
Scene_c3t3_item* result_item = 0;
if(poly_item) {
Polyhedron* pMesh = poly_item->polyhedron();
if(!pMesh) return;
result_item = cgal_code_mesh_3(pMesh,
item->name(),
angle,
facet_sizing,
approx,
tet_sizing,
radius_edge,
lloyd, odt, perturb, exude);
}
else if(image_item)
{
const Image* pImage = image_item->image();
if(!pImage) return;
result_item = cgal_code_mesh_3(pImage,
item->name(),
angle,
facet_sizing,
approx,
tet_sizing,
radius_edge,
lloyd, odt, perturb, exude);
}
else if(function_item)
{
const Implicit_function_interface* function = function_item->function();
if(!function) return;
result_item = cgal_code_mesh_3(function,
item->name(),
angle,
facet_sizing,
approx,
tet_sizing,
radius_edge,
lloyd, odt, perturb, exude);
}
std::stringstream sstr;
sstr << "Meshing file \"" << qPrintable(item->name()) << "\" done in "
<< timer.elapsed()/1000. << "s<br>"
<< "( facet angle: " << angle << " )<br>"
<< "( facets size bound: " << facet_sizing << " )<br>"
<< "( approximation bound: " << approx << " )<br>"
<< "( tetrahedra size bound: " << tet_sizing << " )<br>"
<< "( tetrahedra radius-edge: " << radius_edge << " )<br>";
msg->information(sstr.str().c_str());
if (result_item)
{
result_item->setName(tr("%1 3d mesh(%2 %3 %4)")
.arg(item->name())
.arg(facet_sizing)
.arg(tet_sizing)
.arg(approx));
result_item->setColor(QColor(45,169,70));
result_item->setRenderingMode(item->renderingMode());
result_item->set_data_item(item);
item->setVisible(false);
scene->itemChanged(index);
Scene_interface::Item_id new_item_id = scene->addItem(result_item);
scene->setSelectedItem(new_item_id);
}
QApplication::restoreOverrideCursor();
thread = cgal_code_mesh_3(pMesh,
angle, facet_sizing, approx,
tet_sizing, radius_edge);
}
// Image
else if( NULL != image_item )
{
const Image* pImage = image_item->image();
if( NULL == pImage )
{
QMessageBox::critical(mw,tr(""),tr("ERROR: no data in selected item"));
return;
}
thread = cgal_code_mesh_3(pImage,
angle, facet_sizing, approx,
tet_sizing, radius_edge);
}
// Function
else if( NULL != function_item )
{
const Implicit_function_interface* pFunction = function_item->function();
if( NULL == pFunction )
{
QMessageBox::critical(mw,tr(""),tr("ERROR: no data in selected item"));
return;
}
thread = cgal_code_mesh_3(pFunction,
angle, facet_sizing, approx,
tet_sizing, radius_edge);
}
if ( NULL == thread )
{
QMessageBox::critical(mw,tr(""),tr("ERROR: no thread created"));
return;
}
// Launch thread
source_item_ = item;
launch_thread(thread);
QApplication::restoreOverrideCursor();
}
void
Mesh_3_plugin::
launch_thread(Meshing_thread* mesh_thread)
{
// -----------------------------------
// Create message box with stop button
// -----------------------------------
message_box_ = new QMessageBox(QMessageBox::NoIcon,
"Meshing",
"Mesh generation in progress...",
QMessageBox::Cancel,
mw);
message_box_->setDefaultButton(QMessageBox::Cancel);
QAbstractButton* cancelButton = message_box_->button(QMessageBox::Cancel);
cancelButton->setText(tr("Stop"));
QObject::connect(cancelButton, SIGNAL(clicked()),
mesh_thread, SLOT(stop()));
message_box_->show();
// -----------------------------------
// Connect main thread to optimization thread and launch optimizer
// -----------------------------------
QObject::connect(mesh_thread, SIGNAL(done(Meshing_thread*)),
this, SLOT(meshing_done(Meshing_thread*)));
mesh_thread->start();
}
void
Mesh_3_plugin::
meshing_done(Meshing_thread* thread)
{
// Print message in console
QString str = QString("Meshing of \"%1\" done in %2s<br>")
.arg(source_item_->name())
.arg(thread->time());
Q_FOREACH( QString param, thread->parameters_log() )
{
str.append(QString("( %1 )<br>").arg(param));
}
msg->information(qPrintable(str));
// Treat new c3t3 item
Scene_c3t3_item* result_item = thread->item();
treat_result(*source_item_, *result_item);
// close message box
message_box_->close();
// free memory
delete thread;
}
void
Mesh_3_plugin::
treat_result(Scene_item& source_item,
Scene_c3t3_item& result_item) const
{
result_item.setName(tr("%1 [3D Mesh]").arg(source_item.name()));
// If a new item has been 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(default_mesh_color);
result_item.setRenderingMode(source_item.renderingMode());
result_item.set_data_item(&source_item);
source_item.setVisible(false);
const Scene_interface::Item_id index = scene->mainSelectionIndex();
scene->itemChanged(index);
Scene_interface::Item_id new_item_id = scene->addItem(&result_item);
scene->setSelectedItem(new_item_id);
}
@ -299,5 +362,3 @@ get_approximate(double d, int precision, int& decimals)
Q_EXPORT_PLUGIN2(Mesh_3_plugin, Mesh_3_plugin);
#include "Mesh_3_plugin.moc"
#endif // CGAL_POLYHEDRON_DEMO_USE_SURFACE_MESHER

View File

@ -1,86 +1,34 @@
//#define CGAL_MESH_3_VERBOSE
#include "C3t3_type.h"
#include "Scene_c3t3_item.h"
#include <CGAL/Mesh_criteria_3.h>
#include "Image_type.h"
#include "Meshing_thread.h"
#include "Mesh_function.h"
#include <CGAL/Labeled_image_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h>
#include <fstream>
#include <CGAL/Timer.h>
#include <CGAL/Bbox_3.h>
// Mesh Criteria
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
typedef Mesh_criteria::Facet_criteria Facet_criteria;
typedef Mesh_criteria::Cell_criteria Cell_criteria;
typedef Tr::Point Point_3;
Scene_c3t3_item* cgal_code_mesh_3(const Image* pImage,
const QString filename,
const double angle,
const double sizing,
const double approx,
const double tets_sizing,
const double tet_shape,
const bool lloyd,
const bool odt,
const bool perturb,
const bool exude)
Meshing_thread* cgal_code_mesh_3(const Image* pImage,
const double facet_angle,
const double facet_sizing,
const double facet_approx,
const double tet_sizing,
const double tet_shape)
{
if(!pImage) return 0;
// remesh
typedef Tr::Geom_traits GT;
// Set mesh criteria
Facet_criteria facet_criteria(angle, sizing, approx); // angle, size, approximation
Cell_criteria cell_criteria(tet_shape, tets_sizing); // radius-edge ratio, size
Mesh_criteria criteria(facet_criteria, cell_criteria);
Image_mesh_domain domain(*pImage, 1e-6);
CGAL::Timer timer;
timer.start();
std::cerr << "Meshing file \"" << qPrintable(filename) << "\"\n";
std::cerr << " facet angle: " << angle << std::endl
<< " facets size bound: " << sizing << std::endl
<< " approximation bound: " << approx << std::endl
<< " tetrahedra size bound: " << tets_sizing << std::endl
<< " tetrahedra radius-edge: " << tet_shape << std::endl;
// Meshing
std::cerr << "Mesh...";
typedef Mesh_function<Image_mesh_domain> Mesh_function;
namespace cgp = CGAL::parameters;
namespace cgpi = cgp::internal;
if( NULL == pImage ) { return NULL; }
cgpi::Lloyd_options lloyd_obj = lloyd ? cgp::lloyd() : cgp::no_lloyd();
cgpi::Odt_options odt_obj = odt ? cgp::odt() : cgp::no_odt();
cgpi::Perturb_options perturb_obj = perturb ? cgp::perturb() : cgp::no_perturb();
cgpi::Exude_options exude_obj = exude ? cgp::exude() : cgp::no_exude();
Image_mesh_domain* p_domain = new Image_mesh_domain(*pImage, 1e-6);
Scene_c3t3_item* new_item =
new Scene_c3t3_item(CGAL::make_mesh_3<C3t3>(domain, criteria,
lloyd_obj, odt_obj, perturb_obj, exude_obj));
std::cerr << "done (" << timer.time() << " s, "
<< new_item->c3t3().triangulation().number_of_vertices() << " vertices)" << std::endl;
if(new_item->c3t3().triangulation().number_of_vertices() > 0)
{
std::ofstream medit_out("out.mesh");
new_item->c3t3().output_to_medit(medit_out);
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);
return new_item;
}
else {
delete new_item;
return 0;
}
}
Scene_c3t3_item* p_new_item = new Scene_c3t3_item();
Mesh_parameters param;
param.facet_angle = facet_angle;
param.facet_sizing = facet_sizing;
param.facet_approx = facet_approx;
param.tet_sizing = tet_sizing;
param.tet_shape = tet_shape;
Mesh_function* p_mesh_function = new Mesh_function(p_new_item->c3t3(), p_domain, param);
return new Meshing_thread(p_mesh_function, p_new_item);
}

View File

@ -1,44 +1,22 @@
//#define CGAL_MESH_3_VERBOSE
#include "C3t3_type.h"
#include "Scene_c3t3_item.h"
#include "implicit_functions/Implicit_function_interface.h"
#include <CGAL/Mesh_criteria_3.h>
#include <CGAL/make_mesh_3.h>
#include "Meshing_thread.h"
#include "Mesh_function.h"
#include <CGAL/Bbox_3.h>
#include <fstream>
#include <CGAL/Timer.h>
// Mesh Criteria
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
typedef Mesh_criteria::Facet_criteria Facet_criteria;
typedef Mesh_criteria::Cell_criteria Cell_criteria;
typedef Tr::Point Point_3;
Scene_c3t3_item* cgal_code_mesh_3(const Implicit_function_interface* pfunction,
const QString filename,
const double angle,
const double sizing,
const double approx,
const double tets_sizing,
const double tet_shape,
const bool lloyd,
const bool odt,
const bool perturb,
const bool exude)
Meshing_thread* cgal_code_mesh_3(const Implicit_function_interface* pfunction,
const double facet_angle,
const double facet_sizing,
const double facet_approx,
const double tet_sizing,
const double tet_shape)
{
if( pfunction == NULL ) { return NULL; }
typedef Mesh_function<Function_mesh_domain> Mesh_function;
typedef Tr::Geom_traits GT;
// Set mesh criteria
Facet_criteria facet_criteria(angle, sizing, approx); // angle, size, approximation
Cell_criteria cell_criteria(tet_shape, tets_sizing); // radius-edge ratio, size
Mesh_criteria criteria(facet_criteria, cell_criteria);
if( pfunction == NULL ) { return NULL; }
CGAL::Bbox_3 domain_bbox (pfunction->bbox().xmin,
pfunction->bbox().ymin,
@ -47,51 +25,18 @@ Scene_c3t3_item* cgal_code_mesh_3(const Implicit_function_interface* pfunction,
pfunction->bbox().ymax,
pfunction->bbox().zmax);
Function_mesh_domain domain(Function_wrapper(*pfunction), domain_bbox, 1e-7);
CGAL::Timer timer;
timer.start();
std::cerr << "Meshing file \"" << qPrintable(filename) << "\"\n";
std::cerr << " facet angle: " << angle << std::endl
<< " facets size bound: " << sizing << std::endl
<< " approximation bound: " << approx << std::endl
<< " tetrahedra size bound: " << tets_sizing << std::endl
<< " tetrahedra radius-edge: " << tet_shape << std::endl;
// Meshing
std::cerr << "Mesh...";
Function_mesh_domain* p_domain =
new Function_mesh_domain(Function_wrapper(*pfunction), domain_bbox, 1e-7);
namespace cgp = CGAL::parameters;
namespace cgpi = cgp::internal;
Scene_c3t3_item* p_new_item = new Scene_c3t3_item();
cgpi::Lloyd_options lloyd_obj = lloyd ? cgp::lloyd() : cgp::no_lloyd();
cgpi::Odt_options odt_obj = odt ? cgp::odt() : cgp::no_odt();
cgpi::Perturb_options perturb_obj = perturb ? cgp::perturb() : cgp::no_perturb();
cgpi::Exude_options exude_obj = exude ? cgp::exude() : cgp::no_exude();
Mesh_parameters param;
param.facet_angle = facet_angle;
param.facet_sizing = facet_sizing;
param.facet_approx = facet_approx;
param.tet_sizing = tet_sizing;
param.tet_shape = tet_shape;
Scene_c3t3_item* new_item =
new Scene_c3t3_item(CGAL::make_mesh_3<C3t3>(domain, criteria,
lloyd_obj, odt_obj, perturb_obj, exude_obj));
//
// Scene_c3t3_item* new_item =
// new Scene_c3t3_item(CGAL::make_mesh_3<C3t3>(domain, criteria,
// cgp::no_lloyd(),
// cgp::no_odt(),
// cgp::no_perturb(),
// cgp::no_exude()));
std::cerr << "done (" << timer.time() << " s, "
<< new_item->c3t3().triangulation().number_of_vertices() << " vertices)" << std::endl;
if(new_item->c3t3().triangulation().number_of_vertices() > 0)
{
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);
return new_item;
}
else {
delete new_item;
return 0;
}
}
Mesh_function* p_mesh_function = new Mesh_function(p_new_item->c3t3(), p_domain, param);
return new Meshing_thread(p_mesh_function, p_new_item);
}

View File

@ -1,89 +1,34 @@
//#define CGAL_MESH_3_VERBOSE
#include "C3t3_type.h"
#include "Scene_c3t3_item.h"
#include <CGAL/Mesh_criteria_3.h>
#include "Polyhedron_type.h"
#include "Meshing_thread.h"
#include "Mesh_function.h"
#include <CGAL/Polyhedral_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h>
#include <fstream>
#include <CGAL/Timer.h>
#include <CGAL/Bbox_3.h>
// Mesh Criteria
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
typedef Mesh_criteria::Facet_criteria Facet_criteria;
typedef Mesh_criteria::Cell_criteria Cell_criteria;
typedef Tr::Point Point_3;
Scene_c3t3_item* cgal_code_mesh_3(const Polyhedron* pMesh,
const QString filename,
const double angle,
const double sizing,
const double approx,
const double tet_sizing,
const double tet_shape,
const bool lloyd,
const bool odt,
const bool perturb,
const bool exude)
Meshing_thread* cgal_code_mesh_3(const Polyhedron* pMesh,
const double facet_angle,
const double facet_sizing,
const double facet_approx,
const double tet_sizing,
const double tet_shape)
{
if(!pMesh) return 0;
// remesh
typedef Tr::Geom_traits GT;
// Set mesh criteria
Facet_criteria facet_criteria(angle, sizing, approx); // angle, size, approximation
Cell_criteria cell_criteria(tet_shape, tet_sizing); // radius-edge ratio, size
Mesh_criteria criteria(facet_criteria, cell_criteria);
CGAL::Timer timer;
timer.start();
std::cerr << "Meshing file \"" << qPrintable(filename) << "\"\n";
std::cerr << " angle: " << angle << std::endl
<< " facets size bound: " << sizing << std::endl
<< " approximation bound: " << approx << std::endl
<< " tetrahedra size bound: " << tet_sizing << std::endl
<< " tetrahedron radius-edge: " << tet_shape << std::endl;
std::cerr << "Build AABB tree...";
// Create domain
Mesh_domain domain(*pMesh);
std::cerr << "done (" << timer.time() << " s)" << std::endl;
// Meshing
timer.stop();timer.reset();timer.start();
std::cerr << "Mesh...";
typedef Mesh_function<Polyhedral_mesh_domain> Mesh_function;
namespace cgp = CGAL::parameters;
namespace cgpi = cgp::internal;
if( NULL == pMesh ) { return NULL; }
cgpi::Lloyd_options lloyd_obj = lloyd ? cgp::lloyd() : cgp::no_lloyd();
cgpi::Odt_options odt_obj = odt ? cgp::odt() : cgp::no_odt();
cgpi::Perturb_options perturb_obj = perturb ? cgp::perturb() : cgp::no_perturb();
cgpi::Exude_options exude_obj = exude ? cgp::exude() : cgp::no_exude();
Polyhedral_mesh_domain* p_domain = new Polyhedral_mesh_domain(*pMesh);
Scene_c3t3_item* new_item = new Scene_c3t3_item(
CGAL::make_mesh_3<C3t3>(domain, criteria, lloyd_obj, odt_obj, perturb_obj, exude_obj));
Scene_c3t3_item* p_new_item = new Scene_c3t3_item();
std::cerr << "done (" << timer.time() << " s, "
<< new_item->c3t3().triangulation().number_of_vertices() << " vertices)" << std::endl;
if(new_item->c3t3().triangulation().number_of_vertices() > 0)
{
std::ofstream medit_out("out.mesh");
new_item->c3t3().output_to_medit(medit_out);
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);
return new_item;
}
else {
delete new_item;
return 0;
}
}
Mesh_parameters param;
param.facet_angle = facet_angle;
param.facet_sizing = facet_sizing;
param.facet_approx = facet_approx;
param.tet_sizing = tet_sizing;
param.tet_shape = tet_shape;
Mesh_function* p_mesh_function = new Mesh_function(p_new_item->c3t3(), p_domain, param);
return new Meshing_thread(p_mesh_function, p_new_item);
}

View File

@ -0,0 +1,185 @@
// 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 CGAL_DEMO_MESH_3_MESH_FUNCTION_H
#define CGAL_DEMO_MESH_3_MESH_FUNCTION_H
#include <QStringList>
#include <CGAL/Mesh_3/Mesher_3.h>
#include <CGAL/Mesh_criteria_3.h>
#include "C3t3_type.h"
#include "Meshing_thread.h"
struct Mesh_parameters
{
double facet_angle;
double facet_sizing;
double facet_approx;
double tet_shape;
double tet_sizing;
inline QStringList log() const;
};
template < typename Domain_ >
class Mesh_function
: public Mesh_function_interface
{
typedef Domain_ Domain;
public:
Mesh_function(C3t3& c3t3, Domain* domain, const Mesh_parameters& p);
~Mesh_function();
// Launch
virtual void launch();
// Stop
virtual void stop();
// Logs
virtual QStringList parameters_log() const;
private:
C3t3& c3t3_;
Domain* domain_;
Mesh_parameters p_;
bool continue_;
};
// -----------------------------------
// Class Mesh_parameters
// -----------------------------------
inline
QStringList
Mesh_parameters::
log() const
{
return QStringList()
<< QString("facet min angle: %1").arg(facet_angle)
<< QString("facet max size: %1").arg(facet_sizing)
<< QString("facet approx error: %1").arg(facet_approx)
<< QString("tet shape (radius-edge): %1").arg(tet_shape)
<< QString("tet max size: %1").arg(tet_sizing);
}
// -----------------------------------
// Class Mesh_function
// -----------------------------------
template < typename D_ >
Mesh_function<D_>::
Mesh_function(C3t3& c3t3, Domain* domain, const Mesh_parameters& p)
: c3t3_(c3t3)
, domain_(domain)
, p_(p)
, continue_(true)
{
}
template < typename D_ >
Mesh_function<D_>::
~Mesh_function()
{
delete domain_;
}
template < typename D_ >
void
Mesh_function<D_>::
launch()
{
typedef typename Domain::Point_3 Point_3;
typedef typename Domain::Index Index;
typedef std::vector<std::pair<Point_3, Index> > Initial_points_vector;
typedef typename Initial_points_vector::iterator Ipv_iterator;
typedef C3t3::Vertex_handle Vertex_handle;
typedef C3t3::Triangulation Tr;
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
typedef Mesh_criteria::Facet_criteria Facet_criteria;
typedef Mesh_criteria::Cell_criteria Cell_criteria;
typedef CGAL::Mesh_3::Mesher_3<C3t3, Mesh_criteria, Domain> Mesher;
// Mesh initialization : get some points and add them to the mesh
Initial_points_vector initial_points;
domain_->construct_initial_points_object()(std::back_inserter(initial_points),20);
// Insert points and set their index and dimension
for ( Ipv_iterator it = initial_points.begin() ;
it != initial_points.end() ;
++it )
{
Vertex_handle v = c3t3_.triangulation().insert(it->first);
c3t3_.set_dimension(v,2); // by construction, points are on surface
c3t3_.set_index(v,it->second);
}
// Create mesh criteria
Mesh_criteria criteria(Facet_criteria(p_.facet_angle,
p_.facet_sizing,
p_.facet_approx),
Cell_criteria(p_.tet_shape,
p_.tet_sizing));
// Build mesher and launch refinement process
Mesher mesher (c3t3_, *domain_, criteria);
mesher.initialize();
while ( !mesher.is_algorithm_done() && continue_ )
{
mesher.one_step();
}
}
template < typename D_ >
void
Mesh_function<D_>::
stop()
{
continue_ = false;
}
template < typename D_ >
QStringList
Mesh_function<D_>::
parameters_log() const
{
return p_.log();
}
#endif // CGAL_DEMO_MESH_3_MESH_FUNCTION_H

View File

@ -0,0 +1,71 @@
// 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 <QTime>
#include "Meshing_thread.h"
#include "Scene_c3t3_item.h"
Meshing_thread::
Meshing_thread(Mesh_function_interface* f, Scene_c3t3_item* item)
: f_(f)
, item_(item)
, time_(0)
{
}
Meshing_thread::
~Meshing_thread()
{
delete f_;
}
void
Meshing_thread::
run()
{
QTime timer;
timer.start();
f_->launch();
time_ = double(timer.elapsed()) / 1000;
item_->c3t3_changed();
emit done(this);
}
void
Meshing_thread::
stop()
{
f_->stop();
}
#include "Meshing_thread.moc"

View File

@ -0,0 +1,84 @@
// 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 CGAL_DEMO_MESH_3_MESHING_THREAD_H
#define CGAL_DEMO_MESH_3_MESHING_THREAD_H
#include <QThread>
#include <QObject>
#include <QStringList>
class Scene_c3t3_item;
class Mesh_function_interface
{
public:
virtual ~Mesh_function_interface() {}
// Launch
virtual void launch() = 0;
// Stop
virtual void stop() = 0;
// Logs
virtual QStringList parameters_log() const = 0;
};
class Meshing_thread : public QThread
{
Q_OBJECT
public:
// Constructor / Destructor
Meshing_thread(Mesh_function_interface* f, Scene_c3t3_item* item);
virtual ~Meshing_thread();
// Scene item
Scene_c3t3_item* item() const { return item_; }
// Infos about meshing
double time() const { return time_; }
// Logs
QStringList parameters_log() const { return f_->parameters_log(); }
public slots:
// Stop
void stop();
signals:
// Emitted at the end of the process
void done(Meshing_thread*);
protected:
// Overload of QThread function
virtual void run();
private:
Mesh_function_interface* f_;
Scene_c3t3_item* item_;
double time_; // in seconds
};
#endif // CGAL_DEMO_MESH_3_MESHING_THREAD_H

View File

@ -23,6 +23,7 @@
#include <QTime>
#include "Optimizer_thread.h"
#include "Scene_c3t3_item.h"
Optimizer_thread::~Optimizer_thread()
{
@ -38,8 +39,9 @@ run()
timer.start();
rc_ = f_->launch();
time_ = double(timer.elapsed()) / 1000;
item_->c3t3_changed();
emit done(this);
}

View File

@ -67,30 +67,32 @@ double complex_diag(const Scene_item* item) {
struct Scene_c3t3_item_priv {
Scene_c3t3_item_priv() : c3t3() {}
Scene_c3t3_item_priv(const C3t3& c3t3_) : c3t3(c3t3_) {}
C3t3 c3t3;
QVector<QColor> colors;
};
Scene_c3t3_item::
Scene_c3t3_item()
: d(new Scene_c3t3_item_priv())
, frame(new ManipulatedFrame())
, histogram_()
, data_item_(NULL)
, indices_()
{
connect(frame, SIGNAL(modified()), this, SLOT(changed()));
c3t3_changed();
}
Scene_c3t3_item::Scene_c3t3_item(const C3t3& c3t3)
: d(new Scene_c3t3_item_priv(c3t3)), frame(new ManipulatedFrame())
, histogram_(), data_item_(NULL), indices_()
{
connect(frame, SIGNAL(modified()), this, SLOT(changed()));
// Fill indices map and get max subdomain value
int max = 0;
for(C3t3::Cell_iterator cit = this->c3t3().cells_begin(), end = this->c3t3().cells_end();
cit != end; ++cit)
{
max = (std::max)(max, cit->subdomain_index());
indices_.insert(cit->subdomain_index());
}
d->colors.resize(max+1);
compute_color_map(QColor());
c3t3_changed();
}
Scene_c3t3_item::~Scene_c3t3_item()
@ -445,6 +447,20 @@ Scene_c3t3_item::setColor(QColor c)
compute_color_map(c);
}
void
Scene_c3t3_item::c3t3_changed()
{
// Fill indices map and get max subdomain value
int max = 0;
for(C3t3::Cell_iterator cit = this->c3t3().cells_begin(), end = this->c3t3().cells_end();
cit != end; ++cit)
{
max = (std::max)(max, cit->subdomain_index());
indices_.insert(cit->subdomain_index());
}
d->colors.resize(max+1);
}
void
Scene_c3t3_item::compute_color_map(const QColor& c)

View File

@ -23,6 +23,7 @@ class SCENE_C3T3_ITEM_EXPORT Scene_c3t3_item
public:
typedef qglviewer::ManipulatedFrame ManipulatedFrame;
Scene_c3t3_item();
Scene_c3t3_item(const C3t3& c3t3);
~Scene_c3t3_item();
@ -75,6 +76,9 @@ public:
// rebuild histogram
inline void update_histogram();
// Call this if c3t3 has been modified
void c3t3_changed();
public slots:
inline void data_item_destroyed();

View File

@ -106,6 +106,11 @@ public:
/// Launch mesh refinement
double refine_mesh();
// Step-by-step methods
void initialize();
void one_step();
bool is_algorithm_done();
private:
/// Meshers
Null_mesher_level null_mesher_;
@ -253,7 +258,47 @@ Mesher_3<C3T3,MC,MD>::refine_mesh()
elapsed_time += timer.time();
return elapsed_time;
}
template<class C3T3, class MC, class MD>
void
Mesher_3<C3T3,MC,MD>::
initialize()
{
facets_mesher_.scan_triangulation();
}
template<class C3T3, class MC, class MD>
void
Mesher_3<C3T3,MC,MD>::
one_step()
{
if ( ! facets_visitor_.is_active() )
{
facets_mesher_.one_step(facets_visitor_);
if ( facets_mesher_.is_algorithm_done() )
{
facets_visitor_.activate();
cells_mesher_.scan_triangulation();
}
}
else
{
cells_mesher_.one_step(cells_visitor_);
}
}
template<class C3T3, class MC, class MD>
bool
Mesher_3<C3T3,MC,MD>::
is_algorithm_done()
{
return cells_mesher_.is_algorithm_done();
}
} // end namespace Mesh_3
} // end namespace CGAL

View File

@ -81,6 +81,11 @@ namespace Mesh_3 {
active_=true;
}
bool is_active() const
{
return active_;
}
private:
bool active_;