Tulip  4.6.0
Better Visualization Through Research
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 <tulip/ForEach.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");
    node n;
    forEach(n, tree->getNodes()) {
        viewLabel->setNodeValue(n, QString::number(n.id).toStdString());
    }

    // 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");
    forEach(n, tree->getNodes()) {
        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
  tlp::initTulipSoftware();

  Graph* g = NULL;
  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 " << filename.toStdString() << " not compatible. Use a tlp file or a tlp.gz file" << endl;
          exit(EXIT_FAILURE);
      }
      g = tlp::loadGraph(filename.toStdString());
  } 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(NULL);

  // 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();
}
 All Classes Files Functions Variables Enumerations Enumerator Properties