box_in_box.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  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, 2019.
  7. // Modifications copyright (c) 2016-2019, 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. } // namespace detail
  155. #endif // DOXYGEN_NO_DETAIL
  156. // for backward compatibility
  157. template <typename Geometry, std::size_t Dimension, typename CSTag>
  158. struct box_within_range
  159. : within::detail::box_within_coord
  160. {};
  161. template <typename Geometry, std::size_t Dimension, typename CSTag>
  162. struct box_covered_by_range
  163. : within::detail::box_covered_by_coord
  164. {};
  165. // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
  166. template <typename Geometry>
  167. struct box_within_range<Geometry, 0, spherical_tag>
  168. : within::detail::box_longitude_range
  169. <
  170. Geometry,
  171. within::detail::box_within_coord,
  172. within::detail::box_within_longitude_diff
  173. >
  174. {};
  175. template <typename Geometry>
  176. struct box_covered_by_range<Geometry, 0, spherical_tag>
  177. : within::detail::box_longitude_range
  178. <
  179. Geometry,
  180. within::detail::box_covered_by_coord,
  181. within::detail::box_covered_by_longitude_diff
  182. >
  183. {};
  184. // for backward compatibility
  185. template
  186. <
  187. typename B1,
  188. typename B2,
  189. template <typename, std::size_t, typename> class SubStrategy = box_within_range
  190. >
  191. struct box_in_box
  192. {
  193. template <typename Box1, typename Box2>
  194. static inline bool apply(Box1 const& box1, Box2 const& box2)
  195. {
  196. typedef typename tag_cast
  197. <
  198. typename geometry::cs_tag<Box1>::type,
  199. spherical_tag
  200. >::type cs_tag;
  201. return within::detail::relate_box_box_loop
  202. <
  203. SubStrategy, cs_tag,
  204. 0, dimension<Box1>::type::value
  205. >::apply(box1, box2);
  206. }
  207. };
  208. struct cartesian_box_box
  209. {
  210. template <typename Box1, typename Box2>
  211. static inline bool apply(Box1 const& box1, Box2 const& box2)
  212. {
  213. return within::detail::relate_box_box_loop
  214. <
  215. box_within_range,
  216. cartesian_tag,
  217. 0, dimension<Box1>::type::value
  218. >::apply(box1, box2);
  219. }
  220. };
  221. struct spherical_box_box
  222. {
  223. template <typename Box1, typename Box2>
  224. static inline bool apply(Box1 const& box1, Box2 const& box2)
  225. {
  226. return within::detail::relate_box_box_loop
  227. <
  228. box_within_range,
  229. spherical_tag,
  230. 0, dimension<Box1>::type::value
  231. >::apply(box1, box2);
  232. }
  233. };
  234. } // namespace within
  235. namespace covered_by
  236. {
  237. struct cartesian_box_box
  238. {
  239. template <typename Box1, typename Box2>
  240. static inline bool apply(Box1 const& box1, Box2 const& box2)
  241. {
  242. return within::detail::relate_box_box_loop
  243. <
  244. strategy::within::box_covered_by_range,
  245. cartesian_tag,
  246. 0, dimension<Box1>::type::value
  247. >::apply(box1, box2);
  248. }
  249. };
  250. struct spherical_box_box
  251. {
  252. template <typename Box1, typename Box2>
  253. static inline bool apply(Box1 const& box1, Box2 const& box2)
  254. {
  255. return within::detail::relate_box_box_loop
  256. <
  257. strategy::within::box_covered_by_range,
  258. spherical_tag,
  259. 0, dimension<Box1>::type::value
  260. >::apply(box1, box2);
  261. }
  262. };
  263. }
  264. #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  265. namespace within { namespace services
  266. {
  267. template <typename BoxContained, typename BoxContaining>
  268. struct default_strategy
  269. <
  270. BoxContained, BoxContaining,
  271. box_tag, box_tag,
  272. areal_tag, areal_tag,
  273. cartesian_tag, cartesian_tag
  274. >
  275. {
  276. typedef cartesian_box_box type;
  277. };
  278. // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
  279. template <typename BoxContained, typename BoxContaining>
  280. struct default_strategy
  281. <
  282. BoxContained, BoxContaining,
  283. box_tag, box_tag,
  284. areal_tag, areal_tag,
  285. spherical_tag, spherical_tag
  286. >
  287. {
  288. typedef spherical_box_box type;
  289. };
  290. }} // namespace within::services
  291. namespace covered_by { namespace services
  292. {
  293. template <typename BoxContained, typename BoxContaining>
  294. struct default_strategy
  295. <
  296. BoxContained, BoxContaining,
  297. box_tag, box_tag,
  298. areal_tag, areal_tag,
  299. cartesian_tag, cartesian_tag
  300. >
  301. {
  302. typedef cartesian_box_box type;
  303. };
  304. // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
  305. template <typename BoxContained, typename BoxContaining>
  306. struct default_strategy
  307. <
  308. BoxContained, BoxContaining,
  309. box_tag, box_tag,
  310. areal_tag, areal_tag,
  311. spherical_tag, spherical_tag
  312. >
  313. {
  314. typedef spherical_box_box type;
  315. };
  316. }} // namespace covered_by::services
  317. #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  318. }}} // namespace boost::geometry::strategy
  319. #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP