Language agnostic 确定经纬度矩形和球体上的圆是否重叠

Language agnostic 确定经纬度矩形和球体上的圆是否重叠,language-agnostic,math,geometry,gis,trigonometry,Language Agnostic,Math,Geometry,Gis,Trigonometry,假设我有以下几点: 由最小和最大纬度和经度定义的区域(通常为“lat-long-rect”,但除了某些投影外,它实际上不是矩形) 一个圆,由一个中心纬度/长度和一个半径定义 我如何确定: 两个形状是否重叠 圆是否完全包含在矩形中 我在寻找一个完整的公式/算法,而不是数学课程本身。警告:如果圆/矩形跨越球体的大部分,这可能会很棘手,例如: “矩形”:最小长度=-90度,最大长度=+90度,最小横向=+70度,最大横向=+80度 圆:圆心=纬度=+85度,长=+160度,半径=20度(例如,如果

假设我有以下几点:

  • 由最小和最大纬度和经度定义的区域(通常为“lat-long-rect”,但除了某些投影外,它实际上不是矩形)
  • 一个圆,由一个中心纬度/长度和一个半径定义
我如何确定:

  • 两个形状是否重叠
  • 圆是否完全包含在矩形中

  • 我在寻找一个完整的公式/算法,而不是数学课程本身。

    警告:如果圆/矩形跨越球体的大部分,这可能会很棘手,例如:

    “矩形”:最小长度=-90度,最大长度=+90度,最小横向=+70度,最大横向=+80度

    圆:圆心=纬度=+85度,长=+160度,半径=20度(例如,如果点A在圆上,点C是圆的圆心,点O是球体的圆心,则角度AOC=40度)

    这些交叉点,但数学可能有几种情况来检查交叉点/包容。以下点位于上述圆上:P1=(+65度纬度,+160度长),P2=(+75度纬度,-20度长)。P1在“矩形”外,P2在“矩形”内,因此圆/矩形至少相交2点

    好的,下面是我对解决方案的概述:


    设C=半径为R的圆心(如上所述,用球面角表示)。C有纬度LATC和经度LONGC。因为“矩形”这个词在这里有点误导(恒定纬度的线不是大圆的线段),所以我将使用术语“边界框”

    • 函数
      内圆(p)
      返回+1,0或-1:
      如果点p在圆内,返回+1;如果点p在圆上,返回0;如果点p在圆外,返回-1:计算大圆距离D(表示为球面角)在C和任何点P之间,都会告诉你P是否在圆圈内:
      InsideCircle(P)=符号(R-D)
      (正如user@Die in Sente提到的,在这个论坛的其他地方已经询问了很大的圆圈距离)

    • 定义
      PANG(x)
      =x=MOD(x+180度,360度)-180度的主角度<代码>倾斜(x)始终在-180度和+180度之间,包括(+180度应映射到-180度)

    • 要定义边界框,您需要知道4个数字,但经度有一个小问题。LAT1和LAT2表示边界纬度(假设LAT1
      • LAT1这个怎么样

        查找将矩形中心点
        Cr
        连接到圆中心的向量
        v
        。查找与矩形相交的点
        i
        。如果
        |i-Cr |+r>| v | |
        则它们相交

        换句话说,矩形内线段的长度加上圆内线段的长度应大于总长度(v
        v
        ,中心连接线段)

        查找点
        i
        应该是个棘手的部分,特别是当它落在经度边缘时,但是你应该能够比我更快地找到一些东西

        编辑:此方法无法判断圆是否完全在矩形内。您需要找到从其中心到矩形所有四条边的距离


        编辑:上述内容不正确。正如Federico Ramponi所建议的,在某些情况下,它甚至在欧几里德几何中也不起作用。我将发布另一个答案。请不要接受这一点,请随意投反对票。我很快就会删除它。

        再试试这个

        我认为解决方案是测试一组点,正如Jason S所建议的,但我不同意他选择的点,我认为这在数学上是错误的

        您需要在lat/long框的侧面找到点,其中到圆中心的距离为局部最小值或最大值。将这些点添加到角点集,则上述算法应该是正确的

        也就是说,让经度为x维,纬度为y维
        框的侧面是o的参数曲线P(t)=P0+t(P1-P0)。对于欧几里德几何答案,请参见:

        这适用于地球上的任何点。如果要将其更改为不同大小的球体,只需将kEarchRadiusKms更改为球体所需的任意半径

        此方法用于计算到lat和lon点之间的距离

        我从这里得到了这个距离公式:

        如果矩形的任何顶点之间的距离小于圆半径的距离,则圆和矩形重叠。如果圆心与所有顶点之间的距离大于圆的半径,且所有这些距离都小于矩形的宽度和高度,则圆应位于矩形的内部

        如果你能发现我的代码有问题的话,请随意修改我的代码
        public static double Calc(double Lat1, double Long1, double Lat2, double Long2)
        {
            double dDistance = Double.MinValue;
            double dLat1InRad = Lat1 * (Math.PI / 180.0);
            double dLong1InRad = Long1 * (Math.PI / 180.0);
            double dLat2InRad = Lat2 * (Math.PI / 180.0);
            double dLong2InRad = Long2 * (Math.PI / 180.0);
        
            double dLongitude = dLong2InRad - dLong1InRad;
            double dLatitude = dLat2InRad - dLat1InRad;
        
            // Intermediate result a.
            double a = Math.Pow(Math.Sin(dLatitude / 2.0), 2.0) +
                       Math.Cos(dLat1InRad) * Math.Cos(dLat2InRad) *
                       Math.Pow(Math.Sin(dLongitude / 2.0), 2.0);
        
            // Intermediate result c (great circle distance in Radians).
            double c = 2.0 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1.0 - a));
        
            // Distance.
            // const Double kEarthRadiusMiles = 3956.0;
            const Double kEarthRadiusKms = 6376.5;
            dDistance = kEarthRadiusKms * c;
        
            return dDistance;
        }
        
        public string Test(double cLat,
            double cLon,
            double cRadius,
            double rlat1,
            double rlon1,
            double rlat2,
            double rlon2,
            double rlat3,
            double rlon3,
            double rlat4,
            double rlon4)
        {
            double d1 = Calc(cLat, cLon, rlat1, rlon1);
            double d2 = Calc(cLat, cLon, rlat2, rlon2);
            double d3 = Calc(cLat, cLon, rlat3, rlon3);
            double d4 = Calc(cLat, cLon, rlat4, rlon4);
        
            if (d1 <= cRadius ||
                d2 <= cRadius ||
                d3 <= cRadius ||
                d4 <= cRadius)
            {
        
                return "Circle and Rectangle intersect...";
            }
        
            double width = Calc(rlat1, rlon1, rlat2, rlon2);
            double height = Calc(rlat1, rlon1, rlat4, rlon4);
        
            if (d1 >= cRadius &&
                d2 >= cRadius &&
                d3 >= cRadius &&
                d4 >= cRadius &&
                width >= d1 &&
                width >= d2 &&
                width >= d3 &&
                width >= d4 &&
                height >= d1 &&
                height >= d2 &&
                height >= d3 &&
                height >= d4)
            {
                return "Circle is Inside of Rectangle!";
            }
        
        
        
            return "NO!";
        }