2012-06-19 71 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