# HG changeset patch
# User gyorokp
# Date 1269193312 -3600
# Node ID 941e63d323f17b503f4d85fc5ec8a9c476672e8a
# Parent  ab0782f0c79f5dcc1418a27fa9b0b1c5255ba21c
Fixed notifier use / added face notifier

diff -r ab0782f0c79f -r 941e63d323f1 lemon/planar_graph.h
--- a/lemon/planar_graph.h	Sun Mar 21 11:27:36 2010 +0100
+++ b/lemon/planar_graph.h	Sun Mar 21 18:41:52 2010 +0100
@@ -220,6 +220,9 @@
     Face rightFace(Arc e) const {
       return Face(arcs[e.id ^ 1].left_face);
     }
+    Face outerFace(Node n) const {
+      return Face(nodes[n.id].outer_face);
+    }
 
     Node u(Edge e) const {
       return Node(arcs[2 * e.id].target);
@@ -571,7 +574,6 @@
         ++components[ca].num_nodes;
         eraseComponent(cb);
         erase(Face(nodes[v.id].outer_face));
-        nodes[v.id].outer_face = -1;
       } else if (p_v.id > -1) {
         arcs[n].left_face = arcs[n | 1].left_face = arcs[p_v.id].left_face;
         faces[arcs[n].left_face].first_arc = n | 1;
@@ -579,7 +581,6 @@
         eraseComponent(ca);
         nodes[u.id].component = nodes[v.id].component;
         erase(Face(nodes[u.id].outer_face));
-        nodes[u.id].outer_face = -1;
       } else {    //both prevs are INVALID
         Face f(nodes[u.id].outer_face);
         arcs[n].left_face = arcs[n | 1].left_face = f.id;
@@ -590,6 +591,7 @@
         erase(Face(nodes[v.id].outer_face));
       }
 
+      nodes[u.id].outer_face = nodes[v.id].outer_face = -1;
       return Edge(n / 2);
     }
 
@@ -680,135 +682,28 @@
     }
 
     Node split(Edge e) {
-      Node v = Node(link_node());
-      Arc a(e.id*2);
-      int b = link_edge();
-
-      nodes[v.id].component = nodes[arcs[a.id].target].component;
-      ++components[nodes[v.id].component].num_nodes;
-      nodes[v.id].first_out = a.id;
-      nodes[v.id].last_out = b | 1;
-
-      arcs[b] = arcs[a.id];
-      arcs[b].target = v.id;
-      if (arcs[a.id].next_out > -1)
-        arcs[arcs[a.id].next_out].prev_out = b;
-      else
-        nodes[arcs[a.id | 1].target].last_out = b;
-      if (arcs[a.id].prev_out > -1)
-        arcs[arcs[a.id].prev_out].next_out = b;
-      else
-        nodes[arcs[a.id | 1].target].first_out = b;
-
-      arcs[b | 1] = arcs[a.id | 1];
-      arcs[b | 1].next_out = -1;
-      arcs[b | 1].prev_out = a.id;
-
-      arcs[a.id].next_out = b | 1;
-      arcs[a.id].prev_out = -1;
-      arcs[a.id | 1].target = v.id;
-
-
-      return v;
+      Node v;
+      Edge e2;
+      inner_split1(v,e2);
+      return inner_split2(e,v,e2);
     }
 
     Node split(Node n1, Edge e1, Edge e2, bool b) {
-      Node n2 = Node(link_node());
-      Edge e3;
-      if (nodes[n1.id].first_out == -1) {
-        if (b) e3 = addEdge(n1,n2,INVALID,INVALID);
-        return n2;
-      }
-      arcs[nodes[n1.id].first_out].prev_out = nodes[n1.id].last_out;
-      arcs[nodes[n1.id].last_out].next_out = nodes[n1.id].first_out;
-      nodes[n2.id].component = nodes[n1.id].component;
-      ++components[nodes[n2.id].component].num_nodes;
-      Arc a1(e1.id*2);
-      if (arcs[a1.id].target != n1.id) a1.id |= 1;
-      Arc a2(e2.id*2);
-      if (arcs[a2.id].target != n1.id) a2.id |= 1;
-      Arc a3(link_edge());
-      arcs[a3.id].target = n1.id;
-      arcs[a3.id | 1].target = n2.id;
-      arcs[a3.id].left_face = arcs[a1.id].left_face;
-      arcs[a3.id | 1].left_face = arcs[a2.id].left_face;
-
-      arcs[a3.id].prev_out = arcs[a2.id ^ 1].prev_out;
-      arcs[arcs[a2.id ^ 1].prev_out].next_out = a3.id;
-      arcs[a3.id | 1].prev_out = arcs[a1.id ^ 1].prev_out;
-      arcs[arcs[a1.id ^ 1].prev_out].next_out = a3.id | 1;
-      nodes[n1.id].first_out = a2.id ^ 1;
-      arcs[a1.id ^ 1].prev_out = -1;
-      nodes[n1.id].last_out = a3.id | 1;
-      arcs[a3.id | 1].next_out = -1;
-      nodes[n2.id].first_out = a1.id ^ 1;
-      arcs[a2.id ^ 1].prev_out = -1;
-      nodes[n2.id].last_out = a3.id;
-      arcs[a3.id].next_out = -1;
-
-      Arc a4(a1.id);
-      while (a4.id != (a3.id | 1)) {
-        arcs[a4.id].target = n2.id;
-        a4.id = arcs[a4.id ^ 1].next_out ^ 1;
-      }
-
-      if (!b) erase(a3);
+      Node n2;
+      inner_split1(n1,n2);
+      Edge a3;
+      inner_split2(n1,n2,e1,e2,b,a3);
+      if (!b && a3 != INVALID) erase(a3);
       return n2;
     }
 
     void contract(Edge e) {
       Node n1 = u(e);
       Node n2 = v(e);
-      if (nodes[n1.id].first_out == nodes[n1.id].last_out) {
-        erase(e);
-        erase(n1);
-        return;
-      }
-      if (nodes[n2.id].first_out == nodes[n2.id].last_out) {
-        erase(e);
-        erase(n2);
-        return;
-      }
-      Arc a(e.id*2);
-      int fl = arcs[a.id].left_face;
-      if ((faces[fl].first_arc | 1) == a.id | 1) {
-        Arc b = a;
-        turnRightF(b);
-        faces[fl].first_arc = b.id;
-      }
-      int fr = arcs[a.id | 1].left_face;
-      if ((faces[fr].first_arc | 1) == a.id | 1) {
-        Arc b = a;
-        turnRightF(b);
-        faces[fr].first_arc = b.id;
-      }
-      Arc b = a;
-      turnLeft(b);
-      while (b != a) {
-        arcs[b.id ^ 1].target = n1.id;
-        if (arcs[b.id].next_out > -1)
-          b.id = arcs[b.id].next_out;
-        else
-          b.id = nodes[n2.id].first_out;
-      }
-      arcs[nodes[n2.id].last_out].next_out = nodes[n2.id].first_out;
-      arcs[nodes[n2.id].first_out].prev_out = nodes[n2.id].last_out;
-      if (arcs[a.id | 1].prev_out > -1) {
-        arcs[arcs[a.id | 1].prev_out].next_out = arcs[a.id].next_out;
-      } else {
-        nodes[n1.id].first_out = arcs[a.id].next_out;
-      }
-      arcs[arcs[a.id].next_out].prev_out = arcs[a.id | 1].prev_out;
-      if (arcs[a.id | 1].next_out > -1) {
-        arcs[arcs[a.id | 1].next_out].prev_out = arcs[a.id].prev_out;
-      } else {
-        nodes[n1.id].last_out = arcs[a.id].prev_out;
-      }
-      arcs[arcs[a.id].prev_out].next_out = arcs[a.id | 1].next_out;
-
-      unlink_edge(e);
-      --components[nodes[n2.id].component].num_nodes;
-      unlink_node(n2.id);
+      Node nd;
+      bool simple;
+      inner_contract1(n1,n2,nd,simple);
+      inner_contract2(e,n1,n2,nd,simple);
     }
 
   protected:
@@ -880,6 +775,151 @@
       arcs[n | 1].prev_out = -2;
     }
 
+    //Primitives of split(Edge)
+    void inner_split1(Node &v, Edge &e2) {
+      v = Node(link_node());
+      e2 = Arc(link_edge());
+    }
+
+    Node inner_split2(Edge e, Node v, Edge e2) {
+      Arc a(e.id*2);
+      int b = e2.id*2;
+      nodes[v.id].component = nodes[arcs[a.id].target].component;
+      ++components[nodes[v.id].component].num_nodes;
+      nodes[v.id].first_out = a.id;
+      nodes[v.id].last_out = b | 1;
+
+      arcs[b] = arcs[a.id];
+      arcs[b].target = v.id;
+      if (arcs[a.id].next_out > -1)
+        arcs[arcs[a.id].next_out].prev_out = b;
+      else
+        nodes[arcs[a.id | 1].target].last_out = b;
+      if (arcs[a.id].prev_out > -1)
+        arcs[arcs[a.id].prev_out].next_out = b;
+      else
+        nodes[arcs[a.id | 1].target].first_out = b;
+
+      arcs[b | 1] = arcs[a.id | 1];
+      arcs[b | 1].next_out = -1;
+      arcs[b | 1].prev_out = a.id;
+
+      arcs[a.id].next_out = b | 1;
+      arcs[a.id].prev_out = -1;
+      arcs[a.id | 1].target = v.id;
+
+      return v;
+    }
+
+    //Primitives of contract(Edge)
+    void inner_contract1(Node n1, Node n2, Node &to_delete, bool &simple) {
+      if (nodes[n1.id].first_out == nodes[n1.id].last_out) {
+        simple = true;
+        to_delete = n1;
+      } else if (nodes[n2.id].first_out == nodes[n2.id].last_out) {
+        simple = true;
+        to_delete = n2;
+      } else {
+        simple = false;
+        to_delete = n2;
+      }
+    }
+
+    void inner_contract2(Edge e, Node n1, Node n2, Node &to_delete, bool
+      &simple) {
+      if (simple) {
+        erase(e);
+        erase(to_delete);
+        return;
+      }
+      Arc a(e.id*2);
+      int fl = arcs[a.id].left_face;
+      if ((faces[fl].first_arc | 1) == a.id | 1) {
+        Arc b = a;
+        turnRightF(b);
+        faces[fl].first_arc = b.id;
+      }
+      int fr = arcs[a.id | 1].left_face;
+      if ((faces[fr].first_arc | 1) == a.id | 1) {
+        Arc b = a;
+        turnRightF(b);
+        faces[fr].first_arc = b.id;
+      }
+      Arc b = a;
+      turnLeft(b);
+      while (b != a) {
+        arcs[b.id ^ 1].target = n1.id;
+        if (arcs[b.id].next_out > -1)
+          b.id = arcs[b.id].next_out;
+        else
+          b.id = nodes[n2.id].first_out;
+      }
+      arcs[nodes[n2.id].last_out].next_out = nodes[n2.id].first_out;
+      arcs[nodes[n2.id].first_out].prev_out = nodes[n2.id].last_out;
+      if (arcs[a.id | 1].prev_out > -1) {
+        arcs[arcs[a.id | 1].prev_out].next_out = arcs[a.id].next_out;
+      } else {
+        nodes[n1.id].first_out = arcs[a.id].next_out;
+      }
+      arcs[arcs[a.id].next_out].prev_out = arcs[a.id | 1].prev_out;
+      if (arcs[a.id | 1].next_out > -1) {
+        arcs[arcs[a.id | 1].next_out].prev_out = arcs[a.id].prev_out;
+      } else {
+        nodes[n1.id].last_out = arcs[a.id].prev_out;
+      }
+      arcs[arcs[a.id].prev_out].next_out = arcs[a.id | 1].next_out;
+
+      unlink_edge(e);
+      --components[nodes[n2.id].component].num_nodes;
+      unlink_node(n2.id);
+    }
+
+    //Primitives of split(Node)
+    void inner_split1(Node n1, Node &n2) {
+      n2 = Node(link_node());
+    }
+
+    void inner_split2(Node n1, Node n2, Edge e1, Edge e2, bool b, Edge &e3) {
+      e3 = INVALID;
+      if (nodes[n1.id].first_out == -1) {
+        if (b) e3 = addEdge(n1,n2,INVALID,INVALID);
+        return;
+      }
+      arcs[nodes[n1.id].first_out].prev_out = nodes[n1.id].last_out;
+      arcs[nodes[n1.id].last_out].next_out = nodes[n1.id].first_out;
+      nodes[n2.id].component = nodes[n1.id].component;
+      ++components[nodes[n2.id].component].num_nodes;
+      Arc a1(e1.id*2);
+      if (arcs[a1.id].target != n1.id) a1.id |= 1;
+      Arc a2(e2.id*2);
+      if (arcs[a2.id].target != n1.id) a2.id |= 1;
+      Arc a3(link_edge());
+      e3 = a3;
+      arcs[a3.id].target = n1.id;
+      arcs[a3.id | 1].target = n2.id;
+      arcs[a3.id].left_face = arcs[a1.id].left_face;
+      arcs[a3.id | 1].left_face = arcs[a2.id].left_face;
+
+      arcs[a3.id].prev_out = arcs[a2.id ^ 1].prev_out;
+      arcs[arcs[a2.id ^ 1].prev_out].next_out = a3.id;
+      arcs[a3.id | 1].prev_out = arcs[a1.id ^ 1].prev_out;
+      arcs[arcs[a1.id ^ 1].prev_out].next_out = a3.id | 1;
+      nodes[n1.id].first_out = a2.id ^ 1;
+      arcs[a1.id ^ 1].prev_out = -1;
+      nodes[n1.id].last_out = a3.id | 1;
+      arcs[a3.id | 1].next_out = -1;
+      nodes[n2.id].first_out = a1.id ^ 1;
+      arcs[a2.id ^ 1].prev_out = -1;
+      nodes[n2.id].last_out = a3.id;
+      arcs[a3.id].next_out = -1;
+
+      Arc a4(a1.id);
+      while (a4.id != (a3.id | 1)) {
+        arcs[a4.id].target = n2.id;
+        a4.id = arcs[a4.id ^ 1].next_out ^ 1;
+      }
+    }
+
     //Relabels the "wall" of a face with a new face ID.
     void wall_paint(Arc arc, int f_id, Arc ed) {
       do {
@@ -1043,6 +1083,46 @@
 
   };
 
+  template <typename GR, typename Enable = void>
+  struct FaceNotifierIndicator {
+    typedef InvalidType Type;
+  };
+  template <typename GR>
+  struct FaceNotifierIndicator<
+    GR,
+    typename enable_if<typename GR::FaceNotifier::Notifier, void>::type
+  > {
+    typedef typename GR::FaceNotifier Type;
+  };
+
+  template <typename GR>
+  class ItemSetTraits<GR, typename GR::Face> {
+  public:
+
+    typedef GR Graph;
+    typedef GR Digraph;
+
+    typedef typename GR::Face Item;
+    typedef typename GR::FaceIt ItemIt;
+
+    typedef typename FaceNotifierIndicator<GR>::Type ItemNotifier;
+
+    template <typename V>
+    class Map : public GR::template FaceMap<V> {
+      typedef typename GR::template FaceMap<V> Parent;
+
+    public:
+      typedef typename GR::template FaceMap<V> Type;
+      typedef typename Parent::Value Value;
+
+      Map(const GR& _digraph) : Parent(_digraph) {}
+      Map(const GR& _digraph, const Value& _value)
+        : Parent(_digraph, _value) {}
+
+     };
+
+  };
+
   template<typename Base>
   class PlanarGraphExtender : public Base{
 
@@ -1051,13 +1131,66 @@
   public:
     typedef PlanarGraphExtender Graph;
 
-    PlanarGraphExtender() {}
-
     typedef typename Parent::Node Node;
     typedef typename Parent::Arc Arc;
     typedef typename Parent::Edge Edge;
     typedef typename Parent::Face Face;
 
+    typedef typename Parent::NodeNotifier NodeNotifier;
+    typedef typename Parent::EdgeNotifier EdgeNotifier;
+    typedef typename Parent::ArcNotifier ArcNotifier;
+    typedef AlterationNotifier<PlanarGraphExtender, Face> FaceNotifier;
+
+  protected:
+    mutable FaceNotifier face_notifier;
+
+  public:
+
+    int maxId(Face) const {
+      return Parent::maxFaceId();
+    }
+
+    NodeNotifier& notifier(Node) const {
+      return Parent::node_notifier;
+    }
+
+    ArcNotifier& notifier(Arc) const {
+      return Parent::arc_notifier;
+    }
+
+    EdgeNotifier& notifier(Edge) const {
+      return Parent::edge_notifier;
+    }
+
+    FaceNotifier& notifier(Face) const {
+      return face_notifier;
+    }
+
+    template <typename _Value>
+    class FaceMap
+    : public MapExtender<DefaultMap<Graph, Face, _Value> > {
+      typedef MapExtender<DefaultMap<Graph, Face, _Value> > Parent;
+
+    public:
+      explicit FaceMap(const Graph& graph)
+      : Parent(graph) {}
+      FaceMap(const Graph& graph, const _Value& value)
+      : Parent(graph, value) {}
+
+    private:
+      FaceMap& operator=(const FaceMap& cmap) {
+        return operator=<FaceMap>(cmap);
+      }
+
+      template <typename CMap>
+      FaceMap& operator=(const CMap& cmap) {
+        Parent::operator=(cmap);
+        return *this;
+      }
+
+    };
+
+
   /// Iterator class for the faces.
 
   /// This iterator goes through the faces of a planar graph.
@@ -1240,6 +1373,26 @@
 
     };
 
+    void clear() {
+      notifier(Face()).clear();
+      Parent::clear();
+    }
+
+    template <typename Graph, typename NodeRefMap, typename EdgeRefMap>
+    void build(const Graph& graph, NodeRefMap& nodeRef,
+            EdgeRefMap& edgeRef) {
+      Parent::build(graph, nodeRef, edgeRef);
+      notifier(Face()).build();
+    }
+
+    PlanarGraphExtender() {
+      face_notifier.setContainer(*this);
+    }
+
+    ~PlanarGraphExtender() {
+      face_notifier.clear();
+    }
+
   };
 
   typedef PlanarGraphExtender<GraphExtender<PlanarGraphBase> >
@@ -1299,9 +1452,6 @@
       for (typename Graph::ArcIt it(g); it != INVALID; ++it) {
         am[it] = INVALID;
       }
-      for (typename Graph::ArcIt it(g); it != INVALID; ++it) {
-        am[it] = INVALID;
-      }
       for (typename Graph::NodeIt it(g); it != INVALID; ++it) {
         for (typename Graph::OutArcIt it2(g,it); it2 != INVALID; ++it2) {
           if (am[it2] == INVALID) {
@@ -1330,9 +1480,29 @@
     /// for the node.
     /// \return The new node.
     Node addNode() {
-      return Parent::addNode();
+      Node n = Parent::addNode();
+      notifier(Face()).add(outerFace(n));
+      return n;
     }
 
+  protected:
+    void edge_add_notify(Edge edge) {
+      notifier(Edge()).add(edge);
+      std::vector<Arc> ev;
+      ev.push_back(Parent::direct(edge, true));
+      ev.push_back(Parent::direct(edge, false));
+      notifier(Arc()).add(ev);
+    }
+
+    void edge_erase_notify(Edge edge) {
+      std::vector<Arc> av;
+      av.push_back(Parent::direct(edge, true));
+      av.push_back(Parent::direct(edge, false));
+      notifier(Arc()).erase(av);
+      notifier(Edge()).erase(edge);
+    }
+
+  public:
     /// \brief Add a new edge to the graph.
     ///
     /// This function adds a new edge to the graph between nodes
@@ -1354,7 +1524,31 @@
     /// \return The new edge, or INVALID if the parameters don't meet the
     /// preconditions.
     Edge addEdge(Node u, Node v, Edge p_u, Edge p_v) {
-      return PlanarGraphBase::addEdge(u, v, p_u, p_v);
+      Face f_u = INVALID, f_v = INVALID;
+      if (p_u != INVALID) {
+        Arc a_u = direct(p_u,u);
+        f_u = leftFace(a_u);
+      }
+      if (p_v != INVALID) {
+        Arc a_v = direct(p_v,v);
+        f_v = leftFace(a_v);
+      }
+      Face o_u = outerFace(u);
+      Face o_v = outerFace(v);
+      Edge edge = PlanarGraphBase::addEdge(u, v, p_u, p_v);
+      if (edge == INVALID) return edge;
+      if (!valid(f_u)) notifier(Face()).erase(f_u);
+      if (!valid(f_v) && f_u != f_v) notifier(Face()).erase(f_v);
+      if (!valid(o_u)) notifier(Face()).erase(o_u);
+      if (!valid(o_v)) notifier(Face()).erase(o_v);
+      edge_add_notify(edge);
+      Face e_l = leftFace(direct(edge,u));
+      Face e_r = rightFace(direct(edge,u));
+      if (e_l != f_u && e_l != f_v && e_l != o_u && e_l != o_v)
+        notifier(Face()).add(e_l);
+      if (e_r != f_u && e_r != f_v && e_r != o_u && e_r != o_v && e_r != e_l)
+        notifier(Face()).add(e_r);
+      return edge;
     }
 
     ///\brief Erase a node from the graph.
@@ -1365,6 +1559,7 @@
     /// \note All iterators referencing the removed node or the incident
     /// edges are invalidated, of course.
     void erase(Node n) {
+      notifier(Face()).erase(outerFace(n));
       Parent::erase(n);
     }
 
@@ -1383,7 +1578,19 @@
     /// iterators might run an incomplete lap or revisit previously passed edges
     /// if edges are added to or removed from the boundary of the face.
     void erase(Edge e) {
+      Node n1 = u(e);
+      Node n2 = v(e);
+      Face f_l = leftFace(direct(e,n1));
+      Face f_r = rightFace(direct(e,n1));
       Parent::erase(e);
+      Face o_u = outerFace(n1);
+      Face o_v = outerFace(n2);
+      if (!valid(f_l)) notifier(Face()).erase(f_l);
+      if (!valid(f_r)) notifier(Face()).erase(f_r);
+      if (valid(o_u) && o_u != f_l && o_u != f_r)
+        notifier(Face()).add(o_u);
+      if (valid(o_v) && o_v != f_l && o_v != f_r)
+        notifier(Face()).add(o_v);
     }
     /// Node validity check
 
@@ -1421,7 +1628,7 @@
     /// This function gives back \c true if the given face is valid,
     /// i.e. it is a real face of the graph.
     ///
-    /// \warning A removed face could become valid again if new edges are
+    /// \warning A removed face could become valid again if new faces are
     /// added to the graph.
     bool valid(Face f) const {
       return Parent::valid(f);
@@ -1453,7 +1660,14 @@
     ///\warning This functionality cannot be used together with the
     ///Snapshot feature.
     void contract(Edge e) {
-      Parent::contract(e);
+      Node n1 = u(e);
+      Node n2 = v(e);
+      Node nd;
+      bool simple;
+      inner_contract1(n1,n2,nd,simple);
+      notifier(Node()).erase(nd);
+      edge_erase_notify(e);
+      inner_contract2(e,n1,n2,nd,simple);
     }
 
     /// \brief Split an edge.
@@ -1470,7 +1684,12 @@
     ///\warning This functionality cannot be used together with the
     ///Snapshot feature.
     Node split(Edge e) {
-      return Parent::split(e);
+      Node v;
+      Edge e2;
+      inner_split1(v,e2);
+      notifier(Node()).add(v);
+      edge_add_notify(e2);
+      return inner_split2(e,v,e2);
     }
 
     ///Split a node.
@@ -1492,10 +1711,22 @@
     ///
     ///\warning This functionality cannot be used together with the
     ///Snapshot feature.
-    Node split(Node n, Edge e1, Edge e2, bool connect = true) {
-      return Parent::split(n,e1,e2,connect);
+    Node split(Node n1, Edge e1, Edge e2, bool connect) {
+      Node n2;
+      inner_split1(n1,n2);
+      notifier(Node()).add(n2);
+      Edge a3;
+      inner_split2(n1,n2,e1,e2,connect,a3);
+      if (!connect) {
+        if (a3 != INVALID)
+          erase(a3);
+      } else {
+        edge_add_notify(a3);
+      }
+      return n2;
     }
 
+
     ///Clear the graph.
 
     ///This function erases all nodes and arcs from the graph.
