1 
2 #include <QtCore/qglobal.h>
3 
4 #include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
5 
6 #include "Scene_surface_mesh_item.h"
7 #include "Scene_polyhedron_selection_item.h"
8 
9 #include <CGAL/iterator.h>
10 #include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
11 #include <CGAL/boost/graph/properties_Polyhedron_3.h>
12 #include <CGAL/utility.h>
13 
14 #include <CGAL/Polygon_mesh_processing/random_perturbation.h>
15 
16 #include <boost/graph/graph_traits.hpp>
17 #include <CGAL/property_map.h>
18 
19 #include <QElapsedTimer>
20 #include <QAction>
21 #include <QMainWindow>
22 #include <QApplication>
23 #include <QString>
24 #include <QInputDialog>
25 #include <QtPlugin>
26 #include <QMessageBox>
27 
28 #include "ui_Random_perturbation_dialog.h"
29 
30 using namespace CGAL::Three;
31 class Polyhedron_demo_random_perturbation_plugin :
32   public QObject,
33   public Polyhedron_demo_plugin_interface
34 {
35   Q_OBJECT
36   Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
37   Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "random_perturbation_plugin.json")
38 
39 public:
init(QMainWindow * mainWindow,Scene_interface * scene_interface,Messages_interface *)40   void init(QMainWindow* mainWindow,
41             Scene_interface* scene_interface,
42             Messages_interface*)
43   {
44     this->scene = scene_interface;
45     this->mw = mainWindow;
46 
47     actionRandomPerturbation_ = new QAction("Random perturbation", mw);
48     actionRandomPerturbation_->setProperty("subMenuName", "Polygon Mesh Processing");
49     if (actionRandomPerturbation_) {
50       connect(actionRandomPerturbation_, SIGNAL(triggered()),
51         this, SLOT(random_perturb()));
52     }
53   }
54 
actions() const55   QList<QAction*> actions() const {
56     return QList<QAction*>() << actionRandomPerturbation_;
57   }
58 
applicable(QAction *) const59   bool applicable(QAction*) const
60   {
61     const Scene_interface::Item_id index = scene->mainSelectionIndex();
62     if (qobject_cast<Scene_surface_mesh_item*>(scene->item(index)))
63       return true;
64     else if (qobject_cast<Scene_polyhedron_selection_item*>(scene->item(index)))
65       return true;
66     else
67       return false;
68   }
69 
70 public Q_SLOTS:
random_perturb()71   void random_perturb()
72   {
73     const Scene_interface::Item_id index = scene->mainSelectionIndex();
74     Scene_surface_mesh_item* poly_item =
75       qobject_cast<Scene_surface_mesh_item*>(scene->item(index));
76     Scene_polyhedron_selection_item* selection_item =
77       qobject_cast<Scene_polyhedron_selection_item*>(scene->item(index));
78 
79     //Create dialog box
80     QDialog dialog(mw);
81     Ui::Random_perturbation_dialog ui
82       = perturb_dialog(&dialog, poly_item, selection_item);
83 
84     //Get values
85     int i = dialog.exec();
86     if (i == QDialog::Rejected)
87     {
88       std::cout << "Perturbation aborted" << std::endl;
89       return;
90     }
91 
92     double max_move = ui.moveSize_dspinbox->value();
93     bool project = ui.project_checkbox->isChecked();
94 
95     // wait cursor
96     QApplication::setOverrideCursor(Qt::WaitCursor);
97     QElapsedTimer time;
98     time.start();
99 
100     std::cout << "Perturbation..." << std::endl;
101 
102     namespace PMP = CGAL::Polygon_mesh_processing;
103 
104     if (poly_item)
105     {
106       SMesh& pmesh = *poly_item->face_graph();
107       if(ui.deterministic_checkbox->isChecked())
108       {
109         unsigned int seed = static_cast<unsigned int>(ui.seed_spinbox->value());
110         PMP::random_perturbation(pmesh, max_move,
111             PMP::parameters::do_project(project)
112             .random_seed(seed));
113       }
114       else
115       {
116         PMP::random_perturbation(pmesh, max_move,
117             PMP::parameters::do_project(project));
118       }
119 
120       poly_item->invalidateOpenGLBuffers();
121       poly_item->itemChanged();
122     }
123     else if (selection_item)
124     {
125       if (selection_item->selected_vertices.empty())
126       {
127         QMessageBox msg(QMessageBox::Warning,
128           QString("Empty selection"),
129           QString("Selection of vertices is empty.\nPerturbation aborted."),
130           QMessageBox::Ok,
131           this->mw);
132         msg.exec();
133         QApplication::restoreOverrideCursor();
134         return;
135       }
136       SMesh& pmesh = *selection_item->polyhedron();
137       if (ui.deterministic_checkbox->isChecked())
138       {
139         unsigned int seed = static_cast<unsigned int>(ui.seed_spinbox->value());
140         PMP::random_perturbation(
141             selection_item->selected_vertices,
142             pmesh,
143             max_move,
144             PMP::parameters::do_project(project)
145             .random_seed(seed));
146       }
147       else
148       {
149         std::cout << "selection_item->selected_vertices : "
150           << selection_item->selected_vertices.size() << std::endl;
151         PMP::random_perturbation(
152           selection_item->selected_vertices,
153           pmesh,
154           max_move,
155           PMP::parameters::do_project(project));
156       }
157 
158       selection_item->invalidateOpenGLBuffers();
159       Q_EMIT selection_item->itemChanged();
160       selection_item->polyhedron_item()->invalidateOpenGLBuffers();
161       Q_EMIT selection_item->polyhedron_item()->itemChanged();
162     }
163     else
164       std::cerr << "Can't perturb that type of item" << std::endl;
165 
166     std::cout << " ok (" << time.elapsed() << " ms)" << std::endl;
167 
168     // default cursor
169     QApplication::restoreOverrideCursor();
170   }
171 
172   Ui::Random_perturbation_dialog
perturb_dialog(QDialog * dialog,Scene_surface_mesh_item * poly_item,Scene_polyhedron_selection_item * selection_item)173   perturb_dialog(QDialog* dialog,
174                  Scene_surface_mesh_item* poly_item,
175                  Scene_polyhedron_selection_item* selection_item)
176   {
177     Ui::Random_perturbation_dialog ui;
178     ui.setupUi(dialog);
179     connect(ui.buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
180     connect(ui.buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
181 
182     //Set default parameters
183     Scene_interface::Bbox bbox = poly_item != NULL ? poly_item->bbox()
184       : (selection_item != NULL ? selection_item->bbox()
185       : scene->bbox());
186     ui.objectName->setText(poly_item != NULL ? poly_item->name()
187       : (selection_item != NULL ? selection_item->name()
188       : QString("Remeshing parameters")));
189 
190     ui.objectNameSize->setText(
191       tr("Object bbox size (w,h,d):  <b>%1</b>,  <b>%2</b>,  <b>%3</b>")
192       .arg(bbox.xmax() - bbox.xmin(), 0, 'g', 3)
193       .arg(bbox.ymax() - bbox.ymin(), 0, 'g', 3)
194       .arg(bbox.zmax() - bbox.zmin(), 0, 'g', 3));
195 
196     double diago_length = CGAL::sqrt((bbox.xmax() - bbox.xmin())*(bbox.xmax() - bbox.xmin())
197       + (bbox.ymax() - bbox.ymin())*(bbox.ymax() - bbox.ymin())
198       + (bbox.zmax() - bbox.zmin())*(bbox.zmax() - bbox.zmin()));
199 
200     //parameters
201     ui.moveSize_dspinbox->setRange(0., diago_length);
202     ui.moveSize_dspinbox->setValue(0.05 * diago_length);
203 
204     ui.project_checkbox->setChecked(true);
205 
206     //advanced
207     ui.deterministic_checkbox->setChecked(false);
208     ui.seed_spinbox->setEnabled(false);
209     ui.seed_label->setEnabled(false);
210     ui.seed_spinbox->setValue(0);
211     ui.seed_spinbox->setMinimum(0);
212 
213     connect(ui.deterministic_checkbox, SIGNAL(toggled(bool)),
214             ui.seed_spinbox, SLOT(setEnabled(bool)));
215     connect(ui.deterministic_checkbox, SIGNAL(toggled(bool)),
216             ui.seed_label, SLOT(setEnabled(bool)));
217 
218     return ui;
219   }
220 
221 private:
222   Scene_interface *scene;
223   QMainWindow* mw;
224   QAction* actionRandomPerturbation_;
225 
226 }; // end Polyhedron_demo_random_perturbation_plugin
227 
228 
229 #include "Random_perturbation_plugin.moc"
230