您可以直接在球体上计算面积,而不是使用等面积投影。
此外,根据this discussion,似乎 Girard 定理(苏尔克的答案)在某些情况下并不能给出准确的结果,例如“由从极到极的 30º 月牙包围并以本初子午线和30ºE"(见here)。
更精确的解决方案是直接在球体上进行线积分。下面的比较表明这种方法更精确。
像所有其他答案一样,我应该提一下我们假设地球是球形的警告,但我认为对于非关键目的来说这已经足够了。
Python 实现
这是一个使用线积分和格林定理的 Python 3 实现:
def polygon_area(lats, lons, 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
我在sphericalgeometry 包there 中编写了一个更明确的版本(以及更多的参考和待办事项...)。
数值比较
科罗拉多州将作为参考,因为之前的所有答案都在其区域进行了评估。其精确的总面积为 104,093.67 平方英里(来自US Census Bureau,第 89 页,另见here),或 269601367661 平方米。我没有找到 USCB 实际方法的来源,但我认为它是基于对地面实际测量的求和,或使用 WGS84/EGM2008 进行的精确计算。
Method | Author | Result | Variation from ground truth
--------------------------------------------------------------------------------
Albers Equal Area | sgillies | 268952044107 | -0.24%
Sinusoidal | J. Kington | 268885360163 | -0.26%
Girard's theorem | sulkeh | 268930758560 | -0.25%
Equal Area Cylindrical | Jason | 268993609651 | -0.22%
Line integral | Yellows | 269397764066 | **-0.07%**
结论:使用直接积分更精确。
性能
我没有对不同的方法进行基准测试,将纯 Python 代码与编译的 PROJ 投影进行比较没有意义。直观上需要更少的计算。另一方面,三角函数可能是计算密集型的。