一、基础知识
1、方向向量(direction vector)是一个数学概念,空间直线的方向用一个与该直线平行的非零向量来表示,该向量称为这条直线的一个方向向量。
2、直线l⊥α,取直线l的方向向量a,则向量a叫做
平面α的法向量。
3、直线表示方式:Ax+By+Cz+d=0
二、已知三点坐标怎样求法向量
已知A(x1,y1,z1),B(x2,y2,z2),C(x3,y3,z3)三点的面怎样求它的法向量
求:1.三个点可以形成3个向量,比如向量AB,向量AC和向量BC,则分别得到(x2-x1,y2-y1,z2-z1),AC(x3-x1,y3-y1,z3-z1),(x3-x2,y3-y2,z3-z2)
2.设平面的法向量坐标是(x,y,z)则,根据法向量定义的,得到方程组:
(x2-x1)*x+(y2-y1)*y+(z2-z1)*z=0;
且(x3-x1)*x+(y3-y1)*y+(z3-z1)*z=0;
且(x3-x2)*x+(y3-y2)*y+(z3-z2)*z=0 ;
解出来x,y,z就是平面法向量的坐标,方向满足 右手螺旋 法则.
三、空间直线与平面的交点
如果直线不与平面平行,将存在交点。如下图所示,已知直线L过点m(m1,m2,m3),且方向向量为VL(v1,v2,v3),平面P过点n(n1,n2,n3),且法线方向向量为VP(vp1,vp2,vp3),求得直线与平面的交点O的坐标(x,y,z):
将直线方程写成参数方程形式,即有:
x = m1+ v1 * t
y = m2+ v2 * t (1)
z = m3+ v3 * t
将平面方程写成点法式方程形式,即有:
vp1 * (x – n1) + vp2 * (y – n2) + vp3 * (z – n3) = 0 (2)
则直线与平面的交点一定满足式(1)和(2),联立两式,求得:
t = ((n1 – m1)*vp1+(n2 – m2)*vp2+(n3 – m3)*vp3) / (vp1* v1+ vp2* v2+ vp3* v3) (3)
如果(3)式中分母(vp1* v1+ vp2* v2+ vp3* v3)为0,则表示直线与平面平行,即直线与平面没有交点。求解出t后,然后将t代入式(1)即可求得交点O的坐标(x,y,z)。定义一个求直线与平面交点坐标的函数
使用向量表示就是 vector3d S = R1 + (RN *(R0-R1))/(RN*RA)*RA (R1是直线起点、RA是直线的方向向量、RN是平面法矢、R0是平面上一点、S就是计算得到的交点)
四、相关代码
1.点方式求法,直线上两点坐标A(Lx1, Ly1, Lz1),B(Lx2, Ly2, Lz2),与平面上的三点坐标C(Px1, Py1, Pz1),D(Px2, Py2, Pz2),E(Px3, Py3, Pz3),则该直线与平面的交点坐标计算方法为:
public double[] MianXianJiaoDianXYZ(double Lx1, double Ly1, double Lz1, double Lx2, double Ly2, double Lz2, double Px1, double Py1, double Pz1, double Px2, double Py2, double Pz2, double Px3, double Py3, double Pz3)
{
double[] newJiaoPoint = new double[3];
//L直线矢量
double m = Lx2 - Lx1;
double n = Ly2 - Ly1;
double p = Lz2 - Lz1;
//MessageBox.Show(m.ToString("#0.#") + "," + n.ToString("#0.#") + "," + p.ToString("#0.#,"));
//平面方程Ax+BY+CZ+d=0 行列式计算
double A = Py1 * Pz2 + Py2 * Pz3 + Py3 * Pz1 - Py1 * Pz3 - Py2 * Pz1 - Py3 * Pz2;
double B = -(Px1 * Pz2 + Px2 * Pz3 + Px3 * Pz1 - Px3 * Pz2 - Px2 * Pz1 - Px1 * Pz3);
double C = Px1 * Py2 + Px2 * Py3 + Px3 * Py1 - Px1 * Py3 - Px2 * Py1 - Px3 * Py2;
double D = -(Px1 * Py2 * Pz3 + Px2 * Py3 * Pz1 + Px3 * Py1 * Pz2 - Px1 * Py3 * Pz2 - Px2 * Py1 * Pz3 - Px3 * Py2 * Pz1);
//MessageBox.Show(A.ToString("#0.#") + "," + B.ToString("#0.#") + "," + C.ToString("#0.#,") + "," + D.ToString("#0.#,"));
//系数比值 t=-(Axp+Byp+Cxp+D)/(A*m+B*n+C*p)
if (A*m+B*n+C*p == 0) //判断直线是否与平面平行
{
newJiaoPoint = null;
}
else
{
double t = -(Lx1 * A + Ly1 * B + Lz1 * C + D) / (A * m + B * n + C * p);
//MessageBox.Show(t.ToString("#0.##############"));
newJiaoPoint[0] = Lx1 + m * t;
newJiaoPoint[1] = Ly1 + n * t;
newJiaoPoint[2] = Lz1 + p * t;
//MessageBox.Show(newJiaoPoint[0].ToString("#0.####") + "," + newJiaoPoint[1].ToString("#0.####") + "," + newJiaoPoint[2].ToString("#0.####"));
}
return (newJiaoPoint);
}
2.向量方式求法
///
/// 求一条直线与平面的交点
///
/// 平面的法线向量,长度为3
/// 平面经过的一点坐标,长度为3
/// 直线的方向向量,长度为3
/// 直线经过的一点坐标,长度为3
///
private float[] CalPlaneLineIntersectPoint(float[] planeVector, float[] planePoint, float[] lineVector, float[] linePoint)
{
float[] returnResult = new float[3];
float vp1, vp2, vp3, n1, n2, n3, v1, v2, v3, m1, m2, m3, t,vpt;
vp1 = planeVector[0];
vp2 = planeVector[1];
vp3 = planeVector[2];
n1 = planePoint[0];
n2 = planePoint[1];
n3 = planePoint[2];
v1 = lineVector[0];
v2 = lineVector[1];
v3 = lineVector[2];
m1 = linePoint[0];
m2 = linePoint[1];
m3 = linePoint[2];
vpt = v1 * vp1 + v2 * vp2 + v3 * vp3;
//首先判断直线是否与平面平行
if (vpt == 0)
{
returnResult = null;
}
else
{
t = ((n1 - m1) * vp1 + (n2 - m2) * vp2 + (n3 - m3) * vp3) / vpt;
returnResult[0] = m1 + v1 * t;
returnResult[1] = m2 + v2 * t;
returnResult[2] = m3 + v3 * t;
}
return returnResult;
}