为何基于笛卡尔坐标与经纬度计算的两点距离结果存在差异?
我有一组经纬度点,先用以下distance函数计算两点间距离,再通过X_Y_Z函数将经纬度转换为笛卡尔坐标,随后用公式$(x2+y2+z2){0.5}$计算距离,结果和第一种方法不同,请问原因是什么?
代码实现
import math def distance(lat2, lat1, lon2, lon1): distance = [] speed = [] accelerate = [] radius = 6371 # km dlat = math.radians(lat2 - lat1) dlon = math.radians(lon2 - lon1) a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \ * math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) d = radius * c distance.append(d) for i in range(len(distance)-1): speed.append((distance[i])/0.25) for i in range(len(speed)-1): accelerate.append((speed[i+1]-speed[i])/0.25) return distance, speed, accelerate def X_Y_Z(latitude, longitude): R = 6371 X = [] Y = [] Z = [] for lat, lon in zip(latitude, longitude): x = R * math.cos(lat) * math.cos(lon) y = R * math.cos(lat) * math.sin(lon) z = R * math.sin(lat) X.append(x) Y.append(y) Z.append(z) return X, Y, Z
示例问题
例如,点(40.714531,-73.725607)与(40.714527,-73.725591)用经纬度计算的距离为0.001377km,但对应的笛卡尔坐标(642.430295,-6287.620268,801.720448)与(642.527042,-6287.607109,801.746119)计算出的距离却不同。
问题原因分析
笛卡尔坐标转换未做弧度转换:
X_Y_Z函数直接使用原始的经纬度(单位是度)调用math.cos和math.sin,但Python的三角函数默认接收弧度值。而distance函数里已经正确将经纬度转为弧度计算,这导致笛卡尔坐标的计算结果完全错误,自然两点间距离和Haversine公式结果不一致。两点间距离计算逻辑错误:
你使用的$(x2+y2+z2){0.5}$是单个笛卡尔坐标点到原点的距离(理论上等于地球半径6371km),不是两点之间的欧氏距离。正确的两点笛卡尔距离应该计算坐标差的模:$\sqrt{(x_2-x_1)^2 + (y_2-y_1)^2 + (z_2-z_1)^2}$。不过即使修正这个逻辑,因为第一个问题的存在,结果还是会和Haversine公式不符。
修正后的代码
只需在X_Y_Z函数中添加弧度转换:
import math def X_Y_Z(latitude, longitude): R = 6371 X = [] Y = [] Z = [] for lat, lon in zip(latitude, longitude): # 将经纬度从度转为弧度 lat_rad = math.radians(lat) lon_rad = math.radians(lon) x = R * math.cos(lat_rad) * math.cos(lon_rad) y = R * math.cos(lat_rad) * math.sin(lon_rad) z = R * math.sin(lat_rad) X.append(x) Y.append(y) Z.append(z) return X, Y, Z
修正后,用正确的欧氏距离公式计算两点笛卡尔坐标的距离,结果会和distance函数的Haversine公式结果基本一致(误差仅来自浮点运算精度)。
内容的提问来源于stack exchange,提问作者user15649753

