Math 计算交点的长度(通过二维栅格)

Math 计算交点的长度(通过二维栅格),math,grid,coordinates,Math,Grid,Coordinates,我有一条线,我必须对这条线经过的每个网格正方形进行计算 我使用了超直线算法来获得所有这些网格正方形。这给了我一个X,Y坐标数组来检查 现在,这里是我被卡住的地方,我需要能够计算通过每个网格方块的距离。。。如中所示,在不是90度角或45度角的直线上,每个网格正方形容纳不同的总直线“长度” 正如你所看到的,一些正方形比其他正方形有更多的“线长度”——这就是我需要找到的 如何计算每个网格正方形的值?我已经做了一段时间了,请求堆栈溢出器的帮助 使用欧几里德距离 sqrt((x2-x1)^2+(y2-y

我有一条线,我必须对这条线经过的每个网格正方形进行计算

我使用了超直线算法来获得所有这些网格正方形。这给了我一个X,Y坐标数组来检查

现在,这里是我被卡住的地方,我需要能够计算通过每个网格方块的距离。。。如中所示,在不是90度角或45度角的直线上,每个网格正方形容纳不同的总直线“长度”

正如你所看到的,一些正方形比其他正方形有更多的“线长度”——这就是我需要找到的


如何计算每个网格正方形的值?我已经做了一段时间了,请求堆栈溢出器的帮助

使用欧几里德距离

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)

看一看:“快速计算三维CT阵列的精确放射路径”

不幸的是,您需要订阅才能阅读原始论文,但在


Siddon算法是一种O(n)算法,用于在常规2d/3d网格中查找线与每个像素/体素的交点长度。

可能有一些聪明的方法可以更快更简单地完成此操作,但您可以像这样进行操作:

你知道距离公式: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)。您可以将其近似到任何所需的精度级别

要在程序中实现这一点,您需要如下内容:(我将使用伪代码,因为我不知道您使用的是什么语言)

//假设y=mx+b
函数y(x)
返回mx+b
函数x(y)
返回(y-b)/m
//cellx、celly是单元格左下角的坐标
//因此,右上角必须是cellx+1,celly+1
函数segLength(cellx,celly)
//我们将创建两个数组pointx和pointy来保存相交点的坐标
//n是这些数组的索引
//在面向对象的语言中,我们会创建一个点对象数组,但不管怎样
n=0
y1=y(单元X)

如果y1>=celly,y1=celly,y2=cellx,x1=cellx,x2是的,我想过这样做,但这能在每个网格正方形上工作吗?(假设我把小数保留在?)-我的意思是,我的算法只计算整数网格平方。我是否也需要将其更改为十进制计算?我知道这可以解决我的问题,但我想要的是更简单的方法。那应该是
^2
(或
**2
,取决于你的符号)而不是
*2
。这是计算二维平面上两点之间实际距离的最佳方法。是的,问题是我只知道起点和终点,而不知道中间点,我相信Siddons算法更接近我所需要的。我明白了。感谢您更全面地解释这一点。我将尝试实现这一点,看看我能做到什么。非常感谢,我花了大约3个小时让它正常工作,但这主要是计算坡度的问题(使用的是起点和终点,而不是实际的直线点),我不知道如何计算Y截距。一旦我开始了,我还必须复制你的代码块,包括cellX-1和Y-1,因为我有多个方向的行。非常感谢!
// 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"