计算三维空间中直线和三角形的交点

2 篇文章 1 订阅


前言

在3D编程中,处理点击事件等时可能会遇到判断鼠标是否点击了指定模型的问题,实际上该问题可以拆成几部分考虑:

  1. 根据三点确定一个平面,及两点确定一条直线的原理,可求出直线方程与平面方程。
  2. 两方程联立,可解出直线与平面交点坐标(暂不考虑直线在平面上或与平面平行的情况 )。
  3. 判断平面与直线的交点是否在三角形内部。

一、计算平面方程

3维空间中的平面方程通式为 a x + b y + c z + d = 0 ax+by+cz+d=0 ax+by+cz+d=0
P 1 ( x 1 , y 1 , z 1 ) P_1(x_1,y_1,z_1) P1(x1,y1,z1) P 2 ( x 2 , y 2 , z 2 ) P_2(x_2,y_2,z_2) P2(x2,y2,z2) P 3 ( x 3 , y 3 , z 3 ) P_3(x_3,y_3,z_3) P3(x3,y3,z3) 为三角形三个顶点坐标

判断平面是否过原点的计算方式为 : 如果行列式 [ x 1 y 1 z 1 x 2 y 2 z 2 x 3 y 3 z 3 ] = 0 \left[ \begin{matrix} x_1 & y_1 & z_1 \\ x_2 & y_2 & z_2 \\ x_3 & y_3 & z_3 \end{matrix} \right]=0 x1x2x3y1y2y3z1z2z3=0,平面过原点 ; 否则平面不过原点。

判断平面是否过 z z z 轴的计算方式为 : 在平面过原点的情况下,如果行列式 [ x 1 y 1 x 2 y 2 ] = 0 \left[ \begin{matrix} x_1 & y_1 \\ x_2 & y_2 \end{matrix} \right]=0 [x1x2y1y2]=0,平面过 z z z 轴 ; 否则平面不过 z z z 轴。

判断平面是否为 y O z yOz yOz 平面的计算方式为 : 在平面过 z z z 轴的情况下,如果 x 1 = 0 x_1=0 x1=0,平面为 y O z yOz yOz 平面 ; 否则平面不为 y O z yOz yOz 平面。

1.1 平面不过原点

如果平面不过原点,则 d ≠ 0 d \neq 0 d=0,由于三个点只能确定三个未知数,设 d = − 1 d=-1 d=1,则方程为 a x + b y + c z = 1 ax+by+cz=1 ax+by+cz=1

分别将平面上的三个点 P 1 、 P 2 、 P 3 P_1、P_2、P_3 P1P2P3 代入公式,可得
{ a x 1 + b y 1 + c z 1 = 1 a x 2 + b y 2 + c z 2 = 1 a x 3 + b y 3 + c z 3 = 1 \begin{cases} ax_1+by_1+cz_1=1 \\ ax_2+by_2+cz_2=1 \\ ax_3+by_3+cz_3=1 \end{cases} ax1+by1+cz1=1ax2+by2+cz2=1ax3+by3+cz3=1

转化为矩阵,即为
[ x 1 y 1 z 1 x 2 y 2 z 2 x 3 y 3 z 3 ] [ a b c ] = [ 1 1 1 ] \left[ \begin{matrix} x_1 & y_1 & z_1 \\ x_2 & y_2 & z_2 \\ x_3 & y_3 & z_3 \end{matrix} \right] \left[ \begin{matrix} a \\ b \\ c \end{matrix} \right] = \left[ \begin{matrix} 1 \\ 1 \\ 1 \end{matrix} \right] x1x2x3y1y2y3z1z2z3abc=111

求解 a , b , c a,b,c a,b,c,即
[ a b c ] = [ x 1 y 1 z 1 x 2 y 2 z 2 x 3 y 3 z 3 ] − 1 [ 1 1 1 ] \left[ \begin{matrix} a \\ b \\ c \end{matrix} \right] = \left[ \begin{matrix} x_1 & y_1 & z_1 \\ x_2 & y_2 & z_2 \\ x_3 & y_3 & z_3 \end{matrix} \right] ^{-1} \left[ \begin{matrix} 1 \\ 1 \\ 1 \end{matrix} \right] abc=x1x2x3y1y2y3z1z2z31111

即:将三个点坐标列为矩阵,求逆,然后右乘一个单位列向量,即可求出参数矩阵。

1.2 平面过原点

如果平面过原点,则 d = 0 d=0 d=0,设 c = 1 , c=1, c=1,则方程为 a x + b y + z = 0 ax+by+z=0 ax+by+z=0,此时只有两个未知数,只需要代入两个坐标点即可(两个坐标点都不可为原点 ),方程组为
{ a x 1 + b y 1 = − z 1 a x 2 + b y 2 = − z 2 \begin{cases} ax_1+by_1=-z_1 \\ ax_2+by_2=-z_2 \end{cases} {ax1+by1=z1ax2+by2=z2

转化为矩阵,即为
[ x 1 y 1 x 2 y 2 ] [ a b ] = [ − z 1 − z 2 ] \left[ \begin{matrix} x_1 & y_1 \\ x_2 & y_2 \end{matrix} \right] \left[ \begin{matrix} a \\ b \end{matrix} \right] = \left[ \begin{matrix} -z_1 \\ -z_2 \end{matrix} \right] [x1x2y1y2][ab]=[z1z2]

求解 a 、 b a、b ab,即
[ a b ] = [ x 1 y 1 x 2 y 2 ] − 1 [ − z 1 − z 2 ] \left[ \begin{matrix} a \\ b \end{matrix} \right] = \left[ \begin{matrix} x_1 & y_1 \\ x_2 & y_2 \end{matrix} \right] ^{-1} \left[ \begin{matrix} -z_1 \\ -z_2 \end{matrix} \right] [ab]=[x1x2y1y2]1[z1z2]

{ c = 1 d = 0 \begin{cases} c=1 \\ d=0 \end{cases} {c=1d=0

1.3 平面过 z z z

如果平面过 z z z 轴,则 c = d = 0 c=d=0 c=d=0,设 b = 1 , b=1, b=1,则方程为 a x + y = 0 ax+y=0 ax+y=0,此时只有一个未知数,只需要代入一个坐标点即可(该坐标点 x 、 y x、y xy 分量不可均为0 ),方程为
a x 1 + y 1 = 0 ax_1+y_1=0 ax1+y1=0

解得
{ a = − y 1 z 1 b = 1 c = 0 d = 0 \begin{cases} a=-\frac{y_1}{z_1} \\ b=1 \\ c=0 \\ d=0 \end{cases} a=z1y1b=1c=0d=0

1.4 平面为 y O z yOz yOz 平面

如果平面为 y O z yOz yOz 平面,则
{ a = 1 b = 0 c = 0 d = 0 \begin{cases} a=1 \\ b=0 \\ c=0 \\ d=0 \end{cases} a=1b=0c=0d=0

至此, a , b , c , d a,b,c,d a,b,c,d 全部求出。

二、计算直线方程

3维空间中的直线方程通式为
x − x 1 x − x 2 = y − y 1 y − y 2 = z − z 1 z − z 2 = t \frac{x-x_1}{x-x_2}=\frac{y-y_1}{y-y_2}=\frac{z-z_1}{z-z_2}=t xx2xx1=yy2yy1=zz2zz1=t

其中 P 1 ( x 1 , y 1 , z 1 ) P_1(x_1,y_1,z_1) P1(x1,y1,z1) P 2 ( x 2 , y 2 , z 2 ) P_2(x_2,y_2,z_2) P2(x2,y2,z2) 为直线上不重合的两个点,t为参数,值为点 P ( x , y , z ) P(x,y,z) P(x,y,z) 到两点的距离比。
整理后可得
{ x = t x 2 − x 1 t − 1 y = t y 2 − y 1 t − 1 z = t z 2 − z 1 t − 1 \begin{cases} x=\frac{tx_2-x_1}{t-1} \\ y=\frac{ty_2-y_1}{t-1} \\ z=\frac{tz_2-z_1}{t-1} \end{cases} x=t1tx2x1y=t1ty2y1z=t1tz2z1

三、计算交点坐标

联立方程组
{ x = t x 2 − x 1 t − 1 y = t y 2 − y 1 t − 1 z = t z 2 − z 1 t − 1 − − − − − − − − − − ( 3.1 ) \begin{cases} x=\frac{tx_2-x_1}{t-1} \\ y=\frac{ty_2-y_1}{t-1} \\ z=\frac{tz_2-z_1}{t-1} \end{cases} ----------(3.1) x=t1tx2x1y=t1ty2y1z=t1tz2z1(3.1)

a x + b y + c z + d = 0 − − − − − − − − − − ( 3.2 ) ax+by+cz+d=0 ----------(3.2) ax+by+cz+d=0(3.2)

可得
a t x 2 − x 1 t − 1 + b t y 2 − y 1 t − 1 + c t z 2 − z 1 t − 1 + d = 0 a\frac{tx_2-x_1}{t-1}+b\frac{ty_2-y_1}{t-1}+c\frac{tz_2-z_1}{t-1}+d=0 at1tx2x1+bt1ty2y1+ct1tz2z1+d=0

整理得
t = a x 1 + b y 1 + c z 1 + d a x 2 + b y 2 + c z 2 + d t=\frac{ax_1+by_1+cz_1+d}{ax_2+by_2+cz_2+d} t=ax2+by2+cz2+dax1+by1+cz1+d

a x 2 + b y 2 + c z 2 + d = 0 ax_2+by_2+cz_2+d=0 ax2+by2+cz2+d=0,则交点为 P 2 P_2 P2 ; 否则将 t t t 代入式(3.1),可解出交点坐标。

四、判断交点是否在三角形内部

三角形ABC的三个点在同一个平面上,如果选中其中一个点,其他两个点不过是相对该点的位移而已,比如选择点 A A A 作为起点,那么点 B B B 相当于在 A B → \overrightarrow{AB} AB 方向移动一段距离得到,而点 C C C 相当于在 A C → \overrightarrow{AC} AC 方向移动一段距离得到。所以对于平面内任意一点,都可以由如下方程来表示 :
A P → = u ∗ A B → + v ∗ A C → \overrightarrow{AP}=u*\overrightarrow{AB}+v*\overrightarrow{AC} AP =uAB +vAC

如果系数 u u u v v v 为负值,那么相当于朝相反的方向移动,即 B A → \overrightarrow{BA} BA C A → \overrightarrow{CA} CA 方向。那么如果想让 P P P 位于三角形 A B C ABC ABC 内部, u u u v v v 必须满足什么条件呢?有如下三个条件:
{ u ≥ 0 v ≥ 0 u + v < = 1 \begin{cases} u \geq 0 \\ v \geq 0 \\ u + v <= 1 \end{cases} u0v0u+v<=1

几个边界情况,当 u = v = 0 u=v=0 u=v=0 时,就是点A,当 u = 0 , v = 1 u=0,v=1 u=0,v=1 时,就是点B,而当 u = 1 , v = 0 u=1,v=0 u=1,v=0 时,就是点C。

v 0 = A C → , v 1 = A B → , v 2 = A P → v_0=\overrightarrow{AC},v_1=\overrightarrow{AB},v_2=\overrightarrow{AP} v0=AC ,v1=AB ,v2=AP ,则 v 2 = u ∗ v 0 + v ∗ v 1 v_2=u*v_0+v*v_1 v2=uv0+vv1,现在是一个方程,两个未知数,无法解出 u u u v v v,将等式两边分别点乘 v 0 v_0 v0 v 1 v_1 v1,得到两个等式 :
{ ( v 2 ) • v 0 = ( u ∗ v 0 + v ∗ v 1 ) • v 0 ( v 2 ) • v 1 = ( u ∗ v 0 + v ∗ v 1 ) • v 1 \begin{cases} (v2)•v0=(u*v0+v*v1)•v0 \\ (v2)•v1=(u*v0+v*v1)•v1 \end{cases} {(v2)v0=(uv0+vv1)v0(v2)v1=(uv0+vv1)v1

注意到这里 u 、 v u、v uv 是数,而 v 0 、 v 1 、 v 2 v_0、v_1、v_2 v0v1v2 是向量,所以可以将点积展开得到下面的式子 :
{ v 2 • v 0 = u ∗ ( v 0 • v 0 ) + v ∗ ( v 1 • v 0 ) v 2 • v 1 = u ∗ ( v 0 • v 1 ) + v ∗ ( v 1 • v 1 ) \begin{cases} v2•v0=u*(v0•v0)+v*(v1•v0) \\ v2•v1=u*(v0•v1)+v*(v1•v1) \end{cases} {v2v0=u(v0v0)+v(v1v0)v2v1=u(v0v1)+v(v1v1)

解这个方程得到
{ u = ( ( v 1 • v 1 ) ( v 2 • v 0 ) − ( v 1 • v 0 ) ( v 2 • v 1 ) ) / ( ( v 0 • v 0 ) ( v 1 • v 1 ) − ( v 0 • v 1 ) ( v 1 • v 0 ) ) v = ( ( v 0 • v 0 ) ( v 2 • v 1 ) − ( v 0 • v 1 ) ( v 2 • v 0 ) ) / ( ( v 0 • v 0 ) ( v 1 • v 1 ) − ( v 0 • v 1 ) ( v 1 • v 0 ) ) \begin{cases} u=((v1•v1)(v2•v0)-(v1•v0)(v2•v1))/((v0•v0)(v1•v1)-(v0•v1)(v1•v0)) \\ v=((v0•v0)(v2•v1)-(v0•v1)(v2•v0))/((v0•v0)(v1•v1)-(v0•v1)(v1•v0)) \end{cases} {u=((v1v1)(v2v0)(v1v0)(v2v1))/((v0v0)(v1v1)(v0v1)(v1v0))v=((v0v0)(v2v1)(v0v1)(v2v0))/((v0v0)(v1v1)(v0v1)(v1v0))

解出 u 、 v u、v uv 后,根据上面的规则,即可判断点 P P P 是否在三角形 A B C ABC ABC 内部。

五、参考链接


  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值