1 #include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
2 #include <QApplication>
3 #include <QObject>
4 #include <QAction>
5 #include <QMainWindow>
6 #include <QMessageBox>
7 #include <QInputDialog>
8 #include "Messages_interface.h"
9 #include <CGAL/Three/Three.h>
10 #include "Scene_surface_mesh_item.h"
11 #include "Scene_movable_sm_item.h"
12 #include <CGAL/Three/Scene_item_rendering_helper.h>
13 #include <CGAL/Three/Triangle_container.h>
14 #include <CGAL/Three/Edge_container.h>
15 #include <CGAL/Three/Point_container.h>
16 #include <CGAL/Rigid_triangle_mesh_collision_detection.h>
17 #include "Scene.h"
18 
19 class DoTreesIntersectplugin:
20     public QObject,
21     public CGAL::Three::Polyhedron_demo_plugin_interface
22 {
23   Q_OBJECT
24   Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
25   Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
26 public:
27 
eventFilter(QObject *,QEvent * event)28   bool eventFilter(QObject *, QEvent *event) Q_DECL_OVERRIDE
29   {
30     if(event->type() != QEvent::KeyPress)
31       return false;
32     QKeyEvent * e = static_cast<QKeyEvent*>(event);
33     if (e->key()==Qt::Key_W){
34       do_transparency = !do_transparency;
35       change_display();
36       return true;
37     }
38     return false;
39   }
40 
applicable(QAction *) const41   bool applicable(QAction*) const Q_DECL_OVERRIDE
42   {
43     if(scene->selectionIndices().size() <2)
44       return false;
45     Q_FOREACH(Scene::Item_id i, scene->selectionIndices())
46     {
47       if(! qobject_cast<Scene_surface_mesh_item*>(scene->item(i)))
48         return false;
49     }
50     return (! group_item);
51   }
52 
actions() const53   QList<QAction*> actions() const Q_DECL_OVERRIDE
54   {
55     return _actions;
56   }
57 
58 
init(QMainWindow * mw,CGAL::Three::Scene_interface * sc,Messages_interface * mi)59   void init(QMainWindow* mw, CGAL::Three::Scene_interface* sc, Messages_interface* mi) Q_DECL_OVERRIDE
60   {
61     this->messageInterface = mi;
62     this->scene = sc;
63     this->mw = mw;
64     QAction *actionCreateTrees= new QAction(QString("Collision Detection"), mw);
65     actionCreateTrees->setProperty("subMenuName", "Polygon Mesh Processing");
66     actionCreateTrees->setProperty("submenuName", "AABB_tree");
67     if(actionCreateTrees) {
68       connect(actionCreateTrees, SIGNAL(triggered()),
69               this, SLOT(start()));
70       _actions << actionCreateTrees;
71     }
72     do_transparency = false;
73     group_item = nullptr;
74   }
75 private Q_SLOTS:
start()76   void start()
77   {
78     QApplication::setOverrideCursor(Qt::WaitCursor);
79     Q_FOREACH(Scene::Item_id i, scene->selectionIndices())
80     {
81       Scene_surface_mesh_item* item=qobject_cast<Scene_surface_mesh_item*>(scene->item(i));
82       if (!CGAL::is_triangle_mesh(*item->face_graph()))
83       {
84         QApplication::restoreOverrideCursor();
85         QMessageBox::warning(mw, "Error", QString("%1 is not pure triangle. Aborting.").arg(item->name()));
86         return;
87       }
88     }
89     group_item = new Scene_group_item("Test Items");
90     connect(group_item, &Scene_group_item::aboutToBeDestroyed,
91             this, [this](){
92       items.clear();
93       if(col_det)
94         delete col_det;
95       col_det = nullptr;
96       group_item = nullptr;});
97 
98     scene->addItem(group_item);
99     Q_FOREACH(Scene::Item_id i, scene->selectionIndices())
100     {
101       Scene_surface_mesh_item* item=qobject_cast<Scene_surface_mesh_item*>(scene->item(i));
102       connect(item, &Scene_surface_mesh_item::aboutToBeDestroyed,
103               this, &DoTreesIntersectplugin::cleanup);
104 
105       CGAL::qglviewer::Vec pos(((item->bbox().min)(0) + (item->bbox().max)(0))/2.0,
106                                ((item->bbox().min)(1) + (item->bbox().max)(1))/2.0,
107                                ((item->bbox().min)(2) + (item->bbox().max)(2))/2.0);
108 
109       Scene_movable_sm_item* mov_item = new Scene_movable_sm_item(pos,item->face_graph(),"");
110       connect(mov_item->manipulatedFrame(), &CGAL::qglviewer::ManipulatedFrame::modified,
111               this, &DoTreesIntersectplugin::update_trees);
112       mov_item->setName(item->name());
113       if(do_transparency)
114       {
115         mov_item->setRenderingMode(Flat);
116         mov_item->setAlpha(120);
117       }
118       else
119       {
120         mov_item->setRenderingMode(Wireframe);
121       }
122       item->setVisible(false);
123       items.push_back(mov_item);
124       scene->addItem(mov_item);
125       scene->changeGroup(mov_item, group_item);
126       group_item->lockChild(mov_item);
127       mov_item->redraw();
128     }
129     scene->setSelectedItem(group_item->getChildren().last());
130     connect(static_cast<Scene*>(scene), &Scene::itemIndexSelected,
131             this, &DoTreesIntersectplugin::update_trees);
132     col_det = new CGAL::Rigid_triangle_mesh_collision_detection<SMesh>();
133     col_det->reserve(items.size());
134     Q_FOREACH(Scene_movable_sm_item* item, items)
135     {
136       col_det->add_mesh(*item->getFaceGraph());
137     }
138     init_trees();
139     static_cast<CGAL::Three::Viewer_interface*>(
140           CGAL::QGLViewer::QGLViewerPool().first())->installEventFilter(this);
141     QApplication::restoreOverrideCursor();
142     CGAL::Three::Three::information("Press `W` to switch between Wireframe and Transparency mode.");
143   }
144 
145 public Q_SLOTS:
init_trees()146   void init_trees()
147   {
148     if(items.empty())
149       return;
150     Q_FOREACH(Scene_movable_sm_item* item, items)
151       item->setColor(QColor(Qt::green));
152 
153     CGAL::Three::Viewer_interface* viewer = static_cast<CGAL::Three::Viewer_interface*>(
154           CGAL::QGLViewer::QGLViewerPool().first());
155     Scene_movable_sm_item* sel_item = qobject_cast<Scene_movable_sm_item*>(scene->item(scene->mainSelectionIndex()));
156     if(!sel_item)
157       return;
158 
159     std::size_t mesh_id = 0;
160     std::size_t sel_id = 0;
161     Q_FOREACH(Scene_movable_sm_item* item, items)
162     {
163       if(item == sel_item)
164       {
165         sel_id = mesh_id;
166         break;
167       }
168       ++mesh_id;
169     }
170     mesh_id = 0;
171     Q_FOREACH(Scene_movable_sm_item* item, items)
172     {
173       if(mesh_id == sel_id)
174       {
175         ++mesh_id;
176         item->setColor(QColor(255,184,61));
177         prev_ids.push_back(sel_id);
178         continue;
179       }
180       const double* matrix = item->manipulatedFrame()->matrix();
181       item->setFMatrix(matrix);
182       EPICK::Aff_transformation_3 translation(CGAL::TRANSLATION, -EPICK::Vector_3(item->center().x,
183                                                                                   item->center().y,
184                                                                                   item->center().z));
185       EPICK::Aff_transformation_3 rota(
186             matrix[0], matrix[4], matrix[8],matrix[12],
187           matrix[1], matrix[5], matrix[9],matrix[13],
188           matrix[2], matrix[6], matrix[10],matrix[14]);
189       EPICK::Aff_transformation_3 transfo =
190           rota*translation;
191 
192       col_det->set_transformation(mesh_id++, transfo);
193 
194       if(do_transparency)
195       {
196         item->setRenderingMode(Flat);
197         item->setAlpha(120);
198       }
199       else
200       {
201         item->setRenderingMode(Wireframe);
202       }
203       item->itemChanged();
204     }
205     const double* matrix = sel_item->manipulatedFrame()->matrix();
206     sel_item->setFMatrix(matrix);
207     EPICK::Aff_transformation_3 translation(CGAL::TRANSLATION, -EPICK::Vector_3(sel_item->center().x,
208                                                                                 sel_item->center().y,
209                                                                                 sel_item->center().z));
210     EPICK::Aff_transformation_3 rota(
211           matrix[0], matrix[4], matrix[8],matrix[12],
212         matrix[1], matrix[5], matrix[9],matrix[13],
213         matrix[2], matrix[6], matrix[10],matrix[14]);
214     EPICK::Aff_transformation_3 transfo =
215         rota*translation;
216     col_det->set_transformation(sel_id, transfo);
217     std::vector<std::pair<std::size_t, bool> > inter_and_incl
218         = col_det->get_all_intersections_and_inclusions(sel_id);
219     for(std::size_t i=0; i<inter_and_incl.size(); ++i)
220     {
221       std::size_t id = inter_and_incl[i].first;
222       bool including = inter_and_incl[i].second;
223       if(including)
224         items[id]->setColor(QColor(Qt::blue));
225       else
226         items[id]->setColor(QColor(Qt::red));
227       prev_ids.push_back(id);
228     }
229     if(do_transparency)
230     {
231       sel_item->setRenderingMode(Flat);
232       sel_item->setAlpha(120);
233     }
234     else
235     {
236       sel_item->setRenderingMode(Wireframe);
237     }
238     sel_item->itemChanged();
239     viewer->update();
240   }
241 
update_trees()242   void update_trees()
243   {
244     if(items.empty())
245       return;
246     CGAL::Three::Viewer_interface* viewer = static_cast<CGAL::Three::Viewer_interface*>(
247           CGAL::QGLViewer::QGLViewerPool().first());
248     Scene_movable_sm_item* sel_item = qobject_cast<Scene_movable_sm_item*>(scene->item(scene->mainSelectionIndex()));
249     if(!sel_item)
250       return;
251 
252     std::size_t mesh_id = 0;
253     std::size_t sel_id = 0;
254     Q_FOREACH(Scene_movable_sm_item* item, items)
255     {
256       if(item == sel_item)
257       {
258         sel_id = mesh_id;
259         ++mesh_id;
260         item->setColor(QColor(255,184,61));
261         break;
262       }
263       ++mesh_id;
264     }
265     for(std::size_t i = 0; i< prev_ids.size(); ++i)
266     {
267       std::size_t id = prev_ids[i];
268       if(id == sel_id)
269       {
270         continue;
271       }
272       Scene_movable_sm_item* item = items[id];
273       item->setColor(QColor(Qt::green));
274       item->itemChanged();
275     }
276     prev_ids.clear();
277     const double* matrix = sel_item->manipulatedFrame()->matrix();
278     sel_item->setFMatrix(matrix);
279 
280     EPICK::Aff_transformation_3 translation(CGAL::TRANSLATION, -EPICK::Vector_3(sel_item->center().x,
281                                                                                 sel_item->center().y,
282                                                                                 sel_item->center().z));
283     EPICK::Aff_transformation_3 rota(
284           matrix[0], matrix[4], matrix[8],matrix[12],
285         matrix[1], matrix[5], matrix[9],matrix[13],
286         matrix[2], matrix[6], matrix[10],matrix[14]);
287     EPICK::Aff_transformation_3 transfo =
288         rota*translation;
289     col_det->set_transformation(sel_id, transfo);
290     std::vector<std::pair<std::size_t, bool> > inter_and_incl
291         = col_det->get_all_intersections_and_inclusions(sel_id);
292     for(std::size_t i=0; i<inter_and_incl.size(); ++i)
293     {
294       std::size_t id = inter_and_incl[i].first;
295       bool including = inter_and_incl[i].second;
296       if(including)
297         items[id]->setColor(QColor(Qt::blue));
298       else
299         items[id]->setColor(QColor(Qt::red));
300       prev_ids.push_back(id);
301     }
302     prev_ids.push_back(sel_id);
303     sel_item->itemChanged();
304     viewer->update();
305   }
306 
cleanup()307   void cleanup()
308   {
309     if(!group_item)
310       return;
311     scene->erase(scene->item_id(group_item));
312     group_item = nullptr;
313     items.clear();
314     prev_ids.clear();
315     delete col_det;
316     col_det = nullptr;
317   }
318 
319   //switch transparent/wireframe.
change_display()320   void change_display()
321   {
322     for(Scene_movable_sm_item* item : items)
323     {
324       if(do_transparency)
325       {
326         item->setRenderingMode(Flat);
327         item->setAlpha(120);
328       }
329       else
330       {
331         item->setRenderingMode(Wireframe);
332       }
333     }
334   }
335 
336 private:
337   QList<QAction*> _actions;
338   Messages_interface* messageInterface;
339   CGAL::Three::Scene_interface* scene;
340   QMainWindow* mw;
341   CGAL::Rigid_triangle_mesh_collision_detection<SMesh> *col_det;
342   std::vector<Scene_movable_sm_item*> items;
343   std::vector<std::size_t> prev_ids;
344   Scene_group_item* group_item;
345   bool do_transparency;
346 };
347 #include "Do_trees_intersect_plugin.moc"
348