⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 face_handles.hpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 HPP
字号:
//=======================================================================// Copyright (c) Aaron Windsor 2007//// Distributed under the Boost Software License, Version 1.0. (See// accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)//=======================================================================#ifndef __FACE_HANDLES_HPP__#define __FACE_HANDLES_HPP__#include <list>#include <boost/graph/graph_traits.hpp>#include <boost/shared_ptr.hpp>// A "face handle" is an optimization meant to serve two purposes in// the implementation of the Boyer-Myrvold planarity test: (1) it holds// the partial planar embedding of a particular vertex as it's being// constructed, and (2) it allows for efficient traversal around the// outer face of the partial embedding at that particular vertex. A face// handle is lightweight, just a shared pointer to the actual implementation,// since it is passed around/copied liberally in the algorithm. It consists// of an "anchor" (the actual vertex it's associated with) as well as a// sequence of edges. The functions first_vertex/second_vertex and// first_edge/second_edge allow fast access to the beginning and end of the// stored sequence, which allows one to traverse the outer face of the partial// planar embedding as it's being created. //// There are some policies below that define the contents of the face handles:// in the case no embedding is needed (for example, if one just wants to use// the Boyer-Myrvold algorithm as a true/false test for planarity, the// no_embedding class can be passed as the StoreEmbedding policy. Otherwise,// either std_list (which uses as std::list) or recursive_lazy_list can be// passed as this policy. recursive_lazy_list has the best theoretical// performance (O(n) for a sequence of interleaved concatenations and reversals// of the underlying list), but I've noticed little difference between std_list// and recursive_lazy_list in my tests, even though using std_list changes// the worst-case complexity of the planarity test to O(n^2)//// Another policy is StoreOldHandlesPolicy, which specifies whether or not// to keep a record of the previous first/second vertex/edge - this is needed// if a Kuratowski subgraph needs to be isolated.namespace boost { namespace graph { namespace detail {  //face handle policies    //EmbeddingStorage policy  struct store_embedding {};  struct recursive_lazy_list : public store_embedding {};  struct std_list : public store_embedding {};  struct no_embedding {};  //StoreOldHandlesPolicy  struct store_old_handles {};  struct no_old_handles {};  template<typename DataType>  struct lazy_list_node  {    typedef shared_ptr< lazy_list_node<DataType> > ptr_t;    lazy_list_node(const DataType& data) :      m_reversed(false),      m_data(data),      m_has_data(true)    {}        lazy_list_node(ptr_t left_child, ptr_t right_child) :      m_reversed(false),      m_has_data(false),      m_left_child(left_child),      m_right_child(right_child)    {}    bool m_reversed;    DataType m_data;    bool m_has_data;    shared_ptr<lazy_list_node> m_left_child;    shared_ptr<lazy_list_node> m_right_child;  };    template <typename StoreOldHandlesPolicy, typename Vertex, typename Edge>  struct old_handles_storage;  template <typename Vertex, typename Edge>  struct old_handles_storage<store_old_handles, Vertex, Edge>  {    Vertex first_vertex;    Vertex second_vertex;    Edge first_edge;    Edge second_edge;  };  template <typename Vertex, typename Edge>  struct old_handles_storage<no_old_handles, Vertex, Edge>  {};  template <typename StoreEmbeddingPolicy, typename Edge>  struct edge_list_storage;  template <typename Edge>  struct edge_list_storage<no_embedding, Edge>  {    typedef void type;    void push_back(Edge) {}    void push_front(Edge) {}    void reverse() {}    void concat_front(edge_list_storage<no_embedding,Edge>) {}    void concat_back(edge_list_storage<no_embedding,Edge>) {}    template <typename OutputIterator>    void get_list(OutputIterator) {}  };  template <typename Edge>  struct edge_list_storage<recursive_lazy_list, Edge>  {    typedef lazy_list_node<Edge> node_type;    typedef shared_ptr< node_type > type;    type value;    void push_back(Edge e)    {      type new_node(new node_type(e));      value = type(new node_type(value, new_node));    }    void push_front(Edge e)    {      type new_node(new node_type(e));      value = type(new node_type(new_node, value));    }    void reverse()    {      value->m_reversed = !value->m_reversed;    }    void concat_front(edge_list_storage<recursive_lazy_list, Edge> other)    {      value = type(new node_type(other.value, value));    }    void concat_back(edge_list_storage<recursive_lazy_list, Edge> other)    {      value = type(new node_type(value, other.value));    }    template <typename OutputIterator>    void get_list(OutputIterator out)    {      get_list_helper(out, value);    }  private:    template <typename OutputIterator>    void get_list_helper(OutputIterator o_itr,                          type root,                         bool flipped = false                         )    {      if (!root)        return;            if (root->m_has_data)        *o_itr = root->m_data;            if ((flipped && !root->m_reversed) ||          (!flipped && root->m_reversed)          )        {          get_list_helper(o_itr, root->m_right_child, true);          get_list_helper(o_itr, root->m_left_child, true);        }      else        {          get_list_helper(o_itr, root->m_left_child, false);          get_list_helper(o_itr, root->m_right_child, false);        }          }      };  template <typename Edge>  struct edge_list_storage<std_list, Edge>  {    typedef std::list<Edge> type;    type value;    void push_back(Edge e)    {      value.push_back(e);    }    void push_front(Edge e)    {      value.push_front(e);    }    void reverse()    {      value.reverse();    }    void concat_front(edge_list_storage<std_list,Edge> other)    {      value.splice(value.begin(), other.value);    }    void concat_back(edge_list_storage<std_list, Edge> other)    {      value.splice(value.end(), other.value);    }    template <typename OutputIterator>    void get_list(OutputIterator out)    {      std::copy(value.begin(), value.end(), out);    }  };    template<typename Graph,            typename StoreOldHandlesPolicy,            typename StoreEmbeddingPolicy                      >  struct face_handle_impl  {    typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;    typedef typename graph_traits<Graph>::edge_descriptor edge_t;    typedef typename edge_list_storage<StoreEmbeddingPolicy, edge_t>::type       edge_list_storage_t;    face_handle_impl() :       cached_first_vertex(graph_traits<Graph>::null_vertex()),      cached_second_vertex(graph_traits<Graph>::null_vertex()),      true_first_vertex(graph_traits<Graph>::null_vertex()),      true_second_vertex(graph_traits<Graph>::null_vertex()),      anchor(graph_traits<Graph>::null_vertex())    {      initialize_old_vertices_dispatch(StoreOldHandlesPolicy());    }    void initialize_old_vertices_dispatch(store_old_handles)    {      old_handles.first_vertex = graph_traits<Graph>::null_vertex();      old_handles.second_vertex = graph_traits<Graph>::null_vertex();    }    void initialize_old_vertices_dispatch(no_old_handles) {}    vertex_t cached_first_vertex;    vertex_t cached_second_vertex;    vertex_t true_first_vertex;    vertex_t true_second_vertex;    vertex_t anchor;    edge_t cached_first_edge;    edge_t cached_second_edge;    edge_list_storage<StoreEmbeddingPolicy, edge_t> edge_list;    old_handles_storage<StoreOldHandlesPolicy, vertex_t, edge_t> old_handles;  };  template <typename Graph,             typename StoreOldHandlesPolicy = store_old_handles,             typename StoreEmbeddingPolicy = recursive_lazy_list            >  class face_handle   {  public:    typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;    typedef typename graph_traits<Graph>::edge_descriptor edge_t;    typedef face_handle_impl      <Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> impl_t;    typedef face_handle      <Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> self_t;    face_handle(vertex_t anchor = graph_traits<Graph>::null_vertex()) :      pimpl(new impl_t())    {      pimpl->anchor = anchor;    }    face_handle(vertex_t anchor, edge_t initial_edge, const Graph& g) :      pimpl(new impl_t())    {      vertex_t s(source(initial_edge,g));      vertex_t t(target(initial_edge,g));      vertex_t other_vertex = s == anchor ? t : s;      pimpl->anchor = anchor;      pimpl->cached_first_edge = initial_edge;      pimpl->cached_second_edge = initial_edge;      pimpl->cached_first_vertex = other_vertex;      pimpl->cached_second_vertex = other_vertex;      pimpl->true_first_vertex = other_vertex;      pimpl->true_second_vertex = other_vertex;      pimpl->edge_list.push_back(initial_edge);      store_old_face_handles_dispatch(StoreOldHandlesPolicy());    }    //default copy construction, assignment okay.        void push_first(edge_t e, const Graph& g)     {       pimpl->edge_list.push_front(e);      pimpl->cached_first_vertex = pimpl->true_first_vertex =         source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);      pimpl->cached_first_edge = e;    }      void push_second(edge_t e, const Graph& g)     {       pimpl->edge_list.push_back(e);      pimpl->cached_second_vertex = pimpl->true_second_vertex =         source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);      pimpl->cached_second_edge = e;    }    inline void store_old_face_handles()    {      store_old_face_handles_dispatch(StoreOldHandlesPolicy());    }    inline vertex_t first_vertex() const    {       return pimpl->cached_first_vertex;    }        inline vertex_t second_vertex() const     {       return pimpl->cached_second_vertex;    }    inline vertex_t true_first_vertex() const     {       return pimpl->true_first_vertex;    }    inline vertex_t true_second_vertex() const     {       return pimpl->true_second_vertex;    }    inline vertex_t old_first_vertex() const    {      return pimpl->old_handles.first_vertex;    }    inline vertex_t old_second_vertex() const    {      return pimpl->old_handles.second_vertex;    }    inline edge_t old_first_edge() const    {      return pimpl->old_handles.first_edge;    }    inline edge_t old_second_edge() const    {      return pimpl->old_handles.second_edge;    }    inline edge_t first_edge() const    {      return pimpl->cached_first_edge;    }      inline edge_t second_edge() const    {      return pimpl->cached_second_edge;    }        inline vertex_t get_anchor() const    {      return pimpl->anchor;    }      void glue_first_to_second      (face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)    {      pimpl->edge_list.concat_front(bottom.pimpl->edge_list);      pimpl->true_first_vertex = bottom.pimpl->true_first_vertex;      pimpl->cached_first_vertex = bottom.pimpl->cached_first_vertex;      pimpl->cached_first_edge = bottom.pimpl->cached_first_edge;    }        void glue_second_to_first      (face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)    {      pimpl->edge_list.concat_back(bottom.pimpl->edge_list);      pimpl->true_second_vertex = bottom.pimpl->true_second_vertex;      pimpl->cached_second_vertex = bottom.pimpl->cached_second_vertex;      pimpl->cached_second_edge = bottom.pimpl->cached_second_edge;    }      void flip()    {      pimpl->edge_list.reverse();      std::swap(pimpl->true_first_vertex, pimpl->true_second_vertex);      std::swap(pimpl->cached_first_vertex, pimpl->cached_second_vertex);      std::swap(pimpl->cached_first_edge, pimpl->cached_second_edge);    }        template <typename OutputIterator>    void get_list(OutputIterator o_itr)    {      pimpl->edge_list.get_list(o_itr);    }    void reset_vertex_cache()    {      pimpl->cached_first_vertex = pimpl->true_first_vertex;      pimpl->cached_second_vertex = pimpl->true_second_vertex;    }    inline void set_first_vertex(vertex_t v)    {      pimpl->cached_first_vertex = v;    }    inline void set_second_vertex(vertex_t v)    {      pimpl->cached_second_vertex = v;    }  private:    void store_old_face_handles_dispatch(store_old_handles)    {      pimpl->old_handles.first_vertex = pimpl->true_first_vertex;      pimpl->old_handles.second_vertex = pimpl->true_second_vertex;      pimpl->old_handles.first_edge = pimpl->cached_first_edge;      pimpl->old_handles.second_edge = pimpl->cached_second_edge;    }      void store_old_face_handles_dispatch(no_old_handles) {}    boost::shared_ptr<impl_t> pimpl;  };} /* namespace detail */ } /* namespace graph */ } /* namespace boost */#endif //__FACE_HANDLES_HPP__

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -