合并相邻多边形出现错误结果

7

我正在尝试编写一段代码,给定一个多边形列表(定义为IntPoints的列表列表),检查它们是否相互接触,如果是,则将它们合并成一个多边形。为了做到这一点,我已经尝试了以下两种方法:

List<List<IntPoint>> output=new List<List<IntPoint>>();
output = Clipper.SimplifyPolygons(input,PolyFillType.pftPositive);

Clipper c = new Clipper();
c.AddPaths(input, PolyType.ptClip, true);
c.Execute(ClipType.ctUnion, output);

现在这两种方法都可以轻松地合并多边形,但它们有点过于热衷于忽略任何多边形的开放空间,并将开放区域简单地合并成单个多边形,这意味着像这样的事情发生了: Sheer horror as a two polygons that are not touching are merged into a single square devoid of any meaning or life
现在这显然是错误的,因为这两个多边形互相不接触。两种方法都会产生相同的结果。有什么办法可以解决这个问题吗?解决方案不必使用clipper库(我不一定要用它),但我需要使用由输入点列表定义的多边形,其中输入是一个List>,而Intpoint只是包含x和y的结构体。
编辑:我注意到当一个多边形没有另一个多边形内部时,这个问题也会发生,所以解决方案总是“填充”。
编辑:这里还有一个输入可能是什么样子的例子。
input[0][0]
{ClipperLib.IntPoint}
    X: -724
    Y: -472
input[0][1]
{ClipperLib.IntPoint}
    X: 428
    Y: -472
input[0][2]
{ClipperLib.IntPoint}
    X: 428
    Y: -472
  input[0][3]
{ClipperLib.IntPoint}
    X: 428
    Y: 632
input[0][4]
{ClipperLib.IntPoint}
    X: 428
    Y: 632
input[0][5]
{ClipperLib.IntPoint}
    X: -724
    Y: 632
input[0][6]
{ClipperLib.IntPoint}
    X: -724
    Y: 632
input[0][7]
{ClipperLib.IntPoint}
    X: -724
    Y: -472
input[0][8]
{ClipperLib.IntPoint}
    X: -88
    Y: -218
input[0][9]
{ClipperLib.IntPoint}
    X: -107
    Y: -218
input[0][10]
{ClipperLib.IntPoint}
    X: -107
    Y: -218
input[0][11]
{ClipperLib.IntPoint}
    X: -107
    Y: -209
input[0][12]
{ClipperLib.IntPoint}
    X: -107
    Y: -209
input[0][13]
{ClipperLib.IntPoint}
    X: -320
    Y: -172
input[0][14]
{ClipperLib.IntPoint}
    X: -320
    Y: -172
input[0][15]
{ClipperLib.IntPoint}
    X: -320
    Y: 132
input[0][16]
{ClipperLib.IntPoint}
    X: -320
    Y: 132
input[0][17]
{ClipperLib.IntPoint}
    X: -88
    Y: 173
input[0][18]
{ClipperLib.IntPoint}
    X: -88
    Y: 173
input[0][19]
{ClipperLib.IntPoint}
    X: -88
    Y: -201
input[0][20]
{ClipperLib.IntPoint}
    X: -88
    Y: -201
input[0][21]
{ClipperLib.IntPoint}
    X: -88
    Y: -218

这里描述的输入是一个带有切口的正方形。

有人知道如何最好地描述这个问题吗?多边形中的多边形被合并了?不允许存在飞地? - Thijser
我认为我可能已经找到了解决方案,但这将取决于 https://stackoverflow.com/questions/34263601/algoritm-for-translating-list-of-wallsections-into-coherent-polygon 的答案。 - Thijser
3个回答

3

在执行之前,您的Clipper需要添加一个PolyType.ptSubject(缺少在您的代码中)和一个PolyType.ptClip。此外,您需要选择所需结果的ClipType,如下所示:

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        clip = new List<List<IntPoint>>();
        clip.Add(pol2);

        input = new List<List<IntPoint>>();
        input.Add(pol1);

        output = new List<List<IntPoint>>();

        Clipper c = new Clipper();
        c.AddPaths(input, PolyType.ptSubject, true);
        c.AddPaths(clip, PolyType.ptClip, true);
        c.Execute(clipType, output);

        DrawPolygon(output, e.Graphics, Pens.Red);
    }

XOR:

enter image description here

Union:

enter image description here

Intersection:

enter image description here

Difference: pol1 - pol2

enter image description here

Difference: pol2 - pol1

enter image description here


我认为问题更多地与不正确的输入格式有关,而不是其他方面。 - Thijser
我认为addpaths会自动将它们添加为主题,因为那里有超过2个(在某些情况下只有1个)多边形。 - Thijser

1
似乎库需要一些PolyTree版本的Execute方法的组合,以及对Clipper对象中多边形的更复杂的构建,考虑到输入是否包含孔。
看起来绿色带孔的多边形并不是由一系列点表示的,它应该是一个具有外部多边形和内部孔多边形的PolyTree。

我该如何着手处理这个问题? - Thijser

-3

你可以研究一下在处理几何形状时,SQL Server 2008引入的空间数据类型。

https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeometry.stintersection.aspx

地理信息是与sqlgeometry相同的URL,但使用sqlgeography。

您可以使用.STIntersects() == 1和.STIntersection(AnotherShape)来检索交集。还有其他方法可以给您与上述相同的结果。

这样做的好处是,如果将其与数据库结合使用,您可以利用空间索引使其更快。

https://msdn.microsoft.com/en-us/library/bb934196.aspx


这个软件很有用,但它不包括任何与数据库相关的内容,我认为强制用户安装数据库也不是一个好主意。 - Thijser
我理解你的关注,但类似于使用EntityFramework一样,你可以使用包含在.NET框架中的类(DbGeometry/DbGeography),并手动填充它们。这不需要数据库甚至任何类型的数据访问。它只是利用了为了更容易处理空间数据类型而设计的内置功能的类。 - Anthony Hart
这个回答与原帖所问的无关。 - Randy

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