Cesium.CesiumMath.toDegrees() unable to read property from a Cartesian position

Hi All,

I am a student completing a masters dissertation at UCL in London.

I’m using Cesium to try and display and (hopefully) perform analysis on a 3D City Mesh (3D tileset .b3dm).

I am new to Cesium and have limited programming experience so please forgive any naivety in this post.

At the moment I am trying to get the position of where a user clicks with the left mouse button. This is with the view to add two points and then measure the distance between them, to say measure the height of a building in the model/mesh.

I have so far been able to get the position in Cartesian coordinates using scene.pick() and then convert these to Cartographic coordinates using Cesium.Cartographic.fromCartesian().

However, when the user clicks on a point on the model I want the coordinates they have click on to be displayed in a label.

I am trying to use Cesium.CesiumMath.toDegrees(‘The cartographic position’.longitude/latitude) to extract the long and lat values to display in the label.

When I do this I am getting an error in the console when I do this saying 'Uncaught TypeError: Cannot read property ‘toDegrees of undefined’.

To me this seems to suggest that the Cartogaphic position returned from Cesium.Cartographic.fromCartesian() is giving the type error when this is used with Cesium.CesiumMath.toDegrees()?

I know in the Cesium Docs it states when using scene.pick() method on a 3D Tiles Tileset a Cesium3DTileFeature object will be returned so maybe this could be the issue too?

Any help would be highly appreciated.

Cheers,

Chris

Please see my code below along with the console messages. Debugging being done in Sandcastle running locally currently.

var viewer = new Cesium.Viewer(‘cesiumContainer’);

var scene = viewer.scene;

// Creates an empty variable for the click event handler and the cartogrpahic position of mouse click

var handler;

var cartographic;

// Adds variables to record the mouse position

var mousePosition;

Sandcastle.addDefaultToolbarButton(‘Show Cartographic Position on Mouse Over’, function() {

var entity = viewer.entities.add({

label : {

show : false,

showBackground : true,

font : ‘14px monospace’,

horizontalOrigin : Cesium.HorizontalOrigin.LEFT,

verticalOrigin : Cesium.VerticalOrigin.TOP,

pixelOffset : new Cesium.Cartesian2(1, 0),

heightReference : Cesium.HeightReference.RELATIVE_TO_GROUND

}

});

// Mouse over the globe to see the cartographic position

handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);

handler.setInputAction(function(click) {

var pickedLocation = scene.pick(click.position);

var cartesian = scene.pickPosition(click.position);

console.log("Cartesian Location is: " + cartesian); // Outputs the location of the click to the console to hceck it is correct

// Creates a if loop to check that the pickPosition method is supported and the pickedPosition variable contains a value

if (scene.pickPositionSupported && Cesium.defined(cartesian)) {

var cartographic = Cesium.Cartographic.fromCartesian(cartesian);

console.log("Cartographic location is: " + cartographic);

var longitude = Cesium.CesiumMath.toDegrees(cartographic.longitude);

var latitude = Cesium.CesiumMath.toDegrees(cartographic.latitude);

var altitude = cartographic.height;

var altitudeString = Math.round(altitude).toString();

entity.position = cartesian;

entity.label.show = true;

entity.label.text =

'Lon: ’ + (longitude) +

'\nLat: ’ + (latitude) +

'\nHeight: ’ + (altitudeString);

} else {

entity.label.show = false;

}

}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

});

viewer.terrainProvider = new Cesium.CesiumTerrainProvider({

url : ‘https://assets.agi.com/stk-terrain/v1/tilesets/world/tiles’,

requestWaterMask : true,

requestVertexNormals : true

});

// Add tileset to Cesium

var tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({

url : ‘http://localhost:8080/gx_data

// shadows : ShadowMode.CAST_ONLY

}));

// Defines a function to fly to Bath

function goToBath() {

Sandcastle.declare(goToBath);

viewer.camera.flyTo({

destination : Cesium.Cartesian3.fromDegrees(-2.354662, 51.391676, 5000)

});

}

// Adds a button for the fly to Bath method

Sandcastle.addToolbarButton(‘Go To Bath’, function(){

goToBath();

Sandcastle.highlight(goToBath);

});

// Adds a shadow toggle button to the viewer

Sandcastle.addToggleButton(‘Shadows’, viewer.shadows, function(checked) {

viewer.shadows = checked;

});

Console Messages:

Documentation not available. Please run the “generateDocumentation” build script to generate Cesium documentation.
This application is using Cesium’s default Bing Maps key. Please create a new key for the application as soon as possible and prior to deployment by visiting https://www.bingmapsportal.com/, and provide your key to Cesium by setting the Cesium.BingMapsApi.defaultKey property before constructing the CesiumWidget or any other object that uses the Bing Maps API.
This tile uses a lowercase refine “replace”. Instead use “REPLACE”.
This b3dm header is using the legacy format [batchLength] [batchTableByteLength]. The new format is [featureTableJsonByteLength] [featureTableBinaryByteLength] [batchTableJsonByteLength] [batchTableBinaryByteLength] from https://github.com/AnalyticalGraphicsInc/3d-tiles/blob/master/TileFormats/Batched3DModel/README.md.
The glTF in this b3dm uses the semantic BATCHID. Application-specific semantics should be prefixed with an underscore: _BATCHID.
Cartesian Location is: (3984441.506698334, -163139.4569894213, 4961186.248175986) // The Cartesian position returned
Cartographic location is: (-0.04092126458066583, 0.897022717868518, 78.8359452697764) // The cartographic position returned
Uncaught TypeError: Cannot read property ‘toDegrees’ of undefined (on line 36) // The error received

Cesium.CesiumMath.toDegrees should be Cesium.Math.toDegrees. I think that will fix it.

Hi Sean,

It worked! Thanks a lot for your help, really appreciate it.

Apologies if it was a bit of a stupid question, I read through the Cesium docs but obviously not closely enough!

Hope you have a lovely weekend!

Cheers,

Chris

Yes, the docs are sort of ambigious on which is the correct way to use. The examples on the following page have the correct format but not the titles.

https://cesiumjs.org/Cesium/Build/Documentation/CesiumMath.html?classFilter=ces

The docs are a bit ambiguous in this regard, especially since classes like Cesium3DTileset for instance still retain the Cesium prefix. I’ve opened issue #6233.

Thanks,

Gabby

Thanks for bringing this up! The fixes to the documentation will be included in the Cesium 1.43 release available on March 1st.