is_straight_line_drawing.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. //=======================================================================
  2. // Copyright 2007 Aaron Windsor
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //=======================================================================
  8. #ifndef __IS_STRAIGHT_LINE_DRAWING_HPP__
  9. #define __IS_STRAIGHT_LINE_DRAWING_HPP__
  10. #include <boost/config.hpp>
  11. #include <boost/next_prior.hpp>
  12. #include <boost/tuple/tuple.hpp>
  13. #include <boost/tuple/tuple_comparison.hpp>
  14. #include <boost/property_map/property_map.hpp>
  15. #include <boost/graph/properties.hpp>
  16. #include <boost/graph/planar_detail/bucket_sort.hpp>
  17. #include <boost/geometry/algorithms/crosses.hpp>
  18. #include <boost/geometry/geometries/linestring.hpp>
  19. #include <boost/geometry/core/coordinate_type.hpp>
  20. #include <boost/numeric/conversion/cast.hpp>
  21. #include <algorithm>
  22. #include <vector>
  23. #include <map>
  24. namespace boost
  25. {
  26. // Overload of make from Boost.Geometry.
  27. template<typename Geometry, typename Graph, typename GridPositionMap>
  28. Geometry make(typename graph_traits<Graph>::edge_descriptor e,
  29. Graph const &g,
  30. GridPositionMap const &drawing)
  31. {
  32. auto e_source(source(e, g));
  33. auto e_target(target(e, g));
  34. using Float = typename geometry::coordinate_type<Geometry>::type;
  35. return {{numeric_cast<Float>(drawing[e_source].x), numeric_cast<Float>(drawing[e_source].y)},
  36. {numeric_cast<Float>(drawing[e_target].x), numeric_cast<Float>(drawing[e_target].y)}};
  37. }
  38. // Overload of crosses from Boost.Geometry.
  39. template<typename Graph, typename GridPositionMap>
  40. bool crosses(typename graph_traits<Graph>::edge_descriptor e,
  41. typename graph_traits<Graph>::edge_descriptor f,
  42. Graph const &g,
  43. GridPositionMap const &drawing)
  44. {
  45. using geometry::crosses;
  46. using geometry::model::linestring;
  47. using geometry::model::d2::point_xy;
  48. using linestring2d = geometry::model::linestring<geometry::model::d2::point_xy<double>>;
  49. return crosses(make<linestring2d>(e, g, drawing),
  50. make<linestring2d>(f, g, drawing));
  51. }
  52. template < typename Graph, typename GridPositionMap, typename VertexIndexMap >
  53. bool is_straight_line_drawing(
  54. const Graph& g, GridPositionMap drawing, VertexIndexMap)
  55. {
  56. typedef typename graph_traits< Graph >::vertex_descriptor vertex_t;
  57. typedef typename graph_traits< Graph >::edge_descriptor edge_t;
  58. typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t;
  59. typedef std::size_t x_coord_t;
  60. typedef std::size_t y_coord_t;
  61. typedef boost::tuple< edge_t, x_coord_t, y_coord_t > edge_event_t;
  62. typedef typename std::vector< edge_event_t > edge_event_queue_t;
  63. typedef tuple< y_coord_t, y_coord_t, x_coord_t, x_coord_t >
  64. active_map_key_t;
  65. typedef edge_t active_map_value_t;
  66. typedef std::map< active_map_key_t, active_map_value_t > active_map_t;
  67. typedef typename active_map_t::iterator active_map_iterator_t;
  68. edge_event_queue_t edge_event_queue;
  69. active_map_t active_edges;
  70. edge_iterator_t ei, ei_end;
  71. for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
  72. {
  73. edge_t e(*ei);
  74. vertex_t s(source(e, g));
  75. vertex_t t(target(e, g));
  76. edge_event_queue.push_back(
  77. make_tuple(e, static_cast< std::size_t >(drawing[s].x),
  78. static_cast< std::size_t >(drawing[s].y)));
  79. edge_event_queue.push_back(
  80. make_tuple(e, static_cast< std::size_t >(drawing[t].x),
  81. static_cast< std::size_t >(drawing[t].y)));
  82. }
  83. // Order by edge_event_queue by first, then second coordinate
  84. // (bucket_sort is a stable sort.)
  85. bucket_sort(edge_event_queue.begin(), edge_event_queue.end(),
  86. property_map_tuple_adaptor< edge_event_t, 2 >());
  87. bucket_sort(edge_event_queue.begin(), edge_event_queue.end(),
  88. property_map_tuple_adaptor< edge_event_t, 1 >());
  89. typedef typename edge_event_queue_t::iterator event_queue_iterator_t;
  90. event_queue_iterator_t itr_end = edge_event_queue.end();
  91. for (event_queue_iterator_t itr = edge_event_queue.begin(); itr != itr_end;
  92. ++itr)
  93. {
  94. edge_t e(get< 0 >(*itr));
  95. vertex_t source_v(source(e, g));
  96. vertex_t target_v(target(e, g));
  97. if (drawing[source_v].y > drawing[target_v].y)
  98. std::swap(source_v, target_v);
  99. active_map_key_t key(get(drawing, source_v).y, get(drawing, target_v).y,
  100. get(drawing, source_v).x, get(drawing, target_v).x);
  101. active_map_iterator_t a_itr = active_edges.find(key);
  102. if (a_itr == active_edges.end())
  103. {
  104. active_edges[key] = e;
  105. }
  106. else
  107. {
  108. active_map_iterator_t before, after;
  109. if (a_itr == active_edges.begin())
  110. before = active_edges.end();
  111. else
  112. before = prior(a_itr);
  113. after = boost::next(a_itr);
  114. if (before != active_edges.end())
  115. {
  116. edge_t f = before->second;
  117. if (crosses(e, f, g, drawing))
  118. return false;
  119. }
  120. if (after != active_edges.end())
  121. {
  122. edge_t f = after->second;
  123. if (crosses(e, f, g, drawing))
  124. return false;
  125. }
  126. active_edges.erase(a_itr);
  127. }
  128. }
  129. return true;
  130. }
  131. template < typename Graph, typename GridPositionMap >
  132. bool is_straight_line_drawing(const Graph& g, GridPositionMap drawing)
  133. {
  134. return is_straight_line_drawing(g, drawing, get(vertex_index, g));
  135. }
  136. }
  137. #endif // __IS_STRAIGHT_LINE_DRAWING_HPP__