Math 计算地球上任意多边形包围的面积';s面

Math 计算地球上任意多边形包围的面积';s面,math,geometry,gis,geography,Math,Geometry,Gis,Geography,假设我有一组任意的纬度和经度对,代表一些简单的闭合曲线上的点。在笛卡尔空间中,我可以很容易地用格林定理计算出这样一条曲线所包围的面积。计算球体表面面积的类似方法是什么?我想我所追求的是(甚至是某种近似的)背后的算法。我对Matlab的函数一无所知,但我们开始吧。考虑把你的球面多边形分割成球面三角形,比如画一个顶点的对角线。球面三角形的表面积如下所示: R^2 * ( A + B + C - \pi) 其中,R是球体的半径,A、B和C是三角形的内角(弧度)。括号中的数量称为“球形过剩” 您的n边

假设我有一组任意的纬度和经度对,代表一些简单的闭合曲线上的点。在笛卡尔空间中,我可以很容易地用格林定理计算出这样一条曲线所包围的面积。计算球体表面面积的类似方法是什么?我想我所追求的是(甚至是某种近似的)背后的算法。

我对Matlab的函数一无所知,但我们开始吧。考虑把你的球面多边形分割成球面三角形,比如画一个顶点的对角线。球面三角形的表面积如下所示:

R^2 * ( A + B + C - \pi)
其中,
R
是球体的半径,
A
B
C
是三角形的内角(弧度)。括号中的数量称为“球形过剩”

您的
n
边多边形将被拆分为
n-2
三角形。对所有三角形求和,提取
R^2
的公因数,并将所有
\pi
组合在一起,多边形的面积为

R^2 * ( S - (n-2)\pi )
其中
S
是多边形的角度和。括号中的数量也是多边形的球形多余部分

[编辑]无论多边形是否为凸面,这都是正确的。重要的是它可以被分解成三角形

你可以通过向量数学来确定角度。假设您有三个顶点
A
B
C
,并且对
B
处的角度感兴趣。因此,我们必须从点
B
沿大圆段(多边形边)找到两个与球体相切的向量(它们的大小无关)。让我们为
BA
计算一下。大圆位于由
OA
OB
定义的平面上,其中
O
是球体的中心,因此它应该垂直于法向量
OA x OB
。它也应该垂直于OB,因为它在那里相切。因此,这样的向量由
obx(oax OB)
给出。您可以使用右侧规则来验证这是否在适当的方向上。还请注意,这简化为
OA*(OB.OB)-OB*(OB.OA)=OA*| OB |-OB*(OB.OA)

然后,您可以使用好的ol'点积来查找边之间的角度:
BA.BC'=|BA'*|BC'|*cos(B)
,其中
BA'
BC'
是从
B
沿边到
A
C
的切向量


[编辑以明确这些是切线向量,而不是点之间的文字]

有几种方法可以做到这一点

1) 整合纬度带的贡献。此处,每条带的面积为(Rcos(A)(B1-B0))(RdA),其中A为纬度,B1和B0为起始经度和结束经度,所有角度均以弧度为单位

2) 将曲面拆分为,并使用计算面积,然后将其相加

3) 正如James Schek在这里提出的,在GIS工作中,他们使用平面空间上保留面积的投影,并计算其中的面积

从对数据的描述来看,听起来第一种方法可能是最简单的。(当然,可能还有其他更简单的方法我不知道。)

编辑–比较这两种方法:

第一次检查时,球面三角形方法似乎最简单,但通常情况并非如此。问题是,我们不仅需要将该区域分解为三角形,还需要将其分解为球面三角形,即边为大圆弧的三角形。例如,纬度边界不符合条件,因此这些边界需要分解为更接近大圆弧的边。这对于任意边来说变得更加困难,因为大圆需要特定的球面角组合。例如,考虑一下如何在一个球体上分解一个中间带,把LAT 0和45°之间的所有区域都变成球面三角形。

最后,如果每个方法都有相似的错误,那么方法2会给出较少的三角形,但它们更难确定。方法1给出了更多条带,但它们很难确定。因此,我建议使用方法1作为更好的方法。

您在一个标记中提到了“地理”,因此我只能假设您位于大地水准面上多边形的面积之后。通常,这是使用投影坐标系而不是地理坐标系(即lon/lat)完成的。如果用lon/lat来计算,那么我假设返回的度量单位是球面的百分比

如果您想以更“GIS”的风格来实现这一点,那么您需要为您的区域选择一个度量单位,并找到一个适当的投影来保留区域(并非所有投影都这样做)。因为你说的是计算任意多边形,所以我会使用一些类似于投影的东西。将投影的原点/中心设置为多边形的中心,将多边形投影到新坐标系,然后使用标准平面技术计算面积

如果您需要在一个地理区域中绘制多个多边形,则可能会有其他投影可用(或足够接近)。例如,如果所有多边形都围绕一条子午线聚集,UTM就是一个很好的近似值

我不确定这些是否与Matlab的areaint函数的工作方式有关。

我用java重写了Matlab的“areaint”函数,结果完全相同。 “areaint”计算“单位表面”,所以我将答案乘以地球的表面积(5.10072e14平方米)

专用双区(ArrayList lats、ArrayList lons)
{       
双和=0;
双前角=0;
双普雷瓦兹=0;
双感冒0=0;
双az0=0;
F
private double area(ArrayList<Double> lats,ArrayList<Double> lons)
{       
    double sum=0;
    double prevcolat=0;
    double prevaz=0;
    double colat0=0;
    double az0=0;
    for (int i=0;i<lats.size();i++)
    {
        double colat=2*Math.atan2(Math.sqrt(Math.pow(Math.sin(lats.get(i)*Math.PI/180/2), 2)+ Math.cos(lats.get(i)*Math.PI/180)*Math.pow(Math.sin(lons.get(i)*Math.PI/180/2), 2)),Math.sqrt(1-  Math.pow(Math.sin(lats.get(i)*Math.PI/180/2), 2)- Math.cos(lats.get(i)*Math.PI/180)*Math.pow(Math.sin(lons.get(i)*Math.PI/180/2), 2)));
        double az=0;
        if (lats.get(i)>=90)
        {
            az=0;
        }
        else if (lats.get(i)<=-90)
        {
            az=Math.PI;
        }
        else
        {
            az=Math.atan2(Math.cos(lats.get(i)*Math.PI/180) * Math.sin(lons.get(i)*Math.PI/180),Math.sin(lats.get(i)*Math.PI/180))% (2*Math.PI);
        }
        if(i==0)
        {
             colat0=colat;
             az0=az;
        }           
        if(i>0 && i<lats.size())
        {
            sum=sum+(1-Math.cos(prevcolat  + (colat-prevcolat)/2))*Math.PI*((Math.abs(az-prevaz)/Math.PI)-2*Math.ceil(((Math.abs(az-prevaz)/Math.PI)-1)/2))* Math.signum(az-prevaz);
        }
        prevcolat=colat;
        prevaz=az;
    }
    sum=sum+(1-Math.cos(prevcolat  + (colat0-prevcolat)/2))*(az0-prevaz);
    return 5.10072E14* Math.min(Math.abs(sum)/4/Math.PI,1-Math.abs(sum)/4/Math.PI);
}
def polygon_area(lats, lons, algorithm = 0, radius = 6378137):
    """
    Computes area of spherical polygon, assuming spherical Earth. 
    Returns result in ratio of the sphere's area if the radius is specified.
    Otherwise, in the units of provided radius.
    lats and lons are in degrees.
    """
    from numpy import arctan2, cos, sin, sqrt, pi, power, append, diff, deg2rad
    lats = np.deg2rad(lats)
    lons = np.deg2rad(lons)

    # Line integral based on Green's Theorem, assumes spherical Earth

    #close polygon
    if lats[0]!=lats[-1]:
        lats = append(lats, lats[0])
        lons = append(lons, lons[0])

    #colatitudes relative to (0,0)
    a = sin(lats/2)**2 + cos(lats)* sin(lons/2)**2
    colat = 2*arctan2( sqrt(a), sqrt(1-a) )

    #azimuths relative to (0,0)
    az = arctan2(cos(lats) * sin(lons), sin(lats)) % (2*pi)

    # Calculate diffs
    # daz = diff(az) % (2*pi)
    daz = diff(az)
    daz = (daz + pi) % (2 * pi) - pi

    deltas=diff(colat)/2
    colat=colat[0:-1]+deltas

    # Perform integral
    integrands = (1-cos(colat)) * daz

    # Integrate 
    area = abs(sum(integrands))/(4*pi)

    area = min(area,1-area)
    if radius is not None: #return in units of radius
        return area * 4*pi*radius**2
    else: #return in ratio of sphere total area
        return area