Merge pull request #1044 from maxGimeno/Euler_operations-rebase-GF

Polyhedron demo : Euler operations in selection_plugin
This commit is contained in:
Sebastien Loriot 2016-05-12 16:47:48 +02:00
commit ef13f66767
10 changed files with 2257 additions and 722 deletions

View File

@ -75,7 +75,7 @@ public:
messages = m;
actionSelection = new QAction(tr("Selection"), mw);
connect(actionSelection, SIGNAL(triggered()), this, SLOT(selection_action()));
last_mode = 0;
dock_widget = new QDockWidget("Selection", mw);
dock_widget->setVisible(false);
@ -93,13 +93,11 @@ public:
this, SLOT(on_Selection_type_combo_box_changed(int)));
connect(ui_widget.Insertion_radio_button, SIGNAL(toggled(bool)), this, SLOT(on_Insertion_radio_button_toggled(bool)));
connect(ui_widget.Brush_size_spin_box, SIGNAL(valueChanged(int)), this, SLOT(on_Brush_size_spin_box_changed(int)));
connect(ui_widget.Create_point_set_item_button, SIGNAL(clicked()), this, SLOT(on_Create_point_set_item_button_clicked()));
connect(ui_widget.Create_polyline_item_button, SIGNAL(clicked()), this, SLOT(on_Create_polyline_item_button_clicked()));
connect(ui_widget.Erase_selected_facets_button, SIGNAL(clicked()), this, SLOT(on_Erase_selected_facets_button_clicked()));
connect(ui_widget.Keep_connected_components_button, SIGNAL(clicked()), this, SLOT(on_Keep_connected_components_button_clicked()));
connect(ui_widget.validateButton, SIGNAL(clicked()), this, SLOT(on_validateButton_clicked()));
connect(ui_widget.Expand_reduce_button, SIGNAL(clicked()), this, SLOT(on_Expand_reduce_button_clicked()));
connect(ui_widget.Create_polyhedron_item_button, SIGNAL(clicked()), this, SLOT(on_Create_polyhedron_item_button_clicked()));
connect(ui_widget.Select_sharp_edges_button, SIGNAL(clicked()), this, SLOT(on_Select_sharp_edges_button_clicked()));
connect(ui_widget.modeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(on_ModeBox_changed(int)));
connect(ui_widget.editionBox, SIGNAL(currentIndexChanged(int)), this, SLOT(on_editionBox_changed(int)));
QObject* scene = dynamic_cast<QObject*>(scene_interface);
if(scene) {
@ -111,7 +109,14 @@ public:
{
dock_widget->hide();
}
Q_SIGNALS:
void save_handleType();
void set_operation_mode(int);
public Q_SLOTS:
void setInstructions(QString s)
{
ui_widget.instructionsLabel->setText(s);
}
void selection_action() {
dock_widget->show();
dock_widget->raise();
@ -119,12 +124,17 @@ public Q_SLOTS:
Scene_polyhedron_item* poly_item = getSelectedItem<Scene_polyhedron_item>();
if(!poly_item || selection_item_map.find(poly_item) != selection_item_map.end()) { return; }
Scene_polyhedron_selection_item* new_item = new Scene_polyhedron_selection_item(poly_item, mw);
connect(this, SIGNAL(save_handleType()),new_item, SLOT(save_handleType()));
connect(new_item, SIGNAL(updateInstructions(QString)), this, SLOT(setInstructions(QString)));
connect(this, SIGNAL(set_operation_mode(int)),new_item, SLOT(set_operation_mode(int)));
int item_id = scene->addItem(new_item);
QObject* scene_ptr = dynamic_cast<QObject*>(scene);
if (scene_ptr)
connect(new_item,SIGNAL(simplicesSelected(CGAL::Three::Scene_item*)), scene_ptr, SLOT(setSelectedItem(CGAL::Three::Scene_item*)));
scene->setSelectedItem(item_id);
on_ModeBox_changed(ui_widget.modeBox->currentIndex());
}
on_Selection_type_combo_box_changed(ui_widget.Selection_type_combo_box->currentIndex());
}
// Select all
void on_Select_all_button_clicked() {
@ -199,11 +209,19 @@ public Q_SLOTS:
// all other arrangements (putting inside selection_item_map), setting names etc,
// other params (e.g. k_ring) will be set inside new_item_created
Scene_polyhedron_selection_item* new_item = new Scene_polyhedron_selection_item(poly_item, mw);
//To specify what action should be performed on shift+left-click
connect(this, SIGNAL(save_handleType()),new_item, SLOT(save_handleType()));
connect(new_item, SIGNAL(updateInstructions(QString)), this, SLOT(setInstructions(QString)));
connect(this, SIGNAL(set_operation_mode(int)),new_item, SLOT(set_operation_mode(int)));
int item_id = scene->addItem(new_item);
QObject* scene_ptr = dynamic_cast<QObject*>(scene);
if (scene_ptr)
connect(new_item,SIGNAL(simplicesSelected(CGAL::Three::Scene_item*)), scene_ptr, SLOT(setSelectedItem(CGAL::Three::Scene_item*)));
scene->setSelectedItem(item_id);
ui_widget.modeBox->setCurrentIndex(last_mode);
on_ModeBox_changed(ui_widget.modeBox->currentIndex());
on_Selection_type_combo_box_changed(ui_widget.Selection_type_combo_box->currentIndex());
}
void on_Selection_type_combo_box_changed(int index) {
typedef Scene_polyhedron_selection_item::Active_handle Active_handle;
@ -222,119 +240,178 @@ public Q_SLOTS:
}
}
void on_Create_point_set_item_button_clicked() {
Scene_polyhedron_selection_item* selection_item = getSelectedItem<Scene_polyhedron_selection_item>();
if(!selection_item) {
print_message("Error: there is no selected polyhedron selection item!");
return;
}
if(selection_item->selected_vertices.empty()) {
print_message("Error: there is no selected vertex in polyhedron selection item!");
return;
}
Scene_points_with_normal_item* point_item = new Scene_points_with_normal_item();
point_item->setName(QString("%1-points").arg(selection_item->name()));
for(Scene_polyhedron_selection_item::Selection_set_vertex::iterator begin = selection_item->selected_vertices.begin();
begin != selection_item->selected_vertices.end(); ++begin) {
point_item->point_set()->push_back((*begin)->point());
}
scene->setSelectedItem( scene->addItem(point_item) );
scene->itemChanged(point_item);
}
void on_Create_polyline_item_button_clicked(){
Scene_polyhedron_selection_item* selection_item = getSelectedItem<Scene_polyhedron_selection_item>();
if(!selection_item) {
print_message("Error: there is no selected polyhedron selection item!");
return;
}
if(selection_item->selected_edges.empty()) {
print_message("Error: there is no selected edge in polyhedron selection item!");
return;
}
Scene_polylines_item* polyline_item = new Scene_polylines_item();
polyline_item->setName(QString("%1-edges").arg(selection_item->name()));
typedef boost::adjacency_list < boost::listS,
boost::vecS,
boost::undirectedS,
Kernel::Point_3 > Edge_graph;
typedef Polyhedron::Vertex_handle Vertex_handle;
Edge_graph edge_graph;
std::map<Vertex_handle, Edge_graph::vertex_descriptor> p2vd;
std::map<Vertex_handle, Edge_graph::vertex_descriptor>::iterator it_find;
bool insert_OK;
for(Scene_polyhedron_selection_item::Selection_set_edge::iterator begin = selection_item->selected_edges.begin();
begin != selection_item->selected_edges.end(); ++begin)
void on_validateButton_clicked() {
switch(ui_widget.operationsBox->currentIndex())
{
Vertex_handle source = begin->halfedge()->opposite()->vertex();
boost::tie(it_find, insert_OK)
= p2vd.insert(std::make_pair(source, Edge_graph::vertex_descriptor()));
if (insert_OK)
{
it_find->second = add_vertex(edge_graph);
edge_graph[it_find->second] = source->point();
//Create Point Set Item from Selected Vertices
case 0:
{
Scene_polyhedron_selection_item* selection_item = getSelectedItem<Scene_polyhedron_selection_item>();
if(!selection_item) {
print_message("Error: there is no selected polyhedron selection item!");
return;
}
Edge_graph::vertex_descriptor src=it_find->second;
Vertex_handle target = begin->halfedge()->vertex();
boost::tie(it_find, insert_OK)
= p2vd.insert(std::make_pair(target, Edge_graph::vertex_descriptor()));
if (insert_OK)
{
it_find->second = add_vertex(edge_graph);
edge_graph[it_find->second] = target->point();
if(selection_item->selected_vertices.empty()) {
print_message("Error: there is no selected vertex in polyhedron selection item!");
return;
}
Scene_points_with_normal_item* point_item = new Scene_points_with_normal_item();
point_item->setName(QString("%1-points").arg(selection_item->name()));
for(Scene_polyhedron_selection_item::Selection_set_vertex::iterator begin = selection_item->selected_vertices.begin();
begin != selection_item->selected_vertices.end(); ++begin) {
point_item->point_set()->push_back((*begin)->point());
break;
}
Edge_graph::vertex_descriptor tgt=it_find->second;
boost::add_edge(src, tgt, edge_graph);
}
//Create Polyline Item from Selected Edges
case 1:
{
Scene_polyhedron_selection_item* selection_item = getSelectedItem<Scene_polyhedron_selection_item>();
if(!selection_item) {
print_message("Error: there is no selected polyhedron selection item!");
return;
}
if(selection_item->selected_edges.empty()) {
print_message("Error: there is no selected edge in polyhedron selection item!");
return;
}
Scene_polylines_item* polyline_item = new Scene_polylines_item();
polyline_item->setName(QString("%1-edges").arg(selection_item->name()));
Polyline_visitor<Edge_graph> polyline_visitor(polyline_item, edge_graph);
CGAL::split_graph_into_polylines( edge_graph,
polyline_visitor,
Is_terminal() );
scene->setSelectedItem( scene->addItem(polyline_item) );
scene->itemChanged(polyline_item);
typedef boost::adjacency_list < boost::listS,
boost::vecS,
boost::undirectedS,
Kernel::Point_3 > Edge_graph;
typedef Polyhedron::Vertex_handle Vertex_handle;
Edge_graph edge_graph;
std::map<Vertex_handle, Edge_graph::vertex_descriptor> p2vd;
std::map<Vertex_handle, Edge_graph::vertex_descriptor>::iterator it_find;
bool insert_OK;
for(Scene_polyhedron_selection_item::Selection_set_edge::iterator begin = selection_item->selected_edges.begin();
begin != selection_item->selected_edges.end(); ++begin)
{
Vertex_handle source = begin->halfedge()->opposite()->vertex();
boost::tie(it_find, insert_OK)
= p2vd.insert(std::make_pair(source, Edge_graph::vertex_descriptor()));
if (insert_OK)
{
it_find->second = add_vertex(edge_graph);
edge_graph[it_find->second] = source->point();
}
Edge_graph::vertex_descriptor src=it_find->second;
Vertex_handle target = begin->halfedge()->vertex();
boost::tie(it_find, insert_OK)
= p2vd.insert(std::make_pair(target, Edge_graph::vertex_descriptor()));
if (insert_OK)
{
it_find->second = add_vertex(edge_graph);
edge_graph[it_find->second] = target->point();
}
Edge_graph::vertex_descriptor tgt=it_find->second;
boost::add_edge(src, tgt, edge_graph);
}
Polyline_visitor<Edge_graph> polyline_visitor(polyline_item, edge_graph);
CGAL::split_graph_into_polylines( edge_graph,
polyline_visitor,
Is_terminal() );
scene->setSelectedItem( scene->addItem(polyline_item) );
scene->itemChanged(polyline_item);
break;
}
//Create Polyhedron Item from Selected Facets
case 2:
{
Scene_polyhedron_selection_item* selection_item = getSelectedItem<Scene_polyhedron_selection_item>();
if(!selection_item) {
print_message("Error: there is no selected polyhedron selection item!");
return;
}
Scene_polyhedron_item* poly_item = new Scene_polyhedron_item();
if(selection_item->export_selected_facets_as_polyhedron(poly_item->polyhedron())) {
poly_item->setName(QString("%1-facets").arg(selection_item->name()));
poly_item->invalidateOpenGLBuffers(); // for init()
scene->setSelectedItem( scene->addItem(poly_item) );
scene->itemChanged(poly_item);
}
else {
delete poly_item;
print_message("Error: polyhedron item is not created!");
}
break;
}
//Erase Selected Facets from Polyhedron Item
case 3:
{
Scene_polyhedron_selection_item* selection_item = getSelectedItem<Scene_polyhedron_selection_item>();
if(!selection_item) {
print_message("Error: there is no selected polyhedron selection item!");
return;
}
selection_item->erase_selected_facets();
break;
}
//Keep connected components of Selected Facets
case 4:
{
Scene_polyhedron_selection_item* selection_item = getSelectedItem<Scene_polyhedron_selection_item>();
if (!selection_item) {
print_message("Error: there is no selected polyhedron selection item!");
return;
}
selection_item->keep_connected_components();
break;
}
default :
break;
}
return;
}
void on_Erase_selected_facets_button_clicked() {
void on_ModeBox_changed(int index)
{
Scene_polyhedron_selection_item* selection_item = getSelectedItem<Scene_polyhedron_selection_item>();
if(!selection_item) {
print_message("Error: there is no selected polyhedron selection item!");
return;
selection_item->on_Ctrlz_pressed();
last_mode = index;
switch(index)
{
//Selection mode
case 0:
ui_widget.selection_groupBox->setVisible(true);
ui_widget.edition_groupBox->setVisible(false);
Q_EMIT set_operation_mode(-1);
on_Selection_type_combo_box_changed(ui_widget.Selection_type_combo_box->currentIndex());
break;
//Edition mode
case 1:
ui_widget.selection_groupBox->setVisible(false);
ui_widget.edition_groupBox->setVisible(true);
Q_EMIT save_handleType();
Q_EMIT set_operation_mode(ui_widget.editionBox->currentIndex());
break;
}
selection_item->erase_selected_facets();
}
void on_Keep_connected_components_button_clicked() {
void on_editionBox_changed(int mode )
{
Scene_polyhedron_selection_item* selection_item = getSelectedItem<Scene_polyhedron_selection_item>();
if (!selection_item) {
print_message("Error: there is no selected polyhedron selection item!");
return;
selection_item->on_Ctrlz_pressed();
if(ui_widget.modeBox->currentIndex() == 0)
{
Q_EMIT set_operation_mode(-1);
}
selection_item->keep_connected_components();
}
void on_Create_polyhedron_item_button_clicked() {
Scene_polyhedron_selection_item* selection_item = getSelectedItem<Scene_polyhedron_selection_item>();
if(!selection_item) {
print_message("Error: there is no selected polyhedron selection item!");
return;
else
{
Q_EMIT set_operation_mode(mode);
}
Scene_polyhedron_item* poly_item = new Scene_polyhedron_item();
if(selection_item->export_selected_facets_as_polyhedron(poly_item->polyhedron())) {
poly_item->setName(QString("%1-facets").arg(selection_item->name()));
poly_item->invalidateOpenGLBuffers(); // for init()
scene->setSelectedItem( scene->addItem(poly_item) );
scene->itemChanged(poly_item);
}
else {
delete poly_item;
print_message("Error: polyhedron item is not created!");
}
}
void on_Select_sharp_edges_button_clicked() {
Scene_polyhedron_selection_item* selection_item = getSelectedItem<Scene_polyhedron_selection_item>();
if (!selection_item) {
@ -431,6 +508,7 @@ private:
Ui::Selection ui_widget;
typedef std::multimap<Scene_polyhedron_item*, Scene_polyhedron_selection_item*> Selection_item_map;
Selection_item_map selection_item_map;
int last_mode;
}; // end Polyhedron_demo_selection_plugin
//Q_EXPORT_PLUGIN2(Polyhedron_demo_selection_plugin, Polyhedron_demo_selection_plugin)

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>455</width>
<height>528</height>
<width>479</width>
<height>606</height>
</rect>
</property>
<property name="windowTitle">
@ -16,136 +16,379 @@
<widget class="QWidget" name="dockWidgetContents">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QComboBox" name="modeBox">
<item>
<property name="text">
<string>Selection Mode</string>
</property>
</item>
<item>
<property name="text">
<string>Edition Mode</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="selection_groupBox">
<property name="title">
<string>Selection by Type</string>
<string>Selection Operations</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Selection Type :</string>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Selection by Type</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Selection Type :</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QComboBox" name="Selection_type_combo_box">
<item>
<property name="text">
<string>Vertex</string>
</property>
</item>
<item>
<property name="text">
<string>Facet</string>
</property>
</item>
<item>
<property name="text">
<string>Edge</string>
</property>
</item>
<item>
<property name="text">
<string>Selected components (facet)</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="Insertion_radio_button">
<property name="text">
<string>Insertion</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="Removal_radio_button">
<property name="text">
<string>Removal</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Brush &amp;size:</string>
</property>
<property name="buddy">
<cstring>Brush_size_spin_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="Brush_size_spin_box"/>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="Select_all_button">
<property name="toolTip">
<string extracomment="Select all simplices of Selection Type"/>
</property>
<property name="text">
<string>Select &amp;All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Inverse_selection_button">
<property name="toolTip">
<string extracomment="Invert selection for Selection Type"/>
</property>
<property name="text">
<string>Invert Selection</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Clear_button">
<property name="toolTip">
<string extracomment="Clear selection for Selection Type"/>
</property>
<property name="text">
<string>&amp;Clear</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QComboBox" name="Selection_type_combo_box">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<property name="text">
<string>Vertex</string>
</property>
</item>
<item>
<property name="text">
<string>Facet</string>
</property>
</item>
<item>
<property name="text">
<string>Edge</string>
</property>
</item>
<item>
<property name="text">
<string>Selected components (facet)</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QRadioButton" name="Insertion_radio_button">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Insertion</string>
<string>Isolated &amp;Component Size:</string>
</property>
<property name="checked">
<bool>true</bool>
<property name="buddy">
<cstring>Threshold_size_spin_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="Removal_radio_button">
<widget class="QSpinBox" name="Threshold_size_spin_box">
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>8</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Get_minimum_button">
<property name="text">
<string>Removal</string>
<string>&amp;Get Minimum</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Brush &amp;size:</string>
</property>
<property name="buddy">
<cstring>Brush_size_spin_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="Brush_size_spin_box"/>
</item>
</layout>
</item>
</layout>
<widget class="QPushButton" name="Select_isolated_components_button">
<property name="text">
<string>Select &amp;Isolated Components Below Threshold</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<spacer name="verticalSpacer_1">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QPushButton" name="Select_all_button">
<property name="toolTip">
<string extracomment="Select all simplices of Selection Type"/>
</property>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Select &amp;All</string>
<string>Sharp edges angle:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Inverse_selection_button">
<property name="toolTip">
<string extracomment="Invert selection for Selection Type"/>
<widget class="QSpinBox" name="Sharp_angle_spinbox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Invert Selection</string>
<property name="maximum">
<number>180</number>
</property>
<property name="value">
<number>60</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Clear_button">
<property name="toolTip">
<string extracomment="Clear selection for Selection Type"/>
</property>
<widget class="QPushButton" name="Select_sharp_edges_button">
<property name="text">
<string>&amp;Clear</string>
<string>Select</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Expand or reduce selection:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="Expand_reduce_spin_box">
<property name="minimum">
<number>-50</number>
</property>
<property name="maximum">
<number>50</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Expand_reduce_button">
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13" stretch="1,0">
<item>
<widget class="QComboBox" name="operationsBox">
<item>
<property name="text">
<string>Create Point Set Item from Selected Vertices</string>
</property>
</item>
<item>
<property name="text">
<string>Create Polyline Item from Selected Edges</string>
</property>
</item>
<item>
<property name="text">
<string>Create Polyhedron Item from Selected Facets</string>
</property>
</item>
<item>
<property name="text">
<string>Erase Selected Facets from Polyhedron Item</string>
</property>
</item>
<item>
<property name="text">
<string>Keep Connected Components of Selected Facets</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QPushButton" name="validateButton">
<property name="text">
<string>Validate</string>
</property>
</widget>
</item>
@ -156,216 +399,6 @@
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Isolated &amp;Component Size:</string>
</property>
<property name="buddy">
<cstring>Threshold_size_spin_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="Threshold_size_spin_box">
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>8</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Get_minimum_button">
<property name="text">
<string>&amp;Get Minimum</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="Select_isolated_components_button">
<property name="text">
<string>Select &amp;Isolated Components Below Threshold</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Sharp edges angle:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="Sharp_angle_spinbox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>180</number>
</property>
<property name="value">
<number>60</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Select_sharp_edges_button">
<property name="text">
<string>Select</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_1">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Expand or reduce selection:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="Expand_reduce_spin_box">
<property name="minimum">
<number>-50</number>
</property>
<property name="maximum">
<number>50</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Expand_reduce_button">
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="Create_point_set_item_button">
<property name="text">
<string>Create Point Set Item from Selected Vertices</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Create_polyline_item_button">
<property name="text">
<string>Create Polyline Item from Selected Edges</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Create_polyhedron_item_button">
<property name="text">
<string>Create Polyhedron Item from Selected Facets</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Erase_selected_facets_button">
<property name="text">
<string>Erase Selected Facets from Polyhedron Item</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Keep_connected_components_button">
<property name="toolTip">
<string extracomment="from selected facets"/>
</property>
<property name="text">
<string>Keep connected components of Selected Facets</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
@ -393,6 +426,94 @@
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="edition_groupBox">
<property name="title">
<string>Editions Operations</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<layout class="QVBoxLayout" name="verticalLayout_9" stretch="0,1,0">
<item>
<widget class="QComboBox" name="editionBox">
<item>
<property name="text">
<string>Join vertex</string>
</property>
</item>
<item>
<property name="text">
<string>Split vertex</string>
</property>
</item>
<item>
<property name="text">
<string>Split edges</string>
</property>
</item>
<item>
<property name="text">
<string>Join face</string>
</property>
</item>
<item>
<property name="text">
<string>Split face</string>
</property>
</item>
<item>
<property name="text">
<string>Collapse edge</string>
</property>
</item>
<item>
<property name="text">
<string>Flip edge</string>
</property>
</item>
<item>
<property name="text">
<string>Add center vertex</string>
</property>
</item>
<item>
<property name="text">
<string>Remove center vertex</string>
</property>
</item>
<item>
<property name="text">
<string>Add vertex and face to border (Advanced)</string>
</property>
</item>
<item>
<property name="text">
<string>Add face to border (Advanced)</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="instructionsLabel">
<property name="text">
<string>Instructions
</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Ctrl+Z to cancel the temporary selection.</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>

View File

@ -40,6 +40,7 @@ typedef boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
typedef boost::graph_traits<Polyhedron>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<Polyhedron>::edge_descriptor edge_descriptor;
class Scene_spheres_item;
namespace PMP = CGAL::Polygon_mesh_processing;
struct Array_based_vertex_point_map
{
public:

View File

@ -32,7 +32,7 @@ typedef CGAL::Triangulation_face_base_with_info_2<Face_info,
P_traits> Fb1;
typedef CGAL::Constrained_triangulation_face_base_2<P_traits, Fb1> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef CGAL::No_intersection_tag Itag;
typedef CGAL::Exact_predicates_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits,
TDS,
Itag> CDTbase;

View File

@ -166,7 +166,7 @@ typedef CGAL::Triangulation_face_base_with_info_2<Face_info,
P_traits> Fb1;
typedef CGAL::Constrained_triangulation_face_base_2<P_traits, Fb1> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef CGAL::No_intersection_tag Itag;
typedef CGAL::Exact_predicates_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits,
TDS,
Itag> CDTbase;

View File

@ -8,8 +8,6 @@
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_face_graph_triangle_primitive.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
@ -39,33 +37,190 @@
#include <boost/container/flat_map.hpp>
namespace PMP = CGAL::Polygon_mesh_processing;
//Used to triangulate the AABB_Tree
class Primitive
{
public:
// types
typedef Polyhedron::Facet_iterator Id; // Id type
typedef Kernel::Point_3 Point; // point type
typedef Kernel::Triangle_3 Datum; // datum type
private:
// member data
Id m_it; // iterator
Datum m_datum; // 3D triangle
// constructor
public:
Primitive() {}
Primitive(Datum triangle, Id it)
: m_it(it), m_datum(triangle)
{
}
public:
Id& id() { return m_it; }
const Id& id() const { return m_it; }
Datum& datum() { return m_datum; }
const Datum& datum() const { return m_datum; }
/// Returns a point on the primitive
Point reference_point() const { return m_datum.vertex(0); }
};
typedef CGAL::AABB_face_graph_triangle_primitive<Polyhedron> Primitive;
typedef CGAL::AABB_traits<Kernel, Primitive> AABB_traits;
typedef CGAL::AABB_tree<AABB_traits> Input_facets_AABB_tree;
const char* aabb_property_name = "Scene_polyhedron_item aabb tree";
Input_facets_AABB_tree* get_aabb_tree(Scene_polyhedron_item* item)
typedef Polyhedron::Traits Traits;
typedef Polyhedron::Facet Facet;
typedef CGAL::Triangulation_2_projection_traits_3<Traits> P_traits;
typedef Polyhedron::Halfedge_handle Halfedge_handle;
struct Face_info {
Polyhedron::Halfedge_handle e[3];
bool is_external;
};
typedef CGAL::Triangulation_vertex_base_with_info_2<Halfedge_handle,
P_traits> Vb;
typedef CGAL::Triangulation_face_base_with_info_2<Face_info,
P_traits> Fb1;
typedef CGAL::Constrained_triangulation_face_base_2<P_traits, Fb1> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef CGAL::Exact_predicates_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits,
TDS,
Itag> CDTbase;
typedef CGAL::Constrained_triangulation_plus_2<CDTbase> CDT;
//Make sure all the facets are triangles
typedef Polyhedron::Traits Kernel;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
typedef Polyhedron::Halfedge_around_facet_circulator HF_circulator;
typedef boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
QList<Kernel::Triangle_3> triangulate_primitive(Polyhedron::Facet_iterator fit,
Traits::Vector_3 normal)
{
QVariant aabb_tree_property = item->property(aabb_property_name);
if(aabb_tree_property.isValid()) {
void* ptr = aabb_tree_property.value<void*>();
return static_cast<Input_facets_AABB_tree*>(ptr);
//The output list
QList<Kernel::Triangle_3> res;
//check if normal contains NaN values
if (normal.x() != normal.x() || normal.y() != normal.y() || normal.z() != normal.z())
{
qDebug()<<"Warning in triangulation of the selection item: normal contains NaN values and is not valid.";
return QList<Kernel::Triangle_3>();
}
P_traits cdt_traits(normal);
CDT cdt(cdt_traits);
Facet::Halfedge_around_facet_circulator
he_circ = fit->facet_begin(),
he_circ_end(he_circ);
// Iterates on the vector of facet handles
typedef boost::graph_traits<Polyhedron>::vertex_descriptor vertex_descriptor;
boost::container::flat_map<CDT::Vertex_handle, vertex_descriptor> v2v;
CDT::Vertex_handle previous, first;
do {
CDT::Vertex_handle vh = cdt.insert(he_circ->vertex()->point());
v2v.insert(std::make_pair(vh, he_circ->vertex()));
if(first == 0) {
first = vh;
}
else {
Polyhedron* poly = item->polyhedron();
if(poly) {
Input_facets_AABB_tree* tree =
new Input_facets_AABB_tree(faces(*poly).first,
faces(*poly).second,
*poly);
item->setProperty(aabb_property_name,
QVariant::fromValue<void*>(tree));
return tree;
vh->info() = he_circ;
if(previous != 0 && previous != vh) {
cdt.insert_constraint(previous, vh);
}
previous = vh;
} while( ++he_circ != he_circ_end );
cdt.insert_constraint(previous, first);
// sets mark is_external
for(CDT::All_faces_iterator
fit2 = cdt.all_faces_begin(),
end = cdt.all_faces_end();
fit2 != end; ++fit2)
{
fit2->info().is_external = false;
}
//check if the facet is external or internal
std::queue<CDT::Face_handle> face_queue;
face_queue.push(cdt.infinite_vertex()->face());
while(! face_queue.empty() ) {
CDT::Face_handle fh = face_queue.front();
face_queue.pop();
if(fh->info().is_external) continue;
fh->info().is_external = true;
for(int i = 0; i <3; ++i) {
if(!cdt.is_constrained(std::make_pair(fh, i)))
{
face_queue.push(fh->neighbor(i));
}
}
}
//iterates on the internal faces to add the vertices to the positions
//and the normals to the appropriate vectors
for(CDT::Finite_faces_iterator
ffit = cdt.finite_faces_begin(),
end = cdt.finite_faces_end();
ffit != end; ++ffit)
{
if(ffit->info().is_external)
continue;
res << Kernel::Triangle_3(ffit->vertex(0)->point(),
ffit->vertex(1)->point(),
ffit->vertex(2)->point());
}
return res;
}
void* Scene_polyhedron_item::get_aabb_tree()
{
QVariant aabb_tree_property = this->property(aabb_property_name);
if(aabb_tree_property.isValid()) {
void* ptr = aabb_tree_property.value<void*>();
return static_cast<Input_facets_AABB_tree*>(ptr);
}
else {
Polyhedron* poly = this->polyhedron();
if(poly) {
Input_facets_AABB_tree* tree =
new Input_facets_AABB_tree();
typedef Polyhedron::Traits Kernel;
int index =0;
Q_FOREACH( Polyhedron::Facet_iterator f, faces(*poly))
{
if(!f->is_triangle())
{
Traits::Vector_3 normal = f->plane().orthogonal_vector(); //initialized in compute_normals_and_vertices
index +=3;
Q_FOREACH(Kernel::Triangle_3 triangle, triangulate_primitive(f,normal))
{
Primitive primitive(triangle, f);
tree->insert(primitive);
}
}
else return 0;
else
{
Kernel::Triangle_3 triangle(
f->halfedge()->vertex()->point(),
f->halfedge()->next()->vertex()->point(),
f->halfedge()->next()->next()->vertex()->point()
);
Primitive primitive(triangle, f);
tree->insert(primitive);
}
}
this->setProperty(aabb_property_name,
QVariant::fromValue<void*>(tree));
return tree;
}
else return 0;
}
}
void delete_aabb_tree(Scene_polyhedron_item* item)
@ -91,38 +246,15 @@ void push_back_xyz(const TypeWithXYZ& t,
vector.push_back(t.z());
}
typedef Polyhedron::Traits Traits;
typedef Polyhedron::Facet Facet;
typedef CGAL::Triangulation_2_projection_traits_3<Traits> P_traits;
typedef Polyhedron::Halfedge_handle Halfedge_handle;
struct Face_info {
Polyhedron::Halfedge_handle e[3];
bool is_external;
};
typedef CGAL::Triangulation_vertex_base_with_info_2<Halfedge_handle,
P_traits> Vb;
typedef CGAL::Triangulation_face_base_with_info_2<Face_info,
P_traits> Fb1;
typedef CGAL::Constrained_triangulation_face_base_2<P_traits, Fb1> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef CGAL::No_intersection_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits,
TDS,
Itag> CDTbase;
typedef CGAL::Constrained_triangulation_plus_2<CDTbase> CDT;
//Make sure all the facets are triangles
template<typename FaceNormalPmap, typename VertexNormalPmap>
template<typename VertexNormalPmap>
void
Scene_polyhedron_item::triangulate_facet(Facet_iterator fit,
const FaceNormalPmap& fnmap,
const Traits::Vector_3& normal,
const VertexNormalPmap& vnmap,
const bool colors_only) const
{
//Computes the normal of the facet
Traits::Vector_3 normal = get(fnmap, fit);
//check if normal contains NaN values
if (normal.x() != normal.x() || normal.y() != normal.y() || normal.z() != normal.z())
{
@ -408,11 +540,11 @@ Scene_polyhedron_item::compute_normals_and_vertices(const bool colors_only) cons
{
if (f == boost::graph_traits<Polyhedron>::null_face())
continue;
Vector nf = get(nf_pmap, f);
f->plane() = Kernel::Plane_3(f->halfedge()->vertex()->point(), nf);
if(is_triangle(f->halfedge(),*poly))
{
const int this_patch_id = f->patch_id();
Vector n = get(nf_pmap, f);
HF_circulator he = f->facet_begin();
HF_circulator end = he;
CGAL_For_all(he,end)
@ -427,7 +559,7 @@ Scene_polyhedron_item::compute_normals_and_vertices(const bool colors_only) cons
continue;
// If Flat shading:1 normal per polygon added once per vertex
push_back_xyz(n, normals_flat);
push_back_xyz(nf, normals_flat);
//// If Gouraud shading: 1 normal per vertex
Vector nv = get(nv_pmap, he->vertex());
@ -454,8 +586,6 @@ Scene_polyhedron_item::compute_normals_and_vertices(const bool colors_only) cons
if (colors_only)
continue;
Vector nf = get(nf_pmap, f);
//1st half-quad
Point p0 = f->halfedge()->vertex()->point();
Point p1 = f->halfedge()->next()->vertex()->point();
@ -512,7 +642,7 @@ Scene_polyhedron_item::compute_normals_and_vertices(const bool colors_only) cons
}
else
{
triangulate_facet(f, nf_pmap, nv_pmap, colors_only);
triangulate_facet(f, nf, nv_pmap, colors_only);
}
}
@ -576,6 +706,7 @@ Scene_polyhedron_item::Scene_polyhedron_item()
nb_lines = 0;
nb_f_lines = 0;
invalidate_stats();
init();
}
Scene_polyhedron_item::Scene_polyhedron_item(Polyhedron* const p)
@ -1011,107 +1142,94 @@ Scene_polyhedron_item::select(double orig_x,
double dir_y,
double dir_z)
{
if(facet_picking_m) {
typedef Input_facets_AABB_tree Tree;
typedef Tree::Object_and_primitive_id Object_and_primitive_id;
void* vertex_to_emit = 0;
if(facet_picking_m) {
typedef Input_facets_AABB_tree Tree;
Tree* aabb_tree = get_aabb_tree(this);
if(aabb_tree) {
const Kernel::Point_3 ray_origin(orig_x, orig_y, orig_z);
const Kernel::Vector_3 ray_dir(dir_x, dir_y, dir_z);
const Kernel::Ray_3 ray(ray_origin, ray_dir);
typedef std::list<Object_and_primitive_id> Intersections;
Intersections intersections;
aabb_tree->all_intersections(ray, std::back_inserter(intersections));
Intersections::iterator closest = intersections.begin();
if(closest != intersections.end()) {
const Kernel::Point_3* closest_point =
CGAL::object_cast<Kernel::Point_3>(&closest->first);
for(Intersections::iterator
it = boost::next(intersections.begin()),
end = intersections.end();
it != end; ++it)
{
if(! closest_point) {
closest = it;
}
else {
const Kernel::Point_3* it_point =
CGAL::object_cast<Kernel::Point_3>(&it->first);
if(it_point &&
(ray_dir * (*it_point - *closest_point)) < 0)
{
closest = it;
closest_point = it_point;
}
}
}
if(closest_point) {
Polyhedron::Facet_handle selected_fh = closest->second;
// The computation of the nearest vertex may be costly. Only
// do it if some objects are connected to the signal
// 'selected_vertex'.
if(QObject::receivers(SIGNAL(selected_vertex(void*))) > 0)
{
Polyhedron::Halfedge_around_facet_circulator
he_it = selected_fh->facet_begin(),
around_end = he_it;
Tree* aabb_tree = static_cast<Input_facets_AABB_tree*>(get_aabb_tree());
if(aabb_tree) {
const Kernel::Point_3 ray_origin(orig_x, orig_y, orig_z);
const Kernel::Vector_3 ray_dir(dir_x, dir_y, dir_z);
const Kernel::Ray_3 ray(ray_origin, ray_dir);
const boost::optional< Tree::Intersection_and_primitive_id<Kernel::Ray_3>::Type >
variant = aabb_tree->first_intersection(ray);
if(variant)
{
const Kernel::Point_3* closest_point = boost::get<Kernel::Point_3>( &variant->first );
if(closest_point) {
Polyhedron::Facet_handle selected_fh = variant->second;
// The computation of the nearest vertex may be costly. Only
// do it if some objects are connected to the signal
// 'selected_vertex'.
if(QObject::receivers(SIGNAL(selected_vertex(void*))) > 0)
{
Polyhedron::Halfedge_around_facet_circulator
he_it = selected_fh->facet_begin(),
around_end = he_it;
Polyhedron::Vertex_handle v = he_it->vertex(), nearest_v = v;
Polyhedron::Vertex_handle v = he_it->vertex(), nearest_v = v;
Kernel::FT sq_dist = CGAL::squared_distance(*closest_point,
v->point());
while(++he_it != around_end) {
v = he_it->vertex();
Kernel::FT new_sq_dist = CGAL::squared_distance(*closest_point,
v->point());
if(new_sq_dist < sq_dist) {
sq_dist = new_sq_dist;
nearest_v = v;
}
}
//bottleneck
Q_EMIT selected_vertex((void*)(&*nearest_v));
}
Kernel::FT sq_dist = CGAL::squared_distance(*closest_point,
v->point());
while(++he_it != around_end) {
v = he_it->vertex();
Kernel::FT new_sq_dist = CGAL::squared_distance(*closest_point,
v->point());
if(new_sq_dist < sq_dist) {
sq_dist = new_sq_dist;
nearest_v = v;
}
}
vertex_to_emit = (void*)(&*nearest_v);
}
if(QObject::receivers(SIGNAL(selected_edge(void*))) > 0
if(QObject::receivers(SIGNAL(selected_edge(void*))) > 0
|| QObject::receivers(SIGNAL(selected_halfedge(void*))) > 0)
{
Polyhedron::Halfedge_around_facet_circulator
he_it = selected_fh->facet_begin(),
around_end = he_it;
{
Polyhedron::Halfedge_around_facet_circulator
he_it = selected_fh->facet_begin(),
around_end = he_it;
Polyhedron::Halfedge_handle nearest_h = he_it;
Kernel::FT sq_dist = CGAL::squared_distance(*closest_point,
Kernel::Segment_3(he_it->vertex()->point(), he_it->opposite()->vertex()->point()));
Polyhedron::Halfedge_handle nearest_h = he_it;
Kernel::FT sq_dist = CGAL::squared_distance(*closest_point,
Kernel::Segment_3(he_it->vertex()->point(),
he_it->opposite()->
vertex()->
point()));
while(++he_it != around_end) {
Kernel::FT new_sq_dist = CGAL::squared_distance(*closest_point,
Kernel::Segment_3(he_it->vertex()->point(), he_it->opposite()->vertex()->point()));
if(new_sq_dist < sq_dist) {
sq_dist = new_sq_dist;
nearest_h = he_it;
}
}
while(++he_it != around_end)
{
Kernel::FT new_sq_dist = CGAL::squared_distance(*closest_point,
Kernel::Segment_3(he_it->vertex()->point(),
he_it->opposite()->
vertex()->
point()));
if(new_sq_dist < sq_dist) {
sq_dist = new_sq_dist;
nearest_h = he_it;
}
}
Q_EMIT selected_halfedge((void*)(&*nearest_h));
Q_EMIT selected_edge((void*)(std::min)(&*nearest_h, &*nearest_h->opposite()));
}
}
Q_EMIT selected_vertex(vertex_to_emit);
Q_EMIT selected_facet((void*)(&*selected_fh));
if(erase_next_picked_facet_m) {
polyhedron()->erase_facet(selected_fh->halfedge());
polyhedron()->normalize_border();
//set_erase_next_picked_facet(false);
invalidateOpenGLBuffers();
if(erase_next_picked_facet_m) {
polyhedron()->erase_facet(selected_fh->halfedge());
polyhedron()->normalize_border();
//set_erase_next_picked_facet(false);
invalidateOpenGLBuffers();
Q_EMIT itemChanged();
}
}
}
}
}
}
}
Base::select(orig_x, orig_y, orig_z, dir_x, dir_y, dir_z);
}
Base::select(orig_x, orig_y, orig_z, dir_x, dir_y, dir_z);
Q_EMIT selection_done();
}
void Scene_polyhedron_item::update_vertex_indices()

View File

@ -109,13 +109,13 @@ public Q_SLOTS:
double dir_x,
double dir_y,
double dir_z);
void update_vertex_indices();
void update_facet_indices();
void update_halfedge_indices();
void invalidate_aabb_tree();
Q_SIGNALS:
void selection_done();
void selected_vertex(void*);
void selected_facet(void*);
void selected_edge(void*);
@ -149,7 +149,7 @@ private:
Edges,
Feature_edges,
Gouraud_Facets,
NbOfVaos = Gouraud_Facets+1
NbOfVaos
};
enum VBOs {
Facets_vertices = 0,
@ -159,7 +159,7 @@ private:
Feature_edges_vertices,
Edges_color,
Facets_normals_gouraud,
NbOfVbos = Facets_normals_gouraud+1
NbOfVbos
};
mutable std::vector<float> positions_lines;
@ -180,10 +180,11 @@ private:
using CGAL::Three::Scene_item::initializeBuffers;
void initializeBuffers(CGAL::Three::Viewer_interface *viewer = 0) const;
void compute_normals_and_vertices(const bool colors_only = false) const;
template<typename FaceNormalPmap, typename VertexNormalPmap>
template<typename VertexNormalPmap>
void triangulate_facet(Facet_iterator,
const FaceNormalPmap&, const VertexNormalPmap&,
const Polyhedron::Traits::Vector_3&, const VertexNormalPmap&,
const bool colors_only) const;
void* get_aabb_tree();
double volume, area;
int m_min_patch_id; // the min value of the patch ids initialized in init()

View File

@ -43,21 +43,24 @@ public:
Scene_polyhedron_item_k_ring_selection
(Scene_polyhedron_item* poly_item, QMainWindow* mw, Active_handle::Type aht, int k_ring)
:is_active(false)
:is_active(false), is_edit_mode(false)
{
init(poly_item, mw, aht, k_ring);
}
void init(Scene_polyhedron_item* poly_item, QMainWindow* /*mw*/, Active_handle::Type aht, int k_ring) {
void setEditMode(bool b) { is_edit_mode = b; }
void init(Scene_polyhedron_item* poly_item, QMainWindow* mw, Active_handle::Type aht, int k_ring) {
this->poly_item = poly_item;
this->active_handle_type = aht;
this->k_ring = k_ring;
mainwindow = mw;
poly_item->enable_facets_picking(true);
poly_item->set_color_vector_read_only(true);
QGLViewer* viewer = *QGLViewer::QGLViewerPool().begin();
viewer->installEventFilter(this);
mw->installEventFilter(this);
#if QGLVIEWER_VERSION >= 0x020501
viewer->setMouseBindingDescription(Qt::Key_D, Qt::ShiftModifier, Qt::LeftButton, "(When in selection plugin) Removes the clicked primitive from the selection. ");
#else
@ -73,8 +76,9 @@ public Q_SLOTS:
void vertex_has_been_selected(void* void_ptr)
{
is_active=true;
if(active_handle_type != Active_handle::VERTEX) { return; }
process_selection( static_cast<Polyhedron::Vertex*>(void_ptr)->halfedge()->vertex() );
if(active_handle_type == Active_handle::VERTEX)
process_selection( static_cast<Polyhedron::Vertex*>(void_ptr)->halfedge()->vertex() );
updateIsTreated();
}
void facet_has_been_selected(void* void_ptr)
{
@ -82,23 +86,37 @@ public Q_SLOTS:
if (active_handle_type == Active_handle::FACET
|| active_handle_type == Active_handle::CONNECTED_COMPONENT)
process_selection(static_cast<Polyhedron::Facet*>(void_ptr)->halfedge()->facet());
updateIsTreated();
}
void edge_has_been_selected(void* void_ptr)
{
is_active=true;
if(active_handle_type != Active_handle::EDGE) { return; }
process_selection( edge(static_cast<Polyhedron::Halfedge*>(void_ptr)->opposite()->opposite(), *poly_item->polyhedron()) );
if(active_handle_type == Active_handle::EDGE)
process_selection( edge(static_cast<Polyhedron::Halfedge*>(void_ptr)->opposite()->opposite(), *poly_item->polyhedron()) );
updateIsTreated();
}
Q_SIGNALS:
void selected(const std::set<Polyhedron::Vertex_handle>&);
void selected(const std::set<Polyhedron::Facet_handle>&);
void selected(const std::set<edge_descriptor>&);
void toogle_insert(const bool);
void endSelection();
void resetIsTreated();
protected:
void updateIsTreated()
{
static ushort i = 0;
i++;
if(i==3)
{
i = 0;
Q_EMIT resetIsTreated();
}
}
template<class HandleType>
void process_selection(HandleType clicked) {
const std::set<HandleType>& selection = extract_k_ring(clicked, k_ring);
@ -169,9 +187,10 @@ protected:
}
bool eventFilter(QObject* /*target*/, QEvent *event)
bool eventFilter(QObject* target, QEvent *event)
{
// This filter is both filtering events from 'viewer' and 'main window'
// key events
if(event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
@ -193,6 +212,12 @@ protected:
}
// mouse events
if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) {
if(!state.shift_pressing && target == mainwindow)
{
QGLViewer* viewer = *QGLViewer::QGLViewerPool().begin();
viewer->setFocus();
return false;
}
QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
if(mouse_event->button() == Qt::LeftButton) {
state.left_button_pressing = event->type() == QEvent::MouseButtonPress;
@ -205,16 +230,22 @@ protected:
}
//to avoid the contextual menu to mess up the states.
else if(mouse_event->button() == Qt::RightButton) {
state.left_button_pressing = false;
state.shift_pressing = false;
}
state.left_button_pressing = false;
state.shift_pressing = false;
}
}
// use mouse move event for paint-like selection
if( (event->type() == QEvent::MouseMove
|| (event->type() == QEvent::MouseButtonPress
&& static_cast<QMouseEvent*>(event)->button() == Qt::LeftButton))
&& (state.shift_pressing && state.left_button_pressing) )
// if not in edit mode, use mouse move event for paint-like selection
if( (!is_edit_mode && event->type() == QEvent::MouseMove && state.shift_pressing && state.left_button_pressing)
||
(event->type() == QEvent::MouseButtonPress && static_cast<QMouseEvent*>(event)->button() == Qt::LeftButton && state.shift_pressing ))
{
if(target == mainwindow)
{
QGLViewer* viewer = *QGLViewer::QGLViewerPool().begin();
viewer->setFocus();
return false;
}
// paint with mouse move event
QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
QGLViewer* viewer = *QGLViewer::QGLViewerPool().begin();
@ -231,6 +262,9 @@ protected:
}//end MouseMove
return false;
}
bool is_edit_mode;
QMainWindow *mainwindow;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,7 @@
#include <CGAL/boost/graph/selection.h>
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
#include <CGAL/boost/graph/Euler_operations.h>
namespace PMP = CGAL::Polygon_mesh_processing;
@ -184,13 +185,15 @@ public:
Scene_polyhedron_selection_item()
: Scene_polyhedron_item_decorator(NULL, false)
{
for(int i=0; i<3; i++)
original_sel_mode = static_cast<Active_handle::Type>(0);
this ->operation_mode = -1;
for(int i=0; i<6; i++)
{
addVaos(i);
vaos[i]->create();
}
for(int i=0; i<7; i++)
for(int i=0; i<10; i++)
{
buffers[i].create();
}
@ -198,28 +201,36 @@ public:
nb_points = 0;
nb_lines = 0;
this->setColor(facet_color);
first_selected = false;
is_treated = false;
poly_need_update = false;
}
Scene_polyhedron_selection_item(Scene_polyhedron_item* poly_item, QMainWindow* mw)
: Scene_polyhedron_item_decorator(NULL, false)
{
original_sel_mode = static_cast<Active_handle::Type>(0);
this ->operation_mode = -1;
nb_facets = 0;
nb_points = 0;
nb_lines = 0;
for(int i=0; i<3; i++)
for(int i=0; i<6; i++)
{
addVaos(i);
vaos[i]->create();
}
for(int i=0; i<7; i++)
for(int i=0; i<8; i++)
{
buffers[i].create();
}
init(poly_item, mw);
this->setColor(facet_color);
invalidateOpenGLBuffers();
first_selected = false;
is_treated = false;
poly_need_update = false;
}
~Scene_polyhedron_selection_item()
@ -237,9 +248,12 @@ protected:
SLOT(selected(const std::set<Polyhedron::Facet_handle>&)));
connect(&k_ring_selector, SIGNAL(selected(const std::set<edge_descriptor>&)), this,
SLOT(selected(const std::set<edge_descriptor>&)));
connect(poly_item, SIGNAL(selection_done()), this, SLOT(update_poly()));
connect(&k_ring_selector, SIGNAL(endSelection()), this,SLOT(endSelection()));
connect(&k_ring_selector, SIGNAL(toogle_insert(bool)), this,SLOT(toggle_insert(bool)));
k_ring_selector.init(poly_item, mw, Active_handle::VERTEX, -1);
connect(&k_ring_selector, SIGNAL(resetIsTreated()), this, SLOT(resetIsTreated()));
QGLViewer* viewer = *QGLViewer::QGLViewerPool().begin();
viewer->installEventFilter(this);
@ -787,14 +801,32 @@ public:
}
Q_SIGNALS:
void updateInstructions(QString);
void simplicesSelected(CGAL::Three::Scene_item*);
public Q_SLOTS:
void update_poly()
{
if(poly_need_update)
poly_item->invalidateOpenGLBuffers();
}
void on_Ctrlz_pressed();
void emitTempInstruct();
void resetIsTreated() { is_treated = false;}
void save_handleType()
{
original_sel_mode = get_active_handle_type();
}
void set_operation_mode(int mode);
void invalidateOpenGLBuffers() {
// do not use decorator function, which calls changed on poly_item which cause deletion of AABB
// poly_item->invalidateOpenGLBuffers();
are_buffers_filled = false;
are_temp_buffers_filled = false;
poly = polyhedron();
compute_bbox();
}
// slots are called by signals of polyhedron_k_ring_selector
@ -820,6 +852,14 @@ public Q_SLOTS:
protected:
bool eventFilter(QObject* /*target*/, QEvent * gen_event)
{
if(gen_event->type() == QEvent::KeyPress
&& static_cast<QKeyEvent*>(gen_event)->key()==Qt::Key_Z)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(gen_event);
if(keyEvent->modifiers().testFlag(Qt::ControlModifier))
on_Ctrlz_pressed();
}
if(!visible() || !k_ring_selector.state.shift_pressing) { return false; }
if(gen_event->type() == QEvent::Wheel)
{
@ -849,24 +889,23 @@ protected:
}
}
template<typename HandleRange>
bool treat_selection(const HandleRange& selection)
{
typedef typename HandleRange::value_type HandleType;
Selection_traits<HandleType, Scene_polyhedron_selection_item> tr(this);
bool any_change = false;
if(is_insert) {
BOOST_FOREACH(HandleType h, selection)
any_change |= tr.container().insert(h).second;
}
else{
BOOST_FOREACH(HandleType h, selection)
any_change |= (tr.container().erase(h)!=0);
}
if(any_change) { invalidateOpenGLBuffers(); Q_EMIT itemChanged(); }
return any_change;
}
//Generic class
template<typename HandleRange>
bool treat_selection(const HandleRange&)
{
qDebug()<<"ERROR : unknown HandleRange";
return false;
}
template<typename HandleRange>
bool treat_classic_selection(const HandleRange& selection);
//Specialization for set<Vertex_handle>
bool treat_selection(const std::set<Polyhedron::Vertex_handle>& selection);
bool treat_selection(const std::set<edge_descriptor>& selection);
bool treat_selection(const std::set<Polyhedron::Facet_handle>& selection);
bool treat_selection(const std::vector<Polyhedron::Facet_handle>& selection);
Facet_handle face(Facet_handle fh)
{ return fh; }
@ -904,6 +943,7 @@ protected:
}
}
public:
Is_selected_property_map<edge_descriptor>
selected_edges_pmap(std::vector<bool>& mark)
@ -943,11 +983,27 @@ public:
Selection_set_vertex selected_vertices;
Selection_set_facet selected_facets;
Selection_set_edge selected_edges; // stores one halfedge for each pair (halfedge with minimum address)
Selection_set_vertex temp_selected_vertices;
Selection_set_facet temp_selected_facets;
Selection_set_edge temp_selected_edges; // stores one halfedge for each pair (halfedge with minimum address)
//
QColor vertex_color, facet_color, edge_color;
private:
bool poly_need_update;
mutable bool are_temp_buffers_filled;
//Specifies Selection/edition mode
bool first_selected;
int operation_mode;
QString m_temp_instructs;
bool is_treated;
Vertex_handle to_split_vh;
Facet_handle to_split_fh;
edge_descriptor to_join_ed;
Active_handle::Type original_sel_mode;
//Only needed for the triangulation
Polyhedron* poly;
mutable std::vector<float> positions_facets;
mutable std::vector<float> normals;
mutable std::vector<float> positions_lines;
@ -955,11 +1011,29 @@ private:
mutable std::size_t nb_facets;
mutable std::size_t nb_points;
mutable std::size_t nb_lines;
mutable std::vector<float> positions_temp_facets;
mutable std::vector<float> temp_normals;
mutable std::vector<float> positions_temp_lines;
mutable std::vector<float> positions_temp_points;
mutable std::size_t nb_temp_facets;
mutable std::size_t nb_temp_points;
mutable std::size_t nb_temp_lines;
mutable QOpenGLShaderProgram *program;
using CGAL::Three::Scene_item::initializeBuffers;
void initializeBuffers(CGAL::Three::Viewer_interface *viewer) const;
void initialize_temp_buffers(CGAL::Three::Viewer_interface *viewer) const;
void computeElements() const;
void compute_any_elements(std::vector<float> &p_facets, std::vector<float> &p_lines, std::vector<float> &p_points, std::vector<float> &p_normals,
const Selection_set_vertex& p_sel_vertex, const Selection_set_facet &p_sel_facet, const Selection_set_edge &p_sel_edges) const;
void compute_temp_elements() const;
template<typename FaceNormalPmap>
void triangulate_facet(Facet_handle, const FaceNormalPmap&,
std::vector<float> &p_facets,std::vector<float> &p_normals) const;
void tempInstructions(QString s1, QString s2);
};
#endif
#endif