求直线与平面的交点

如何求直线与平面的交点

今天遇到一个小问题,如何求线与平面的交点,以及如何将其高效实现,下面就从数学的原理以及编程实现来探究一下这个小问题。

目录

文章目录

  • 如何求直线与平面的交点
      • 目录
    • @[toc]
    • 问题重述与几何模型
    • 数学分析

问题重述与几何模型

已知P1(x1,y1,z1),P2(x2,y2,z2),平面α:ax+by+cz+d=0,求直线P1P2与平面α的交点P。
求直线与平面的交点_第1张图片

数学分析

存在性:直线与平面的交点可能有零个,一个,或无数个。
可行性:已知直线上不重合两点,可以确定一条直线,已知直线与平面,则一定可以得到两者之间的关系。
###常规解法(联立方程
当P1P2不与任一坐标平面平行时:$\dfrac{x-x1}{x1-x2}=\dfrac{y-y1}{y1-y2}=\dfrac{z-z1}{z1-z2} $
xxx表示yyyzzz:
y=y1+(x1−x2)(y1−y2)x−x1y=y1+\dfrac{(x1-x2)(y1-y2)}{x-x1}y=y1+xx1(x1x2)(y1y2)
z=z1+(x1−x2)(z−z1)x−x1z=z1+\dfrac{(x1-x2)(z-z1)}{x-x1}z=z1+xx1(x1x2)(zz1)
与直线方程ax+by+cz+d=0ax+by+cz+d=0ax+by+cz+d=0联立可得:
ax(x1−x2)+b((y1−y2)(x−x1)+y1(x1−x2))+c((z1−z2)(x−x1)+z1(x1−x2))+d=0ax(x1-x2)+b((y1-y2)(x-x1)+y1(x1-x2))+c((z1-z2)(x-x1)+z1(x1-x2))+d=0ax(x1x2)+b((y1y2)(xx1)+y1(x1x2))+c((z1z2)(xx1)+z1(x1x2))+d=0
解该方程即可得:
x=(−d+bx1(y1−y2)−by1(x1−x2)+cx1(z1−z2)−cz1(x1−x2))a(x1−x2)+b(y1−y2)+c(z1−z2)x=\dfrac{(-d+bx1(y1-y2)-by1(x1-x2)+cx1(z1-z2)-cz1(x1-x2))}{a(x1-x2)+b(y1-y2)+c(z1-z2)}x=a(x1x2)+b(y1y2)+c(z1z2)(d+bx1(y1y2)by1(x1x2)+cx1(z1z2)cz1(x1x2))
然后即可得到y,zy,zy,z
:该方法原理简单,容易理解,在一般考试解题中使用较多,但是不容易步骤化,编程实现需要很多判断,代码比较繁琐。
###向量法
当已知平面的一般式方程时(ax+by+cz+d=0ax+by+cz+d=0ax+by+cz+d=0),n⃗=(a,b,c)′\vec n=(a,b,c)'n=(a,b,c)就是平面的法矢量,也就能够很容易求出点到平面的距离和一个向量到法矢量的投影。由前面的几何模型,我们容易得出:
P1P2→P1P→=P1D2→P1D→=∣P1D2→∣∣P1D→∣=n\dfrac{\overrightarrow{P1P2}}{\overrightarrow{P1P}}=\dfrac{\overrightarrow{P1D2}}{\overrightarrow{P1D}}=\dfrac{\lvert\overrightarrow{P1D2}\rvert}{\lvert\overrightarrow{P1D}\rvert}=nP1PP1P2=P1DP1D2=P1DP1D2=n
其中:
∣P1D→∣=ax1+by1+cz1+da2+b2+c2\lvert \overrightarrow{P1D}\rvert=\dfrac{ax1+by1+cz1+d}{\sqrt{a^{2}+b^{2}+c^{2}}}P1D=a2+b2+c2ax1+by1+cz1+d
∣P1D2→∣=a(x2−x1)+b(y2−y1)+c(z2−z1)a2+b2+c2\lvert \overrightarrow{P1D2}\rvert=\dfrac{a(x2-x1)+b(y2-y1)+c(z2-z1)}{\sqrt{a^{2}+b^{2}+c^{2}}}P1D2=a2+b2+c2a(x2x1)+b(y2y1)+c(z2z1)
可得:
n=∣P1D2→∣∣P1D→∣=a(x2−x1)+b(y2−y1)+c(z2−z1)ax1+by1+cz1+dn=\dfrac{\lvert\overrightarrow{P1D2}\rvert}{\lvert\overrightarrow{P1D}\rvert}=\dfrac{a(x2-x1)+b(y2-y1)+c(z2-z1)}{ax1+by1+cz1+d}n=P1DP1D2=ax1+by1+cz1+da(x2x1)+b(y2y1)+c(z2z1)
易得:
OP→=OP1→+P1P→=OP1→+nP1P2→\overrightarrow{OP}=\overrightarrow{OP1}+\overrightarrow{P1P}=\overrightarrow{OP1}+n\overrightarrow{P1P2}OP=OP1+P1P=OP1+nP1P2
上面过程主要使用向量运算,巧妙避开了求模运算中的开方运算,减少了很多的运算量,而且,容易步骤化,易于编程实现。
##编程实现
###常规解法

   //c
    //p[]:XYZ for point P(intersection)
    //P1[]:XYZ for P1
    //P2[]:XYZ for P2
    //coffi[]:a,b,c,d for the plane
    bool intersectionLinePlane(float P[],float P1[],float P2[],float coeffi[])
    {
	    float P1P2[3]={0};
	    float temp_x=P1[0]-P2[0],temp_y=P1[1]-P2[1],temp_z=P1[2]-P2[2];
	    int i=0;
	    for(i=0;i<3;i++)
	    {
		    P1P2[i]=P2[i]-P1[i];
	    }
	    //parallel?
	    if(fabs(P1P2[0]*coeffi[0]+P1P2[1]*coeffi[1]+P1P2[2]*coeffi[2])<1e-5)
	    {
		    //no intersection or the line is on the plane
		    return false;
	    }
	    //if it can't be solve by this method?
	    if(fabs(temp_x)<1e-5||fabs(temp_y)<1e-5||fabs(temp_z)<1e-5)
	    {
		    return false;
	    }
	    *des_x=(-coeffi[3]*temp_x+b*P1[0]*temp_y-coeffi[1]*P1[1]*temp_x+coeffi[2]*p1[0]*temp_z-
	    coeffi[2]*P1[2]*temp_x)/(coeffi[0]*temp_x+coeffi[1]*temp_y+coeffi[2]*temp_z);
	    *des_y=(*des_x-P1[0])*temp_y/temp_x+P1[1];
	    *des_z=(*des_x-P1[0])*temp_z/temp_x+P1[2];
	    
	    return true;
    }
    

:上面代码未严格测试,仅供参考。

###向量解法

    //C
    //p[]:XYZ for point P(intersection)
    //P1[]:XYZ for P1
    //P2[]:XYZ for P2
    //coffi[]:a,b,c,d for the plane
    bool intersectionLinePlane(float P[],float P1[],float P2[],float coeffi[])
    {
	    float P1P2[3]={P2[0]-P1[0],P2[1]-P1[1],P2[2]-P1[2]};
	    int i=0;
	    float num,den,n;
	    num = coeffi[0]*P1[0]+coeffi[1]*P1[1]+coeffi[2]*P1[2] + coeffi[3];
		den = coeffi[0]*P1P2[0]+coeffi[1]*P1P2[1]+coeffi[2]*P1P2[2];
		if(fabs(den)<1e-5)
		{
			//parallel
			return false;
		}
		n=num/den;
		for(i=0;i<3;i++)
			P[i]=P1[i]+n*P1P2[i];

		return true;
    }
    

: 上面代码未严格测试,仅供参考。

##结语
相比来说,第一种适合我们手算,第二种适合编程实现。
:如有错误,还请批评指正。

你可能感兴趣的:(C/C++)