Improvements to dot visitors

This commit is contained in:
Robert Osfield 2017-12-07 17:52:24 +00:00
parent b8fd3abdd5
commit 25f5605ad8
4 changed files with 201 additions and 211 deletions

View File

@ -24,8 +24,11 @@ using namespace osg;
namespace osgDot { namespace osgDot {
BaseDotVisitor::BaseDotVisitor() BaseDotVisitor::BaseDotVisitor():
{ osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
{
// setNodeMaskOverride(0xffffff);
_rankdir = "rankdir = LR;"; _rankdir = "rankdir = LR;";
// Set the locale used by the _nodes and _edges streams to the // Set the locale used by the _nodes and _edges streams to the
// classic or "C" locale. This is needed because most of the // classic or "C" locale. This is needed because most of the
@ -33,156 +36,145 @@ namespace osgDot {
// by id numbers containing commas or periods. // by id numbers containing commas or periods.
_nodes.imbue(std::locale("C")); _nodes.imbue(std::locale("C"));
_edges.imbue(std::locale("C")); _edges.imbue(std::locale("C"));
} }
BaseDotVisitor::~BaseDotVisitor() { BaseDotVisitor::~BaseDotVisitor()
} {
}
void BaseDotVisitor::setOptions(const osgDB::Options* options) void BaseDotVisitor::setOptions(const osgDB::Options* options)
{
_options = const_cast<osgDB::Options*>(options);
OSG_INFO<<"BaseDotVisitor::setOptions("<<options<<")"<<std::endl;
if (_options.valid() && !(_options->getOptionString().empty()))
{ {
_options = const_cast<osgDB::Options*>(options);
OSG_INFO<<"BaseDotVisitor::setOptions("<<options<<")"<<std::endl; std::string optionString = _options->getOptionString();
if (_options.valid() && !(_options->getOptionString().empty()))
OSG_INFO<<" BaseDotVisitor::optionString ("<<optionString<<")"<<std::endl;
std::string::size_type pos = optionString.find("rankdir");
if (pos!=std::string::npos)
{ {
std::string::size_type semi_pos = optionString.find(";",pos);
std::string optionString = _options->getOptionString(); if (semi_pos!=std::string::npos)
OSG_INFO<<" BaseDotVisitor::optionString ("<<optionString<<")"<<std::endl;
std::string::size_type pos = optionString.find("rankdir");
if (pos!=std::string::npos)
{ {
std::string::size_type semi_pos = optionString.find(";",pos); _rankdir = optionString.substr(pos, semi_pos-pos);
if (semi_pos!=std::string::npos) OSG_INFO<<" BaseDotVisitor::Set _rankdir to "<<_rankdir<<std::endl;
{
_rankdir = optionString.substr(pos, semi_pos-pos);
OSG_INFO<<" BaseDotVisitor::Set _rankdir to "<<_rankdir<<std::endl;
}
} }
} }
} }
bool BaseDotVisitor::run( osg::Node& root, std::ostream* fout ) { }
setTraversalMode( TRAVERSE_ALL_CHILDREN );
if ( fout && *fout ) {
root.accept( *this );
*fout << "digraph osg_scenegraph { "<<_rankdir<< std::endl; bool BaseDotVisitor::run( osg::Node& root, std::ostream* fout )
{
*fout << _nodes.str() << _edges.str(); if ( fout && *fout )
{
root.accept( *this );
*fout << "}" << std::endl; *fout << "digraph osg_scenegraph { "<<_rankdir<< std::endl;
_nodes.clear(); *fout << "bgcolor=transparent;"<<std::endl;
_edges.clear();
_objectMap.clear();
return true; *fout << _nodes.str() << _edges.str();
*fout << "}" << std::endl;
_nodes.clear();
_edges.clear();
_objectMap.clear();
return true;
} }
return false; return false;
} }
void BaseDotVisitor::apply(Node& node) { void BaseDotVisitor::apply(Node& node)
{
int id; int id;
if ( getOrCreateId( &node, id ) ) { if ( getOrCreateId( &node, id ) )
handle( node, id ); {
handleNodeAndTraverse( node, id ); handle( node, id );
handleNodeAndTraverse( node, id );
} }
} }
void BaseDotVisitor::apply(Geode& node) { void BaseDotVisitor::apply(Drawable& drawable)
{
int id; int id;
if ( getOrCreateId( &node, id ) ) { if ( getOrCreateId( &drawable, id ) )
handle( node, id ); {
handleNodeAndTraverse( node, id ); handle( drawable, id );
handleNodeAndTraverse( drawable, id );
unsigned int i;
for ( i = 0; i < node.getNumDrawables(); i++ ) {
osg::Drawable* drawable = node.getDrawable( i );
int id2;
if ( getOrCreateId( drawable, id2 ) ) {
handle( *drawable, id2 );
osg::StateSet* s = drawable->getStateSet();
if ( s ) {
int id3;
if ( getOrCreateId( s, id3 ) ) {
handle( *s, id3 );
}
handle( *drawable, *s, id2, id3 );
}
}
handle( node, *drawable, id, id2 );
}
} }
}
} void BaseDotVisitor::apply(Group& node)
{
void BaseDotVisitor::apply(Group& node) {
int id; int id;
if ( getOrCreateId( &node, id ) ) { if ( getOrCreateId( &node, id ) )
handle( node, id ); {
handleNodeAndTraverse( node, id ); handle( node, id );
handleNodeAndTraverse( node, id );
unsigned int i; unsigned int i;
for ( i = 0; i < node.getNumChildren(); i++ ) { for ( i = 0; i < node.getNumChildren(); i++ )
osg::Node* child = node.getChild( i );
//handleNodeAndTraverse( *child );
int id2;
if (getOrCreateId( child, id2 ))
{ {
osg::Node* child = node.getChild( i );
//handleNodeAndTraverse( *child );
int id2;
getOrCreateId( child, id2 );
handle( node, *child, id, id2 ); handle( node, *child, id, id2 );
} }
}
} }
}
} void BaseDotVisitor::handle(osg::Node&, int) {}
void BaseDotVisitor::handle(osg::Node&, int) {} void BaseDotVisitor::handle(osg::Group&, int) {}
void BaseDotVisitor::handle(osg::Geode&, int) {} void BaseDotVisitor::handle(osg::Group&, osg::Node&, int, int) {}
void BaseDotVisitor::handle(osg::Group&, int) {} void BaseDotVisitor::handleNodeAndTraverse(osg::Node& node, int id)
{
void BaseDotVisitor::handle(osg::Group&, osg::Node&, int, int) {}
void BaseDotVisitor::handleNodeAndTraverse(osg::Node& node, int id) {
osg::StateSet* ss = node.getStateSet(); osg::StateSet* ss = node.getStateSet();
if ( ss ) { if ( ss )
int id2; {
if ( getOrCreateId( ss, id2 ) ) { int id2;
handle( *ss, id2 ); if ( getOrCreateId( ss, id2 ) )
} {
handle( node, *ss, id, id2 ); handle( *ss, id2 );
}
handle( node, *ss, id, id2 );
} }
traverse(node); traverse(node);
} }
void BaseDotVisitor::handle(osg::StateSet&, int) {} void BaseDotVisitor::handle(osg::StateSet&, int) {}
void BaseDotVisitor::handle(osg::Node&, osg::StateSet&, int, int) {} void BaseDotVisitor::handle(osg::Node&, osg::StateSet&, int, int) {}
void BaseDotVisitor::handle(osg::Drawable&, int) {} void BaseDotVisitor::handle(osg::Drawable&, int) {}
void BaseDotVisitor::handle(osg::Drawable&, osg::StateSet&, int, int) {} void BaseDotVisitor::handle(osg::Drawable&, osg::StateSet&, int, int) {}
void BaseDotVisitor::handle(osg::Geode&, osg::Drawable&, int, int) {} bool BaseDotVisitor::getOrCreateId( osg::Object* object, int &id )
{
bool BaseDotVisitor::getOrCreateId( osg::Object* object, int &id ) {
assert( object );
ObjectMap::iterator it = _objectMap.find( object ); ObjectMap::iterator it = _objectMap.find( object );
if ( it != _objectMap.end() ) { if ( it != _objectMap.end() )
id = it->second; {
return false; id = it->second;
return false;
} }
id = _objectMap.size(); id = _objectMap.size();
_objectMap[ object ] = id; _objectMap[ object ] = id;
return true; return true;
} }
} // namespace osgDot } // namespace osgDot

View File

@ -30,54 +30,52 @@
namespace osgDot { namespace osgDot {
class BaseDotVisitor : public osg::NodeVisitor { class BaseDotVisitor : public osg::NodeVisitor
public: {
typedef std::map< osg::Object*, int > ObjectMap; public:
typedef std::map< osg::Object*, int > ObjectMap;
public: public:
BaseDotVisitor(); BaseDotVisitor();
virtual ~BaseDotVisitor(); virtual ~BaseDotVisitor();
void setOptions(const osgDB::Options* options); void setOptions(const osgDB::Options* options);
bool run( osg::Node& root, std::ostream* ostream ); bool run( osg::Node& root, std::ostream* ostream );
virtual void apply(osg::Node& node); virtual void apply(osg::Node& node);
virtual void apply(osg::Geode& node); virtual void apply(osg::Drawable& node);
virtual void apply(osg::Group& node); virtual void apply(osg::Group& node);
protected:
protected: void handleNodeAndTraverse(osg::Node& node, int id);
void handleNodeAndTraverse(osg::Node& node, int id); virtual void handle(osg::StateSet& stateset, int id);
virtual void handle(osg::Drawable& drawable, int id);
virtual void handle(osg::Node& node, int id);
virtual void handle(osg::Group& node, int id);
virtual void handle(osg::Node& node, int id); virtual void handle(osg::Node& node, osg::StateSet& stateset, int parentID, int childID);
virtual void handle(osg::Geode& node, int id); virtual void handle(osg::Drawable& drawable, osg::StateSet& stateset, int parentID, int childID );
virtual void handle(osg::Group& node, int id); virtual void handle(osg::Group& parent, osg::Node& child, int parentID, int childID);
virtual void handle(osg::StateSet& stateset, int id);
virtual void handle(osg::Drawable& drawable, int id);
virtual void handle(osg::Node& node, osg::StateSet& stateset, int parentID, int childID); osg::ref_ptr<osgDB::Options> _options;
virtual void handle(osg::Group& parent, osg::Node& child, int parentID, int childID);
virtual void handle(osg::Geode& geode, osg::Drawable& drawable, int parentID, int childID);
virtual void handle(osg::Drawable& drawable, osg::StateSet& stateset, int parentID, int childID );
osg::ref_ptr<osgDB::Options> _options; std::string _rankdir;
std::string _rankdir; std::stringstream _nodes;
std::stringstream _edges;
std::stringstream _nodes; private:
std::stringstream _edges; bool getOrCreateId( osg::Object* object, int& id );
private: ObjectMap _objectMap;
bool getOrCreateId( osg::Object* object, int& id );
ObjectMap _objectMap; };
};
} // namespace osgDot } // namespace osgDot

View File

@ -15,79 +15,80 @@
namespace osgDot { namespace osgDot {
SimpleDotVisitor::SimpleDotVisitor() { SimpleDotVisitor::SimpleDotVisitor()
} {
}
SimpleDotVisitor::~SimpleDotVisitor() { SimpleDotVisitor::~SimpleDotVisitor()
} {
}
void SimpleDotVisitor::handle(osg::Node& node, int id) {
std::stringstream label;
label << "<top> Node";
if ( !node.getName().empty() ) { label << "| " << node.getName(); }
drawNode( id, "record", "solid", label.str(), "black", "white" );
}
void SimpleDotVisitor::handle(osg::Geode& node, int id) { void SimpleDotVisitor::handle(osg::StateSet& stateset, int id)
std::stringstream label; {
label << "<top> " << node.className();
if ( !node.getName().empty() ) { label << "| " << node.getName(); }
drawNode( id, "record", "solid", label.str(), "brown", "white" );
}
void SimpleDotVisitor::handle(osg::Group& node, int id) {
std::stringstream label;
label << "<top> " << node.className();
if ( !node.getName().empty() ) { label << "| " << node.getName(); }
drawNode( id, "record", "solid", label.str(), "black", "white" );
}
void SimpleDotVisitor::handle(osg::Group&, osg::Node&, int parentID, int childID ) {
drawEdge( parentID, childID, "setlinewidth(2)" );
}
void SimpleDotVisitor::handle(osg::StateSet& stateset, int id) {
std::stringstream label; std::stringstream label;
label << "<top> " << stateset.className(); label << "<top> " << stateset.className();
if ( !stateset.getName().empty() ) { label << "| " << stateset.getName(); } if ( !stateset.getName().empty() ) { label << " | " << stateset.getName(); }
drawNode( id, "Mrecord", "solid", label.str(), "green", "white" ); drawNode( id, "Mrecord", "solid, filled", label.str(), "green", "black" );
} }
void SimpleDotVisitor::handle(osg::Node&, osg::StateSet&, int parentID, int childID ) { void SimpleDotVisitor::handle(osg::Drawable& drawable, int id)
drawEdge( parentID, childID, "dashed" ); {
}
void SimpleDotVisitor::handle(osg::Drawable& drawable, int id) {
std::stringstream label; std::stringstream label;
label << "<top> " << drawable.className(); label << "<top> " << drawable.className();
if ( !drawable.getName().empty() ) { label << "| " << drawable.getName(); } if ( !drawable.getName().empty() ) { label << " | " << drawable.getName(); }
drawNode( id, "record", "solid", label.str(), "blue", "white" ); drawNode( id, "record", "solid, filled", label.str(), "lightblue", "black" );
} }
void SimpleDotVisitor::handle(osg::Geode&, osg::Drawable&, int parentID, int childID ) { void SimpleDotVisitor::handle(osg::Node& node, int id)
drawEdge( parentID, childID, "dashed" ); {
} std::stringstream label;
label << "<top> "<<node.className();
if ( !node.getName().empty() ) { label << " | " << node.getName(); }
drawNode( id, "record", "solid", label.str(), "black", "white" );
}
void SimpleDotVisitor::handle(osg::Drawable&, osg::StateSet&, int parentID, int childID ) { void SimpleDotVisitor::handle(osg::Group& node, int id)
drawEdge( parentID, childID, "dashed" ); {
} std::stringstream label;
label << "<top> " << node.className();
if ( !node.getName().empty() ) { label << " | " << node.getName(); }
drawNode( id, "record", "solid, filled", label.str(), "yellow", "black" );
}
void SimpleDotVisitor::drawNode( int id, const std::string& shape, const std::string& style, const std::string& label, const std::string& color, const std::string& fillColor ) { void SimpleDotVisitor::handle(osg::Node&, osg::StateSet&, int parentID, int childID )
{
drawEdge( parentID, childID, "" );
}
void SimpleDotVisitor::handle(osg::Drawable&, osg::StateSet&, int parentID, int childID )
{
drawEdge( parentID, childID, "" );
}
void SimpleDotVisitor::handle(osg::Group&, osg::Node&, int parentID, int childID )
{
drawEdge( parentID, childID, "" );
}
void SimpleDotVisitor::drawNode( int id, const std::string& shape, const std::string& style, const std::string& label, const std::string& color, const std::string& fillColor )
{
_nodes << id << _nodes << id <<
"[shape=\"" << shape << "[shape=\"" << shape <<
"\" ,label=\"" << label << "\" ,label=\"" << label <<
"\" ,style=\"" << style << "\" ,style=\"" << style <<
"\" ,color=\"" << color << "\" ,color=\"" << color <<
"\" ,fillColor=\"" << fillColor << "\" ,fillColor=\"" << fillColor <<
"\"]" << std::endl; "\"]" << std::endl;
} }
void SimpleDotVisitor::drawEdge( int sourceId, int sinkId, const std::string& style ) { void SimpleDotVisitor::drawEdge( int sourceId, int sinkId, const std::string& style )
{
_edges _edges
<< sourceId << ":top -> " << sourceId << ":top -> "
<< sinkId << ":top [style=\"" << sinkId << ":top [style=\""
<< style << "\"];" << style << "\"];"
<< std::endl; << std::endl;
} }
} // namespace osgDot } // namespace osgDot

View File

@ -23,30 +23,29 @@
namespace osgDot { namespace osgDot {
class SimpleDotVisitor : public BaseDotVisitor { class SimpleDotVisitor : public BaseDotVisitor
public: {
SimpleDotVisitor(); public:
SimpleDotVisitor();
virtual ~SimpleDotVisitor(); virtual ~SimpleDotVisitor();
protected: protected:
virtual void handle(osg::Node& node, int id);
virtual void handle(osg::Geode& geode, int id);
virtual void handle(osg::Group& node, int id);
virtual void handle(osg::StateSet& stateset, int id); virtual void handle(osg::StateSet& stateset, int id);
virtual void handle(osg::Drawable& drawable, int id); virtual void handle(osg::Drawable& drawable, int id);
virtual void handle(osg::Node& node, int id);
virtual void handle(osg::Group& node, int id);
virtual void handle(osg::Node& node, osg::StateSet& stateset, int parentID, int childID ); virtual void handle(osg::Node& node, osg::StateSet& stateset, int parentID, int childID );
virtual void handle(osg::Geode& geometry, osg::Drawable& drawable, int parentID, int childID ); virtual void handle(osg::Drawable& drawable, osg::StateSet& stateset, int parentID, int childID );
virtual void handle(osg::Group& parent, osg::Node& child, int parentID, int childID ); virtual void handle(osg::Group& parent, osg::Node& child, int parentID, int childID );
virtual void handle(osg::Drawable& drawable, osg::StateSet& stateset, int parentID, int childID );
virtual void drawNode( int id, const std::string& shape, const std::string& style, const std::string& label, const std::string& color, const std::string& fillColor ); virtual void drawNode( int id, const std::string& shape, const std::string& style, const std::string& label, const std::string& color, const std::string& fillColor );
virtual void drawEdge( int sourceId, int sinkId, const std::string& style ); virtual void drawEdge( int sourceId, int sinkId, const std::string& style );
}; };
} // namespace osgDot } // namespace osgDot