递归查找矩形

时间:2012-09-04 09:27:52

标签: c# recursion

我有一个重叠矩形列表。我需要找到一个列表列表,其中返回所有重叠的矩形。例如,在7个矩形的列表中,如果4个矩形重叠并且其余部分是分开的,则列表列表应如下所示:

[0]: r1, r2, r3, r4
[1]: r5
[2]: r6
[3]: r7

我知道我必须进行一次命中测试。我正在寻找一个算法或一个例子来创建链。

由于

我已经尝试过这段代码:有时它会起作用,有时它会抛出索引超出绑定的异常。

while (rects.Count != 0)
            {
                listOfRects.Add(joinRectangles(rects, new List<Rectangle>(), rects[rects.Count - 1]));
            }

        private List<Rectangle> joinRectangles(List<Rectangle> rects, List<Rectangle> tempRects, Rectangle curRect)
        {
            for (int j = rects.Count; j-- > 0; )
            {
                if (hitTest(curRect, rects[j]) == true)
                {
                    if (tempRects.Contains(rects[j]) == false)
                    {
                        tempRects.Add(rects[j]);
                        curRect = rects[j];
                        rects.Remove(rects[j]);

                        j--;

                        joinRectangles(rects, tempRects, curRect);
                    }
                }


            }


            return tempRects;
        }

如果我提供这些坐标,那么我应该得到一个包含4个列表的列表:

    [0]: 1 rectangle
    [1]: 3 rectangles
    [2]: 1 rectangle
    [3]: 1 rectangle


<?xml version="1.0" encoding="utf-16"?>
<rectangles>
  <rectangle>
    <X1>50.833333344375</X1>
    <Y1>100</Y1>
    <X2>53.833333344375</X2>
    <Y2>127.00000004975</Y2>
  </rectangle>
  <rectangle>
    <X1>136.500000033125</X1>
    <Y1>100</Y1>
    <X2>139.516666655625</X2>
    <Y2>127.00000004975</Y2>
  </rectangle>
  <rectangle>
    <X1>50.833333344375</X1>
    <Y1>130.647222172472</Y1>
    <X2>53.833333344375</X2>
    <Y2>157.647222222222</Y2>
  </rectangle>
  <rectangle>
    <X1>136.500000033125</X1>
    <Y1>130.647222172472</Y1>
    <X2>139.516666655625</X2>
    <Y2>157.647222222222</Y2>
  </rectangle>
  <rectangle>
    <X1>136.500000033125</X1>
    <Y1>100</Y1>
    <X2>139.516666655625</X2>
    <Y2>157.3333333830833</Y2>
  </rectangle>
  <rectangle>
    <X1>179.3333333775</X1>
    <Y1>100</Y1>
    <X2>182.3333333775</X2>
    <Y2>157.3333333830833</Y2>
  </rectangle>
</rectangles>

3 个答案:

答案 0 :(得分:0)

在您发布自己的代码之前快速从头开始编写。 您有一个矩形列表,并希望按重叠组对它们进行分组。

您使用此groupRectangles函数

public List<List<Rectangle>> groupRectangles(List<Rectangle> rectangleList) {

List<List<Rectangle>> groupOverlappedRectangles = new List<List<Rectangle>>();

foreach (Rectangle r : rectangleList) {
    bool overLap = false;
    foreach (List<Rectangle> liste : groupOverlappedRectangles) {
        if (overlapsRectangleList(r,liste))
        {
                liste.add(r);
            overLap = true;
            break;
        }
    }
    if (!overLap) {
        List<Rectangle> newOverlapList = new List<Rectangle>();
        newOverlapList.add(r);
        groupOverlappedRectangles.add(newOverlapList);
    }
}
return groupOverlappedRectangles;
}

public bool overlapsRectangleList(Rectangle r, List<Rectangle> listeOver)
{
    foreach (Rectangle rOver : listeOver) {
        if (r.IntersectsWith(rOver)) {
            return true;
    }
    }
    return false;
}

答案 1 :(得分:0)

使用Rectangle.IntersectsWith和Linq的延迟执行的另一种方法:

var intersectingRectangles = new List<List<Rectangle>>();
var alreadyChecked = new HashSet<Rectangle>();
var toCheck = rectangles.Except(alreadyChecked);
while (alreadyChecked.Count != rectangles.Count)
{
    var intersections = toCheck.Where(r => r.IntersectsWith(toCheck.ElementAt(0)))
                               .ToList();
    intersectingRectangles.Add(intersections);
    foreach (var r in intersections)
        alreadyChecked.Add(r);
}
intersectingRectangles.Sort((rl1, rl2) => (-1) * rl1.Count.CompareTo(rl2.Count));

也许不是最可读的方式,但最短的方式之一:)

编辑:这是一个演示(没有System.Drawing和Rectangles的单声道很难):

http://ideone.com/eOCMN

答案 2 :(得分:0)

对于每个矩形,必须检查所有早期的矩形组。例如,如果A和C重叠,而B和C重叠,而不是A和B.如果算法接收A,B,C,它将首先将A放在一个列表中,然后将B放在另一个列表中。但是当C来时,它必须将列表与A和列表与B合并到包含C的新列表中。(这是其他答案似乎错过的。)

public static List<List<Rectangle>> SortOverlap(Rectangle[] rectangles)
{
    var result = new List<List<Rectangle>>();
    for (int i = 0; i < rectangles.Length; i++) 
    {
        var newList = new List<Rectangle>();
        newList.Add(rectangles[i]);
        for (int j = 0; j < result.Count; j++) 
        {
            if(result[j].Any(r => r.Overlap(newList[0])))
            {
                newList.AddRange(result[j]);
                result[j] = null;
            }
        }
        result.Add(newList);
        result.RemoveAll(list => list == null);
    }
    return result;
}

修改: 重叠检查实现起来相当简单,因此不需要仅使用System.Drawing或类似的检查...

public class Rectangle {
    ....
    public bool Overlap(Rectangle other)
    {
        return !(this.MinX >= other.MaxX || this.MaxX <= other.MinX ||
                 this.MinY >= other.MaxY || this.MaxY <= other.MinY);
    }
}