minmaxdist.hpp 4.2 KB

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