我正在清理我的一个旧项目。它必须做的一件事是——给定一个笛卡尔网格系统,以及网格上的两个正方形,找到连接这两个正方形中心的一条线将通过的所有正方形的列表。
这里的特殊情况是所有起点和终点都被限制在正方形/单元格的确切中心。
这里有一些例子——有成对的样本起点和终点。阴影方块是相应函数调用应返回的方块
删除了无效的 ImageShack 链接 - 示例
起点和终点由它们所在的正方形表示。在上图中,假设左下角是[1,1]
,则右下角的线将被标识[6,2]
为[9,5]
。
即从左起第六列、下第二行的方格(中心)到左起第九列、下起第五行的方格(中心)
这看起来真的没有那么复杂。不过,不知怎么的,我好像在网上找到了一些复杂的算法并实现了。
我记得那是非常非常快的。就像,每帧快速优化了数百或数千次。
基本上,它沿着线(线与网格线相交的点)从正方形的边界跳到边界。它通过查看哪个交叉点更接近(水平的或垂直的)来知道下一个交叉点在哪里,然后移动到下一个交叉点。
这在概念上是可以的,但实际的实现结果并不那么漂亮,而且我担心优化水平可能对我实际需要的东西来说太高了(我称之为遍历算法可能每分钟五六次)。
有没有简单、易懂、透明的直线网格遍历算法?
在程序化方面:
def traverse(start_point,end_point)
# returns a list of all squares that this line would pass through
end
其中给定的坐标标识了正方形本身。
一些例子:
traverse([0,0],[0,4])
# => [0,0], [0,1], [0,2], [0,3], [0,4]
traverse([0,0],[3,2])
# => [0,0], [0,1], [1,1], [2,1], [2,2], [3,2]
traverse([0,0],[3,3])
# => [0,0], [1,1], [2,2], [3,3]
请注意,直接通过拐角的线不应包括线“翼”上的正方形。
(Good ol' Bresenham's 可能在这里工作,但它与我想要的有点倒退。据我所知,为了使用它,我基本上必须将它应用到线上,然后扫描每个正方形真或假的网格。对于大型网格不可行——或者至少不优雅——
(由于我的误解,我正在重新研究 Bresenham 和基于 Bresenham 的算法)
为了澄清起见,一个可能的应用是,如果我将所有对象存储在区域(网格)内的游戏中,并且我有一条射线,并且想查看射线接触到哪些对象。使用这个算法,我可以只测试给定区域内的对象,而不是地图上的每个对象。
在我的应用程序中,它的实际用途是每个图块都有与之关联的效果,并且对象每转都会通过给定的线段。在每一个转弯处,都需要检查对象已经穿过了哪些方格,因此需要对对象应用哪些效果。
请注意,在这一点上,我当前的实现确实有效。这个问题主要是出于好奇的目的。对于这样一个简单的问题,必须有一种更简单的方法......不知何故......
我到底在寻找什么?概念上/整洁干净的东西。另外,我意识到由于我确切指定的内容,所有起点和终点都将始终位于正方形/单元格的中心;所以也许利用这一点的东西也会很整洁。