示例#1
0
BOOST_AUTO_TEST_CASE_TEMPLATE( intint_bgl_mutable_graph_test, Graph, intint_graphtest_types )
{
  typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
  typedef typename boost::graph_traits<Graph>::vertex_iterator VertexIter;
  typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
  typedef typename boost::graph_traits<Graph>::edge_iterator EdgeIter;
  typedef typename boost::graph_traits<Graph>::out_edge_iterator OutEdgeIter;
  typedef typename boost::graph_traits<Graph>::in_edge_iterator InEdgeIter;
  
  Graph g;
  
  Vertex v_root = Vertex();
  BOOST_CHECK_NO_THROW( v_root = add_vertex(g) );
  BOOST_CHECK_EQUAL( num_vertices(g), 1);
  BOOST_CHECK_NO_THROW( remove_vertex(v_root,g) );
  BOOST_CHECK_EQUAL( num_vertices(g), 0);
  
  BOOST_CHECK_NO_THROW( v_root = add_vertex(1, g) );
  g[v_root] = 1;
  BOOST_CHECK_EQUAL( g[v_root], 1 );
  
  int vp_rc[] = {2,3,4,5};
  int ep_rc[] = {1002,1003,1004,1005};
  Vertex v_rc[4];
  Edge e_rc[4];
  for(int i = 0; i < 4; ++i) {
    BOOST_CHECK_NO_THROW( v_rc[i] = add_vertex(g) );
    g[ v_rc[i] ] = vp_rc[i];
    BOOST_CHECK_EQUAL( g[ v_rc[i] ], vp_rc[i] );
    bool edge_added_success = false;
    BOOST_CHECK_NO_THROW( boost::tie(e_rc[i],edge_added_success) = add_edge(v_root, v_rc[i], g) );
    BOOST_CHECK( edge_added_success );
    g[ e_rc[i] ] = ep_rc[i];
    BOOST_CHECK_EQUAL( g[ e_rc[i] ], ep_rc[i] );
  };
  BOOST_CHECK_EQUAL( num_vertices(g), 5 );
  
  int vp_rc1c[] = {6,7,8,9};
  int ep_rc1c[] = {2006,2007,2008,2009};
  Vertex v_rc1c[4];
  Edge e_rc1c[4];
  for(std::size_t i = 0; i < 4; ++i) {
    BOOST_CHECK_NO_THROW( v_rc1c[i] = add_vertex(vp_rc1c[i], g) );
    BOOST_CHECK_EQUAL( g[ v_rc1c[i] ], vp_rc1c[i] );
    bool edge_added_success = false;
    BOOST_CHECK_NO_THROW( boost::tie(e_rc1c[i],edge_added_success) = add_edge(v_rc[0], v_rc1c[i], ep_rc1c[i], g) );
    BOOST_CHECK( edge_added_success );
    BOOST_CHECK_EQUAL( g[ e_rc1c[i] ], ep_rc1c[i] );
  };
  BOOST_CHECK_EQUAL( num_vertices(g), 9 );
  
  
  BOOST_CHECK_EQUAL( g[v_root], 1 );
  {
    OutEdgeIter ei, ei_end;
    BOOST_CHECK_NO_THROW( boost::tie(ei,ei_end) = out_edges(v_root,g) );
    std::vector<int> e_list;
    for(; ei != ei_end; ++ei) {
      if(is_edge_valid(*ei,g)) {
        BOOST_CHECK_EQUAL( g[*ei], (g[source(*ei,g)] * 1000 + g[target(*ei,g)]) );
        e_list.push_back(g[*ei]);
      };
    };
    std::sort(e_list.begin(), e_list.end());
    BOOST_CHECK_EQUAL( e_list[0], 1002);
    BOOST_CHECK_EQUAL( e_list[1], 1003);
    BOOST_CHECK_EQUAL( e_list[2], 1004);
    BOOST_CHECK_EQUAL( e_list[3], 1005);
    
    
    InEdgeIter iei, iei_end;
    BOOST_CHECK_NO_THROW( boost::tie(iei, iei_end) = in_edges(v_rc[0], g) );
    BOOST_CHECK( iei != iei_end );
    BOOST_CHECK_EQUAL( g[*iei], 1002);
    ++iei;
    BOOST_CHECK( iei == iei_end );
    
    
    BOOST_CHECK_NO_THROW( boost::tie(ei,ei_end) = out_edges(v_rc[0],g) );
    std::vector<int> e_list2;
    for(; ei != ei_end; ++ei) {
      if(is_edge_valid(*ei,g)) {
        BOOST_CHECK_EQUAL( g[*ei], (g[source(*ei,g)] * 1000 + g[target(*ei,g)]) );
        e_list2.push_back(g[*ei]);
      };
    };
    std::sort(e_list2.begin(), e_list2.end());
    BOOST_CHECK_EQUAL( e_list2[0], 2006);
    BOOST_CHECK_EQUAL( e_list2[1], 2007);
    BOOST_CHECK_EQUAL( e_list2[2], 2008);
    BOOST_CHECK_EQUAL( e_list2[3], 2009);

  };
  
  int vp_rc2c[] = {10,11,12,13};
  int ep_rc2c[] = {3010,3011,3012,3013};
  Vertex v_rc2c[4];
  Edge e_rc2c[4];
  for(std::size_t i = 0; i < 4; ++i) {
#ifdef RK_ENABLE_CXX0X_FEATURES
    BOOST_CHECK_NO_THROW( v_rc2c[i] = add_vertex(std::move(vp_rc2c[i]), g) );
#else
    BOOST_CHECK_NO_THROW( v_rc2c[i] = add_vertex(vp_rc2c[i], g) );
#endif
    bool edge_added_success = false;
#ifdef RK_ENABLE_CXX0X_FEATURES
    BOOST_CHECK_NO_THROW( boost::tie(e_rc2c[i],edge_added_success) = add_edge(v_rc[1], v_rc2c[i], ep_rc2c[i], g) );
#else
    BOOST_CHECK_NO_THROW( boost::tie(e_rc2c[i],edge_added_success) = add_edge(v_rc[1], v_rc2c[i], ep_rc2c[i], g) );
#endif
    BOOST_CHECK( edge_added_success );
  };
  BOOST_CHECK_EQUAL( num_vertices(g), 13 );
  
  {
    OutEdgeIter ei, ei_end;
    BOOST_CHECK_NO_THROW( boost::tie(ei,ei_end) = out_edges(v_rc[1],g) );
    std::vector<int> e_list;
    std::vector<int> vp_list;
    for(; ei != ei_end; ++ei) {
      if(is_edge_valid(*ei,g)) {
        BOOST_CHECK_EQUAL( g[*ei], (g[source(*ei,g)] * 1000 + g[target(*ei,g)]) );
        e_list.push_back(g[*ei]);
        vp_list.push_back(g[target(*ei,g)]);
      };
    };
    std::sort(e_list.begin(), e_list.end());
    BOOST_CHECK_EQUAL( e_list[0], 3010);
    BOOST_CHECK_EQUAL( e_list[1], 3011);
    BOOST_CHECK_EQUAL( e_list[2], 3012);
    BOOST_CHECK_EQUAL( e_list[3], 3013);
    
    std::sort(vp_list.begin(), vp_list.end());
    BOOST_CHECK_EQUAL( vp_list[0], 10);
    BOOST_CHECK_EQUAL( vp_list[1], 11);
    BOOST_CHECK_EQUAL( vp_list[2], 12);
    BOOST_CHECK_EQUAL( vp_list[3], 13);
  };
  
  BOOST_CHECK_NO_THROW( clear_vertex(v_rc[0],g) );
  
  BOOST_CHECK_EQUAL( out_degree(v_rc[0], g), 0 );
  BOOST_CHECK_EQUAL( in_degree(v_rc[0], g), 0 );
  BOOST_CHECK_EQUAL( out_degree(v_root, g), 3 );
  BOOST_CHECK_EQUAL( in_degree(v_rc1c[0], g), 0 );
  BOOST_CHECK_EQUAL( in_degree(v_rc1c[1], g), 0 );
  BOOST_CHECK_EQUAL( in_degree(v_rc1c[2], g), 0 );
  BOOST_CHECK_EQUAL( in_degree(v_rc1c[3], g), 0 );
  
  BOOST_CHECK_EQUAL( num_vertices(g), 13 );
  {
    VertexIter vi, vi_end;
    BOOST_CHECK_NO_THROW( boost::tie(vi, vi_end) = vertices(g) );
    std::vector<int> vp_list;
    for(; vi != vi_end; ++vi)
      if( is_vertex_valid(*vi, g) )
        vp_list.push_back( g[*vi] );
    std::sort(vp_list.begin(), vp_list.end());
    BOOST_CHECK_EQUAL( vp_list[0], 1 );
    BOOST_CHECK_EQUAL( vp_list[1], 2 );
    BOOST_CHECK_EQUAL( vp_list[2], 3 );
    BOOST_CHECK_EQUAL( vp_list[3], 4 );
    BOOST_CHECK_EQUAL( vp_list[4], 5 );
    BOOST_CHECK_EQUAL( vp_list[5], 6 );
    BOOST_CHECK_EQUAL( vp_list[6], 7 );
    BOOST_CHECK_EQUAL( vp_list[7], 8 );
    BOOST_CHECK_EQUAL( vp_list[8], 9 );
    BOOST_CHECK_EQUAL( vp_list[9], 10 );
    BOOST_CHECK_EQUAL( vp_list[10], 11 );
    BOOST_CHECK_EQUAL( vp_list[11], 12 );
    BOOST_CHECK_EQUAL( vp_list[12], 13 );
  };
  
  BOOST_CHECK_EQUAL( num_edges(g), 7 );
  {
    EdgeIter ei, ei_end;
    BOOST_CHECK_NO_THROW( boost::tie(ei, ei_end) = edges(g) );
    std::vector<int> ep_list;
    for(; ei != ei_end; ++ei)
      if( is_edge_valid(*ei, g) )
        ep_list.push_back( g[*ei] );
    std::sort(ep_list.begin(), ep_list.end());
    BOOST_CHECK_EQUAL( ep_list[0], 1003 );
    BOOST_CHECK_EQUAL( ep_list[1], 1004 );
    BOOST_CHECK_EQUAL( ep_list[2], 1005 );
    BOOST_CHECK_EQUAL( ep_list[3], 3010 );
    BOOST_CHECK_EQUAL( ep_list[4], 3011 );
    BOOST_CHECK_EQUAL( ep_list[5], 3012 );
    BOOST_CHECK_EQUAL( ep_list[6], 3013 );
  };
  
  
  
  BOOST_CHECK_NO_THROW( remove_edge(v_rc[1], v_rc2c[2], g) );
  
  BOOST_CHECK_EQUAL( num_vertices(g), 13 );
  {
    VertexIter vi, vi_end;
    BOOST_CHECK_NO_THROW( boost::tie(vi, vi_end) = vertices(g) );
    std::vector<int> vp_list;
    for(; vi != vi_end; ++vi) {
      if( is_vertex_valid(*vi, g) ) {
        vp_list.push_back( g[*vi] );
      };
    };
    std::sort(vp_list.begin(), vp_list.end());
    BOOST_CHECK_EQUAL( vp_list[0], 1 );
    BOOST_CHECK_EQUAL( vp_list[1], 2 );
    BOOST_CHECK_EQUAL( vp_list[2], 3 );
    BOOST_CHECK_EQUAL( vp_list[3], 4 );
    BOOST_CHECK_EQUAL( vp_list[4], 5 );
    BOOST_CHECK_EQUAL( vp_list[5], 6 );
    BOOST_CHECK_EQUAL( vp_list[6], 7 );
    BOOST_CHECK_EQUAL( vp_list[7], 8 );
    BOOST_CHECK_EQUAL( vp_list[8], 9 );
    BOOST_CHECK_EQUAL( vp_list[9], 10 );
    BOOST_CHECK_EQUAL( vp_list[10], 11 );
    BOOST_CHECK_EQUAL( vp_list[11], 12 );
    BOOST_CHECK_EQUAL( vp_list[12], 13 );
  };
  
  BOOST_CHECK_EQUAL( num_edges(g), 6 );
  {
    EdgeIter ei, ei_end;
    BOOST_CHECK_NO_THROW( boost::tie(ei, ei_end) = edges(g) );
    std::vector<int> ep_list;
    for(; ei != ei_end; ++ei) {
      if( is_edge_valid(*ei, g) ) {
        ep_list.push_back( g[*ei] );
      };
    };
    std::sort(ep_list.begin(), ep_list.end());
    BOOST_CHECK_EQUAL( ep_list[0], 1003 );
    BOOST_CHECK_EQUAL( ep_list[1], 1004 );
    BOOST_CHECK_EQUAL( ep_list[2], 1005 );
    BOOST_CHECK_EQUAL( ep_list[3], 3010 );
    BOOST_CHECK_EQUAL( ep_list[4], 3011 );
    BOOST_CHECK_EQUAL( ep_list[5], 3013 );
  };
  
  
  
  BOOST_CHECK_NO_THROW( remove_edge(e_rc2c[3], g) );
  
  BOOST_CHECK_EQUAL( num_vertices(g), 13 );
  {
    VertexIter vi, vi_end;
    BOOST_CHECK_NO_THROW( boost::tie(vi, vi_end) = vertices(g) );
    std::vector<int> vp_list;
    for(; vi != vi_end; ++vi) {
      if( is_vertex_valid(*vi, g) ) {
        vp_list.push_back( g[*vi] );
      };
    };
    std::sort(vp_list.begin(), vp_list.end());
    BOOST_CHECK_EQUAL( vp_list[0], 1 );
    BOOST_CHECK_EQUAL( vp_list[1], 2 );
    BOOST_CHECK_EQUAL( vp_list[2], 3 );
    BOOST_CHECK_EQUAL( vp_list[3], 4 );
    BOOST_CHECK_EQUAL( vp_list[4], 5 );
    BOOST_CHECK_EQUAL( vp_list[5], 6 );
    BOOST_CHECK_EQUAL( vp_list[6], 7 );
    BOOST_CHECK_EQUAL( vp_list[7], 8 );
    BOOST_CHECK_EQUAL( vp_list[8], 9 );
    BOOST_CHECK_EQUAL( vp_list[9], 10 );
    BOOST_CHECK_EQUAL( vp_list[10], 11 );
    BOOST_CHECK_EQUAL( vp_list[11], 12 );
    BOOST_CHECK_EQUAL( vp_list[12], 13 );
  };
  
  BOOST_CHECK_EQUAL( num_edges(g), 5 );
  {
    EdgeIter ei, ei_end;
    BOOST_CHECK_NO_THROW( boost::tie(ei, ei_end) = edges(g) );
    std::vector<int> ep_list;
    for(; ei != ei_end; ++ei) {
      if( is_edge_valid(*ei, g) ) {
        ep_list.push_back( g[*ei] );
      };
    };
    std::sort(ep_list.begin(), ep_list.end());
    BOOST_CHECK_EQUAL( ep_list[0], 1003 );
    BOOST_CHECK_EQUAL( ep_list[1], 1004 );
    BOOST_CHECK_EQUAL( ep_list[2], 1005 );
    BOOST_CHECK_EQUAL( ep_list[3], 3010 );
    BOOST_CHECK_EQUAL( ep_list[4], 3011 );
  };
  
  
  
  BOOST_CHECK_NO_THROW( clear_vertex(v_rc2c[0], g) );
  BOOST_CHECK_NO_THROW( remove_vertex(v_rc2c[0], g) );
  
  BOOST_CHECK_EQUAL( num_vertices(g), 12 );
  {
    VertexIter vi, vi_end;
    BOOST_CHECK_NO_THROW( boost::tie(vi, vi_end) = vertices(g) );
    std::vector<int> vp_list;
    for(; vi != vi_end; ++vi) {
      if( is_vertex_valid(*vi, g) ) {
        vp_list.push_back( g[*vi] );
      };
    };
    std::sort(vp_list.begin(), vp_list.end());
    BOOST_CHECK_EQUAL( vp_list[0], 1 );
    BOOST_CHECK_EQUAL( vp_list[1], 2 );
    BOOST_CHECK_EQUAL( vp_list[2], 3 );
    BOOST_CHECK_EQUAL( vp_list[3], 4 );
    BOOST_CHECK_EQUAL( vp_list[4], 5 );
    BOOST_CHECK_EQUAL( vp_list[5], 6 );
    BOOST_CHECK_EQUAL( vp_list[6], 7 );
    BOOST_CHECK_EQUAL( vp_list[7], 8 );
    BOOST_CHECK_EQUAL( vp_list[8], 9 );
    BOOST_CHECK_EQUAL( vp_list[9], 11 );
    BOOST_CHECK_EQUAL( vp_list[10], 12 );
    BOOST_CHECK_EQUAL( vp_list[11], 13 );
  };
  
  BOOST_CHECK_EQUAL( num_edges(g), 4 );
  {
    EdgeIter ei, ei_end;
    BOOST_CHECK_NO_THROW( boost::tie(ei, ei_end) = edges(g) );
    std::vector<int> ep_list;
    for(; ei != ei_end; ++ei) {
      if( is_edge_valid(*ei, g) ) {
        ep_list.push_back( g[*ei] );
      };
    };
    std::sort(ep_list.begin(), ep_list.end());
    BOOST_CHECK_EQUAL( ep_list[0], 1003 );
    BOOST_CHECK_EQUAL( ep_list[1], 1004 );
    BOOST_CHECK_EQUAL( ep_list[2], 1005 );
    BOOST_CHECK_EQUAL( ep_list[3], 3011 );
  };
  
  
};
示例#2
0
int main(const int argc, const char* const argv[]) {

  //! undirected graphs with out-edges stored in lists and the vertices stored in a vector (to enable index-access)
  typedef boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, boost::property<boost::vertex_name_t, std::string> > UndirectedGraph;
  typedef boost::graph_traits<UndirectedGraph>::vertex_descriptor vertex_type;
  typedef boost::graph_traits<UndirectedGraph>::vertices_size_type vertices_size_type;
  typedef boost::graph_traits<UndirectedGraph>::edges_size_type edges_size_type;

  UndirectedGraph g;
  {
    boost::dynamic_properties p;
    p.property("node_id", get(boost::vertex_name, g));
    boost::read_graphviz(std::cin, g, p);
  }
  
  const vertices_size_type n = num_vertices(g);
  const edges_size_type m = num_edges(g);
  
  std::cout << "\n" << n << ", " << m << std::endl;
  OKlib::HypergraphColouring::output_vertex_degrees(g, std::cout);
  std::cout << std::endl;

  OKlib::HypergraphColouring::Greedy_colouring<UndirectedGraph> fgg(g);
  assert(fgg.n == n);

  {
    typedef std::map<std::string, vertex_type> name_map_type;
    name_map_type map;
    for (vertices_size_type i = 0; i < n; ++i)
      map.insert(std::make_pair(get(boost::vertex_name, g, fgg.given_order[i]), fgg.given_order[i]));
    assert(map.size() == n);
    typedef name_map_type::const_iterator iterator;
    const iterator end(map.end());
    vertices_size_type i = 0;
    for (iterator j(map.begin()); j != end; ++i, ++j)
      fgg.running_order[i] = j -> second;
  }
  fgg.colouring();
  std::cout << "lexicographical order = " << fgg.num_colours << std::endl;
  for (vertices_size_type i = 0; i < n; ++i)
    std::cout << get(boost::vertex_name, g, fgg.running_order[i]) << " ";
  std::cout << std::endl;
  for (vertices_size_type i = 0; i < n; ++i)
    std::cout << get(boost::vertex_name, g, fgg.running_order[i]) << " -> " << fgg.colour_vec[get(boost::vertex_index, g, fgg.running_order[i])] << ", ";
  std::cout << std::endl;
  
  std::stable_sort(fgg.running_order.begin(), fgg.running_order.end(), fgg.sort);
  fgg.colouring();
  std::cout << "smallest degrees first = " << fgg.num_colours << std::endl;
  for (vertices_size_type i = 0; i < n; ++i)
    std::cout << get(boost::vertex_name, g, fgg.running_order[i]) << " ";
  std::cout << std::endl;
  for (vertices_size_type i = 0; i < n; ++i)
    std::cout << get(boost::vertex_name, g, fgg.running_order[i]) << " -> " << fgg.colour_vec[get(boost::vertex_index, g, fgg.running_order[i])] << ", ";
  std::cout << std::endl;
  
  std::reverse(fgg.running_order.begin(), fgg.running_order.end());
  fgg.colouring();
  std::cout << "largest degrees first = " << fgg.num_colours << std::endl;
  for (vertices_size_type i = 0; i < n; ++i)
    std::cout << get(boost::vertex_name, g, fgg.running_order[i]) << " ";
  std::cout << std::endl;
  for (vertices_size_type i = 0; i < n; ++i)
    std::cout << get(boost::vertex_name, g, fgg.running_order[i]) << " -> " << fgg.colour_vec[get(boost::vertex_index, g, fgg.running_order[i])] << ", ";
  std::cout << std::endl;
  
  if (argc > 1) {
    fgg.evaluation();

    std::cout << "\n";
    for (vertices_size_type i = 0; i <= n; ++i)
      std::cout << i << " : " << fgg.hash_orders[i] << "\n";
    std::cout << std::endl;
    
    std::cout << "min numbers of colours = " << fgg.min_colours << std::endl;
    for (vertices_size_type i = 0; i < n; ++i)
      std::cout << get(boost::vertex_name, g, fgg.optimal_order[i]) << " ";
    std::cout << std::endl;
    for (vertices_size_type i = 0; i < n; ++i)
      std::cout <<  get(boost::vertex_name, g, fgg.optimal_order[i]) << " -> " << fgg.optimal_colouring[get(boost::vertex_index, g, fgg.optimal_order[i])] << ", ";
    std::cout << std::endl;
    
    std::cout << "max number of colours = " << fgg.max_colours << std::endl;
    for (vertices_size_type i = 0; i < n; ++i)
      std::cout <<  get(boost::vertex_name, g, fgg.worst_order[i]) << " ";
    std::cout << std::endl;
    for (vertices_size_type i = 0; i < n; ++i)
      std::cout << get(boost::vertex_name, g, fgg.worst_order[i]) << " -> " << fgg.worst_colouring[get(boost::vertex_index, g, fgg.worst_order[i])] << ", ";
    std::cout << std::endl;
  }

}
示例#3
0
size_t num_edges(const NGHolder &h) {
    if (!h.isValidNumEdges) {
        return num_edges(h.g);
    }
    return h.numEdges;
}
示例#4
0
DANI_INLINE
int EpsTrimesh::add_triangle(const int vid0, const int vid1, const int vid2, const int scalar)
{
    assert(vid0 >= 0 && vid0 < num_vertices());
    assert(vid1 >= 0 && vid1 < num_vertices());
    assert(vid2 >= 0 && vid2 < num_vertices());

    int tid = num_triangles();
    //
    tris.push_back(vid0);
    tris.push_back(vid1);
    tris.push_back(vid2);
    //
    t_label.push_back(scalar);
    //
    tri2edg.push_back(std::vector<int>());
    tri2tri.push_back(std::vector<int>());
    //
    vtx2tri.at(vid0).push_back(tid);
    vtx2tri.at(vid1).push_back(tid);
    vtx2tri.at(vid2).push_back(tid);
    //
    ipair new_e[3]   = { unique_pair(vid0, vid1), unique_pair(vid1, vid2), unique_pair(vid2, vid0) };
    int   new_eid[3] = { -1, -1, -1 };
    for(int eid=0; eid<num_edges(); ++eid)
    {
        ipair e = unique_pair(edge_vertex_id(eid, 0), edge_vertex_id(eid, 1));
        for(int i=0; i<3; ++i) if (e == new_e[i]) new_eid[i] = eid;
    }
    //
    for(int i=0; i<3; ++i)
    {
        if (new_eid[i] == -1)
        {
            new_eid[i] = num_edges();
            edges.push_back(new_e[i].first);
            edges.push_back(new_e[i].second);
            edg2tri.push_back(std::vector<int>());

            vtx2edg.at(new_e[i].first).push_back(num_edges()-1);
            vtx2edg.at(new_e[i].second).push_back(num_edges()-1);

            vtx2vtx.at(new_e[i].first).push_back(new_e[i].second);
            vtx2vtx.at(new_e[i].second).push_back(new_e[i].first);

        }
        //
        for(int nbr : edg2tri.at(new_eid[i]))
        {
            tri2tri.at(nbr).push_back(tid);
            tri2tri.at(tid).push_back(nbr);
        }
        edg2tri.at(new_eid[i]).push_back(tid);
        tri2edg.at(tid).push_back(new_eid[i]);
    }
    //
    t_norm.push_back(0); //tnx
    t_norm.push_back(0); //tny
    t_norm.push_back(0); //tnz

#ifdef CINOLIB
    //
    update_t_normal(tid);
    update_v_normal(vid0);
    update_v_normal(vid1);
    update_v_normal(vid2);
#else

    std::cerr << "[WARNING] Cinolib required to update triangle and vertex normals." << std::endl;

#endif

    return tid;
}
  void planar_face_traversal(const Graph& g, 
                             PlanarEmbedding embedding, 
                             Visitor& visitor, EdgeIndexMap em
                             )
  {
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
    typedef typename graph_traits<Graph>::edge_descriptor edge_t;
    typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
    typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
    typedef typename 
      property_traits<PlanarEmbedding>::value_type embedding_value_t;
    typedef typename embedding_value_t::const_iterator embedding_iterator_t;

    typedef typename 
      std::vector< std::set<vertex_t> > distinguished_edge_storage_t;
    typedef typename 
      std::vector< std::map<vertex_t, edge_t> > 
      distinguished_edge_to_edge_storage_t;

    typedef typename 
      boost::iterator_property_map
        <typename distinguished_edge_storage_t::iterator, EdgeIndexMap>
      distinguished_edge_map_t;

    typedef typename 
      boost::iterator_property_map
        <typename distinguished_edge_to_edge_storage_t::iterator, EdgeIndexMap>
      distinguished_edge_to_edge_map_t;

    distinguished_edge_storage_t visited_vector(num_edges(g));
    distinguished_edge_to_edge_storage_t next_edge_vector(num_edges(g));

    distinguished_edge_map_t visited(visited_vector.begin(), em);
    distinguished_edge_to_edge_map_t next_edge(next_edge_vector.begin(), em);

    vertex_iterator_t vi, vi_end;
    typename std::vector<edge_t>::iterator ei, ei_end;
    edge_iterator_t fi, fi_end;
    embedding_iterator_t pi, pi_begin, pi_end;

    visitor.begin_traversal();

    // Initialize the next_edge property map. This map is initialized from the
    // PlanarEmbedding so that get(next_edge, e)[v] is the edge that comes
    // after e in the clockwise embedding around vertex v.

    for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
      {
        vertex_t v(*vi);
        pi_begin = embedding[v].begin();
        pi_end = embedding[v].end();
        for(pi = pi_begin; pi != pi_end; ++pi)
          {
            edge_t e(*pi);
            std::map<vertex_t, edge_t> m = get(next_edge, e);
            m[v] = boost::next(pi) == pi_end ? *pi_begin : *boost::next(pi);
            put(next_edge, e, m);
          } 
      }

    // Take a copy of the edges in the graph here, since we want to accomodate
    // face traversals that add edges to the graph (for triangulation, in 
    // particular) and don't want to use invalidated edge iterators.
    // Also, while iterating over all edges in the graph, we single out
    // any self-loops, which need some special treatment in the face traversal.

    std::vector<edge_t> self_loops;
    std::vector<edge_t> edges_cache;
    std::vector<vertex_t> vertices_in_edge;

    for(boost::tie(fi,fi_end) = edges(g); fi != fi_end; ++fi)
      {
        edge_t e(*fi);
        edges_cache.push_back(e);
        if (source(e,g) == target(e,g))
          self_loops.push_back(e);
      }


    // Iterate over all edges in the graph
    ei_end = edges_cache.end();
    for(ei = edges_cache.begin(); ei != ei_end; ++ei)
      {

        edge_t e(*ei);
        vertices_in_edge.clear();
        vertices_in_edge.push_back(source(e,g));
        vertices_in_edge.push_back(target(e,g));

        typename std::vector<vertex_t>::iterator vi, vi_end;
        vi_end = vertices_in_edge.end();
        
        //Iterate over both vertices in the current edge
        for(vi = vertices_in_edge.begin(); vi != vi_end; ++vi)
          {

            vertex_t v(*vi);
            std::set<vertex_t> e_visited = get(visited, e);
            typename std::set<vertex_t>::iterator e_visited_found 
              = e_visited.find(v);
            
            if (e_visited_found == e_visited.end())
              visitor.begin_face();
            
            while (e_visited.find(v) == e_visited.end())
              {
                visitor.next_vertex(v);
                visitor.next_edge(e);
                e_visited.insert(v);
                put(visited, e, e_visited);
                v = source(e,g) == v ? target(e,g) : source(e,g);
                e = get(next_edge, e)[v];
                e_visited = get(visited, e);
              }
            
            if (e_visited_found == e_visited.end())
              visitor.end_face();
            
          }

      }

    // Iterate over all self-loops, visiting them once separately
    // (they've already been visited once, this visitation is for
    // the "inside" of the self-loop)
    
    ei_end = self_loops.end();
    for(ei = self_loops.begin(); ei != ei_end; ++ei)
      {
        visitor.begin_face();
        visitor.next_edge(*ei);
        visitor.next_vertex(source(*ei,g));
        visitor.end_face();
      }

    visitor.end_traversal();

  }