00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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* , core::objectmodel::BaseObject* obj)
00205 {
00206
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* )
00309 {
00310 }
00311
00312 }
00313
00314 }
00315
00316 }
00317