public static Vector3 GetHoverPoint(Vector3 lp1, Vector3 lp2, Vector3 modelP, float attachR)
        {
            var _area    = Geometric.GetArea(lp1, lp2, modelP);                  //三角形面积
            var _lLength = Vector3.Distance(lp1, lp2);                           //lp1,lp2长度
            var dis      = _lLength < 1e-3 ? attachR + 1 : 2 * _area / _lLength; //modelP到lp1,lp2的距离

            if (dis > attachR)                                                   //太远
            {
                return(default(Vector3));
            }

            Vector3 lDir = lp1 - lp2;                                //直线方向
            Vector3 mDir = QuaternionUtility.Euler(0, 90, 0) * lDir; //xz平面上垂直直线方向
            Vector3 __S  = modelP - mDir * 999;
            Vector3 __E  = modelP + mDir * 999;                      //临时的两个线点

            if (!Geometric.Meet(__S, __E, lp1, lp2))                 //不相交
            {
                return(default(Vector3));
            }

            //到这里还能执行的话是相交且接近, 就要计算点
            Vector3 res = Geometric.GetCorssPointOfSegment(__E, __S, lp1, lp2);

            return(res);
        }
        public static bool IsPointAlmostOnSegment(Vector3 lineP1, Vector3 lineP2, float width, Vector3 toCheck)
        {
            Vector3    _lineDir  = (lineP2 - lineP1).normalized;
            Quaternion q         = QuaternionUtility.Euler(0, 90, 0);
            Vector3    _rightDir = (q * _lineDir).normalized;

            Vector3 diff = _rightDir * width - _lineDir * width;

            Vector3 lp1Right = lineP1 + diff;
            Vector3 lp1Left  = lineP1 - diff;

            Vector3 lp2Right = lineP2 + diff;
            Vector3 lp2Left  = lineP2 - diff;

            var res = Geometric.IsPointInArea(new[] { lp1Right, lp2Right, lp2Left, lp1Left }, toCheck);

            return(res);
        }
        public static bool AlmostOnLine(Vector3 lineP1, Vector3 lineP2, float width, Vector3 toCheck)
        {
            Vector3 _lineDir = (lineP2 - lineP1).normalized;

            lineP1 += _lineDir * 99;
            lineP2 -= _lineDir * 99;

            Quaternion q         = QuaternionUtility.Euler(0, 90, 0);
            Vector3    _rightDir = (q * _lineDir).normalized;

            Vector3 lp1Right = lineP1 + _rightDir * 0.5f * width - _lineDir * 0.5f * width;
            Vector3 lp1Left  = lineP1 - _rightDir * 0.5f * width - _lineDir * 0.5f * width;

            Vector3 lp2Right = lineP2 + _rightDir * 0.5f * width + _lineDir * 0.5f * width;
            Vector3 lp2Left  = lineP2 - _rightDir * 0.5f * width + _lineDir * 0.5f * width;

            return(Geometric.IsPointInArea(new[] { lp1Right, lp2Right, lp2Left, lp1Left }, toCheck));
        }
        public static Vector3 GetHoverPointOfLine(Vector3 lp1, Vector3 lp2, Vector3 modelP, float attachR)
        {
            var _area    = Geometric.GetArea(lp1, lp2, modelP);                  //三角形面积
            var _lLength = Vector3.Distance(lp1, lp2);                           //lp1,lp2长度
            var dis      = _lLength < 1e-3 ? attachR + 1 : 2 * _area / _lLength; //modelP到lp1,lp2的距离

            if (dis > attachR)                                                   //太远
            {
                return(default(Vector3));
            }

            Vector3 lDir = lp1 - lp2;                                //直线方向
            Vector3 mDir = QuaternionUtility.Euler(0, 90, 0) * lDir; //xz平面上垂直直线方向
            Vector3 __S  = modelP - mDir * 99;
            Vector3 __E  = modelP + mDir * 99;                       //临时的两个线点

            //if (!Geometric.Meet(__S, __E, lp1, lp2))//不相交
            //{
            //    return default(Vector3);
            //}

            //到这里还能执行的话是相交且接近, 就要计算点
            Vector3 res = Geometric.GetCrossPointOfLine(__E, __S, lp1, lp2);

            if ((Mathf.Abs(res.x - modelP.x) < 0.01f))
            {
                res.x = modelP.x;
            }

            if ((Mathf.Abs(res.z - modelP.z) < 0.01f))
            {
                res.z = modelP.z;
            }

            return(res);
        }