【问题标题】:Merging touching polygons giving wrong result合并接触多边形给出错误结果
【发布时间】:2016-03-04 04:47:46
【问题描述】:

我正在尝试编写一段代码,它给出一个多边形列表(定义为 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);

现在这两个很容易将多边形合并在一起,但是它们有点过分了,因为任何多边形的开放空间都被忽略了,开放区域被简单地组合成一个多边形,这意味着像这样:

发生。现在这显然是错误的,因为这两个多边形不相互接触。两种方法都会出现相同的结果。结果将与输入相同。知道如何解决这个问题吗?解决方案不必使用裁剪器库(我没有嫁给它),但我确实需要使用由点列表定义的多边形的东西输入是 List> 其中 Intpoint 只是一个包含 x 的结构和一个。

编辑我注意到当另一个多边形内部没有多边形时也会出现这个问题,所以解决方案总是“填充” 编辑编辑:这也是输入可能是什么样的示例

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

这个描述的输入是一个正方形,里面有一个洞。

【问题讨论】:

  • 有人知道如何最好地描述这个问题吗?多边形中的多边形被合并?不允许飞地?
  • 我想我可能已经找到了解决方案,但这取决于stackoverflow.com/questions/34263601/…的答案

标签: c# geometry 2d polygon clipperlib


【解决方案1】:

在执行之前,需要将PolyType.ptSubject(您的代码中缺少)和PolyType.ptClip 添加到您的Clipper 中。您还需要选择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);
    }

异或:

联合:

路口:

区别:pol1 - pol2

区别:pol2 - pol1

【讨论】:

  • 我认为问题与输入格式不正确有关吗?
  • 我认为 addpaths 会自动将它们添加为主题,因为那里还有超过 2 个(在某些情况下只有 1 个)多边形。
【解决方案2】:

您可以研究的另一件事是 SQL Server 2008 在处理几何形状时引入的空间数据类型。

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

Geography 是相同的 URL,但使用 sqlgeography 而不是 sqlgeometry

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

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

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

【讨论】:

  • 有用,但是这个软件不包含任何与数据库相关的东西,我认为强迫人们也安装数据库不是一个好主意。
  • 我理解您的担忧,但与使用 EntityFramework 类似,您可以使用 .NET 框架 (DbGeometry/DbGeography) 中包含的类并手动填充它们。这不需要数据库,甚至不需要任何类型的数据访问。它只是利用了类的内置功能,这些功能旨在简化空间数据类型的处理。
  • 这个答案与OP的要求无关。
【解决方案3】:

看起来该库需要结合 PolyTree 版本的 Execute 方法,以及 Clipper 对象中一些更复杂的多边形构建,考虑输入是否包含孔洞。

它看起来不像带有孔的绿色多边形仅表示为点数组,它应该是具有外部多边形和内部孔多边形的 PolyTree。

【讨论】:

  • 知道我将如何处理吗?
猜你喜欢
  • 1970-01-01
  • 2020-08-01
  • 2021-07-20
  • 2013-01-26
  • 2021-03-03
  • 2016-11-22
  • 2013-05-29
  • 1970-01-01
相关资源
最近更新 更多