discrete_frechet_distance.hpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // Boost.Geometry
  2. // Copyright (c) 2018 Yaghyavardhan Singh Khangarot, Hyderabad, India.
  3. // Contributed and/or modified by Yaghyavardhan Singh Khangarot,
  4. // as part of Google Summer of Code 2018 program.
  5. // This file was modified by Oracle on 2018.
  6. // Modifications copyright (c) 2018 Oracle and/or its affiliates.
  7. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  8. // Use, modification and distribution is subject to the Boost Software License,
  9. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. #ifndef BOOST_GEOMETRY_ALGORITHMS_DISCRETE_FRECHET_DISTANCE_HPP
  12. #define BOOST_GEOMETRY_ALGORITHMS_DISCRETE_FRECHET_DISTANCE_HPP
  13. #include <algorithm>
  14. #ifdef BOOST_GEOMETRY_DEBUG_FRECHET_DISTANCE
  15. #include <iostream>
  16. #endif
  17. #include <iterator>
  18. #include <utility>
  19. #include <vector>
  20. #include <limits>
  21. #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
  22. #include <boost/geometry/algorithms/not_implemented.hpp>
  23. #include <boost/geometry/core/assert.hpp>
  24. #include <boost/geometry/core/tag.hpp>
  25. #include <boost/geometry/core/tags.hpp>
  26. #include <boost/geometry/core/point_type.hpp>
  27. #include <boost/geometry/strategies/distance.hpp>
  28. #include <boost/geometry/strategies/distance_result.hpp>
  29. #include <boost/geometry/util/range.hpp>
  30. namespace boost { namespace geometry
  31. {
  32. #ifndef DOXYGEN_NO_DETAIL
  33. namespace detail { namespace discrete_frechet_distance
  34. {
  35. template <typename size_type1 , typename size_type2,typename result_type>
  36. class coup_mat
  37. {
  38. public:
  39. coup_mat(size_type1 w, size_type2 h)
  40. : m_data(w * h,-1), m_width(w), m_height(h)
  41. {}
  42. result_type & operator()(size_type1 i, size_type2 j)
  43. {
  44. BOOST_GEOMETRY_ASSERT(i < m_width && j < m_height);
  45. return m_data[j * m_width + i];
  46. }
  47. private:
  48. std::vector<result_type> m_data;
  49. size_type1 m_width;
  50. size_type2 m_height;
  51. };
  52. struct linestring_linestring
  53. {
  54. template <typename Linestring1, typename Linestring2, typename Strategy>
  55. static inline typename distance_result
  56. <
  57. typename point_type<Linestring1>::type,
  58. typename point_type<Linestring2>::type,
  59. Strategy
  60. >::type apply(Linestring1 const& ls1, Linestring2 const& ls2, Strategy const& strategy)
  61. {
  62. typedef typename distance_result
  63. <
  64. typename point_type<Linestring1>::type,
  65. typename point_type<Linestring2>::type,
  66. Strategy
  67. >::type result_type;
  68. typedef typename boost::range_size<Linestring1>::type size_type1;
  69. typedef typename boost::range_size<Linestring2>::type size_type2;
  70. boost::geometry::detail::throw_on_empty_input(ls1);
  71. boost::geometry::detail::throw_on_empty_input(ls2);
  72. size_type1 const a = boost::size(ls1);
  73. size_type2 const b = boost::size(ls2);
  74. //Coupling Matrix CoupMat(a,b,-1);
  75. coup_mat<size_type1,size_type2,result_type> coup_matrix(a,b);
  76. result_type const not_feasible = -100;
  77. //findin the Coupling Measure
  78. for (size_type1 i = 0 ; i < a ; i++ )
  79. {
  80. for(size_type2 j=0;j<b;j++)
  81. {
  82. result_type dis = strategy.apply(range::at(ls1,i), range::at(ls2,j));
  83. if(i==0 && j==0)
  84. coup_matrix(i,j) = dis;
  85. else if(i==0 && j>0)
  86. coup_matrix(i,j) =
  87. (std::max)(coup_matrix(i,j-1), dis);
  88. else if(i>0 && j==0)
  89. coup_matrix(i,j) =
  90. (std::max)(coup_matrix(i-1,j), dis);
  91. else if(i>0 && j>0)
  92. coup_matrix(i,j) =
  93. (std::max)((std::min)(coup_matrix(i,j-1),
  94. (std::min)(coup_matrix(i-1,j),
  95. coup_matrix(i-1,j-1))),
  96. dis);
  97. else
  98. coup_matrix(i,j) = not_feasible;
  99. }
  100. }
  101. #ifdef BOOST_GEOMETRY_DEBUG_FRECHET_DISTANCE
  102. //Print CoupLing Matrix
  103. for(size_type i = 0; i <a; i++)
  104. {
  105. for(size_type j = 0; j <b; j++)
  106. std::cout << coup_matrix(i,j) << " ";
  107. std::cout << std::endl;
  108. }
  109. #endif
  110. return coup_matrix(a-1,b-1);
  111. }
  112. };
  113. }} // namespace detail::frechet_distance
  114. #endif // DOXYGEN_NO_DETAIL
  115. #ifndef DOXYGEN_NO_DISPATCH
  116. namespace dispatch
  117. {
  118. template
  119. <
  120. typename Geometry1,
  121. typename Geometry2,
  122. typename Tag1 = typename tag<Geometry1>::type,
  123. typename Tag2 = typename tag<Geometry2>::type
  124. >
  125. struct discrete_frechet_distance : not_implemented<Tag1, Tag2>
  126. {};
  127. template <typename Linestring1, typename Linestring2>
  128. struct discrete_frechet_distance
  129. <
  130. Linestring1,
  131. Linestring2,
  132. linestring_tag,
  133. linestring_tag
  134. >
  135. : detail::discrete_frechet_distance::linestring_linestring
  136. {};
  137. } // namespace dispatch
  138. #endif // DOXYGEN_NO_DISPATCH
  139. /*!
  140. \brief Calculate discrete Frechet distance between two geometries (currently
  141. works for LineString-LineString) using specified strategy.
  142. \ingroup discrete_frechet_distance
  143. \tparam Geometry1 \tparam_geometry
  144. \tparam Geometry2 \tparam_geometry
  145. \tparam Strategy A type fulfilling a DistanceStrategy concept
  146. \param geometry1 Input geometry
  147. \param geometry2 Input geometry
  148. \param strategy Distance strategy to be used to calculate Pt-Pt distance
  149. \qbk{distinguish,with strategy}
  150. \qbk{[include reference/algorithms/discrete_frechet_distance.qbk]}
  151. \qbk{
  152. [heading Available Strategies]
  153. \* [link geometry.reference.strategies.strategy_distance_pythagoras Pythagoras (cartesian)]
  154. \* [link geometry.reference.strategies.strategy_distance_haversine Haversine (spherical)]
  155. [/ \* more (currently extensions): Vincenty\, Andoyer (geographic) ]
  156. [heading Example]
  157. [discrete_frechet_distance_strategy]
  158. [discrete_frechet_distance_strategy_output]
  159. }
  160. */
  161. template <typename Geometry1, typename Geometry2, typename Strategy>
  162. inline typename distance_result
  163. <
  164. typename point_type<Geometry1>::type,
  165. typename point_type<Geometry2>::type,
  166. Strategy
  167. >::type
  168. discrete_frechet_distance(Geometry1 const& geometry1,
  169. Geometry2 const& geometry2,
  170. Strategy const& strategy)
  171. {
  172. return dispatch::discrete_frechet_distance
  173. <
  174. Geometry1, Geometry2
  175. >::apply(geometry1, geometry2, strategy);
  176. }
  177. // Algorithm overload using default Pt-Pt distance strategy
  178. /*!
  179. \brief Calculate discrete Frechet distance between two geometries (currently
  180. work for LineString-LineString).
  181. \ingroup discrete_frechet_distance
  182. \tparam Geometry1 \tparam_geometry
  183. \tparam Geometry2 \tparam_geometry
  184. \param geometry1 Input geometry
  185. \param geometry2 Input geometry
  186. \qbk{[include reference/algorithms/discrete_frechet_distance.qbk]}
  187. \qbk{
  188. [heading Example]
  189. [discrete_frechet_distance]
  190. [discrete_frechet_distance_output]
  191. }
  192. */
  193. template <typename Geometry1, typename Geometry2>
  194. inline typename distance_result
  195. <
  196. typename point_type<Geometry1>::type,
  197. typename point_type<Geometry2>::type
  198. >::type
  199. discrete_frechet_distance(Geometry1 const& geometry1, Geometry2 const& geometry2)
  200. {
  201. typedef typename strategy::distance::services::default_strategy
  202. <
  203. point_tag, point_tag,
  204. typename point_type<Geometry1>::type,
  205. typename point_type<Geometry2>::type
  206. >::type strategy_type;
  207. return discrete_frechet_distance(geometry1, geometry2, strategy_type());
  208. }
  209. }} // namespace boost::geometry
  210. #endif // BOOST_GEOMETRY_ALGORITHMS_DISCRETE_FRECHET_DISTANCE_HPP