We want to count the number of nodes of an X3D scene.
Some important functions and classes:
X3DTK::Singleton
.
Declaration of the class which inherits X3DTK::StateVariables
:
It is important to have a constructor with no parameter, because the instantiation of the class is accessed by theclass SimpleNodeCounterStateVariables : public StateVariables { public: SimpleNodeCounterStateVariables(); void init(); void addNode(); inline unsigned int getNodeNumber() const {return _count;}; private: unsigned int _count; };
X3DTK::Singleton
class. The definition of the class contains no X3DToolKit specific code.X3DTK::X3D::X3DNode
that belong to the Core component.
Declaration of the class which inherits X3DTK::X3D::CoreVisitor
:
The callback function is a static enter function taking anclass SimpleNodeCounterCoreVisitor : public CoreVisitor { public: SimpleNodeCounterCoreVisitor(); static void enterX3DNode(X3DNode *N); };
X3DTK::X3D::X3DNode
in parameter. The function must be static because if you want to reuse this function in another component visitor, you don't need to have a pointer to X3DTK::X3D::SimpleNodeCounterCoreVisitor
.Let's see the definition of the constructor:
The body of the constructor contains the most important line: the recording of the callback. The portable syntax is quite complicated. A generic template classSimpleNodeCounterCoreVisitor::SimpleNodeCounterCoreVisitor() : CoreVisitor() { define(Recorder<X3DNode>::getEnterFunction(&SimpleNodeCounterCoreVisitor::enterX3DNode)); }
X3DTK::Recorder
collects informations relative to the function. The member function pointer is used. The line means that an enter function acting on an X3DTK::X3D::X3DNode
is defined for X3DTK::X3D::SimpleNodeCounterVisitor
.And now the body of the callback function:
The state variables are accessed by the templatevoid SimpleNodeCounterCoreVisitor::enterX3DNode(X3DNode *N) { Singleton<SimpleNodeCounterStateVariables>::getInstance()->addNode(); }
X3DTK::Singleton
class ensuring that they are shared.
Declaration of the class which inherits X3DTK::X3DOnePassProcessor
:
It is important to have a constructor with no parameter since it is usual to instantiate the class by a singleton. Methods are made virtual to allow reuse.class SimpleNodeCounter : public X3DOnePassProcessor { public: SimpleNodeCounter(); virtual ~SimpleNodeCounter(); virtual void count(X3DNode *N); };
Let's have a look at the body of the constructor:
The first line assigns a Depth First Search walking algorithm, and the second one adds the component visitor previously defined.SimpleNodeCounter::SimpleNodeCounter() : X3DOnePassProcessor() { setGraphTraversal(new DFSGraphTraversal()); setComponentVisitor(new SimpleNodeCounterCoreVisitor()); }
Definition of the destructor:
The instance of the state variables is removed in the destructor, because it is useless.SimpleNodeCounter::~SimpleNodeCounter() { Singleton<SimpleNodeCounterStateVariables>::removeInstance(); }
Definition of the count
method:
The initialisation of the state variables is made as well as the call to thevoid SimpleNodeCounter::count(X3DNode *N) { Singleton<SimpleNodeCounterStateVariables>::getInstance()->init(); traverse(N); cout << "number of nodes is " << Singleton<SimpleNodeCounterStateVariables>::getInstance()->getNodeNumber() << endl; }
X3DTK::X3DOnePassProcessor::traverse
function, launching the graph traversal. It is often very important to have a call to an initialisation function, because of the use of singleton, the state variables are not destroyed at the end of the graph traversal and old values remain.#ifndef X3D_SIMPLENODECOUNTERSTATEVARIABLES_H #define X3D_SIMPLENODECOUNTERSTATEVARIABLES_H #include <X3DTK/kernel.h> namespace X3DTK { namespace X3D { class SimpleNodeCounterStateVariables : public StateVariables { public: SimpleNodeCounterStateVariables(); void init(); void addNode(); inline unsigned int getNodeNumber() const {return _count;}; private: unsigned int _count; }; } } #endif
#include "X3D_SimpleNodeCounterStateVariables.h" namespace X3DTK { namespace X3D { SimpleNodeCounterStateVariables::SimpleNodeCounterStateVariables() : _count(0) { } void SimpleNodeCounterStateVariables::init() { _count = 0; } void SimpleNodeCounterStateVariables::addNode() { ++_count; } } }
#ifndef X3D_SIMPLENODECOUNTERCOREVISITOR_H #define X3D_SIMPLENODECOUNTERCOREVISITOR_H #include <X3DTK/kernel.h> #include <X3DTK/X3D/scenegraph.h> namespace X3DTK { namespace X3D { class SimpleNodeCounterCoreVisitor : public CoreVisitor { public: SimpleNodeCounterCoreVisitor(); static void enterX3DNode(X3DNode *N); }; } } #endif
#include "X3D_SimpleNodeCounterCoreVisitor.h" #include "X3D_SimpleNodeCounterStateVariables.h" namespace X3DTK { namespace X3D { SimpleNodeCounterCoreVisitor::SimpleNodeCounterCoreVisitor() : CoreVisitor() { define(Recorder<X3DNode>::getEnterFunction(&SimpleNodeCounterCoreVisitor::enterX3DNode)); } void SimpleNodeCounterCoreVisitor::enterX3DNode(X3DNode *N) { Singleton<SimpleNodeCounterStateVariables>::getInstance()->addNode(); } } }
#ifndef X3D_SIMPLENODECOUNTER_H #define X3D_SIMPLENODECOUNTER_H #include <X3DTK/kernel.h> #include <X3DTK/X3D/scenegraph.h> namespace X3DTK { namespace X3D { class SimpleNodeCounter : public X3DOnePassProcessor { public: SimpleNodeCounter(); virtual ~SimpleNodeCounter(); virtual void count(X3DNode *N); }; } } #endif
#include "X3D_SimpleNodeCounter.h" #include "X3D_SimpleNodeCounterCoreVisitor.h" #include "X3D_SimpleNodeCounterStateVariables.h" #include <iostream> using namespace std; namespace X3DTK { namespace X3D { SimpleNodeCounter::SimpleNodeCounter() : X3DOnePassProcessor() { setGraphTraversal(new DFSGraphTraversal()); setComponentVisitor(new SimpleNodeCounterCoreVisitor()); } SimpleNodeCounter::~SimpleNodeCounter() { Singleton<SimpleNodeCounterStateVariables>::removeInstance(); } void SimpleNodeCounter::count(X3DNode *N) { Singleton<SimpleNodeCounterStateVariables>::getInstance()->init(); traverse(N); cout << "number of nodes is " << Singleton<SimpleNodeCounterStateVariables>::getInstance()->getNodeNumber() << endl; } } }