segment_utils.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. Copyright 2012 Lucanus Simonson
  3. Use, modification and distribution are subject to the Boost Software License,
  4. Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. */
  7. #ifndef BOOST_POLYGON_SEGMENT_UTILS_HPP
  8. #define BOOST_POLYGON_SEGMENT_UTILS_HPP
  9. #include <set>
  10. #include <vector>
  11. #include <utility>
  12. namespace boost {
  13. namespace polygon {
  14. template <typename Segment, typename SegmentIterator>
  15. typename enable_if<
  16. typename gtl_and<
  17. typename gtl_if<
  18. typename is_segment_concept<
  19. typename geometry_concept<
  20. typename std::iterator_traits<SegmentIterator>::value_type
  21. >::type
  22. >::type
  23. >::type,
  24. typename gtl_if<
  25. typename is_segment_concept<
  26. typename geometry_concept<Segment>::type
  27. >::type
  28. >::type
  29. >::type,
  30. void
  31. >::type
  32. intersect_segments(
  33. std::vector<std::pair<std::size_t, Segment> >& result,
  34. SegmentIterator first, SegmentIterator last) {
  35. typedef typename segment_traits<Segment>::coordinate_type Unit;
  36. typedef typename scanline_base<Unit>::Point Point;
  37. typedef typename scanline_base<Unit>::half_edge half_edge;
  38. typedef int segment_id;
  39. std::vector<std::pair<half_edge, segment_id> > half_edges;
  40. std::vector<std::pair<half_edge, segment_id> > half_edges_out;
  41. segment_id id_in = 0;
  42. half_edges.reserve(std::distance(first, last));
  43. for (; first != last; ++first) {
  44. Point l, h;
  45. assign(l, low(*first));
  46. assign(h, high(*first));
  47. half_edges.push_back(std::make_pair(half_edge(l, h), id_in++));
  48. }
  49. half_edges_out.reserve(half_edges.size());
  50. // Apparently no need to pre-sort data when calling validate_scan.
  51. if (half_edges.size() != 0) {
  52. line_intersection<Unit>::validate_scan(
  53. half_edges_out, half_edges.begin(), half_edges.end());
  54. }
  55. result.reserve(result.size() + half_edges_out.size());
  56. for (std::size_t i = 0; i < half_edges_out.size(); ++i) {
  57. std::size_t id = (std::size_t)(half_edges_out[i].second);
  58. Point l = half_edges_out[i].first.first;
  59. Point h = half_edges_out[i].first.second;
  60. result.push_back(std::make_pair(id, construct<Segment>(l, h)));
  61. }
  62. }
  63. template <typename SegmentContainer, typename SegmentIterator>
  64. typename enable_if<
  65. typename gtl_and<
  66. typename gtl_if<
  67. typename is_segment_concept<
  68. typename geometry_concept<
  69. typename std::iterator_traits<SegmentIterator>::value_type
  70. >::type
  71. >::type
  72. >::type,
  73. typename gtl_if<
  74. typename is_segment_concept<
  75. typename geometry_concept<
  76. typename SegmentContainer::value_type
  77. >::type
  78. >::type
  79. >::type
  80. >::type,
  81. void
  82. >::type
  83. intersect_segments(
  84. SegmentContainer& result,
  85. SegmentIterator first,
  86. SegmentIterator last) {
  87. typedef typename SegmentContainer::value_type segment_type;
  88. typedef typename segment_traits<segment_type>::coordinate_type Unit;
  89. typedef typename scanline_base<Unit>::Point Point;
  90. typedef typename scanline_base<Unit>::half_edge half_edge;
  91. typedef int segment_id;
  92. std::vector<std::pair<half_edge, segment_id> > half_edges;
  93. std::vector<std::pair<half_edge, segment_id> > half_edges_out;
  94. segment_id id_in = 0;
  95. half_edges.reserve(std::distance(first, last));
  96. for (; first != last; ++first) {
  97. Point l, h;
  98. assign(l, low(*first));
  99. assign(h, high(*first));
  100. half_edges.push_back(std::make_pair(half_edge(l, h), id_in++));
  101. }
  102. half_edges_out.reserve(half_edges.size());
  103. // Apparently no need to pre-sort data when calling validate_scan.
  104. if (half_edges.size() != 0) {
  105. line_intersection<Unit>::validate_scan(
  106. half_edges_out, half_edges.begin(), half_edges.end());
  107. }
  108. result.reserve(result.size() + half_edges_out.size());
  109. for (std::size_t i = 0; i < half_edges_out.size(); ++i) {
  110. Point l = half_edges_out[i].first.first;
  111. Point h = half_edges_out[i].first.second;
  112. result.push_back(construct<segment_type>(l, h));
  113. }
  114. }
  115. template <typename Rectangle, typename SegmentIterator>
  116. typename enable_if<
  117. typename gtl_and<
  118. typename gtl_if<
  119. typename is_rectangle_concept<
  120. typename geometry_concept<Rectangle>::type
  121. >::type
  122. >::type,
  123. typename gtl_if<
  124. typename is_segment_concept<
  125. typename geometry_concept<
  126. typename std::iterator_traits<SegmentIterator>::value_type
  127. >::type
  128. >::type
  129. >::type
  130. >::type,
  131. bool
  132. >::type
  133. envelope_segments(
  134. Rectangle& rect,
  135. SegmentIterator first,
  136. SegmentIterator last) {
  137. for (SegmentIterator it = first; it != last; ++it) {
  138. if (it == first) {
  139. set_points(rect, low(*it), high(*it));
  140. } else {
  141. encompass(rect, low(*it));
  142. encompass(rect, high(*it));
  143. }
  144. }
  145. return first != last;
  146. }
  147. } // polygon
  148. } // boost
  149. #endif // BOOST_POLYGON_SEGMENT_UTILS_HPP