由多个多边形联合构成的多边形建造方法

11

假设我有许多多边形,什么是构建一个由所有这些多边形的联合组成的多边形(可能带有孔)的最佳算法?

为了我的目的,可以将每个多边形的每一块想象为拼图,当你完成它们时,你将得到一个漂亮的图片。但问题在于,一小部分(例如<5%)的拼图缺失,你仍然需要尽可能完整地形成一张图片;这就是我想要形成的多边形(或多边形)--也许带有孔。

我的天真的方法是取两个多边形,将它们联合起来,再取另一个多边形,用它与两个多边形的联合体联合起来,重复此过程直到每个单独的块都联合起来。然后我将遍历联合多边形列表,并检查是否仍有一些多边形可以合并,我会重复此过程,直到达到满意的结果。

但这似乎是一个极其天真的方法。我只是想知道是否还有其他更好的算法?


我在同一个问题的这里发布了答案:https://dev59.com/1nE85IYBdhLWcg3wqlaE#19475433 - xtmq
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
9
你需要一个多边形剪裁库——我会推荐我的Clipper库,因为它是用C#(和C++、Delphi)编写的,是开源免费软件,可以完全满足你的需求。

我幼稚的方法是取两个多边形,合并它们,再取另一个多边形,将其与两个多边形的联合体合并,然后重复此过程直到每个片段都被合并。

这种方法非常低效。更好的方法是在一次操作中全部“合并”...

using ClipperLib;
using Polygon = List<IntPoint>;
using Polygons = List<List<IntPoint>>;
...

//precondition: all your polygons have the same orientation 
//(ie either clockwise or counter clockwise)
Polygons polys = new Polygons(PolyCnt);
for (int i = 0; i < PolyCnt; i++)
    polys.Add(loadPolyFromFile(String.Format("poly{0}.txt", i +1)));

Polygons solution = new Polygons();
Clipper c = new Clipper();
c.AddPolygons(polys, PolyType.ptSubject);
c.Execute(ClipType.ctUnion, solution, 
    PolyFillType.pftNonZero, PolyFillType.pftNonZero);

//code to display solution here.

你的 precondition 注释解决了我早上一直在努力解决的问题。 我正在进行一个联合操作,结果形成了一个差异形式,我无法弄清楚自己错在哪里。 原来我用逆时针多边形写成了一组顺时针多边形。我相信您的文档中肯定有相关内容,但我没有找到。总的来说,您的文档非常实用,做得很好。迄今为止,我非常满意移植后的go.clipper库。 - swill
有这个库的C#版本的NuGet包会很不错。 - Guillaume

1

你现在正在使用暴力破解的方法。更好的暴力破解方法是分支限界法。但它仍然难以扩展。

下一步可以尝试 元启发式 算法(禁忌搜索,模拟退火,……)或者直接重用一个框架,比如 Drools Planner(开源,Java),该框架已经为你实现了这些算法。


有关元启发式算法如何帮助的任何指针?我看到了维基百科,但它对我上面描述的问题几乎没有参考。 - Graviton
元启发式算法是关于"移动事物"的,因此在您的情况下,请"移动多边形;或添加或删除多边形"。看看禁忌搜索,它非常容易实现。 - Geoffrey De Smet
如果您只是想计算多边形的并集,而不是寻找解决基本问题的其他方案,那么正确的方法是一次性将所有多边形合并,而不是成对地合并。例如,可以改编用于计算并集的扫描线算法以合并整个集合,而不是一对多边形。下面提到的Clipper答案听起来不错。 - jjrv
OP还在Math上提出了这个问题,我认为那里的答案更好(更具体)。http://math.stackexchange.com/questions/15815/how-to-union-many-polygons-efficiently - Pimin Konstantin Kefaloukos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,