1 #include "config.h"
2 #include "Scene_points_with_normal_item.h"
3 #include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
4 #include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
5
6 #include <CGAL/grid_simplify_point_set.h>
7 #include <CGAL/random_simplify_point_set.h>
8 #include <CGAL/hierarchy_simplify_point_set.h>
9 #include <CGAL/compute_average_spacing.h>
10 #include <CGAL/Timer.h>
11 #include <CGAL/Memory_sizer.h>
12
13 #include <QObject>
14 #include <QAction>
15 #include <QMainWindow>
16 #include <QApplication>
17 #include <QtPlugin>
18 #include <QMessageBox>
19
20 #include "run_with_qprogressdialog.h"
21
22 #include "ui_Point_set_simplification_plugin.h"
23
24 // Concurrency
25 typedef CGAL::Parallel_if_available_tag Concurrency_tag;
26
27 struct Compute_average_spacing_functor
28 : public Functor_with_signal_callback
29 {
30 Point_set* points;
31 const int nb_neighbors;
32 boost::shared_ptr<double> result;
33
Compute_average_spacing_functorCompute_average_spacing_functor34 Compute_average_spacing_functor (Point_set* points, const int nb_neighbors)
35 : points (points), nb_neighbors (nb_neighbors), result (new double(0)) { }
36
operator ()Compute_average_spacing_functor37 void operator()()
38 {
39 *result = CGAL::compute_average_spacing<Concurrency_tag>(
40 points->all_or_selection_if_not_empty(),
41 nb_neighbors,
42 points->parameters().
43 callback (*(this->callback())));
44 }
45 };
46
47 struct Grid_simplify_functor
48 : public Functor_with_signal_callback
49 {
50 Point_set* points;
51 double grid_size;
52 boost::shared_ptr<Point_set::iterator> result;
53
Grid_simplify_functorGrid_simplify_functor54 Grid_simplify_functor (Point_set* points, double grid_size)
55 : points (points), grid_size (grid_size), result (new Point_set::iterator) { }
56
operator ()Grid_simplify_functor57 void operator()()
58 {
59 *result = CGAL::grid_simplify_point_set(*points,
60 grid_size,
61 points->parameters().
62 callback (*(this->callback())));
63 }
64 };
65
66 struct Hierarchy_simplify_functor
67 : public Functor_with_signal_callback
68 {
69 Point_set* points;
70 unsigned int max_cluster_size;
71 double max_surface_variation;
72 boost::shared_ptr<Point_set::iterator> result;
73
Hierarchy_simplify_functorHierarchy_simplify_functor74 Hierarchy_simplify_functor (Point_set* points,
75 double max_cluster_size,
76 double max_surface_variation)
77 : points (points), max_cluster_size (max_cluster_size)
78 , max_surface_variation (max_surface_variation), result (new Point_set::iterator) { }
79
operator ()Hierarchy_simplify_functor80 void operator()()
81 {
82 *result = CGAL::hierarchy_simplify_point_set(*points,
83 points->parameters().
84 size(max_cluster_size).
85 maximum_variation(max_surface_variation).
86 callback (*(this->callback())));
87 }
88 };
89
90 using namespace CGAL::Three;
91 class Polyhedron_demo_point_set_simplification_plugin :
92 public QObject,
93 public Polyhedron_demo_plugin_helper
94 {
95 Q_OBJECT
96 Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
97 Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
98
99 QAction* actionSimplify;
100
101 public:
init(QMainWindow * mainWindow,CGAL::Three::Scene_interface * scene_interface,Messages_interface *)102 void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface,Messages_interface*) {
103 scene = scene_interface;
104 mw = mainWindow;
105 actionSimplify = new QAction(tr("Simplification Selection"), mainWindow);
106 actionSimplify->setProperty("subMenuName","Point Set Processing");
107
108 actionSimplify->setObjectName("actionSimplify");
109 autoConnectActions();
110 }
111
applicable(QAction *) const112 bool applicable(QAction*) const {
113 return qobject_cast<Scene_points_with_normal_item*>(scene->item(scene->mainSelectionIndex()));
114 }
115
actions() const116 QList<QAction*> actions() const {
117 return QList<QAction*>() << actionSimplify;
118 }
119
120 public Q_SLOTS:
121 void on_actionSimplify_triggered();
122
123
124 }; // end Polyhedron_demo_point_set_simplification_plugin
125
126 class Point_set_demo_point_set_simplification_dialog : public QDialog, private Ui::PointSetSimplificationDialog
127 {
128 Q_OBJECT
129 public:
Point_set_demo_point_set_simplification_dialog(QWidget * =nullptr)130 Point_set_demo_point_set_simplification_dialog(QWidget * /*parent*/ = nullptr)
131 {
132 setupUi(this);
133 m_maximumSurfaceVariation->setRange(0.000010, 0.33330);
134 }
135
simplificationMethod() const136 unsigned int simplificationMethod() const
137 {
138 if (Random->isChecked())
139 return 0;
140 else if (Grid->isChecked())
141 return 1;
142 else
143 return 2;
144 }
randomSimplificationPercentage() const145 double randomSimplificationPercentage() const { return m_randomSimplificationPercentage->value(); }
gridCellSize() const146 double gridCellSize() const { return m_gridCellSize->value(); }
maximumClusterSize() const147 unsigned int maximumClusterSize() const { return m_maximumClusterSize->value(); }
maximumSurfaceVariation() const148 double maximumSurfaceVariation() const { return m_maximumSurfaceVariation->value(); }
149
150 public Q_SLOTS:
151
on_Random_toggled(bool toggled)152 void on_Random_toggled (bool toggled)
153 {
154 m_randomSimplificationPercentage->setEnabled (toggled);
155 m_gridCellSize->setEnabled (!toggled);
156 m_maximumClusterSize->setEnabled (!toggled);
157 m_maximumSurfaceVariation->setEnabled (!toggled);
158 }
on_Grid_toggled(bool toggled)159 void on_Grid_toggled (bool toggled)
160 {
161 m_randomSimplificationPercentage->setEnabled (!toggled);
162 m_gridCellSize->setEnabled (toggled);
163 m_maximumClusterSize->setEnabled (!toggled);
164 m_maximumSurfaceVariation->setEnabled (!toggled);
165 }
on_Hierarchy_toggled(bool toggled)166 void on_Hierarchy_toggled (bool toggled)
167 {
168 m_randomSimplificationPercentage->setEnabled (!toggled);
169 m_gridCellSize->setEnabled (!toggled);
170 m_maximumClusterSize->setEnabled (toggled);
171 m_maximumSurfaceVariation->setEnabled (toggled);
172 }
173
174 };
175
on_actionSimplify_triggered()176 void Polyhedron_demo_point_set_simplification_plugin::on_actionSimplify_triggered()
177 {
178 const CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex();
179
180 Scene_points_with_normal_item* item =
181 qobject_cast<Scene_points_with_normal_item*>(scene->item(index));
182
183 if(item)
184 {
185 // Gets point set
186 Point_set* points = item->point_set();
187 if(points == nullptr)
188 return;
189
190 // Gets options
191 Point_set_demo_point_set_simplification_dialog dialog;
192 if(!dialog.exec())
193 return;
194
195 QApplication::setOverrideCursor(Qt::BusyCursor);
196
197 CGAL::Timer task_timer; task_timer.start();
198
199 // First point to delete
200 Point_set::iterator first_point_to_remove = points->end();
201
202 unsigned int method = dialog.simplificationMethod ();
203 if (method == 0)
204 {
205 std::cerr << "Point set random simplification (" << dialog.randomSimplificationPercentage() <<"%)...\n";
206
207 // Computes points to remove by random simplification
208 first_point_to_remove =
209 CGAL::random_simplify_point_set(*points,
210 dialog.randomSimplificationPercentage());
211 }
212 else if (method == 1)
213 {
214 std::cerr << "Point set grid simplification (cell size = " << dialog.gridCellSize() <<" * average spacing)...\n";
215
216 // Computes average spacing
217 Compute_average_spacing_functor functor_as (points, 6);
218 run_with_qprogressdialog (functor_as, "Simplification: computing average spacing...", mw);
219
220 double average_spacing = *functor_as.result;
221
222 Grid_simplify_functor functor (points, dialog.gridCellSize() * average_spacing);
223 run_with_qprogressdialog<CGAL::Sequential_tag> (functor, "Grid simplyfing...", mw);
224
225 // Computes points to remove by Grid Clustering
226 first_point_to_remove = *functor.result;
227
228 }
229 else
230 {
231 std::cerr << "Point set hierarchy simplification (cluster size = " << dialog.maximumClusterSize()
232 << ", maximum variation = " << dialog.maximumSurfaceVariation() << ")...\n";
233
234 // Computes points to remove by Hierarchy
235 Hierarchy_simplify_functor functor (points, dialog.maximumClusterSize(),
236 dialog.maximumSurfaceVariation());
237 run_with_qprogressdialog<CGAL::Sequential_tag> (functor, "Hierarchy simplyfing...", mw);
238
239 first_point_to_remove = *functor.result;
240
241 }
242
243 std::size_t nb_points_to_remove = std::distance(first_point_to_remove, points->end());
244 std::size_t memory = CGAL::Memory_sizer().virtual_size();
245 std::cerr << "Simplification: " << nb_points_to_remove << " point(s) are selected for removal ("
246 << task_timer.time() << " seconds, "
247 << (memory>>20) << " Mb allocated)"
248 << std::endl;
249
250 // Selects points to delete
251 points->set_first_selected(first_point_to_remove);
252
253 // Updates scene
254 item->invalidateOpenGLBuffers();
255 scene->itemChanged(index);
256
257 QApplication::restoreOverrideCursor();
258
259 // Warns user
260 if (nb_points_to_remove > 0)
261 {
262 QMessageBox::information(nullptr,
263 tr("Points selected for removal"),
264 tr("%1 point(s) are selected for removal.\nYou may delete or reset the selection using the item context menu.")
265 .arg(nb_points_to_remove));
266 }
267 }
268 }
269
270 #include "Point_set_simplification_plugin.moc"
271