1,多边形概念(Polygon Concept)
2,一个接一个求并,{p0, p1, p2, p3} => p0+p1=p01, p01+p2=p012,p012+p3=p0123。
代码实现
namespace bg = boost::geometry;
using point_d = bg::model::d2::point_xy<double>;
using polygon_d = bg::model::polygon<point_d>; //顺时针,闭合
using multi_polygon_d = bg::model::multi_polygon<polygon_d>;
multi_polygon_d polys; //需要求并的多多边形
multi_polygon_d outs; //求并后的输出
multi_polygon_d tmp;
for (const auto& poly : polys) {
boost::geometry::union_(outs, poly, tmp);
outs.swap(tmp);
tmp.clear();
}
3,中间结果输出可能无效,比如p01无效,做为下一次求并的输入就是无效的。
通过调用is_valid (with failure value) - 1.84.0 (boost.org)
无效的原因是可能有尖刺(failure_spikes = 12)或者自相交(failure_self_intersections = 21)。
4,correct - 1.84.0 (boost.org) 可以修复尖刺(failure_spikes = 12)
https://github.com/kleunen/boost_geometry_correct
可以修复部分自相交(failure_self_intersections = 21)。但一直求并下去,有可能仍然存在无效的中间结果多边形,无法修复,导致合并的结果不正确。
5,用整数表示多边形坐标求并。
using point_i = bg::model::d2::point_xy<long>;
using ring_d = bg::model::ring<point_d>;
using ring_i = bg::model::ring<point_i>;
using polygon_i = bg::model::polygon<point_i>;
using multi_polygon_i = bg::model::multi_polygon<polygon_i>;
constexpr static double transform = 100.0;
void polyd2i(const polygon_d& poly, polygon_i& polyi) {
for (const auto& p : poly.outer()) {
polyi.outer().emplace_back(point_i(static_cast<long>(p.x() * transform), static_cast<long>(p.y() * transform)));
}
for (const auto& in : poly.inners()) {
ring_i ini;
for (const auto& p : in) {
ini.emplace_back(point_i(static_cast<long>(p.x() * transform), static_cast<long>(p.y() * transform)));
}
polyi.inners().emplace_back(ini);
}
if (!bg::is_valid(polyi)) {
bg::correct(polyi);
}
}
void polyi2d(const polygon_i& polyi, polygon_d& poly) {
for (const auto& p : polyi.outer()) {
poly.outer().emplace_back(point_d(static_cast<double>(p.x()) / transform, static_cast<double>(p.y()) / transform));
}
for (const auto& in : polyi.inners()) {
ring_d ini;
for (const auto& p : in) {
ini.emplace_back(point_d(static_cast<double>(p.x()) / transform, static_cast<double>(p.y()) / transform));
}
poly.inners().emplace_back(ini);
}
if (!bg::is_valid(poly)) {
bg::correct(poly);
}
}
multi_polygon_i tmpi;
multi_polygon_i outsi;
for (const auto& polyd : polys) {
polygon_i polyi;
polyd2i(polyd, polyi);
bg::union_(outsi, polyi, tmpi);
outsi.swap(tmpi);
bg::clear(tmpi);
}
outs.clear();
for (const auto& polyi : outsi) {
polygon_d polyd;
polyi2d(polyi, polyd);
outs.emplace_back(polyd);
}
6,浮点数表示多边形坐标可能不准确,在对多边形进行布尔运算或者其他各种算法时,其实都用整数表示多边形坐标会比较好。
7,c++ - What is the fastest way to create the union of many boost::polygons? - Stack Overflow
其中提到的属性合并Boost Polygon Library: Property Merge
没有研究清楚,写了一点demo无法编译,希望有大佬赐教。