segment_utils.hpp 4.8 KB

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