首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Boost Geometry进行面缓冲时结果不佳或不正确

使用Boost Geometry进行面缓冲时结果不佳或不正确
EN

Stack Overflow用户
提问于 2017-07-13 05:24:40
回答 3查看 1.6K关注 0票数 3

我正在使用Boost::Geometry::Buffer来创建不规则形状多边形的内部偏移或膨胀。下图显示了一个输入和输出示例。原始多边形显示为白色,偏移多边形显示为紫色。紫色多边形的右侧有两组无关的线(显示为较粗/较亮的区域),左侧有一个长长的无关尖峰。

示例中使用的多边形非常基础。它缺乏任何类型的对称性,但没有尖锐的转弯或锯齿状的边缘。输入多边形的原始数据是以下笛卡尔点列表:

代码语言:javascript
运行
复制
x: 61.2101898, y: 81.9854202
x: 61.3715706, y: 82.0616913
x: 61.4335442, y: 82.1924744
x: 61.4778328, y: 82.2606735
x: 61.5202942, y: 82.3236465
x: 61.5283432, y: 82.3527832
x: 61.5431557, y: 82.4063950
x: 61.5221367, y: 82.4381790
x: 61.3944855, y: 82.4706116
x: 61.3497124, y: 82.4679184
x: 61.3284111, y: 82.4674301
x: 61.1539803, y: 82.3401947
x: 61.1297760, y: 82.2854843
x: 61.0671043, y: 82.1489639
x: 61.0682831, y: 82.0264740
x: 61.0667953, y: 82.0112915
x: 61.0663414, y: 82.0066376
x: 61.0707321, y: 81.9976196
x: 61.0998306, y: 81.9980850
x: 61.2101898, y: 81.9854202

这是我用来生成偏移多边形的代码:

代码语言:javascript
运行
复制
namespace bg = boost::geometry;
typedef bg::model::d2::point_xy BoostPoint;
typedef bg::model::polygon BoostPolygon;
typedef bg::model::multi_polygon BoostMultipolygon;

std::vector points;
BoostPoint tmpPoint;
BoostPolygon input;
BoostMultipolygon output;

/* currentContour is a pointer to a non-Boost specialized polygon
*  structure. It contains a bool indicating clockwise/counterclockwise
*  direction and a list of lines, each line defined by two x-y points.
*  For each line, point 2 follows point 1 in the clockwise/counterclockwise
*  direction of that polygon.
*/

if (currentContour->clockwise) {
    for (int line = 0; line < currentContour->lines.size(); line++) {
        bg::set<0>(tmpPoint, currentContour->lines[line].x1);
        bg::set<1>(tmpPoint, currentContour->lines[line].y1);
        points.push_back(tmpPoint);
    }
    // Add last point to wrap back around to starting point.
    bg::set<0>(tmpPoint, currentContour->lines.back().x2);
    bg::set<1>(tmpPoint, currentContour->lines.back().y2);
    points.push_back(tmpPoint);
}
else {
    for (int line = currentContour->lines.size() - 1; line >= 0; line--) {
        bg::set<0>(tmpPoint, currentContour->lines[line].x2);
        bg::set<1>(tmpPoint, currentContour->lines[line].y2);
        points.push_back(tmpPoint);
    }
    // Add last point to wrap back around to starting point.
    bg::set<0>(tmpPoint, currentContour->lines.front().x1);
    bg::set<1>(tmpPoint, currentContour->lines.front().y1);
    points.push_back(tmpPoint);
}

// Transfer points to polygon object.
bg::assign_points(input, points);
// Declare boost strategies for buffer function.
bg::strategy::buffer::distance_symmetric distance_strategy(-0.05);
bg::strategy::buffer::join_miter join_strategy;
bg::strategy::buffer::end_round end_strategy;
bg::strategy::buffer::point_circle point_strategy;
bg::strategy::buffer::side_straight side_strategy;
// Perform polygon buffering.
bg::buffer(input, output, distance_strategy, side_strategy, join_strategy,
    end_strategy, point_strategy);

Boost是一个主要的有声望的库,所以我很难相信它的几何API会在如此简单的多边形上失败。为什么我会得到那些无关的行?如果任何其他信息将是有帮助的,我将很乐意提供它。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-02-25 21:11:33

Boost::geometry::strategy::buffer::join_在1.71之前的版本中,miter存在导致此行为的错误。更新boost应该可以解决这个问题。

相关GitHub问题:https://github.com/boostorg/geometry/issues/596

票数 0
EN

Stack Overflow用户

发布于 2017-07-13 17:11:25

我们无法判断,因为您没有包含源数据。你的"currentContour“可以包含任何东西。

幸运的是,我使用的是您包含的原始数据,我从WKT中读取了多边形:

代码语言:js
复制
boost::geometry::read_wkt("POLYGON((61.2101898 81.9854202, 61.3715706 82.0616913, 61.4335442 82.1924744, 61.4778328 82.2606735, 61.5202942 82.3236465, 61.5283432 82.3527832, 61.5431557 82.4063950, 61.5221367 82.4381790, 61.3944855 82.4706116, 61.3497124 82.4679184, 61.3284111 82.4674301, 61.1539803 82.3401947, 61.1297760 82.2854843, 61.0671043 82.1489639, 61.0682831 82.0264740, 61.0667953 82.0112915, 61.0663414 82.0066376, 61.0707321 81.9976196, 61.0998306 81.9980850, 61.2101898 81.9854202))", input);

验证失败,因为它在错误的方向上:

我不知道你的方向是否被顺时针标志正确管理,所以检查如下:

代码语言:javascript
运行
复制
{
    std::string reason;
    if (!bg::is_valid(input, reason))
        std::cout << "Input is not valid: " << reason << "\n";
}

如果您需要修复任何可修复的错误:

代码语言:js
复制
bg::correct(input);

在那之后,我得到了一个干净的缓冲区,但我看到了尖峰。没有精通所有的选项buffer,我“随机”改变join_miterjoin_round然后它就消失了:

Wandbox**](https://wandbox.org/permlink/4SOwaGC17qcXAgdZ)上的

代码语言:javascript
运行
复制
#include 
#include 
#include 
#include 
#include 

namespace bg = boost::geometry;
typedef bg::model::d2::point_xy BoostPoint;
typedef bg::model::polygon BoostPolygon;
typedef bg::model::multi_polygon BoostMultipolygon;

int main() {
    BoostPolygon input;
    BoostMultipolygon output;

    boost::geometry::read_wkt("POLYGON((61.2101898 81.9854202, 61.3715706 82.0616913, 61.4335442 82.1924744, 61.4778328 82.2606735, 61.5202942 82.3236465, 61.5283432 82.3527832, 61.5431557 82.4063950, 61.5221367 82.4381790, 61.3944855 82.4706116, 61.3497124 82.4679184, 61.3284111 82.4674301, 61.1539803 82.3401947, 61.1297760 82.2854843, 61.0671043 82.1489639, 61.0682831 82.0264740, 61.0667953 82.0112915, 61.0663414 82.0066376, 61.0707321 81.9976196, 61.0998306 81.9980850, 61.2101898 81.9854202))", input);
    {
        std::string reason;
        if (!bg::is_valid(input, reason))
            std::cout << "Input is not valid: " << reason << "\n";
    }
    bg::correct(input);
    {
        std::string reason;
        if (!bg::is_valid(input, reason))
            std::cout << "Input is not valid: " << reason << "\n";
        else
            std::cout << "Input is valid";
    }

    // Declare boost strategies for buffer function.
    bg::strategy::buffer::distance_symmetric distance_strategy(-0.05);
    bg::strategy::buffer::join_round join_strategy;
    bg::strategy::buffer::end_round end_strategy;
    bg::strategy::buffer::point_circle point_strategy;
    bg::strategy::buffer::side_straight side_strategy;
    // Perform polygon buffering.
    bg::buffer(input, output, distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy);

    {
        std::ofstream svg("output.svg");
        boost::geometry::svg_mapper mapper(svg, 400, 400);
        mapper.add(output);
        mapper.add(input);

        mapper.map(input, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2");
        mapper.map(output, "fill-opacity:0.5;fill:rgb(204,153,0);stroke:rgb(202,153,0);stroke-width:2");
    }
}

票数 3
EN

Stack Overflow用户

发布于 2017-07-14 04:18:42

我不能让斜接的末端与Boost一起工作。我转而使用

裁剪器[Clipper Library它能毫不费力地处理斜接的末端。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45067757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档