地理空间分析中的常用python操作(持续更新)

本章节主要参考《python地理空间分析指南》第五章的内容。


一、距离测量

距离测量包括欧式距离,球面距离,以及大地线距离(椭球距离)。主要采用math库(标准库,无需下载)进行运算。

1.欧式距离

计算任意两点之间的距离可以采用距离公式:

                                                   distance = \sqrt{(x_{1}-x_{2})^{2}+(y_{1}-y_{2})^{2}}

例如:计算点A(x1, y1)和点B(x2, y2)之间的欧式距离(UTM坐标)

import math

x1 = 456456.23
y1 = 1279721.064 
x2 = 576628.34
y2 = 1071740.33

ditance = math.sqrt((x1-x2)**2+(y1-y2)**2)
print(distance)

# 输出240.63

2.球面距离(半正矢公式)

利用球面距离的计算公式(Haversine公式)进行计算。

例如:计算点A(-90.212,32.316)和点B(-88.952,30.438)之间的距离(经纬度坐标)

import math

x1 = -90.212
y1 = 32.316
x2 = -88.952
y2 = 30.438

# 经纬度转换为弧度
x_dist = math.radians(x1-x2)
y_dist = math.radians(y1-y2)
y1_rad = math.radians(y1)
y2_rad = math.radians(y2)

a = math.sin(y_dist/2)**2 + math.sin(x_dist/2) * math.cos(y1_rad) * math.cos(y2_rad)
c = 2 * math.asin(math.sqrt(a))
distance = c * 6371
print(distance)

# 输出240.63

3.椭球距离(Vincenty公式)

椭球距离一般采用的是Vincenty公式NAD83(North American Datum )椭球模型。

Vincenty公式的相关准则如下:

其中,NAD83的相关参数为:

例如:计算点A(-90.212,32.316)和点B(-88.952,30.438)之间的距离(经纬度坐标)

import math

x1 = -90.212
y1 = 32.316
x2 = -88.952
y2 = 30.438

# NAD83的椭球参数
a = 6378137        # 半长轴
f = 1/298.257      # 扁平度
b = abs((f*a)-a)   # 半短轴

# 经纬度转化为弧度
L = math.radians(x2-x1)
U1 = math.atan((1-f) * math.tan(math.radians(y1)))
U2 = math.atan((1-f) * math.tan(math.radians(y2)))

sinU1 = math.sin(U1)
cosU1 = math.cos(U1)
sinU2 = math.sin(U2)
cosU2 = math.cos(U2)
lam = L

for i in range(100):
    sinLam = math.sin(lam)
    cosLam = math.cos(lam)
    sinSigma = math.sqrt((cosU2 * sinLam)**2 + (cosU1 * sinU2 - sinU1 * cosU2 * cosLam)**2)
    cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLam    

    # 判断是否为重合点
    if sinSigma==0:
        distance = 0
        break

    sigma = math.atan2(sinSigma, cosSigma)
    sinAlpha = cosU1 * cosU2 * sinLam / sinSigma
    cosSqAlpha = 1 - sinAlpha**2
    cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha
    
    if math.isnan(cos2SigmaM):
        cos2SigmaM = 0
    
    C = f/16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha))
    LP = lam
    lam = L + (1 - c) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + 
            C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)))
    
    if not abs(lam - LP) > 1e-12:
        break

uSq = cosSqAlpha * (a**2 - b**2) / b**2
A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)))
B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)))
deltaSigma = B * sinSigma * (cos2SigmaM + B/4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
            B/6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM *cos2SigmaM)))
distance = b * A * (sigma - deltaSigma)
print(distance)
    
# 输出结果240237.67

二、方位计算

方位计算是以正北方向为0°方向,顺时针方向角度依次增大的方位角计算。

例如:计算点A(-90.212,32.316)和点B(-88.952,30.438)之间的方位角。

from math import atan2, cos, sin, degrees

x1 = -90.212
y1 = 32.316
x2 = -88.952
y2 = 30.438

angle = atan2(cos(y1)*sin(y2) - sin(y1)*cos(y2)*cos(x2-x1), sin(x2-x1)*cos(y2))
bearing = (degrees(angle) + 360) % 360
print(bearing)

#输出309.36

三、坐标转换

可以利用utm模块进行墨卡托投影和大地经纬度的相互转换。utm模块的官方下载地址为:https://pypi.org/project/utm/

例如:墨卡托投影点(5377685.825,479747.045)转大地经纬度。

import utm

y = 479747.045
x = 5377685.825

zone = 32
band = 'U'
print(utm.to_latlon(y, x, zone, band))

#输出(48.551,8.725)

例如:大地经纬度(48.551,8.725)转墨卡托投影坐标。

import utm
utm.from_latlon(48.551, 8.725)
# 输出(479747.045,5377691.373,32,'U')

四、重投影

猜你喜欢

转载自blog.csdn.net/z704630835/article/details/82777616
今日推荐