You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
275 lines
8.2 KiB
275 lines
8.2 KiB
//======================================================================= |
|
// Copyright 2007 Aaron Windsor |
|
// |
|
// 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 __MAKE_MAXIMAL_PLANAR_HPP__ |
|
#define __MAKE_MAXIMAL_PLANAR_HPP__ |
|
|
|
#include <boost/config.hpp> |
|
#include <boost/tuple/tuple.hpp> //for tie |
|
#include <boost/graph/biconnected_components.hpp> |
|
#include <boost/property_map/property_map.hpp> |
|
#include <vector> |
|
#include <iterator> |
|
#include <algorithm> |
|
|
|
#include <boost/graph/planar_face_traversal.hpp> |
|
#include <boost/graph/planar_detail/add_edge_visitors.hpp> |
|
|
|
|
|
namespace boost |
|
{ |
|
|
|
|
|
template <typename Graph, typename VertexIndexMap, typename AddEdgeVisitor> |
|
struct triangulation_visitor : public planar_face_traversal_visitor |
|
{ |
|
|
|
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t; |
|
typedef typename graph_traits<Graph>::edge_descriptor edge_t; |
|
typedef typename graph_traits<Graph>::vertices_size_type v_size_t; |
|
typedef typename graph_traits<Graph>::degree_size_type degree_size_t; |
|
typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t; |
|
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t; |
|
typedef typename graph_traits<Graph>::adjacency_iterator |
|
adjacency_iterator_t; |
|
typedef typename std::vector<vertex_t> vertex_vector_t; |
|
typedef typename std::vector<v_size_t> v_size_vector_t; |
|
typedef typename std::vector<degree_size_t> degree_size_vector_t; |
|
typedef iterator_property_map |
|
< typename v_size_vector_t::iterator, VertexIndexMap > |
|
vertex_to_v_size_map_t; |
|
typedef iterator_property_map |
|
< typename degree_size_vector_t::iterator, VertexIndexMap > |
|
vertex_to_degree_size_map_t; |
|
typedef typename vertex_vector_t::iterator face_iterator; |
|
|
|
|
|
triangulation_visitor(Graph& arg_g, |
|
VertexIndexMap arg_vm, |
|
AddEdgeVisitor arg_add_edge_visitor |
|
) : |
|
g(arg_g), |
|
vm(arg_vm), |
|
add_edge_visitor(arg_add_edge_visitor), |
|
timestamp(0), |
|
marked_vector(num_vertices(g), timestamp), |
|
degree_vector(num_vertices(g), 0), |
|
marked(marked_vector.begin(), vm), |
|
degree(degree_vector.begin(), vm) |
|
{ |
|
vertex_iterator_t vi, vi_end; |
|
for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) |
|
put(degree, *vi, out_degree(*vi, g)); |
|
} |
|
|
|
template <typename Vertex> |
|
void next_vertex(Vertex v) |
|
{ |
|
// Self-loops will appear as consecutive vertices in the list of |
|
// vertices on a face. We want to skip these. |
|
if (!vertices_on_face.empty() && |
|
(vertices_on_face.back() == v || vertices_on_face.front() == v) |
|
) |
|
return; |
|
|
|
vertices_on_face.push_back(v); |
|
} |
|
|
|
void end_face() |
|
{ |
|
++timestamp; |
|
|
|
if (vertices_on_face.size() <= 3) |
|
{ |
|
// At most three vertices on this face - don't need to triangulate |
|
vertices_on_face.clear(); |
|
return; |
|
} |
|
|
|
// Find vertex on face of minimum degree |
|
degree_size_t min_degree = num_vertices(g); |
|
typename vertex_vector_t::iterator min_degree_vertex_itr; |
|
face_iterator fi_end = vertices_on_face.end(); |
|
for(face_iterator fi = vertices_on_face.begin(); fi != fi_end; ++fi) |
|
{ |
|
degree_size_t deg = get(degree,*fi); |
|
if (deg < min_degree) |
|
{ |
|
min_degree_vertex_itr = fi; |
|
min_degree = deg; |
|
} |
|
} |
|
|
|
// To simplify some of the manipulations, we'll re-arrange |
|
// vertices_on_face so that it still contains the same |
|
// (counter-clockwise) order of the vertices on this face, but now the |
|
// min_degree_vertex is the first element in vertices_on_face. |
|
vertex_vector_t temp_vector; |
|
std::copy(min_degree_vertex_itr, vertices_on_face.end(), |
|
std::back_inserter(temp_vector)); |
|
std::copy(vertices_on_face.begin(), min_degree_vertex_itr, |
|
std::back_inserter(temp_vector)); |
|
vertices_on_face.swap(temp_vector); |
|
|
|
// Mark all of the min degree vertex's neighbors |
|
adjacency_iterator_t ai, ai_end; |
|
for(boost::tie(ai,ai_end) = adjacent_vertices(vertices_on_face.front(),g); |
|
ai != ai_end; ++ai |
|
) |
|
{ |
|
put(marked, *ai, timestamp); |
|
} |
|
|
|
typename vertex_vector_t::iterator marked_neighbor |
|
= vertices_on_face.end(); |
|
|
|
// The iterator manipulations on the next two lines are safe because |
|
// vertices_on_face.size() > 3 (from the first test in this function) |
|
fi_end = prior(vertices_on_face.end()); |
|
for(face_iterator fi = boost::next(boost::next(vertices_on_face.begin())); |
|
fi != fi_end; ++fi |
|
) |
|
{ |
|
if (get(marked, *fi) == timestamp) |
|
{ |
|
marked_neighbor = fi; |
|
break; |
|
} |
|
} |
|
|
|
if (marked_neighbor == vertices_on_face.end()) |
|
{ |
|
add_edge_range( |
|
vertices_on_face[0], |
|
boost::next(boost::next(vertices_on_face.begin())), |
|
prior(vertices_on_face.end()) |
|
); |
|
} |
|
else |
|
{ |
|
add_edge_range( |
|
vertices_on_face[1], |
|
boost::next(marked_neighbor), |
|
vertices_on_face.end() |
|
); |
|
|
|
add_edge_range( |
|
*boost::next(marked_neighbor), |
|
boost::next(boost::next(vertices_on_face.begin())), |
|
marked_neighbor |
|
); |
|
} |
|
|
|
//reset for the next face |
|
vertices_on_face.clear(); |
|
|
|
} |
|
|
|
private: |
|
|
|
|
|
void add_edge_range(vertex_t anchor, |
|
face_iterator fi, |
|
face_iterator fi_end |
|
) |
|
{ |
|
for (; fi != fi_end; ++fi) |
|
{ |
|
vertex_t v(*fi); |
|
add_edge_visitor.visit_vertex_pair(anchor, v, g); |
|
put(degree, anchor, get(degree, anchor) + 1); |
|
put(degree, v, get(degree, v) + 1); |
|
} |
|
} |
|
|
|
|
|
Graph& g; |
|
VertexIndexMap vm; |
|
AddEdgeVisitor add_edge_visitor; |
|
v_size_t timestamp; |
|
vertex_vector_t vertices_on_face; |
|
v_size_vector_t marked_vector; |
|
degree_size_vector_t degree_vector; |
|
vertex_to_v_size_map_t marked; |
|
vertex_to_degree_size_map_t degree; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
template <typename Graph, |
|
typename PlanarEmbedding, |
|
typename VertexIndexMap, |
|
typename EdgeIndexMap, |
|
typename AddEdgeVisitor |
|
> |
|
void make_maximal_planar(Graph& g, |
|
PlanarEmbedding embedding, |
|
VertexIndexMap vm, |
|
EdgeIndexMap em, |
|
AddEdgeVisitor& vis) |
|
{ |
|
triangulation_visitor<Graph,VertexIndexMap,AddEdgeVisitor> |
|
visitor(g, vm, vis); |
|
planar_face_traversal(g, embedding, visitor, em); |
|
} |
|
|
|
|
|
|
|
|
|
template <typename Graph, |
|
typename PlanarEmbedding, |
|
typename VertexIndexMap, |
|
typename EdgeIndexMap |
|
> |
|
void make_maximal_planar(Graph& g, |
|
PlanarEmbedding embedding, |
|
VertexIndexMap vm, |
|
EdgeIndexMap em |
|
) |
|
{ |
|
default_add_edge_visitor vis; |
|
make_maximal_planar(g, embedding, vm, em, vis); |
|
} |
|
|
|
|
|
|
|
|
|
template <typename Graph, |
|
typename PlanarEmbedding, |
|
typename VertexIndexMap |
|
> |
|
void make_maximal_planar(Graph& g, |
|
PlanarEmbedding embedding, |
|
VertexIndexMap vm |
|
) |
|
{ |
|
make_maximal_planar(g, embedding, vm, get(edge_index,g)); |
|
} |
|
|
|
|
|
|
|
|
|
template <typename Graph, |
|
typename PlanarEmbedding |
|
> |
|
void make_maximal_planar(Graph& g, |
|
PlanarEmbedding embedding |
|
) |
|
{ |
|
make_maximal_planar(g, embedding, get(vertex_index,g)); |
|
} |
|
|
|
|
|
|
|
|
|
} // namespace boost |
|
|
|
|
|
|
|
#endif //__MAKE_MAXIMAL_PLANAR_HPP__
|
|
|