diff --git a/CMakeLists.txt b/CMakeLists.txt
index cea373bcdff689623b3d950763b029e95a1acb13..dc4b724f519fe0ab86b6862de0be077852292fd9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -66,6 +66,7 @@ SET (${PROJECT_NAME}_HEADERS
   include/hpp/manipulation/graph/statistics.hh
   include/hpp/manipulation/graph/graph-component.hh
   include/hpp/manipulation/graph/fwd.hh
+  include/hpp/manipulation/graph/dot.hh
   )
 
 # Add dependency toward hpp-model library in pkg-config file.
diff --git a/include/hpp/manipulation/graph/dot.hh b/include/hpp/manipulation/graph/dot.hh
new file mode 100644
index 0000000000000000000000000000000000000000..ecf503c93e12f0048bc3d8e846179574ca0f3453
--- /dev/null
+++ b/include/hpp/manipulation/graph/dot.hh
@@ -0,0 +1,51 @@
+// Copyright (c) 2014, LAAS-CNRS
+// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
+//
+// This file is part of hpp-manipulation.
+// hpp-manipulation is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// hpp-manipulation is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.  You should have
+// received a copy of the GNU Lesser General Public License along with
+// hpp-manipulation. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HPP_MANIPULATION_GRAPH_DOT_HH
+# define HPP_MANIPULATION_GRAPH_DOT_HH
+
+# include <ostream>
+# include <map>
+
+namespace hpp {
+  namespace manipulation {
+    namespace graph {
+      namespace dot {
+        struct DrawingAttributes {
+          typedef std::pair <std::string, std::string> Pair;
+          typedef std::map <std::string, std::string> Map;
+          Map attr;
+
+          inline void insertWithQuote (const std::string& K, const std::string& V) {
+            attr.insert (Pair (K, "\"" + V + "\""));
+          }
+          inline void insert (const std::string& K, const std::string& V) {
+            attr.insert (Pair (K, V));
+          }
+          std::string& operator [] (const std::string& K) {
+            return attr [K];
+          }
+        };
+
+        std::ostream& insertComments (std::ostream& os, const std::string& c);
+
+        std::ostream& operator<< (std::ostream& os, const DrawingAttributes& da);
+      } // namespace dot
+    } // namespace graph
+  } // namespace manipulation
+} // namespace hpp
+
+#endif // HPP_MANIPULATION_GRAPH_DOT_HH
diff --git a/include/hpp/manipulation/graph/edge.hh b/include/hpp/manipulation/graph/edge.hh
index 65ce4e2c472113f045eb80580804ae80705c2f06..351f74213d1fd0f8328b34f6511cfc9f6eef41d3 100644
--- a/include/hpp/manipulation/graph/edge.hh
+++ b/include/hpp/manipulation/graph/edge.hh
@@ -88,7 +88,7 @@ namespace hpp {
           }
 
           /// Print the object in a stream.
-          virtual std::ostream& dotPrint (std::ostream& os) const;
+          virtual std::ostream& dotPrint (std::ostream& os, dot::DrawingAttributes da = dot::DrawingAttributes ()) const;
 
         protected:
           /// Initialization of the object.
@@ -169,7 +169,7 @@ namespace hpp {
           boost::shared_ptr <EdgeType> waypoint () const;
 
           /// Print the object in a stream.
-          virtual std::ostream& dotPrint (std::ostream& os) const;
+          virtual std::ostream& dotPrint (std::ostream& os, dot::DrawingAttributes da = dot::DrawingAttributes ()) const;
 
           /// Create inner waypoints.
           /// \param depth the number of waypoints between from() and to()
@@ -219,7 +219,7 @@ namespace hpp {
           void insertConfigConstraint (const LockedDofPtr_t lockedDof);
 
           /// Print the object in a stream.
-          virtual std::ostream& dotPrint (std::ostream& os) const;
+          virtual std::ostream& dotPrint (std::ostream& os, dot::DrawingAttributes da = dot::DrawingAttributes ()) const;
 
         protected:
           /// Initialization of the object.
diff --git a/include/hpp/manipulation/graph/graph-component.hh b/include/hpp/manipulation/graph/graph-component.hh
index 1644fe43dd4f4459f3b68d891378be760c8280bf..74f66eeb82f865a3edacfb5d1d372a6ddaab830c 100644
--- a/include/hpp/manipulation/graph/graph-component.hh
+++ b/include/hpp/manipulation/graph/graph-component.hh
@@ -24,6 +24,7 @@
 # include "hpp/manipulation/config.hh"
 # include "hpp/manipulation/fwd.hh"
 # include "hpp/manipulation/graph/fwd.hh"
+# include "hpp/manipulation/graph/dot.hh"
 
 namespace hpp {
   namespace manipulation {
@@ -74,7 +75,7 @@ namespace hpp {
           void parentGraph(const GraphWkPtr_t& parent);
 
           /// Print the component in DOT language.
-          virtual std::ostream& dotPrint (std::ostream& os) const;
+          virtual std::ostream& dotPrint (std::ostream& os, dot::DrawingAttributes da = dot::DrawingAttributes ()) const;
 
         protected:
           /// Initialize the component
diff --git a/include/hpp/manipulation/graph/graph.hh b/include/hpp/manipulation/graph/graph.hh
index 55e7f761ec07f0d1707780e798e10ef032a7dce7..77050d1b692f41259677b17fa81090765bee46e3 100644
--- a/include/hpp/manipulation/graph/graph.hh
+++ b/include/hpp/manipulation/graph/graph.hh
@@ -84,7 +84,7 @@ namespace hpp {
           const RobotPtr_t& robot () const;
 
           /// Print the component in DOT language.
-          virtual std::ostream& dotPrint (std::ostream& os) const;
+          virtual std::ostream& dotPrint (std::ostream& os, dot::DrawingAttributes da = dot::DrawingAttributes ()) const;
 
         protected:
           /// Initialization of the object.
diff --git a/include/hpp/manipulation/graph/node-selector.hh b/include/hpp/manipulation/graph/node-selector.hh
index 875b99fc5d8ce5b4072d6c5c4b5d64d416bd8586..de0e0cf2ca4b731712ba69d90a541887d020034c 100644
--- a/include/hpp/manipulation/graph/node-selector.hh
+++ b/include/hpp/manipulation/graph/node-selector.hh
@@ -55,7 +55,7 @@ namespace hpp {
           }
 
           /// Print the object in a stream.
-          std::ostream& dotPrint (std::ostream& os) const;
+          std::ostream& dotPrint (std::ostream& os, dot::DrawingAttributes da = dot::DrawingAttributes ()) const;
 
         protected:
           /// Initialization of the object.
diff --git a/include/hpp/manipulation/graph/node.hh b/include/hpp/manipulation/graph/node.hh
index 15c83e87aae6e30ac28cf8fc940f4f0a4db7dc03..6dde6d6285416b42f47b569b3dfdf77edc02a4da 100644
--- a/include/hpp/manipulation/graph/node.hh
+++ b/include/hpp/manipulation/graph/node.hh
@@ -111,7 +111,7 @@ namespace hpp {
           }
 
           /// Print the object in a stream.
-          std::ostream& dotPrint (std::ostream& os) const;
+          std::ostream& dotPrint (std::ostream& os, dot::DrawingAttributes da = dot::DrawingAttributes ()) const;
 
         protected:
           /// Initialize the object.
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f1cff328e0bf0547c93a1be40a15be3da0a8f076..3073519ccdb3e474d0606410f935a304c20b8ec5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -35,6 +35,8 @@ ADD_LIBRARY(${LIBRARY_NAME} SHARED
   graph/graph-component.cc
   graph/node-selector.cc
   graph/statistics.cc
+
+  graph/dot.cc
 )
 
 PKG_CONFIG_USE_DEPENDENCY(${LIBRARY_NAME} hpp-core)
diff --git a/src/graph/dot.cc b/src/graph/dot.cc
new file mode 100644
index 0000000000000000000000000000000000000000..dfe592ccef38fda4d8453fb8e0d27123c99fcb21
--- /dev/null
+++ b/src/graph/dot.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2014, LAAS-CNRS
+// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
+//
+// This file is part of hpp-manipulation.
+// hpp-manipulation is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// hpp-manipulation is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.  You should have
+// received a copy of the GNU Lesser General Public License along with
+// hpp-manipulation. If not, see <http://www.gnu.org/licenses/>.
+
+#include "hpp/manipulation/graph/dot.hh"
+
+namespace hpp {
+  namespace manipulation {
+    namespace graph {
+      namespace dot {
+        std::ostream& operator<< (std::ostream& os, const DrawingAttributes& da)
+        {
+          if (da.attr.empty ()) return os;
+          os << "[";
+          size_t i = da.attr.size ();
+          for (DrawingAttributes::Map::const_iterator it = da.attr.begin ();
+              it != da.attr.end (); ++it) {
+            os << it->first << "=" << it->second; 
+            i--;
+            if (i > 0) os << ", ";
+          }
+          return os << "]";
+        }
+
+        std::ostream& insertComments (std::ostream& os, const std::string& c)
+        {
+          return os << "/*" << std::endl << c << std::endl << "*/";
+        }
+      } // namespace dot
+    } // namespace graph
+  } // namespace manipulation
+} // namespace hpp
diff --git a/src/graph/edge.cc b/src/graph/edge.cc
index feb5d8a613dce4fedcc691ac7941357f176bd4c7..d099b92119f9b1359c53edbc58862273fdaa16e0 100644
--- a/src/graph/edge.cc
+++ b/src/graph/edge.cc
@@ -82,9 +82,11 @@ namespace hpp {
         return os;
       }
 
-      std::ostream& Edge::dotPrint (std::ostream& os) const
+      std::ostream& Edge::dotPrint (std::ostream& os, dot::DrawingAttributes da) const
       {
-        os << from()->id () << " -> " << to()->id () << " [shape=onormal,label=\"" << name () << "\"];";
+        da.insertWithQuote ("label", name ());
+        da.insert ("shape", "onormal");
+        os << from()->id () << " -> " << to()->id () << " " << da << ";";
         return os;
       }
 
@@ -277,9 +279,19 @@ namespace hpp {
         return os;
       }
 
-      std::ostream& WaypointEdge::dotPrint (std::ostream& os) const
+      std::ostream& WaypointEdge::dotPrint (std::ostream& os, dot::DrawingAttributes da) const
       {
-        os << from()->id () << " -> " << to()->id () << " [shape=onormal,label=\"" << name () << "\"];";
+        // First print the waypoint node, then the first edge.
+        da ["style"]="dashed";
+        waypoint_.second->dotPrint (os, da);
+        da ["style"]="solid";
+        waypoint_.first->dotPrint (os, da) << std::endl;
+        da ["style"]="dotted";
+        da ["dir"] = "both";
+        da ["arrowtail"]="dot";
+        da.insert ("shape", "onormal");
+        da.insertWithQuote ("label", name());
+        os << waypoint_.second->id () << " -> " << to()->id () << " " << da << ";";
         return os;
       }
 
@@ -291,10 +303,11 @@ namespace hpp {
         return os;
       }
 
-      std::ostream& LevelSetEdge::dotPrint (std::ostream& os) const
+      std::ostream& LevelSetEdge::dotPrint (std::ostream& os, dot::DrawingAttributes da) const
       {
-        os << from()->id () << " -> " << to()->id () << " [shape=onormal,label=\"" << name () << "\"];";
-        return os;
+        da.insert ("shape", "onormal");
+        da.insert ("style", "dashed");
+        return Edge::dotPrint (os, da);
       }
 
       bool LevelSetEdge::applyConstraints (ConfigurationIn_t, ConfigurationOut_t) const
diff --git a/src/graph/graph-component.cc b/src/graph/graph-component.cc
index e7b6f36dfd526761b4ffad405edb09c236b823ca..acc48779274cd18ba206ccdc206a04481ece386d 100644
--- a/src/graph/graph-component.cc
+++ b/src/graph/graph-component.cc
@@ -55,7 +55,7 @@ namespace hpp {
         return os;
       }
 
-      std::ostream& GraphComponent::dotPrint (std::ostream& os) const
+      std::ostream& GraphComponent::dotPrint (std::ostream& os, dot::DrawingAttributes) const
       {
         os << id ();
         return os;
diff --git a/src/graph/graph.cc b/src/graph/graph.cc
index 5f42a22f21e2d01c65c84bfd4f28ad079b32d8e5..e455cd9726ba6bd69f7d5631f2cb205d2468d407 100644
--- a/src/graph/graph.cc
+++ b/src/graph/graph.cc
@@ -108,9 +108,9 @@ namespace hpp {
         return edge->pathConstraint ();
       }
 
-      std::ostream& Graph::dotPrint (std::ostream& os) const
+      std::ostream& Graph::dotPrint (std::ostream& os, dot::DrawingAttributes da) const
       {
-        os << "digraph " << id() << " {" << std::endl;
+        os << "digraph " << id() << " " << da << " {" << std::endl;
         nodeSelector_->dotPrint (os);
         os << "}" << std::endl;
         return os;
diff --git a/src/graph/node-selector.cc b/src/graph/node-selector.cc
index 2b7e15e29d87e9a4ae36d5d44cd50c35d6e36fb4..418f470842f9b9f14cd7356d9bde83d16c9f755d 100644
--- a/src/graph/node-selector.cc
+++ b/src/graph/node-selector.cc
@@ -59,7 +59,7 @@ namespace hpp {
         return neighborPicker ();
       }
 
-      std::ostream& NodeSelector::dotPrint (std::ostream& os) const
+      std::ostream& NodeSelector::dotPrint (std::ostream& os, dot::DrawingAttributes) const
       {
         for (Nodes_t::const_iterator it = orderedStates_.begin();
             orderedStates_.end() != it; ++it)
diff --git a/src/graph/node.cc b/src/graph/node.cc
index 24b3b6217c9c7ba450a37424b15953089c7dfbae..b7e30bf25460a628ebebf383472d012d76bfdc69 100644
--- a/src/graph/node.cc
+++ b/src/graph/node.cc
@@ -58,12 +58,22 @@ namespace hpp {
         return configConstraint()->isSatisfied (config);
       }
 
-      std::ostream& Node::dotPrint (std::ostream& os) const
+      std::ostream& Node::dotPrint (std::ostream& os, dot::DrawingAttributes da) const
       {
-        os << id () << " [label=\"" << name () << "\"];" << std::endl;
+        da.insertWithQuote ("label", name ());
+        da.insert ("style","filled");
+        os << id () << " " << da << ";" << std::endl;
+
+        dot::DrawingAttributes dac;
+        std::vector <double> p = neighbors_.probabilities ();
+        size_t i = 0;
         for (Neighbors_t::const_iterator it = neighbors_.begin();
-            it != neighbors_.end(); ++it)
-          it->second->dotPrint (os) << std::endl;
+            it != neighbors_.end(); ++it) {
+          std::ostringstream oss; oss << (p[i] * 3 + 0.5);
+          dac ["penwidth"] = oss.str ();
+          i++;
+          it->second->dotPrint (os, dac) << std::endl;
+        }
         return os;
       }