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