提高内点的几何多边形距离

Posted

技术标签:

【中文标题】提高内点的几何多边形距离【英文标题】:boost geometry polygon distance for inside point 【发布时间】:2018-07-10 14:15:53 【问题描述】:

我正在使用boost::geometry 处理一些几何任务。我有两个要求需要满足:

处理点 -> 多边形交点(在内部或不在)。这对boost::geometry::within 很有效,所以很好 获取任意点到多边形最近边缘的距离。虽然boost::geometry::distance 正确处理了多边形外的点,但它似乎认为多边形是实心的。所以多边形内的每个点到多边形的距离显然都是 0。

我尝试用内部/外部的东西做实验,想知道是否有可能获得多边形内部和外部点的距离。

【问题讨论】:

【参考方案1】:

如果点在多边形内,您可以使用comparable_distance 而不是distance 算法来加速您的代码。您不需要计算每个段点对的确切距离。使用comparable_distance 找到距离给定点最近的多边形段,然后使用distance 算法计算实际距离。

auto distance = std::numeric_limits<float>::max();
if(boost::geometry::within(pt, mPolygon)) 

  Segment nearestSegment;
  boost::geometry::for_each_segment(mPolygon, 
    [&distance, &pt, &nearestSegment](const auto& segment) 
     
        double cmpDst = boost::geometry::comparable_distance(segment,pt);
        if (cmpDst < distance)
        
          distance = cmpDst;
          nearestSegment = segment; // UPDATE NEAREST SEGMENT
        
      );
      // CALCULATE EXACT DST
      distance = boost::geometry::distance(nearestSegment,pt);
 else 
  distance = boost::geometry::distance(pt, mPolygon);

【讨论】:

【参考方案2】:

我决定使用以下方法,到目前为止似乎提供了正确的结果:

const TPolygonPoint pt x, y ;
auto distance = std::numeric_limits<float>::max();

if(boost::geometry::within(pt, mPolygon)) 
    boost::geometry::for_each_segment(mPolygon, [&distance, &pt](const auto& segment) 
        distance = std::min<float>(distance, boost::geometry::distance(segment, pt));
    );
 else 
    distance = boost::geometry::distance(pt, mPolygon);


return distance;

如果有人知道更快或更好的方法,请发表评论:)

【讨论】:

我得到了正确的结果,而我的结果与 rafix07 答案不连贯,我得到了一个相当远的部分。我没有进一步调查。我正在计算从 point_xy 到环的距离。谢谢!【参考方案3】:

为了获得最佳性能,您应该使用带有 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(point10 * c, 10 * s);
        poly.inners().resize(1);
        poly.inners()[0].push_back(point5 * 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;

【讨论】:

【参考方案4】:

如果将内边界添加到与外边界重合的多边形 [Polygon Concept],则可以直接使用 boost::geometry::distance。

#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>

namespace bg = boost::geometry;

int main() 
    typedef bg::model::point<int, 2, bg::cs::cartesian> point_t;
    typedef bg::model::polygon<point_t> polygon_t;

    polygon_t poly1;    

    bg::append (poly1.outer(), point_t (1, -1));
    bg::append (poly1.outer(), point_t (1, 1));
    bg::append (poly1.outer(), point_t (-1, 1));
    bg::append (poly1.outer(), point_t (-1, -1));
    bg::append (poly1.outer(), point_t (1, -1));

    poly1.inners().resize (1);
    bg::append (poly1.inners()[0], point_t (1, -1));
    bg::append (poly1.inners()[0], point_t (1, 1));
    bg::append (poly1.inners()[0], point_t (-1, 1));
    bg::append (poly1.inners()[0], point_t (-1, -1));
    bg::append (poly1.inners()[0], point_t (1, -1));


    point_t myPoint (0, 0);
    std::cout << "Minimal distance: " << bg::distance (poly1, myPoint) << std::endl;
    std::cout << "Is within: " << bg::within (myPoint, poly1) << std::endl;

    return 0;

-> 将返回:

    Minimal distance: 1
    Is within: 0

但是,如果您这样做,则严格位于多边形内部的点将被 boost::geometry::within 视为位于多边形“外部”。如果你想要这两种功能,你可以维护两个单独的多边形——一个有内边界,一个没有。

【讨论】:

以上是关于提高内点的几何多边形距离的主要内容,如果未能解决你的问题,请参考以下文章

点到多边形最近边的距离

POJ 1113 Wall(思维 计算几何 数学)

JTS 空间数据关系分析

EOJ 1127. 多边形面积(计算几何)

R中多边形内点(shapefile)的选择和提取

JTS 空间数据关系分析