Tulip  5.3.0
Large graphs analysis and drawing
graph_display/graph_display.cpp

This example gives a minimalistic approach of importing a graph and displaying it with Tulip OpenGL rendering engine In this example, we are making a standalone program that will load a graph file passed as argument to the program and display it into a new window.

The code contains a step-by-step explanation of the process, please refer to classes documentation for more information about their usage.

#include <tulip/PluginLoaderTxt.h>
#include <tulip/PluginLibraryLoader.h>
#include <tulip/GlMainWidget.h>
#include <tulip/MouseInteractors.h>
#include <tulip/TlpQtTools.h>
#include <tulip/LayoutProperty.h>
#include <tulip/SizeProperty.h>
#include <tulip/StringProperty.h>
#include <tulip/DoubleProperty.h>
#include <tulip/IntegerProperty.h>
#include <tulip/TulipViewSettings.h>
#include <tulip/GlGraphComposite.h>
#include <tulip/GlGraphRenderingParameters.h>
#include <QApplication>
#include <QString>
#include <iostream>
using namespace tlp;
using namespace std;
void addChildren(Graph *graph, node root, int depth, int degree) {
if (depth > 0) {
for (int i = 0; i < degree; ++i) {
node child = graph->addNode();
graph->addEdge(root, child);
addChildren(graph, child, depth - 1, degree);
}
}
}
Graph *createCompleteTree(int depth, int degree) {
Graph *graph = newGraph();
node root = graph->addNode();
addChildren(graph, root, depth, degree);
return graph;
}
// That function sets some visual properties on a complete tree whose depth equals 5
void setTreeVisualProperties(Graph *tree) {
// First compute a layout, we use the Bubble Tree algorithm
LayoutProperty *viewLayout = tree->getProperty<LayoutProperty>("viewLayout");
std::string errMsg;
tree->applyPropertyAlgorithm("Bubble Tree", viewLayout, errMsg);
// Then apply Auto Sizing on the nodes
SizeProperty *viewSize = tree->getProperty<SizeProperty>("viewSize");
tree->applyPropertyAlgorithm("Auto Sizing", viewSize, errMsg);
// Labels the node with their id
StringProperty *viewLabel = tree->getProperty<StringProperty>("viewLabel");
for (auto n : tree->nodes()) {
viewLabel->setNodeValue(n, QStringToTlpString(QString::number(n.id)));
}
// Add a border to the nodes, keep the default color who is black
DoubleProperty *viewBorderWidth = tree->getProperty<DoubleProperty>("viewBorderWidth");
viewBorderWidth->setAllNodeValue(1);
// Build some maps to set shapes and colors according to the dag level of a node
std::vector<int> glyphsMap;
glyphsMap.push_back(tlp::NodeShape::Square);
glyphsMap.push_back(tlp::NodeShape::Circle);
glyphsMap.push_back(tlp::NodeShape::RoundedBox);
glyphsMap.push_back(tlp::NodeShape::Hexagon);
glyphsMap.push_back(tlp::NodeShape::Star);
glyphsMap.push_back(tlp::NodeShape::Ring);
std::vector<Color> colorsMap;
colorsMap.push_back(Color::Red);
colorsMap.push_back(Color::Azure);
colorsMap.push_back(Color::Lemon);
colorsMap.push_back(Color::SpringGreen);
colorsMap.push_back(Color::Apricot);
colorsMap.push_back(Color::Magenta);
// Compute the Dag Level metric, the value of each node will correspond
// to their layer id in the tree
DoubleProperty dagLevel(tree);
tree->applyPropertyAlgorithm("Dag Level", &dagLevel, errMsg);
// Sets different shapes and colors for each layer of the tree
IntegerProperty *viewShape = tree->getProperty<IntegerProperty>("viewShape");
ColorProperty *viewColor = tree->getProperty<ColorProperty>("viewColor");
for (auto n : tree->nodes()) {
viewShape->setNodeValue(n, glyphsMap[int(dagLevel.getNodeValue(n))]);
viewColor->setNodeValue(n, colorsMap[int(dagLevel.getNodeValue(n))]);
}
}
// That function sets some rendering parameters on the graph to visualize
void setGraphRenderingParameters(GlGraphComposite *glGraphComposite) {
GlGraphRenderingParameters *renderingParameters =
glGraphComposite->getRenderingParametersPointer();
// Activate the display of edge extremities (arrows by default)
renderingParameters->setViewArrow(true);
// No color interpolation for the edges
renderingParameters->setEdgeColorInterpolate(false);
// Size interpolation for the edges
renderingParameters->setEdgeSizeInterpolate(true);
// Scale labels to node sizes
renderingParameters->setLabelScaled(true);
}
int main(int argc, char **argv) {
// A QApplication must always be declared at the beginning of the main function if you intend to
// use the tulip-gui library
// This must be done before calling tlp::initTulipSoftware()
QApplication app(argc, argv);
// Initialize the library and load all plugins
Graph *g = nullptr;
if (QApplication::arguments().size() == 2) {
// Load the file passed as first argument into a graph.
// This method will select the default Tulip algorithm plugin (TLP)
QString filename = QApplication::arguments()[1];
if (!((filename.endsWith(".tlp")) || (filename.endsWith(".tlp.gz")))) {
cout << "File " << QStringToTlpString(filename)
<< " not compatible. Use a tlp file or a tlp.gz file" << endl;
exit(EXIT_FAILURE);
}
} else {
// If no arguments were given to the command, create a complete tree of depth 5
// and degree 2 for demo purpose
g = createCompleteTree(5, 2);
// Set some visual properties in order to visualize the tree
setTreeVisualProperties(g);
}
// Creates the main widget that will display our graph
GlMainWidget *mainWidget = new GlMainWidget(nullptr);
// Adds a layer to the scene
GlLayer *mainLayer = mainWidget->getScene()->createLayer("Main");
// Adds the graph to this layer
mainLayer->addGraph(g, "graph");
// Sets some rendering parameters on the graph to visualize
setGraphRenderingParameters(mainWidget->getScene()->getGlGraphComposite());
// Display the widget
mainWidget->show();
// Flush event loop in order to let paint events pass through in order for the scene to be
// initialized.
QApplication::processEvents();
// Center the camera and draw the graph
mainWidget->centerScene();
mainWidget->draw();
// Adds Zoom and pan navigation to the widget
mainWidget->installEventFilter(new MouseNKeysNavigator);
return app.exec();
}