comparable_distance_result.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2014-2021, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  4. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  5. // Licensed under the Boost Software License version 1.0.
  6. // http://www.boost.org/users/license.html
  7. #ifndef BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP
  8. #define BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP
  9. #include <boost/geometry/algorithms/detail/select_geometry_type.hpp>
  10. #include <boost/geometry/core/point_type.hpp>
  11. #include <boost/geometry/core/reverse_dispatch.hpp>
  12. #include <boost/geometry/strategies/default_strategy.hpp>
  13. #include <boost/geometry/strategies/detail.hpp>
  14. #include <boost/geometry/strategies/distance.hpp>
  15. #include <boost/geometry/strategies/distance/services.hpp>
  16. #include <boost/geometry/util/select_most_precise.hpp>
  17. #include <boost/geometry/util/sequence.hpp>
  18. #include <boost/geometry/util/type_traits.hpp>
  19. namespace boost { namespace geometry
  20. {
  21. namespace resolve_strategy
  22. {
  23. // TODO: This utility could be entirely implemented as:
  24. // decltype(geometry::comparable_distance(std::declval<Geometry1>(), std::declval<Geometry2>(), std::declval<Strategy>()))
  25. // however then the algorithm would have to be compiled.
  26. template
  27. <
  28. typename Geometry1, typename Geometry2, typename Strategy,
  29. bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
  30. >
  31. struct comparable_distance_strategy2_type
  32. {
  33. typedef decltype(std::declval<Strategy>().distance(
  34. std::declval<Geometry1>(), std::declval<Geometry2>())) type;
  35. };
  36. template <typename Geometry1, typename Geometry2, typename Strategy>
  37. struct comparable_distance_strategy2_type<Geometry1, Geometry2, Strategy, false>
  38. {
  39. typedef Strategy type;
  40. };
  41. template
  42. <
  43. typename Geometry1, typename Geometry2, typename Strategy,
  44. bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
  45. >
  46. struct comparable_distance_strategy_type
  47. : strategy::distance::services::comparable_type
  48. <
  49. typename comparable_distance_strategy2_type
  50. <
  51. Geometry1, Geometry2, Strategy
  52. >::type
  53. >
  54. {};
  55. template <typename Geometry1, typename Geometry2, typename Strategy>
  56. struct comparable_distance_strategy_type<Geometry1, Geometry2, Strategy, true>
  57. : comparable_distance_strategy_type<Geometry2, Geometry1, Strategy, false>
  58. {};
  59. template <typename Geometry1, typename Geometry2, typename Strategy>
  60. struct comparable_distance_result
  61. : strategy::distance::services::return_type
  62. <
  63. typename comparable_distance_strategy_type<Geometry1, Geometry2, Strategy>::type,
  64. typename point_type<Geometry1>::type,
  65. typename point_type<Geometry2>::type
  66. >
  67. {};
  68. template <typename Geometry1, typename Geometry2>
  69. struct comparable_distance_result<Geometry1, Geometry2, default_strategy>
  70. : comparable_distance_result
  71. <
  72. Geometry1,
  73. Geometry2,
  74. typename strategies::distance::services::default_strategy
  75. <
  76. Geometry1, Geometry2
  77. >::type
  78. >
  79. {};
  80. } // namespace resolve_strategy
  81. #ifndef DOXYGEN_NO_DETAIL
  82. namespace detail { namespace distance
  83. {
  84. template <typename Strategy = geometry::default_strategy>
  85. struct more_precise_comparable_distance_result
  86. {
  87. template <typename Curr, typename Next>
  88. struct predicate
  89. : std::is_same
  90. <
  91. typename resolve_strategy::comparable_distance_result
  92. <
  93. typename util::sequence_element<0, Curr>::type,
  94. typename util::sequence_element<1, Curr>::type,
  95. Strategy
  96. >::type,
  97. typename geometry::select_most_precise
  98. <
  99. typename resolve_strategy::comparable_distance_result
  100. <
  101. typename util::sequence_element<0, Curr>::type,
  102. typename util::sequence_element<1, Curr>::type,
  103. Strategy
  104. >::type,
  105. typename resolve_strategy::comparable_distance_result
  106. <
  107. typename util::sequence_element<0, Next>::type,
  108. typename util::sequence_element<1, Next>::type,
  109. Strategy
  110. >::type
  111. >::type
  112. >
  113. {};
  114. };
  115. }} // namespace detail::distance
  116. #endif //DOXYGEN_NO_DETAIL
  117. namespace resolve_dynamic
  118. {
  119. template
  120. <
  121. typename Geometry1, typename Geometry2, typename Strategy,
  122. bool IsDynamicOrCollection = util::is_dynamic_geometry<Geometry1>::value
  123. || util::is_dynamic_geometry<Geometry2>::value
  124. || util::is_geometry_collection<Geometry1>::value
  125. || util::is_geometry_collection<Geometry2>::value
  126. >
  127. struct comparable_distance_result
  128. : resolve_strategy::comparable_distance_result
  129. <
  130. Geometry1,
  131. Geometry2,
  132. Strategy
  133. >
  134. {};
  135. template <typename Geometry1, typename Geometry2, typename Strategy>
  136. struct comparable_distance_result<Geometry1, Geometry2, Strategy, true>
  137. {
  138. // Select the most precise distance strategy result type
  139. // for all variant type combinations.
  140. // TODO: We should ignore the combinations that are not valid
  141. // but is_implemented is not ready for prime time.
  142. using selected_types = typename detail::select_geometry_types
  143. <
  144. Geometry1, Geometry2,
  145. detail::distance::more_precise_comparable_distance_result<Strategy>::template predicate
  146. >::type;
  147. using type = typename resolve_strategy::comparable_distance_result
  148. <
  149. typename util::sequence_element<0, selected_types>::type,
  150. typename util::sequence_element<1, selected_types>::type,
  151. Strategy
  152. >::type;
  153. };
  154. } // namespace resolve_dynamic
  155. /*!
  156. \brief Meta-function defining return type of comparable_distance function
  157. \ingroup distance
  158. */
  159. template
  160. <
  161. typename Geometry1,
  162. typename Geometry2 = Geometry1,
  163. typename Strategy = void
  164. >
  165. struct comparable_distance_result
  166. : resolve_dynamic::comparable_distance_result
  167. <
  168. Geometry1, Geometry2, Strategy
  169. >
  170. {};
  171. template <typename Geometry1, typename Geometry2>
  172. struct comparable_distance_result<Geometry1, Geometry2, void>
  173. : comparable_distance_result<Geometry1, Geometry2, default_strategy>
  174. {};
  175. }} // namespace boost::geometry
  176. #endif // BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP