欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

2几何学的方法

程序员文章站 2022-04-01 16:39:01
...
public static class Geometry
{
    #region 点是否在多边形内(含边界)
    /// <summary>
    /// 判断点是否在多边形内部(含边界)
    /// </summary>
    /// <remarks>
    /// 将测试点的Y坐标与多边形的每一个点进行比较,得到测试点所在的行与多边形边的交点的列表,如果测试点的两边点的个数都是奇数个则该测试点在多边形内,否则在多边形外
    /// </remarks>
    public static bool IsPointInsidePolygon(IEnumerable<Vector2> polygon, Vector2 point, float torlance = 0.001f)
    {
        // 多边形顶点数目必须大于2
        if (polygon.Count() < 3)
        {
            Debug.LogError(string.Format("Polygon must have at least 3 vertex, current polygon has {0} vertex!", polygon.Count()));
            return false;
        }

        bool isInside = false;

        List<float> polyX = polygon.Select(x => x.x).ToList();
        List<float> polyY = polygon.Select(x => x.y).ToList();
        for (int i = 0, j = polygon.Count() - 1; i < polygon.Count(); i++)
        {
            if ((polyY[i] < point.y && polyY[j] >= point.y || polyY[j] < point.y && polyY[i] >= point.y) &&
                (polyX[i] <= point.x || polyX[j] <= point.x))
            {
                isInside ^= (polyX[i] + (point.y - polyY[i]) / (polyY[j] - polyY[i]) * (polyX[j] - polyX[i]) < point.x);
            }

            j = i;
        }

        // 做边界判断
        if (!isInside)
        {
            //Debug.Log("做边界判断!");
            //float torlance = 0.001f;
            foreach (Vector2 vert in polygon)
            {
                if (Vector2.Distance(vert, point) < torlance)
                {
                    //Debug.Log("有相近点!");
                    isInside = true;
                    break;
                }
            }

            if (!isInside)
            {
                for (int i = 0; i < polyX.Count; i++)
                {
                    Vector2 start = new Vector2(polyX[i], polyY[i]);
                    Vector2 end = new Vector2(polyX[(i + 1) % polyX.Count], polyY[(i + 1) % polyY.Count]);
                    //Debug.Log(string.Format("Start:{0} End:{1} Point:{2} Dis:{3}", start, end, point, DisPoint2Line(point, start, end)));
                    if (DisPoint2Line(point, start, end) < torlance)
                    {
                        Vector2 s2p = (point - start).normalized;
                        Vector2 e2p = (point - end).normalized;
                        //Debug.Log("是否在边上 " + Mathf.Abs(Vector2.Dot(s2p, e2p) - (-1)));

                        if (Mathf.Abs(Vector2.Dot(s2p, e2p) - (-1)) < torlance)
                        {
                            //Debug.Log("有相近边!");
                            isInside = true;
                            break;
                        }
                    }
                }
            }
        }

        return isInside;
    }
    #endregion

    #region 点是否在线段上(含两端点)
    /// <summary>
    /// 判断点是否在线段上(含边界)
    /// </summary>
    /// <remarks>
    /// 点到线段两端的距离之和为线段的长度则在线段上,否则在线段外
    /// </remarks>
    public static bool IsPointInsideSegment(IEnumerable<Vector2> segment, Vector2 point)
    {
        // 线段顶点数目必须等于2
        if (segment.Count() != 2)
        {
            Debug.LogError(string.Format("Segment must have only 2 vertex, current segment have {0} vertex!", segment.Count()));
            return false;
        }

        if (Mathf.Approximately((point - segment.First()).magnitude + (point - segment.Last()).magnitude, (segment.First() - segment.Last()).magnitude))
            return true;
        else
            return false;
    }
    /// <summary>
    /// 检测某个点是否在线段上
    /// </summary>
    /// <param name="lineStart"></param>
    /// <param name="lineEnd"></param>
    /// <param name="point"></param>
    /// <returns></returns>
    public static bool CheckPointInSegement(Vector2 lineStart, Vector2 lineEnd, Vector2 point)
    {
        // 误差范围

        if (DisPoint2Line(point, lineStart, lineEnd) >= 0.002f)
        {
            return false;
        }

        Vector2 p2Start = (lineStart - point).normalized;
        Vector2 p2End = (lineEnd - point).normalized;

        if (Vector2.Dot(p2End, p2Start) <= 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    #endregion

    #region 坐标系偏移
    /// <summary>
    /// 将Unity世界坐标系按照逆时针方向偏移指定degrees后,origin相对于偏移坐标系的位置
    /// </summary>
    public static Vector2 CoordinateOffsetByDegrees(Vector2 origin, float degrees)
    {
        return CoordinateOffsetByRadians(origin, degrees * Mathf.Deg2Rad);
    }

    /// <summary>
    /// 将Unity世界坐标系内,指定点围绕坐标系原点,按照逆时针方向偏移指定radians后,origin相对于偏移坐标系的位置
    /// </summary>
    public static Vector2 CoordinateOffsetByRadians(Vector2 origin, float radians)
    {
        float x = origin.x * Mathf.Cos(radians) + origin.y * Mathf.Sin(radians);
        float y = origin.y * Mathf.Cos(radians) - origin.x * Mathf.Sin(radians);
        return new Vector2(x, y);
    }

    /// <summary>
    /// 计算在Unity世界坐标系内,指定点围绕锚点,按照逆时针方向旋转一定角度后,得到的新的世界坐标
    /// </summary>
    /// <param name="point">需要操作的点</param>
    /// <param name="anchor">锚点,指定点围绕该点进行旋转操作</param>
    /// <param name="degrees">角度,以逆时针方向为正值</param>
    public static Vector2 RotateArroundAnchorByDegrees(Vector2 point, Vector2 anchor, float degrees)
    {
        return RotateArroundAnchorByRadians(point, anchor, degrees * Mathf.Deg2Rad);
    }

    /// <summary>
    /// 计算在Unity世界坐标系内,指定点围绕锚点,按照逆时针方向旋转一定弧度后,得到的新的世界坐标
    /// </summary>
    /// <param name="point">需要操作的点</param>
    /// <param name="anchor">锚点,指定点围绕该点进行旋转操作</param>
    /// <param name="radians">弧度,以逆时针方向为正值</param>
    public static Vector2 RotateArroundAnchorByRadians(Vector2 point, Vector2 anchor, float radians)
    {
        float x = (point.x - anchor.x) * Mathf.Cos(radians) - (point.y - anchor.y) * Mathf.Sin(radians) + anchor.x;
        float y = (point.x - anchor.x) * Mathf.Sin(radians) + (point.y - anchor.y) * Mathf.Cos(radians) + anchor.y;
        return new Vector2(x, y);
    }

    #endregion

    #region 判断多边形各顶点是否按照顺时针排序
    /// <summary>
    /// 判断多边形顶点是否按照顺时针排序
    /// </summary>
    /// <remarks>
    /// 在凸点A处,若CA、AB的叉积的y值小于0时,为逆时针方向,大于0时为顺时针方向,不考虑为0的情况;
    /// 由于Unity使用左手坐标系,与数学定义上的叉乘使用的右手坐标系正好相反,因此需要特别注意
    /// </remarks>
    public static bool IsPolygonClockWise(IEnumerable<Vector2> polygon)
    {
        // 多边形顶点数目必须大于2
        if (polygon.Count() < 3)
        {
            Debug.LogError(string.Format("Polygon must have at least 3 vertex, current polygon has {0} vertex!", polygon.Count()));
            return false;
        }

        List<Vector2> sortedPolygon = polygon.ToList();
        // 选择凸点进行判断(此处选择左下角顶点)
        int leftBottomIndex = FindLeftBottomPointIndex(sortedPolygon);
        Vector3 ptC = sortedPolygon[(leftBottomIndex - 1 + sortedPolygon.Count) % sortedPolygon.Count].ToVector3XZ();
        Vector3 ptA = sortedPolygon[leftBottomIndex].ToVector3XZ();
        Vector3 ptB = sortedPolygon[(leftBottomIndex + 1) % sortedPolygon.Count].ToVector3XZ();
        if (Vector3.Cross((ptA - ptC), (ptB - ptA)).y < 0)
            return false;
        else
            return true;
    }

    #endregion

    #region 以顺/逆实在排列多边形的顶点
    /// <summary>
    /// 以顺/逆时针顺序排列多边形的顶点集合
    /// </summary>
    /// <remarks>
    /// 在凸点A处,若CA、AB的叉积的y值小于0时,为逆时针方向,大于0时为顺时针方向,不考虑为0的情况;
    /// 由于Unity使用左手坐标系,与数学定义上的叉乘使用的右手坐标系正好相反,因此需要特别注意
    /// </remarks>
    public static IEnumerable<Vector2> SortPolygonInClockWise(IEnumerable<Vector2> polygon, bool isClockWise = true)
    {
        // 多边形顶点数目必须大于2
        if (polygon.Count() < 3)
        {
            Debug.LogError(string.Format("Polygon must have at least 3 vertex, current polygon has {0} vertex!", polygon.Count()));
            return polygon;
        }

        List<Vector2> sortedPolygon = polygon.ToList();
        // 选择凸点进行判断(此处选择左下角顶点)
        int leftBottomIndex = FindLeftBottomPointIndex(sortedPolygon);
        Vector3 ptC = sortedPolygon[(leftBottomIndex - 1 + sortedPolygon.Count) % sortedPolygon.Count].ToVector3XZ();
        Vector3 ptA = sortedPolygon[leftBottomIndex].ToVector3XZ();
        Vector3 ptB = sortedPolygon[(leftBottomIndex + 1) % sortedPolygon.Count].ToVector3XZ();
        Vector3 crossProduct = Vector3.Cross((ptA - ptC), (ptB - ptA));
        // 实际为逆而要求顺,或实际为顺而要求逆时,翻转列表
        if ((crossProduct.y < 0 && isClockWise) || (crossProduct.y > 0 && !isClockWise))
            sortedPolygon.Reverse();

        return sortedPolygon;
    }
    #endregion

    #region 寻找点集中的特定点
    /// <summary>
    /// 寻找点集中的左下角顶点
    /// </summary>
    /// <remarks>
    /// 左下角的定义:y值最小的情况下取x值最小的点
    /// </remarks>
    public static Vector2 FindLeftBottomPoint(IEnumerable<Vector2> vertices)
    {
        float minY = vertices.Min(x => x.y);
        return vertices.Where(x => x.y == minY).OrderBy(x => x.x).First();
    }

    /// <summary>
    /// 寻找点集中的左下角顶点的Index
    /// </summary>
    /// <remarks>
    /// 左下角的定义:y值最小的情况下取x值最小的点
    /// </remarks>
    public static int FindLeftBottomPointIndex(List<Vector2> vertices)
    {
        float minY = vertices.Min(x => x.y);
        return vertices.IndexOf(vertices.Where(x => x.y == minY).OrderBy(x => x.x).First());
    }

    #endregion

    #region 获取两直线交点
    /// <summary>
    /// 得到两直线交点的方法
    /// </summary>
    /// <param name="lineFirstStart"> 第一条线的一个点 </param>
    /// <param name="lineFirstEnd"> 第一条线的另外一个点 </param>
    /// <param name="lineSecondStart"> 第二条线的一个点 </param>
    /// <param name="lineSecondEnd"> 第二条线的另外一个点 </param>
    /// <returns></returns>
    public static Vector3 GetIntersectionByPoints(Vector3 lineFirstStart, Vector3 lineFirstEnd, Vector3 lineSecondStart,
        Vector3 lineSecondEnd)
    {
        float y = lineFirstStart.y;
        double a = 0, b = 0;
        int state = 0;
        if (lineFirstStart.x != lineFirstEnd.x)
        {
            a = (lineFirstEnd.z - lineFirstStart.z) / (lineFirstEnd.x - lineFirstStart.x);
            state |= 1;
        }
        if (lineSecondStart.x != lineSecondEnd.x)
        {
            b = (lineSecondEnd.z - lineSecondStart.z) / (lineSecondEnd.x - lineSecondStart.x);
            state |= 2;
        }
        switch (state)
        {
            case 0:
                {
                    if (lineFirstStart.x == lineSecondStart.x)
                    {
                        return Vector3.zero;
                    }
                    else
                    {
                        return Vector3.zero;
                    }
                }
            case 1:
                {
                    double x = lineSecondStart.x;
                    double z = (lineFirstStart.x - x) * (-a) + lineFirstStart.z;
                    return new Vector3((float)x, y, (float)z);
                }
            case 2:
                {
                    double x = lineFirstStart.x;
                    double z = (lineSecondStart.x - x) * (-b) + lineSecondStart.z;
                    return new Vector3((float)x, y, (float)z);
                }
            case 3:
                {
                    if (Mathf.Abs((float)(a - b)) < 0.0001)
                    {
                        return Vector3.zero;
                    }
                    double x = (a * lineFirstStart.x - b * lineSecondStart.x - lineFirstStart.z + lineSecondStart.z) / (a - b);
                    double z = a * x - a * lineFirstStart.x + lineFirstStart.z;
                    return new Vector3((float)x, y, (float)z);
                }
        }
        return Vector3.zero;
    }

    #endregion

    #region 获取线段与直线的交点
    public static Vector3? GetIntersectonBetweenLineAndSegment(Vector3 linePointA, Vector3 linePointB, Vector3 segmentPointA, Vector3 segmentPointB)
    {
        // 先求两直线交点 再判断交点是否在线段上
        Vector3? intersection = GetIntersectionByPoints(linePointA, linePointB, segmentPointA, segmentPointB);
        if (intersection != Vector3.zero)
        {
            //if (CheckPointInSegement(segmentPointA, segmentPointB, intersection.Value))
            //{
            //    Debug.Log(string.Format("segmentStart: {0} segmentEnd: {1} intersection:{2}", segmentPointA.ToString("f4"), segmentPointB.ToString("f4"), intersection.Value.ToString("f4")));
            //    return intersection;
            //}

            if (IsPointInsideSegment(new List<Vector2>() { segmentPointA.ToVector2XZ(), segmentPointB.ToVector2XZ() }, intersection.Value.ToVector2XZ()))
            {
                //Debug.Log(string.Format("segmentStart: {0} segmentEnd: {1} intersection:{2}", segmentPointA.ToString("f4"), segmentPointB.ToString("f4"), intersection.Value.ToString("f4")));
                return intersection;
            }
        }
        return null;
    }
    #endregion

    #region 点到直线的距离
    /// <summary>
    /// 某个点到线段上的距离
    /// </summary>
    /// <param name="point"></param>
    /// <param name="linePointA"></param>
    /// <param name="linePointB"></param>
    /// <returns></returns>
    public static double DisPoint2Line(Vector2 point, Vector2 linePointA, Vector2 linePointB)
    {
        double dis = 0;
        if (linePointA.x == linePointB.x)
        {
            dis = Math.Abs(point.x - linePointA.x);
            return dis;
        }
        double lineK = (linePointB.y - linePointA.y) / (linePointB.x - linePointA.x);
        double lineC = (linePointB.x * linePointA.y - linePointA.x * linePointB.y) / (linePointB.x - linePointA.x);
        dis = Math.Abs(lineK * point.x - point.y + lineC) / (Math.Sqrt(lineK * lineK + 1));
        return dis;

    }

    #endregion

    #region 获取点在直线上的垂直投影点
    /// <summary>
    /// 获得某点在一个直线上的投影
    /// </summary>
    /// <param name="point"></param>
    /// <param name="linePoint1"></param>
    /// <param name="linePoint2"></param>
    /// <returns></returns>
    public static Vector3 GetProjectivePoint(Vector3 point, Vector3 linePoint1, Vector3 linePoint2)
    {
        Vector3 target;

        Vector3 lineDir = (linePoint2 - linePoint1).normalized;

        Vector3 projectiveDir = Quaternion.Euler(0, 90, 0) * lineDir;

        Vector3 point2 = point + projectiveDir;

        target = GetIntersectionByPoints(point, point2, linePoint1, linePoint2);

        return target;
    }
    #endregion

    #region 判断两多边形是否相交
    // 函数存在缺陷,最后一个点到第一个点的线段会被忽略
    public static bool IsPolygonIntersectOtherPolygon(IEnumerable<Vector2> polgon, IEnumerable<Vector2> otherPolgon)
    {
        Vector2 segmentStart = Vector2.zero;
        Vector2 segmentEnd = Vector2.zero;
        int count = 0;
        // 让两个多边形的边依次进行判断
        foreach (Vector2 point in polgon)
        {
            if (count == 0)
            {
                segmentStart = point;
                count++;
                continue;
            }
            else
            {
                segmentEnd = point;

                Vector2 otherStart = Vector2.zero;
                Vector2 otherEnd = Vector2.zero;
                int otherCount = 0;
                foreach (Vector2 otherPoint in otherPolgon)
                {
                    if (otherCount == 0)
                    {
                        otherStart = otherPoint;
                        otherCount++;
                        continue;
                    }
                    else
                    {
                        otherEnd = otherPoint;

                        bool isCrose = CheckTwoSegmentCrose(segmentStart, segmentEnd, otherStart, otherEnd);

                        if (isCrose)
                            return true;

                        otherStart = otherPoint;
                    }
                }

                segmentStart = point;
            }
        }
        return false;
    }

    #endregion

    #region 判断两线段是否相交
    //firstlineStart, firstlineEnd为一条线段两端点 SecondlineStart, SecondlineEnd为另一条线段的两端点 相交返回true, 不相交返回false  
    public static bool CheckTwoSegmentCrose(Vector2 firstlineStart, Vector2 firstlineEnd, Vector2 SecondlineStart, Vector2 SecondlineEnd)
    {
        if (max(firstlineStart.x, firstlineEnd.x) < min(SecondlineStart.x, SecondlineEnd.x))
        {
            return false;
        }
        if (max(firstlineStart.y, firstlineEnd.y) < min(SecondlineStart.y, SecondlineEnd.y))
        {
            return false;
        }
        if (max(SecondlineStart.x, SecondlineEnd.x) < min(firstlineStart.x, firstlineEnd.x))
        {
            return false;
        }
        if (max(SecondlineStart.y, SecondlineEnd.y) < min(firstlineStart.y, firstlineEnd.y))
        {
            return false;
        }
        if (mult(SecondlineStart, firstlineEnd, firstlineStart) * mult(firstlineEnd, SecondlineEnd, firstlineStart) < 0)
        {
            return false;
        }
        if (mult(firstlineStart, SecondlineEnd, SecondlineStart) * mult(SecondlineEnd, firstlineEnd, SecondlineStart) < 0)
        {
            return false;
        }
        return true;
    }
    #endregion

    #region 判断两个线段是否端点相连
    // 判断两条线段是否相连
    public static bool CheckTwoSegmentSharePoint(Vector2 firstlineStart, Vector2 firstlineEnd, Vector2 SecondlineStart, Vector2 SecondlineEnd)
    {
        return firstlineStart == SecondlineStart || firstlineStart == SecondlineEnd || firstlineEnd == SecondlineStart || firstlineEnd == SecondlineEnd;
    }
    #endregion

    #region 计算多边形面积
    /// <summary>
    /// 多边形面积计算(不论凸凹)
    /// </summary>
    /// <param name="count">坐标点数</param>
    /// <param name="X">坐标的横坐标集合</param>
    /// <param name="Y">坐标的纵坐标集合</param>
    /// <returns></returns>
    public static double AoArea(int count, double[] X, double[] Y)
    {
        double area;
        if (count < 3)
            return 0;
        area = Y[0] * (X[count - 1] - X[1]);
        for (int i = 1; i < count; i++)
            area += Y[i] * (X[(i - 1)] - X[(i + 1) % count]);
        return area / 2;
    }
    public static double GetAreaOfPolygon(Vector3[] polygon)
    {
        double[] xDoubles = new double[polygon.Length];
        double[] yDoubles = new double[polygon.Length];

        int i = 0;
        foreach (Vector3 vector3 in polygon)
        {
            xDoubles[i] = vector3.x;
            yDoubles[i] = vector3.z;
            i++;
        }

        return Geometry.AoArea(xDoubles.Length, xDoubles, yDoubles);
    }
    #endregion

    #region 2D平面上某点绕某点旋转一定角度后的位置
    /// <summary>
    /// 一个点绕另外一个点逆时针旋转一定角度得到的点
    /// </summary>
    /// <param name="startPos"></param>
    /// <param name="origin"></param>
    /// <param name="angle"></param>
    /// <returns></returns>
    public static Vector2 RotateAround(Vector2 startPos, Vector2 origin, float angle)
    {
        float rad = Mathf.Deg2Rad * angle;
        double x = (startPos.x - origin.x) * Math.Cos(rad) - (startPos.y - origin.y) * Math.Sin(rad) + origin.x;
        //Debug.Log(string.Format("angle : {0} cos: {1} sin: {2} startPos: {3} origin: {4}", angle, Math.Cos(rad), Math.Sin(rad), startPos.ToString("f4"), origin.ToString("f4")));
        double y = (startPos.x - origin.x) * Math.Sin(rad) + (startPos.y - origin.y) * Math.Cos(rad) + origin.y;
        return new Vector2((float)x, (float)y);
    }
    #endregion

    #region 删掉多边形*线的顶点
    /// <summary>
    /// 删掉共线的点
    /// </summary>
    /// <param name="Polygon"></param>
    /// <returns></returns>
    public static List<Vector3> RemoveInLinePoint(List<Vector3> polygon)
    {
        List<Vector3> resultPolygon = new List<Vector3>(polygon);

        // 一个点一个点地检验过去 如果在这个点前一个点和这个点后一个点连成的直线上,就删除该点
        bool check = true;
        do
        {
            check = true;
            for (int i = 0; i < resultPolygon.Count; i++)
            {
                int frontIndex = i <= 0 ? resultPolygon.Count - 1 : i - 1;
                int nextIndex = (i + 1) % resultPolygon.Count;

                Vector3 frontToCur = resultPolygon[i] - resultPolygon[frontIndex];
                Vector3 nextToCur = resultPolygon[i] - resultPolygon[nextIndex];

                bool inLine = (frontToCur.normalized + nextToCur.normalized == Vector3.zero);

                if (inLine)
                {
                    resultPolygon.RemoveAt(i);
                    check = false;
                    break;
                }
            }
        } while (!check);

        return resultPolygon;
    }
    #endregion

    #region 判断两线段是否共线
    /// <summary>
    /// 判断两个线段是否共线
    /// </summary>
    /// <param name="firstWall"></param>
    /// <param name="secondWall"></param>
    /// <returns></returns>
    public static bool CheckTwoSegmentShareLine(Vector2 lineAStart, Vector2 lineAEnd, Vector2 lineBStart, Vector2 lineBEnd)
    {
        Vector2 firstWallDir = (lineAEnd - lineAStart).normalized;
        Vector2 secondWallDir = (lineBEnd - lineBStart).normalized;
        //Debug.Log(string.Format("aStart:{2] end:{3} bStart:{4} end:{5} firstWallDir:{0} secondWallDir:{1}",
        //    firstWallDir.ToString("f4"), secondWallDir.ToString("f4"), lineAStart.ToString("f4"), lineAEnd.ToString("f4"), lineBStart.ToString("f4"), lineBEnd.ToString("f4")));
        //if (DisPoint2Line(lineAStart, lineBStart, lineBEnd)>0.001f|| DisPoint2Line(lineAEnd, lineBStart, lineBEnd)>0.001f)
        //    return false;
        //// 没有加检测
        //return Vector3.Distance(firstWallDir, secondWallDir) < 0.001f || Vector3.Distance(firstWallDir, -secondWallDir) < 0.001f;

        return (CheckThreePointShareLine(lineAStart, lineAEnd, lineBStart)) && (CheckThreePointShareLine(lineAStart, lineAEnd, lineBEnd));
    }
    #endregion

    #region 判断三点是否共线
    /// <summary>
    /// 判断三点是否共线
    /// </summary>
    /// <param name="lineA"></param>
    /// <param name="lineB"></param>
    /// <param name="lineC"></param>
    /// <returns></returns>
    public static bool CheckThreePointShareLine(Vector2 lineA, Vector2 lineB, Vector2 lineC)
    {
        if (lineA != lineB && lineB != lineC && lineC != lineA)//这里修改了一下
        {
            Vector2 a2b = (lineB - lineA).normalized;
            Vector2 c2b = (lineB - lineC).normalized;

            //Debug.Log(a2b.ToString("f6") + "  " + c2b.ToString("f6"));

            return (a2b == c2b) || (a2b == -c2b);
        }
        else
        {
            return true;
        }
    }
    #endregion

    #region 判断两条线段是否共线且存在重叠
    /// <summary>
    /// 判断两条选段是否有重叠
    /// </summary>
    /// <param name="lineAStart"></param>
    /// <param name="lineAEnd"></param>
    /// <param name="lineBStart"></param>
    /// <param name="lineBEnd"></param>
    /// <returns></returns>
    public static bool CheckTwoSegmentOverlap(Vector2 lineAStart, Vector2 lineAEnd, Vector2 lineBStart, Vector2 lineBEnd)
    {
        if (CheckTwoSegmentShareLine(lineAStart, lineAEnd, lineBStart, lineBEnd))
        {
            //Debug.Log("ShareLine");
            Vector2 s2s = (lineBStart - lineAStart).normalized;
            Vector2 s2e = (lineBEnd - lineAStart).normalized;
            Vector2 e2s = (lineBStart - lineAEnd).normalized;
            Vector2 e2e = (lineBEnd - lineAEnd).normalized;

            if (s2s == s2e && s2e == e2s && e2s == e2e)
            {
                return false;
            }

            return true;
        }
        return false;
    }
    #endregion

    #region 判断两个向量是否平行
    public static bool CheckTwoVectorParallel(Vector3 vectorA, Vector3 vectorB, float tolerance)
    {
        return Mathf.Abs(Mathf.Abs(Vector3.Dot(vectorA, vectorB)) - 1) < tolerance;
    }
    #endregion

    #region 判断两个向量是否垂直
    public static bool CheckTwoVectorPerpendicular(Vector3 vectorA, Vector3 vectorB, float tolerance)
    {
        return Mathf.Abs(Vector3.Dot(vectorA, vectorB)) < tolerance;
    }
    #endregion

    #region 二次贝塞尔曲线
    public static List<Vector3> GetQuadraticBezierCurve(int segmentCount, Vector3 start, Vector3 controlPoint, Vector3 end)
    {
        List<Vector3> curve = new List<Vector3>();
        for (int i = 0; i <= segmentCount; i++)
        {
            float t = i / (float)segmentCount;
            Vector3 pixel = CalculateQuadraticBezierPoint(t, start, controlPoint, end);
            curve.Add(pixel);
        }
        return curve;
    }

    public static List<Vector3> GetQuadraticBezierCurve(int segmentCount, float fromT, float toT, Vector3 start, Vector3 controlPoint, Vector3 end)
    {
        List<Vector3> curve = new List<Vector3>();
        for (int i = 0; i <= segmentCount; i++)
        {
            float t = (i / (float)segmentCount) * (toT - fromT) + fromT;
            Vector3 pixel = CalculateQuadraticBezierPoint(t, start, controlPoint, end);
            curve.Add(pixel);
        }
        return curve;
    }

    public static Vector3 CalculateQuadraticBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
    {
        float u = 1 - t;
        float tt = t * t;
        float uu = u * u;

        Vector3 p = uu * p0;
        p += 2 * u * t * p1;
        p += tt * p2;

        return p;
    }

    // 获得曲线某点处切线方向(方向向量)
    public static Vector3 GetQuadraticBezierDirAtPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
    {
        return (2 * (p0 + -2 * p1 + p2) * t + 2 * p1 - 2 * p0).normalized;
    }

    public static double GetQuadraticBezierT(Vector2 point, Vector2 p0, Vector2 p1, Vector2 p2)
    {
        Vector2 a = p0 - 2 * p1 + p2;
        Vector2 b = 2 * (p1 - p0);
        Vector2 c = p0 - point;

        double t = (-b.x + Math.Pow(b.x * b.x - 4 * a.x * c.x, 0.5f)) / (2 * a.x);
        //Debug.Log("t:" + t);
        return t;
    }
    #endregion

    #region 一些计算
    static double mult(Vector2 a, Vector2 b, Vector2 c)
    {
        return (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y);
    }

    static float max(float a, float b)
    {
        return a > b ? a : b;
    }

    static float min(float a, float b)
    {
        return a < b ? a : b;
    }

    /// <summary>  
    /// 计算两个向量的叉乘。  
    /// </summary>  
    /// <param name="pt1"></param>  
    /// <param name="pt2"></param>  
    /// <returns></returns>  
    static float CrossMul(Vector2 pt1, Vector2 pt2)
    {
        return pt1.x * pt2.y - pt1.y * pt2.x;
    }
    #endregion
}