range_in_geometry.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Boost.Geometry
  2. // Copyright (c) 2017-2022 Oracle and/or its affiliates.
  3. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  4. // Use, modification and distribution is subject to the Boost Software License,
  5. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RANGE_IN_GEOMETRY_HPP
  8. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RANGE_IN_GEOMETRY_HPP
  9. #include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
  10. #include <boost/geometry/core/tags.hpp>
  11. #include <boost/geometry/iterators/point_iterator.hpp>
  12. namespace boost { namespace geometry
  13. {
  14. #ifndef DOXYGEN_NO_DETAIL
  15. namespace detail { namespace overlay
  16. {
  17. template
  18. <
  19. typename Geometry,
  20. typename Tag = typename geometry::tag<Geometry>::type
  21. >
  22. struct points_range
  23. {
  24. typedef geometry::point_iterator<Geometry const> iterator_type;
  25. explicit points_range(Geometry const& geometry)
  26. : m_geometry(geometry)
  27. {}
  28. iterator_type begin() const
  29. {
  30. return geometry::points_begin(m_geometry);
  31. }
  32. iterator_type end() const
  33. {
  34. return geometry::points_end(m_geometry);
  35. }
  36. Geometry const& m_geometry;
  37. };
  38. // Specialized because point_iterator doesn't support boxes
  39. template <typename Box>
  40. struct points_range<Box, box_tag>
  41. {
  42. typedef typename geometry::point_type<Box>::type point_type;
  43. typedef const point_type * iterator_type;
  44. explicit points_range(Box const& box)
  45. {
  46. detail::assign_box_corners(box,
  47. m_corners[0], m_corners[1], m_corners[2], m_corners[3]);
  48. }
  49. iterator_type begin() const
  50. {
  51. return m_corners;
  52. }
  53. iterator_type end() const
  54. {
  55. return m_corners + 4;
  56. }
  57. point_type m_corners[4];
  58. };
  59. template
  60. <
  61. typename Geometry,
  62. typename Tag = typename geometry::tag<Geometry>::type
  63. >
  64. struct point_in_geometry_helper
  65. {
  66. template <typename Point, typename Strategy>
  67. static inline int apply(Point const& point, Geometry const& geometry,
  68. Strategy const& strategy)
  69. {
  70. return detail::within::point_in_geometry(point, geometry, strategy);
  71. }
  72. };
  73. // Specialized because point_in_geometry doesn't support Boxes
  74. template <typename Box>
  75. struct point_in_geometry_helper<Box, box_tag>
  76. {
  77. template <typename Point, typename Strategy>
  78. static inline int apply(Point const& point, Box const& box,
  79. Strategy const& strategy)
  80. {
  81. return geometry::covered_by(point, box, strategy) ? 1 : -1;
  82. }
  83. };
  84. // This function returns
  85. // when it finds a point of geometry1 inside or outside geometry2
  86. template <typename Geometry1, typename Geometry2, typename Strategy>
  87. static inline int range_in_geometry(Geometry1 const& geometry1,
  88. Geometry2 const& geometry2,
  89. Strategy const& strategy,
  90. bool skip_first = false)
  91. {
  92. int result = 0;
  93. points_range<Geometry1> points(geometry1);
  94. typedef typename points_range<Geometry1>::iterator_type iterator_type;
  95. iterator_type const end = points.end();
  96. iterator_type it = points.begin();
  97. if (it == end)
  98. {
  99. return result;
  100. }
  101. else if (skip_first)
  102. {
  103. ++it;
  104. }
  105. for ( ; it != end; ++it)
  106. {
  107. result = point_in_geometry_helper<Geometry2>::apply(*it, geometry2, strategy);
  108. if (result != 0)
  109. {
  110. return result;
  111. }
  112. }
  113. // all points contained entirely by the boundary
  114. return result;
  115. }
  116. // This function returns if first_point1 is inside or outside geometry2 or
  117. // when it finds a point of geometry1 inside or outside geometry2
  118. template <typename Point1, typename Geometry1, typename Geometry2, typename Strategy>
  119. inline int range_in_geometry(Point1 const& first_point1,
  120. Geometry1 const& geometry1,
  121. Geometry2 const& geometry2,
  122. Strategy const& strategy)
  123. {
  124. // check a point on border of geometry1 first
  125. int result = point_in_geometry_helper<Geometry2>::apply(first_point1, geometry2, strategy);
  126. if (result == 0)
  127. {
  128. // if a point is on boundary of geometry2
  129. // check points of geometry1 until point inside/outside is found
  130. // NOTE: skip first point because it should be already tested above
  131. result = range_in_geometry(geometry1, geometry2, strategy, true);
  132. }
  133. return result;
  134. }
  135. }} // namespace detail::overlay
  136. #endif // DOXYGEN_NO_DETAIL
  137. }} // namespace boost::geometry
  138. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RANGE_IN_GEOMETRY_HPP