2012-06-19 112 views
3

我有一個System.Drawing.RectangleF對象的列表,所有對象都重疊在同一個RectangleF對象上。在下面的圖片中,3個重疊的矩形將是粉紅色,黃色和紅色矩形。我的主矩形是淺藍色的矩形。查找與同一矩形重疊的多個矩形的總重疊百分比?

enter image description here

二圖片: enter image description here

我知道,與RectangleF對象我可以使用Intersect()方法將返回我代表彼此重疊RectangleF對象。但據我所知,這隻在比較兩個矩形時才起作用。

我的問題是:我怎麼能確定的總面積/百分比(即紅色,黃色和粉紅色長方形的總和重疊相比,淡藍色的長方形 - 但它需要是足夠聰明,無法計算出紅色和黃色重疊的區域兩次,粉色和黃色的區域相同)?

注意:綠線代表我正在查找的區域,只是藍色矩形的總面積不可見。

UPDATE:我已經添加了第二張圖片以進一步說明我在找什麼。在第二張圖片中,勃艮第矩形的存在不應影響總覆蓋百分比,因爲該區域已被黃色和綠色矩形覆蓋。

+0

有趣的問題,花了我幾分鐘想出一個辦法。這是功課嗎? – tcarvin

+0

這實際上是對我的工作 - 它讓我陷入困境。它的主要特點是我需要識別「隱藏」的矩形,這些矩形或者完全重疊或者幾乎完全重疊。現在我試圖找到該區域,以便我可以識別90%覆蓋(或更多)的矩形。 – lhan

+0

爲了確保我理解這一點,您需要重疊藍色矩形的總面積而不重複計算任何其他矩形,這些矩形也重疊在同一空間上。對? –

回答

2

OK,我想我找到了解決辦法使用Region,這似乎是工作均高於我的例子中圖片:

Private Function TotalCoveredAreaPercent(ByVal oRectToCheck As RectangleF, ByVal oOverlappingRects As List(Of RectangleF)) As Double 

    Dim oRegion As New Region(oRectToCheck) 
    Dim dTotalVisibleArea As Double = 0 
    Dim dTotalCoveredArea As Double = 0 

    'now we need to exclude the intersection of our 
    'overlapping rectangles with our main rectangle: 
    For Each oOverlappingRect As RectangleF In oOverlappingRects 

     oRegion.Exclude(RectangleF.Intersect(oRectToCheck, oOverlappingRect)) 

    Next 

    'now we have access to the non-overlapping 
    'rectangles that make up the visible area of our main rectangle: 
    Dim oVisibleRects As RectangleF() 

    oVisibleRects = oRegion.GetRegionScans(New Drawing2D.Matrix()) 

    'add the area of the visible rectangles together 
    'to find the total visible area of our main rectangle: 
    For Each oVisibleRect As RectangleF In oVisibleRects 
     dTotalVisibleArea += AreaOf(oVisibleRect) 
    Next 

    Dim dPercentVisible As Double = dTotalVisibleArea/AreaOf(oRectToCheck) * 100 

    'percent covered is 100 - the visible percentage: 
    Return (100 - dPercentVisible) 

End Function 

這似乎是相當不錯的了,而且是相當簡單的。

+0

之前從未使用過Regions。感謝分享! – tcarvin

+0

我其實首先嚐試了Regions,但不確定如何正確使用它們 - 而且我沒有看到GetRegionScans()方法。我已經在線閱讀了C++,你可以將GetRegionData.Data中返回的字節數組轉換爲表示矩形可見部分的非重疊矩形結構。但是,我無法在.NET中找到這樣的方法。幸運的是,我在一位同事的幫助下再次看了一眼,我們提出了這個問題。再次感謝您的幫助! – lhan

+1

當我看到你的答案時,我開始去排除路線,除了矩形和使用遞歸例程。尼斯。 –

1

這是我的算法。關鍵是我們正在減去重疊的重疊。

Dim baseRect As New RectangleF(10, 10, 20, 20) 
    Dim otherRectList As New List(Of RectangleF) 
    otherRectList.Add(New RectangleF(5, 5, 10, 10)) 
    otherRectList.Add(New RectangleF(20, 20, 10, 10)) 
    otherRectList.Add(New RectangleF(10, 5, 10, 10)) 

    Dim overlapRectList As New List(Of RectangleF) 
    For Each otherRect As RectangleF In otherRectList 
     If RectangleF.Intersect(otherRect, baseRect) <> RectangleF.Empty Then 
     overlapRectList.Add(RectangleF.Intersect(otherRect, baseRect)) 
     End If 
    Next 

    Dim totalArea As Single = 0 
    For Each overlapRect As RectangleF In overlapRectList 
     totalArea += overlapRect.Width * overlapRect.Height 
    Next 

    'Subtract out any overlaps that overlap each other 
    For i = 0 To overlapRectList.Count - 2 
     For j = i+1 To overlapRectList.Count - 1 
     If i <> j Then 
      If RectangleF.Intersect(overlapRectList(i), overlapRectList(j)) <> RectangleF.Empty Then 
      Dim dupeRect As RectangleF = RectangleF.Intersect(overlapRectList(i), overlapRectList(j)) 
      totalArea -= dupeRect.Width * dupeRect.Height   
      End If 
     End If 
     Next 
    Next 

我修改了代碼以考慮tcarvin的注意事項。但是,我沒有在方格紙上畫出結果,看看它是否完全正確。我會在有更多時間後儘快查看。還請注意,我沒有包含任何代碼來處理少於2個交叉點的情況。

+0

與減法相同的錯誤。給定矩形A,B,C和D全部相互重疊(並且重疊基本矩形Z),減法循環遞減每次通過的重疊。因此,例如,矩形D可能會在該區域添加10,但在每次通過時減去10(對於A,B和C)。 – tcarvin

+0

謝謝你的代碼,但像@tcarvin提到的,太多的遞減發生。例如,在上面的圖片2中,無論中間的勃艮第矩形是否存在(不包括尚未覆蓋的區域),您都應該得到完全相同的結果。 – lhan