4. 计算点之间的距离

任务说明

本案例提供两组地理坐标点(经纬度),分别使用Haversine公式和GeoPandas的distance()方法计算点与点之间的球面距离,并对比两种方法的结果是否一致。输入数据为两个点坐标,输出为两种方法计算的距离值及差异。

实现代码

import math
import geopandas as gpd
from shapely.geometry import Point

# 输入:两个点的经纬度(经度, 纬度)
point_a = (116.4074, 39.9042)   # 北京
point_b = (121.4737, 31.2304)   # 上海

# ---------- 1. Haversine公式 ----------
def haversine(coord1, coord2):
    """计算两个经纬度坐标之间的球面距离(单位:米)"""
    lon1, lat1 = coord1
    lon2, lat2 = coord2
    R = 6371000.0  # 地球平均半径(米)
    phi1 = math.radians(lat1)
    phi2 = math.radians(lat2)
    dphi = math.radians(lat2 - lat1)
    dlambda = math.radians(lon2 - lon1)
    a = math.sin(dphi / 2) ** 2 + math.cos(phi1) * math.cos(phi2) * math.sin(dlambda / 2) ** 2
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    return R * c

dist_haversine = haversine(point_a, point_b)
print(f"Haversine距离: {dist_haversine:.2f} 米")

# ---------- 2. GeoPandas distance()方法 ----------
# 创建GeoDataFrame,坐标系为WGS84(EPSG:4326)
gdf = gpd.GeoDataFrame(
    geometry=[Point(point_a), Point(point_b)],
    crs="EPSG:4326"
)

# 将坐标系转换为适合测距的投影坐标系(Web Mercator,单位:米)
gdf_proj = gdf.to_crs("EPSG:3857")

# 计算两点之间的距离(投影后平面距离近似球面距离)
dist_geopandas = gdf_proj.geometry[0].distance(gdf_proj.geometry[1])
print(f"GeoPandas distance()距离: {dist_geopandas:.2f} 米")

# ---------- 3. 结果对比 ----------
diff = abs(dist_haversine - dist_geopandas)
print(f"两种方法差异: {diff:.2f} 米")
print(f"相对误差: {diff / dist_haversine * 100:.4f}%")

代码说明

代码首先定义了两个城市的经纬度坐标。Haversine函数直接根据球面三角公式计算大圆距离。GeoPandas部分先将坐标点构建为GeoDataFrame(EPSG:4326),再投影到EPSG:3857(Web Mercator)坐标系,使距离计算以米为单位,然后调用distance()方法获取两点间距离。最后输出两种结果并计算差值和相对误差。

运行方式与依赖

运行前需安装依赖:pip install geopandas shapely。将代码保存为point_distance.py,在命令行执行python point_distance.py即可。

验证方法与判定标准

程序输出应包含三行:Haversine距离、GeoPandas距离和差异值。判定通过的标准为:两种方法计算的距离均在1060~1080千米范围内(北京到上海的实际球面距离约1067千米),且相对误差小于1%。由于Web Mercator投影在纬度40°附近存在约0.3%的长度变形,两种方法结果存在小量差异属正常现象。

两种球面距离计算方法对比 点A 北京 (116.41, 39.90) 点B 上海 (121.47, 31.23) 球面距离 ≈ 1067 km Haversine vs GeoPandas Haversine公式 球面三角学 · 直接计算 GeoPandas distance() 投影到EPSG:3857后计算 验证:两种方法结果差异应小于1%