已知圆心、圆弧起止点经纬度,求解圆弧中点经纬度
求解圆弧中点经纬度及角度计算疑问
已知条件
- 圆心A:经纬度
(-16.850278, 145.743889) - 圆弧起点B:经纬度
(-14.421667, 145.086389) - 圆弧终点C:经纬度
(-16.050833, 143.278056) - 已知圆弧半径
尝试代码
var angle = Math.atan2(start.lat, start.lng) - Math.atan2(end.lat, end.lng);
疑问点
Math.atan2是否基于X轴?经纬度在公式中的正确顺序是什么?- 当前计算的∠CAB角度值不正确,不确定是否可通过将角度除以2,结合B点与半径来求得D点。
- 当∠CAB大于180度时的处理方法。
注:配图旋转与给定点位不完全匹配。
解决方案与答疑
1. Math.atan2 的参数规则与坐标系
Math.atan2(y, x)计算的是从X轴正方向指向点(x,y)的逆时针角度,返回值范围是[-π, π](即-180°到180°)。- 经纬度对应坐标系:经度(东西方向)是X轴,纬度(南北方向)是Y轴,所以传入
Math.atan2的顺序应该是(纬度差, 经度差),而非直接传入点的原始经纬度——你之前的错误在于直接使用原始经纬度计算,而不是基于圆心的向量差。
2. 正确计算∠CAB的方法
∠CAB是向量AB与AC的夹角,必须先计算两点相对圆心的向量差:
- 计算相对向量:
// 向量AB:B相对于A的经纬度差 const x1 = start.lng - center.lng; const y1 = start.lat - center.lat; // 向量AC:C相对于A的经纬度差 const x2 = end.lng - center.lng; const y2 = end.lat - center.lat; - 计算两个向量的角度:
const angleAB = Math.atan2(y1, x1); // 向量AB与X轴的夹角 const angleAC = Math.atan2(y2, x2); // 向量AC与X轴的夹角 let angleCAB = angleAC - angleAB; - 角度归一化(确保在
[-π, π]范围内):if (angleCAB > Math.PI) angleCAB -= 2 * Math.PI; if (angleCAB < -Math.PI) angleCAB += 2 * Math.PI;
3. 圆弧中点D的计算
平面近似(小范围圆弧,精度要求不高时)
这种方法假设经纬度可以当作平面坐标处理:
- 计算向量AB、AC的单位向量(因为AB、AC长度等于半径):
const r = 已知半径; // 或通过AB的距离计算:r = Math.sqrt(x1*x1 + y1*y1) const unitAB = { x: x1/r, y: y1/r }; const unitAC = { x: x2/r, y: y2/r }; - 计算中点方向向量:两个单位向量的和,再归一化
const midX = unitAB.x + unitAC.x; const midY = unitAB.y + unitAC.y; const midLen = Math.sqrt(midX*midX + midY*midY); const unitMid = { x: midX/midLen, y: midY/midLen }; - 得到D点经纬度:
const D = { lng: center.lng + unitMid.x * r, lat: center.lat + unitMid.y * r };
球面精确计算(大范围圆弧)
如果是跨越大范围的球面圆弧,需用球面三角公式:
- 将经纬度转换为三维单位向量(地心坐标系)
- 计算向量AB与AC的球面夹角θ
- 将向量AB绕圆心A的法线旋转θ/2角度,得到D点的三维向量
- 将三维向量转换回经纬度
4. ∠CAB大于180度的处理
- 判断优弧:计算向量叉积
cross = x1*y2 - x2*y1,若cross < 0,说明∠CAB是大于180度的优弧。 - 优弧中点计算:此时中点方向是两个单位向量和的反方向,只需将
unitMid取反:const unitMid = { x: -midX/midLen, y: -midY/midLen }; - 角度归一化时,若原始角度差大于π,自动减去2π后会得到负角度,对应优弧的补角,此时计算中点时要注意方向。
内容的提问来源于stack exchange,提问作者tj26
相关产品推荐
相关产品推荐

