我有一条线,我必须对线经过的每个网格方格进行计算。
我使用Superline算法来获取所有这些网格方块。这给了我一个X,Y坐标数组来检查。
现在,这里是我被卡住的地方,我需要能够计算通过每个网格方块的距离......就像在不是90度或45度角的线上一样,每个网格方块适应总线的不同“长度”。
Image example here, need 10 reputation to post images
正如您所看到的,有些正方形比其他正方形具有更多的“线长” - 这是我需要找到的。
我如何为每个网格方块进行此操作?我已经有一段时间了,请求Stack Overflowers的帮助!
答案 0 :(得分:2)
看看Siddon's algorithm:“快速计算三维CT阵列的精确放射路径”
很遗憾,您需要订阅才能阅读原始论文,但在this paper
中有相当好的描述Siddon的算法是一种O(n)算法,用于在常规的2d / 3d网格中查找线与每个像素/体素的交点长度。
答案 1 :(得分:1)
可能有一些聪明的方法可以更快更容易地做到这一点,但你总是可以像这样破解它:
你知道距离公式:s = sqrt((x2-x1)^ 2 +(y2-y1)^ 2)。要应用此选项,您必须找到线与每个网格单元边缘相交的点的x和y坐标。您可以通过将单元格边界的x和y坐标插入线的等式并在适当时求解x或y来实现此目的。
即,每个单元格从某个点(x0,y0)延伸到(x0 + 1,y0 + 1)。所以我们需要找到y(x0),y(x0 + 1),x(y0)和x(y0 + 1)。对于这些中的每一个,找到的x或y值可以在或可以不在该单元的该坐标的范围内。具体来说,其中两个将是,两个不会。两条线对应于线穿过的边,而两条线不是它不通过的边。
好吧,也许这听起来很混乱,所以让我们通过一个例子。
假设您的线具有等式x = 2/3 * y。您想知道它与从(1,0)到(2,1)的单元格边缘相交的位置。
插入x = 1,你得到y = 2/3。 2/3在y - 0到1的合法范围内 - 因此(1,2 / 3)是线与该单元格相交的边缘上的一个点。即,左边缘。
插入x = 2,你得到y = 4/3。 4/3超出y的范围。所以线不会通过右边缘。
插入y = 0,你得到x = 0。 0不在x的范围内,因此该线不会通过底边。
插入y = 1,你得到x = 3/2。 3/2在x的合法范围内,因此(3 / 2,1)是另一个交叉点,位于顶部边缘。
因此,线与单元边缘相交的两个点是(1,2 / 3)和(3 / 2,1)。将这些插入到距离公式中,您将获得通过此单元格的线段长度,即sqrt((1-3 / 2)^ 2 +(2 / 3-1)^ 2)= sqrt(1/4) +1/9)= SQRT(13/36)。您可以将其逼近任何所需的精度水平。
要在程序中执行此操作,您需要以下内容:(我将使用伪代码,因为我不知道您使用的是哪种语言)
// Assuming y=mx+b
function y(x)
return mx+b
function x(y)
return (y-b)/m
// cellx, celly are co-ordinates of lower left corner of cell
// Upper right must therefore be cellx+1, celly+1
function segLength(cellx, celly)
// We'll create two arrays pointx and pointy to hold co-ordinates of intersect points
// n is index into these arrays
// In an object-oriented language, we'd create an array of point objects, but whatever
n=0
y1=y(cellx)
if y1>=celly and y1<=celly+1
pointx[n]=cellx
pointy[n]=y1
n=n+1
y2=y(cellx+1)
if y2>=celly and y2<=celly+1
pointx[n]=cellx+1
pointy[n]=y2
n=n+1
x1=x(celly)
if x1>=cellx and x1<=cellx+1
pointx[n]=x1
pointy[n]=celly
n=n+1
x2=x(celly+1)
if x2>=cellx and x2<=cellx+1
pointx[n]=x2
pointy[n]=celly+1
n=n+1
if n==0
return "Error: line does not intersect this cell"
else if n==2
return sqrt((pointx[0]-pointx[1])^2+(pointy[0]-pointy[1])^2)
else
return "Error: Impossible condition"
嗯,我相信你可以让代码更清洁,但这就是主意。
答案 2 :(得分:0)
使用欧几里德距离。
sqrt((x2-x1)^ 2 +(y2-y1)^ 2)
这给出了点(x1,y1)和(x2,y2)之间的实际距离
你可以相当简单地找到每个方格。
你有m =(y2-y1)/(x2-x1)的斜率。
你有一个起点: (X1,Y2)
x1 + 1的y位置是多少? (即从下一个广场开始)
假设您将起点设置为0,此行的等式就是: y_n = mx_n
所以y_n =(y2-y1)/(x2-x1)* x_n
然后第一个方格的坐标是(x1,y1)和第n个点: (1,((y2-y1)/(x2-x1))* 1) (2,((y2-y1)/(x2-x1))* 2) (3,((y2-y1)/(x2-x1))* 3) ... (n,((y2-y1)/(x2-x1))* n)
然后通过第n个方格的距离是: sqrt((x_n + 1 - x_n)^ 2 +(y_n + 1 - y_n)^ 2)