在日常工作中,经常有人要求我以30弧秒的分辨率计算地理投影中的全球栅格数据集的面积。这些数据集通常是“合并”操作的结果(一个典型的示例是与国家层相结合的植被类别)。为此,我们的单位创建了一个栅格数据集,其中地理投影中每个像素的面积为30弧秒。使用该面积网格,将执行zonalstat来汇总每个类别的面积。由于我不确定如何创建该区域网格,因此我一直想知道这种方法是否仅在等面积投影中重新投影栅格是否更准确(从简单的测试来看,这两种方法的结果是相似的)。是否有人遇到过类似情况?
在日常工作中,经常有人要求我以30弧秒的分辨率计算地理投影中的全球栅格数据集的面积。这些数据集通常是“合并”操作的结果(一个典型的示例是与国家层相结合的植被类别)。为此,我们的单位创建了一个栅格数据集,其中地理投影中每个像素的面积为30弧秒。使用该面积网格,将执行zonalstat来汇总每个类别的面积。由于我不确定如何创建该区域网格,因此我一直想知道这种方法是否仅在等面积投影中重新投影栅格是否更准确(从简单的测试来看,这两种方法的结果是相似的)。是否有人遇到过类似情况?
Answers:
对于由平行线(纬度)和子午线(经度)界定的任何球形四边形的面积,都有一个相对简单的精确公式。可以使用椭圆(长轴a和短轴b)的基本属性直接得出该椭圆,该椭圆绕其短轴旋转以产生椭球。(该推导很好地完成了微积分练习,但我相信对此站点不会有太大兴趣。)
通过将计算分解为基本步骤来简化公式。
首先,东西边界之间的距离(子午线l0和l1)是整个圆的一部分,等于q =(l1- l0)/ 360(按度数测量子午线)或1 =( l1-l0)/(2 * pi)(当子午线以弧度为单位时)。找到位于平行线f0和f1之间的整个切片的面积,然后乘以q即可。
其次,我们将针对由赤道界定的椭圆形水平切片(在f0 = 0处)和在纬度f处平行的椭圆(= f1)处采用一个公式。任意两个纬度f0和f1之间的切片面积(位于同一半球上)将是较大面积和较小面积之间的差。
最后,假设模型是真正的椭球(而不是球体),则赤道与纬度为f的平行线之间的此类切片的面积为
area(f) = pi * b^2 * (log(zp/zm) / (2*e) + sin(f) / (zp*zm))
其中a
和b
分别是生成椭圆的长轴和短轴的长度,
e = sqrt(1 - (b/a)^2)
是它的怪癖
zm = 1 - e*sin(f); zp = 1 + e*sin(f)
(这比使用测地线的计算要简单得多,无论如何,测地线仅仅是并行的近似值。请注意@cffk的评论,涉及一种log(zp/zm)
在低纬度下避免精度损失的计算方式。)
area(f)
是从赤道到纬度f(图中北约30度)的不透明切片的面积。X和Y是所示的地心笛卡尔坐标轴,仅供参考。
对于WGS 84椭球,请使用常数
a = 6 378 137 meters, b = 6 356 752.3142 meters,
要求
e = 0.08181919084296
(对于具有球形模型一个 = b,公式变为不定你必须采取限制为e -从上面,然后降低到标准式> 0 2 * pi * a^2 * sin(f)
。)
根据这些公式,以赤道为基准的30'x 30'四边形的面积为3077.2300079129平方公里,而与杆(实际上只是一个三角形)接触的30'x 30'四边形的面积仅为13.6086152平方公里。
作为检验,适用于覆盖地球表面的720 x 360网格的所有单元的公式得出的总表面积为4 * pi *(6371.0071809)^ 2平方公里,表明地球的真实半径应为6371.0071809公里。这与Wikipedia值的不同之处仅在于最后一个有效数字(大约十分之一毫米)。(我认为Wikipedia的计算有点差劲:-)。
作为其他检查,我使用了这些公式的版本来复制列夫·M·布加耶夫斯基和约翰·P·斯奈德在《地图投影:参考手册》(Taylor和Francis,1995年)中的附录4和5 。附录4显示了最近的子午线和平行线的30'长段的弧长。抽查结果显示完全一致。然后,我以0.0005'(而不是0.5')的增量重新创建了表格,并根据这些弧长估算出的四边形面积在数值上进行了积分。椭球的总面积被精确地复制到八个以上的有效数字。附录5示出的值area(f)
用于˚F = 0,1/2,1,...,90度,乘以1 /(2 * PI)。这些值被指定为最接近的平方公里。 肉眼检查0、45和90度附近的值显示出完美的一致性。
可以使用栅格代数来应用此精确公式,栅格代数以给出每个像元上限的纬度的网格和给出下限的纬度的网格开头。这些基本上都是y坐标网格。(在每种情况下,你可能想要创建sin(f)
,然后zm
和zp
作为中间结果。)减去两个结果,采取的所述绝对值,并乘以分数q在第一步骤中获得的(等于0.5 / 360 = 1/720例如30英寸的单元格宽度)。这将是一个其值包含精确值的网格每个像元的面积(取决于网格自身的数值精度)。只需确保以正弦函数期望的形式表达纬度:许多栅格计算器会以度为单位给您提供坐标,但期望三角函数的弧度!
作为记录,这是 WGS 84椭球上从赤道到极点的30'x 30'单元的精确区域,间隔为30'至11位数字(与小半径b相同的数字):
3077.2300079,3077.0019391,3076.5458145,3075.8616605,3074.9495164,3073.8094348,3072.4414813,3070.8457347,3069.0222870,3066.9712434,3064.6927222,3062.1868550,3059.4537865,3056.4936748,3053.3066912,3049.8930202,3046.2528597,3042.3864209,3038.2939285,3033.9756204,3029.4317480,3024.6625762,3019.6683833,3014.4494612,3009.0061153,3003.3386648,2997.4474422,2991.3327939,2984.9950800,2978.4346744,2971.6519646,2964.6473522,2957.4212526,2949.9740951,2942.3063230,2934.4183938,2926.3107788,2917.9839636,2909.4384482,2900.6747464,2891.6933866,2882.4949115,2873.0798782,2863.4488581,2853.6024374,2843.5412166,2833.2658109,2822.7768503,2812.0749792,2801.1608571,2790.0351582,2778.6985716,2767.1518013,2755.3955665,2743.4306011,2731.2576543,2718.8774905,2706.2908892,2693.4986451,2680.5015685,2667.3004848,2653.8962347,2640.2896746,2626.4816763,2612.4731271,2598.2649300,2583.8580035,2569.2532818,2554.4517149,2539.4542684,2524.2619238,2508.8756783,2493.2965451,2477.5255533,2461.5637477,2445.4121891,2429.0719545,2412.5441367,2395.8298444,2378.9302026,2361.8463521,2344.5794500,2327.1306692,2309.5011988,2291.6922441,2273.7050264,2255.5407830,2237.2007674,2218.6862492,2199.9985139,2181.1388633,2162.1086151,2142.9091030,2123.5416769,2104.0077025,2084.3085615,2064.4456516,2044.4203864,2024.2341953,2003.8885234,1983.3848318,1962.7245972,1941.9093120,1920.9404843,1899.8196375,1878.5483108,1857.1280585,1835.5604507,1813.8470724,1791.9895239,1769.9894206,1747.8483931,1725.5680867,1703.1501618,1680.5962932,1657.9081707,1635.0874985,1612.1359952,1589.0553936,1565.8474409,1542.5138984,1519.0565410,1495.4771578,1471.7775513,1447.9595378,1424.0249466,1399.9756206,1375.8134157,1351.5402005,1327.1578567,1302.6682785,1278.0733724,1253.3750574,1228.5752643,1203.6759360,1178.6790272,1153.5865040,1128.4003439,1103.1225355,1077.7550785,1052.2999830,1026.7592702,1001.1349711,975.42912705,949.64378940,923.78101904,897.84288636,871.83147097,845.74886152,819.59715539,793.37845851,767.09488512,740.74855748,714.34160569,687.87616739,661.35438752,634.77841811,608.15041795,581.47255240,554.74699308,527.97591765,501.16150951,474.30595754,447.41145586,420.48020351,393.51440422,366.51626611,339.48800143,312.43182627,285.34996030,258.24462644,231.11805066,203.97246162,176.81009042,149.63317034,122.44393648,95.244625564,68.037475592,40.824725575,13.608615243
值以平方公里为单位。
如果您想近似这些区域或只是简单地更好地了解它们的行为,则公式可以按照以下模式简化为幂级数:
area(f) = 2 * pi * b^2 * z * (1 + (4/3)y + (6/5)y^2 + (8/7)y^3 + ...)
哪里
z = sin(f), y = (e*z)^2.
(等效公式出现在Bugayevskiy&Snyder,同上,公式(2.1)。)
由于e ^ 2很小(对于地球的所有椭圆模型,约为1/150),并且z介于0和1之间,因此y也很小。因此,项y ^ 2,y ^ 3,...迅速变小,每个项又增加了两位小数的精度。如果我们完全忽略y,则公式将是半径为b的球体面积的公式。其余术语可以理解为纠正了地球赤道隆起。
关于面积的测地距离计算如何与这些精确公式进行比较,提出了一些问题。测地线距离方法是通过测地线而不是平行线来近似每个四边形,而水平线将它们的角连接起来,并为梯形应用欧几里得公式。对于较小的四边形,例如30'的四边形,它的偏置会略低,并且相对精度在百万分之6到10之间。这是WGS 84(或与此有关的任何合理的地球椭球)的误差图:
因此,如果(1)您可以轻松访问测地距离计算,并且(2)可以接受ppm级误差,则可以考虑使用这些测地线计算并将其结果乘以1.00000791来校正偏差。对于另外两个小数位精度,请从校正因子中减去pi / 2 * cos(2f)/ 10 ^ 6:结果将精确到0.04 ppm以内。
radouxju问题的答案取决于投影到椭球体上的像素的形状。如果栅格的坐标系是经度和纬度,则像素为菱形线矩形,可以使用wuber的答案,或者更普遍地,您可以将公式用于边缘为菱形线的多边形。如果坐标系是大规模的保形投影(UTM,状态平面等),则通过测地线近似边缘并将其用于测地线多边形将更为准确。测地多边形可能是最适合常规使用的多边形,因为与菱形线多边形不同,测地多边形在极点附近表现良好。
我的库GeographicLib提供了测地线和横线多边形的公式的实现。测地线有多种语言版本。大黄线区域仅C ++。有一个在线版本(大地+恒向线),可在这里。这些计算的精度通常优于0.1平方米。
您必须判断可信/官方的...测地线公式来自测地线下方的区域(Danielsen,1989,需要订购)和测地线算法(Karney,2013,开放获取)。此处给出了横线公式。
我在尝试确定WGS84像素面积的公式时遇到了这个问题。虽然@whuber的答案确实包含此信息,但要获得给定纬度下平方度像素的面积的公式仍是一项工作。我包括了下面编写的Python函数,该函数将其抽象为一个调用。尽管它不能直接回答张贴者关于整个栅格面积的问题(尽管可以将所有像素的面积相加),但我认为对于那些正在寻找类似计算的人来说,它仍然是有用的信息。
def area_of_pixel(pixel_size, center_lat):
"""Calculate m^2 area of a wgs84 square pixel.
Adapted from: /gis//a/127327/2397
Parameters:
pixel_size (float): length of side of pixel in degrees.
center_lat (float): latitude of the center of the pixel. Note this
value +/- half the `pixel-size` must not exceed 90/-90 degrees
latitude or an invalid area will be calculated.
Returns:
Area of square pixel of side length `pixel_size` centered at
`center_lat` in m^2.
"""
a = 6378137 # meters
b = 6356752.3142 # meters
e = math.sqrt(1 - (b/a)**2)
area_list = []
for f in [center_lat+pixel_size/2, center_lat-pixel_size/2]:
zm = 1 - e*math.sin(math.radians(f))
zp = 1 + e*math.sin(math.radians(f))
area_list.append(
math.pi * b**2 * (
math.log(zp/zm) / (2*e) +
math.sin(math.radians(f)) / (zp*zm)))
return pixel_size / 360. * (area_list[0] - area_list[1])