zoukankan      html  css  js  c++  java
  • 点,线,面与矩形是否相交

      最近项目开发一个地图的服务端程序,需要 计算点,线,面与矩形是否有相交,
    起初遇到这个问题脑袋里很混乱不知如何下手,静下心来仔细考虑,其实问题也不复杂.分三个步骤可以解决此问题
    1.判断组成点,线,面的点元素是否在矩形内
      假设矩形的近点:P1 远点:P2,要判断一个新的坐标点Px是否在矩形内,只要判断Px的坐标和P1,P2的大小就可以了代码如下

    点是否在矩形内
            /// <summary>
            /// 点是否与矩形有相交
            /// </summary>
            /// <param name="cPoint">当前点</param>
            /// <param name="p1">矩形近点</param>
            /// <param name="p3">矩形远点</param>
            /// <returns></returns>
            public static bool PointCheck(MapPoint cPoint, MapPoint p1, MapPoint p3)
            {
                bool blResult = (cPoint.X >= p1.X && cPoint.X <= p3.X) && (cPoint.Y >= p1.Y && cPoint.Y <= p3.Y);
                return blResult;
            }

    2.如果是线段还需要在判断线段与矩形的四条边是否有相交
      需要判断做成多段线,多边形 的线段 与组成矩形的四条线段是否相交(几何原理:如果两条线段相交,那么一条线段的两个端点必定在另一条线段的两侧)

    线段与矩形的四条边是否有相交
            /// <summary>
            /// 检查线段与矩形的四条边是否有相交
            /// </summary>
            /// <param name="points"></param>
            /// <param name="p1"></param>
            /// <param name="p2"></param>
            /// <param name="p3"></param>
            /// <param name="p4"></param>
            /// <returns></returns>
            protected bool Check4Line(List<MapPoint> points, MapPoint p1, MapPoint p2, MapPoint p3, MapPoint p4)
            {
                bool blResult = false;
                if (points == null | (points != null && points.Count < 2))
                {
                    return false;
                }
                for (int i = 0; i < points.Count - 1; i++)
                {
                    var ptCurr = points[i];
                    var ptNext = points[i + 1];
                    blResult = CommMeth.Intersect(ptCurr, ptNext, p1, p2);//与矩形的第1条线段相比较
                    if (blResult) break;
                    blResult = CommMeth.Intersect(ptCurr, ptNext, p2, p3);//与矩形的第2条线段相比较
                    if (blResult) break;
                    blResult = CommMeth.Intersect(ptCurr, ptNext, p3, p4);//与矩形的第3条线段相比较
                    if (blResult) break;
                    blResult = CommMeth.Intersect(ptCurr, ptNext, p4, p1);//与矩形的第3条线段相比较
                    if (blResult) break;
                }
                return blResult;
            }
    两条线段是否相交
            /// <summary>
            /// 两条线段是否相交
            /// </summary>
            /// <param name="p1">第1条线段起点</param>
            /// <param name="p2">第1条线段终点</param>
            /// <param name="p3">第2条线段起点</param>
            /// <param name="p4">第2条线段终点点</param>
            /// <returns></returns>
            public static bool Intersect(MapPoint p1, MapPoint p2, MapPoint p3, MapPoint p4)
            {
                double x1 = p1.X;
                double y1 = p1.Y;
                double x2 = p2.X;
                double y2 = p2.Y;
                double x3 = p3.X;
                double y3 = p3.Y;
                double x4 = p4.X;
                double y4 = p4.Y;
                //依据:两条线段不相交,必定是存在其中一条线段的两端点在在另一条线段所在直线的同側.所以要分别考虑两种情况.
                if (DirectionV3(x1, y1, x2, y2, x3, y3) * DirectionV3(x1, y1, x2, y2, x4, y4) > 0)//一条线段的两点全在另一条线段的同一側
                    return false;
                if (DirectionV3(x3, y3, x4, y4, x1, y1) * DirectionV3(x3, y3, x4, y4, x2, y2) > 0)//
                    return false;
                return true;
            }
            private static double DirectionV3(double x1, double y1, double x2, double y2, double x3, double y3)
            {
                //判断点在直线的上或下及左或右側.具体是采用点斜式求出一条线段所在直线的方程,然后将点代如求值进行判断 参照网站:计算几何算法概览
                return x1 * y3 + x2 * y1 + x3 * y2 - x1 * y2 - x2 * y3 - x3 * y1;
            }

    3.最后如果是面(多边形)还需要判断多边形是否全包括了矩形(即矩形的四个点,需要在多边形内)
    在经过1,2两个步骤后,其实只需要判断矩形的其中一个点是否在多边形内即可(不用判断矩形的四个点)

    点是否在多边形内
    public static bool PointInPolygon(MapPoint point, MapPoint[] _vertices)
            {
                var j = _vertices.Length - 1;
                var oddNodes = false;
                for (var i = 0; i < _vertices.Length; i++)
                {
                    if (_vertices[i].Y < point.Y && _vertices[j].Y >= point.Y ||
                        _vertices[j].Y < point.Y && _vertices[i].Y >= point.Y)
                    {
                        if (_vertices[i].X +
                            (point.Y - _vertices[i].Y) / (_vertices[j].Y - _vertices[i].Y) * (_vertices[j].X - _vertices[i].X) < point.X)
                        {
                            oddNodes = !oddNodes;
                        }
                    }
                    j = i;
                }
                return oddNodes;
            }
  • 相关阅读:
    Oracle(00):PL/SQL嵌入SQL语句
    Oracle(00):CASE WHEN 用法
    Oracle(00):正则表达式
    Oracle(00):删除重复记录
    Oracle(00):PL/SQL块与表达式
    Oracle(00):PL/SQL复合类型
    Oracle(00):PL/SQL数据类型
    Oracle(00):rownum行号
    Oracle(00):递归查询connect by
    Oracle(00):Update语句
  • 原文地址:https://www.cnblogs.com/chengruhui/p/2833072.html
Copyright © 2011-2022 走看看