简体   繁体   English

合并触摸多边形给出错误的结果

[英]Merging touching polygons giving wrong result

I'm trying to write a piece of code that given a list of polygons (defined as a list of lists of IntPoints) checks if any of them touch and if so merge them into a single polygon. 我正在尝试编写一段代码,给出一个多边形列表(定义为IntPoints列表列表)检查是否有任何触摸,如果是,则将它们合并为一个多边形。 In order to do this I have already tried the following two methods: 为了做到这一点,我已经尝试了以下两种方法:

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

and

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

Now both of these merge the polygons together quite easily however they are a bit overzelous as any polygon open spaces are ignored and open areas are simply combined into a single polygon, meaning that something like this: 现在这两个都很容易将多边形合并在一起,但是它们有点过于粗糙,因为忽略了任何多边形开放空间,并且开放区域简单地组合成一个多边形,这意味着像这样: 作为一个没有触及的两个多边形的纯粹恐怖被合并成一个没有任何意义或生命的方形

happens. 发生。 Now this is obviously wrong as these two polygons do not touch each other. 现在这显然是错误的,因为这两个多边形不相互接触。 The same result occurs with both methods. 两种方法都会出现相同的结果。 The result would be the same as the input. 结果与输入相同。 Any idea how to fix this? 知道如何解决这个问题吗? The sollution does not have to use the clipper library (I'm not married to it) but I do need something that uses polygons that are defined by a list of points input is a List> where an Intpoint is just a struct containing an x and a y. sollution不必使用限幅器库(我没有与它结合)但我确实需要一些使用由点列表定义的多边形的输入是List>其中Intpoint只是一个包含x的结构和y。

Edit I notice that this problem also occurs when there is no polygon inside of the other polygon, so the solution is always "filled" edit edit: here is also an example of what input might be like 编辑我注意到当另一个多边形内没有多边形时也会出现这个问题,所以解决方案总是“填充”编辑编辑:这里也是一个输入可能是什么样的例子

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

The input this descripes is a square with a hole cut into it. 这个描述的输入是一个正方形,其中有一个孔。

There needs to be a PolyType.ptSubject (missing from your code) and a PolyType.ptClip added to your Clipper before execution. 需要有PolyType.ptSubject (代码中缺少)和PolyType.ptClip在执行之前添加到Clipper Also you need to select the ClipType that will produce the result you want, as shown below: 您还需要选择将产生所需结果的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: XOR:

在此输入图像描述

Union: 联盟:

在此输入图像描述

Intersection: 路口:

在此输入图像描述

Difference: pol1 - pol2 差异: pol1 - pol2

在此输入图像描述

Difference: pol2 - pol1 差异: pol2 - pol1

在此输入图像描述

It looks like the library needs some combination of the PolyTree version of the Execute method, and some more complicated build up of the polygons in the Clipper object, that takes into account whether the input contains holes. 看起来这个库需要一些Execute方法的PolyTree版本的组合,以及Clipper对象中一些更复杂的多边形构建,它考虑了输入是否包含空洞。

It doesn't look like the green polygon with the hole is represented as just an array of points, it should be a PolyTree with an outer polygon and an inner hole polygon. 它看起来不像带有孔的绿色多边形只是一个点数组,它应该是一个具有外多边形和内孔多边形的PolyTree。

Another thing you could look into is the Spatial datatypes introduced in SQL Server 2008 when handling geometric shapes. 您可以研究的另一件事是在处理几何形状时SQL Server 2008中引入的Spatial数据类型。

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

Geography is same URL but with sqlgeography instead of sqlgeometry 地理位置是相同的URL,但使用sqlgeography而不是sqlgeometry

You can use the .STIntersects() == 1 and .STIntersection(AnotherShape) to retrieve the intersections. 您可以使用.STIntersects()== 1和.STIntersection(AnotherShape)来检索交叉点。 There are also other methods to give you the same results as above. 还有其他方法可以提供与上面相同的结果。

The benefit to this is that if you incorporate this with your database, you can utilize spatial indexes to make it even faster. 这样做的好处是,如果将其与数据库结合使用,则可以利用空间索引使其更快。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM