簡體   English   中英

提高內部點的幾何多邊形距離

[英]boost geometry polygon distance for inside point

我正在使用boost::geometry處理一些幾何任務。 我需要滿足兩個要求:

  • 處理點->多邊形相交(是否在內部)。 這與boost::geometry::within一起使用效果很好,那就很好
  • 獲取任意點到多邊形最近邊緣的距離。 雖然可以通過boost::geometry::distance正確處理多邊形外部的點,但是似乎將多邊形視為實體。 因此,多邊形內的每個點到多邊形的距離顯然為0。

我嘗試對內部/外部內容進行實驗,想知道是否有可能獲取多邊形的內部和外部點的距離。

如果點在多邊形內部,則可以使用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);
}

我決定使用以下方法,到目前為止似乎可以提供正確的結果:

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;

如果有人知道更快或更更好的方法,請發表評論:)

為了獲得最佳性能,您應該使用帶有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;
}

如果您向與外邊界重合的多邊形添加內邊界[ 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將嚴格限制在多邊形內部的點視為在多邊形“外部”。 如果需要這兩種功能,則可以維護兩個單獨的多邊形-一個具有內部邊界,另一個不具有內部邊界。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM