minmaxdist.hpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Boost.Geometry Index
  2. //
  3. // minmaxdist used in R-tree k nearest neighbors query
  4. //
  5. // Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
  6. //
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MINMAXDIST_HPP
  11. #define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MINMAXDIST_HPP
  12. #include <boost/geometry/algorithms/distance.hpp>
  13. #include <boost/geometry/algorithms/comparable_distance.hpp>
  14. #include <boost/geometry/index/detail/algorithms/diff_abs.hpp>
  15. #include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
  16. #include <boost/geometry/index/detail/algorithms/smallest_for_indexable.hpp>
  17. namespace boost { namespace geometry { namespace index { namespace detail {
  18. struct minmaxdist_tag {};
  19. template <
  20. typename Point,
  21. typename BoxIndexable,
  22. size_t DimensionIndex>
  23. struct smallest_for_indexable_dimension<Point, BoxIndexable, box_tag, minmaxdist_tag, DimensionIndex>
  24. {
  25. typedef typename geometry::default_comparable_distance_result<Point, BoxIndexable>::type result_type;
  26. inline static result_type apply(Point const& pt, BoxIndexable const& i, result_type const& maxd)
  27. {
  28. typedef typename coordinate_type<Point>::type point_coord_t;
  29. typedef typename coordinate_type<BoxIndexable>::type indexable_coord_t;
  30. point_coord_t pt_c = geometry::get<DimensionIndex>(pt);
  31. indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);
  32. indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);
  33. indexable_coord_t ind_c_avg = ind_c_min + (ind_c_max - ind_c_min) / 2;
  34. // TODO: awulkiew - is (ind_c_min + ind_c_max) / 2 safe?
  35. // TODO: awulkiew - optimize! don't calculate 2x pt_c <= ind_c_avg
  36. // take particular case pt_c == ind_c_avg into account
  37. result_type closer_comp = 0;
  38. if ( pt_c <= ind_c_avg )
  39. closer_comp = detail::diff_abs(pt_c, ind_c_min); // unsigned values protection
  40. else
  41. closer_comp = ind_c_max - pt_c;
  42. result_type further_comp = 0;
  43. if ( ind_c_avg <= pt_c )
  44. further_comp = pt_c - ind_c_min;
  45. else
  46. further_comp = detail::diff_abs(pt_c, ind_c_max); // unsigned values protection
  47. return (maxd + closer_comp * closer_comp) - further_comp * further_comp;
  48. }
  49. };
  50. template <typename Point, typename Indexable, typename IndexableTag>
  51. struct minmaxdist_impl
  52. {
  53. BOOST_MPL_ASSERT_MSG(
  54. (false),
  55. NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_TAG_TYPE,
  56. (minmaxdist_impl));
  57. };
  58. template <typename Point, typename Indexable>
  59. struct minmaxdist_impl<Point, Indexable, point_tag>
  60. {
  61. typedef typename geometry::default_comparable_distance_result<Point, Indexable>::type result_type;
  62. inline static result_type apply(Point const& pt, Indexable const& i)
  63. {
  64. return geometry::comparable_distance(pt, i);
  65. }
  66. };
  67. template <typename Point, typename Indexable>
  68. struct minmaxdist_impl<Point, Indexable, box_tag>
  69. {
  70. typedef typename geometry::default_comparable_distance_result<Point, Indexable>::type result_type;
  71. inline static result_type apply(Point const& pt, Indexable const& i)
  72. {
  73. result_type maxd = geometry::comparable_distance(pt, i);
  74. return smallest_for_indexable<
  75. Point,
  76. Indexable,
  77. box_tag,
  78. minmaxdist_tag,
  79. dimension<Indexable>::value
  80. >::apply(pt, i, maxd);
  81. }
  82. };
  83. /**
  84. * This is comparable distace.
  85. */
  86. template <typename Point, typename Indexable>
  87. typename geometry::default_comparable_distance_result<Point, Indexable>::type
  88. minmaxdist(Point const& pt, Indexable const& i)
  89. {
  90. return detail::minmaxdist_impl<
  91. Point,
  92. Indexable,
  93. typename tag<Indexable>::type
  94. >::apply(pt, i);
  95. }
  96. }}}} // namespace boost::geometry::index::detail
  97. #endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MINMAXDIST_HPP