box_in_box.hpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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-2020.
  7. // Modifications copyright (c) 2016-2020, 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. #ifndef DOXYGEN_NO_DETAIL
  26. namespace detail
  27. {
  28. struct box_within_coord
  29. {
  30. template <typename BoxContainedValue, typename BoxContainingValue>
  31. static inline bool apply(BoxContainedValue const& bed_min,
  32. BoxContainedValue const& bed_max,
  33. BoxContainingValue const& bing_min,
  34. BoxContainingValue const& bing_max)
  35. {
  36. return bing_min <= bed_min && bed_max <= bing_max // contained in containing
  37. && bed_min < bed_max; // interiors overlap
  38. }
  39. };
  40. struct box_covered_by_coord
  41. {
  42. template <typename BoxContainedValue, typename BoxContainingValue>
  43. static inline bool apply(BoxContainedValue const& bed_min,
  44. BoxContainedValue const& bed_max,
  45. BoxContainingValue const& bing_min,
  46. BoxContainingValue const& bing_max)
  47. {
  48. return bed_min >= bing_min && bed_max <= bing_max;
  49. }
  50. };
  51. struct box_within_longitude_diff
  52. {
  53. template <typename CalcT>
  54. static inline bool apply(CalcT const& diff_ed)
  55. {
  56. return diff_ed > CalcT(0);
  57. }
  58. };
  59. struct box_covered_by_longitude_diff
  60. {
  61. template <typename CalcT>
  62. static inline bool apply(CalcT const&)
  63. {
  64. return true;
  65. }
  66. };
  67. template <typename Geometry,
  68. typename CoordCheck,
  69. typename InteriorCheck>
  70. struct box_longitude_range
  71. {
  72. template <typename BoxContainedValue, typename BoxContainingValue>
  73. static inline bool apply(BoxContainedValue const& bed_min,
  74. BoxContainedValue const& bed_max,
  75. BoxContainingValue const& bing_min,
  76. BoxContainingValue const& bing_max)
  77. {
  78. typedef typename select_most_precise
  79. <
  80. BoxContainedValue,
  81. BoxContainingValue
  82. >::type calc_t;
  83. typedef typename geometry::detail::cs_angular_units<Geometry>::type units_t;
  84. typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
  85. if (CoordCheck::apply(bed_min, bed_max, bing_min, bing_max))
  86. {
  87. return true;
  88. }
  89. // min <= max <=> diff >= 0
  90. calc_t const diff_ed = bed_max - bed_min;
  91. calc_t const diff_ing = bing_max - bing_min;
  92. // if containing covers the whole globe it contains all
  93. if (diff_ing >= constants::period())
  94. {
  95. return true;
  96. }
  97. // if containing is smaller it cannot contain
  98. // and check interior (within vs covered_by)
  99. if (diff_ing < diff_ed || ! InteriorCheck::apply(diff_ed))
  100. {
  101. return false;
  102. }
  103. // calculate positive longitude translation with bing_min as origin
  104. calc_t const diff_min = math::longitude_distance_unsigned<units_t>(bing_min, bed_min);
  105. // max of contained translated into the containing origin must be lesser than max of containing
  106. return bing_min + diff_min + diff_ed <= bing_max
  107. /*|| bing_max - diff_min - diff_ed >= bing_min*/;
  108. }
  109. };
  110. template
  111. <
  112. template <typename, std::size_t, typename> class SubStrategy,
  113. typename CSTag,
  114. std::size_t Dimension,
  115. std::size_t DimensionCount
  116. >
  117. struct relate_box_box_loop
  118. {
  119. template <typename Box1, typename Box2>
  120. static inline bool apply(Box1 const& b_contained, Box2 const& b_containing)
  121. {
  122. assert_dimension_equal<Box1, Box2>();
  123. if (! SubStrategy<Box1, Dimension, CSTag>::apply(
  124. get<min_corner, Dimension>(b_contained),
  125. get<max_corner, Dimension>(b_contained),
  126. get<min_corner, Dimension>(b_containing),
  127. get<max_corner, Dimension>(b_containing)
  128. )
  129. )
  130. {
  131. return false;
  132. }
  133. return within::detail::relate_box_box_loop
  134. <
  135. SubStrategy, CSTag,
  136. Dimension + 1, DimensionCount
  137. >::apply(b_contained, b_containing);
  138. }
  139. };
  140. template
  141. <
  142. template <typename, std::size_t, typename> class SubStrategy,
  143. typename CSTag,
  144. std::size_t DimensionCount
  145. >
  146. struct relate_box_box_loop<SubStrategy, CSTag, DimensionCount, DimensionCount>
  147. {
  148. template <typename Box1, typename Box2>
  149. static inline bool apply(Box1 const& , Box2 const& )
  150. {
  151. return true;
  152. }
  153. };
  154. template <typename Geometry, std::size_t Dimension, typename CSTag>
  155. struct box_within_range
  156. : within::detail::box_within_coord
  157. {};
  158. template <typename Geometry, std::size_t Dimension, typename CSTag>
  159. struct box_covered_by_range
  160. : within::detail::box_covered_by_coord
  161. {};
  162. // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
  163. template <typename Geometry>
  164. struct box_within_range<Geometry, 0, spherical_tag>
  165. : within::detail::box_longitude_range
  166. <
  167. Geometry,
  168. within::detail::box_within_coord,
  169. within::detail::box_within_longitude_diff
  170. >
  171. {};
  172. template <typename Geometry>
  173. struct box_covered_by_range<Geometry, 0, spherical_tag>
  174. : within::detail::box_longitude_range
  175. <
  176. Geometry,
  177. within::detail::box_covered_by_coord,
  178. within::detail::box_covered_by_longitude_diff
  179. >
  180. {};
  181. } // namespace detail
  182. #endif // DOXYGEN_NO_DETAIL
  183. struct cartesian_box_box
  184. {
  185. template <typename Box1, typename Box2>
  186. static inline bool apply(Box1 const& box1, Box2 const& box2)
  187. {
  188. return within::detail::relate_box_box_loop
  189. <
  190. within::detail::box_within_range,
  191. cartesian_tag,
  192. 0, dimension<Box1>::type::value
  193. >::apply(box1, box2);
  194. }
  195. };
  196. struct spherical_box_box
  197. {
  198. template <typename Box1, typename Box2>
  199. static inline bool apply(Box1 const& box1, Box2 const& box2)
  200. {
  201. return within::detail::relate_box_box_loop
  202. <
  203. within::detail::box_within_range,
  204. spherical_tag,
  205. 0, dimension<Box1>::type::value
  206. >::apply(box1, box2);
  207. }
  208. };
  209. } // namespace within
  210. namespace covered_by
  211. {
  212. struct cartesian_box_box
  213. {
  214. template <typename Box1, typename Box2>
  215. static inline bool apply(Box1 const& box1, Box2 const& box2)
  216. {
  217. return within::detail::relate_box_box_loop
  218. <
  219. within::detail::box_covered_by_range,
  220. cartesian_tag,
  221. 0, dimension<Box1>::type::value
  222. >::apply(box1, box2);
  223. }
  224. };
  225. struct spherical_box_box
  226. {
  227. template <typename Box1, typename Box2>
  228. static inline bool apply(Box1 const& box1, Box2 const& box2)
  229. {
  230. return within::detail::relate_box_box_loop
  231. <
  232. within::detail::box_covered_by_range,
  233. spherical_tag,
  234. 0, dimension<Box1>::type::value
  235. >::apply(box1, box2);
  236. }
  237. };
  238. }
  239. #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  240. namespace within { namespace services
  241. {
  242. template <typename BoxContained, typename BoxContaining>
  243. struct default_strategy
  244. <
  245. BoxContained, BoxContaining,
  246. box_tag, box_tag,
  247. areal_tag, areal_tag,
  248. cartesian_tag, cartesian_tag
  249. >
  250. {
  251. typedef cartesian_box_box type;
  252. };
  253. // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
  254. template <typename BoxContained, typename BoxContaining>
  255. struct default_strategy
  256. <
  257. BoxContained, BoxContaining,
  258. box_tag, box_tag,
  259. areal_tag, areal_tag,
  260. spherical_tag, spherical_tag
  261. >
  262. {
  263. typedef spherical_box_box type;
  264. };
  265. }} // namespace within::services
  266. namespace covered_by { namespace services
  267. {
  268. template <typename BoxContained, typename BoxContaining>
  269. struct default_strategy
  270. <
  271. BoxContained, BoxContaining,
  272. box_tag, box_tag,
  273. areal_tag, areal_tag,
  274. cartesian_tag, cartesian_tag
  275. >
  276. {
  277. typedef cartesian_box_box type;
  278. };
  279. // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
  280. template <typename BoxContained, typename BoxContaining>
  281. struct default_strategy
  282. <
  283. BoxContained, BoxContaining,
  284. box_tag, box_tag,
  285. areal_tag, areal_tag,
  286. spherical_tag, spherical_tag
  287. >
  288. {
  289. typedef spherical_box_box type;
  290. };
  291. }} // namespace covered_by::services
  292. #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  293. }}} // namespace boost::geometry::strategy
  294. #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP