我有一个大小为10x10的2D单元格数组,以及多个浮点值对的点,如:(1.6,1.54),(4.53,3.23)。对(x,y)使得x <10且y <10
每个单元格采用坐标与单元格坐标具有相同整数部分的点。 所以arr [3] [7]将取x = {3 ... 3.99(9)}和y = {7 ... 7.99(9)}的点,例如(3.5,7.1)或(3.2,7.6) )。类似地(1.6,1.54)在arr [1] [1]中,(4.53,3.23)在arr [4] [3]等中。
每个点在数组中都有一个易于查找的指定位置,因为我只需要将x和y转换为int以除去小数点。
但我想找到阵列中哪些单元格被两个点A(x,y)和B(x,y)之间的线段穿过。
例如:A(1.5,2.5)和B(4.3,3.2)穿过具有索引[1] [2],[2] [2],[3,3]和[3,4]的数组中的单元格
有没有算法?
这是一个类似的问题: Cells in grid crossed by a line ( PHP )
答案 0 :(得分:2)
让您的积分为A
和B
,各自的坐标为(xA,yA)
和(xB,yB)
。
两点之间的线段的参数方程由下式给出:
A + t * (B-A) = (xA + t * (xB - xA), yA + t * (yB - yA))
其中t
将所有估值器的值介于0和1之间。
您需要考虑沿线段的任一坐标的所有积分值。这将为您提供线和单元格边的交点,因此您可以将与此边相邻的两个单元格标记为“遍历”。
以下是执行此操作的算法概要,沿着该行对交叉点进行排序:
有一些特殊情况,例如仅在一个角落触摸的细胞。要专门处理以前算法中的那些,您可以认识到两个潜在的未来交叉点都是相同的。
以下是a quick python demo,其中我将参数方程的所有t
值按dx * dy
缩放(乘以),因此您不必除以dx
或{ {1}},除非你想要精确的交点坐标。
dy
如果您的单元格宽度为from math import floor
def sign(n):
return (n > 0) - (n < 0)
def raytrace(A, B):
""" Return all cells of the unit grid crossed by the line segment between
A and B.
"""
(xA, yA) = A
(xB, yB) = B
(dx, dy) = (xB - xA, yB - yA)
(sx, sy) = (sign(dx), sign(dy))
grid_A = (floor(A[0]), floor(A[1]))
grid_B = (floor(B[0]), floor(B[1]))
(x, y) = grid_A
traversed=[grid_A]
tIx = dy * (x + sx - xA) if dx != 0 else float("+inf")
tIy = dx * (y + sy - yA) if dy != 0 else float("+inf")
while (x,y) != grid_B:
# NB if tIx == tIy we increment both x and y
(movx, movy) = (tIx <= tIy, tIy <= tIx)
if movx:
# intersection is at (x + sx, yA + tIx / dx^2)
x += sx
tIx = dy * (x + sx - xA)
if movy:
# intersection is at (xA + tIy / dy^2, y + sy)
y += sy
tIy = dx * (y + sy - yA)
traversed.append( (x,y) )
return traversed
且坐标为w
的单元格从0, 0
开始(即(x0, y0)
),则在调用函数时将其标准化,即的
[x0 , x0 + w] * [y0, y0 + w]
使用
raytrace( (1,1.5) , (5,2.5) )
答案 1 :(得分:2)
Amanatides和Woo A Fast Voxel Traversal Algorithm for Ray Tracing的方法允许枚举所有相交的单元格 Here is实际执行。
工作示例(相交和触摸的单元格是彩色的)
答案 2 :(得分:1)
尝试使用具有python package的Bresenham的线条绘制算法。代码如下:
from bresenham import bresenham
cells = list(bresenham(96, 280, 95, 275))
print(cells)
我收到了
[(96, 280), (96, 279), (96, 278), (95, 277), (95, 276), (95, 275)]