如何检查棱镜之间是否有一条线
How to check if a line lies between a prism
如果我在 3d 中有 2 个点 space 我如何确定直角棱镜是否位于这 2 个点之间?另外,关于直角棱镜,我所掌握的唯一信息是它的最小和最大 x、y 和 z 值。我知道我可以沿着这 2 个点之间的线进行迭代,检查该点是否在直角棱镜内,但这似乎非常耗费资源。我真正需要的是一种检查线段是否与棱镜相交的方法,但我不确定该怎么做,有什么想法吗?
我发现这两个资源与我的问题相似
https://math.stackexchange.com/questions/2134505/how-to-check-if-an-infinite-line-intersects-a-rectangular-prism-in-3d-space
How to check if an infinite line intersects a rectangular prism in 3d space?
看那个底部 link 它只是简单地说要找到与直角棱镜相交的参数 t 这很明显,但问题是我不知道该怎么做,有什么想法吗?
将您的线点和棱镜边缘投影到垂直于您的线的二维平面上。
在二维平面上,直线的两点只是一个点,棱柱的边只是一串相连的顶点,形成一个封闭区域。检查一个点是否在封闭区域内,这对于 2D 很容易做到。
如果你的点在 3D 中,那么直线与棱镜相交,如果不在,则不相交。
现在有一种情况是两端不接触棱镜的线段。在这种情况下,您只需检查点到棱镜表面的距离,有一个方程式。
设线段由(X1, Y1)
和(X2, Y2)
两点定义。
让框由范围 xmin..xmax
、ymin..ymax
、zmin..zmax
.
定义
我们可以为线段写参数方程,其中t
在范围0..1:
X = X1 + t * (X2 - X1)
Y = Y1 + t * (Y2 - Y1)
Z = Z1 + t * (Z2 - Z1)
盒子有 6 个面。让第一个在 xmin
。我们可以在第一个等式中替换 xmin
并找到参数 t
,其中线与该面相交。
xmin = X1 + t1 * (X2 - X1)
t1 = (xmin - X1) / (X2 - X1)
现在检查 t1
是否在 0..1
范围内。如果是,将此 t1
值代入第二个和第三个等式
Y = Y1 + t1 * (Y2 - Y1)
Z = Z1 + t1 * (Z2 - Z1)
并检查结果 Y 和 Z 是否分别位于 ymin..ymax
和 zmin..zmax
范围内。
如果是 - 线段确实与框相交
如果没有,对其他面重复xmax
、ymin
等。
P.S。您还可以考虑线段完全在框内的特殊情况(只需检查 X1、Y1、Z1 是否在框范围内)
P.P.S。当线平行于某个坐标平面时,不检查与相应面的交点(例如,如果 X2-X1==0
,你不能除以零,但你不需要检查 xmin
和 xmax
脸)
Quick-made Python-like伪代码供参考:
def DoesSegmentIntersectBox(x1,y1,z1,x2,y2,z2,xmin,xmax,yin,ymax,zmin,zmax):
if zmin<=z1<=zmax and ymin<=y1<=ymax and xmin<=x1<=xmax:
return True #end inside the box
if (x2-x1):
t = (xmin-x1) / (x2-x1)
if 0<=t<=1: #line intersects plane in segment range
y = y1+t*(y2-y1)
if ymin<=y<=ymax: #segment intersects face in y range
z = z1+t*(z2-z1)
if zmin<=z<=zmax: #segment intersects face in z range
return True #segment does intersect face xmin
t = (xmax-x1) / (x2-x1)
#same 6 lines
if (y2-y1):
t = (ymin-y1) / (y2-y1)
if 0<=t<=1:
x = x1+t*(x2-x1)
if xmin<=x<=xmax:
z = z1+t*(z2-z1)
if zmin<=z<=zmax:
return True
t = (ymax-y1) / (y2-y1)
#same 6 lines
if (z2-z1):
t = (zmin-z1) / (z2-z1)
if 0<=t<=1:
x = x1+t*(x2-x1)
if xmin<=x<=xmax:
y = y1+t*(y2-y1)
if ymin<=y<=ymax:
return True
t = (zmax-z1) / (z2-z1)
#same 6 lines
return False
如果我在 3d 中有 2 个点 space 我如何确定直角棱镜是否位于这 2 个点之间?另外,关于直角棱镜,我所掌握的唯一信息是它的最小和最大 x、y 和 z 值。我知道我可以沿着这 2 个点之间的线进行迭代,检查该点是否在直角棱镜内,但这似乎非常耗费资源。我真正需要的是一种检查线段是否与棱镜相交的方法,但我不确定该怎么做,有什么想法吗?
我发现这两个资源与我的问题相似 https://math.stackexchange.com/questions/2134505/how-to-check-if-an-infinite-line-intersects-a-rectangular-prism-in-3d-space
How to check if an infinite line intersects a rectangular prism in 3d space?
看那个底部 link 它只是简单地说要找到与直角棱镜相交的参数 t 这很明显,但问题是我不知道该怎么做,有什么想法吗?
将您的线点和棱镜边缘投影到垂直于您的线的二维平面上。
如果你的点在 3D 中,那么直线与棱镜相交,如果不在,则不相交。
现在有一种情况是两端不接触棱镜的线段。在这种情况下,您只需检查点到棱镜表面的距离,有一个方程式。
设线段由(X1, Y1)
和(X2, Y2)
两点定义。
让框由范围 xmin..xmax
、ymin..ymax
、zmin..zmax
.
我们可以为线段写参数方程,其中t
在范围0..1:
X = X1 + t * (X2 - X1)
Y = Y1 + t * (Y2 - Y1)
Z = Z1 + t * (Z2 - Z1)
盒子有 6 个面。让第一个在 xmin
。我们可以在第一个等式中替换 xmin
并找到参数 t
,其中线与该面相交。
xmin = X1 + t1 * (X2 - X1)
t1 = (xmin - X1) / (X2 - X1)
现在检查 t1
是否在 0..1
范围内。如果是,将此 t1
值代入第二个和第三个等式
Y = Y1 + t1 * (Y2 - Y1)
Z = Z1 + t1 * (Z2 - Z1)
并检查结果 Y 和 Z 是否分别位于 ymin..ymax
和 zmin..zmax
范围内。
如果是 - 线段确实与框相交
如果没有,对其他面重复xmax
、ymin
等。
P.S。您还可以考虑线段完全在框内的特殊情况(只需检查 X1、Y1、Z1 是否在框范围内)
P.P.S。当线平行于某个坐标平面时,不检查与相应面的交点(例如,如果 X2-X1==0
,你不能除以零,但你不需要检查 xmin
和 xmax
脸)
Quick-made Python-like伪代码供参考:
def DoesSegmentIntersectBox(x1,y1,z1,x2,y2,z2,xmin,xmax,yin,ymax,zmin,zmax):
if zmin<=z1<=zmax and ymin<=y1<=ymax and xmin<=x1<=xmax:
return True #end inside the box
if (x2-x1):
t = (xmin-x1) / (x2-x1)
if 0<=t<=1: #line intersects plane in segment range
y = y1+t*(y2-y1)
if ymin<=y<=ymax: #segment intersects face in y range
z = z1+t*(z2-z1)
if zmin<=z<=zmax: #segment intersects face in z range
return True #segment does intersect face xmin
t = (xmax-x1) / (x2-x1)
#same 6 lines
if (y2-y1):
t = (ymin-y1) / (y2-y1)
if 0<=t<=1:
x = x1+t*(x2-x1)
if xmin<=x<=xmax:
z = z1+t*(z2-z1)
if zmin<=z<=zmax:
return True
t = (ymax-y1) / (y2-y1)
#same 6 lines
if (z2-z1):
t = (zmin-z1) / (z2-z1)
if 0<=t<=1:
x = x1+t*(x2-x1)
if xmin<=x<=xmax:
y = y1+t*(y2-y1)
if ymin<=y<=ymax:
return True
t = (zmax-z1) / (z2-z1)
#same 6 lines
return False