From 02a46781594b5fc91df74efd081713dc01adbddd Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 29 Jul 2015 10:35:11 +0200 Subject: [PATCH] Point set selection widget and global selection tools (all, clear, revert, new objet, etc.) --- Polyhedron/demo/Polyhedron/CMakeLists.txt | 4 + .../Polyhedron/Point_set_selection_widget.ui | 151 +++++++++++ ...hedron_demo_point_set_selection_plugin.cpp | 159 ++++++++++++ .../Scene_points_with_normal_item.cpp | 241 +++++++++--------- .../Scene_points_with_normal_item.h | 4 + .../demo/Polyhedron/cgal_test_with_cmake | 1 + .../demo/Polyhedron/include/Point_set_3.h | 9 + 7 files changed, 454 insertions(+), 115 deletions(-) create mode 100644 Polyhedron/demo/Polyhedron/Point_set_selection_widget.ui create mode 100644 Polyhedron/demo/Polyhedron/Polyhedron_demo_point_set_selection_plugin.cpp diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 71788125cf2..9e38a66ea21 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -79,6 +79,7 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) qt5_wrap_ui( cameraUI_FILES Camera_positions_list.ui ) qt5_wrap_ui( PreferencesUI_FILES Preferences.ui ) qt5_wrap_ui( point_inside_polyhedronUI_FILES Point_inside_polyhedron_widget.ui) + qt5_wrap_ui( point_set_selectionUI_FILES Point_set_selection_widget.ui) qt5_wrap_ui( polyhedron_slicerUI_FILES Polyhedron_slicer_widget.ui) qt5_wrap_ui( segmentationUI_FILES Mesh_segmentation_widget.ui) qt5_wrap_ui( hole_fillingUI_FILES Hole_filling_widget.ui) @@ -429,6 +430,9 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) qt5_wrap_ui( ps_outliers_removal_UI_FILES Polyhedron_demo_point_set_outliers_removal_plugin.ui) + polyhedron_demo_plugin(point_set_selection_plugin Polyhedron_demo_point_set_selection_plugin ${point_set_selectionUI_FILES}) + target_link_libraries(point_set_selection_plugin scene_points_with_normal_item) + qt5_wrap_ui(point_set_shape_detectionUI_FILES Polyhedron_demo_point_set_shape_detection_plugin.ui) polyhedron_demo_plugin(point_set_shape_detection_plugin Polyhedron_demo_point_set_shape_detection_plugin ${point_set_shape_detectionUI_FILES}) target_link_libraries(point_set_shape_detection_plugin scene_polyhedron_item scene_points_with_normal_item) diff --git a/Polyhedron/demo/Polyhedron/Point_set_selection_widget.ui b/Polyhedron/demo/Polyhedron/Point_set_selection_widget.ui new file mode 100644 index 00000000000..8e1c1afa88a --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Point_set_selection_widget.ui @@ -0,0 +1,151 @@ + + + PointSetSelection + + + + 0 + 0 + 369 + 239 + + + + Point Set Selection + + + + + + + + + + + Selection &Tool: + + + Selection_tool_combo_box + + + + + + + + Rectangle + + + + + Free form + + + + + + + + + + + + 6 + + + QLayout::SetDefaultConstraint + + + + + Selection &Mode: + + + Selection_mode_combo_box + + + + + + + + New Selection + + + + + Union + + + + + Intersection + + + + + Difference + + + + + + + + + + + + Select &All + + + + + + + &Clear + + + + + + + + + &Invert Selection + + + + + + + &Erase Selected Points + + + + + + + Create Point Set Item from Selected Points + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_point_set_selection_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_point_set_selection_plugin.cpp new file mode 100644 index 00000000000..6f7f0a1270c --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_point_set_selection_plugin.cpp @@ -0,0 +1,159 @@ +#include +#include "opengl_tools.h" + +#include "Messages_interface.h" +#include "Scene_points_with_normal_item.h" +#include "Scene_polylines_item.h" + +#include "Scene_interface.h" +#include "Polyhedron_demo_plugin_helper.h" +#include "ui_Point_set_selection_widget.h" +#include "Point_set_3.h" + +#include +#include +#include + +#include + + +class Polyhedron_demo_point_set_selection_plugin : + public QObject, + public Polyhedron_demo_plugin_helper +{ + Q_OBJECT + Q_INTERFACES(Polyhedron_demo_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") +public: + bool applicable(QAction*) const { + return qobject_cast(scene->item(scene->mainSelectionIndex())); + } + void print_message(QString message) { messages->information(message); } + QList actions() const { return QList() << actionPointSetSelection; } + using Polyhedron_demo_plugin_helper::init; + void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface* m) { + mw = mainWindow; + scene = scene_interface; + messages = m; + actionPointSetSelection = new QAction(tr("Selection"), mw); + connect(actionPointSetSelection, SIGNAL(triggered()), this, SLOT(selection_action())); + + dock_widget = new QDockWidget("Point Set Selection", mw); + dock_widget->setVisible(false); + + ui_widget.setupUi(dock_widget); + add_dock_widget(dock_widget); + + connect(ui_widget.Selection_tool_combo_box, SIGNAL(currentIndexChanged(int)), + this, SLOT(on_Selection_tool_combo_box_changed(int))); + connect(ui_widget.Selection_mode_combo_box, SIGNAL(currentIndexChanged(int)), + this, SLOT(on_Selection_mode_combo_box_changed(int))); + connect(ui_widget.Select_all_button, SIGNAL(clicked()), this, SLOT(on_Select_all_button_clicked())); + connect(ui_widget.Clear_button, SIGNAL(clicked()), this, SLOT(on_Clear_button_clicked())); + connect(ui_widget.Invert_selection_button, SIGNAL(clicked()), this, SLOT(on_Invert_selection_button_clicked())); + connect(ui_widget.Erase_selected_points_button, SIGNAL(clicked()), this, SLOT(on_Erase_selected_points_button_clicked())); + connect(ui_widget.Create_point_set_item_button, SIGNAL(clicked()), this, SLOT(on_Create_point_set_item_button_clicked())); + } + +public Q_SLOTS: + void selection_action() { + dock_widget->show(); + dock_widget->raise(); + Scene_points_with_normal_item* point_set_item + = qobject_cast(scene->item(scene->mainSelectionIndex())); + if(!point_set_item) + return; + } + + // Select all + void on_Select_all_button_clicked() { + Scene_points_with_normal_item* point_set_item = get_selected_item(); + if(!point_set_item) + { + print_message("Error: no point set selected!"); + return; + } + + point_set_item->selectAll(); + } + + // Clear selection + void on_Clear_button_clicked() { + Scene_points_with_normal_item* point_set_item + = qobject_cast(scene->item(scene->mainSelectionIndex())); + if(!point_set_item) { + print_message("Error: no point set selected!"); + return; + } + + point_set_item->resetSelection(); + } + + void on_Erase_selected_points_button_clicked() { + Scene_points_with_normal_item* point_set_item + = qobject_cast(scene->item(scene->mainSelectionIndex())); + if(!point_set_item) { + print_message("Error: no point set selected!"); + return; + } + + point_set_item->deleteSelection(); + } + + void on_Invert_selection_button_clicked() { + Scene_points_with_normal_item* point_set_item + = qobject_cast(scene->item(scene->mainSelectionIndex())); + if(!point_set_item) { + print_message("Error: no point set selected!"); + return; + } + + point_set_item->invertSelection(); + } + + void on_Create_point_set_item_button_clicked() { + Scene_points_with_normal_item* point_set_item + = qobject_cast(scene->item(scene->mainSelectionIndex())); + if(!point_set_item) { + print_message("Error: no point set selected!"); + return; + } + if(point_set_item->isSelectionEmpty ()) { + print_message("Error: there is no selected point in point set item!"); + return; + } + + Scene_points_with_normal_item* new_item = new Scene_points_with_normal_item(); + new_item->setName(QString("%1 (selected points)").arg(point_set_item->name())); + new_item->set_has_normals (point_set_item->has_normals()); + new_item->setColor(point_set_item->color()); + new_item->setRenderingMode(point_set_item->renderingMode()); + new_item->setVisible(point_set_item->visible()); + + typedef Point_set_3 Point_set; + for(typename Point_set::iterator it = point_set_item->point_set()->begin (); + it != point_set_item->point_set()->end(); ++ it) { + if (it->is_selected ()) + new_item->point_set()->push_back(*it); + } + new_item->resetSelection(); + new_item->changed(); + + scene->addItem(new_item); + } + + + +private: + Messages_interface* messages; + QAction* actionPointSetSelection; + + QDockWidget* dock_widget; + Ui::PointSetSelection ui_widget; + Scene_points_with_normal_item* point_set_item; + +}; // end Polyhedron_demo_point_set_selection_plugin + +//Q_EXPORT_PLUGIN2(Polyhedron_demo_point_set_selection_plugin, Polyhedron_demo_point_set_selection_plugin) + +#include "Polyhedron_demo_point_set_selection_plugin.moc" diff --git a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp index e4efe232a91..f30635f8dea 100644 --- a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp @@ -1,6 +1,6 @@ #include "Scene_points_with_normal_item.h" #include "Polyhedron_type.h" -#include +#include #include #include @@ -24,10 +24,10 @@ Scene_points_with_normal_item::Scene_points_with_normal_item() : Scene_item(3,3), - m_points(new Point_set), - m_has_normals(false) + m_points(new Point_set), + m_has_normals(false) { - setRenderingMode(Points); + setRenderingMode(Points); is_selected = true; qFunc.initializeOpenGLFunctions(); } @@ -35,18 +35,18 @@ Scene_points_with_normal_item::Scene_points_with_normal_item() // Copy constructor Scene_points_with_normal_item::Scene_points_with_normal_item(const Scene_points_with_normal_item& toCopy) : Scene_item(3,3), // do not call superclass' copy constructor - m_points(new Point_set(*toCopy.m_points)), - m_has_normals(toCopy.m_has_normals) + m_points(new Point_set(*toCopy.m_points)), + m_has_normals(toCopy.m_has_normals) { - if (m_has_normals) + if (m_has_normals) { - setRenderingMode(PointsPlusNormals); + setRenderingMode(PointsPlusNormals); is_selected = true; qFunc.initializeOpenGLFunctions(); } - else + else { - setRenderingMode(Points); + setRenderingMode(Points); is_selected = true; qFunc.initializeOpenGLFunctions(); } @@ -56,23 +56,20 @@ Scene_points_with_normal_item::Scene_points_with_normal_item(const Scene_points_ // Converts polyhedron to point set Scene_points_with_normal_item::Scene_points_with_normal_item(const Polyhedron& input_mesh) : Scene_item(6,3), - m_points(new Point_set), - m_has_normals(true) + m_points(new Point_set), + m_has_normals(true) { - // Converts Polyhedron vertices to point set. - // Computes vertices normal from connectivity. + // Converts Polyhedron vertices to point set. + // Computes vertices normal from connectivity. + Polyhedron::Vertex_const_iterator v; + for (v = input_mesh.vertices_begin(); v != input_mesh.vertices_end(); v++) + { + const Kernel::Point_3& p = v->point(); + Kernel::Vector_3 n = compute_vertex_normal(*v); + m_points->push_back(UI_point(p,n)); + } - Polyhedron::Vertex_iterator v; - for (v = const_cast(input_mesh).vertices_begin(); - v != const_cast(input_mesh).vertices_end(); v++) - { - const Kernel::Point_3& p = v->point(); - Kernel::Vector_3 n = - CGAL::Polygon_mesh_processing::compute_vertex_normal(v, input_mesh); - m_points->push_back(UI_point(p,n)); - } - - setRenderingMode(PointsPlusNormals); + setRenderingMode(PointsPlusNormals); is_selected = true; qFunc.initializeOpenGLFunctions(); changed(); @@ -80,8 +77,8 @@ Scene_points_with_normal_item::Scene_points_with_normal_item(const Polyhedron& i Scene_points_with_normal_item::~Scene_points_with_normal_item() { - Q_ASSERT(m_points != NULL); - delete m_points; m_points = NULL; + Q_ASSERT(m_points != NULL); + delete m_points; m_points = NULL; } @@ -244,130 +241,144 @@ void Scene_points_with_normal_item::compute_normals_and_vertices(void) Scene_points_with_normal_item* Scene_points_with_normal_item::clone() const { - return new Scene_points_with_normal_item(*this); + return new Scene_points_with_normal_item(*this); } // Is selection empty? bool Scene_points_with_normal_item::isSelectionEmpty() const { - return (m_points->nb_selected_points() == 0); + return (m_points->nb_selected_points() == 0); } // Delete selection void Scene_points_with_normal_item::deleteSelection() { - CGAL::Timer task_timer; task_timer.start(); - std::cerr << "Delete " << m_points->nb_selected_points() << " points..."; + CGAL::Timer task_timer; task_timer.start(); + std::cerr << "Delete " << m_points->nb_selected_points() << " points..."; - // Delete selected points - m_points->delete_selection(); + // Delete selected points + m_points->delete_selection(); - std::size_t memory = CGAL::Memory_sizer().virtual_size(); - std::cerr << "done: " << task_timer.time() << " seconds, " - << (memory>>20) << " Mb allocated" - << std::endl; + std::size_t memory = CGAL::Memory_sizer().virtual_size(); + std::cerr << "done: " << task_timer.time() << " seconds, " + << (memory>>20) << " Mb allocated" + << std::endl; + Q_EMIT itemChanged(); +} + +// Invert selection +void Scene_points_with_normal_item::invertSelection() +{ + m_points->invert_selection(); Q_EMIT itemChanged(); } // Reset selection mark -void Scene_points_with_normal_item::resetSelection() +void Scene_points_with_normal_item::selectAll() { - // Un-select all points - m_points->select(m_points->begin(), m_points->end(), false); + // Un-select all points + m_points->select(m_points->begin(), m_points->end(), true); Q_EMIT itemChanged(); } - //Select duplicated points +// Reset selection mark +void Scene_points_with_normal_item::resetSelection() +{ + // Un-select all points + m_points->select(m_points->begin(), m_points->end(), false); + Q_EMIT itemChanged(); +} +//Select duplicated points void Scene_points_with_normal_item::selectDuplicates() { - std::set unique_points; - for (Point_set::Point_iterator ptit=m_points->begin(); ptit!=m_points->end();++ptit ) - if ( !unique_points.insert(*ptit).second ) - m_points->select(&(*ptit)); + std::set unique_points; + for (Point_set::Point_iterator ptit=m_points->begin(); ptit!=m_points->end();++ptit ) + if ( !unique_points.insert(*ptit).second ) + m_points->select(&(*ptit)); Q_EMIT itemChanged(); } // Loads point set from .OFF file bool Scene_points_with_normal_item::read_off_point_set(std::istream& stream) { - Q_ASSERT(m_points != NULL); + Q_ASSERT(m_points != NULL); - m_points->clear(); - bool ok = stream && + m_points->clear(); + bool ok = stream && CGAL::read_off_points_and_normals(stream, std::back_inserter(*m_points), CGAL::make_normal_of_point_with_normal_pmap(Point_set::value_type())) && !isEmpty(); changed(); - return ok; + return ok; } // Write point set to .OFF file bool Scene_points_with_normal_item::write_off_point_set(std::ostream& stream) const { - Q_ASSERT(m_points != NULL); + Q_ASSERT(m_points != NULL); - return stream && - CGAL::write_off_points_and_normals(stream, - m_points->begin(), m_points->end(), - CGAL::make_normal_of_point_with_normal_pmap(Point_set::value_type())); + return stream && + CGAL::write_off_points_and_normals(stream, + m_points->begin(), m_points->end(), + CGAL::make_normal_of_point_with_normal_pmap(Point_set::value_type())); } // Loads point set from .XYZ file bool Scene_points_with_normal_item::read_xyz_point_set(std::istream& stream) { - Q_ASSERT(m_points != NULL); + Q_ASSERT(m_points != NULL); - m_points->clear(); - bool ok = stream && + m_points->clear(); + bool ok = stream && CGAL::read_xyz_points_and_normals(stream, std::back_inserter(*m_points), CGAL::make_normal_of_point_with_normal_pmap(Point_set::value_type())) && !isEmpty(); - if (ok) - { - for (Point_set::iterator it=m_points->begin(), - end=m_points->end();it!=end; ++it) + if (ok) { - if (it->normal() != CGAL::NULL_VECTOR) - { - m_has_normals=true; - setRenderingMode(PointsPlusNormals); - break; - } + for (Point_set::iterator it=m_points->begin(), + end=m_points->end();it!=end; ++it) + { + if (it->normal() != CGAL::NULL_VECTOR) + { + m_has_normals=true; + setRenderingMode(PointsPlusNormals); + break; + } + } } - } changed(); - return ok; + return ok; } // Write point set to .XYZ file bool Scene_points_with_normal_item::write_xyz_point_set(std::ostream& stream) const { - Q_ASSERT(m_points != NULL); + Q_ASSERT(m_points != NULL); - return stream && - CGAL::write_xyz_points_and_normals(stream, - m_points->begin(), m_points->end(), - CGAL::make_normal_of_point_with_normal_pmap(Point_set::value_type())); + return stream && + CGAL::write_xyz_points_and_normals(stream, + m_points->begin(), m_points->end(), + CGAL::make_normal_of_point_with_normal_pmap(Point_set::value_type())); } QString Scene_points_with_normal_item::toolTip() const { - Q_ASSERT(m_points != NULL); + Q_ASSERT(m_points != NULL); - return QObject::tr("

%1 (color: %4)
" - "Point set

" - "

Number of points: %2

") - .arg(name()) - .arg(m_points->size()) - .arg(color().name()); + return QObject::tr("

%1 (color: %4)
" + "Point set

" + "

Number of points: %2

") + .arg(name()) + .arg(m_points->size()) + .arg(color().name()); } -bool Scene_points_with_normal_item::supportsRenderingMode(RenderingMode m) const +bool Scene_points_with_normal_item::supportsRenderingMode(RenderingMode m) const { - return m==Points || + return m==Points || ( has_normals() && m==PointsPlusNormals ); } @@ -415,56 +426,56 @@ void Scene_points_with_normal_item::draw_points(Viewer_interface* viewer) const // Gets wrapped point set Point_set* Scene_points_with_normal_item::point_set() { - Q_ASSERT(m_points != NULL); - return m_points; + Q_ASSERT(m_points != NULL); + return m_points; } const Point_set* Scene_points_with_normal_item::point_set() const { - Q_ASSERT(m_points != NULL); - return m_points; + Q_ASSERT(m_points != NULL); + return m_points; } bool Scene_points_with_normal_item::isEmpty() const { - Q_ASSERT(m_points != NULL); - return m_points->empty(); + Q_ASSERT(m_points != NULL); + return m_points->empty(); } Scene_points_with_normal_item::Bbox Scene_points_with_normal_item::bbox() const { - Q_ASSERT(m_points != NULL); + Q_ASSERT(m_points != NULL); - Kernel::Iso_cuboid_3 bbox = m_points->bounding_box(); - return Bbox(bbox.xmin(),bbox.ymin(),bbox.zmin(), - bbox.xmax(),bbox.ymax(),bbox.zmax()); + Kernel::Iso_cuboid_3 bbox = m_points->bounding_box(); + return Bbox(bbox.xmin(),bbox.ymin(),bbox.zmin(), + bbox.xmax(),bbox.ymax(),bbox.zmax()); } void Scene_points_with_normal_item::computes_local_spacing(int k) { - typedef Kernel Geom_traits; - typedef CGAL::Search_traits_3 TreeTraits; - typedef CGAL::Orthogonal_k_neighbor_search Neighbor_search; - typedef Neighbor_search::Tree Tree; + typedef Kernel Geom_traits; + typedef CGAL::Search_traits_3 TreeTraits; + typedef CGAL::Orthogonal_k_neighbor_search Neighbor_search; + typedef Neighbor_search::Tree Tree; - Point_set::iterator end(m_points->end()); + Point_set::iterator end(m_points->end()); - // build kdtree - Tree tree(m_points->begin(), end); + // build kdtree + Tree tree(m_points->begin(), end); - // Compute the radius of each point = (distance max to k nearest neighbors)/2. - { - int i=0; - for (Point_set::iterator it=m_points->begin(); it!=end; ++it, ++i) + // Compute the radius of each point = (distance max to k nearest neighbors)/2. { - Neighbor_search search(tree, *it, k+1); - double maxdist2 = (--search.end())->second; // squared distance to furthest neighbor - it->radius() = sqrt(maxdist2)/2.; + int i=0; + for (Point_set::iterator it=m_points->begin(); it!=end; ++it, ++i) + { + Neighbor_search search(tree, *it, k+1); + double maxdist2 = (--search.end())->second; // squared distance to furthest neighbor + it->radius() = sqrt(maxdist2)/2.; + } } - } - m_points->set_radii_uptodate(true); + m_points->set_radii_uptodate(true); } QMenu* Scene_points_with_normal_item::contextMenu() @@ -515,12 +526,12 @@ void Scene_points_with_normal_item::setRenderingMode(RenderingMode m) bool Scene_points_with_normal_item::has_normals() const { return m_has_normals; } void Scene_points_with_normal_item::set_has_normals(bool b) { - if (b!=m_has_normals){ - m_has_normals=b; - //reset the context menu - delete this->defaultContextMenu; - this->defaultContextMenu = 0; - } + if (b!=m_has_normals){ + m_has_normals=b; + //reset the context menu + delete this->defaultContextMenu; + this->defaultContextMenu = 0; + } } void Scene_points_with_normal_item::changed() diff --git a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.h b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.h index 2b7ca2a214b..7cafc153119 100644 --- a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.h @@ -72,6 +72,10 @@ public: public Q_SLOTS: // Delete selection virtual void deleteSelection(); + // Invert selection + void invertSelection(); + // Select all points + void selectAll(); // Reset selection mark void resetSelection(); //Select duplicated points diff --git a/Polyhedron/demo/Polyhedron/cgal_test_with_cmake b/Polyhedron/demo/Polyhedron/cgal_test_with_cmake index 22b387487f5..11b88d3f40b 100755 --- a/Polyhedron/demo/Polyhedron/cgal_test_with_cmake +++ b/Polyhedron/demo/Polyhedron/cgal_test_with_cmake @@ -130,6 +130,7 @@ else point_inside_polyhedron_plugin \ point_set_average_spacing_plugin \ point_set_outliers_removal_plugin \ + point_set_selection_plugin \ point_set_shape_detection_plugin \ point_set_simplification_plugin \ point_set_smoothing_plugin \ diff --git a/Polyhedron/demo/Polyhedron/include/Point_set_3.h b/Polyhedron/demo/Polyhedron/include/Point_set_3.h index bc987f60f8c..e84d1712173 100644 --- a/Polyhedron/demo/Polyhedron/include/Point_set_3.h +++ b/Polyhedron/demo/Polyhedron/include/Point_set_3.h @@ -134,6 +134,15 @@ public: std::mem_fun_ref(&UI_point::is_selected)); } + // Invert selection + void invert_selection() + { + for (iterator it = begin(); it != end(); ++ it) + it->select(!(it->is_selected ())); + + m_nb_selected_points = size() - m_nb_selected_points; + } + /// Deletes selected points. void delete_selection() {