C# 合并产生错误结果的多边形

C# 合并产生错误结果的多边形,c#,geometry,2d,polygon,clipperlib,C#,Geometry,2d,Polygon,Clipperlib,我试着写一段代码,给出一个多边形列表(定义为一个整数点列表),检查它们是否有接触,如果有,将它们合并成一个多边形。为此,我已经尝试了以下两种方法: List<List<IntPoint>> output=new List<List<IntPoint>>(); output = Clipper.SimplifyPolygons(input,PolyFillType.pftPositive); 现在,这两种方法很容易将多边形合并在一起,但是它们有点过

我试着写一段代码,给出一个多边形列表(定义为一个整数点列表),检查它们是否有接触,如果有,将它们合并成一个多边形。为此,我已经尝试了以下两种方法:

List<List<IntPoint>> output=new List<List<IntPoint>>();
output = Clipper.SimplifyPolygons(input,PolyFillType.pftPositive);
现在,这两种方法很容易将多边形合并在一起,但是它们有点过于复杂,因为任何多边形开放空间都会被忽略,而开放区域只会合并成一个多边形,这意味着类似以下内容:

发生了。这显然是错误的,因为这两个多边形彼此不接触。两种方法的结果相同。结果将与输入相同。你知道怎么解决这个问题吗?解决方案不必使用clipper库(我没有结婚),但我确实需要使用由点列表定义的多边形的东西输入是一个列表>,其中一个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

这个描述的输入是一个正方形,上面有一个孔

在执行之前,需要将
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);
    }
private void Form1\u Paint(对象发送方,PaintEventArgs e)
{
clip=新列表();
clip.Add(pol2);
输入=新列表();
输入。添加(pol1);
输出=新列表();
Clipper c=新的Clipper();
c、 addpath(输入,PolyType.ptSubject,true);
c、 addpath(clip,PolyType.ptClip,true);
c、 执行(clipType,output);
DrawPolygon(输出,例如图形、笔、红色);
}
异或:

工会:

交叉口:

差异:
pol1
-
pol2

差异:
pol2
-
pol1


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

地理位置与URL相同,但使用sqlgeography而不是sqlgeometry

可以使用.STIntersects()==1和.STIntersection(另一个形状)检索交点。还有其他方法可以提供与上述相同的结果

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


看起来该库需要将执行方法的PolyTree版本与Clipper对象中更复杂的多边形构建结合起来,以考虑输入是否包含孔


带孔的绿色多边形看起来不像是一个点数组,它应该是一个带外多边形和内孔多边形的多边形树。

有人知道如何最好地描述这个问题吗?正在合并的多边形中的多边形?不允许使用飞地?我想我可能已经找到了解决方案,但这取决于有用的答案,但该软件不包括任何与数据库相关的内容,我认为强迫人们也安装数据库不是一个好主意。我理解你的担忧,但与EntityFramework的工作类似,您可以使用.NET framework中包含的类(DbGeometry/DbGeography)并手动填充它们。这不需要数据库,甚至不需要任何类型的数据访问。它只是利用了类的内置功能,这些类的设计目的是使处理空间数据类型更容易。这个答案与OP的要求无关。你知道我该如何处理吗?我认为问题更多地与inproper输入格式有关?我认为AddPath会自动将它们添加为由于存在主题,因此也有超过2个(在某些情况下只有1个)多边形。
    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);
    }