ExportDotVisitor.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #include <sofa/simulation/tree/ExportDotVisitor.h>
00026 #include <sofa/helper/system/config.h>
00027 #include <sofa/helper/Factory.h>
00028 #include <sofa/simulation/common/Node.h>
00029 #include <sofa/simulation/common/Colors.h>
00030 
00031 namespace sofa
00032 {
00033 
00034 namespace simulation
00035 {
00036 
00037 namespace tree
00038 {
00039 
00040 ExportDotVisitor::ExportDotVisitor(std::ostream* out)
00041 : out(out),
00042   showNode(true),
00043   showObject(true),
00044   showBehaviorModel(true),
00045   showCollisionModel(true),
00046   showVisualModel(true),
00047   showMapping(true),
00048   showContext(true),
00049   showCollisionPipeline(true),
00050   showSolver(true),
00051   showMechanicalState(true),
00052   showForceField(true),
00053   showInteractionForceField(true),
00054   showConstraint(true),
00055   showMass(true),
00056   showTopology(true),
00057   showMechanicalMapping(true),
00058   labelNodeName(true),
00059   labelNodeClass(false),
00060   labelObjectName(true),
00061   labelObjectClass(true)
00062 {
00063     *out << "digraph G {" << std::endl;
00064 }
00065 
00066 ExportDotVisitor::~ExportDotVisitor()
00067 {
00068     *out << "}" << std::endl;
00069 }
00070 
00072 bool ExportDotVisitor::display(GNode* node, const char **color)
00073 {
00074     using namespace Colors;
00075     if (!node) return false;
00076     if (showNode)
00077     {
00078         if (color) *color = COLOR[NODE];
00079         return true;
00080     }
00081     else
00082         return false;
00083 }
00084 
00086 bool ExportDotVisitor::display(core::objectmodel::BaseObject* obj, const char **color)
00087 {
00088     using namespace Colors;
00089     const char* c = NULL;
00090     if (color==NULL) color=&c;
00091     if (!obj) return false;
00092     if (!showObject) return false;
00093     *color = COLOR[OBJECT];
00094     bool show = false;
00095     bool hide = false;
00096     if (dynamic_cast<core::componentmodel::behavior::BaseMechanicalState*>(obj)){
00097         if (showMechanicalState) { show = true; *color = COLOR[MMODEL]; } else hide = true;}
00098     if (dynamic_cast<core::componentmodel::behavior::BaseMass*>(obj)){
00099         if (showMass) { show = true; *color = COLOR[MASS]; } else hide = true;}
00100     if (dynamic_cast<core::componentmodel::topology::Topology *>(obj)){
00101         if (showTopology) { show = true; *color = COLOR[TOPOLOGY]; } else hide = true;}
00102     if (dynamic_cast<core::CollisionModel*>(obj)){
00103         if (showCollisionModel) { show = true; *color = COLOR[CMODEL]; } else hide = true;}
00104     if (dynamic_cast<core::componentmodel::behavior::BaseMechanicalMapping*>(obj)){
00105         if (showMechanicalMapping) { show = true; *color = COLOR[MMAPPING]; } else hide = true;}
00106     else if (dynamic_cast<core::BaseMapping*>(obj)){
00107         if (showMapping) { show = true; *color = COLOR[MAPPING]; } else hide = true;}
00108     if (dynamic_cast<core::objectmodel::ContextObject*>(obj)){
00109         if (showContext) { show = true; *color = COLOR[CONTEXT]; } else hide = true;}
00110     if (dynamic_cast<core::componentmodel::collision::Pipeline*>(obj)
00111         || dynamic_cast<core::componentmodel::collision::Intersection*>(obj)
00112         || dynamic_cast<core::componentmodel::collision::Detection*>(obj)
00113         || dynamic_cast<core::componentmodel::collision::ContactManager*>(obj)
00114         || dynamic_cast<core::componentmodel::collision::CollisionGroupManager*>(obj)){
00115         if (showCollisionPipeline) { show = true; *color = COLOR[COLLISION]; } else hide = true;}
00116     if (dynamic_cast<core::componentmodel::behavior::OdeSolver*>(obj)){
00117         if (showSolver) { show = true; *color = COLOR[SOLVER]; } else hide = true;}
00118     if (dynamic_cast<core::componentmodel::behavior::InteractionForceField*>(obj) &&
00119         dynamic_cast<core::componentmodel::behavior::InteractionForceField*>(obj)->getMechModel1()!=dynamic_cast<core::componentmodel::behavior::InteractionForceField*>(obj)->getMechModel2()){
00120         if (showInteractionForceField) { show = true; *color = COLOR[IFFIELD]; } else hide = true;}
00121     else if (dynamic_cast<core::componentmodel::behavior::BaseForceField*>(obj)){
00122         if (showForceField) { show = true; *color = COLOR[FFIELD]; } else hide = true;}
00123     if (dynamic_cast<core::componentmodel::behavior::BaseConstraint*>(obj)){
00124         if (showConstraint) { show = true; *color = COLOR[CONSTRAINT]; } else hide = true;}
00125     if (dynamic_cast<core::BehaviorModel*>(obj)){
00126         if (showBehaviorModel) { show = true; *color = COLOR[BMODEL]; } else hide = true;}
00127 
00128     if (dynamic_cast<core::VisualModel*>(obj) && !hide && !show){
00129         if (showVisualModel) { show = true; *color = COLOR[VMODEL]; } else hide = true;}
00130 
00131     return show || !hide;
00132 }
00133 
00137 std::string ExportDotVisitor::getParentName(core::objectmodel::BaseObject* obj)
00138 {
00139     GNode* node = dynamic_cast<GNode*>(obj->getContext());
00140     if (!node) return "";
00141     if (display(node))
00142         return getName(node);
00143     if (dynamic_cast<core::BaseMapping*>(obj))
00144         return "";
00145     if (!node->collisionPipeline.empty() && display(node->collisionPipeline) &&
00146         (dynamic_cast<core::componentmodel::collision::Intersection*>(obj) ||
00147          dynamic_cast<core::componentmodel::collision::Detection*>(obj) ||
00148          dynamic_cast<core::componentmodel::collision::ContactManager*>(obj) ||
00149          dynamic_cast<core::componentmodel::collision::CollisionGroupManager*>(obj)))
00150          return getName(node->collisionPipeline);
00152         if (node->mechanicalState!=obj && node->solver[0]!=obj  && node->masterSolver!=obj && display(node->mechanicalState))
00153         return getName(node->mechanicalState);
00154     if (node->solver[0]!=obj && node->masterSolver!=obj && display(node->solver[0]))
00155         return getName(node->solver[0]);
00156     if (node->masterSolver!=obj && display(node->solver[0]))
00157         return getName(node->masterSolver);
00158     if ((node->mechanicalState==obj || node->solver[0]==obj) && node->mechanicalMapping==NULL && node->parent!=NULL && display(node->parent->solver[0]))
00159         return getName(node->parent->solver[0]);
00160     if ((node->mechanicalState==obj || node->solver[0]==obj || node->masterSolver==obj) && node->mechanicalMapping==NULL && node->parent!=NULL && display(node->parent->masterSolver))
00161         return getName(node->parent->masterSolver);
00162     return "";
00163 }
00164 
00166 std::string ExportDotVisitor::getName(core::objectmodel::Base* o, std::string prefix)
00167 {
00168     if (names.count(o)>0)
00169         return names[o];
00170     std::string oname = o->getName();
00171     std::string name = prefix;
00172     for (unsigned i = 0; i<oname.length(); i++)
00173     {
00174         char c = oname[i];
00175         static const char *chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
00176         if (strchr(chars, c))
00177             name += c;
00178     }
00179     if (name.length() > prefix.length())
00180         name += '_';
00181     int index = nextIndex[name]++;
00182     if (index)
00183     {
00184         char str[16];
00185         snprintf(str,sizeof(str),"%d",index+1);
00186         name += str;
00187     }
00188     names[o] = name;
00189     return name;
00190 }
00191 
00193 std::string ExportDotVisitor::getName(GNode* node)
00194 {
00195     return getName(node, "n_");
00196 }
00197 
00199 std::string ExportDotVisitor::getName(core::objectmodel::BaseObject* obj)
00200 {
00201     return getName(obj, "o_");
00202 }
00203 
00204 void ExportDotVisitor::processObject(GNode* /*node*/, core::objectmodel::BaseObject* obj)
00205 {
00206     //std::cout << ' ' << obj->getName() << '(' << sofa::helper::gettypename(typeid(*obj)) << ')';
00207     const char* color=NULL;
00208     if (display(obj,&color))
00209     {
00210         std::string name = getName(obj);
00211         *out << name << " [shape=box,";
00212         if (color!=NULL)
00213             *out << "style=\"filled\",fillcolor=\"" << color << "\",";
00214         *out << "label=\"";
00215         if (labelObjectClass)
00216         {
00217             std::string name = helper::gettypename(typeid(*obj));
00218             std::string::size_type pos = name.find('<');
00219             if (pos != std::string::npos)
00220                 name.erase(pos);
00221             *out << name;
00222             if (labelObjectName)
00223                 *out << "\\n";
00224         }
00225         if (labelObjectName)
00226         {
00227             if (std::string(obj->getName(),0,7) != "default")
00228                 *out << obj->getName();
00229         }
00230         *out << "\"];" << std::endl;
00231         std::string pname = getParentName(obj);
00232         if (!pname.empty())
00233         {
00234             *out << pname << " -> " << name;
00235             if (dynamic_cast<core::BaseMapping*>(obj))
00236                 *out << "[constraint=false]";
00237             *out << ";" << std::endl;
00238         }
00239         core::componentmodel::behavior::InteractionForceField* iff = dynamic_cast<core::componentmodel::behavior::InteractionForceField*>(obj);
00240         if (iff!=NULL)
00241         {
00242             core::componentmodel::behavior::BaseMechanicalState* model1 = iff->getMechModel1();
00243             core::componentmodel::behavior::BaseMechanicalState* model2 = iff->getMechModel2();
00244             if (model1 != model2)
00245             {
00246                 if (display(model1))
00247                     *out << name << " -> " << getName(model1) << " [style=\"dashed\",arrowhead=\"open\"];" << std::endl;
00248                 if (display(model2))
00249                     *out << name << " -> " << getName(model2) << " [style=\"dashed\",arrowhead=\"open\"];" << std::endl;
00250             }
00251         }
00252         core::BaseMapping* map = dynamic_cast<core::BaseMapping*>(obj);
00253         if (map!=NULL)
00254         {
00255             core::objectmodel::BaseObject* model1 = map->getFrom();
00256             core::objectmodel::BaseObject* model2 = map->getTo();
00257             if (display(model1))
00258             {
00259                 *out << getName(model1) << " -> " << name << " [style=\"dashed\",arrowhead=\"none\"";
00260                 if (dynamic_cast<core::componentmodel::behavior::BaseMechanicalMapping*>(obj))
00261                     *out << ",arrowtail=\"open\"";
00262                 *out << "];" << std::endl;
00263             }
00264             if (display(model2))
00265                 *out << name << " -> " << getName(model2) << " [style=\"dashed\"];" << std::endl;
00266         }
00267     }
00268 }
00269 
00270   simulation::Visitor::Result ExportDotVisitor::processNodeTopDown(GNode* node)
00271 {
00272     const char* color=NULL;
00273     if (display(node,&color))
00274     {
00275         *out << getName(node) << " [shape=hexagon,width=0.25,height=0.25,style=\"filled\"";
00276         if (color) *out << ",fillcolor=\"" << color << "\"";
00277         *out << ",label=\"";
00278         if (labelNodeClass)
00279         {
00280             std::string name = helper::gettypename(typeid(*node));
00281             std::string::size_type pos = name.find('<');
00282             if (pos != std::string::npos)
00283                 name.erase(pos);
00284             *out << name;
00285             if (labelNodeName)
00286                 *out << "\\n";
00287         }
00288         if (labelNodeName)
00289         {
00290             if (std::string(node->getName(),0,7) != "default")
00291                 *out << node->getName();
00292         }
00293         *out << "\"];" << std::endl;
00294         if (node->parent!=NULL)
00295         {
00296             *out << getName(node->parent) << " -> " << getName(node)<< " [minlen=2,style=\"bold\"];" << std::endl;
00297         }
00298     }
00299 
00300     for (GNode::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it)
00301     {
00302         this->processObject(node, *it);
00303     }
00304     
00305     return RESULT_CONTINUE;
00306 }
00307 
00308 void ExportDotVisitor::processNodeBottomUp(GNode* /*node*/)
00309 {
00310 }
00311 
00312 } // namespace tree
00313 
00314 } // namespace simulation
00315 
00316 } // namespace sofa
00317 

Generated on Sun Nov 23 04:05:47 2008 for Sofa by  doxygen 1.5.7.1