我正在尝试遍历线路经过的所有单元格。我发现Fast Voxel Traversal Algorithm似乎符合我的需要,但我目前发现它不准确。下面是一个红线和点作为算法给出的体素坐标的图形。正如你所看到的,除了(4,7)点之外它几乎是正确的,因为它应该是(5,6)。我不确定我是否正确实现了算法,所以我把它包含在Python中。所以我想我的问题是我的实现是正确的还是有更好的算法呢?
由于
L
[[ 125.20560531 292.91525518 92.76132814 141.33797061 282.93586313
185.71134917 199.48789246 96.04089205 192.11501055 118.68811072]
[ 174.72737183 408.77013914 129.45061871 197.24046765 394.84366245
259.16456278 278.39005349 134.0273274 268.1010231 165.63205458]
[ 194.38951303 454.76920678 144.01774873 219.43601655 439.27557808
288.32845493 309.71739782 149.10947628 298.27053871 184.27069609]]
S
[[ -25.20560531 0. 252.23867186 -0. 0.
201.28865083 78.51210754 336.95910795 -0. 34.31188928]
[ 125.27262817 238.22986086 115.54938129 228.75953235 494.15633755
727.83543722 -0. -0. 26.8989769 -0. ]
[ 0. 292.23079322 -0. 0. 49.72442192
-0. 68.28260218 883.89052372 0. 268.72930391]]
答案 0 :(得分:1)
你走的体素从0.0开始,即第一个体素从0.0到1.0跨越空间,而不是从-0.5到0.5,正如你所假设的那样。换句话说,它们是用虚线标记的,而不是实线的。
如果您想要自己的体素,则必须修复初始的maxX和maxY计算。
答案 1 :(得分:0)
难道没有人有时间阅读您发布的论文并弄清楚您是否已正确实施。
但这是一个问题。您使用的算法(a)实际上是用于确定线穿过的所有单元格还是(b)形成两点之间直线的体面体素近似值?
我更熟悉执行(b)的Bresenham's line algorithm。以下是它的实际情况:
请注意,细胞的选择是“美学的”,但是省略了细胞经过的某些细胞。包括这些将使这条线“更加丑陋”。
我怀疑你的体素线算法正在发生类似的事情。但是,查看您的数据和Bresenham图像提示了一个简单的解决方案。沿着发现的细胞行走,但是,每当你必须做一个对角线步骤时,考虑两个中间细胞。然后,您可以使用线矩形交集算法(请参阅here)来确定哪些候选单元格应该包含但不包括在内。
答案 2 :(得分:-1)
我想要完成,我决定使用不同的算法。这里引用的那个dtb's answer on another question。
这里是实施
def getIntersectPts(strPt, endPt, geom=[0,1,0,0,0,1]):
'''
Find intersections pts for every half cell size
** cell size has only been tested with 1
Returns cell coordinates that the line passes through
'''
x0 = geom[0]
y0 = geom[3]
(sX, sY) = (strPt[0], strPt[1])
(eX, eY) = (endPt[0], endPt[1])
xSpace = geom[1]
ySpace = geom[5]
sXIndex = ((sX - x0) / xSpace)
sYIndex = ((sY - y0) / ySpace)
eXIndex = ((eX - sXIndex) / xSpace) + sXIndex
eYIndex = ((eY - sYIndex) / ySpace) + sYIndex
dx = (eXIndex - sXIndex)
dy = (eYIndex - sYIndex)
xHeading = 1.0 if dx > 0 else -1.0 if dx < 0 else 0.0
yHeading = 1.0 if dy > 0 else -1.0 if dy < 0 else 0.0
xOffset = (1 - (math.modf(sXIndex)[0]))
yOffset = (1 - (math.modf(sYIndex)[0]))
ptsIndexes = []
x = sXIndex
y = sYIndex
pt = (x, y) #1st pt
if dx != 0:
m = (float(dy) / float(dx))
b = float(sY - sX * m )
dx = abs(int(dx))
dy = abs(int(dy))
if dx == 0:
for h in range(0, dy + 1):
pt = (x, y + (yHeading *h))
ptsIndexes.append(pt)
return ptsIndexes
#print("m {}, dx {}, dy {}, b {}, xdir {}, ydir {}".format(m, dx, dy, b, xHeading, yHeading))
#print("x {}, y {}, {} {}".format(sXIndex, sYIndex, eXIndex, eYIndex))
#snap to half a cell size so we can find intersections on cell boundaries
sXIdxSp = round(2.0 * sXIndex) / 2.0
sYIdxSp = round(2.0 * sYIndex) / 2.0
eXIdxSp = round(2.0 * eXIndex) / 2.0
eYIdxSp = round(2.0 * eYIndex) / 2.0
# ptsIndexes.append(pt)
prevPt = False
#advance half grid size
for w in range(0, dx * 4):
x = xHeading * (w / 2.0) + sXIdxSp
y = (x * m + b)
if xHeading < 0:
if x < eXIdxSp:
break
else:
if x > eXIdxSp:
break
pt = (round(x), round(y)) #snapToGrid
# print(w, x, y)
if prevPt != pt:
ptsIndexes.append(pt)
prevPt = pt
#advance half grid size
for h in range(0, dy * 4):
y = yHeading * (h / 2.0) + sYIdxSp
x = ((y - b) / m)
if yHeading < 0:
if y < eYIdxSp:
break
else:
if y > eYIdxSp:
break
pt = (round(x), round(y)) # snapToGrid
# print(h, x, y)
if prevPt != pt:
ptsIndexes.append(pt)
prevPt = pt
return set(ptsIndexes) #elminate duplicates