我正在整理我的一个旧项目。其中需要做的一件事是,给定一个笛卡尔坐标系和两个正方形,找到连接这两个正方形中心的直线穿过的所有正方形的列表。
特殊情况是所有起始点和结束点都限制在正方形 / 单元格的正中心。
下面是一些示例 - 带有示例起始点和结束点的对。阴影正方形是应由各自的函数调用返回的正方形
已删除的ImageShack链接-示例
起始点和结束点由它们所在的正方形引用。在上图中,假设左下角是[1,1]
,右下角的线将被识别为从第六列中心的正方形,从底部第二行到第九列中心的正方形,从底部第五行。
也就是说,从第六列最左边的(中央)正方形开始,在底部第二行到第九列最左边的(中央)正方形结束,在底部第五行。
看起来并不那么复杂。然而,我在某个在线复杂算法中实现了它。
我记得它非常快。像为每一帧优化了几百或几千次快。
基本上,它沿着线跳过正方形的边界(线穿越网格线的点)。 它通过观察哪个交叉点更接近 -水平交叉点还是垂直交叉点- 来确定下一个交叉点的位置,并移动到那个交叉点。
这个算法在概念上还行,但实际实现起来并不美观,我担心所需的优化级别对我实际需要的要求过高(我大约每分钟调用此遍历算法五到六次)。
有没有简单易懂、透明的直线网格遍历算法?
以编程术语表述:
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]
请注意,直接穿过角落的线条不应包括在线条的“翼”部分的正方形中。
(好老的Bresenham可能适用于这里,但与我想要的有点背道而驰。就我所知,为了使用它,我基本上必须将其应用于该线并扫描网格上的每个正方形以获取真或假。对于大型网格来说是不可行的,或者至少是不优雅的)
(我正在重新研究Bresenham和基于Bresenham的算法,因为我的一个误解)
澄清一下,这种算法的一个可能应用是,如果我在游戏中将所有对象存储在区域内(网格),并且我有一个光线,并且想要查看光线触及哪些对象。使用此算法,我可以测试光线仅针对给定区域内的对象,而不是地图上的每个对象。
在我的应用程序中的实际用途是,每个图块都有一个与之关联的效果,并且对象在每个回合通过给定的线段移动。 每次回合,需要检查对象已经穿过的正方形,从而确定要向对象应用哪些效果。
请注意,此时我拥有的当前实现确实可行。这个问题主要是为了好奇心。肯定有更简单的方法......对于这样一个简单的问题。
我要找的到底是什么? 某种概念上/整洁明了的东西。另外,我意识到由于我所指定的内容,所有起始点和结束点始终会在方块/单元格的中心;因此,也许利用这一点的某些东西也很棒。