自动合并相邻的矩形

Posted

技术标签:

【中文标题】自动合并相邻的矩形【英文标题】:Automatically Merging Ajacent Rectangles 【发布时间】:2012-11-26 21:50:38 【问题描述】:

我一直在 XNA 中制作一个需要矩形碰撞地图的自上而下的射击游戏。

地图的碰撞墙存储在文本文件中,格式为:rect[0,0,1024,8]

这些值对应于定义一个矩形(x、y、宽度、高度)。

我一直在想,我可以编写一个单独的应用程序,它可以对地图图像的数据进行文盲,找出黑色(或墙壁的任何颜色)的像素并在那里制作矩形。基本上,该程序将生成碰撞所需的矩形。理想情况下,它应该是像素完美的,这需要像一千个每个 1 像素宽的矩形来覆盖所有的墙壁。

有没有一种可能的方法来检测这些矩形(或我应该说的正方形)中的哪些彼此相邻,然后将它们连接成一个更大(但仍覆盖相同区域)的矩形?

EG。假设我有一堵 10 x 2 的墙。该程序将生成 20 个不同的矩形,每个矩形高 1 个像素。我如何有效地检测这些矩形是相邻的,并自动制作一个 10 x 2 的矩形覆盖整个墙壁,而不是拥有 20 个不同的小像素矩形?

编辑:我已经制定了一个适合我的目的的解决方案,以供将来参考,我的代码如下:

//map is a bitmap, horizontalCollisions and collisions are List<Rectangle>s
for (int y = 0; y < map.Height; y++) //loop through pixels
        
            for (int x = 0; x < map.Width; x++)
            
                if (map.GetPixel(x, y).Name == "ff000000") //wall color
                
                    int i = 1;
                    while (map.GetPixel(x + i, y).Name == "ff000000")
                    
                        if (i != map.Width - x)
                        
                            i++;
                        
                        if (i == map.Width - x)
                        
                            break;
                        
                    
                    Rectangle r = new Rectangle(x, y, i, 1);//create and add
                    x += i - 1;
                    horizontalCollisions.Add(r);
                
            
        
        for (int j = 0; j < horizontalCollisions.Count; j++)
        
            int i = 1;
            Rectangle current = horizontalCollisions[j];
            Rectangle r = new Rectangle(current.X, current.Y + 1, current.Width, 1);
            while(horizontalCollisions.Contains(r))
            
                i++;
                horizontalCollisions.Remove(r);
                r = new Rectangle(current.X, current.Y + i, current.Width, 1);
            
            Rectangle add = new Rectangle(current.X, current.Y, current.Width, i);
            collisions.Add(add);
        

            //collisions now has all the rectangles

基本上,它会水平循环遍历像素数据。当它遇到一个墙壁像素时,它会停止计数器并(使用一个while循环)将计数器向右移动,一个接一个,直到它碰到一个非墙壁像素。然后,它将创建一个该宽度的矩形,然后继续。在这个过程之后,会有一个大的矩形列表,每个 1px 高。基本上,一堆水平线。下一个循环将遍历水平线,并使用与上述相同的过程,它将找出其下具有相同X值和相同Width值(y + 1)的任何矩形。这将不断增加,直到没有,其中将创建一个大矩形,并从列表中删除使用的矩形。最终结果列表包含构成图像上所有黑色像素的所有矩形(我认为非常有效)。

【问题讨论】:

【参考方案1】:

礼仪可能会建议我对此发表评论而不是将其添加为答案,但我还没有这种能力,所以请耐心等待。

恐怕我无法为您将其翻译成代码,但我可以向您发送一些学术论文,讨论可以完成您所要求的某些事情的算法。

其他时候出现过这个问题:

Find the set of largest contiguous rectangles to cover multiple areas

Puzzle: Find largest rectangle (maximal rectangle problem)

在这些问题中链接的论文:

Fast Algorithms To Partition Simple Rectilinear Polygons

Polygon Decomposition

The Maximal Rectangle Problem

希望这些问题和论文可以帮助您找到您正在寻找的答案,或者至少吓跑您寻找其他解决方案。

【讨论】:

感谢您的帮助,我浏览了部分论文(并感到害怕),但我已经编写了一些对我有用的基本通用代码。我不需要它超级有效。我用我的代码和解释编辑了我的原始问题。希望它对未来的人们有所帮助。

以上是关于自动合并相邻的矩形的主要内容,如果未能解决你的问题,请参考以下文章

arcpy地理处理工具案例教程-将细碎图斑按相同属性或相近属性合并相邻图斑

如何批量合并碎图斑到相邻的图斑

Opencv 最小外接矩形合并拼接

P5161 WD与数列(后缀自动机+线段树合并)

合并来自 std::set 的相邻条目

在mapgis里,如何将两个相邻的区域合并,并进行添加属性字段啊?