SampleTerrain elevation changes with view pitch

Below is a sand castle snippet. If you run the snippet it zooms to an area Called Mount Prevost. The summit is about 740m high.

If you view it looking straight down at earth and you click on the summit the elevation shown (in the debug console) is about right - Give or take normal errors in the terrain model. However, if you change the pitch and heading and click on the summit again the elevation shown changes.

It seems maybe like I’m not getting the right Lat/long from the mouse when I change the camera view.

I really don’t understand what is going. Can anyone explain this to me.

var terrain = Cesium.Terrain.fromWorldTerrain();

const viewer = new Cesium.Viewer('cesiumContainer', {
  terrain: terrain,
  animation: false,
  timeline: false
});
      
var view = 
  {
  latitude: 48.830054,
  longitude: -123.758148,
  height: 1500,
  heading: 300,
  pitch: -45,
  roll: 0
};


var position = new Cesium.Cartesian3.fromDegrees(view.longitude, view.latitude, view.height);
var orientation = { heading: Cesium.Math.toRadians(view.heading), pitch: Cesium.Math.toRadians(view.pitch), roll: Cesium.Math.toRadians(view.roll) };

viewer.camera.setView({
  destination: position,
  orientation: orientation
});

viewer.canvas.addEventListener('click', async function (e) {

  var mousePosition = new Cesium.Cartesian2(e.clientX, e.clientY);

  var ellipsoid = viewer.scene.globe.ellipsoid;
  var cartesian = viewer.camera.pickEllipsoid(mousePosition, ellipsoid);
  if (cartesian) {

    var cartographic = ellipsoid.cartesianToCartographic(cartesian);
    var mouseLon = Cesium.Math.toDegrees(cartographic.longitude);
    var mouseLat = Cesium.Math.toDegrees(cartographic.latitude);
    var mouseHeight = Cesium.Math.toDegrees(cartographic.height);

    var mousePoint = Cesium.Cartographic.fromDegrees( mouseLon, mouseLat);
    const positions = [
      mousePoint
    ];
    const updatedPositions = await Cesium.sampleTerrainMostDetailed( viewer.terrainProvider, positions);

    var camera = viewer.scene.camera;
    var position = camera.positionCartographic;
    var orientation = { heading: 0, roll: 0, pitch: 0 };
    orientation.heading = camera.heading;
    orientation.pitch = camera.pitch;
    orientation.roll = camera.roll;
    var view = {
      latitude: Cesium.Math.toDegrees(position.latitude),
      longitude: Cesium.Math.toDegrees(position.longitude),
      height: positions.height,
      heading: Cesium.Math.toDegrees(orientation.heading),
      pitch: Cesium.Math.toDegrees(orientation.pitch),
      roll: Cesium.Math.toDegrees(orientation.roll),
    }
    var json = {
      "title": "new pin",
      "pin": {
        "latitude": mouseLat,
        "longitude": mouseLon,
        "elevation1": updatedPositions[0].height,
      },
      "view": view
    }
    navigator.clipboard.writeText(JSON.stringify(json));

    console.log(JSON.stringify(json));
  } else {
  }
}, false);

Hmmm… so I tried a different approach and getPickRay works exactly as I expect.

I guess I don’t understand what sampleTerrainMostDetailed is doing, or meant to do. I’ve read in these forums that sampleTerrainMostDetailed is the function to use for most accurate height. But seems not to be the case for me. Here is the code that does exactly what I was trying to do

  // Your access token can be found at: https://ion.cesium.com/tokens.
  // This is the default access token from your ion account

  Cesium.Ion.defaultAccessToken = 'xxx';
  var terrain = Cesium.Terrain.fromWorldTerrain();

  // Initialize the Cesium Viewer in the HTML element with the `cesiumContainer` ID.
  const viewer = new Cesium.Viewer('cesiumContainer', {
    terrain: terrain,
    animation: false,
    timeline: false
  });
  //viewer.extend(Cesium.viewerCesiumInspectorMixin);

  var views = [
    {
    latitude: 48.830054,
    longitude: -123.758148,
    height: 1000,
    heading: 300,
    pitch: -45,
    roll: 0
  },
  {
    latitude: 48.830054,
    longitude: -123.758148,
    height: 1000,
    heading: 300,
    pitch: -30.5,
    roll: 0
  },
  {
    latitude: 48.830054,
    longitude: -123.758148,
    height: 1000,
    heading: 300,
    pitch: -15,
    roll: 0
  }
]
  var view = views[0];


  var position = new Cesium.Cartesian3.fromDegrees(view.longitude, view.latitude, view.height);
  var orientation = { heading: Cesium.Math.toRadians(view.heading), pitch: Cesium.Math.toRadians(view.pitch), roll: Cesium.Math.toRadians(view.roll) };

  viewer.dataSources.add(Cesium.GeoJsonDataSource.load('/pins/pins.json', {
    stroke: Cesium.Color.HOTPINK,
    fill: Cesium.Color.PINK,
    strokeWidth: 3,
    markerSymbol: '?'
  }));

  viewer.camera.setView({
    destination: position,
    orientation: orientation
  });


  var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
  handler.setInputAction(function (event) {
  var ray = viewer.camera.getPickRay(event.position);
  var mousePosition = viewer.scene.globe.pick(ray, viewer.scene);
  if (Cesium.defined(mousePosition)) {
      var cartographic = Cesium.Cartographic.fromCartesian(mousePosition);
      var mouseLat = Cesium.Math.toDegrees(cartographic.latitude);
      var mouseLon = Cesium.Math.toDegrees(cartographic.longitude);
      var mouseHeight = cartographic.height;

      var camera = viewer.scene.camera;
      var position = camera.positionCartographic;
      var orientation = { heading: 0, roll: 0, pitch: 0 };
      orientation.heading = camera.heading;
      orientation.pitch = camera.pitch;
      orientation.roll = camera.roll;
      var view = {
        latitude: Cesium.Math.toDegrees(position.latitude),
        longitude: Cesium.Math.toDegrees(position.longitude),
        height: position.height,
        heading: Cesium.Math.toDegrees(orientation.heading),
        pitch: Cesium.Math.toDegrees(orientation.pitch),
        roll: Cesium.Math.toDegrees(orientation.roll),
      }
      var json = {
        "title": "new pin",
        "pin": {
          "latitude": mouseLat,
          "longitude": mouseLon,
          "height": mouseHeight
        },
        "view": view
      }
      navigator.clipboard.writeText(JSON.stringify(json));

      console.log(JSON.stringify(json));

    }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);