利用Python計算兩個地理位置之間的中點

介紹

眾所周知地球是一個球體,地平面是一個弧形,那么兩個地理位置之間的中點該如何確定,比如北京與上海兩個城市之間的中點在哪里?
可以直接對經緯度進行平均,求中點嗎?答案:當然不可以
我們都知道一個地理位置是由經度、維度來確定,平時在計算地理信息時基本都是兩列數據,一列是經度,一列是維度,比如:
北京:"lon":116.512885,"lat":39.847469,
上海:"lon":116.332334,"lat":39.882806

  • lon:longitude 經度
    經度是指通過某地的經線面與本初子午面所成的二面角
    在本初子午線以東的經度叫東經,在本初子午線以西的叫西經。
    東經用“E”表示,西經用“W”表示。
  • lat:latitude 維度
    赤道的緯度為0°,將行星平分為南半球和北半球。
    緯度是指某點與地球球心的連線和地球赤道面所成的線面角,其數值在0至90度之間。
    位于赤道以北的點的緯度叫北緯,記為N,位于赤道以南的點的緯度稱南緯,記為S。

概念-----計算原理

那么應該怎么計算呢?
我們可以把地球看做是一個立體坐標系,有x軸,y軸,z軸三個方向,對于球面上的一個點,可以分別計算出在x軸,y軸,z軸的投影,那么在三個軸上面的分量是可以直接求均值,最后再進行反向合成,這樣即可求出球面上對應的中點。

下圖手工畫出了,在x軸,y軸,z軸如何進行投影(可進行參考):

球面點進行分解

根據手繪圖可以計算出,各個分量:
x = cos(lat) * sin(lon)
y = cos(lat) * cos(lon)
z = sin(lat)

角度和弧度相互轉換
由于我們實際數據中的經緯度是角度,而我們在計算分量時需要用弧度,比如cos(π/2),這里就先需要轉換,那么怎么進行轉換:
python的math模塊里面有相應轉換函數
radians()-----將角度轉換為弧度
degrees()-----將弧度轉換為角度

腦補一下角度與弧度:
度和弧度都是衡量角的大小的單位,就像米(m)和英寸(in)都是用來衡量長度的單位。度用°來表示,弧度用rad表示。
1rad = (180/π)° ≈ 57.3°
1° = (π/180)rad ≈ 0.01745rad
弧度的定義
在一個圓中,弧長等于半徑的弧,其所對的圓心角就是 1rad。也就是說,兩條射線從圓心向圓周射出,形成一個夾角和夾角正對的一段弧。當這段弧的長度正好等于圓的半徑時,兩條射線的夾角的弧度為 1。

弧度

根據定義,圓一周的弧度數為 2πr/r = 2π,360° = 2πrad,平角(即 180° 角)為 πrad,直角為 π/2rad
角度與弧度

在具體計算中,角度以弧度給出時,通常不寫弧度單位,直接寫值。最典型的例子是三角函數,例如sin(8π)、tan(3π/2)

自定義函數

import pandas as pd
import numpy as np
from math import cos, sin, atan2, sqrt, radians, degrees

data=pd.read_excel('./data.xlsx')

def center_geolocation(df): 
    """
    輸入多個經緯度坐標,找出中心點  [lon,lat]->[經度,維度]
    :param geolocations: 列表
    :return 中心經緯度
    """
    x = 0
    y = 0
    z = 0
    lenth = len(df)
    for lon, lat in zip(df['lon'].to_list(),df['lat'].to_list()):
        lon = radians(float(lon))    #radians將角度轉換為弧度
        lat = radians(float(lat))
        x += cos(lat) * sin(lon)
        y += cos(lat) * cos(lon)
        z += sin(lat)
    
    x = float(x / lenth)
    y = float(y / lenth)
    z = float(z / lenth)
    
    #degrees將弧度轉換為角度
    lon=degrees(atan2(x, y))
    lat=degrees(atan2(z, sqrt(x * x + y * y)))
    
    return pd.DataFrame({'lon':[lon],'lat':[lat]})    

#使用
result_data=data.groupby('ID').apply(center_geolocation)
result_data.index=result_data.index.droplevel(level=1)
result_data.to_excel('./result_data.xlsx')
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。