Search code examples
cesiumjs

CesiumJS: How can I get the midpoint of a line on the globe?


I have a sandcastle

The relevant code is:

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}` );
})

The output is:

180, 49.11979677835345
180, 44.111242494938004

The latitudes are wrong. The first one should be 45 instead of 49.11 and the second should be 40 instead of 44.11.

I have also tried using the Cesium.Cartesian3.midpoint and Cesium.Cartesian3.lerp( endpoints[0], endpoints[1], .5, midpoint ) functions directly, but they produce the same result.

I have also tried:

  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}` );

but the result is the same.

What needs to change so this will work? Or, I a misunderstanding some fundamental concept?


Solution

  • The concept I was missing was the difference between a geodesic and rhumb line.

    from Great Circles, Geodesics, and Rhumb Lines:

    A great circle is the shortest path between two points along the surface of a sphere, a geodesic is the shortest path between two points on a curved surface, and a rhumb line is a curve that crosses each meridian at the same angle

    Cesium provides some rhumb line computations with EllipsoidRhumbLine.

    I can get the midpoint I was expecting with interpolateUsingFraction

    Sandcastle