You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CesiumJS:如何正确获取地球表面线段的中点?

问题:Cesium中计算纬线线段中点纬度不符合预期

问题背景

定义了两条沿纬线的线段,尝试计算中点时,纬度结果与预期不符:

  • 第一条线段端点[-150,45]和[150,45],预期中点纬度45,实际得到49.11979677835345
  • 第二条线段端点[150,40]和[-150,40],预期中点纬度40,实际得到44.111242494938004

初始代码

const testLines = [
                    [ [ -150,  45 ], [  150,  45 ] ], // <---
                    [ [  150,  40 ], [ -150,  40 ] ], // --->
                  ];

testLines.forEach( ( line ) => {
  const endpoints = Cesium.Cartesian3.fromDegreesArray( [ ...line[0], ...line[1] ] );
  const e1e2      = new Cesium.Cartesian3();
  const halfe1e2  = new Cesium.Cartesian3();
  const midpoint  = new Cesium.Cartesian3();
  
  Cesium.Cartesian3.subtract( endpoints[1], endpoints[0], e1e2 );
  Cesium.Cartesian3.multiplyByScalar( e1e2, 0.5, halfe1e2 );
  Cesium.Cartesian3.add( endpoints[0], halfe1e2, midpoint ); 
 
  const carto = Cesium.Cartographic.fromCartesian( midpoint );
  const lon   = Cesium.Math.toDegrees( carto.longitude );
  const lat   = Cesium.Math.toDegrees( carto.latitude );
  
  console.log( `${lon}, ${lat}` );
})

输出结果

180, 49.11979677835345
180, 44.111242494938004

已尝试的方法

  • 直接使用Cesium.Cartesian3.midpoint和Cesium.Cartesian3.lerp(endpoints[0], endpoints[1], .5, midpoint),结果一致
  • 使用EllipsoidGeodesic插值计算,代码如下,结果仍然相同:
const a = new Cesium.Cartographic()
const b = new Cesium.Cartographic()
      
Cesium.Cartographic.fromDegrees( line[0][0], line[0][1], 0, a );
Cesium.Cartographic.fromDegrees( line[1][0], line[1][1], 0, b );

const globeCalc = new Cesium.EllipsoidGeodesic( a, b )
const midpoint = new Cesium.Cartographic()
      
globeCalc.interpolateUsingFraction( .5, midpoint )

const lon   = Cesium.Math.toDegrees( midpoint.longitude );
const lat   = Cesium.Math.toDegrees( midpoint.latitude );

console.log( `${lon}, ${lat}` );

原因及解决方案

核心原因

你混淆了两个关键概念:

  1. 笛卡尔空间中点:Cartesian3相关方法计算的是3D空间中两点的直线中点,该点不在椭球表面,投影回椭球后会出现纬度偏移。
  2. 测地线中点:EllipsoidGeodesic计算的是椭球表面两点的最短路径(测地线)中点,而除赤道外的纬线并非测地线,测地线会更靠近极点,因此中点纬度会高于原纬线纬度。

解决方案(获取纬线中点)

如果需要的是沿等纬度线的中点,直接在经纬度层面计算即可,无需转换为笛卡尔坐标:

testLines.forEach( ( line ) => {
  const [lon1, lat1] = line[0];
  const [lon2, lat2] = line[1];
  
  // 处理跨180°经线的经度计算
  let lonMid;
  if (Math.abs(lon2 - lon1) > 180) {
    const delta = (lon2 + 360 - lon1) / 2;
    lonMid = (lon1 + delta) % 360;
    lonMid = lonMid > 180 ? lonMid - 360 : lonMid;
  } else {
    lonMid = (lon1 + lon2) / 2;
  }
  
  // 纬度直接取平均值(沿纬线的中点纬度与端点一致)
  const latMid = (lat1 + lat2) / 2;
  
  console.log(`${lonMid}, ${latMid}`);
})

说明

  • 对于沿纬线的线段,其中点纬度必然与端点纬度相同,无需复杂计算。
  • 如果确实需要测地线中点,那么之前的结果是正确的,这是椭球测地线的固有特性。

内容的提问来源于stack exchange,提问作者Eric G

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:07:50