我正在使用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<float> BoostPoint;
typedef bg::model::polygon<BoostPoint> BoostPolygon;
typedef bg::model::multi_polygon<BoostPolygon> BoostMultipolygon;
std::vector<BoostPoint> 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<double> 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会在多边形上失败如此简单。为什么我会得到那些无关紧要的台词?如果任何其他信息有用,我将很乐意提供。
答案 0 :(得分:3)
我们无法说明,因为您未能包含源数据。你的&#34; currentContour&#34;可以包含任何东西。
使用原始数据 - 幸运的是 - 包括在内,我从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
的所有选项,我随机地&#34;已将join_miter
更改为join_round
,它就消失了:
<强> Live On Wandbox 强>
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/io/io.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <fstream>
#include <iostream>
namespace bg = boost::geometry;
typedef bg::model::d2::point_xy<float> BoostPoint;
typedef bg::model::polygon<BoostPoint> BoostPolygon;
typedef bg::model::multi_polygon<BoostPolygon> 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<double> 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<BoostPoint> 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");
}
}
答案 1 :(得分:0)
我无法使用Boost进行斜接。我改为切换到Clipper Library处理斜接的结尾而没有任何障碍。
答案 2 :(得分:0)
Boost::geometry::strategy::buffer::join_miter 在 1.71 版本之前有一个导致此行为的错误。更新 boost 应该可以解决这个问题。
相关的 GitHub 问题: https://github.com/boostorg/geometry/issues/596