异面直线公垂线的垂足坐标计算公式推导(二)

    根据异面直线公垂线的垂足坐标计算公式,定义逻辑类,计算垂足的坐标值。用C#定义该逻辑类,如下

    /// <summary>
    ///公垂线垂足坐标通用推导公式
    /// </summary>
    public class CommonPerpendicular
    {
        //AB构成的直线
        private IPoint ptA = null;
        private IPoint ptB = null;

        //AB直线上的垂足
        private IPoint ptM = null;

        //CD构成的直线
        private IPoint ptC = null;
        private IPoint ptD = null;

        //CD直线上的垂足
        private IPoint ptN = null;

        public CommonPerpendicular()
        {
            try
            {
            }
            catch (Exception ex)
            {
                if (AppLog.log.IsErrorEnabled)
                    AppLog.log.Error("PipeProjFactory:" + ex.Message);
            }
        }

        /// <summary>
        /// 计算异面直线的公垂线两个垂足的坐标
        /// </summary>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <param name="C"></param>
        /// <param name="D"></param>
        /// <param name="M">AB直线上的垂足坐标M</param>
        /// <param name="N">CD直线上的垂足坐标N</param>
        /// <returns></returns>
        public bool ComputePerpendicular(IPoint A, IPoint B, IPoint C, IPoint D, IPoint M, IPoint N)
        {
            try
            {
                if (null == A || null == B || null == C || null == D || null == M || null == N)
                {
                    return false;
                }

                ptA = A;
                ptB = B;

                ptC = C;
                ptD = D;

                ptM = M;
                ptN = N;

                //f1ab
                double fSquareAB = FunSquare(ptA, ptB);

                if (-99999999.99999 == fSquareAB)
                {
                    return false;

                }

                //f1cd
                double fSquareCD = FunSquare(ptC, ptD);

                if (-99999999.99999 == fSquareCD)
                {
                    return false;

                }

                //f3ab
                double fVaryAB = FunVaryOperation(ptA, ptB);
                if (-99999999.99999 == fVaryAB)
                {
                    return false;

                }

                //f3cd
                double fVaryCD = FunVaryOperation(ptC, ptD);
                if (-99999999.99999 == fVaryCD)
                {
                    return false;

                }

                //f2
                double fCross = FunCrossOperation();
                if (-99999999.99999 == fCross)
                {
                    return false;

                }

                double t1 = (fVaryAB * fSquareCD - fVaryCD * fCross) / (fSquareAB * fSquareCD - fCross * fCross);

                double t2 = (fVaryCD * fSquareAB - fCross * fVaryAB) / (fCross * fCross - fSquareAB * fSquareCD);

                ptM.X = t1 * (ptB.X - ptA.X) + ptA.X;
                ptM.Y = t1 * (ptB.Y - ptA.Y) + ptA.Y;
                ptM.Z = t1 * (ptB.Z - ptA.Z) + ptA.Z;

                ptN.X = t2 * (ptD.X - ptC.X) + ptC.X;
                ptN.Y = t2 * (ptD.Y - ptC.Y) + ptC.Y;
                ptN.Z = t2 * (ptD.Z - ptC.Z) + ptC.Z;

                return true;
            }
            catch (Exception ex)
            {
                if (AppLog.log.IsErrorEnabled)
                    AppLog.log.Error("PipeProjFactory:" + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// [(xb-xa)*(xb-xa)+(yb-ya)*(yb-ya)+(zb-za)*(zb-za)],两个点可以被替换
        /// </summary>
        /// <param name="P1"></param>
        /// <param name="P2"></param>
        /// <returns></returns>
        private double FunSquare(IPoint P1, IPoint P2)
        {
            try
            {
                double funValue = 0.0;

                funValue = Math.Sqrt(P2.X - P1.X) + Math.Sqrt(P2.Y - P1.Y) + Math.Sqrt(P2.Z - P1.Z);

                return funValue;

            }
            catch (Exception ex)
            {
                if (AppLog.log.IsErrorEnabled)
                    AppLog.log.Error("PipeProjFactory:" + ex.Message);
                return -99999999.99999;
            }
        }

       /// <summary>
       /// (xb-xa)*(xc-xa)+(yb-ya)*(yc-ya)+(zb-za)*(zc-za),每个和项的第一个公式可以被替换
       /// </summary>
       /// <param name="P1"></param>
       /// <param name="P2"></param>
       /// <returns></returns>
        private double FunVaryOperation(IPoint P1,IPoint P2)
        {
            try
            {
                double funValue = 0.0;

                funValue = (P2.X-P1.X)*(ptC.X -ptA.X)+(P2.Y-P1.Y)*(ptC.Y-ptA.Y)+(P2.Z-P1.Z)*(ptC.Z-ptA.Z);

                return funValue;
            }
            catch (Exception ex)
            {
                if (AppLog.log.IsErrorEnabled)
                    AppLog.log.Error("PipeProjFactory:" + ex.Message);
                return -99999999.99999;
            }
        }

        /// <summary>
        /// (xb-xa)*(xd-xc)+(yb-ya)*(yd-yc)+(zb-za)*(zd-zc)
        /// </summary>
        /// <returns></returns>
        private double FunCrossOperation()
        {
            try
            {
                double funValue = 0.0;

                funValue = (ptB.X - ptA.X) * (ptD.X - ptC.X) + (ptB.Y - ptA.Y) * (ptD.Y - ptC.Y) + (ptB.Z - ptA.Z) * (ptD.Z - ptC.Z);

                return funValue;
            }
            catch (Exception ex)
            {
                if (AppLog.log.IsErrorEnabled)
                    AppLog.log.Error("PipeProjFactory:" + ex.Message);
                return -99999999.99999;
            }
        }
    }

    在逻辑函数定义中,已知P1和P2定义的直线,Q1和Q2定义的直线。判断这两个异面直线的公垂线垂足是否在各自线段范围内,即垂足PPNormalPoint是否在P1P2线段范围内,垂足QQNormalPoint是否在Q1Q2线段范围内。

         /// <summary>
        /// 计算公垂线的两个垂足,判断是否都在4个点确定的两条线段范围上
        /// </summary>
        /// <returns></returns>
        private bool GetNormalCoplanarPoints()
        {
            try
            {
                IPoint PPNormalPoint = new PointClass();
                IPoint QQNormalPoint = new PointClass();

                CommonPerpendicular commonPerPoint = new CommonPerpendicular();

                if (commonPerPoint.ComputePerpendicular(P1, P2, Q1, Q2, PPNormalPoint, QQNormalPoint))
                {
                    if (IsPointInLine(PPNormalPoint, P1, P2) && IsPointInLine(QQNormalPoint, Q1, Q2))
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                if (AppLog.log.IsErrorEnabled)
                    AppLog.log.Error("CollisionAnalysis:" + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 直线上一点是否在起终点确定线段上
        /// </summary>
        /// <param name="pNormal"></param>
        /// <param name="pStart"></param>
        /// <param name="pEnd"></param>
        /// <returns></returns>
        private bool IsPointInLine(IPoint pNormal, IPoint pStart, IPoint pEnd)
        {
            try
            {
                if (null == pNormal || null == pStart || null == pEnd)
                {
                    return false;
                }

                double x = pNormal.X;
                double y = pNormal.Y;
                double z = pNormal.Z;

                double minx = pStart.X > pEnd.X ? pEnd.X : pStart.X;
                double maxx = pStart.X > pEnd.X ? pStart.X : pEnd.X;
                double miny = pStart.Y > pEnd.Y ? pEnd.Y : pStart.Y;
                double maxy = pStart.Y > pEnd.Y ? pStart.Y : pEnd.Y;
                double minz = pStart.Z > pEnd.Z ? pEnd.Z : pStart.Z;
                double maxz = pStart.Z > pEnd.Z ? pStart.Z : pEnd.Z;

                if ((x > minx && x < maxx) && (y > miny && y < maxy) && (z > minz && z < maxz))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                if (AppLog.log.IsErrorEnabled)
                    AppLog.log.Error("CollisionAnalysis:" + ex.Message);
                return false;
            }
        }

QQ32663739,欢迎沟通交流。
原文地址:https://www.cnblogs.com/chuzhouGIS/p/2286308.html