boost::geometry: nearest neighbors using a circle

筅森魡賤 提交于 2019-11-30 09:01:12

The last example in the documented "User-defined queries" shows how to use a lambda in the predicate. This lambda can bind other variables in the scope, for instance, the point whose neighbors you are looking for.

Here is a small example. The example looks for points that are closer to (5, 5) than 2 units, for a collection of points that lie on the straight y = x. It should be easy to modify in order to check first if the sought point is in the R-tree, or get it directly out of the R-tree.

#include <iostream>

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/index/rtree.hpp>


namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;

typedef bg::model::point<float, 2, bg::cs::cartesian> point;
typedef std::pair<point, unsigned> value;

int main(int argc, char *argv[])
{
    bgi::rtree< value, bgi::quadratic<16> > rtree;

    // create some values
    for ( unsigned i = 0 ; i < 10 ; ++i )
    {
        point p = point(i, i);
        rtree.insert(std::make_pair(p, i));
    }

    // search for nearest neighbours
    std::vector<value> returned_values;
    point sought = point(5, 5);
    rtree.query(bgi::satisfies([&](value const& v) {return bg::distance(v.first, sought) < 2;}),
                std::back_inserter(returned_values));

    // print returned values
    value to_print_out;
    for (size_t i = 0; i < returned_values.size(); i++) {
        to_print_out = returned_values[i];
        float x = to_print_out.first.get<0>();
        float y = to_print_out.first.get<1>();
        std::cout << "Select point: " << to_print_out.second << std::endl;
        std::cout << "x: " << x << ", y: " << y << std::endl;
    }

    return 0;
}

Compile and run with Boost installed via Macports on OS X:

$ c++ -std=c++11 -I/opt/local/include -L/opt/local/lib main.cpp -o geom && ./geom
Select point: 4
x: 4, y: 4
Select point: 5
x: 5, y: 5
Select point: 6
x: 6, y: 6

The manual documents some model::ring class that I thought at first might fit for a circle, but it is actually more a kind of a piece-wise line (a polygon). Is that assumption correct ?

I think that's correct.

I noticed that you can define a unary-predicate, but is is... unary (thus, not suitable for a condition on two points).

Would the 'second' (or reference) point not be fixed? Because then you can use a simple bind expression to supply the reference point.


Additionally you can use the KNN algorithm with a very large n and add some kind of breaking condition on the predicate:

Breaking or pausing the query

for ( Rtree::const_query_iterator it = tree.qbegin(bgi::nearest(pt, 10000)) ;
      it != tree.qend() ; ++it )
{
    // do something with value
    if ( has_enough_nearest_values() )
        break;
}

This could work pretty well, assuming that the algorithm already traverses the points in order of ascending distance (you will want to check that assumption of course).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!