假设我有一组任意的纬度和经度对代表一些简单的闭合曲线上的点。在笛卡尔空间中,我可以使用格林定理轻松计算出这条曲线所包围的区域。计算球体表面区域的类似方法是什么?我猜我所追求的是Matlab's areaint
function背后的算法(甚至是一些近似值)。
答案 0 :(得分:11)
有几种方法可以做到这一点。
1)整合来自纬度带的贡献。这里每个条带的面积为(Rcos(A)(B1-B0))(RdA),其中A是纬度,B1和B0是起始和结束经度,所有角度都是弧度。
2)将曲面分解为spherical triangles,然后使用Girard's Theorem计算面积,并将其添加。
3)正如James Schek所述,在GIS工作中,他们使用一个区域保留投影到平面空间并计算那里的面积。
从您的数据描述中,听起来像第一种方法可能是最简单的。 (当然,可能还有其他一些我不知道的简单方法。)
编辑 - 比较这两种方法:
在第一次检查时,似乎球形三角形方法最简单,但一般来说情况并非如此。问题是,不仅需要将区域分成三角形,而且需要分成球形三角形,即边长为大圆弧的三角形。例如,纬度边界不符合,因此需要将这些边界分解为更接近大圆弧的边。并且对于任意边缘来说这变得更加困难,其中大圆圈需要球面角度的特定组合。例如,考虑如何分解球体周围的中间带,将纬度0和45度之间的所有区域称为球形三角形。
最后,如果要对每种方法使用类似的错误正确地执行此操作,方法2将提供更少的三角形,但它们将更难确定。方法1给出了更多条带,但它们很容易确定。因此,我建议将方法1作为更好的方法。
答案 1 :(得分:9)
我重写了MATLAB" isaint" java中的函数,它具有完全相同的结果。 " areaint"计算每单位" suface,因此我将答案乘以地球表面积(5.10072e14平方米)。
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);
}
答案 2 :(得分:7)
你在其中一个标签中提到“地理”,所以我只能假设你是在大地水准面表面上的多边形区域之后。通常,这是使用投影坐标系而不是地理坐标系(即lon / lat)来完成的。如果你是在lon / lat中进行的,那么我会假设返回的度量单位是球面的百分比。
如果你想用更“GIS”的味道来做这件事,那么你需要为你的区域选择一个度量单位,并找到一个保留区域的适当投影(不是全部都做)。既然你在谈论计算任意多边形,我会使用类似Lambert Azimuthal Equal Area投影的东西。将投影的原点/中心设置为多边形的中心,将多边形投影到新坐标系,然后使用标准平面技术计算面积。
如果您需要在某个地理区域内执行多个多边形,则可能会有其他预测可用(或将足够接近)。例如,如果所有多边形都围绕单个子午线聚集,则UTM是一个很好的近似值。
我不确定这些是否与Matlab的isaint功能有什么关系。
答案 3 :(得分:5)
我对Matlab的功能一无所知,但是我们走了。考虑将球形多边形分割为球形三角形,例如从顶点绘制对角线。球形三角形的表面积由
给出R^2 * ( A + B + C - \pi)
其中R
是球体的半径,A
,B
和C
是三角形的内角(以弧度表示)。括号中的数量称为“球形过剩”。
您的n
边多边形将分为n-2
个三角形。对所有三角形求和,提取公共因子R^2
,并将所有\pi
组合在一起,多边形区域为
R^2 * ( S - (n-2)\pi )
其中S
是多边形的角度和。括号中的数量也是多边形的球形过剩。
[edit]无论多边形是凸的,都是如此。重要的是它可以被解剖成三角形。
您可以通过一些矢量数学确定角度。假设您有三个顶点A
,B
,C
并且对B
处的角度感兴趣。因此,我们必须从点B
沿大圆段(多边形边)找到两个相切矢量(它们的大小无关)。让我们为BA
解决这个问题。大圆位于由OA
和OB
定义的平面中,其中O
是球体的中心,因此它应垂直于法线向量OA x OB
。它也应垂直于OB
,因为它在那里相切。因此,这种向量由OB x (OA x OB)
给出。您可以使用右侧规则来验证这是否在适当的方向。另请注意,这会简化为OA * (OB.OB) - OB * (OB.OA) = OA * |OB| - OB * (OB.OA)
。
然后,您可以使用好的'点积来查找边之间的角度:BA'.BC' = |BA'|*|BC'|*cos(B)
,其中BA'
和BC'
是来自B
边的切线向量到A
和C
。
[编辑清楚这些是切线向量,而不是点之间的文字]
答案 4 :(得分:0)
这是一个Python 3实现,受到上述答案的启发:
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
请找到更明确的版本(以及更多参考文献和待办事项...)here。
答案 5 :(得分:-1)