Skip to main content

Rounding glyph

Posted in

In the Tulip system a glyph is a small object drawing a node in a specific way. By example there is a glyph to represent nodes as spheres, cubes or square. If we want to add a new representation method for nodes we just have to create a new glyph plug-in.

In this tutorial we want to represent nodes with polygons. The number of sides of the polygon evolves in function of an integer value associated to the node. The higher the value the more sides the polygon has. A node with the value 3 will be represented by a triangle, a node with 4 by a square...

We will split the work in 3 parts :

  1. Base class creation.
  2. Getting glyph drawing parameters.
  3. Drawing the polygon.

 

Base class creation

To create a new glyph we have to inherit from the Glyph class. We will call it Rounding glyph as with a high number of sides this glyph looks like a circle.

Here is the base class declaration.


#ifndef ROUNDINGGLYPH_H_
#define ROUNDINGGLYPH_H_
#include <tulip/Glyph.h>
#include <math.h>

/**
 * RoundingGlyph class definition inherits from the tulip Glyph class.
 */
class RoundingGlyph: tlp::Glyph {
public:
        RoundingGlyph(tlp::GlyphContext *context);
        virtual ~RoundingGlyph();
	/**
	* Glyph drawing function. Performs all the drawing directives. 
	* The parameter called n is the node to draw.
	* The parameter called lod corresponds to the level of detail of the node.
	**/
	void draw(tlp::node n, float lod);
};

#endif /*ROUNDINGGLYPH_H_ */

And here the class definition.

#include "RoundingGlyph.h"
#include <tulip/Plugin.h>
#include <tulip/GlTools.h>
#include <tulip/GlTextureManager.h>
#include <tulip/IntegerProperty.h>
#include <utility>
#include <GL/glu.h>
using namespace tlp;
using namespace std;

RoundingGlyph::RoundingGlyph(tlp::GlyphContext *context) :
	Glyph(context) {
}

RoundingGlyph::~RoundingGlyph() {
}

void RoundingGlyph::draw(node n, float lod) {      
}
//Macro registering the plug-in into Tulip. The last number is the Glyph unique id. 
//Each glyph in Tulip must have a unqiue id. 
//Whe create a new glyph make sure to use an unused id for your plug-in.
GLYPHPLUGIN(RoundingGlyph,"2D - Rounding Glyph","Jonathan Dubois","","","1.0",29)

Getting glyph drawing parameters

Now we have the skeletton of our glyph. We have to get some drawing parameters into the graph like the number of sides, the node color ect...

We just have to update the draw function.

void RoundingGlyph::draw(node n, float lod) {    
    //Getting number of sides.
    //We will search the number of sides in a property called "viewRoundingGlyphSides"
    //This property is not a Tulip default property it only exists if the user creates it.
    //We have to check if this property exists, if it doesn't just set the side number to 3.
    unsigned int sidesNumber = 3;
    //Get the graph
    Graph* graph = glGraphInputData->getGraph();
    if(graph->existProperty("viewRoundingGlyphSides")){
        //The viewRoundingGlyphSides property exists, get the value for the node n.
        sidesNumber = graph->getProperty<IntegerProperty> ("viewRoundingGlyphSides")->getNodeValue(n);
    }
    //Get the node color.
    Color color = glGraphInputData->elementColor->getNodeValue(n);
    //Get the texture.
    string texture = glGraphInputData->elementTexture->getNodeValue(n);
    //Get the border width.
    double borderWith = glGraphInputData->elementBorderWidth->getNodeValue(n);
    //Get the border color.
    Color borderColor = glGraphInputData->elementBorderColor->getNodeValue(n);
}

Drawing the polygon

In this step we will use the parameters to draw the polygon.

First we will create a new function called drawPolygon to draw the glyph.

#ifndef ROUNDINGGLYPH_H_
#define ROUNDINGGLYPH_H_
#include <tulip/Glyph.h>
#include <math.h>

/**
 * RoundingGlyph class definition inherits from the tulip Glyph class.
 */
class RoundingGlyph: tlp::Glyph {
public:
        RoundingGlyph(tlp::GlyphContext *context);
        virtual ~RoundingGlyph();
	/**
	* Glyph drawing function. Performs all the drawing directives. 
	* The parameter called n is the node to draw.
	* The parameter called lod corresponds to the level of detail of the node.
	**/
	void draw(tlp::node n, float lod);
	/**
	* Draw the polygon in function of the drawing parameters.	
	**/
	void drawPolygon(unsigned int sliceNumber, const tlp::Color& nodeColor,
		const std::string& textureName, double borderWidth, 
                const tlp::Color& borderColor, float lod);
};

#endif /*ROUNDINGGLYPH_H_ */

Now we just have to implement this function and call it.

#include "RoundingGlyph.h"
#include <tulip/Plugin.h>
#include <tulip/GlTools.h>
#include <tulip/GlTextureManager.h>
#include <tulip/IntegerProperty.h>
#include <utility>
#include <GL/glu.h>
using namespace tlp;
using namespace std;

RoundingGlyph::RoundingGlyph(tlp::GlyphContext *context) :
	Glyph(context) {
}

RoundingGlyph::~RoundingGlyph() {
}

void RoundingGlyph::draw(node n, float lod) {    
   
//Getting number of sides.
    //We will search the number of sides in a property called "viewRoundingGlyphSides"
    //This property is not a Tulip default property it only exists if the user creates it.
    //We have to check if this property exists, if it doesn't just set the side number to 3.
    unsigned int sidesNumber = 3;
    //Get the graph
    Graph* graph = glGraphInputData->getGraph();
    if(graph->existProperty("viewRoundingGlyphSides")){
        //The viewRoundingGlyphSides property exists, get the value for the node n.
        sidesNumber = graph->getProperty<IntegerProperty> ("viewRoundingGlyphSides")->getNodeValue(n);
    }
    //Get the node color.
    Color color = glGraphInputData->elementColor->getNodeValue(n);
    //Get the texture.
    string texture = glGraphInputData->elementTexture->getNodeValue(n);
    //Get the border width.
    double borderWith = glGraphInputData->elementBorderWidth->getNodeValue(n);
    //Get the border color.
    Color borderColor = glGraphInputData->elementBorderColor->getNodeValue(n);    
    //Call the draw method
    drawPolygon(sidesNumber,color,texture,borderWith,borderColor,lod);
}

void RoundingGlyph::drawPolygon(unsigned int sliceNumber, const Color& nodeColor,
                                const string& textureName, double borderWidth, 
				const Color& borderColor, float lod) {
    //Set the drawing color to the node color.
    setMaterial(nodeColor);
    //Activate the texture if any
    if (textureName != "") {
        GlTextureManager::getInst().activateTexture(textureName);
    }
    //Check the number of sides and correct it if needed.
    GLint sliceNum = sliceNumber;
    if (sliceNum < 3)
        sliceNum = 3;

    //Create and initialize a GLUquadricObj to draw the polygon.
    GLUquadricObj *quadratic;
    quadratic = gluNewQuadric();
    gluQuadricNormals(quadratic, GLU_SMOOTH);
    gluQuadricTexture(quadratic, GL_TRUE);
    //Specify the quadratic orientaion to outside. Draw the front.
    gluQuadricOrientation(quadratic, GLU_OUTSIDE);
    //Use the gluDisk function to draw the polygon with the right number of sides.
    gluDisk(quadratic, 0.0f, 0.5f, sliceNum, 1);
    //Draw the inside of the polygon. Draw the rear.
    gluQuadricOrientation(quadratic, GLU_INSIDE);
    gluDisk(quadratic, 0.0f, 0.5f, sliceNum, 1);

    //Destuct the GLUquadricObj.
    gluDeleteQuadric(quadratic);

    //Disable the texture before drawing the border.
    GlTextureManager::getInst().desactivateTexture();

    //Check the level of detail before drawing the border.
    //The smaller the lod the less details we have to draw.
    //So if the object lod is under 20 we don't need to draw the border.
    if (lod > 20) {
        //Initialize the border width.
        if (borderWidth < 1e-6)
            glLineWidth(1e-6); //no negative borders
        else
            glLineWidth(borderWidth);
        //Set the border color.
        setColor(borderColor);
        //Draw the border.
        glBegin( GL_LINE_LOOP);
        double alpha = M_PI / 2.;
        double delta = 2. * M_PI / sliceNum;
        for (int i = 0; i < sliceNum; ++i) {
            glVertex3f(0.5 * cos(alpha), 0.5 * sin(alpha), 0.0);
            alpha += delta;
        }
        glEnd();
    }
}

//Macro registering the plug-in into Tulip. The last number is the Glyph unique id. 
//Each glyph in Tulip must have a unqiue id. 
//We create a new glyph make sure to use an unused id for your plug-in.
GLYPHPLUGIN(RoundingGlyph,"2D - Rounding Glyph","Jonathan Dubois","","","1.0",29)