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