within_no_turns.hpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  5. // This file was modified by Oracle on 2013.
  6. // Modifications copyright (c) 2013, Oracle and/or its affiliates.
  7. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  8. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  9. // Use, modification and distribution is subject to the Boost Software License,
  10. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt)
  12. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_WITHIN_NO_TURNS_HPP
  13. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_WITHIN_NO_TURNS_HPP
  14. #include <boost/geometry/algorithms/detail/point_on_border.hpp>
  15. #include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
  16. namespace boost { namespace geometry {
  17. #ifndef DOXYGEN_NO_DETAIL
  18. namespace detail_dispatch { namespace within {
  19. // returns true if G1 is within G2
  20. // this function should be called only if there are no intersection points
  21. // otherwise it may return invalid result
  22. // e.g. when non-first point of G1 is outside G2 or when some rings of G1 are the same as rings of G2
  23. template <typename Geometry1,
  24. typename Geometry2,
  25. typename Tag1 = typename geometry::tag<Geometry1>::type,
  26. typename Tag2 = typename geometry::tag<Geometry2>::type>
  27. struct within_no_turns
  28. {
  29. template <typename Strategy> static inline
  30. bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
  31. {
  32. typedef typename geometry::point_type<Geometry1>::type point1_type;
  33. point1_type p;
  34. if ( !geometry::point_on_border(p, geometry1) )
  35. return false;
  36. return detail::within::point_in_geometry(p, geometry2, strategy) >= 0;
  37. }
  38. };
  39. template <typename Geometry1, typename Geometry2>
  40. struct within_no_turns<Geometry1, Geometry2, ring_tag, polygon_tag>
  41. {
  42. template <typename Strategy> static inline
  43. bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
  44. {
  45. typedef typename geometry::point_type<Geometry1>::type point1_type;
  46. typedef typename geometry::point_type<Geometry2>::type point2_type;
  47. point1_type p;
  48. if ( !geometry::point_on_border(p, geometry1) )
  49. return false;
  50. // check if one of ring points is outside the polygon
  51. if ( detail::within::point_in_geometry(p, geometry2, strategy) < 0 )
  52. return false;
  53. // Now check if holes of G2 aren't inside G1
  54. typedef typename boost::range_const_iterator
  55. <
  56. typename geometry::interior_type<Geometry2>::type
  57. >::type iterator;
  58. for ( iterator it = boost::begin(geometry::interior_rings(geometry2)) ;
  59. it != boost::end(geometry::interior_rings(geometry2)) ;
  60. ++it )
  61. {
  62. point2_type p;
  63. if ( !geometry::point_on_border(p, *it) )
  64. return false;
  65. if ( detail::within::point_in_geometry(p, geometry1, strategy) > 0 )
  66. return false;
  67. }
  68. return true;
  69. }
  70. };
  71. template <typename Geometry1, typename Geometry2>
  72. struct within_no_turns<Geometry1, Geometry2, polygon_tag, polygon_tag>
  73. {
  74. template <typename Strategy> static inline
  75. bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
  76. {
  77. typedef typename geometry::point_type<Geometry1>::type point1_type;
  78. typedef typename geometry::point_type<Geometry2>::type point2_type;
  79. point1_type p;
  80. if ( !geometry::point_on_border(p, geometry1) )
  81. return false;
  82. // check if one of ring points is outside the polygon
  83. if ( detail::within::point_in_geometry(p, geometry2, strategy) < 0 )
  84. return false;
  85. // Now check if holes of G2 aren't inside G1
  86. typedef typename boost::range_const_iterator
  87. <
  88. typename geometry::interior_type<Geometry2>::type
  89. >::type iterator2;
  90. for ( iterator2 it = boost::begin(geometry::interior_rings(geometry2)) ;
  91. it != boost::end(geometry::interior_rings(geometry2)) ;
  92. ++it )
  93. {
  94. point2_type p2;
  95. if ( !geometry::point_on_border(p2, *it) )
  96. return false;
  97. // if the hole of G2 is inside G1
  98. if ( detail::within::point_in_geometry(p2, geometry1, strategy) > 0 )
  99. {
  100. // if it's also inside one of the G1 holes, it's ok
  101. bool ok = false;
  102. typedef typename boost::range_const_iterator
  103. <
  104. typename geometry::interior_type<Geometry1>::type
  105. >::type iterator1;
  106. for ( iterator1 it1 = boost::begin(geometry::interior_rings(geometry1)) ;
  107. it1 != boost::end(geometry::interior_rings(geometry1)) ;
  108. ++it1 )
  109. {
  110. if ( detail::within::point_in_geometry(p2, *it1, strategy) < 0 )
  111. {
  112. ok = true;
  113. break;
  114. }
  115. }
  116. if ( !ok )
  117. return false;
  118. }
  119. }
  120. return true;
  121. }
  122. };
  123. template <typename Geometry1,
  124. typename Geometry2,
  125. typename Tag1 = typename geometry::tag<Geometry1>::type,
  126. typename Tag2 = typename geometry::tag<Geometry2>::type,
  127. bool IsMulti1 = boost::is_base_of<geometry::multi_tag, Tag1>::value,
  128. bool IsMulti2 = boost::is_base_of<geometry::multi_tag, Tag2>::value>
  129. struct within_no_turns_multi
  130. {
  131. template <typename Strategy> static inline
  132. bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
  133. {
  134. return within_no_turns<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
  135. }
  136. };
  137. template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>
  138. struct within_no_turns_multi<Geometry1, Geometry2, Tag1, Tag2, true, false>
  139. {
  140. template <typename Strategy> static inline
  141. bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
  142. {
  143. // All values of G1 must be inside G2
  144. typedef typename boost::range_value<Geometry1>::type subgeometry1;
  145. typedef typename boost::range_const_iterator<Geometry1>::type iterator;
  146. for ( iterator it = boost::begin(geometry1) ; it != boost::end(geometry1) ; ++it )
  147. {
  148. if ( !within_no_turns<subgeometry1, Geometry2>::apply(*it, geometry2, strategy) )
  149. return false;
  150. }
  151. return true;
  152. }
  153. };
  154. template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>
  155. struct within_no_turns_multi<Geometry1, Geometry2, Tag1, Tag2, false, true>
  156. {
  157. template <typename Strategy> static inline
  158. bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
  159. {
  160. // G1 must be within at least one value of G2
  161. typedef typename boost::range_value<Geometry2>::type subgeometry2;
  162. typedef typename boost::range_const_iterator<Geometry2>::type iterator;
  163. for ( iterator it = boost::begin(geometry2) ; it != boost::end(geometry2) ; ++it )
  164. {
  165. if ( within_no_turns<Geometry1, subgeometry2>::apply(geometry1, *it, strategy) )
  166. return true;
  167. }
  168. return false;
  169. }
  170. };
  171. template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>
  172. struct within_no_turns_multi<Geometry1, Geometry2, Tag1, Tag2, true, true>
  173. {
  174. template <typename Strategy> static inline
  175. bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
  176. {
  177. // each value of G1 must be inside at least one value of G2
  178. typedef typename boost::range_value<Geometry1>::type subgeometry1;
  179. typedef typename boost::range_const_iterator<Geometry1>::type iterator;
  180. for ( iterator it = boost::begin(geometry1) ; it != boost::end(geometry1) ; ++it )
  181. {
  182. if ( !within_no_turns_multi<subgeometry1, Geometry2>::apply(*it, geometry2, strategy) )
  183. return false;
  184. }
  185. return true;
  186. }
  187. };
  188. }} // namespace detail_dispatch::within
  189. namespace detail { namespace within {
  190. template <typename Geometry1, typename Geometry2, typename Strategy>
  191. inline bool within_no_turns(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
  192. {
  193. return detail_dispatch::within::within_no_turns_multi<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
  194. }
  195. }} // namespace detail::within
  196. #endif // DOXYGEN_NO_DETAIL
  197. }} // namespace boost::geometry
  198. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_WITHIN_NO_TURNS_HPP