# HG changeset patch
# User gyorokp
# Date 1269772785 -7200
# Node ID c8e6952a00ebefcb7d775719f45101faebf81ea4
# Parent  7ac85249925613d89547bccc26e977084be69e59
Added tests for split(Node) and contract(Edge) (#363)

diff -r 7ac852499256 -r c8e6952a00eb lemon/planar_graph.h
--- a/lemon/planar_graph.h	Sun Mar 28 10:40:34 2010 +0200
+++ b/lemon/planar_graph.h	Sun Mar 28 12:39:45 2010 +0200
@@ -847,7 +847,7 @@
       }
       int fr = arcs[a.id | 1].left_face;
       if ((faces[fr].first_arc | 1) == a.id | 1) {
-        Arc b = a;
+        Arc b(a.id | 1);
         turnRightF(b);
         faces[fr].first_arc = b.id;
       }
@@ -1711,6 +1711,9 @@
     /// its incident edges, they are joined to the other node.
     /// \c e will be deleted.
     ///
+    /// The deleted node is v(e) unless the degree of v(e) is higher than 1 and
+    /// the degree of u(e) is 1, in which case u(e) is deleted.
+    ///
     /// \note All edge and arc iterators whose base node is
     /// the deleted one are invalidated.
     /// Moreover all iterators referencing the removed node or
@@ -1723,6 +1726,7 @@
     void contract(Edge e) {
       Node n1 = u(e);
       Node n2 = v(e);
+      if (n1 == n2) return;
       Node nd;
       bool simple;
       inner_contract1(n1,n2,nd,simple);
diff -r 7ac852499256 -r c8e6952a00eb test/planar_graph_test.cc
--- a/test/planar_graph_test.cc	Sun Mar 28 10:40:34 2010 +0200
+++ b/test/planar_graph_test.cc	Sun Mar 28 12:39:45 2010 +0200
@@ -131,6 +131,106 @@
 }
 
 template <class Graph>
+void checkGraphNodeSplit() {
+  TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+    Graph G;
+    Node n0 = G.addNode(),
+         n1 = G.addNode(),
+         n2 = G.addNode(),
+         n3 = G.addNode(),
+         n4 = G.addNode();
+    Edge a0 = G.addEdge(n4,n3,INVALID,INVALID),
+         a1 = G.addEdge(n4,n0,a0,INVALID),
+         a2 = G.addEdge(n1,n4,INVALID,a1),
+         a3 = G.addEdge(n4,n2,a2,INVALID),
+         a4 = G.addEdge(n2,n3,a3,a0);
+
+    checkGraphNodeList(G, 5);
+    checkGraphEdgeList(G, 5);
+    checkGraphArcList(G, 10);
+    checkGraphFaceList(G, 2);
+
+    checkGraphIncEdgeArcLists(G, n0, 1);
+    checkGraphIncEdgeArcLists(G, n1, 1);
+    checkGraphIncEdgeArcLists(G, n2, 2);
+    checkGraphIncEdgeArcLists(G, n3, 2);
+    checkGraphIncEdgeArcLists(G, n4, 4);
+
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a0,false)), 3);
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a0,true)), 7);
+
+    Node n5 = G.split(n4,a3,a1,true);
+
+    checkGraphNodeList(G, 6);
+    checkGraphEdgeList(G, 6);
+    checkGraphArcList(G, 12);
+    checkGraphFaceList(G, 2);
+
+    checkGraphIncEdgeArcLists(G, n0, 1);
+    checkGraphIncEdgeArcLists(G, n1, 1);
+    checkGraphIncEdgeArcLists(G, n2, 2);
+    checkGraphIncEdgeArcLists(G, n3, 2);
+    checkGraphIncEdgeArcLists(G, n4, 3);
+    checkGraphIncEdgeArcLists(G, n5, 3);
+
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a0,false)), 3);
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a0,true)), 9);
+}
+
+template <class Graph>
+void checkGraphContract() {
+  TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+    Graph G;
+    Node n0 = G.addNode(),
+         n1 = G.addNode(),
+         n2 = G.addNode(),
+         n3 = G.addNode();
+    Edge a0 = G.addEdge(n0,n1,INVALID,INVALID),
+         a1 = G.addEdge(n0,n1,a0,a0),
+         a2 = G.addEdge(n0,n1,a1,a0),
+         a3 = G.addEdge(n0,n2,a1,INVALID),
+         a4 = G.addEdge(n0,n3,a3,INVALID),
+         a5 = G.addEdge(n2,n1,a3,a2),
+         a6 = G.addEdge(n3,n1,a4,a2);
+
+    checkGraphNodeList(G, 4);
+    checkGraphEdgeList(G, 7);
+    checkGraphArcList(G, 14);
+    checkGraphFaceList(G, 5);
+
+    checkGraphIncEdgeArcLists(G, n0, 5);
+    checkGraphIncEdgeArcLists(G, n1, 5);
+    checkGraphIncEdgeArcLists(G, n2, 2);
+    checkGraphIncEdgeArcLists(G, n3, 2);
+
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a0,false)), 2);
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a0,true)), 2);
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a1,true)), 3);
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a2,false)), 3);
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a3,true)), 4);
+
+    G.contract(a0);
+
+    checkGraphNodeList(G, 3);
+    checkGraphEdgeList(G, 6);
+    checkGraphArcList(G, 12);
+    checkGraphFaceList(G, 5);
+
+    checkGraphIncEdgeArcLists(G, n0, 8);
+    checkGraphIncEdgeArcLists(G, n2, 2);
+    checkGraphIncEdgeArcLists(G, n3, 2);
+
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a1,false)), 1);
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a2,true)), 1);
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a1,true)), 3);
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a2,false)), 3);
+    checkGraphBoundaryArcList(G, G.leftFace(G.direct(a3,true)), 4);
+
+}
+
+template <class Graph>
 void checkGraphErase() {
   TEMPLATE_GRAPH_TYPEDEFS(Graph);
 
@@ -320,6 +420,8 @@
   { // Checking PlanarGraph
     checkGraphBuild<PlanarGraph>();
     checkGraphArcSplit<PlanarGraph>();
+    checkGraphNodeSplit<PlanarGraph>();
+    checkGraphContract<PlanarGraph>();
     checkGraphErase<PlanarGraph>();
     checkGraphSnapshot<PlanarGraph>();
     checkGraphValidityErase<PlanarGraph>();
