distance_segment_box.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2018-2019 Oracle and/or its affiliates.
  3. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
  4. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  5. // Use, modification and distribution is subject to the Boost Software License,
  6. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP
  9. #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP
  10. #include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
  11. #include <boost/geometry/strategies/distance.hpp>
  12. #include <boost/geometry/strategies/normalize.hpp>
  13. #include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
  14. #include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
  15. #include <boost/geometry/strategies/spherical/point_in_point.hpp>
  16. #include <boost/geometry/strategies/cartesian/point_in_box.hpp> // spherical
  17. namespace boost { namespace geometry
  18. {
  19. namespace strategy { namespace distance
  20. {
  21. struct generic_segment_box
  22. {
  23. template
  24. <
  25. typename LessEqual,
  26. typename ReturnType,
  27. typename SegmentPoint,
  28. typename BoxPoint,
  29. typename SegmentBoxStrategy,
  30. typename AzimuthStrategy,
  31. typename EnvelopeSegmentStrategy,
  32. typename NormalizePointStrategy,
  33. typename DisjointPointBoxStrategy,
  34. typename DisjointBoxBoxStrategy
  35. >
  36. static inline ReturnType segment_below_of_box(
  37. SegmentPoint const& p0,
  38. SegmentPoint const& p1,
  39. BoxPoint const&,
  40. BoxPoint const& top_right,
  41. BoxPoint const& bottom_left,
  42. BoxPoint const& bottom_right,
  43. SegmentBoxStrategy const& sb_strategy,
  44. AzimuthStrategy const& az_strategy,
  45. EnvelopeSegmentStrategy const& es_strategy,
  46. NormalizePointStrategy const& np_strategy,
  47. DisjointPointBoxStrategy const& dpb_strategy,
  48. DisjointBoxBoxStrategy const& dbb_strategy)
  49. {
  50. ReturnType result;
  51. typename LessEqual::other less_equal;
  52. typedef geometry::model::segment<SegmentPoint> Segment;
  53. typedef typename cs_tag<Segment>::type segment_cs_type;
  54. typedef geometry::detail::disjoint::
  55. disjoint_segment_box_sphere_or_spheroid<segment_cs_type>
  56. disjoint_sb;
  57. typedef typename disjoint_sb::disjoint_info disjoint_info_type;
  58. Segment seg(p0, p1);
  59. geometry::model::box<BoxPoint> input_box;
  60. geometry::set_from_radian<geometry::min_corner, 0>
  61. (input_box, geometry::get_as_radian<0>(bottom_left));
  62. geometry::set_from_radian<geometry::min_corner, 1>
  63. (input_box, geometry::get_as_radian<1>(bottom_left));
  64. geometry::set_from_radian<geometry::max_corner, 0>
  65. (input_box, geometry::get_as_radian<0>(top_right));
  66. geometry::set_from_radian<geometry::max_corner, 1>
  67. (input_box, geometry::get_as_radian<1>(top_right));
  68. SegmentPoint p_max;
  69. disjoint_info_type disjoint_result = disjoint_sb::
  70. apply(seg, input_box, p_max,
  71. az_strategy, np_strategy, dpb_strategy, dbb_strategy);
  72. if (disjoint_result == disjoint_info_type::intersect) //intersect
  73. {
  74. return 0;
  75. }
  76. // disjoint but vertex not computed
  77. if (disjoint_result == disjoint_info_type::disjoint_no_vertex)
  78. {
  79. typedef typename coordinate_type<SegmentPoint>::type CT;
  80. geometry::model::box<SegmentPoint> mbr;
  81. geometry::envelope(seg, mbr, es_strategy);
  82. CT lon1 = geometry::get_as_radian<0>(p0);
  83. CT lat1 = geometry::get_as_radian<1>(p0);
  84. CT lon2 = geometry::get_as_radian<0>(p1);
  85. CT lat2 = geometry::get_as_radian<1>(p1);
  86. if (lon1 > lon2)
  87. {
  88. std::swap(lon1, lon2);
  89. std::swap(lat1, lat2);
  90. }
  91. CT vertex_lat;
  92. CT lat_sum = lat1 + lat2;
  93. if (lat_sum > CT(0))
  94. {
  95. vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(mbr);
  96. } else {
  97. vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(mbr);
  98. }
  99. CT alp1;
  100. az_strategy.apply(lon1, lat1, lon2, lat2, alp1);
  101. CT vertex_lon = geometry::formula::vertex_longitude
  102. <
  103. CT,
  104. segment_cs_type
  105. >::apply(lon1, lat1, lon2, lat2,
  106. vertex_lat, alp1, az_strategy);
  107. geometry::set_from_radian<0>(p_max, vertex_lon);
  108. geometry::set_from_radian<1>(p_max, vertex_lat);
  109. }
  110. //otherwise disjoint and vertex computed inside disjoint
  111. if (less_equal(geometry::get_as_radian<0>(bottom_left),
  112. geometry::get_as_radian<0>(p_max)))
  113. {
  114. result = boost::numeric_cast<ReturnType>(typename
  115. SegmentBoxStrategy::distance_ps_strategy::type().apply(bottom_left, p0, p1));
  116. }
  117. else
  118. {
  119. result = geometry::detail::distance::segment_to_box_2D
  120. <
  121. ReturnType,
  122. SegmentPoint,
  123. BoxPoint,
  124. SegmentBoxStrategy
  125. >::template call_above_of_box
  126. <
  127. typename LessEqual::other
  128. >(p1, p0, p_max, bottom_right, sb_strategy);
  129. }
  130. return result;
  131. }
  132. template <typename SPoint, typename BPoint>
  133. static void mirror(SPoint& p0,
  134. SPoint& p1,
  135. BPoint& bottom_left,
  136. BPoint& bottom_right,
  137. BPoint& top_left,
  138. BPoint& top_right)
  139. {
  140. //if segment's vertex is the southest point then mirror geometries
  141. if (geometry::get<1>(p0) + geometry::get<1>(p1) < 0)
  142. {
  143. BPoint bl = bottom_left;
  144. BPoint br = bottom_right;
  145. geometry::set<1>(p0, geometry::get<1>(p0) * -1);
  146. geometry::set<1>(p1, geometry::get<1>(p1) * -1);
  147. geometry::set<1>(bottom_left, geometry::get<1>(top_left) * -1);
  148. geometry::set<1>(top_left, geometry::get<1>(bl) * -1);
  149. geometry::set<1>(bottom_right, geometry::get<1>(top_right) * -1);
  150. geometry::set<1>(top_right, geometry::get<1>(br) * -1);
  151. }
  152. }
  153. };
  154. //===========================================================================
  155. template
  156. <
  157. typename CalculationType = void,
  158. typename Strategy = haversine<double, CalculationType>
  159. >
  160. struct spherical_segment_box
  161. {
  162. template <typename PointOfSegment, typename PointOfBox>
  163. struct calculation_type
  164. : promote_floating_point
  165. <
  166. typename strategy::distance::services::return_type
  167. <
  168. Strategy,
  169. PointOfSegment,
  170. PointOfBox
  171. >::type
  172. >
  173. {};
  174. // strategy getters
  175. // point-point strategy getters
  176. struct distance_pp_strategy
  177. {
  178. typedef Strategy type;
  179. };
  180. inline typename distance_pp_strategy::type get_distance_pp_strategy() const
  181. {
  182. return typename distance_pp_strategy::type();
  183. }
  184. // point-segment strategy getters
  185. struct distance_ps_strategy
  186. {
  187. typedef cross_track<CalculationType, Strategy> type;
  188. };
  189. inline typename distance_ps_strategy::type get_distance_ps_strategy() const
  190. {
  191. return typename distance_ps_strategy::type();
  192. }
  193. typedef within::spherical_point_point equals_point_point_strategy_type;
  194. static inline equals_point_point_strategy_type get_equals_point_point_strategy()
  195. {
  196. return equals_point_point_strategy_type();
  197. }
  198. // methods
  199. template <typename LessEqual, typename ReturnType,
  200. typename SegmentPoint, typename BoxPoint>
  201. inline ReturnType segment_below_of_box(SegmentPoint const& p0,
  202. SegmentPoint const& p1,
  203. BoxPoint const& top_left,
  204. BoxPoint const& top_right,
  205. BoxPoint const& bottom_left,
  206. BoxPoint const& bottom_right) const
  207. {
  208. typedef typename azimuth::spherical<CalculationType> azimuth_strategy_type;
  209. azimuth_strategy_type az_strategy;
  210. typedef typename envelope::spherical_segment<CalculationType>
  211. envelope_segment_strategy_type;
  212. envelope_segment_strategy_type es_strategy;
  213. return generic_segment_box::segment_below_of_box
  214. <
  215. LessEqual,
  216. ReturnType
  217. >(p0,p1,top_left,top_right,bottom_left,bottom_right,
  218. spherical_segment_box<CalculationType>(),
  219. az_strategy, es_strategy,
  220. normalize::spherical_point(),
  221. covered_by::spherical_point_box(),
  222. disjoint::spherical_box_box());
  223. }
  224. template <typename SPoint, typename BPoint>
  225. static void mirror(SPoint& p0,
  226. SPoint& p1,
  227. BPoint& bottom_left,
  228. BPoint& bottom_right,
  229. BPoint& top_left,
  230. BPoint& top_right)
  231. {
  232. generic_segment_box::mirror(p0, p1,
  233. bottom_left, bottom_right,
  234. top_left, top_right);
  235. }
  236. };
  237. #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  238. namespace services
  239. {
  240. template <typename CalculationType, typename Strategy>
  241. struct tag<spherical_segment_box<CalculationType, Strategy> >
  242. {
  243. typedef strategy_tag_distance_segment_box type;
  244. };
  245. template <typename CalculationType, typename Strategy, typename PS, typename PB>
  246. struct return_type<spherical_segment_box<CalculationType, Strategy>, PS, PB>
  247. : spherical_segment_box<CalculationType, Strategy>::template calculation_type<PS, PB>
  248. {};
  249. template <typename CalculationType, typename Strategy>
  250. struct comparable_type<spherical_segment_box<CalculationType, Strategy> >
  251. {
  252. // Define a cartesian_segment_box strategy with its underlying point-segment
  253. // strategy being comparable
  254. typedef spherical_segment_box
  255. <
  256. CalculationType,
  257. typename comparable_type<Strategy>::type
  258. > type;
  259. };
  260. template <typename CalculationType, typename Strategy>
  261. struct get_comparable<spherical_segment_box<CalculationType, Strategy> >
  262. {
  263. typedef typename comparable_type
  264. <
  265. spherical_segment_box<CalculationType, Strategy>
  266. >::type comparable_type;
  267. public :
  268. static inline comparable_type apply(spherical_segment_box<CalculationType, Strategy> const& )
  269. {
  270. return comparable_type();
  271. }
  272. };
  273. template <typename CalculationType, typename Strategy, typename PS, typename PB>
  274. struct result_from_distance<spherical_segment_box<CalculationType, Strategy>, PS, PB>
  275. {
  276. private :
  277. typedef typename return_type<
  278. spherical_segment_box
  279. <
  280. CalculationType,
  281. Strategy
  282. >,
  283. PS,
  284. PB
  285. >::type return_type;
  286. public :
  287. template <typename T>
  288. static inline return_type apply(spherical_segment_box<CalculationType,
  289. Strategy> const& ,
  290. T const& value)
  291. {
  292. Strategy s;
  293. return result_from_distance<Strategy, PS, PB>::apply(s, value);
  294. }
  295. };
  296. template <typename Segment, typename Box>
  297. struct default_strategy
  298. <
  299. segment_tag, box_tag, Segment, Box,
  300. spherical_equatorial_tag, spherical_equatorial_tag
  301. >
  302. {
  303. typedef spherical_segment_box<> type;
  304. };
  305. template <typename Box, typename Segment>
  306. struct default_strategy
  307. <
  308. box_tag, segment_tag, Box, Segment,
  309. spherical_equatorial_tag, spherical_equatorial_tag
  310. >
  311. {
  312. typedef typename default_strategy
  313. <
  314. segment_tag, box_tag, Segment, Box,
  315. spherical_equatorial_tag, spherical_equatorial_tag
  316. >::type type;
  317. };
  318. }
  319. #endif
  320. }} // namespace strategy::distance
  321. }} // namespace boost::geometry
  322. #endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP