我有一个二维数组,其大小为10x10,并且许多点是成对的浮点值,例如:(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]的数组中的单元格交叉
有什么算法吗?
让您的点为A和B,并分别具有坐标(xA,yA)和(xB,yB)。
A
B
(xA,yA)
(xB,yB)
两点之间线段的参数方程式由 A + t * (B-A) = (xA + t * (xB - xA), yA + t * (yB - yA)) 下式给出:其中t,所有取值器在0和1之间。
A + t * (B-A) = (xA + t * (xB - xA), yA + t * (yB - yA))
t
您需要考虑沿线段的任一坐标的所有积分值。这将为您提供直线和单元格一侧的交点,因此您可以将与该侧相邻的两个单元格都标记为“横越”。
这是执行此操作的算法的概述,该算法沿线对交点进行排序:
有一些特殊情况,例如仅在一个角上被触摸的单元格。要对以前的算法中的那些进行特殊处理,您可以识别出两个潜在的未来交集是相同的。
这是一个快速的python演示,其中我按比例缩放(乘以了)t参数方程式的所有值,dx *dy因此您不必除以dx或dy,除非您需要确切的交点坐标。
dx *dy
dx
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]),则在调用函数时对此进行标准化,即
w
0, 0
(x0, y0)
[x0 , x0 + w] * [y0, y0 + w]
raytrace( (1,1.5) , (5,2.5) )
用
raytrace( ((1 - x0) / w, (1.5 - y0) / w) , ((4 - x0) / w, (1.5 - y0) / w) )