2015-11-30 45 views
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); 

現在這兩個在一起很容易合併的多邊形但是他們有點overzelous任何多邊形開放空間被忽略並且開放區域被簡單地組合成單個多邊形,意思是這樣的: Sheer horror as a two polygons that are not touching are merged into a single square devoid of any meaning or life

發生。現在這顯然是錯誤的,因爲這兩個多邊形彼此不接觸。兩種方法都會出現相同的結果。結果將與輸入相同。任何想法如何解決這個問題?溶劑不需要使用削波器庫(我沒有與它結合),但我確實需要一些使用由點列表定義的多邊形的東西輸入是一個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 
爲例

這個描述的輸入是一個有洞的正方形。

+0

有人甚至知道如何最好地描述這個問題?多邊形中的多邊形被合併?不允許飛地? – Thijser

+0

我想我可能已經找到了溶劑,但這將取決於答案https://stackoverflow.com/questions/34263601/algoritm-for-translating-list-of-wallsections-into-coherent-polygon – Thijser

回答

2

在執行之前,需要將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); 
    } 

XOR:

enter image description here

聯盟:

enter image description here

路口:

enter image description here

差異:pol1 - pol2

enter image description here

差異:pol2 - pol1

enter image description here

+0

我認爲問題有更多的不正確的輸入格式呢? – Thijser

+0

我認爲加入路徑會自動添加它們作爲主題,因爲那裏還有更多的2(在某些情況下只有1)多邊形。 – Thijser

-3

另一件事你可以看看是空間數據類型在SQL Server 2008中,當介紹處理幾何形狀。

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

地理是相同的URL,但與sqlgeography代替sqlgeometry

可以使用.STIntersects()== 1和.STIntersection(AnotherShape)來檢索交叉點。還有其他方法可以爲您提供與上述相同的結果。

這樣做的好處是,如果您將其與數據庫結合使用,則可以利用空間索引使其更快。

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

+0

很有用,但是這個軟件不包含與數據庫相關的任何東西,我不認爲強制人們也安裝數據庫是一個好主意。 – Thijser

+0

我理解你的擔憂,但與使用EntityFramework類似,可以使用.NET框架(DbGeometry/DbGeography)中包含的類並手動填充它們。這不需要數據庫甚至任何類型的數據訪問。它只是利用類的內置功能,這些類設計用於更輕鬆地處理空間數據類型。 –

+0

這個答案與OP要求的內容無關。 – Randy

1

它看起來像庫需要的Execute方法的PolyTree版本,並在帆船對象的多邊形的一些更復雜的堆積,考慮到輸入是否包含孔的某種組合。

它看起來並不像帶洞的綠色多邊形只是一個點陣列,它應該是一個具有外部多邊形和內部多邊形的PolyTree。

+0

任何想法我會怎麼做? – Thijser

+0

我也添加了一個輸入格式的例子。 – Thijser