diff --git a/include/hpp/manipulation/graph/edge.hh b/include/hpp/manipulation/graph/edge.hh
index bc36ccce7f9e05f8c4779169f46f0d56c00cff5e..be27b5f8675bb91865bd133d6f9b6fa47051d25f 100644
--- a/include/hpp/manipulation/graph/edge.hh
+++ b/include/hpp/manipulation/graph/edge.hh
@@ -100,6 +100,15 @@ namespace hpp {
 	    return steeringMethod_;
 	  }
 
+          /// Get direction of the path compare to the edge
+          /// \return true is reverse
+          virtual bool direction (const core::PathPtr_t& path) const;
+
+          /// Populate a ConfigProjector with constraints required to generate
+          /// a path at the intersection of two edges.
+          virtual bool intersectionConstraint (const EdgePtr_t& other,
+              ConfigProjectorPtr_t projector) const;
+
           /// Print the object in a stream.
           virtual std::ostream& dotPrint (std::ostream& os, dot::DrawingAttributes da = dot::DrawingAttributes ()) const;
 
@@ -188,6 +197,8 @@ namespace hpp {
 	   const GraphWkPtr_t& graph, const NodeWkPtr_t& from,
 	   const NodeWkPtr_t& to);
 
+          virtual bool direction (const core::PathPtr_t& path) const;
+
           virtual bool build (core::PathPtr_t& path, ConfigurationIn_t q1, ConfigurationIn_t q2, const core::WeighedDistance& d) const;
 
           virtual bool applyConstraints (ConfigurationIn_t qoffset, ConfigurationOut_t q) const;
diff --git a/src/graph/edge.cc b/src/graph/edge.cc
index ddc519b1a6fa9a21c1f3a4283f8071e80b11f59a..cf709af8cc828b7fafee93310c5cca84fbe6bc59 100644
--- a/src/graph/edge.cc
+++ b/src/graph/edge.cc
@@ -61,6 +61,60 @@ namespace hpp {
         else return to ();
       }
 
+      bool Edge::direction (const core::PathPtr_t& path) const
+      {
+        Configuration_t q0 = path->initial (),
+                        q1 = path->end ();
+        const bool src_contains_q0 = from()->contains (q0);
+        const bool dst_contains_q0 = to  ()->contains (q0);
+        const bool src_contains_q1 = from()->contains (q1);
+        const bool dst_contains_q1 = to  ()->contains (q1);
+        assert ((src_contains_q0 && dst_contains_q1)
+             || (src_contains_q1 && dst_contains_q0));
+        /// true if reverse
+        return !dst_contains_q1;
+      }
+
+      bool WaypointEdge::direction (const core::PathPtr_t& path) const
+      {
+        Configuration_t q0 = path->initial (),
+                        q1 = path->end ();
+        const bool src_contains_q0 = waypoint_.second->contains (q0);
+        const bool dst_contains_q0 = to  ()->contains (q0);
+        const bool src_contains_q1 = waypoint_.second->contains (q1);
+        const bool dst_contains_q1 = to  ()->contains (q1);
+        assert ((src_contains_q0 && dst_contains_q1)
+             || (src_contains_q1 && dst_contains_q0));
+        /// true if reverse
+        return !dst_contains_q1;
+      }
+
+      bool Edge::intersectionConstraint (const EdgePtr_t& other,
+          ConfigProjectorPtr_t proj) const
+      {
+        GraphPtr_t g = graph_.lock ();
+        
+        g->insertNumericalConstraints (proj);
+        insertNumericalConstraints (proj);
+        node ()->insertNumericalConstraints (proj);
+
+        g->insertLockedJoints (proj);
+        insertLockedJoints (proj);
+        node ()->insertLockedJoints (proj);
+
+        if (wkPtr_.lock() == other) // No intersection to be computed.
+          return false;
+
+        bool nodeB_Eq_nodeA = (node() == other->node());
+
+        other->insertNumericalConstraints (proj);
+        if (!nodeB_Eq_nodeA) other->node()->insertNumericalConstraints (proj);
+        other->insertLockedJoints (proj);
+        if (!nodeB_Eq_nodeA) other->node()->insertLockedJoints (proj);
+
+        return true;
+      }
+
       EdgePtr_t Edge::create (const std::string& name,
 			      const core::SteeringMethodPtr_t& steeringMethod,
 			      const GraphWkPtr_t& graph,
diff --git a/src/path-optimization/config-optimization.cc b/src/path-optimization/config-optimization.cc
index f93149d93adf9e07260c8f61a2a15f19c8e067bf..74f026602c5e1926d2058dc3c2aa5fc6181df90e 100644
--- a/src/path-optimization/config-optimization.cc
+++ b/src/path-optimization/config-optimization.cc
@@ -37,23 +37,13 @@ namespace hpp {
           HPP_STATIC_PTR_CAST (ConstraintSet, after->constraints ());
         assert (setA->edge () && setB->edge());
         graph::GraphPtr_t graph = setA->edge()->parentGraph ();
-        graph::NodePtr_t n0 = graph->getNode (before->initial ()),
-                         n1 = graph->getNode (before->end ()),
-                         n2 = graph->getNode (after->initial ()),
-                         n3 = graph->getNode (after->end ());
         /// Find if path were computed from init or goal config
         /// There is a nasty case: when build a path fails partially, then you
         /// end up where the edge->to() do not correspond to the node of
         /// path->end(). In that case, path->end () should be in edge->node().
         /// (obviously, in this case, we have edge->isInNodeFrom_ = true)
-        assert ((n0 == setB->edge()->from () && n1 == setB->edge()->to ())
-                || (n1 == setB->edge()->from () && n0 == setB->edge()->to ()));
-        assert ((n2 == setA->edge()->from () && n3 == setA->edge()->to ())
-                || (n3 == setA->edge()->from () && n2 == setA->edge()->to ()));
-        bool reverseB = (n0 != n1) &&
-          (n1 == setB->edge()->from () && n0 == setB->edge()->to ());
-        bool reverseA = (n2 != n3) &&
-          (n3 == setA->edge()->from () && n2 == setA->edge()->to ());
+        const bool reverseB = setB->edge ()->direction(before);
+        const bool reverseA = setA->edge ()->direction(after);
 
         reverse = reverseB;
 
@@ -61,25 +51,7 @@ namespace hpp {
             "intersect_" + setB->edge()->name() + "_" + setA->edge()->name(),
             graph->errorThreshold (), graph->maxIterations ());
 
-        graph->insertNumericalConstraints (p);
-        // TODO: Is reverse case different ?
-        bool nodeB_Eq_nodeA = (setB->edge()->node() == setA->edge()->node());
-
-        setB->edge()->insertNumericalConstraints (p);
-        setB->edge()->node ()->insertNumericalConstraints (p);
-
-        graph->insertLockedJoints (p);
-        setB->edge()->insertLockedJoints (p);
-        setB->edge()->node ()->insertLockedJoints (p);
-
-        vector_t rhsB = p->rightHandSideFromConfig (before->initial ());
-
-        setA->edge()->insertNumericalConstraints (p);
-        if (!nodeB_Eq_nodeA)
-          setA->edge()->node()->insertNumericalConstraints (p);
-        setA->edge()->insertLockedJoints (p);
-        if (!nodeB_Eq_nodeA)
-          setA->edge()->node()->insertLockedJoints (p);
+        setB->edge()->intersectionConstraint (setA->edge (), p);
 
         p->rightHandSideFromConfig (before->end ());
         return p;