boost :: geometry测量点到多边形环的最大/最小距离的最有效方法

时间:2015-08-26 14:44:32

标签: c++ boost polygon boost-geometry

我一直在程序中使用boost::geometry库,主要用于处理多边形对象。

我现在正在尝试优化我的代码以使用更大的多边形更好地扩展。我的一个函数检查给定的多边形和给定的点(通常在多边形内),点和多边形外环之间的最小和最大距离。

我是通过在多边形边上循环来实现的:

polygon pol;
point myPoint;
double min = 9999999, max = 0;
for(auto it1 = boost::begin(bg::exterior_ring(pol)); it1 != boost::end(bg::exterior_ring(pol)); ++it1){
    double distance = bg::distance(*it1, myPoint);
        if(max < distance)
            max = distance;
        if(min > distance)
            min = distance;
    }

我希望有比这更快的算法,在边的多边形数量上是线性的。 boost::geometry库中是否已存在此类内容?

1 个答案:

答案 0 :(得分:0)

为获得最佳性能,应使用带有boost :: geometry :: index的RTree。创建RTree会有一定的成本,但是计算到任何(多)多边形环的点的距离会更快。示例代码:

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

int main()
{
    namespace bg = boost::geometry;
    namespace bgi = boost::geometry::index;
    typedef bg::model::point<double, 2, bg::cs::cartesian> point;
    typedef bg::model::polygon<point> polygon;

    point p{ 0, 0 };
    // create some polygon and fill it with data
    polygon poly;
    double a = 0;
    double as = bg::math::two_pi<double>() / 100;
    for (int i = 0; i < 100; ++i, a += as)
    {
        double c = cos(a);
        double s = sin(a);
        poly.outer().push_back(point{10 * c, 10 * s});
        poly.inners().resize(1);
        poly.inners()[0].push_back(point{5 * c, 5 * s});
    }
    // make sure it is valid
    bg::correct(poly);

    // create rtree containing objects of type bg::model::pointing_segment
    typedef bg::segment_iterator<polygon const> segment_iterator;
    typedef std::iterator_traits<segment_iterator>::value_type segment_type;

    bgi::rtree<segment_type, bgi::rstar<4> > rtree(bg::segments_begin(poly),
                                                   bg::segments_end(poly));

    // get 1 nearest segment
    std::vector<segment_type> result;
    rtree.query(bgi::nearest(p, 1), std::back_inserter(result));

    BOOST_ASSERT(!result.empty());

    std::cout << bg::wkt(result[0]) << ", " << bg::distance(p, result[0]) << std::endl;

    return 0;
}