1 #include <QApplication>
2 #include <QMainWindow>
3 #include <QAction>
4 #include <QVector>
5 #include <QMessageBox>
6 #include <QBitmap>
7 #include <QTabBar>
8 
9 #include <CGAL/boost/graph/helpers.h>
10 #include <CGAL/boost/graph/Euler_operations.h>
11 
12 #include <CGAL/subdivision_method_3.h>
13 #include <CGAL/Kernel_traits.h>
14 
15 #include <CGAL/Polygon_mesh_processing/triangulate_hole.h>
16 #include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
17 
18 #include <CGAL/Three/Scene_item.h>
19 #include <CGAL/Three/Viewer_interface.h>
20 #include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
21 #include <CGAL/Three/Three.h>
22 
23 #include "Scene_surface_mesh_item.h"
24 #include "Scene_points_with_normal_item.h"
25 #include "Scene_polylines_item.h"
26 
27 #include "ui_Basic_generator_widget.h"
28 
29 struct Face : public std::array<int,3>
30 {
FaceFace31   Face(int i, int j, int k)
32   {
33     (*this)[0] = i;
34     (*this)[1] = j;
35     (*this)[2] = k;
36   }
37 };
38 
39 class GeneratorWidget :
40     public QDockWidget,
41     public Ui::BasicGenerator
42 {
43   Q_OBJECT
44 public:
GeneratorWidget(QString name,QWidget * parent)45   GeneratorWidget(QString name, QWidget *parent)
46     :QDockWidget(name,parent)
47   {
48     setupUi(this);
49   }
50 };
51 
52 typedef Kernel::Point_3 Point;
53 
54 namespace euler =  CGAL::Euler;
55 using namespace CGAL::Three;
56 namespace params = CGAL::parameters;
57 
58 class Q_DECL_EXPORT Basic_generator_plugin :
59     public QObject,
60     public Polyhedron_demo_plugin_helper
61 {
62   Q_OBJECT
63   Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
64   Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "basic_generator_plugin.json")
65 public :
init(QMainWindow * mainWindow,CGAL::Three::Scene_interface * scene_interface,Messages_interface *)66   void init(QMainWindow* mainWindow,
67             CGAL::Three::Scene_interface* scene_interface,
68             Messages_interface*)
69   {
70     this->scene = scene_interface;
71     this->mw = mainWindow;
72     for(int i=0; i<=POLYLINE; ++i)
73       nbs[i]=0;
74 
75 
76     QMenu* menuFile = mw->findChild<QMenu*>("menuFile");
77 
78     QMenu* menu = menuFile->findChild<QMenu*>("menuGenerateObject");
79     if(!menu){
80       QAction* actionLoad = mw->findChild<QAction*>("actionLoadPlugin");
81       menu = new QMenu(tr("Generate &Object"), menuFile);
82       menu->setObjectName("menuGenerateObject");
83       menuFile->insertMenu(actionLoad, menu);
84     }
85 
86 
87     QAction* actionPrism       = new QAction("P&rism", mw);
88     QAction* actionSphere      = new QAction("&Sphere", mw);
89     QAction* actionPyramid     = new QAction("Py&ramid", mw);
90     QAction* actionHexahedron  = new QAction("&Hexahedron", mw);
91     QAction* actionTetrahedron = new QAction("&Tetrahedron", mw);
92     QAction* actionGrid        = new QAction("&Grid", mw);
93     QAction* actionPointSet    = new QAction("Po&int Set", mw);
94     QAction* actionPolyline    = new QAction("Po&lyline", mw);
95 
96 
97 
98 
99     connect(actionPrism, SIGNAL(triggered()),
100             this, SLOT(on_actionPrism_triggered()));
101     _actions << actionPrism;
102 
103     connect(actionSphere, SIGNAL(triggered()),
104             this, SLOT(on_actionSphere_triggered()));
105     _actions << actionSphere;
106 
107     connect(actionPyramid, SIGNAL(triggered()),
108             this, SLOT(on_actionPyramid_triggered()));
109     _actions << actionPyramid;
110 
111     connect(actionHexahedron, SIGNAL(triggered()),
112             this, SLOT(on_actionHexahedron_triggered()));
113     _actions << actionHexahedron;
114 
115     connect(actionTetrahedron, SIGNAL(triggered()),
116             this, SLOT(on_actionTetrahedron_triggered()));
117     _actions << actionTetrahedron;
118 
119     connect(actionGrid, SIGNAL(triggered()),
120             this, SLOT(on_actionGrid_triggered()));
121     _actions << actionGrid;
122 
123     connect(actionPointSet, SIGNAL(triggered()),
124             this, SLOT(on_actionPointSet_triggered()));
125     _actions << actionPointSet;
126 
127     connect(actionPolyline, SIGNAL(triggered()),
128             this, SLOT(on_actionPolyline_triggered()));
129     _actions << actionPolyline;
130 
131     Q_FOREACH(QAction* action, _actions)
132     {
133       menu->addAction(action);
134     }
135     dock_widget = new GeneratorWidget("Basic Objects", mw);
136     dock_widget->setVisible(false); // do not show at the beginning
137     addDockWidget(dock_widget);
138     connect(dock_widget->generateButton, &QAbstractButton::clicked,
139             this, &Basic_generator_plugin::on_generate_clicked);
140     connect(dock_widget->selector_tabWidget, &QTabWidget::currentChanged,
141             this, &Basic_generator_plugin::on_tab_changed);
142     connect(dock_widget, &GeneratorWidget::visibilityChanged,
143             this, &Basic_generator_plugin::on_tab_changed);
144     connect(dock_widget->prismCheckBox, &QCheckBox::stateChanged,
145             this, &Basic_generator_plugin::on_tab_changed);
146     connect(dock_widget->pyramidCheckBox, &QCheckBox::stateChanged,
147             this, &Basic_generator_plugin::on_tab_changed);
148   }
149 
applicable(QAction *) const150   bool applicable(QAction*) const
151   {
152     //not in the Operations menu
153     return false;
154   }
actions() const155   QList<QAction*> actions() const {
156     return QList<QAction*>();
157   }
158 public Q_SLOTS:
159 
160   void on_actionPrism_triggered();
161   void on_actionSphere_triggered();
162   void on_actionPyramid_triggered();
163   void on_actionHexahedron_triggered();
164   void on_actionTetrahedron_triggered();
165   void on_actionGrid_triggered();
166   void on_actionPointSet_triggered();
167   void on_actionPolyline_triggered();
168   void on_generate_clicked();
169   void on_tab_changed();
closure()170   void closure(){ dock_widget->hide(); }
171 private:
172   QList<QAction*> _actions;
173   GeneratorWidget* dock_widget;
174   enum VolumeTab
175   {
176     PRISM=0,
177     SPHERE,
178     PYRAMID,
179     HEXAHEDRON,
180     TETRAHEDRON,
181     GRID,
182     POINT_SET,
183     POLYLINE
184   };
185 
186   int nbs[POLYLINE+1];
187   template<class Facegraph_item>
188   void generateCube();
189   template<class Facegraph_item>
190   void generatePrism();
191   template<class Facegraph_item>
192   void generatePyramid();
193   template<class Facegraph_item>
194   void generateSphere();
195   template<class Facegraph_item>
196   void generateTetrahedron();
197   void generatePoints();
198   void generateLines();
199   template<class Facegraph_item>
200   void generateGrid();
201 }; //end of class Basic_generator_plugin
202 
203 //show the widget
on_actionPrism_triggered()204 void Basic_generator_plugin::on_actionPrism_triggered()
205 {
206   dock_widget->show(); dock_widget->raise();
207   dock_widget->selector_tabWidget->tabBar()->setCurrentIndex(PRISM);
208 }
on_actionSphere_triggered()209 void Basic_generator_plugin::on_actionSphere_triggered()
210 {
211   dock_widget->show(); dock_widget->raise();
212   dock_widget->selector_tabWidget->tabBar()->setCurrentIndex(SPHERE);
213 }
on_actionPyramid_triggered()214 void Basic_generator_plugin::on_actionPyramid_triggered()
215 {
216   dock_widget->show(); dock_widget->raise();
217   dock_widget->selector_tabWidget->tabBar()->setCurrentIndex(PYRAMID);
218 }
on_actionHexahedron_triggered()219 void Basic_generator_plugin::on_actionHexahedron_triggered()
220 {
221   dock_widget->show(); dock_widget->raise();
222   dock_widget->selector_tabWidget->tabBar()->setCurrentIndex(HEXAHEDRON);
223 }
on_actionTetrahedron_triggered()224 void Basic_generator_plugin::on_actionTetrahedron_triggered()
225 {
226   dock_widget->show(); dock_widget->raise();
227   dock_widget->selector_tabWidget->tabBar()->setCurrentIndex(TETRAHEDRON);
228 }
on_actionGrid_triggered()229 void Basic_generator_plugin::on_actionGrid_triggered()
230 {
231   dock_widget->show(); dock_widget->raise();
232   dock_widget->selector_tabWidget->tabBar()->setCurrentIndex(GRID);
233 }
on_actionPointSet_triggered()234 void Basic_generator_plugin::on_actionPointSet_triggered()
235 {
236   dock_widget->show(); dock_widget->raise();
237   dock_widget->selector_tabWidget->tabBar()->setCurrentIndex(POINT_SET);
238 }
on_actionPolyline_triggered()239 void Basic_generator_plugin::on_actionPolyline_triggered()
240 {
241   dock_widget->show(); dock_widget->raise();
242   dock_widget->selector_tabWidget->tabBar()->setCurrentIndex(POLYLINE);
243 }
on_tab_changed()244 void Basic_generator_plugin::on_tab_changed()
245 {
246   QString name;
247   int nb = 0;
248   switch(dock_widget->selector_tabWidget->currentIndex())
249   {
250   case PRISM:
251   {
252     name = QString("Prism");
253     nb = nbs[PRISM];
254     QPixmap pic;
255     if(dock_widget->prismCheckBox->isChecked())
256       pic = QPixmap(":/cgal/Polyhedron_3/resources/prism.png");
257     else
258       pic = QPixmap(":/cgal/Polyhedron_3/resources/prism-open.png");
259     dock_widget->prism_picLabel->setPixmap(pic);
260     dock_widget->prism_picLabel->show();
261   }
262     break;
263   case SPHERE:
264     name = QString("Sphere");
265     nb = nbs[SPHERE];
266     break;
267 
268   case PYRAMID:
269   {
270     name = QString("Pyramid");
271     nb = nbs[PYRAMID];
272     QPixmap pic;
273     if(dock_widget->pyramidCheckBox->isChecked())
274       pic = QPixmap(":/cgal/Polyhedron_3/resources/pyramid.png");
275     else
276       pic = QPixmap(":/cgal/Polyhedron_3/resources/pyramid-open.png");
277     dock_widget->pyramid_picLabel->setPixmap(pic);
278     dock_widget->pyramid_picLabel->show();
279   }
280     break;
281 
282   case HEXAHEDRON:
283     name = QString("Hexahedron");
284     nb = nbs[HEXAHEDRON];
285     break;
286 
287   case TETRAHEDRON:
288     name = QString("Tetrahedron");
289     nb = nbs[TETRAHEDRON];
290     break;
291   case GRID:
292     name = QString("Grid");
293     nb = nbs[GRID];
294     break;
295   case POINT_SET:
296     name = QString("Point_set");
297     nb = nbs[POINT_SET];
298     break;
299 
300   case POLYLINE:
301     name = QString("Polyline");
302     nb = nbs[POLYLINE];
303     break;
304   default:
305     break;
306   };
307   dock_widget->name_lineEdit->setText((nb==0)?name:QString(name).append(QString("%1").arg(nb)));
308 }
309 //generate
on_generate_clicked()310 void Basic_generator_plugin::on_generate_clicked()
311 {
312   switch(dock_widget->selector_tabWidget->currentIndex())
313   {
314   case PRISM:
315     generatePrism<Scene_surface_mesh_item>();
316     ++nbs[PRISM];
317     break;
318 
319   case SPHERE:
320     generateSphere<Scene_surface_mesh_item>();
321     ++nbs[SPHERE];
322     break;
323 
324   case PYRAMID:
325     generatePyramid<Scene_surface_mesh_item>();
326     ++nbs[PYRAMID];
327     break;
328 
329   case HEXAHEDRON:
330     generateCube<Scene_surface_mesh_item>();
331     ++nbs[HEXAHEDRON];
332     break;
333 
334   case TETRAHEDRON:
335     generateTetrahedron<Scene_surface_mesh_item>();
336     ++nbs[TETRAHEDRON];
337     break;
338   case GRID:
339     generateGrid<Scene_surface_mesh_item>();
340     ++nbs[GRID];
341     break;
342   case POINT_SET:
343     generatePoints();
344     ++nbs[POINT_SET];
345     break;
346 
347   case POLYLINE:
348     generateLines();
349     ++nbs[POLYLINE];
350     break;
351   default:
352     break;
353   };
354   on_tab_changed();
355 }
356 //make a non triangle hexahedron
357 template<class Facegraph_item>
generateCube()358 void Basic_generator_plugin::generateCube()
359 {
360   typename Facegraph_item::Face_graph cube;
361   if(dock_widget->tabWidget_2->currentIndex() == 0)
362   {
363     QString point_texts[8];
364     Point points[8];
365     point_texts[0] = dock_widget->cubeP0->text(); point_texts[4] = dock_widget->cubeP4->text();
366     point_texts[1] = dock_widget->cubeP1->text(); point_texts[5] = dock_widget->cubeP5->text();
367     point_texts[2] = dock_widget->cubeP2->text(); point_texts[6] = dock_widget->cubeP6->text();
368     point_texts[3] = dock_widget->cubeP3->text(); point_texts[7] = dock_widget->cubeP7->text();
369 
370     for(int i=0; i<8; ++i)
371     {
372       QStringList list = point_texts[i].split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS);
373       if (list.isEmpty()) return;
374       if (list.size()!=3){
375         QMessageBox *msgBox = new QMessageBox;
376         msgBox->setWindowTitle("Error");
377         msgBox->setText("ERROR : Input should consists of 3 doubles.");
378         msgBox->exec();
379         return;
380       }
381       double coords[3];
382       for(int j=0; j<3; ++j)
383       {
384         bool ok;
385         coords[j] = list.at(j).toDouble(&ok);
386         if(!ok)
387         {
388             QMessageBox *msgBox = new QMessageBox;
389             msgBox->setWindowTitle("Error");
390             msgBox->setText("ERROR : Coordinates are invalid.");
391             msgBox->exec();
392             return;
393         }
394       }
395       points[i] = Point(coords[0], coords[1], coords[2]);
396     }
397 
398     CGAL::make_hexahedron(
399           points[0],
400         points[1],
401         points[2],
402         points[3],
403 
404         points[4],
405         points[5],
406         points[6],
407         points[7],
408         cube);
409   }
410   else
411   {
412     QString text = dock_widget->extremaEdit->text();
413     QStringList list = text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS);
414     if (list.isEmpty()) return;
415     if (list.size()!=6){
416       QMessageBox *msgBox = new QMessageBox;
417       msgBox->setWindowTitle("Error");
418       msgBox->setText("ERROR : Input should consists of 6 doubles.");
419       msgBox->exec();
420       return;
421     }
422 
423     for(int i=0; i<6; ++i)
424     {
425       bool ok;
426       list.at(i).toDouble(&ok);
427       if(!ok)
428       {
429         QMessageBox *msgBox = new QMessageBox;
430         msgBox->setWindowTitle("Error");
431         msgBox->setText("ERROR : Coordinates are invalid.");
432         msgBox->exec();
433         return;
434       }
435     }
436     CGAL::make_hexahedron(
437           Point(list.at(0).toDouble(),list.at(1).toDouble(),list.at(5).toDouble()),
438           Point(list.at(3).toDouble(),list.at(1).toDouble(),list.at(5).toDouble()),
439           Point(list.at(3).toDouble(),list.at(1).toDouble(),list.at(2).toDouble()),
440           Point(list.at(0).toDouble(),list.at(1).toDouble(),list.at(2).toDouble()),
441 
442           Point(list.at(0).toDouble(),list.at(4).toDouble(),list.at(2).toDouble()),
443           Point(list.at(0).toDouble(),list.at(4).toDouble(),list.at(5).toDouble()),
444           Point(list.at(3).toDouble(),list.at(4).toDouble(),list.at(5).toDouble()),
445           Point(list.at(3).toDouble(),list.at(4).toDouble(),list.at(2).toDouble()),
446           cube);
447   }
448   Facegraph_item* cube_item = new Facegraph_item(cube);
449   cube_item->setName(dock_widget->name_lineEdit->text());
450   Scene_interface::Item_id id = scene->addItem(cube_item);
451   scene->setSelectedItem(id);
452 }
453 //make a prism
454 template<class Facegraph_item>
generatePrism()455 void Basic_generator_plugin::generatePrism()
456 {
457   //gets the precision parameter
458   int nb_vertices = dock_widget->prismSpinBox->value();
459   double height(dock_widget->prismHeightSpinBox->value()),
460       radius(dock_widget->prismBaseSpinBox->value());
461   bool is_closed = dock_widget->prismCheckBox->isChecked();
462 
463   QString text = dock_widget->prism_lineEdit->text();
464   QStringList list = text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS);
465   if (list.isEmpty()) return;
466   if (list.size()!=3){
467     QMessageBox *msgBox = new QMessageBox;
468     msgBox->setWindowTitle("Error");
469     msgBox->setText("ERROR : Input should consists of 3 doubles.");
470     msgBox->exec();
471     return;
472   }
473   double coords[3];
474   for(int i=0; i<3; ++i)
475   {
476     bool ok;
477     coords[i] = list.at(i).toDouble(&ok);
478     if(!ok)
479     {
480       QMessageBox *msgBox = new QMessageBox;
481       msgBox->setWindowTitle("Error");
482       msgBox->setText("ERROR : Coordinates are invalid.");
483       msgBox->exec();
484       return;
485     }
486   }
487 
488   typename Facegraph_item::Face_graph prism;
489   make_regular_prism(nb_vertices,
490                      prism,
491                      Point(coords[0], coords[1], coords[2]),
492                      height,
493                      radius,
494                      is_closed);
495 
496   Facegraph_item* prism_item = new Facegraph_item(prism);
497   prism_item->setName(dock_widget->name_lineEdit->text());
498   Scene_interface::Item_id id = scene->addItem(prism_item);
499   scene->setSelectedItem(id);
500 }
501 //make a pyramid
502 template<class Facegraph_item>
generatePyramid()503 void Basic_generator_plugin::generatePyramid()
504 {
505   int nb_vertices = dock_widget->pyramidSpinBox->value();
506   double height(dock_widget->pyramidHeightSpinBox->value()),
507       radius(dock_widget->pyramidBaseSpinBox->value());
508   bool is_closed = dock_widget->pyramidCheckBox->isChecked();
509 
510   QString text = dock_widget->pyramid_lineEdit->text();
511   QStringList list = text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS);
512   if (list.isEmpty()) return;
513   if (list.size()!=3){
514     QMessageBox *msgBox = new QMessageBox;
515     msgBox->setWindowTitle("Error");
516     msgBox->setText("ERROR : Input should consists of 3 doubles.");
517     msgBox->exec();
518     return;
519   }
520   double coords[3];
521   for(int i=0; i<3; ++i)
522   {
523     bool ok;
524     coords[i] = list.at(i).toDouble(&ok);
525     if(!ok)
526     {
527       QMessageBox *msgBox = new QMessageBox;
528       msgBox->setWindowTitle("Error");
529       msgBox->setText("ERROR : Coordinates are invalid.");
530       msgBox->exec();
531       return;
532     }
533   }
534 
535   typename Facegraph_item::Face_graph pyramid;
536   make_pyramid(nb_vertices,
537                pyramid,
538                Point(coords[0], coords[1], coords[2]),
539                height,
540                radius,
541                is_closed);
542 
543   Facegraph_item* pyramid_item = new Facegraph_item(pyramid);
544   pyramid_item->setName(dock_widget->name_lineEdit->text());
545   Scene_interface::Item_id id = scene->addItem(pyramid_item);
546   scene->setSelectedItem(id);
547 }
548 //make a sphere
549 template<class Facegraph_item>
generateSphere()550 void Basic_generator_plugin::generateSphere()
551 {
552   int precision = dock_widget->SphereSpinBox->value();
553   QString text = dock_widget->center_radius_lineEdit->text();
554   QStringList list = text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS);
555   if (list.isEmpty()) return;
556   if (list.size()!=4){
557     QMessageBox *msgBox = new QMessageBox;
558     msgBox->setWindowTitle("Error");
559     msgBox->setText("ERROR : Input should consists of four doubles.");
560     msgBox->exec();
561     return;
562   }
563 
564   double radius = list.at(3).toDouble();
565   Point center = Point(list.at(0).toDouble(), list.at(1).toDouble(), list.at(2).toDouble());
566   typename Facegraph_item::Face_graph sphere;
567   make_icosahedron(sphere, center, radius);
568   typedef typename boost::property_map<typename Facegraph_item::Face_graph, CGAL::vertex_point_t>::type VPMap;
569   if(precision !=0)
570     CGAL::Subdivision_method_3::Sqrt3_subdivision(sphere,
571                                                   params::number_of_iterations(precision));
572   VPMap vpmap = get(CGAL::vertex_point, sphere);
573   //emplace the points back on the sphere
574   for(typename boost::graph_traits<typename Facegraph_item::Face_graph>::vertex_descriptor vd : vertices(sphere))
575   {
576     Kernel::Vector_3 vec(center, get(vpmap, vd));
577     vec = radius*vec/CGAL::sqrt(vec.squared_length());
578     put(vpmap, vd, Kernel::Point_3(center.x() + vec.x(),
579                                    center.y() + vec.y(),
580                                    center.z() + vec.z()));
581   }
582 
583   Facegraph_item* sphere_item = new Facegraph_item(sphere);
584   sphere_item->setName(dock_widget->name_lineEdit->text());
585   Scene_interface::Item_id id = scene->addItem(sphere_item);
586   scene->setSelectedItem(id);
587 }
588 //make a tetrahedron
589 template<class Facegraph_item>
generateTetrahedron()590 void Basic_generator_plugin::generateTetrahedron()
591 {
592   typename Facegraph_item::Face_graph tetrahedron;
593 
594   QString point_texts[4];
595   Point points[4];
596   point_texts[0] = dock_widget->tetP0->text();
597   point_texts[1] = dock_widget->tetP1->text();
598   point_texts[2] = dock_widget->tetP2->text();
599   point_texts[3] = dock_widget->tetP3->text();
600 
601   for(int i=0; i<4; ++i)
602   {
603     QStringList list = point_texts[i].split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS);
604     if (list.isEmpty()) return;
605     if (list.size()!=3){
606       QMessageBox *msgBox = new QMessageBox;
607       msgBox->setWindowTitle("Error");
608       msgBox->setText("ERROR : Input should consists of 3 doubles.");
609       msgBox->exec();
610       return;
611     }
612     double coords[3];
613     for(int j=0; j<3; ++j)
614     {
615       bool ok;
616       coords[j] = list.at(j).toDouble(&ok);
617       if(!ok)
618       {
619           QMessageBox *msgBox = new QMessageBox;
620           msgBox->setWindowTitle("Error");
621           msgBox->setText("ERROR : Coordinates are invalid.");
622           msgBox->exec();
623           return;
624       }
625     }
626     points[i] = Point(coords[0], coords[1], coords[2]);
627   }
628   CGAL::make_tetrahedron(points[0],
629                          points[1],
630                          points[2],
631                          points[3],
632                          tetrahedron);
633 
634   Facegraph_item* tet_item = new Facegraph_item(tetrahedron);
635   tet_item->setName(dock_widget->name_lineEdit->text());
636   Scene_interface::Item_id id = scene->addItem(tet_item);
637   scene->setSelectedItem(id);
638 }
639 //make a point set
generatePoints()640 void Basic_generator_plugin::generatePoints()
641 {
642   QString text = dock_widget->point_textEdit->toPlainText();
643   Scene_points_with_normal_item* item = new Scene_points_with_normal_item();
644   QStringList list = text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS);
645   int counter = 0;
646   double coord[3];
647   bool ok = true;
648   if (list.isEmpty()) return;
649   if (list.size()%3!=0){
650     QMessageBox *msgBox = new QMessageBox;
651     msgBox->setWindowTitle("Error");
652     msgBox->setText("ERROR : Input should consists of triplets.");
653     msgBox->exec();
654     return;
655   }
656 
657   Q_FOREACH(QString s, list)
658   {
659     if(!s.isEmpty())
660     {
661       double res = s.toDouble(&ok);
662       if(!ok)
663       {
664         QMessageBox *msgBox = new QMessageBox;
665         msgBox->setWindowTitle("Error");
666         msgBox->setText("ERROR : Coordinates are invalid.");
667         msgBox->exec();
668         break;
669       }
670       else
671       {
672         coord[counter] = res;
673         counter++;
674       }
675     }
676     if(counter == 3)
677     {
678       const Kernel::Point_3 p(coord[0], coord[1], coord[2]);
679       item->point_set()->insert(p);
680       counter =0;
681     }
682   }
683   if(ok)
684   {
685     dock_widget->point_textEdit->clear();
686     item->point_set()->unselect_all();
687     item->setName(dock_widget->name_lineEdit->text());
688     item->setColor(Qt::black);
689     item->invalidateOpenGLBuffers();
690     Scene_interface::Item_id id = scene->addItem(item);
691     scene->setSelectedItem(id);
692   }
693 }
694 //make a polyline
generateLines()695 void Basic_generator_plugin::generateLines()
696 {
697   QString text = dock_widget->line_textEdit->toPlainText();
698   std::list<std::vector<Scene_polylines_item::Point_3> > polylines;
699   polylines.resize(polylines.size()+1);
700   std::vector<Scene_polylines_item::Point_3>& polyline = *(polylines.rbegin());
701   QStringList polylines_metadata;
702 
703   QStringList list = text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS);
704   int counter = 0;
705   double coord[3];
706   bool ok = true;
707   if (list.isEmpty()) return;
708   if(!dock_widget->polygon_checkBox->isChecked() && list.size()%3!=0){
709     QMessageBox *msgBox = new QMessageBox;
710     msgBox->setWindowTitle("Error");
711     msgBox->setText("ERROR : Input should consists of triplets.");
712     msgBox->exec();
713     return;
714   }
715   else if(dock_widget->polygon_checkBox->isChecked()&& list.size()%2!=0){
716     QMessageBox *msgBox = new QMessageBox;
717     msgBox->setWindowTitle("Error");
718     msgBox->setText("ERROR : Input should consists of pairs.");
719     msgBox->exec();
720     return;
721   }
722   Q_FOREACH(QString s, list)
723   {
724     if(!s.isEmpty())
725     {
726       double res = s.toDouble(&ok);
727       if(!ok)
728       {
729         QMessageBox *msgBox = new QMessageBox;
730         msgBox->setWindowTitle("Error");
731         msgBox->setText("ERROR : Coordinates are invalid.");
732         msgBox->exec();
733         break;
734       }
735       else
736       {
737         coord[counter] = res;
738         counter++;
739       }
740     }
741     if(!dock_widget->polygon_checkBox->isChecked() && counter == 3)
742     {
743       Scene_polylines_item::Point_3 p(coord[0], coord[1], coord[2]);
744       polyline.push_back(p);
745       counter =0;
746     }
747     else if(dock_widget->polygon_checkBox->isChecked() && counter == 2)
748     {
749       Scene_polylines_item::Point_3 p(coord[0], coord[1], 0);
750       polyline.push_back(p);
751       counter = 0;
752     }
753   }
754   if(dock_widget->polygon_checkBox->isChecked())
755   {
756     polyline.push_back(polyline.front()); //polygon_2 are not closed.
757   }
758   if(ok)
759   {
760     dock_widget->line_textEdit->clear();
761     if(dock_widget->fill_checkBox->isChecked())
762     {
763       CGAL::Three::Three::CursorScopeGuard guard(Qt::WaitCursor);
764       QApplication::processEvents();
765       if(polyline.front() != polyline.back()) {
766         polyline.push_back(polyline.front());
767       }
768       if(polyline.size() < 4) { // no triangle, skip it (needs at least 3 + 1 repeat)
769         QMessageBox::warning(mw, "Warning", "Needs at least 3 points to triangulate. Aborting.");
770         return;
771       }
772       std::vector<Face> patch;
773       CGAL::Polygon_mesh_processing::triangulate_hole_polyline(polyline,
774                                                                std::back_inserter(patch),
775                                                                CGAL::Polygon_mesh_processing::parameters::use_delaunay_triangulation(true));
776 
777       if(patch.empty()) {
778           QMessageBox::warning(mw, "Warning", "Triangulation failed.");
779           return;
780       }
781       SMesh* poly = new SMesh;
782       CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(polyline,
783                                                                   patch,
784                                                                   *poly);
785 
786       Scene_surface_mesh_item* poly_item = new Scene_surface_mesh_item(poly);
787       poly_item->setName(dock_widget->name_lineEdit->text());
788       poly_item->setRenderingMode(FlatPlusEdges);
789       scene->setSelectedItem(scene->addItem(poly_item));
790     }
791     else
792     {
793       Scene_polylines_item* item = new Scene_polylines_item();
794       item->polylines = polylines;
795       item->invalidateOpenGLBuffers();
796       item->setName(dock_widget->name_lineEdit->text());
797       item->setColor(Qt::black);
798       item->setProperty("polylines metadata", polylines_metadata);
799       Scene_interface::Item_id id = scene->addItem(item);
800       scene->setSelectedItem(id);
801     }
802   }
803 }
804 
805 struct Point_generator
806 {
807   std::size_t w,h;
808   Point bl, ur;
Point_generatorPoint_generator809   Point_generator(const std::size_t& w,
810                   const std::size_t& h,
811                   const Point& bl,
812                   const Point& ur)
813     :w(w), h(h), bl(bl), ur(ur)
814   {}
operator ()Point_generator815   Point operator()(std::size_t i, std::size_t j) const
816   {
817     return Point(bl.x() + i*(ur.x()-bl.x())/(w-1),
818                  bl.y() + j*(ur.y()-bl.y())/(h-1),
819                  bl.z() + j*(ur.z()-bl.z())/(h-1));
820   }
821 };
822 template<class Facegraph_item>
generateGrid()823 void Basic_generator_plugin::generateGrid()
824 {
825   typedef typename Facegraph_item::Face_graph Face_graph;
826   Face_graph grid;
827 
828   QString points_text;
829   Point extrema[2];
830   using size_type = typename boost::graph_traits<Face_graph>::vertices_size_type;
831   size_type nb_cells[2];
832   bool triangulated = dock_widget->grid_checkBox->isChecked();
833   points_text= dock_widget->grid_lineEdit->text();
834 
835   QStringList list = points_text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS);
836   if (list.isEmpty()) return;
837   if (list.size()!=6){
838     QMessageBox *msgBox = new QMessageBox;
839     msgBox->setWindowTitle("Error");
840     msgBox->setText("ERROR : Input should consists of 6 doubles.");
841     msgBox->exec();
842     return;
843   }
844   double coords[6];
845   for(int j=0; j<6; ++j)
846   {
847     bool ok;
848     coords[j] = list.at(j).toDouble(&ok);
849     if(!ok)
850     {
851       QMessageBox *msgBox = new QMessageBox;
852       msgBox->setWindowTitle("Error");
853       msgBox->setText("ERROR : Coordinates are invalid.");
854       msgBox->exec();
855       return;
856     }
857   }
858   extrema[0] = Point(coords[0], coords[1], coords[2]);
859   extrema[1] = Point(coords[3], coords[4], coords[5]);
860   nb_cells[0] = static_cast<size_type>(dock_widget->gridX_spinBox->value());
861   nb_cells[1] = static_cast<size_type>(dock_widget->gridY_spinBox->value());
862 
863   //nb_points = nb_cells+1
864   Point_generator point_gen(nb_cells[0]+1, nb_cells[1]+1, extrema[0], extrema[1]);
865 
866   CGAL::make_grid(nb_cells[0], nb_cells[1], grid, point_gen, triangulated);
867   Facegraph_item* grid_item = new Facegraph_item(grid);
868   grid_item->setName(dock_widget->name_lineEdit->text());
869   Scene_interface::Item_id id = scene->addItem(grid_item);
870   scene->setSelectedItem(id);
871 }
872 #include "Basic_generator_plugin.moc"
873