【发布时间】:2017-05-08 12:21:30
【问题描述】:
我正在尝试遍历一条线所经过的所有单元格。我发现Fast Voxel Traversal Algorithm 似乎符合我的需求,但我目前发现它不准确。下面是一个带有红线和点作为算法给出的体素坐标的图。正如你所看到的,除了 (4, 7) 点之外它几乎是正确的,因为它应该是 (5,6)。我不确定我是否正确地实现了算法,所以我已经将它包含在 Python 中。所以我想我的问题是我的实现正确还是有更好的算法?
谢谢
def getVoxelTraversalPts(strPt, endPt, geom):
Max_Delta = 1000000.0
#origin
x0 = geom[0]
y0 = geom[3]
(sX, sY) = (strPt[0], strPt[1])
(eX, eY) = (endPt[0], endPt[1])
dx = geom[1]
dy = geom[5]
sXIndex = ((sX - x0) / dx)
sYIndex = ((sY - y0) / dy)
eXIndex = ((eX - sXIndex) / dx) + sXIndex
eYIndex = ((eY - sYIndex) / dy) + sYIndex
deltaX = float(eXIndex - sXIndex)
deltaXSign = 1 if deltaX > 0 else -1 if deltaX < 0 else 0
stepX = deltaXSign
tDeltaX = min((deltaXSign / deltaX), Max_Delta) if deltaXSign != 0 else Max_Delta
maxX = tDeltaX * (1 - sXIndex + int(sXIndex)) if deltaXSign > 0 else tDeltaX * (sXIndex - int(sXIndex))
deltaY = float(eYIndex - sYIndex)
deltaYSign = 1 if deltaY > 0 else -1 if deltaY < 0 else 0
stepY = deltaYSign
tDeltaY = min(deltaYSign / deltaY, Max_Delta) if deltaYSign != 0 else Max_Delta
maxY = tDeltaY * (1 - sYIndex + int(sYIndex)) if deltaYSign > 0 else tDeltaY * (sYIndex - int(sYIndex))
x = sXIndex
y = sYIndex
ptsIndexes = []
pt = [round(x), round(y)]
ptsIndexes.append(pt)
prevPt = pt
while True:
if maxX < maxY:
maxX += tDeltaX
x += deltaXSign
else:
maxY += tDeltaY
y += deltaYSign
pt = [round(x), round(y)]
if pt != prevPt:
#print pt
ptsIndexes.append(pt)
prevPt = pt
if maxX > 1 and maxY > 1:
break
return (ptsIndexes)
【问题讨论】:
-
你可以尝试在codereview.stackexchange.com上提问
-
多年前我已经实现了这个算法并且效果很好。比较不容易比较,因为(似乎)您使用的是以整数为中心的体素。当我调试时,我记录了每个被触摸的单元格的输入参数和坐标。
-
@MBo:我在另一个问题上使用了你之前的回答来让我开始。感谢那。如果我正确地实现了它,并且看起来我做到了。算法会错过单元格。看起来它提供了很好的覆盖率
-
能否在图片中标出进入单元格的位置并在日志中输出参数?给定案例的确切输入参数是什么?
-
输入坐标的数据类型有哪些?您使用的是哪个 Python 版本?您可能会失去初始分区的精度...
标签: python algorithm math geometry raytracing