mirror of https://github.com/CGAL/cgal
Merge pull request #1044 from maxGimeno/Euler_operations-rebase-GF
Polyhedron demo : Euler operations in selection_plugin
This commit is contained in:
commit
ef13f66767
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 &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 &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>&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 &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>&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 &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 &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 &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>&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 &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>&Get Minimum</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="Select_isolated_components_button">
|
||||
<property name="text">
|
||||
<string>Select &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>
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue