box_in_box.hpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
  5. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
  6. // This file was modified by Oracle on 2015, 2016, 2017.
  7. // Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
  8. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  9. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  10. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  11. // Use, modification and distribution is subject to the Boost Software License,
  12. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  13. // http://www.boost.org/LICENSE_1_0.txt)
  14. #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP
  15. #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP
  16. #include <boost/geometry/core/access.hpp>
  17. #include <boost/geometry/core/coordinate_dimension.hpp>
  18. #include <boost/geometry/strategies/covered_by.hpp>
  19. #include <boost/geometry/strategies/within.hpp>
  20. #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
  21. namespace boost { namespace geometry { namespace strategy
  22. {
  23. namespace within
  24. {
  25. struct box_within_coord
  26. {
  27. template <typename BoxContainedValue, typename BoxContainingValue>
  28. static inline bool apply(BoxContainedValue const& bed_min,
  29. BoxContainedValue const& bed_max,
  30. BoxContainingValue const& bing_min,
  31. BoxContainingValue const& bing_max)
  32. {
  33. return bing_min <= bed_min && bed_max <= bing_max // contained in containing
  34. && bed_min < bed_max; // interiors overlap
  35. }
  36. };
  37. struct box_covered_by_coord
  38. {
  39. template <typename BoxContainedValue, typename BoxContainingValue>
  40. static inline bool apply(BoxContainedValue const& bed_min,
  41. BoxContainedValue const& bed_max,
  42. BoxContainingValue const& bing_min,
  43. BoxContainingValue const& bing_max)
  44. {
  45. return bed_min >= bing_min && bed_max <= bing_max;
  46. }
  47. };
  48. template <typename Geometry, std::size_t Dimension, typename CSTag>
  49. struct box_within_range
  50. : box_within_coord
  51. {};
  52. template <typename Geometry, std::size_t Dimension, typename CSTag>
  53. struct box_covered_by_range
  54. : box_covered_by_coord
  55. {};
  56. struct box_within_longitude_diff
  57. {
  58. template <typename CalcT>
  59. static inline bool apply(CalcT const& diff_ed)
  60. {
  61. return diff_ed > CalcT(0);
  62. }
  63. };
  64. struct box_covered_by_longitude_diff
  65. {
  66. template <typename CalcT>
  67. static inline bool apply(CalcT const&)
  68. {
  69. return true;
  70. }
  71. };
  72. template <typename Geometry,
  73. typename CoordCheck,
  74. typename InteriorCheck>
  75. struct box_longitude_range
  76. {
  77. template <typename BoxContainedValue, typename BoxContainingValue>
  78. static inline bool apply(BoxContainedValue const& bed_min,
  79. BoxContainedValue const& bed_max,
  80. BoxContainingValue const& bing_min,
  81. BoxContainingValue const& bing_max)
  82. {
  83. typedef typename select_most_precise
  84. <
  85. BoxContainedValue,
  86. BoxContainingValue
  87. >::type calc_t;
  88. typedef typename coordinate_system<Geometry>::type::units units_t;
  89. typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
  90. if (CoordCheck::apply(bed_min, bed_max, bing_min, bing_max))
  91. {
  92. return true;
  93. }
  94. // min <= max <=> diff >= 0
  95. calc_t const diff_ed = bed_max - bed_min;
  96. calc_t const diff_ing = bing_max - bing_min;
  97. // if containing covers the whole globe it contains all
  98. if (diff_ing >= constants::period())
  99. {
  100. return true;
  101. }
  102. // if containing is smaller it cannot contain
  103. // and check interior (within vs covered_by)
  104. if (diff_ing < diff_ed || ! InteriorCheck::apply(diff_ed))
  105. {
  106. return false;
  107. }
  108. // calculate positive longitude translation with bing_min as origin
  109. calc_t const diff_min = math::longitude_distance_unsigned<units_t>(bing_min, bed_min);
  110. // max of contained translated into the containing origin must be lesser than max of containing
  111. return bing_min + diff_min + diff_ed <= bing_max
  112. /*|| bing_max - diff_min - diff_ed >= bing_min*/;
  113. }
  114. };
  115. // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
  116. template <typename Geometry>
  117. struct box_within_range<Geometry, 0, spherical_tag>
  118. : box_longitude_range<Geometry, box_within_coord, box_within_longitude_diff>
  119. {};
  120. template <typename Geometry>
  121. struct box_covered_by_range<Geometry, 0, spherical_tag>
  122. : box_longitude_range<Geometry, box_covered_by_coord, box_covered_by_longitude_diff>
  123. {};
  124. template
  125. <
  126. template <typename, std::size_t, typename> class SubStrategy,
  127. typename Box1,
  128. typename Box2,
  129. std::size_t Dimension,
  130. std::size_t DimensionCount
  131. >
  132. struct relate_box_box_loop
  133. {
  134. static inline bool apply(Box1 const& b_contained, Box2 const& b_containing)
  135. {
  136. assert_dimension_equal<Box1, Box2>();
  137. typedef typename tag_cast<typename cs_tag<Box1>::type, spherical_tag>::type cs_tag_t;
  138. if (! SubStrategy<Box1, Dimension, cs_tag_t>::apply(
  139. get<min_corner, Dimension>(b_contained),
  140. get<max_corner, Dimension>(b_contained),
  141. get<min_corner, Dimension>(b_containing),
  142. get<max_corner, Dimension>(b_containing)
  143. )
  144. )
  145. {
  146. return false;
  147. }
  148. return relate_box_box_loop
  149. <
  150. SubStrategy,
  151. Box1, Box2,
  152. Dimension + 1, DimensionCount
  153. >::apply(b_contained, b_containing);
  154. }
  155. };
  156. template
  157. <
  158. template <typename, std::size_t, typename> class SubStrategy,
  159. typename Box1,
  160. typename Box2,
  161. std::size_t DimensionCount
  162. >
  163. struct relate_box_box_loop<SubStrategy, Box1, Box2, DimensionCount, DimensionCount>
  164. {
  165. static inline bool apply(Box1 const& , Box2 const& )
  166. {
  167. return true;
  168. }
  169. };
  170. template
  171. <
  172. typename Box1,
  173. typename Box2,
  174. template <typename, std::size_t, typename> class SubStrategy = box_within_range
  175. >
  176. struct box_in_box
  177. {
  178. static inline bool apply(Box1 const& box1, Box2 const& box2)
  179. {
  180. return relate_box_box_loop
  181. <
  182. SubStrategy,
  183. Box1, Box2, 0, dimension<Box1>::type::value
  184. >::apply(box1, box2);
  185. }
  186. };
  187. } // namespace within
  188. #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  189. namespace within { namespace services
  190. {
  191. template <typename BoxContained, typename BoxContaining>
  192. struct default_strategy
  193. <
  194. BoxContained, BoxContaining,
  195. box_tag, box_tag,
  196. areal_tag, areal_tag,
  197. cartesian_tag, cartesian_tag
  198. >
  199. {
  200. typedef within::box_in_box<BoxContained, BoxContaining> type;
  201. };
  202. // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
  203. template <typename BoxContained, typename BoxContaining>
  204. struct default_strategy
  205. <
  206. BoxContained, BoxContaining,
  207. box_tag, box_tag,
  208. areal_tag, areal_tag,
  209. spherical_tag, spherical_tag
  210. >
  211. {
  212. typedef within::box_in_box<BoxContained, BoxContaining> type;
  213. };
  214. }} // namespace within::services
  215. namespace covered_by { namespace services
  216. {
  217. template <typename BoxContained, typename BoxContaining>
  218. struct default_strategy
  219. <
  220. BoxContained, BoxContaining,
  221. box_tag, box_tag,
  222. areal_tag, areal_tag,
  223. cartesian_tag, cartesian_tag
  224. >
  225. {
  226. typedef within::box_in_box
  227. <
  228. BoxContained, BoxContaining,
  229. within::box_covered_by_range
  230. > type;
  231. };
  232. // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
  233. template <typename BoxContained, typename BoxContaining>
  234. struct default_strategy
  235. <
  236. BoxContained, BoxContaining,
  237. box_tag, box_tag,
  238. areal_tag, areal_tag,
  239. spherical_tag, spherical_tag
  240. >
  241. {
  242. typedef within::box_in_box
  243. <
  244. BoxContained, BoxContaining,
  245. within::box_covered_by_range
  246. > type;
  247. };
  248. }} // namespace covered_by::services
  249. #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  250. }}} // namespace boost::geometry::strategy
  251. #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP