2017-07-12 31 views
2

我正在使用Boost :: Geometry :: Buffer创建不规则形状多边形的内部偏移量或膨胀。下图显示了一个示例输入和输出。原始多边形显示为白色,偏移多边形显示为紫色。紫色多边形右侧有两组外部线条(看起来像是较厚/较亮的区域),左边是一个很长的无关尖峰。使用Boost几何体进行多边形缓冲时结果不正确或不正确

Example output from 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); 

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

+0

“万一有用”的原始数据。什么。这是最有用的一点。 – sehe

+2

Geez。谁是建设性的。或者跳动。我很抱歉我花了时间。我猜? – sehe

+1

@ChrisD如果你知道问题是什么,为什么还要问这里? –

回答

2

我们不能说,因为你没有包括源数据。您的“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_miterjoin_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"); 
    } 
} 

enter image description here

+0

我很欣赏这种回应。我必须弄清楚我的取向概念与Boost的不同。不幸的是,我的用例需要尖端。任何人都知道为什么测试结果不起作用? –

+0

我不知道。也许你可以问一个简单的,有针对性的问题。而且我会考虑发布到图书馆邮件列表,因为开发者在那里非常活跃(他们也是零星贡献) – sehe

0

我不能以获得与Boost一起工作的端点。我反而切换到Clipper Library,它处理斜切结尾。