mirror of https://github.com/CGAL/cgal
Merge hole_filling and hole_filling_polylines plugins
This commit is contained in:
parent
b8d5c5e89a
commit
d44c38644e
|
|
@ -22,9 +22,6 @@ if(TARGET CGAL::Eigen_support)
|
||||||
polyhedron_demo_plugin(fairing_plugin Fairing_plugin ${fairingUI_FILES} KEYWORDS PMP)
|
polyhedron_demo_plugin(fairing_plugin Fairing_plugin ${fairingUI_FILES} KEYWORDS PMP)
|
||||||
target_link_libraries(fairing_plugin PUBLIC scene_selection_item CGAL::Eigen_support)
|
target_link_libraries(fairing_plugin PUBLIC scene_selection_item CGAL::Eigen_support)
|
||||||
|
|
||||||
polyhedron_demo_plugin(hole_filling_polyline_plugin Hole_filling_polyline_plugin )
|
|
||||||
target_link_libraries(hole_filling_polyline_plugin PUBLIC scene_surface_mesh_item scene_polylines_item CGAL::Eigen_support)
|
|
||||||
|
|
||||||
qt5_wrap_ui( Mean_curvature_flow_skeleton_pluginUI_FILES Mean_curvature_flow_skeleton_plugin.ui)
|
qt5_wrap_ui( Mean_curvature_flow_skeleton_pluginUI_FILES Mean_curvature_flow_skeleton_plugin.ui)
|
||||||
polyhedron_demo_plugin(mean_curvature_flow_skeleton_plugin Mean_curvature_flow_skeleton_plugin ${Mean_curvature_flow_skeleton_pluginUI_FILES})
|
polyhedron_demo_plugin(mean_curvature_flow_skeleton_plugin Mean_curvature_flow_skeleton_plugin ${Mean_curvature_flow_skeleton_pluginUI_FILES})
|
||||||
target_link_libraries(mean_curvature_flow_skeleton_plugin
|
target_link_libraries(mean_curvature_flow_skeleton_plugin
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,10 @@
|
||||||
#include "ui_Hole_filling_widget.h"
|
#include "ui_Hole_filling_widget.h"
|
||||||
|
|
||||||
#include <CGAL/Polygon_mesh_processing/triangulate_hole.h>
|
#include <CGAL/Polygon_mesh_processing/triangulate_hole.h>
|
||||||
|
#include <CGAL/Polygon_mesh_processing/self_intersections.h>
|
||||||
|
#include <CGAL/Polygon_mesh_processing/refine.h>
|
||||||
|
#include <CGAL/Polygon_mesh_processing/internal/named_function_params.h>
|
||||||
|
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
|
||||||
#include <CGAL/Timer.h>
|
#include <CGAL/Timer.h>
|
||||||
#include <CGAL/iterator.h>
|
#include <CGAL/iterator.h>
|
||||||
|
|
||||||
|
|
@ -23,6 +27,7 @@
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
|
#include <QInputDialog>
|
||||||
|
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
|
@ -33,7 +38,6 @@
|
||||||
|
|
||||||
#include <CGAL/Qt/qglviewer.h>
|
#include <CGAL/Qt/qglviewer.h>
|
||||||
|
|
||||||
#include <CGAL/Polygon_mesh_processing/self_intersections.h>
|
|
||||||
#include <CGAL/boost/graph/Euler_operations.h>
|
#include <CGAL/boost/graph/Euler_operations.h>
|
||||||
#include "Kernel_type.h"
|
#include "Kernel_type.h"
|
||||||
|
|
||||||
|
|
@ -47,6 +51,17 @@ using namespace CGAL::Three;
|
||||||
|
|
||||||
typedef Scene_surface_mesh_item Scene_face_graph_item;
|
typedef Scene_surface_mesh_item Scene_face_graph_item;
|
||||||
|
|
||||||
|
|
||||||
|
struct Face : public std::array<int,3>
|
||||||
|
{
|
||||||
|
Face(int i, int j, int k)
|
||||||
|
{
|
||||||
|
(*this)[0] = i;
|
||||||
|
(*this)[1] = j;
|
||||||
|
(*this)[2] = k;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void normalize_border(Scene_face_graph_item::Face_graph&)
|
void normalize_border(Scene_face_graph_item::Face_graph&)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
@ -77,6 +92,7 @@ public:
|
||||||
};
|
};
|
||||||
public: typedef std::list<Polyline_data> Polyline_data_list;
|
public: typedef std::list<Polyline_data> Polyline_data_list;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct List_iterator_comparator {
|
struct List_iterator_comparator {
|
||||||
bool operator()(Polyline_data_list::const_iterator it_1, Polyline_data_list::const_iterator it_2) const
|
bool operator()(Polyline_data_list::const_iterator it_1, Polyline_data_list::const_iterator it_2) const
|
||||||
{ return (&*it_1) < (&*it_2); }
|
{ return (&*it_1) < (&*it_2); }
|
||||||
|
|
@ -328,10 +344,21 @@ class Polyhedron_demo_hole_filling_plugin :
|
||||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "hole_filling_plugin.json")
|
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "hole_filling_plugin.json")
|
||||||
public:
|
public:
|
||||||
bool applicable(QAction*) const { return qobject_cast<Scene_face_graph_item*>(scene->item(scene->mainSelectionIndex())) ||
|
bool applicable(QAction* action) const
|
||||||
qobject_cast<Scene_polyhedron_selection_item*>(scene->item(scene->mainSelectionIndex())); }
|
{
|
||||||
|
if(action == actionHoleFilling)
|
||||||
|
{
|
||||||
|
return qobject_cast<Scene_face_graph_item*>(scene->item(scene->mainSelectionIndex())) ||
|
||||||
|
qobject_cast<Scene_polyhedron_selection_item*>(scene->item(scene->mainSelectionIndex()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return qobject_cast<Scene_polylines_item*>(scene->item(scene->mainSelectionIndex()));
|
||||||
|
}
|
||||||
|
}
|
||||||
void print_message(QString message) { CGAL::Three::Three::information(message); }
|
void print_message(QString message) { CGAL::Three::Three::information(message); }
|
||||||
QList<QAction*> actions() const { return QList<QAction*>() << actionHoleFilling; }
|
QList<QAction*> actions() const { return QList<QAction*>() << actionHoleFilling
|
||||||
|
<<actionHoleFillingPolyline; }
|
||||||
|
|
||||||
|
|
||||||
void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface* m);
|
void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface* m);
|
||||||
|
|
@ -352,6 +379,7 @@ public Q_SLOTS:
|
||||||
}
|
}
|
||||||
void on_Select_all_holes_button();
|
void on_Select_all_holes_button();
|
||||||
void on_Fill_from_selection_button();
|
void on_Fill_from_selection_button();
|
||||||
|
void hole_filling_polyline_action();
|
||||||
void on_Deselect_all_holes_button();
|
void on_Deselect_all_holes_button();
|
||||||
void on_Visualize_holes_button();
|
void on_Visualize_holes_button();
|
||||||
void on_Fill_selected_holes_button();
|
void on_Fill_selected_holes_button();
|
||||||
|
|
@ -380,9 +408,15 @@ protected:
|
||||||
private:
|
private:
|
||||||
Messages_interface* messages;
|
Messages_interface* messages;
|
||||||
QAction* actionHoleFilling;
|
QAction* actionHoleFilling;
|
||||||
|
QAction* actionHoleFillingPolyline;
|
||||||
|
|
||||||
QDockWidget* dock_widget;
|
QDockWidget* dock_widget;
|
||||||
Ui::HoleFilling ui_widget;
|
Ui::HoleFilling ui_widget;
|
||||||
|
struct Nop_functor {
|
||||||
|
template<class T>
|
||||||
|
void operator()(const T & /*t*/) const {}
|
||||||
|
};
|
||||||
|
typedef boost::function_output_iterator<Nop_functor> Nop_out;
|
||||||
|
|
||||||
//Maintains a reference between all the visualizers and their poly_item
|
//Maintains a reference between all the visualizers and their poly_item
|
||||||
// to ease the management of the visualizers
|
// to ease the management of the visualizers
|
||||||
|
|
@ -435,6 +469,10 @@ void Polyhedron_demo_hole_filling_plugin::init(QMainWindow* mainWindow,
|
||||||
), mw);
|
), mw);
|
||||||
actionHoleFilling->setProperty("subMenuName", "Polygon Mesh Processing");
|
actionHoleFilling->setProperty("subMenuName", "Polygon Mesh Processing");
|
||||||
connect(actionHoleFilling, SIGNAL(triggered()), this, SLOT(hole_filling_action()));
|
connect(actionHoleFilling, SIGNAL(triggered()), this, SLOT(hole_filling_action()));
|
||||||
|
actionHoleFillingPolyline = new QAction(tr("Polyline Hole Filling"), mw);
|
||||||
|
actionHoleFillingPolyline->setProperty("subMenuName", "Polygon Mesh Processing");
|
||||||
|
connect(actionHoleFillingPolyline, SIGNAL(triggered()),
|
||||||
|
this, SLOT(hole_filling_polyline_action()));
|
||||||
|
|
||||||
dock_widget = new QDockWidget(
|
dock_widget = new QDockWidget(
|
||||||
"Hole Filling"
|
"Hole Filling"
|
||||||
|
|
@ -873,6 +911,75 @@ void Polyhedron_demo_hole_filling_plugin::on_Fill_from_selection_button() {
|
||||||
edge_selection->polyhedron_item()->itemChanged();
|
edge_selection->polyhedron_item()->itemChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Polyhedron_demo_hole_filling_plugin::hole_filling_polyline_action() {
|
||||||
|
Scene_polylines_item* polylines_item = qobject_cast<Scene_polylines_item*>(scene->item(scene->mainSelectionIndex()));
|
||||||
|
if(!polylines_item) {
|
||||||
|
print_message("Error: there is no selected polyline item!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool also_refine;
|
||||||
|
const double density_control_factor =
|
||||||
|
QInputDialog::getDouble(mw, tr("Density Control Factor"),
|
||||||
|
tr("Density Control Factor (Cancel for not Refine): "), 1.41, 0.0, 100.0, 2, &also_refine);
|
||||||
|
|
||||||
|
bool use_DT =
|
||||||
|
QMessageBox::Yes == QMessageBox::question(
|
||||||
|
NULL, "Use Delaunay Triangulation", "Use Delaunay Triangulation ?", QMessageBox::Yes|QMessageBox::No);
|
||||||
|
|
||||||
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
QApplication::processEvents();
|
||||||
|
std::size_t counter = 0;
|
||||||
|
for(Scene_polylines_item::Polylines_container::iterator it = polylines_item->polylines.begin();
|
||||||
|
it != polylines_item->polylines.end(); ++it, ++counter)
|
||||||
|
{
|
||||||
|
if(it->front() != it->back()) { //not closed, skip it
|
||||||
|
print_message("Warning: skipping not closed polyline!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(it->size() < 4) { // no triangle, skip it (needs at least 3 + 1 repeat)
|
||||||
|
print_message("Warning: skipping polyline which has less than 4 points!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGAL::Timer timer; timer.start();
|
||||||
|
std::vector<Face> patch;
|
||||||
|
CGAL::Polygon_mesh_processing::triangulate_hole_polyline(*it,
|
||||||
|
std::back_inserter(patch),
|
||||||
|
PMP::parameters::use_delaunay_triangulation(use_DT));
|
||||||
|
print_message(QString("Triangulated in %1 sec.").arg(timer.time()));
|
||||||
|
|
||||||
|
if(patch.empty()) {
|
||||||
|
if(use_DT){
|
||||||
|
print_message("Warning: generating patch is not successful, please try it without 'Delaunay Triangulation'!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
print_message("Warning: generating patch is not successful, skipping.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SMesh* poly = new SMesh;
|
||||||
|
CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(*it,
|
||||||
|
patch,
|
||||||
|
*poly);
|
||||||
|
|
||||||
|
if(also_refine) {
|
||||||
|
timer.reset();
|
||||||
|
CGAL::Polygon_mesh_processing::refine(*poly, faces(*poly),
|
||||||
|
Nop_out(), Nop_out(),
|
||||||
|
CGAL::Polygon_mesh_processing::parameters::density_control_factor(density_control_factor));
|
||||||
|
print_message(QString("Refined in %1 sec.").arg(timer.time()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Scene_surface_mesh_item* poly_item = new Scene_surface_mesh_item(poly);
|
||||||
|
poly_item->setName(tr("%1-filled-%2").arg(polylines_item->name()).arg(counter));
|
||||||
|
poly_item->setRenderingMode(FlatPlusEdges);
|
||||||
|
scene->setSelectedItem(scene->addItem(poly_item));
|
||||||
|
}
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
}
|
||||||
|
|
||||||
// Q_EXPORT_PLUGIN2(Polyhedron_demo_hole_filling_plugin, Polyhedron_demo_hole_filling_plugin)
|
// Q_EXPORT_PLUGIN2(Polyhedron_demo_hole_filling_plugin, Polyhedron_demo_hole_filling_plugin)
|
||||||
|
|
||||||
#include "Hole_filling_plugin.moc"
|
#include "Hole_filling_plugin.moc"
|
||||||
|
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
#include <QtCore/qglobal.h>
|
|
||||||
|
|
||||||
#include "Messages_interface.h"
|
|
||||||
#include "Scene_surface_mesh_item.h"
|
|
||||||
#include "Scene_polylines_item.h"
|
|
||||||
#include <CGAL/Three/Scene_interface.h>
|
|
||||||
|
|
||||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
|
||||||
|
|
||||||
#include <CGAL/Polygon_mesh_processing/triangulate_hole.h>
|
|
||||||
#include <CGAL/Polygon_mesh_processing/refine.h>
|
|
||||||
#include <CGAL/Polygon_mesh_processing/internal/named_function_params.h>
|
|
||||||
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
|
|
||||||
#include <CGAL/Timer.h>
|
|
||||||
#include <CGAL/array.h>
|
|
||||||
|
|
||||||
#include <QAction>
|
|
||||||
#include <QMainWindow>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QInputDialog>
|
|
||||||
#include <QMessageBox>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include <boost/function_output_iterator.hpp>
|
|
||||||
#include <CGAL/boost/iterator/transform_iterator.hpp>
|
|
||||||
#include <CGAL/Three/Three.h>
|
|
||||||
|
|
||||||
|
|
||||||
struct Face : public std::array<int,3>
|
|
||||||
{
|
|
||||||
Face(int i, int j, int k)
|
|
||||||
{
|
|
||||||
(*this)[0] = i;
|
|
||||||
(*this)[1] = j;
|
|
||||||
(*this)[2] = k;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
|
||||||
|
|
||||||
using namespace CGAL::Three;
|
|
||||||
class Polyhedron_demo_hole_filling_polyline_plugin :
|
|
||||||
public QObject,
|
|
||||||
public Polyhedron_demo_plugin_interface
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
|
||||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
|
|
||||||
public:
|
|
||||||
bool applicable(QAction *) const { return qobject_cast<Scene_polylines_item*>(scene->item(scene->mainSelectionIndex())); }
|
|
||||||
void print_message(QString message) { CGAL::Three::Three::information(message); }
|
|
||||||
QList<QAction*> actions() const { return QList<QAction*>() << actionHoleFillingPolyline; }
|
|
||||||
|
|
||||||
void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface* m){
|
|
||||||
mw = mainWindow;
|
|
||||||
scene = scene_interface;
|
|
||||||
messages = m;
|
|
||||||
actionHoleFillingPolyline = new QAction(tr("Polyline Hole Filling"), mw);
|
|
||||||
connect(actionHoleFillingPolyline, SIGNAL(triggered()),
|
|
||||||
this, SLOT(hole_filling_polyline_action()));
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
struct Nop_functor {
|
|
||||||
template<class T>
|
|
||||||
void operator()(const T & /*t*/) const {}
|
|
||||||
};
|
|
||||||
typedef boost::function_output_iterator<Nop_functor> Nop_out;
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void hole_filling_polyline_action() {
|
|
||||||
Scene_polylines_item* polylines_item = qobject_cast<Scene_polylines_item*>(scene->item(scene->mainSelectionIndex()));
|
|
||||||
if(!polylines_item) {
|
|
||||||
print_message("Error: there is no selected polyline item!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool also_refine;
|
|
||||||
const double density_control_factor =
|
|
||||||
QInputDialog::getDouble(mw, tr("Density Control Factor"),
|
|
||||||
tr("Density Control Factor (Cancel for not Refine): "), 1.41, 0.0, 100.0, 2, &also_refine);
|
|
||||||
|
|
||||||
bool use_DT =
|
|
||||||
QMessageBox::Yes == QMessageBox::question(
|
|
||||||
NULL, "Use Delaunay Triangulation", "Use Delaunay Triangulation ?", QMessageBox::Yes|QMessageBox::No);
|
|
||||||
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
||||||
QApplication::processEvents();
|
|
||||||
std::size_t counter = 0;
|
|
||||||
for(Scene_polylines_item::Polylines_container::iterator it = polylines_item->polylines.begin();
|
|
||||||
it != polylines_item->polylines.end(); ++it, ++counter)
|
|
||||||
{
|
|
||||||
if(it->front() != it->back()) { //not closed, skip it
|
|
||||||
print_message("Warning: skipping not closed polyline!");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(it->size() < 4) { // no triangle, skip it (needs at least 3 + 1 repeat)
|
|
||||||
print_message("Warning: skipping polyline which has less than 4 points!");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGAL::Timer timer; timer.start();
|
|
||||||
std::vector<Face> patch;
|
|
||||||
CGAL::Polygon_mesh_processing::triangulate_hole_polyline(*it,
|
|
||||||
std::back_inserter(patch),
|
|
||||||
PMP::parameters::use_delaunay_triangulation(use_DT));
|
|
||||||
print_message(QString("Triangulated in %1 sec.").arg(timer.time()));
|
|
||||||
|
|
||||||
if(patch.empty()) {
|
|
||||||
if(use_DT){
|
|
||||||
print_message("Warning: generating patch is not successful, please try it without 'Delaunay Triangulation'!");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
print_message("Warning: generating patch is not successful, skipping.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SMesh* poly = new SMesh;
|
|
||||||
CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(*it,
|
|
||||||
patch,
|
|
||||||
*poly);
|
|
||||||
|
|
||||||
if(also_refine) {
|
|
||||||
timer.reset();
|
|
||||||
CGAL::Polygon_mesh_processing::refine(*poly, faces(*poly),
|
|
||||||
Nop_out(), Nop_out(),
|
|
||||||
CGAL::Polygon_mesh_processing::parameters::density_control_factor(density_control_factor));
|
|
||||||
print_message(QString("Refined in %1 sec.").arg(timer.time()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Scene_surface_mesh_item* poly_item = new Scene_surface_mesh_item(poly);
|
|
||||||
poly_item->setName(tr("%1-filled-%2").arg(polylines_item->name()).arg(counter));
|
|
||||||
poly_item->setRenderingMode(FlatPlusEdges);
|
|
||||||
scene->setSelectedItem(scene->addItem(poly_item));
|
|
||||||
}
|
|
||||||
QApplication::restoreOverrideCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QMainWindow* mw;
|
|
||||||
CGAL::Three::Scene_interface* scene;
|
|
||||||
Messages_interface* messages;
|
|
||||||
QAction* actionHoleFillingPolyline;
|
|
||||||
|
|
||||||
}; // end Polyhedron_demo_hole_filling_polyline_plugin
|
|
||||||
|
|
||||||
// Q_EXPORT_PLUGIN2(Polyhedron_demo_hole_filling_polyline_plugin, Polyhedron_demo_hole_filling_polyline_plugin)
|
|
||||||
|
|
||||||
#include "Hole_filling_polyline_plugin.moc"
|
|
||||||
Loading…
Reference in New Issue