如何计算 python 中多个地理位置的中点

How to calculate the midpoint of several geolocations in python

是否有库或方法可以计算多个地理位置点的中心点? 这是我在纽约的地理位置列表,想找到大致的中点地理位置

L = [
     (-74.2813611,40.8752222),
     (-73.4134167,40.7287778),
     (-74.3145014,40.9475244),
     (-74.2445833,40.6174444),
     (-74.4148889,40.7993333),
     (-73.7789256,40.6397511)
    ]

comments 之后我收到了 HERE

的评论

使用 close to each other 的坐标,您可以将地球视为局部平坦的,并简单地找到质心,就好像它们是平面坐标一样。然后,您只需取纬度的平均值和经度的 average 即可找到 centroid.

latitudelongitude
lat = []
long = []
for l in L :
  lat.append(l[0])
  long.append(l[1])

sum(lat)/len(lat)
sum(long)/len(long)

-74.07461283333332, 40.76800886666667

考虑到您使用的是有符号度数格式 (more),即使是靠近反子午线(即 + 或 - 180 度经度)的小区域,由于不连续性,纬度和经度的简单平均也会产生问题这条线的经度值(在 -180 到 180 之间突然跳跃)。

考虑经度为 -179 和 179 的两个位置,它们的平均值为 0,这是错误的。

基于:https://gist.github.com/tlhunter/0ea604b77775b3e7d7d25ea0f70a23eb

假设您有一个 pandas 包含纬度和经度列的 DataFrame,下一个代码将 return 一个包含平均坐标的字典。

import math

x = 0.0
y = 0.0
z = 0.0

for i, coord in coords_df.iterrows():
    latitude = math.radians(coord.latitude)
    longitude = math.radians(coord.longitude)

    x += math.cos(latitude) * math.cos(longitude)
    y += math.cos(latitude) * math.sin(longitude)
    z += math.sin(latitude)

total = len(coords_df)

x = x / total
y = y / total
z = z / total

central_longitude = math.atan2(y, x)
central_square_root = math.sqrt(x * x + y * y)
central_latitude = math.atan2(z, central_square_root)

mean_location = {
    'latitude': math.degrees(central_latitude),
    'longitude': math.degrees(central_longitude)
    }

这个link会有用,先把lat/lon转成n向量,再求平均值。第一次尝试将代码转换为 Python 低于

import numpy as np
import numpy.linalg as lin

E = np.array([[0, 0, 1],
              [0, 1, 0],
              [-1, 0, 0]])

def lat_long2n_E(latitude,longitude):
    res = [np.sin(np.deg2rad(latitude)),
           np.sin(np.deg2rad(longitude)) * np.cos(np.deg2rad(latitude)),
           -np.cos(np.deg2rad(longitude)) * np.cos(np.deg2rad(latitude))]
    return np.dot(E.T,np.array(res))

def n_E2lat_long(n_E):
    n_E = np.dot(E, n_E)
    longitude=np.arctan2(n_E[1],-n_E[2]);
    equatorial_component = np.sqrt(n_E[1]**2 + n_E[2]**2 );
    latitude=np.arctan2(n_E[0],equatorial_component);
    return np.rad2deg(latitude), np.rad2deg(longitude)

def average(coords):
    res = []
    for lat,lon in coords:
        res.append(lat_long2n_E(lat,lon))
    res = np.array(res)
    m = np.mean(res,axis=0)
    m = m / lin.norm(m)
    return n_E2lat_long(m)
        

n = lat_long2n_E(30,20)
print (n)
print (n_E2lat_long(np.array(n)))

# find middle of france and libya
coords = [[30,20],[47,3]]
m = average(coords)
print (m)

我想改进@BBSysDyn 的回答。 如果计算一侧有额外顶点的多边形的中心,则平均计算可能会有偏差。因此 average 函数可以替换为质心计算解释 here

def get_centroid(points):

    x = points[:,0]
    y = points[:,1]
    
    # Solving for polygon signed area
    A = 0
    for i, value in enumerate(x):
        if i + 1 == len(x):
            A += (x[i]*y[0] - x[0]*y[i])
        else:
            A += (x[i]*y[i+1] - x[i+1]*y[i])
    A = A/2

    #solving x of centroid
    Cx = 0
    for i, value in enumerate(x):
        if i + 1 == len(x):
            Cx += (x[i]+x[0]) * ( (x[i]*y[0]) - (x[0]*y[i]) )
        else:
            Cx += (x[i]+x[i+1]) * ( (x[i]*y[i+1]) - (x[i+1]*y[i]) )
    Cx = Cx/(6*A)

    #solving y of centroid
    Cy = 0
    for i , value in enumerate(y):
        if i+1 == len(x):
            Cy += (y[i]+y[0]) * ( (x[i]*y[0]) - (x[0]*y[i]) )
        else:
            Cy += (y[i]+y[i+1]) * ( (x[i]*y[i+1]) - (x[i+1]*y[i]) )
    Cy = Cy/(6*A)

    return Cx, Cy

注意:如果是多边形或2个以上的点,必须列出它们,以便绘制多边形或形状。