This is an example on how to create a parent node, meaning a node that can have children. That implies that we must extend the traversal algorithm to visit the children of the node. Here we define an X3D::Info
node that can contain two nodes, X3D::Price
and X3D::Modeler
.
Like a node that can only be a child, the three special methods load
, write
and clone
still have to be redefined. Nevertheless others methods must be redefined. For the X3D::Price
child, the methods setPrice
and getPrice
are defined. Note in setPrice
the calls to removeLink
and addLink
. Three other necessary methods are redefined: setChild
, addChild
and removeChild
.
These nodes are simple child nodes and are defined like the nodes of the precedent examples.
To enable the visit of the X3D::Price
and X3D::Modeler
, We have to extend the X3D::DFSGroupingWalker
because X3D::Info
belongs to the Grouping Component. To finish, we extend the DFS algorithm X3D::DFSGraphTraversal
by defining X3D::MyDFSGraphTraversal
.
To test X3D::MyDFS
, we define a new processor called InfoReader
that extracts and displays the content of the nodes X3D::Info
, X3D::Price
and X3D::Modeler
.
#ifndef INFO_H #define INFO_H #include <X3DTK/x3d_scenegraph.h> namespace X3DTK { namespace X3D { class Price; class Modeler; class Info : public X3DChildNode { public: // Constructor. Info(); // Constructs a Cylinder from its attributes. Info(const SFString &date, SFNode price, SFNode modeler); // Destructor. ~Info(); // Clones the node. virtual SFNode clone() const; // sets the date. void setDate(const SFString &date); // sets the Price node. void setPrice(Price *price); // sets the Modeler node. void setModeler(Modeler *modeler); // gets the date. inline const SFString &getDate() const {return _date;}; // sets the Price node. inline SFNode getPrice() const {return _price;}; // sets the Modeler node. inline SFNode getModeler() const {return _modeler;}; virtual bool addChild(const SFAbstractNode &N); virtual bool setChild(const SFAbstractNode &N); virtual bool removeChild(const SFAbstractNode &N); // Loads the attributes from a X3DFileElement e. virtual void load(const X3DFileElement *element); // Writes the attributes of the node. virtual SFString write() const; protected: // Copy constructor. Info(const Info &I); private: SFString _date; SFNode _price; SFNode _modeler; }; } } #endif
#include "X3D_Info.h" #include "X3D_Price.h" #include "X3D_Modeler.h" namespace X3DTK { namespace X3D { Info::Info() : X3DChildNode(), _date("0/0/0"), _price(0), _modeler(0) { // Defines the tag of the node. This string must be the same than the one // entered for the creation function, otherwise the node won't be loaded. defineTypeName("Info"); } Info::Info(const SFString &date, SFNode price, SFNode modeler) : X3DChildNode(), _date(date), _price(price), _modeler(modeler) { // Defines the tag of the node. defineTypeName("Info"); } Info::Info(const Info &I) : X3DChildNode(I), _date(I._date), _price(I._price), _modeler(I._modeler) { } Info::~Info() { removeParentFromChild(this, _price); removeParentFromChild(this, _modeler); } SFNode Info::clone() const { return new Info(*this); } void Info::setDate(const SFString &date) { _date = date; } void Info::setPrice(Price *price) { removeParentFromChild(this, _price); _price = price; addParentToChild(this, _price); } void Info::setModeler(Modeler *modeler) { removeParentFromChild(this, _modeler); _modeler = modeler; addParentToChild(this, _modeler); } bool Info::addChild(const SFAbstractNode &N) { if (dynamic_cast<Price *>(N) != 0) { if (_price != 0) return false; setPrice(static_cast<Price *>(N)); return true; } if (dynamic_cast<Modeler *>(N) != 0) { if (_modeler != 0) return false; setModeler(static_cast<Modeler *>(N)); return true; } return false; } bool Info::setChild(const SFAbstractNode &N) { if (dynamic_cast<Price *>(N) != 0) { setPrice(static_cast<Price *>(N)); return true; } if (dynamic_cast<Modeler *>(N) != 0) { setModeler(static_cast<Modeler *>(N)); return true; } return false; } bool Info::removeChild(const SFAbstractNode &N) { if (_price == N) { setPrice(0); return true; } if (_modeler == N) { setModeler(0); return true; } return false; } void Info::load(const X3DFileElement *element) { int index; index = element->getIndexAttribute("date"); if (index != -1) _date = element->getAttribute(index); } SFString Info::write() const { SFString attr; if (_date != "0/0/0") attr += " date=\"" + toSFString(_date) + "\""; return attr; } } }
#ifndef PRICE_H #define PRICE_H #include <X3DTK/x3d_scenegraph.h> namespace X3DTK { namespace X3D { class Price : public X3DChildNode { public: // Constructor. Price(); // Constructs a Cylinder from its attributes. Price(const SFFloat &price, const SFString &money); // Clones the node. virtual SFNode clone() const; // sets the date. void setPrice(const SFFloat &price); // sets the date. void setMoney(const SFString &money); // gets the price. inline const SFFloat &getPrice() const {return _price;}; // sets the money. inline const SFString &getMoney() const {return _money;}; // Loads the attributes from a X3DFileElement e. virtual void load(const X3DFileElement *element); // Writes the attributes of the node. virtual SFString write() const; protected: // Copy constructor. Price(const Price &I); private: SFFloat _price; SFString _money; }; } } #endif
#include "X3D_Price.h" namespace X3DTK { namespace X3D { Price::Price() : X3DChildNode(), _price(0.0f), _money("euro") { // Defines the tag of the node. This string must be the same than the one // entered for the creation function, otherwise the node won't be loaded. defineTypeName("Price"); } Price::Price(const SFFloat &price, const SFString &money) : X3DChildNode(), _price(price), _money(money) { // Defines the tag of the node. defineTypeName("Price"); } Price::Price(const Price &P) : X3DChildNode(P), _price(P._price), _money(P._money) { } SFNode Price::clone() const { return new Price(*this); } void Price::setPrice(const SFFloat &price) { _price = price; } void Price::setMoney(const SFString &money) { _money = money; } void Price::load(const X3DFileElement *element) { int index; index = element->getIndexAttribute("price"); if (index != -1) _price = element->getAttribute(index).toFloat(); index = element->getIndexAttribute("money"); if (index != -1) _money = element->getAttribute(index); } SFString Price::write() const { SFString attr; if (_price != 0.0f) attr += " price=\"" + toSFString(_price) + "\""; if (_money != "euro") attr += " money=\"" + _money + "\""; return attr; } } }
#ifndef MODELER_H #define MODELER_H #include <X3DTK/x3d_scenegraph.h> namespace X3DTK { namespace X3D { class Modeler : public X3DChildNode { public: // Constructor. Modeler(); // Constructs a Cylinder from its attributes. Modeler(const SFString &name); // Clones the node. virtual SFNode clone() const; // sets the date. void setName(const SFString &name); // gets the name. inline const SFString &getName() const {return _name;}; // Loads the attributes from a X3DFileElement e. virtual void load(const X3DFileElement *element); // Writes the attributes of the node. virtual SFString write() const; protected: // Copy constructor. Modeler(const Modeler &I); private: SFString _name; }; } } #endif
#include "X3D_Modeler.h" namespace X3DTK { namespace X3D { Modeler::Modeler() : X3DChildNode(), _name("") { // Defines the tag of the node. This string must be the same than the one // entered for the creation function, otherwise the node won't be loaded. defineTypeName("Modeler"); } Modeler::Modeler(const SFString &name) : X3DChildNode(), _name(name) { // Defines the tag of the node. defineTypeName("Modeler"); } Modeler::Modeler(const Modeler &P) : X3DChildNode(P), _name(P._name) { } SFNode Modeler::clone() const { return new Modeler(*this); } void Modeler::setName(const SFString &name) { _name = name; } void Modeler::load(const X3DFileElement *element) { int index; index = element->getIndexAttribute("name"); if (index != -1) _name = element->getAttribute(index); } SFString Modeler::write() const { SFString attr; if (_name != "") attr += " name=\"" + _name + "\""; return attr; } } }
#ifndef MYGROUPINGCREATOR_H #define MYGROUPINGCREATOR_H #include <X3DTK/x3d_scenegraph.h> namespace X3DTK { namespace X3D { // Concrete component Creator for the Grouping component defining the default // X3D nodes. class MyGroupingCreator : public GroupingCreator { public: // Constructor. MyGroupingCreator(); }; } } #endif
#include "X3D_MyGroupingCreator.h" #include "X3D_Info.h" #include "X3D_Price.h" #include "X3D_Modeler.h" namespace X3DTK { namespace X3D { MyGroupingCreator::MyGroupingCreator() : GroupingCreator() { // Defines the new creation functions for the new nodes. defineNode<Info>(); defineNode<Price>(); defineNode<Modeler>(); } } }
#ifndef MyDFSGROUPINGWALKER_H #define MyDFSGROUPINGWALKER_H #include <X3DTK/x3d_scenegraph.h> namespace X3DTK { namespace X3D { class Info; class MyDFSGroupingWalker : public DFSGroupingWalker { public: MyDFSGroupingWalker(); virtual ~MyDFSGroupingWalker(); virtual void walkInfo(Info *I) const; }; } } #endif
#include "X3D_MyDFSGroupingWalker.h" #include "X3D_Info.h" #include "X3D_Price.h" #include "X3D_Modeler.h" #include <iostream> using namespace std; namespace X3DTK { namespace X3D { MyDFSGroupingWalker::MyDFSGroupingWalker() : DFSGroupingWalker() { defineWalkingFunction(&MyDFSGroupingWalker::walkInfo); } MyDFSGroupingWalker::~MyDFSGroupingWalker() { } void MyDFSGroupingWalker::walkInfo(Info *I) const { visitor->enter(I); SFNode N = I->getPrice(); if ((N != 0) && (visitor->walkOn(I, N))) walker->walk(N); N = I->getModeler(); if ((N != 0) && (visitor->walkOn(I, N))) walker->walk(N); visitor->leave(I); } } }
#ifndef MYDFSGRAPHTRAVERSAL_H #define MYDFSGRAPHTRAVERSAL_H #include <X3DTK/x3d_scenegraph.h> namespace X3DTK { namespace X3D { class MyDFSGraphTraversal : public DFSGraphTraversal { public: MyDFSGraphTraversal(); }; } } #endif
#include "X3D_MyDFSGraphTraversal.h" #include "X3D_MyDFSGroupingWalker.h" namespace X3DTK { namespace X3D { MyDFSGraphTraversal::MyDFSGraphTraversal() { setComponentWalker(new MyDFSGroupingWalker()); } } }
#ifndef INFOREADERGROUPINGVISITOR_H #define INFOREADERGROUPINGVISITOR_H #include <X3DTK/x3d_scenegraph.h> namespace X3DTK { namespace X3D { class Info; class Price; class Modeler; class InfoReaderGroupingVisitor : public GroupingVisitor { public: InfoReaderGroupingVisitor(); virtual ~InfoReaderGroupingVisitor(); virtual void enterInfo(Info *I) const; virtual void enterPrice(Price *P) const; virtual void enterModeler(Modeler *M) const; }; } } #endif
#include "X3D_InfoReaderGroupingVisitor.h" #include "X3D_Info.h" #include "X3D_Price.h" #include "X3D_Modeler.h" #include <iostream> using namespace std; namespace X3DTK { namespace X3D { InfoReaderGroupingVisitor::InfoReaderGroupingVisitor() : GroupingVisitor() { // WalkOn functions. defineEnterFunction(&InfoReaderGroupingVisitor::enterInfo); defineEnterFunction(&InfoReaderGroupingVisitor::enterPrice); defineEnterFunction(&InfoReaderGroupingVisitor::enterModeler); } InfoReaderGroupingVisitor::~InfoReaderGroupingVisitor() { } void InfoReaderGroupingVisitor::enterInfo(Info *I) const { cout << "Informations relative to the scene:"<< endl; } void InfoReaderGroupingVisitor::enterPrice(Price *P) const { cout << " price = " << P->getPrice() << " " << P->getMoney() << endl; } void InfoReaderGroupingVisitor::enterModeler(Modeler *M) const { cout << " realized on the " << M->getName() << " modeler" << endl; } } }
#ifndef INFOREADER_H #define INFOREADER_H #include <X3DTK/kernel.h> #include <X3DTK/x3d_scenegraph.h> namespace X3DTK { namespace X3D { class InfoReader : public X3DOnePassProcessor { public: InfoReader(); virtual ~InfoReader(); virtual void read(SFNode N); }; } } #endif
#include "X3D_InfoReader.h" #include "X3D_MyDFSGraphTraversal.h" #include "X3D_InfoReaderGroupingVisitor.h" namespace X3DTK { namespace X3D { InfoReader::InfoReader() { graphTraversal = new MyDFSGraphTraversal(); graphTraversal->setComponentVisitor(new InfoReaderGroupingVisitor()); } InfoReader::~InfoReader() { delete graphTraversal; } void InfoReader::read(SFNode N) { graphTraversal->traverse(N); } } }
#include "X3D_InfoReader.h" #include "X3D_MyGroupingCreator.h" #include <X3DTK/x3d_scenegraph.h> #include <iostream> using namespace X3DTK; using namespace std; int main(int argc, char *argv[]) { if (argc <= 1) { cerr << "usage: infoReader input" << endl; exit(0); } // DefaultLoader to load the default X3D Nodes. X3D::Loader *loader = X3DLoader::getInstanceOf<X3D::Loader>(); loader->setComponentCreator(new X3D::MyGroupingCreator()); // Instanciation of the new InfoReader. X3D::InfoReader *infoReader = X3DProcessor::getInstanceOf<X3D::InfoReader>(); // Loads the scene. X3D::Scene *s = loader->load(argv[1], false); // reads the graph. infoReader->read(s); // Removes the instances. X3DProcessor::removeInstanceOf<X3D::InfoReader>(); X3DLoader::removeInstanceOf<X3D::Loader>(); return 1; }