在Boost.Geometry中将两个多边形组合成一个多边形:只有外点,没有洞
Posted
技术标签:
【中文标题】在Boost.Geometry中将两个多边形组合成一个多边形:只有外点,没有洞【英文标题】:Combining two polygons into one polygon in Boost.Geometry: Exterior points only, no holes 【发布时间】:2020-07-05 13:12:45 【问题描述】:我有两个多边形。我想将它们组合成一个多边形,使其仅包含外部点而没有任何孔。 我该怎么做?几乎没有解释的代码将非常有帮助。谢谢。 请参阅图片以更好地理解。
【问题讨论】:
【参考方案1】:我认为你可以使用union_
算法
polygon a, b;
bg::read_wkt("POLYGON((0 0, 5 5, 9 0, 0 0))", a);
bg::read_wkt("POLYGON((5 1, 10 5, 10 -2, 5 1))", b);
std::string reason;
std::cout << std::boolalpha;
std::cout << bg::is_valid(a, reason) << " (" << reason << ")\n";
std::cout << bg::is_valid(b, reason) << " (" << reason << ")\n";
multi_polygon ab;
bg::union_(a, b, ab);
write_svg("union.svg", a, b, ab);
创造
麻烦
当然,用你的第二个例子代替
bg::read_wkt("POLYGON((0 0, 0 5, 3 5, 1 2, 3 0, 0 0))", a);
bg::read_wkt("POLYGON((5 0, 10 5, 14 0, 5 0))", b);
只是单独生成多边形。这是正确答案:
这是正确的,因为没有重叠。像你一样用力将多边形拍打在一起是
任意(你可以通过不同的人工线路加入它们) 无效(生成的多边形是自相交的)参见例如
for (auto wkt :
"POLYGON((0 0, 0 5, 3 5, 1 2, 3 0, 5 0, 10 5, 14 0, 5 0, 3 0, 0 0))",
"POLYGON((0 0, 0 5, 3 5, 1 2, 3 0, 5 0, 10 5, 14 0, 5 0, 0 0))",
"POLYGON((0 0, 0 5, 3 5, 1 2, 3 0, 5 0, 10 5, 14 0, 0 0))",
)
polygon invalid;
bg::read_wkt(wkt, invalid);
std::cout << bg::is_valid(invalid, reason) << " (" << reason << ")\n";
打印
false (Geometry has invalid self-intersections. A self-intersection point was found at (3, 0); method: t; operations: x/i; segment IDs source, multi, ring, segment: 0, -1, -1, 3/0, -1, -1, 8)
false (Geometry has invalid self-intersections. A self-intersection point was found at (3, 0); method: m; operations: x/i; segment IDs source, multi, ring, segment: 0, -1, -1, 3/0, -1, -1, 8)
false (Geometry has invalid self-intersections. A self-intersection point was found at (3, 0); method: m; operations: x/i; segment IDs source, multi, ring, segment: 0, -1, -1, 3/0, -1, -1, 7)
强制问题
不起作用,例如:
polygon force_combine;
bg::append(force_combine, a.outer());
bg::append(force_combine, b.outer());
force_fix(force_combine);
有
template <typename G> void force_fix(G& g)
G previous;
std::string reason;
do
if (bg::is_valid(g, reason))
return;
std::cout << "Invalid: " << reason << "\n";
previous = g;
bg::correct(g);
while (!bg::equals(previous, g));
std::cout << "Warning: could not force_fix\n";
打印
Invalid: Geometry is defined as closed but is open
Warning: could not force_fix
完整的演示代码
Live On Coliru
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <iostream>
namespace bg = boost::geometry;
namespace bgm = bg::model;
using point = bgm::d2::point_xy<double>;
using polygon = bgm::polygon<point>;
using multi_polygon = bgm::multi_polygon<polygon>;
template <typename G>
void write_svg(std::string fname, polygon const& a, polygon const& b, G const& g);
template <typename G>
void force_fix(G& g);
struct std::string a,b; const examples[] =
"POLYGON((0 0, 5 5, 9 0, 0 0))",
"POLYGON((5 1, 10 5, 10 -2, 5 1))" ,
"POLYGON((0 0, 0 5, 3 5, 1 2, 3 0, 0 0))",
"POLYGON((5 0, 10 5, 14 0, 5 0))" ;
int main()
int n = 0;
for (auto example : examples)
++n;
polygon a, b;
bg::read_wkt(example.a, a);
bg::read_wkt(example.b, b);
force_fix(a); // input sanitation if needed
force_fix(b);
multi_polygon ab;
bg::union_(a, b, ab);
write_svg("example" + std::to_string(n) + ".svg", a, b, ab);
std::cout << "Example " << n << " is compound? " << (ab.size() > 1) << "\n";
#include <fstream>
template <typename G>
void write_svg(std::string fname, polygon const& a, polygon const& b, G const& g)
std::ofstream ofs(fname);
bg::svg_mapper<point> mapper(ofs, 400, 400);
mapper.add(g);
mapper.map(g, "fill-opacity:0.1;fill:rgb(100,0,0);stroke:rgb(200,0,0);stroke-width:2", 5);
mapper.add(a);
mapper.map(a, "fill-opacity:0.01;fill:rgb(0,100,0);stroke:rgb(0,200,0);stroke-width:1;stroke-dasharray:4", 5);
mapper.add(b);
mapper.map(b, "fill-opacity:0.01;fill:rgb(0,0,100);stroke:rgb(0,0,200);stroke-width:1;stroke-dasharray:4", 5);
template <typename G> void force_fix(G& g)
G previous;
std::string reason;
do
if (bg::is_valid(g, reason))
return;
std::cout << "Invalid: " << reason << "\n";
previous = g;
bg::correct(g);
while (!bg::equals(previous, g));
std::cout << "Warning: could not force_fix\n";
打印
Example 1 is compound? 0
Example 2 is compound? 1
【讨论】:
以上是关于在Boost.Geometry中将两个多边形组合成一个多边形:只有外点,没有洞的主要内容,如果未能解决你的问题,请参考以下文章