mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-12 12:12:10 +00:00
k-nearest query optimized by use of heap instead of sorting.
[SVN r74608]
This commit is contained in:
@@ -73,22 +73,30 @@ public:
|
||||
inline explicit nearest_k(size_t k)
|
||||
: m_count(k)
|
||||
{
|
||||
// TEMP?
|
||||
m_neighbors.reserve(m_count + 1);
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_count, "Number of neighbors should be greater than 0");
|
||||
|
||||
m_neighbors.reserve(m_count);
|
||||
}
|
||||
|
||||
inline void store(Value const& val, distance_type const& curr_comp_dist)
|
||||
{
|
||||
m_neighbors.push_back(std::make_pair(curr_comp_dist, val));
|
||||
std::sort(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
|
||||
if ( m_neighbors.size() < m_count )
|
||||
{
|
||||
m_neighbors.push_back(std::make_pair(curr_comp_dist, val));
|
||||
|
||||
if ( m_count < m_neighbors.size() )
|
||||
m_neighbors.pop_back();
|
||||
|
||||
// TODO: awulkiew - test other methods:
|
||||
// heap, manual inserting
|
||||
// don't sort if size < k ?
|
||||
// check the furthest distance at the first place, before push_back()
|
||||
if ( m_neighbors.size() == m_count )
|
||||
std::make_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( curr_comp_dist < m_neighbors.front().first )
|
||||
{
|
||||
std::pop_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
|
||||
m_neighbors.back().first = curr_comp_dist;
|
||||
m_neighbors.back().second = val;
|
||||
std::push_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool is_comparable_distance_valid() const
|
||||
@@ -98,9 +106,9 @@ public:
|
||||
|
||||
inline distance_type comparable_distance() const
|
||||
{
|
||||
return m_neighbors.size() < m_count ?
|
||||
std::numeric_limits<distance_type>::max() :
|
||||
m_neighbors.back().first;
|
||||
return m_neighbors.size() < 0
|
||||
? std::numeric_limits<distance_type>::max()
|
||||
: m_neighbors.front().first;
|
||||
}
|
||||
|
||||
template <typename OutIter>
|
||||
@@ -123,6 +131,7 @@ private:
|
||||
|
||||
size_t m_count;
|
||||
std::vector< std::pair<distance_type, Value> > m_neighbors;
|
||||
distance_type m_biggest_comp_dist;
|
||||
};
|
||||
|
||||
// TODO: awulkiew - add additional pruning before adding nodes to the ABL
|
||||
|
||||
@@ -148,6 +148,43 @@ namespace helpers
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Point, typename Cont, typename Translator>
|
||||
bool nearest_results_compare(Point const& p, Cont const& c1, Cont const& c2, Translator const& tr)
|
||||
{
|
||||
namespace bg = boost::geometry;
|
||||
namespace bgi = boost::geometry::index;
|
||||
|
||||
typedef typename Translator::indexable_type indexable_type;
|
||||
typedef bg::default_distance_result<Point, indexable_type>::type distance_type;
|
||||
|
||||
if ( c1.size() != c2.size() )
|
||||
return false;
|
||||
|
||||
if ( c1.size() == 0 && c2.size() == 0 )
|
||||
return true;
|
||||
|
||||
distance_type biggest_distance1 = 0;
|
||||
|
||||
for ( typename Cont::const_iterator it = c1.begin() ; it != c1.end() ; ++it )
|
||||
{
|
||||
distance_type curr_distance = bgi::comparable_distance_near(p, tr(*it));
|
||||
|
||||
if ( biggest_distance1 < curr_distance )
|
||||
biggest_distance1 = curr_distance;
|
||||
}
|
||||
|
||||
distance_type biggest_distance2 = 0;
|
||||
for ( typename Cont::const_iterator it = c2.begin() ; it != c2.end() ; ++it )
|
||||
{
|
||||
distance_type curr_distance = bgi::comparable_distance_near(p, tr(*it));
|
||||
|
||||
if ( biggest_distance2 < curr_distance )
|
||||
biggest_distance2 = curr_distance;
|
||||
}
|
||||
|
||||
return biggest_distance1 == biggest_distance2;
|
||||
}
|
||||
|
||||
template <typename Predicate, typename Rtree, typename Cont, typename Randomizer>
|
||||
void random_query_check(Rtree const& t, Cont const& c, size_t n, Randomizer r)
|
||||
{
|
||||
@@ -233,7 +270,7 @@ namespace helpers
|
||||
std::stringstream ss;
|
||||
ss << "\nPredicate: " << typeid(Predicate).name() << "\nres1: " << res1.size() << ", res2: " << res2.size() << '\n';
|
||||
|
||||
BOOST_CHECK_MESSAGE( helpers::results_compare(res1, res2, t.get_translator()), ss.str());
|
||||
BOOST_CHECK_MESSAGE(helpers::nearest_results_compare(pt, res1, res2, t.get_translator()), ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user