Tulip  5.2.1
Large graphs analysis and drawing
GlMainWidget.h
1 /*
2  *
3  * This file is part of Tulip (http://tulip.labri.fr)
4  *
5  * Authors: David Auber and the Tulip development Team
6  * from LaBRI, University of Bordeaux
7  *
8  * Tulip is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation, either version 3
11  * of the License, or (at your option) any later version.
12  *
13  * Tulip is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  *
18  */
19 
20 #ifndef Tulip_GLMAINWIDGET_H
21 #define Tulip_GLMAINWIDGET_H
22 
23 #include <QGLWidget>
24 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
25 #include <QWindow>
26 #endif
27 
28 #include <tulip/tulipconf.h>
29 #include <tulip/GlScene.h>
30 #include <tulip/Graph.h>
31 
32 class QGLFramebufferObject;
33 
34 namespace tlp {
35 
36 class View;
37 class GlCompositeHierarchyManager;
38 
39 /** @ingroup OpenGL
40  * @brief This widget provide a simple system to visualize data/graph with OpenGL 3D engine
41  *
42  * This widget is an interface between Qt Widget system and tulip OpenGL engine
43  * The central object of GlMainWidget is the GlScene member
44  * @see GlScene
45  *
46  * To use this class you have to :
47  * - create a GlMainWidget
48  * - get the GlScene with getScene() function
49  * - add GlLayer and GlEntity to this scene
50  * - call centerScene() to compute a good GlCamera
51  * - see the result
52  *
53  * @see GlLayer
54  * @see GlSimpleEntity
55  *
56  *
57  * If you only want to visualize a graph, you can call the setGraph function
58  *
59  *
60  * After scene construction you can perform some operation on GlMainWidget :
61  * - Selection with doSelect() and selectGlEntities()
62  * - Image output with getImage(), createPicture(), outputSVG() and outputEPS()
63  * - Texture output with createTexture()
64  * - others operation on GlScene and QGlWidget
65  */
66 class TLP_QT_SCOPE GlMainWidget : public QGLWidget {
67  Q_OBJECT
68 
69 public:
70  /**
71  * @brief Configure the rendering process ( see render function)
72  * @see render
73  **/
75  RenderScene = 0x1, /** Force to render the graph even if there is a previous buffered render.
76  You need to call this option if the graph is updated to regenerate the
77  buffer. If not set try to use the last buffered graph render, if there is
78  no valid buffer this flag is forced. **/
79  SwapBuffers = 0x2 /** Call the swapBuffer functions at the end of the rendering process. If the
80  disabled it's up to you to call the swapBuffer function. **/
81  };
82  Q_DECLARE_FLAGS(RenderingOptions, RenderingOption)
83 
84  /**
85  * @brief Constructor of GlMainWidget
86  *
87  * Create a GlMainWidget with the GlScene associated to it
88  * @param parent Qt Widget parent system
89  * @param view if you want to link this GlMainWidget to a view : use this parameter
90  */
91  GlMainWidget(QWidget *parent = nullptr, View *view = nullptr);
92  ~GlMainWidget() override;
93 
94  /**
95  * @brief Get the GlScene of this GlMainWidget
96  * You have to add yours GlLayer and GlEntity to this GlScene
97  * At the construction this GlScene is empty
98  * @see GlScene
99  * @see GlScene::createLayer(const std::string &name)
100  * @see GlLayer::addGlEntity(GlSimpleEntity *entity,const std::string& name)
101  */
103  return &scene;
104  }
105 
106  /** @brief Select nodes and edges in a region of the screen
107  *
108  * Select all nodes and edges lying in the area of the screen of given width and height,
109  * and with its upper-left corner at (x,y)
110  * @param selectedNodes filled by the method with the nodes found in the region
111  * @param selectedEdges filled by the method with the edges found in the region
112  * @param layer specify the layer in which to perform the picking
113  * @param pickNodes enable or disable the picking of nodes
114  * @param pickEdges enable or disable the picking of edges
115  */
116  void pickNodesEdges(const int x, const int y, const int width, const int height,
117  std::vector<SelectedEntity> &selectedNodes,
118  std::vector<SelectedEntity> &selectedEdges, tlp::GlLayer *layer = nullptr,
119  bool pickNodes = true, bool pickEdges = true);
120 
121  /** @brief Select a node or edge at a screen point
122  * Try to select at point (x,y) a node in the first place then if no result try to select an edge
123  * @param type tells what has been found: NODE, EDGE
124  * @param layer specify the layer in which to perform the picking
125  * @param pickNodes enable or disable the picking of nodes
126  * @param pickEdges enable or disable the picking of edges
127  * @return true if something has been found, false otherwise
128  */
129  bool pickNodesEdges(const int x, const int y, SelectedEntity &selectedEntity,
130  tlp::GlLayer *layer = nullptr, bool pickNodes = true, bool pickEdges = true);
131 
132  /**
133  * @deprecated this function should not be used anymore, use pickNodesEdges()
134  */
135  _DEPRECATED void doSelect(const int x, const int y, const int width, const int height,
136  std::vector<tlp::node> &sNode, std::vector<tlp::edge> &sEdge,
137  tlp::GlLayer *layer = nullptr);
138 
139  /**
140  * @deprecated this function should not be used anymore, use pickNodesEdges()
141  */
142  _DEPRECATED bool doSelect(const int x, const int y, tlp::ElementType &type, tlp::node &n,
143  tlp::edge &e, tlp::GlLayer *layer = nullptr);
144 
145  /**
146  * @brief convert a screen measure into a viewport measure
147  * @param a measure in screen coordinates specified as an integer
148  * @return the converted measure in viewport coordinates as an integer
149  */
150  int screenToViewport(int l) {
151 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
152  return l * windowHandle()->devicePixelRatio();
153 #else
154  return l;
155 #endif
156  }
157 
158  /**
159  * @brief convert a screen measure into a viewport measure
160  * @param a measure in screen coordinates specified as a double
161  * @return the converted measure in viewport coordinates as a double
162  */
163  double screenToViewport(double l) {
164 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
165  return l * windowHandle()->devicePixelRatio();
166 #else
167  return l;
168 #endif
169  }
170 
171  /**
172  * @brief convert a screen point into a viewport point
173  * @param a point in screen coordinates
174  * @return the converted point in viewport coordinates
175  */
176  Coord screenToViewport(const Coord &point) {
177 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
178  qreal dpr = windowHandle()->devicePixelRatio();
179  return Coord(point.x() * dpr, point.y() * dpr);
180 #else
181  return point;
182 #endif
183  }
184 
185  /**
186  * @brief convert a viewport measure into a screen measure
187  * @param a measure in viewport coordinates specified as a double
188  * @return the converted measure in screen coordinates as a double
189  */
190  double viewportToScreen(double l) {
191 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
192  return l / windowHandle()->devicePixelRatio();
193 #else
194  return l;
195 #endif
196  }
197 
198  /**
199  * @brief convert a viewport point into a screen point
200  * @param a point in viewport coordinates
201  * @return the converted point in screen coordinates
202  */
203  Coord viewportToScreen(const Coord &point) {
204 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
205  qreal dpr = windowHandle()->devicePixelRatio();
206  return Coord(point.x() / dpr, point.y() / dpr);
207 #else
208  return point;
209 #endif
210  }
211 
212  /**
213  * @brief EPS output of the GlMainWidget
214  */
215  bool outputEPS(int size, int doSort, const char *filename);
216  /**
217  * @brief SVG output of the GlMainWidget
218  */
219  bool outputSVG(int size, const char *filename);
220 
221  /**
222  * @brief Compute texture size in power of two with given height and width
223  * For example if you set width to 94 and height to 256, this function set textureRealWidth to 128
224  * and textureRealHeight to 256
225  */
226  static void getTextureRealSize(int width, int height, int &textureRealWidth,
227  int &textureRealHeight);
228 
229  /**
230  * @brief Take a snapshot of the Widget and put it in an OpenGl texture
231  * @param width power of two number (for example 256)
232  * @param height power of two number (for example 256)
233  * You can use this texture with Tulip texture system
234  * @see GlTextureManager
235  */
236  QGLFramebufferObject *createTexture(const std::string &textureName, int width, int height);
237  /**
238  * @brief Take a snapshot of the Widget and put it in a picture
239  * @param width size
240  * @param height size
241  * @param center if true this function call a centerScene() before picture output
242  */
243  void createPicture(const std::string &pictureName, int width, int height, bool center = true);
244 
245  /**
246  * Take a snapshot of the Widget and return it
247  * @param width size
248  * @param height size
249  * @param center if true this function call a centerScene() before picture output
250  */
251  QImage createPicture(int width, int height, bool center = true);
252 
253  /**
254  * @brief Function to do picking on entities in a screen region
255  * It just calls selectEntities on the GlScene instance.
256  * @param x screen coordinates
257  * @param y screen coordinates
258  * @param width screen size
259  * @param height screen size
260  * @param pickedEntities filled with entity under the selection screen rectangle
261  * @param layer if you want to do the selection only on one GlLayer
262  */
263  bool pickGlEntities(const int x, const int y, const int width, const int height,
264  std::vector<SelectedEntity> &pickedEntities, tlp::GlLayer *layer = nullptr);
265  /**
266  * @brief Function to do picking on entities.
267  * It just calls selectEntities on the GlScene instance with a small window of twelve pixels.
268  * @param x screen coordinates
269  * @param y screen coordinates
270  * @param pickedEntities filled with entity under the selection screen rectangle
271  * @param layer if you want to do the selection only on one GlLayer
272  */
273  bool pickGlEntities(const int x, const int y, std::vector<SelectedEntity> &pickedEntities,
274  tlp::GlLayer *layer = nullptr);
275 
276  /**
277  * @deprecated this function should not be used anymore, please use pickGlEntities() instead.
278  */
279  _DEPRECATED bool selectGlEntities(const int x, const int y, const int width, const int height,
280  std::vector<GlSimpleEntity *> &pickedEntities,
281  tlp::GlLayer *layer = nullptr) {
282  std::vector<SelectedEntity> entities;
283  pickGlEntities(x, y, width, height, entities, layer);
284  bool foundEntity = false;
285 
286  for (std::vector<SelectedEntity>::iterator it = entities.begin(); it != entities.end(); ++it) {
287  if ((*it).getEntityType() == SelectedEntity::SIMPLE_ENTITY_SELECTED) {
288  pickedEntities.push_back((*it).getSimpleEntity());
289  foundEntity = true;
290  }
291  }
292 
293  return foundEntity;
294  }
295 
296  /**
297  * @deprecated this function should not be used anymore, please use pickGlEntities() instead.
298  */
299  _DEPRECATED bool selectGlEntities(const int x, const int y,
300  std::vector<GlSimpleEntity *> &pickedEntities,
301  tlp::GlLayer *layer = nullptr) {
302  std::vector<SelectedEntity> entities;
303  pickGlEntities(x, y, entities, layer);
304  bool foundEntity = false;
305 
306  for (std::vector<SelectedEntity>::iterator it = entities.begin(); it != entities.end(); ++it) {
307  if ((*it).getEntityType() == SelectedEntity::SIMPLE_ENTITY_SELECTED) {
308  pickedEntities.push_back((*it).getSimpleEntity());
309  foundEntity = true;
310  }
311  }
312 
313  return foundEntity;
314  }
315 
316  /**
317  * Grab the FrameBuffer of this GlMainWidget
318  * @param withAlpha use alpha chanel
319  */
320  virtual QImage grabFrameBuffer(bool withAlpha = false);
321 
322  /**
323  * Extend makeCurrent function of QGLWidget to inform TextureManager and DisplayListManager of
324  * context changement
325  */
326  virtual void makeCurrent();
327 
328  /**
329  * Resize openGL view
330  */
331  void resizeGL(int w, int h) override;
332 
333  /**
334  * Compute interactors before drawing
335  */
336  void computeInteractors();
337 
338  /**
339  * Draw interactors
340  */
341  void drawInteractors();
342 
343  /**
344  * @brief This function performs all the rendering process of the graph.
345  * Use this function only for advanced purpose, if you want to perform simple rendering use the
346  *draw or redraw functions instead.
347  * @param options Configure the rendering process, see the RenderingOption documentation for more
348  *information on each rendering option effect.
349  * @see RenderingOption
350  * @param checkVisibility If check visibility is set as true : the engine check if GlMainWidget
351  *QWidget is visible. If set at false : the engine render the scene in all cases
352  **/
353  void render(RenderingOptions options = RenderingOptions(RenderScene | SwapBuffers),
354  bool checkVisibility = true);
355 
356  /**
357  * @brief Specify if the scene point of view must be kept
358  * when changing between graphs belonging to the same hierarchy
359  */
360  void setKeepScenePointOfViewOnSubgraphChanging(bool);
361  /**
362  * @brief Returns if the scene point of view must be kept
363  * when changing between graphs belonging to the same hierarchy
364  */
365  bool keepScenePointOfViewOnSubgraphChanging() const;
366 
367  /**
368  * @brief Specify if an advanced technique for better scene anti-aliasing has to be activated
369  *
370  * That option allows to obtain a better scene antialiasing through the use of offscreen rendering
371  * and sampling.
372  * The result rendering will look better while the performance will be slightly altered.
373  * That option is desactivated by default. Use it with caution as it could cause crashes with some
374  * buggy OpenGL drivers.
375  */
376  void setAdvancedAntiAliasing(bool advancedAntiAliasing) {
377  this->advancedAntiAliasing = advancedAntiAliasing;
378  }
379 
380  /**
381  * Returns the advanced anti-aliasing technique state
382  */
384  return advancedAntiAliasing;
385  }
386 
387 private:
388  void setupOpenGlContext();
389  void createRenderingStore(int width, int height);
390  void deleteRenderingStore();
391 
392  tlp::GlScene scene;
393  QRegion _visibleArea;
394  View *view;
395  int widthStored;
396  int heightStored;
397  unsigned char *renderingStore;
398  bool frameBufferStored;
399  bool useFramebufferObject;
400  QGLFramebufferObject *glFrameBuf, *glFrameBuf2;
401  static bool inRendering;
402  bool keepPointOfViewOnSubgraphChanging;
403  bool advancedAntiAliasing;
404 
405 public slots:
406  /**
407  * Draw the GlScene and the interactors
408  */
409  void draw(bool graphChanged = true);
410  /**
411  * This function is given for optimisation purpose only. If the hardware enable it,
412  * it enables to redraw only the Augmented display and the interactors and not the graph
413  * it is really usefull for interactors such as zoom box etc..
414  * Warning, if you change the graph or the porperties of element (Colors, size, etc...)
415  * applying that fonction will not display the change, in that case, use the draw function.
416  */
417  void redraw();
418 
419  void closeEvent(QCloseEvent *e) override;
420 
421  /**
422  * @brief Convenience function that call center function on the current scene, apply a zoom (if
423  *needed) and draw the view.
424  * Same thing than
425  * @code
426  * getScene()->centerScene();
427  * getScene()->zoomFactor();
428  * draw();
429  * @endcode
430  **/
431  void centerScene(bool graphChanged = false, float zoomFactor = 1.0);
432 
433  void emitGraphChanged();
434 
435 protected slots:
436  void paintEvent(QPaintEvent *) override;
437 
438 signals:
439  /**
440  * This signal is emit when the GlMainWidget will be deleted
441  */
442  void closing(GlMainWidget *, QCloseEvent *);
443 
444  /**
445  * This signal is emit when GlMainWidget::redraw() is call
446  */
447  void viewRedrawn(GlMainWidget *glWidget);
448  /**
449  * This signal is emit when GlMainWidget::draw() is call
450  */
451  void viewDrawn(GlMainWidget *glWidget, bool graphChanged);
452 
453  void glResized(int w, int h);
454 
455  void graphChanged();
456 
457 public:
458  /**
459  * This function return the first QGLWidget created
460  * This function is use to share OpenGL context
461  */
462  static QGLWidget *getFirstQGLWidget();
463 
464  static void clearFirstQGLWidget();
465 
466 private:
467  static QGLWidget *firstQGLWidget;
468 };
469 } // namespace tlp
470 
471 #endif
tlp::GlScene * getScene()
Get the GlScene of this GlMainWidget You have to add yours GlLayer and GlEntity to this GlScene At th...
Definition: GlMainWidget.h:102
double viewportToScreen(double l)
convert a viewport measure into a screen measure
Definition: GlMainWidget.h:190
bool selectGlEntities(const int x, const int y, const int width, const int height, std::vector< GlSimpleEntity *> &pickedEntities, tlp::GlLayer *layer=nullptr)
Definition: GlMainWidget.h:279
void setAdvancedAntiAliasing(bool advancedAntiAliasing)
Specify if an advanced technique for better scene anti-aliasing has to be activated.
Definition: GlMainWidget.h:376
ElementType
Definition: Graph.h:48
Tulip scene class.
Definition: GlScene.h:160
The edge struct represents an edge in a Graph object.
Definition: Edge.h:40
The node struct represents a node in a Graph object.
Definition: Node.h:40
bool advancedAntiAliasingActivated() const
Definition: GlMainWidget.h:383
double screenToViewport(double l)
convert a screen measure into a viewport measure
Definition: GlMainWidget.h:163
bool selectGlEntities(const int x, const int y, std::vector< GlSimpleEntity *> &pickedEntities, tlp::GlLayer *layer=nullptr)
Definition: GlMainWidget.h:299
View plugins provide a way to dynamically add to a Tulip plateform various ways to visualize a graph...
Definition: View.h:90
int screenToViewport(int l)
convert a screen measure into a viewport measure
Definition: GlMainWidget.h:150
Structure to store selected entities.
Definition: GlScene.h:48
RenderingOption
Configure the rendering process ( see render function)
Definition: GlMainWidget.h:74
A GlLayer is like an 2D drawing software layer system.
Definition: GlLayer.h:54
Coord viewportToScreen(const Coord &point)
convert a viewport point into a screen point
Definition: GlMainWidget.h:203
Coord screenToViewport(const Coord &point)
convert a screen point into a viewport point
Definition: GlMainWidget.h:176
This widget provide a simple system to visualize data/graph with OpenGL 3D engine.
Definition: GlMainWidget.h:66