Tulip  5.3.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 #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  * @param format indicates the format of the created image
229  */
230  QImage createPicture(int width, int height, bool center = true,
231  QImage::Format format = QImage::Format_RGB32);
232 
233  /**
234  * @brief Function to do picking on entities in a screen region
235  * It just calls selectEntities on the GlScene instance.
236  * @param x screen coordinates
237  * @param y screen coordinates
238  * @param width screen size
239  * @param height screen size
240  * @param pickedEntities filled with entity under the selection screen rectangle
241  * @param layer if you want to do the selection only on one GlLayer
242  */
243  bool pickGlEntities(const int x, const int y, const int width, const int height,
244  std::vector<SelectedEntity> &pickedEntities, tlp::GlLayer *layer = nullptr);
245  /**
246  * @brief Function to do picking on entities.
247  * It just calls selectEntities on the GlScene instance with a small window of twelve pixels.
248  * @param x screen coordinates
249  * @param y screen coordinates
250  * @param pickedEntities filled with entity under the selection screen rectangle
251  * @param layer if you want to do the selection only on one GlLayer
252  */
253  bool pickGlEntities(const int x, const int y, std::vector<SelectedEntity> &pickedEntities,
254  tlp::GlLayer *layer = nullptr);
255 
256  /**
257  * @deprecated this function should not be used anymore, please use pickGlEntities() instead.
258  */
259  _DEPRECATED bool selectGlEntities(const int x, const int y, const int width, const int height,
260  std::vector<GlSimpleEntity *> &pickedEntities,
261  tlp::GlLayer *layer = nullptr) {
262  std::vector<SelectedEntity> entities;
263  pickGlEntities(x, y, width, height, entities, layer);
264  bool foundEntity = false;
265 
266  for (std::vector<SelectedEntity>::iterator it = entities.begin(); it != entities.end(); ++it) {
267  if ((*it).getEntityType() == SelectedEntity::SIMPLE_ENTITY_SELECTED) {
268  pickedEntities.push_back((*it).getSimpleEntity());
269  foundEntity = true;
270  }
271  }
272 
273  return foundEntity;
274  }
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,
280  std::vector<GlSimpleEntity *> &pickedEntities,
281  tlp::GlLayer *layer = nullptr) {
282  std::vector<SelectedEntity> entities;
283  pickGlEntities(x, y, 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  * Extend makeCurrent function of QGLWidget to inform TextureManager and DisplayListManager of
298  * context changement
299  */
300  virtual void makeCurrent();
301 
302  /**
303  * Resize openGL view
304  */
305  void resizeGL(int w, int h) override;
306 
307  /**
308  * Compute interactors before drawing
309  */
310  void computeInteractors();
311 
312  /**
313  * Draw interactors
314  */
315  void drawInteractors();
316 
317  /**
318  * @brief This function performs all the rendering process of the graph.
319  * Use this function only for advanced purpose, if you want to perform simple rendering use the
320  *draw or redraw functions instead.
321  * @param options Configure the rendering process, see the RenderingOption documentation for more
322  *information on each rendering option effect.
323  * @see RenderingOption
324  * @param checkVisibility If check visibility is set as true : the engine check if GlMainWidget
325  *QWidget is visible. If set at false : the engine render the scene in all cases
326  **/
327  void render(RenderingOptions options = RenderingOptions(RenderScene | SwapBuffers),
328  bool checkVisibility = true);
329 
330  /**
331  * @brief Specify if the scene point of view must be kept
332  * when changing between graphs belonging to the same hierarchy
333  */
334  void setKeepScenePointOfViewOnSubgraphChanging(bool);
335  /**
336  * @brief Returns if the scene point of view must be kept
337  * when changing between graphs belonging to the same hierarchy
338  */
339  bool keepScenePointOfViewOnSubgraphChanging() const;
340 
341  /**
342  * @brief Specify if an advanced technique for better scene anti-aliasing has to be activated
343  *
344  * That option allows to obtain a better scene antialiasing through the use of offscreen rendering
345  * and sampling.
346  * The result rendering will look better while the performance will be slightly altered.
347  * That option is desactivated by default. Use it with caution as it could cause crashes with some
348  * buggy OpenGL drivers.
349  */
350  void setAdvancedAntiAliasing(bool advancedAntiAliasing) {
351  this->advancedAntiAliasing = advancedAntiAliasing;
352  }
353 
354  /**
355  * Returns the advanced anti-aliasing technique state
356  */
358  return advancedAntiAliasing;
359  }
360 
361 private:
362  void setupOpenGlContext();
363  void createRenderingStore(int width, int height);
364  void deleteRenderingStore();
365 
366  tlp::GlScene scene;
367  QRegion _visibleArea;
368  View *view;
369  int widthStored;
370  int heightStored;
371  unsigned char *renderingStore;
372  bool frameBufferStored;
373  bool useFramebufferObject;
374  QOpenGLFramebufferObject *glFrameBuf, *glFrameBuf2;
375  static bool inRendering;
376  bool keepPointOfViewOnSubgraphChanging;
377  bool advancedAntiAliasing;
378 
379 public slots:
380  /**
381  * Draw the GlScene and the interactors
382  */
383  void draw(bool graphChanged = true);
384  /**
385  * This function is given for optimisation purpose only. If the hardware enable it,
386  * it enables to redraw only the Augmented display and the interactors and not the graph
387  * it is really usefull for interactors such as zoom box etc..
388  * Warning, if you change the graph or the porperties of element (Colors, size, etc...)
389  * applying that fonction will not display the change, in that case, use the draw function.
390  */
391  void redraw();
392 
393  void closeEvent(QCloseEvent *e) override;
394 
395  /**
396  * @brief Convenience function that call center function on the current scene, apply a zoom (if
397  *needed) and draw the view.
398  * Same thing than
399  * @code
400  * getScene()->centerScene();
401  * getScene()->zoomFactor();
402  * draw();
403  * @endcode
404  **/
405  void centerScene(bool graphChanged = false, float zoomFactor = 1.0);
406 
407  void emitGraphChanged();
408 
409 protected slots:
410  void paintEvent(QPaintEvent *) override;
411 
412 signals:
413  /**
414  * This signal is emit when the GlMainWidget will be deleted
415  */
416  void closing(GlMainWidget *, QCloseEvent *);
417 
418  /**
419  * This signal is emit when GlMainWidget::redraw() is call
420  */
421  void viewRedrawn(GlMainWidget *glWidget);
422  /**
423  * This signal is emit when GlMainWidget::draw() is call
424  */
425  void viewDrawn(GlMainWidget *glWidget, bool graphChanged);
426 
427  void glResized(int w, int h);
428 
429  void graphChanged();
430 
431 public:
432  /**
433  * This function return the first QGLWidget created
434  * This function is use to share OpenGL context
435  */
436  static QGLWidget *getFirstQGLWidget();
437 
438  static void clearFirstQGLWidget();
439 
440 private:
441  static QGLWidget *firstQGLWidget;
442 };
443 } // namespace tlp
444 
445 #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:259
void setAdvancedAntiAliasing(bool advancedAntiAliasing)
Specify if an advanced technique for better scene anti-aliasing has to be activated.
Definition: GlMainWidget.h:350
ElementType
Definition: Graph.h:50
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:357
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:279
View plugins provide a way to dynamically add to a Tulip plateform various ways to visualize a graph...
Definition: View.h:95
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