distance_projected_point.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
  3. // Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.
  4. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
  5. // This file was modified by Oracle on 2014-2021.
  6. // Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
  7. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  8. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  9. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  10. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  11. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  12. // Use, modification and distribution is subject to the Boost Software License,
  13. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  14. // http://www.boost.org/LICENSE_1_0.txt)
  15. #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
  16. #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
  17. #include <type_traits>
  18. #include <boost/concept_check.hpp>
  19. #include <boost/core/ignore_unused.hpp>
  20. #include <boost/geometry/core/access.hpp>
  21. #include <boost/geometry/core/point_type.hpp>
  22. #include <boost/geometry/algorithms/convert.hpp>
  23. #include <boost/geometry/arithmetic/arithmetic.hpp>
  24. #include <boost/geometry/arithmetic/dot_product.hpp>
  25. #include <boost/geometry/strategies/tags.hpp>
  26. #include <boost/geometry/strategies/distance.hpp>
  27. #include <boost/geometry/strategies/default_distance_result.hpp>
  28. #include <boost/geometry/strategies/cartesian/closest_points_pt_seg.hpp>
  29. #include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
  30. #include <boost/geometry/strategies/cartesian/point_in_point.hpp>
  31. #include <boost/geometry/strategies/cartesian/intersection.hpp>
  32. // Helper geometry (projected point on line)
  33. #include <boost/geometry/geometries/point.hpp>
  34. namespace boost { namespace geometry
  35. {
  36. namespace strategy { namespace distance
  37. {
  38. /*!
  39. \brief Strategy for distance point to segment
  40. \ingroup strategies
  41. \details Calculates distance using projected-point method, and (optionally) Pythagoras
  42. \author Adapted from: http://geometryalgorithms.com/Archive/algorithm_0102/algorithm_0102.htm
  43. \tparam CalculationType \tparam_calculation
  44. \tparam Strategy underlying point-point distance strategy
  45. \par Concepts for Strategy:
  46. - cartesian_distance operator(Point,Point)
  47. \note If the Strategy is a "comparable::pythagoras", this strategy
  48. automatically is a comparable projected_point strategy (so without sqrt)
  49. \qbk{
  50. [heading See also]
  51. [link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
  52. }
  53. */
  54. template
  55. <
  56. typename CalculationType = void,
  57. typename Strategy = pythagoras<CalculationType>
  58. >
  59. class projected_point
  60. {
  61. public:
  62. // The three typedefs below are necessary to calculate distances
  63. // from segments defined in integer coordinates.
  64. // Integer coordinates can still result in FP distances.
  65. // There is a division, which must be represented in FP.
  66. // So promote.
  67. template <typename Point, typename PointOfSegment>
  68. struct calculation_type
  69. : promote_floating_point
  70. <
  71. typename strategy::distance::services::return_type
  72. <
  73. Strategy,
  74. Point,
  75. PointOfSegment
  76. >::type
  77. >
  78. {};
  79. template <typename Point, typename PointOfSegment>
  80. inline typename calculation_type<Point, PointOfSegment>::type
  81. apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const
  82. {
  83. assert_dimension_equal<Point, PointOfSegment>();
  84. typedef typename calculation_type<Point, PointOfSegment>::type calculation_type;
  85. auto closest_point = closest_points::detail::compute_closest_point_to_segment
  86. <calculation_type>::apply(p, p1, p2);
  87. return Strategy().apply(p, closest_point);
  88. }
  89. template <typename CT>
  90. inline CT vertical_or_meridian(CT const& lat1, CT const& lat2) const
  91. {
  92. return lat1 - lat2;
  93. }
  94. };
  95. #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  96. namespace services
  97. {
  98. template <typename CalculationType, typename Strategy>
  99. struct tag<projected_point<CalculationType, Strategy> >
  100. {
  101. typedef strategy_tag_distance_point_segment type;
  102. };
  103. template <typename CalculationType, typename Strategy, typename P, typename PS>
  104. struct return_type<projected_point<CalculationType, Strategy>, P, PS>
  105. : projected_point<CalculationType, Strategy>::template calculation_type<P, PS>
  106. {};
  107. template <typename CalculationType, typename Strategy>
  108. struct comparable_type<projected_point<CalculationType, Strategy> >
  109. {
  110. // Define a projected_point strategy with its underlying point-point-strategy
  111. // being comparable
  112. typedef projected_point
  113. <
  114. CalculationType,
  115. typename comparable_type<Strategy>::type
  116. > type;
  117. };
  118. template <typename CalculationType, typename Strategy>
  119. struct get_comparable<projected_point<CalculationType, Strategy> >
  120. {
  121. typedef typename comparable_type
  122. <
  123. projected_point<CalculationType, Strategy>
  124. >::type comparable_type;
  125. public :
  126. static inline comparable_type apply(projected_point<CalculationType, Strategy> const& )
  127. {
  128. return comparable_type();
  129. }
  130. };
  131. template <typename CalculationType, typename Strategy, typename P, typename PS>
  132. struct result_from_distance<projected_point<CalculationType, Strategy>, P, PS>
  133. {
  134. private :
  135. typedef typename return_type<projected_point<CalculationType, Strategy>, P, PS>::type return_type;
  136. public :
  137. template <typename T>
  138. static inline return_type apply(projected_point<CalculationType, Strategy> const& , T const& value)
  139. {
  140. Strategy s;
  141. return result_from_distance<Strategy, P, PS>::apply(s, value);
  142. }
  143. };
  144. // Get default-strategy for point-segment distance calculation
  145. // while still have the possibility to specify point-point distance strategy (PPS)
  146. // It is used in algorithms/distance.hpp where users specify PPS for distance
  147. // of point-to-segment or point-to-linestring.
  148. // Convenient for geographic coordinate systems especially.
  149. template <typename Point, typename PointOfSegment, typename Strategy>
  150. struct default_strategy
  151. <
  152. point_tag, segment_tag, Point, PointOfSegment,
  153. cartesian_tag, cartesian_tag, Strategy
  154. >
  155. {
  156. typedef strategy::distance::projected_point
  157. <
  158. void,
  159. std::conditional_t
  160. <
  161. std::is_void<Strategy>::value,
  162. typename default_strategy
  163. <
  164. point_tag, point_tag, Point, PointOfSegment,
  165. cartesian_tag, cartesian_tag
  166. >::type,
  167. Strategy
  168. >
  169. > type;
  170. };
  171. template <typename PointOfSegment, typename Point, typename Strategy>
  172. struct default_strategy
  173. <
  174. segment_tag, point_tag, PointOfSegment, Point,
  175. cartesian_tag, cartesian_tag, Strategy
  176. >
  177. {
  178. typedef typename default_strategy
  179. <
  180. point_tag, segment_tag, Point, PointOfSegment,
  181. cartesian_tag, cartesian_tag, Strategy
  182. >::type type;
  183. };
  184. } // namespace services
  185. #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  186. }} // namespace strategy::distance
  187. }} // namespace boost::geometry
  188. #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP