求直线上最近的二点(在公垂线上)

直线是用一个点和一个方向向量(已单位化)构成.现在要求二条直线最近的点(即公垂线与两直线的交点)

class Cray//射线类

{

protected:

    CVector_3D m_ptStart;//原点

    CVector_3D m_ptDir;//方向

……

}

如果二个直线平行,则两条直线r1,r2的方向向量的内积必为1-1,此时可计算S2r1上的投影(点乘),r1上计算投影点为Sproject,则要求的两点分别为SprojectS2.如下图所示

如果二直线不平行,可用数学公式求解:

 

设所求公垂线上的二点分别为M(m0, m1, m2), N(n0, n1, n2).二个起点分别为S1(S1x, S1y, S1z), S2(S2x, S2y, S2z),二个方向向量分别为D1(D1x, D1y,D1z)则根据直线的参数方程法:

(M0- S1x)/ D1x = (M1- S1y)/ D1y = (M2- S1z)/ D1z = K1;

(N0- S2x)/ D2x = (N1- S2y)/ D2y = (N2- S2z)/ D2z = K2;

M(m0, m1, m2)可表示为(D1x* K1+ S1x, D1y* K1+ S1y, D1z* K1+ S1z)

N(n0, n1, n2) 可表示为(D2x* K2+ S2x, D2y* K2+ S2y, D2z* K2+ S2z)

MN点乘D1结果为0MN点乘D1结果为0。所以,可得:

-a+ K1-t.K2=0D1.D1=1D2.D2=1,可设D1.D2=t, D1 .(S1-S2)=-a

       b+t.K1-K2=0

解之,可得:

K1=(a+ b* dot)/ (1-t*t)

K2=(b+ a* dot)/ (1-t*t)

M(D1x* K1+ S1x, D1y* K1+ S1y, D1z* K1+ S1z),N(D2x* K2+ S2x, D2y* K2+ S2y, D2z* K2+ S2z)求解完毕。

 

代码如下:

double dot= CVector_3D::Dot( m_ptDir, r.Get_Dir() );//求二个方向向量的内积

    double t2= 1- dot* dot;

    CVector_3D v;

 

    if ( abs( t2 ) < INFINITY_LITTLE)//如果二射线平行

    {

       double dProject= CVector_3D::Dot( m_ptDir, m_ptStart- r.Get_Start()) / dot;//获取投影

 

       pt1= m_ptStart;

       CVector_3D::Add( r.Get_Start(), CVector_3D::Multiply( r.Get_Dir(), dProject, v ), pt2);

 

 

    }

    else

    {

       double a= CVector_3D::Dot( m_ptDir, CVector_3D::Subtract( r.Get_Start(), m_ptStart, v));

       double b= CVector_3D::Dot( r.Get_Dir(), CVector_3D::Subtract( m_ptStart, r.Get_Start(), v));

 

       double k1= ( a+ b* dot)/ t2;//二个直线方向参数

       double k2= ( b+ a* dot)/ t2;

 

       CVector_3D::Add( m_ptStart , CVector_3D::Multiply( m_ptDir, k1, v ), pt1);

       CVector_3D::Add( r.Get_Start() , CVector_3D::Multiply( r.Get_Dir(), k2, v ), pt2);

    }

 

  

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值