基于Boost Geometry buffer实现多边形扩大或缩小(buffer)

参考官方教程:        buffer (with strategies) - 1.73.0icon-default.png?t=M276https://www.boost.org/doc/libs/1_73_0/libs/geometry/doc/html/geometry/reference/algorithms/buffer/buffer_7_with_strategies.html某些场景下需要对多边形的边界进行一定距离的扩大或缩小,查找相关资料时发现了boost的geometry这个宝藏库,提供了个针对几何图形操作的接口,下面简单介绍一下对上面链接中官方buffer demo中的一个参数

"points_per_circle" 测试的理解,从变量命名的字面意思看是每圈的点数,估计可能是膨胀或缩小后的插值数,不太确定,于是写了个demo简单调试了一下。

采用ros在rviz工具作为可视化,将多边形边界点集发布为geometry_msgs::PolygonStamped消息, 假设原始边界为一个纵向200m(x轴方向,正向150m, 负方向50m), 横向100m(左右各50m)的矩形,原点x轴正向超上,y正向轴朝左.rviz Grid中每个格子10m.

在处理原始多边形形框的函数里如下

void BufferPolygon(
    const PointArrayConstPtr &map_ptr, const float distance,
    geometry_msgs::PolygonStampedPtr map_msg) {
  // Declare strategies
  // const double buffer_distance = 0;
  // <=4就是9个点,>4(最少5个点)比扩展前点多就至少拐角补一个点,>2*size(最少9个点)补两个点
  const int points_per_circle = map_ptr->array.size() + 1;
  boost::geometry::strategy::buffer::distance_symmetric<double>
      distance_strategy(distance);
  boost::geometry::strategy::buffer::join_round join_strategy(
      points_per_circle);
  boost::geometry::strategy::buffer::end_round end_strategy(points_per_circle);
  boost::geometry::strategy::buffer::point_circle circle_strategy(
      points_per_circle);
  boost::geometry::strategy::buffer::side_straight side_strategy;
  boost::geometry::model::multi_polygon<polygon> mpol;
  polygon map_polygon;
  for (const auto &pt : map_ptr->array) {
    boost::geometry::append(map_polygon, make<point_type>(pt.x, pt.y));
  }
  correct(map_polygon);
  mpol.push_back(map_polygon);
  // Declare output
  boost::geometry::model::multi_polygon<polygon> result;
  // Create the buffer of a multi polygon
  boost::geometry::buffer(mpol, result, distance_strategy, side_strategy,
                          join_strategy, end_strategy, circle_strategy);

  map_msg->polygon.points.resize(result[0].outer().size());
  for (size_t i = 0; i < result[0].outer().size(); i++) {
    map_msg->polygon.points[i].x = result[0].outer()[i].x();
    map_msg->polygon.points[i].y = result[0].outer()[i].y();
    map_msg->polygon.points[i].z = 0;
  }
}

当边界为设定的矩形时,原始边框有4个点,当输入buffer distance>0时,经测试,当设置points_per_circle

<=4个点时,输出9个点(每个角多一个点,不插值,首尾点相连,加一个)

 

当>4(最少5个点)比扩展前点就至少拐角插值补一个点, 即输出多边形点数为(2+1)*4+1 = 13, 

 

当>2*size(最少9个点)补两个点,即(2+2)*4+1 = 17,个点。

输出如下,注意边界拐角插值了两个点:

插值点数越多,拐角越平滑。

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要基于线上的点将线分为两段,可以使用Boost.Geometry库中的相应API。以下是一个示例代码: ```cpp #include <iostream> #include <vector> #include <boost/geometry.hpp> #include <boost/geometry/geometries/point.hpp> #include <boost/geometry/geometries/linestring.hpp> #include <boost/geometry/algorithms/split.hpp> namespace bg = boost::geometry; int main() { // 定义线和点 bg::model::linestring<bg::model::point<double, 2, bg::cs::cartesian>> line; bg::model::point<double, 2, bg::cs::cartesian> point_on_line; // 向线中添加点 line.push_back(bg::make<bg::model::point<double, 2>>(0, 0)); // 第一个点 line.push_back(bg::make<bg::model::point<double, 2>>(1, 1)); // 第二个点 line.push_back(bg::make<bg::model::point<double, 2>>(2, 2)); // 第三个点 // 设置线上的点 point_on_line = bg::make<bg::model::point<double, 2>>(1.5, 1.5); // 分割线为两段 std::vector<bg::model::linestring<bg::model::point<double, 2, bg::cs::cartesian>>> output; bg::split(line, point_on_line, output); // 输出结果 std::cout << "Line 1: "; for (const auto& point : output[0]) { std::cout << "(" << bg::get<0>(point) << ", " << bg::get<1>(point) << ") "; } std::cout << std::endl; std::cout << "Line 2: "; for (const auto& point : output[1]) { std::cout << "(" << bg::get<0>(point) << ", " << bg::get<1>(point) << ") "; } std::cout << std::endl; return 0; } ``` 上面的代码中,我们首先定义了一条线`line`和一个在线上的点`point_on_line`。然后,我们向线中添加了三个点,并设置了在线上的点。接下来,我们使用`bg::split`函数将线分割为两段,并将结果存储在`output`变量中。最后,我们输出了分割后的两条线`output[0]`和`output[1]`。 值得注意的是,上面的示例代码使用了二维笛卡尔坐标系`bg::cs::cartesian`,你可以根据实际情况修改坐标系。另外,如果要分割的点不在线上,`bg::split`函数会将线分割为两个线段(即`output`中会有两个元素)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值