我正在尝试使用boost::geometry::difference
计算两个多边形的差异,boost::geometry::model::polygon
代表我的多边形。
如果第一个多边形包含第二个结果,则操作的结果是单个boost::geometry::model::polygon
,内圈和外圈填充了源多边形的坐标。
如何从boost::geometry::model::polygon
获取多边形(in the elementary geometry sense)?
澄清:
在基本几何中,多边形是一个平面图形,由一条有限的直线段链接而成,这些直线段在一个环中闭合,形成一个封闭的链或电路。
boost::geometry::model::polygon
的外环是多边形,内环也是多边形。整体而言boost::geometry::model::polygon
不是多边形。
所以,我在问:如何将boost::geometry::model::polygon
转换为普通多边形(具有单条直线段链),它代表平面上的相同区域。
以下是我想要实现的目标:
polygon1 = (0,0), (0,8), (8,8), (8,0), (0,0)
polygon2 = (2,2), (2,6), (6,6), (6,2), (2,2)
多边形1& 2 in green / oker:
difference = (0,0), (0,4), (2,4), (2,2), (6,2), (6,6), (2,6), (2,4), (0,4), (0,8), (8,8), (8,0), (0,0)
灰色的预期差异:
我知道具有内环的相同boost::geometry::model::polygon
可以由无数多个不同的普通多边形表示。我不在乎我得到哪一个。
答案 0 :(得分:1)
您可以轻松构建一个模拟预期弱简单多边形的环。第一:
请注意,结果无法与Boost Geometry库的算法一起使用。
以你的文字为例:
std::string reason;
poly expected;
bg::read_wkt("POLYGON((0 0, 0 4, 2 4, 2 2, 6 2, 6 6, 2 6, 2 4, 0 4, 0 8, 8 8, 8 0, 0 0))", expected);
bool ok = bg::is_valid(expected, reason);
std::cout << "Expected: " << bg::dsv(expected) << (ok?" valid":" invalid: '" + reason + "'") << "\n";
打印
期望:(((0,0),(0,4),(2,4),(2,2),(6,2),(6,6),(2,6),( 2,4),(0,4),(0,8),(8,8),(8,0),(0,0)))无效:'几何具有无效的自相交。在(0,4)处发现了自交点;方法:t;操作:x / u;段ID {source,multi,ring,segment}:{0,-1,-1,0} / {0,-1,-1,7}'
有了这个,这里有一个简单的算法来构造给定多边形的简单弱多边形:
ring weak_simple_ring(poly& p) {
ring r = p.outer();
for (auto& i: p.inners()) {
auto last = r.back();
r.insert(r.end(), i.rbegin(), i.rend());
r.insert(r.end(), last);
}
return r;
}
唯一更微妙的一点就是反转内圈的方向(CW / CCW)以匹配外圈的方向。
该算法不会试图找到内环的切点,这也可能意味着它对于具有多个内环的通用情况不会很好地工作。
这是一个完整的现场演示
<强> Live On Coliru 强>
输入为
bg::read_wkt("POLYGON((0 0,0 10,10 10,10 0,0 0))", a);
bg::read_wkt("POLYGON((2 2, 2 6, 6 6, 6 2, 2 2))", b);
转型是
std::vector<poly> output;
bg::difference(a, b, output);
for (auto& p : output) {
ring r = weak_simple_ring(p);
bg::convert(r, p);
}
结果变为
考虑b
何时有漏洞:
bg::read_wkt("POLYGON((0 0,0 10,10 10,10 0,0 0))", a);
bg::read_wkt("POLYGON((2 2, 2 6, 6 6, 6 2, 2 2)(3 3, 5 3, 5 5, 3 5, 3 3))", b);
具有相同代码的输出变为
答案 1 :(得分:0)
这是旧答案。在编辑问题后,我发布了a simple implementation of an algorithm that suits the sample given
已经是。
如果你的意思是,&#34;简单&#34;无孔的多边形,外圈就是你想要的。只需丢弃内圈。
但是,在最通用的情况下,您最终可能会有多个完全不相关的多边形,这就是the output is a collection of polygons的原因。你也必须考虑这种可能性(可选择将不同的结果多边形连接到一个并丢弃内环,如果这是你想要的,在功能上)。
样本:
bg::read_wkt("POLYGON((0 0,0 10,10 10,10 0,0 0))", a);
bg::read_wkt("POLYGON((2 -2,2 12,5 12,5 -2,2 -2))", b);
此处,b
将a
分成两个单独的部分。因此,您必须准备好处理多个,不相交的输出多边形:
<强> Live On Coliru 强>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/io/io.hpp>
#include <iostream>
#include <fstream>
namespace bg = boost::geometry;
using pt = bg::model::d2::point_xy<int>;
using poly = bg::model::polygon<pt>;
int main() {
poly a, b;
bg::read_wkt("POLYGON((0 0,0 10,10 10,10 0,0 0))", a);
bg::read_wkt("POLYGON((2 -2,2 12,5 12,5 -2,2 -2))", b);
std::cout << bg::dsv(a) << "\n";
std::cout << bg::dsv(b) << "\n";
{
std::ofstream svg("/tmp/input.svg");
boost::geometry::svg_mapper<pt> mapper(svg, 400, 400);
mapper.add(a);
mapper.add(b);
mapper.map(a, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2");
mapper.map(b, "fill-opacity:0.5;fill:rgb(204,153,0);stroke:rgb(202,153,0);stroke-width:2");
}
std::vector<poly> output;
bg::difference(a, b, output);
for (auto& p : output)
std::cout << "\n\t" << bg::dsv(p);
{
std::ofstream svg("/tmp/output.svg");
boost::geometry::svg_mapper<pt> mapper(svg, 400, 400);
assert(output.size() == 2);
mapper.add(output[0]);
mapper.add(output[1]);
mapper.add(b);
mapper.map(output[0], "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2");
mapper.map(output[1], "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2");
mapper.map(b, "fill-opacity:0.15;fill:rgb(153,153,153);stroke-width:0");
}
}
打印:
(((0, 0), (0, 10), (10, 10), (10, 0), (0, 0)))
(((2, -2), (2, 12), (5, 12), (5, -2), (2, -2)))
(((5, 10), (10, 10), (10, 0), (5, 0), (5, 10)))
(((2, 10), (2, 0), (0, 0), (0, 10), (2, 10)))
呈现的SVG: