void make_biconnected_planar(Graph& g,
                             PlanarEmbedding embedding,
                             EdgeIndexMap em,
                             AddEdgeVisitor& vis
                            )
{
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
    typedef typename graph_traits<Graph>::edge_descriptor edge_t;
    typedef typename graph_traits<Graph>::edges_size_type edge_size_t;
    typedef typename
    property_traits<PlanarEmbedding>::value_type embedding_value_t;
    typedef typename embedding_value_t::const_iterator embedding_iterator_t;
    typedef iterator_property_map
    <std::vector<std::size_t>::iterator, EdgeIndexMap> component_map_t;

    edge_size_t n_edges(num_edges(g));
    std::vector<vertex_t> articulation_points;
    std::vector<edge_size_t> component_vector(n_edges);
    component_map_t component_map(component_vector.begin(), em);

    biconnected_components(g, component_map,
                           std::back_inserter(articulation_points));

    typename std::vector<vertex_t>::iterator ap, ap_end;
    ap_end = articulation_points.end();
    for(ap = articulation_points.begin(); ap != ap_end; ++ap)
    {
        vertex_t v(*ap);
        embedding_iterator_t pi = embedding[v].begin();
        embedding_iterator_t pi_end = embedding[v].end();
        edge_size_t previous_component(n_edges + 1);
        vertex_t previous_vertex = graph_traits<Graph>::null_vertex();

        for(; pi != pi_end; ++pi)
        {
            edge_t e(*pi);
            vertex_t e_source(source(e,g));
            vertex_t e_target(target(e,g));

            //Skip self-loops and parallel edges
            if (e_source == e_target || previous_vertex == e_target)
                continue;

            vertex_t current_vertex = e_source == v ? e_target : e_source;
            edge_size_t current_component = component_map[e];
            if (previous_vertex != graph_traits<Graph>::null_vertex() &&
                    current_component != previous_component)
            {
                vis.visit_vertex_pair(current_vertex, previous_vertex, g);
            }
            previous_vertex = current_vertex;
            previous_component = current_component;
        }
    }

}
bool is_straight_line_drawing(const Graph& g,
                              GridPositionMap drawing,
                              VertexIndexMap vm
                             )
{

    typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
    typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
    typedef typename graph_traits<Graph>::edge_descriptor edge_t;
    typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
    typedef typename graph_traits<Graph>::edges_size_type e_size_t;
    typedef typename graph_traits<Graph>::vertices_size_type v_size_t;

    typedef std::size_t x_coord_t;
    typedef std::size_t y_coord_t;
    typedef boost::tuple<edge_t, x_coord_t, y_coord_t> edge_event_t;
    typedef typename std::vector< edge_event_t > edge_event_queue_t;

    typedef tuple<y_coord_t, y_coord_t, x_coord_t, x_coord_t> active_map_key_t;
    typedef edge_t active_map_value_t;
    typedef std::map< active_map_key_t, active_map_value_t > active_map_t;
    typedef typename active_map_t::iterator active_map_iterator_t;


    edge_event_queue_t edge_event_queue;
    active_map_t active_edges;

    edge_iterator_t ei, ei_end;
    for(tie(ei,ei_end) = edges(g); ei != ei_end; ++ei)
    {
        edge_t e(*ei);
        vertex_t s(source(e,g));
        vertex_t t(target(e,g));
        edge_event_queue.push_back
        (make_tuple(e,
                    static_cast<std::size_t>(drawing[s].x),
                    static_cast<std::size_t>(drawing[s].y)
                   )
        );
        edge_event_queue.push_back
        (make_tuple(e,
                    static_cast<std::size_t>(drawing[t].x),
                    static_cast<std::size_t>(drawing[t].y)
                   )
        );
    }

    // Order by edge_event_queue by first, then second coordinate
    // (bucket_sort is a stable sort.)
    bucket_sort(edge_event_queue.begin(), edge_event_queue.end(),
                property_map_tuple_adaptor<edge_event_t, 2>()
               );

    bucket_sort(edge_event_queue.begin(), edge_event_queue.end(),
                property_map_tuple_adaptor<edge_event_t, 1>()
               );

    typedef typename edge_event_queue_t::iterator event_queue_iterator_t;
    event_queue_iterator_t itr_end = edge_event_queue.end();
    for(event_queue_iterator_t itr = edge_event_queue.begin();
            itr != itr_end; ++itr
       )
    {
        edge_t e(get<0>(*itr));
        vertex_t source_v(source(e,g));
        vertex_t target_v(target(e,g));
        if (drawing[source_v].y > drawing[target_v].y)
            std::swap(source_v, target_v);

        active_map_key_t key(get(drawing, source_v).y,
                             get(drawing, target_v).y,
                             get(drawing, source_v).x,
                             get(drawing, target_v).x
                            );

        active_map_iterator_t a_itr = active_edges.find(key);
        if (a_itr == active_edges.end())
        {
            active_edges[key] = e;
        }
        else
        {
            active_map_iterator_t before, after;
            if (a_itr == active_edges.begin())
                before = active_edges.end();
            else
                before = prior(a_itr);
            after = boost::next(a_itr);

            if (before != active_edges.end())
            {

                edge_t f = before->second;
                vertex_t e_source(source(e,g));
                vertex_t e_target(target(e,g));
                vertex_t f_source(source(f,g));
                vertex_t f_target(target(f,g));

                if (intersects(drawing[e_source].x,
                               drawing[e_source].y,
                               drawing[e_target].x,
                               drawing[e_target].y,
                               drawing[f_source].x,
                               drawing[f_source].y,
                               drawing[f_target].x,
                               drawing[f_target].y
                              )
                   )
                    return false;
            }

            if (after != active_edges.end())
            {

                edge_t f = after->second;
                vertex_t e_source(source(e,g));
                vertex_t e_target(target(e,g));
                vertex_t f_source(source(f,g));
                vertex_t f_target(target(f,g));

                if (intersects(drawing[e_source].x,
                               drawing[e_source].y,
                               drawing[e_target].x,
                               drawing[e_target].y,
                               drawing[f_source].x,
                               drawing[f_source].y,
                               drawing[f_target].x,
                               drawing[f_target].y
                              )
                   )
                    return false;
            }

            active_edges.erase(a_itr);

        }
    }

    return true;

}
示例#3
0
void
NavGraph::edge_add_split_intersection(const NavGraphEdge &edge)
{
  std::list<std::pair<cart_coord_2d_t, NavGraphEdge>> intersections;
  const NavGraphNode &n1 = node(edge.from());
  const NavGraphNode &n2 = node(edge.to());

  try {

    for (const NavGraphEdge &e : edges_) {
      cart_coord_2d_t ip;
      if (e.intersection(n1.x(), n1.y(), n2.x(), n2.y(), ip)) {
	// we need to split the edge at the given intersection point,
	// and the new line segments as well
	intersections.push_back(std::make_pair(ip, e));
      }
    }

    std::list<std::list<std::pair<cart_coord_2d_t, NavGraphEdge> >::iterator> deletions;

    for (auto i1 = intersections.begin(); i1 != intersections.end(); ++i1) {
      const std::pair<cart_coord_2d_t, NavGraphEdge> &p1 = *i1;
      const cart_coord_2d_t &c1 = p1.first;
      const NavGraphEdge    &e1 = p1.second;

      const NavGraphNode    &n1_from = node(e1.from());
      const NavGraphNode    &n1_to   = node(e1.to());

      for (auto i2 = std::next(i1); i2 != intersections.end(); ++i2) {
	const std::pair<cart_coord_2d_t, NavGraphEdge> &p2 = *i2;
	const cart_coord_2d_t &c2 = p2.first;
	const NavGraphEdge    &e2 = p2.second;

	if (points_different(c1.x, c1.y, c2.x, c2.y))  continue;

	float d = 1.;
	if (e1.from() == e2.from() || e1.from() == e2.to()) {
	  d = point_dist(n1_from.x(), n1_from.y(), c1.x, c1.y);
	} else if (e1.to() == e2.to() || e1.to() == e2.from()) {
	  d = point_dist(n1_to.x(), n1_to.y(), c1.x, c1.y);
	}
	if (d < 1e-4) {
	  // the intersection point is the same as a common end
	  // point of the two edges, only keep it once
	  deletions.push_back(i1);
	  break;
	}
      }
    }
    for (auto d = deletions.rbegin(); d != deletions.rend(); ++d) {
      intersections.erase(*d);
    }

    if (intersections.empty()) {
      NavGraphEdge e(edge);
      e.set_property("created-for", edge.from() + "--" + edge.to());
      add_edge(e, EDGE_FORCE);
    } else {
      Eigen::Vector2f e_origin(n1.x(), n1.y());
      Eigen::Vector2f e_target(n2.x(), n2.y());
      Eigen::Vector2f e_dir = (e_target - e_origin).normalized();

      intersections.sort([&e_origin, &e_dir](const std::pair<cart_coord_2d_t, NavGraphEdge> &p1,
					     const std::pair<cart_coord_2d_t, NavGraphEdge> &p2)
			 {
			   const Eigen::Vector2f p1p(p1.first.x, p1.first.y);
			   const Eigen::Vector2f p2p(p2.first.x, p2.first.y);
			   const float k1 = e_dir.dot(p1p - e_origin);
			   const float k2 = e_dir.dot(p2p - e_origin);
			   return k1 < k2;
			 });

      std::string     en_from = edge.from();
      cart_coord_2d_t ec_from(n1.x(), n1.y());
      std::string     prev_to;
      for (const auto &i : intersections) {
	const cart_coord_2d_t &c = i.first;
	const NavGraphEdge    &e = i.second;

	// add intersection point (if necessary)
	NavGraphNode ip = closest_node(c.x, c.y);
	if (! ip || points_different(c.x, c.y, ip.x(), ip.y())) {
	  ip = NavGraphNode(gen_unique_name(), c.x, c.y);
	  add_node(ip);
	}

	// if neither edge end node is the intersection point, split the edge
	if (ip.name() != e.from() && ip.name() != e.to()) {
	  NavGraphEdge e1(e.from(), ip.name(), e.is_directed());
	  NavGraphEdge e2(ip.name(), e.to(), e.is_directed());
	  remove_edge(e);
	  e1.set_properties(e.properties());
	  e2.set_properties(e.properties());
	  add_edge(e1, EDGE_FORCE, /* allow existing */ true);
	  add_edge(e2, EDGE_FORCE, /* allow existing */ true);

	  // this is a special case: we might intersect an edge
	  // which has the same end node and thus the new edge
	  // from the intersection node to the end node would
	  // be added twice
	  prev_to = e.to();
	}
      
	// add segment edge
	if (en_from != ip.name() && prev_to != ip.name()) {
	  NavGraphEdge e3(en_from, ip.name(), edge.is_directed());
	  e3.set_property("created-for", en_from + "--" + ip.name());
	  add_edge(e3, EDGE_FORCE, /* allow existing */ true);

	}

	en_from = ip.name();
	ec_from = c;
      }

      if (en_from != edge.to()) {
	NavGraphEdge e3(en_from, edge.to(), edge.is_directed());
	e3.set_property("created-for", en_from + "--" + edge.to());
	add_edge(e3, EDGE_FORCE, /* allow existing */ true);
      }
    }
    
  } catch (Exception &ex) {
    throw Exception("Failed to add edge %s-%s%s: %s",
		    edge.from().c_str(), edge.is_directed() ? ">" : "-", edge.to().c_str(),
		    ex.what_no_backtrace());
  }
}