在地理信息处理中,计算两点之间的距离、方位角以及从一个点出发给定距离和方位角求解另一个点的位置等问题是非常常见的需求。Python 提供了多种方式来实现这些功能,其中 pygc
是一个特别强大的库,它使用 Vincenty 的公式来精确地进行大圆相关的计算。
无论你是使用 pip 还是 conda 来管理你的 Python 环境,安装 pygc
都非常简单:
pip 安装命令:
pip install pygc
conda 安装命令:
conda install -c conda-forge pygc
如果你想要获取最新的开发版本,可以通过以下命令直接从 GitHub 上安装:
pip install git+https://github.com/axiom-data-science/pygc.git
!pip install pygc -i https://pypi.mirrors.ustc.edu.cn/simple/
Looking in indexes: https://pypi.mirrors.ustc.edu.cn/simple/
Collecting pygc
Downloading https://mirrors.ustc.edu.cn/pypi/packages/49/7c/af09d2f53967326c0d605c55a22f2f432b5034ca0c943287375695e743f7/pygc-2.0.0-py3-none-any.whl (19 kB)
Requirement already satisfied: pyproj in /opt/conda/lib/python3.9/site-packages (from pygc) (3.4.1)
Requirement already satisfied: numpy in /opt/conda/lib/python3.9/site-packages (from pygc) (1.26.4)
Requirement already satisfied: certifi in /opt/conda/lib/python3.9/site-packages (from pyproj->pygc) (2024.2.2)
Installing collected packages: pygc
Successfully installed pygc-2.0.0
我们可以利用 great_circle
函数来根据给定的起始点(纬度和经度)、距离(单位:米)和方位角(角度)来计算到达的新点的位置。例如:
from pygc import great_circle
result = great_circle(distance=111000, azimuth=65, latitude=30, longitude=-74)
result
这个例子将会返回一个新的点,其纬度为约 30.419,经度约为 -72.953,反方位角约为 245.527°。
from pygc import great_circle
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
# 设置参数
distance_km = 111# 假设距离为111公里(大约等于一度纬度)
start_latitude = 30
start_longitude = -74
azimuths = np.arange(0, 360, 10) # 每隔10度计算一个点
# 计算新点位置
results = [great_circle(distance=distance_km*1000, azimuth=az, latitude=start_latitude, longitude=start_longitude) for az in azimuths]
# 提取经纬度
lats = [res['latitude'][0] for res in results]
lons = [res['longitude'][0] for res in results]
# 可视化
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
# 设置地图范围
ax.set_extent([start_longitude-5, start_longitude+5, start_latitude-5, start_latitude+5], crs=ccrs.PlateCarree())
# 添加地理特征
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.BORDERS, linestyle=':')
ax.add_feature(cfeature.LAND, color='lightgray')
ax.add_feature(cfeature.OCEAN, color='lightblue')
# 绘制起点和新点
ax.plot(start_longitude, start_latitude, 'bo', markersize=12, transform=ccrs.Geodetic()) # 起点
for lon, lat in zip(lons, lats):
ax.plot(lon, lat, 'r.', transform=ccrs.Geodetic()) # 新点
# 连接线
for lon, lat in zip(lons, lats):
ax.plot([start_longitude, lon], [start_latitude, lat], linewidth=1, color='b', transform=ccrs.Geodetic())
plt.title('Visualization of Points at Different Azimuths using Cartopy')
plt.show()
为了生成以某个中心点为中心向不同方向延伸的多个点,你可以这样操作:
简单示例
result = great_circle(distance=100000, azimuth=[0, 60, 120, 180, 240, 300], latitude=30, longitude=-74)
#可视化
from pygc import great_circle
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
# 设置参数
distance_km = 100# 距离为100公里
start_latitude = 30
start_longitude = -74
azimuths = [0, 60, 120, 180, 240, 300] # 方位角列表
# 计算新点位置
result = great_circle(distance=distance_km*1000, azimuth=azimuths, latitude=start_latitude, longitude=start_longitude)
# 提取经纬度
lats = result['latitude']
lons = result['longitude']
# 可视化
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
# 设置地图范围,确保所有点都在图内
ax.set_extent([min(lons)-5, max(lons)+5, min(lats)-5, max(lats)+5], crs=ccrs.PlateCarree())
# 添加地理特征
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.BORDERS, linestyle=':')
ax.add_feature(cfeature.LAND, color='lightgray')
ax.add_feature(cfeature.OCEAN, color='lightblue')
# 绘制起点和新点
ax.plot(start_longitude, start_latitude, 'bo', markersize=12, transform=ccrs.Geodetic(), label='Start Point') # 起点
for lon, lat in zip(lons, lats):
ax.plot(lon, lat, 'r.', transform=ccrs.Geodetic()) # 新点
# 连接线
for lon, lat in zip(lons, lats):
ax.plot([start_longitude, lon], [start_latitude, lat], linewidth=1, color='b', transform=ccrs.Geodetic())
plt.legend()
plt.title('Visualization of Points at Different Azimuths using Cartopy')
plt.show()
这将围绕指定的中心点创建六个等距的点,每个点与前一个点之间的方位差为 60°。
great_distance
函数可以用来计算两个点之间的距离(单位:米)和方位角。例如:
from pygc import great_distance
result = great_distance(start_latitude=30, start_longitude=-74, end_latitude=40, end_longitude=-74)
result
此例中的结果表示两地之间的大圆距离大约为 1109415.6 米,且由于它们位于同一经度线上,所以方位角为 0°。
from pygc import great_distance
# 定义多组起点和终点坐标
start_latitudes = [30, 35] # 起始点纬度数组
start_longitudes = [-74, -79] # 起始点经度数组
end_latitudes = [40, 45] # 结束点纬度数组
end_longitudes = [-74, -79] # 结束点经度数组
# 使用 great_distance 计算距离和方位角
result = great_distance(start_latitude=start_latitudes, start_longitude=start_longitudes,
end_latitude=end_latitudes, end_longitude=end_longitudes)
print(result)
{'distance': array([1109415.63240213, 1110351.47627678]), 'azimuth': array([0., 0.]), 'reverse_azimuth': array([180., 180.])}
假设我们有一个台风的轨迹数据,包含一系列时间戳以及相应的经纬度位置。我们可以使用 pygc 库来计算两个连续观测点之间的距离,并结合时间差来估算台风的移动速度。
from pygc import great_distance
# 示例台风轨迹数据
times = ['2025-02-06T00:00:00Z', '2025-02-06T01:00:00Z'] # 时间戳
latitudes = [18.5, 19.0] # 纬度
longitudes = [120.5, 121.0] # 经度
# 计算距离和方位角
result = great_distance(start_latitude=latitudes[0], start_longitude=longitudes[0],
end_latitude=latitudes[1], end_longitude=longitudes[1])
distance = result['distance'][0] # 单位:米
time_diff_seconds = (1 * 60 * 60) # 假设时间差为1小时,转换为秒
# 计算速度
speed_m_per_s = distance / time_diff_seconds
print(f"台风的平均移动速度约为 {speed_m_per_s:.2f} 米/秒")
台风的平均移动速度约为 21.23 米/秒
在雷达系统中,如果已知雷达站的位置和探测到的目标位置,可以使用 pygc 来计算两者之间的距离和方位角
# 雷达站位置
radar_lat, radar_lon = 40.7128, -74.0060 # 纽约市为例
# 目标位置
target_lat, target_lon = 40.730610, -73.935242 # 自由女神像为例
result = great_distance(start_latitude=radar_lat, start_longitude=radar_lon,
end_latitude=target_lat, end_longitude=target_lon)
distance_to_target = result['distance'][0] # 目标距离,单位:米
azimuth_to_target = result['azimuth'][0] # 方位角
print(f"从雷达站到目标的距离是 {distance_to_target:.2f} 米,方位角是 {azimuth_to_target:.2f} 度。")
从雷达站到目标的距离是 6296.87 米,方位角是 71.67 度。
pygc 库以其高效性和准确性,在执行基于 Vincenty 公式的大圆计算方面表现出色,无论是简单的距离测量还是复杂的方位分析任务都能胜任。本文旨在帮助读者快速上手,并将所学应用于实际项目中。对于深入学习和探索更多高级应用,推荐参考相关技术手册或文档。