我正在使用Boost::Geometry::Buffer来创建不规则形状多边形的内部偏移或膨胀。下图显示了一个输入和输出示例。原始多边形显示为白色,偏移多边形显示为紫色。紫色多边形的右侧有两组无关的线(显示为较粗/较亮的区域),左侧有一个长长的无关尖峰。
示例中使用的多边形非常基础。它缺乏任何类型的对称性,但没有尖锐的转弯或锯齿状的边缘。输入多边形的原始数据是以下笛卡尔点列表:
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
这是我用来生成偏移多边形的代码:
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会在如此简单的多边形上失败。为什么我会得到那些无关的行?如果任何其他信息将是有帮助的,我将很乐意提供它。
发布于 2021-02-25 21:11:33
Boost::geometry::strategy::buffer::join_在1.71之前的版本中,miter存在导致此行为的错误。更新boost应该可以解决这个问题。
发布于 2017-07-13 17:11:25
我们无法判断,因为您没有包含源数据。你的"currentContour“可以包含任何东西。
幸运的是,我使用的是您包含的原始数据,我从WKT中读取了多边形:
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);
在那之后,我得到了一个干净的缓冲区,但我看到了尖峰。没有精通所有的选项buffer
,我“随机”改变join_miter
至join_round
然后它就消失了:
Wandbox**](https://wandbox.org/permlink/4SOwaGC17qcXAgdZ)上的
#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");
}
}
发布于 2017-07-14 04:18:42
我不能让斜接的末端与Boost一起工作。我转而使用
裁剪器[Clipper Library它能毫不费力地处理斜接的末端。
https://stackoverflow.com/questions/45067757
复制相似问题