Point set selection widget and global selection tools (all, clear, revert, new objet, etc.)

This commit is contained in:
Simon Giraudot 2015-07-29 10:35:11 +02:00
parent b30ac099a9
commit 02a4678159
7 changed files with 454 additions and 115 deletions

View File

@ -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)

View File

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PointSetSelection</class>
<widget class="QDockWidget" name="PointSetSelection">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>369</width>
<height>239</height>
</rect>
</property>
<property name="windowTitle">
<string>Point Set Selection</string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Selection &amp;Tool:</string>
</property>
<property name="buddy">
<cstring>Selection_tool_combo_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="Selection_tool_combo_box">
<item>
<property name="text">
<string>Rectangle</string>
</property>
</item>
<item>
<property name="text">
<string>Free form</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14" stretch="0,0">
<property name="spacing">
<number>6</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Selection &amp;Mode:</string>
</property>
<property name="buddy">
<cstring>Selection_mode_combo_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="Selection_mode_combo_box">
<item>
<property name="text">
<string>New Selection</string>
</property>
</item>
<item>
<property name="text">
<string>Union</string>
</property>
</item>
<item>
<property name="text">
<string>Intersection</string>
</property>
</item>
<item>
<property name="text">
<string>Difference</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="Select_all_button">
<property name="text">
<string>Select &amp;All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Clear_button">
<property name="text">
<string>&amp;Clear</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="Invert_selection_button">
<property name="text">
<string>&amp;Invert Selection</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Erase_selected_points_button">
<property name="text">
<string>&amp;Erase Selected Points</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Create_point_set_item_button">
<property name="text">
<string>Create Point Set Item from Selected Points</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>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,159 @@
#include <QtCore/qglobal.h>
#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 <QAction>
#include <QMainWindow>
#include <QApplication>
#include <map>
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_points_with_normal_item*>(scene->item(scene->mainSelectionIndex()));
}
void print_message(QString message) { messages->information(message); }
QList<QAction*> actions() const { return QList<QAction*>() << 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_points_with_normal_item*>(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<Scene_points_with_normal_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_points_with_normal_item*>(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_points_with_normal_item*>(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_points_with_normal_item*>(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_points_with_normal_item*>(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<Kernel> 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"

View File

@ -1,6 +1,6 @@
#include "Scene_points_with_normal_item.h"
#include "Polyhedron_type.h"
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
#include <CGAL/internal/Operations_on_polyhedra/compute_normal.h>
#include <CGAL/IO/read_off_points.h>
#include <CGAL/IO/write_off_points.h>
@ -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<Polyhedron::Vertex,Kernel>(*v);
m_points->push_back(UI_point(p,n));
}
Polyhedron::Vertex_iterator v;
for (v = const_cast<Polyhedron&>(input_mesh).vertices_begin();
v != const_cast<Polyhedron&>(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<Kernel::Point_3> 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<Kernel::Point_3> 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("<p><b>%1</b> (color: %4)<br />"
"<i>Point set</i></p>"
"<p>Number of points: %2</p>")
.arg(name())
.arg(m_points->size())
.arg(color().name());
return QObject::tr("<p><b>%1</b> (color: %4)<br />"
"<i>Point set</i></p>"
"<p>Number of points: %2</p>")
.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<Geom_traits> TreeTraits;
typedef CGAL::Orthogonal_k_neighbor_search<TreeTraits> Neighbor_search;
typedef Neighbor_search::Tree Tree;
typedef Kernel Geom_traits;
typedef CGAL::Search_traits_3<Geom_traits> TreeTraits;
typedef CGAL::Orthogonal_k_neighbor_search<TreeTraits> 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()

View File

@ -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

View File

@ -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 \

View File

@ -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()
{