How to calculate polygon area and line length on terrain

1. A concise explanation of the problem you’re experiencing.

How to calculate polygon area and line length on terrain?

I am using Sandcastle example for drawing on terrain.

I am interested to calculate polygon area and line length as shown in images below. After calculating area and length I am interested to save polygon in geojson format.

Anyone tell me how to calculate area of polygon and how to save polygon in geojson file in server?

2. A minimal code example. If you’ve found a bug, this helps us reproduce and repair it.

I am trying below code to calculate area and length of polygon and line.
Could you please check error…

Uncaught DeveloperError: normalized result is not a number
Error
at new DeveloperError (http://localhost/cesiumjs/Source/Core/DeveloperError.js:43:19 )
at Function.Cartesian3.normalize (http://localhost/cesiumjs/Source/Core/Cartesian3.js:421:19 )
at Function.Cartographic.fromCartesian (http://localhost/cesiumjs/Source/Core/Cartographic.js:132:24 )
at startup (:109:50)
at Object.execCb (http://localhost/cesiumjs/ThirdParty/requirejs-2.1.20/require.js:1678:33 )
at Module.check (http://localhost/cesiumjs/ThirdParty/requirejs-2.1.20/require.js:878:51 )
at Module. (http://localhost/cesiumjs/ThirdParty/requirejs-2.1.20/require.js:1128:34 )
at http://localhost/cesiumjs/ThirdParty/requirejs-2.1.20/require.js:131:23
at http://localhost/cesiumjs/ThirdParty/requirejs-2.1.20/require.js:1178:21
at each (http://localhost/cesiumjs/ThirdParty/requirejs-2.1.20/require.js:56:31) (on line 421 of http://localhost/cesiumjs/Source/Core/Cartesian3.js)

var viewer = new Cesium.Viewer(‘cesiumContainer’, {

selectionIndicator : false,

infoBox : false,

terrainProvider : Cesium.createWorldTerrain()

});

viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

function createPoint(worldPosition) {

var point = viewer.entities.add({

position : worldPosition,

point : {

color : Cesium.Color.WHITE,

pixelSize : 5,

heightReference: Cesium.HeightReference.CLAMP_TO_GROUND

}

});

return point;

}

var drawingMode = ‘line’;

function drawShape(positionData) {

var shape;

if (drawingMode === ‘line’) {

shape = viewer.entities.add({

polyline : {

positions : positionData,

clampToGround : true,

width : 3

}

});

}

else if (drawingMode === ‘polygon’) {

shape = viewer.entities.add({

polygon: {

hierarchy: positionData,

material: new Cesium.ColorMaterialProperty(Cesium.Color.WHITE.withAlpha(0.7))

}

});

}

return shape;

}

var activeShapePoints = ;

var activeShape;

var floatingPoint;

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

handler.setInputAction(function(event) {

// We use viewer.scene.pickPosition here instead of viewer.camera.pickEllipsoid so that

// we get the correct point when mousing over terrain.

var earthPosition = viewer.scene.pickPosition(event.position);

// earthPosition will be undefined if our mouse is not over the globe.

if (Cesium.defined(earthPosition)) {

if (activeShapePoints.length === 0) {

floatingPoint = createPoint(earthPosition);

activeShapePoints.push(earthPosition);

var dynamicPositions = new Cesium.CallbackProperty(function () {

return activeShapePoints;

}, false);

activeShape = drawShape(dynamicPositions);

}

activeShapePoints.push(earthPosition);

createPoint(earthPosition);

}

}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

handler.setInputAction(function(event) {

if (Cesium.defined(floatingPoint)) {

var newPosition = viewer.scene.pickPosition(event.endPosition);

if (Cesium.defined(newPosition)) {

floatingPoint.position.setValue(newPosition);

activeShapePoints.pop();

activeShapePoints.push(newPosition);

}

}

}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

// Redraw the shape so it’s not dynamic and remove the dynamic shape.

function terminateShape() {

activeShapePoints.pop();

drawShape(activeShapePoints);

viewer.entities.remove(floatingPoint);

viewer.entities.remove(activeShape);

floatingPoint = undefined;

activeShape = undefined;

activeShapePoints = ;

}

handler.setInputAction(function(event) {

terminateShape();

}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

var options = [{

text : ‘Draw Lines’,

onselect : function() {

terminateShape();

drawingMode = ‘line’;

}

}, {

text : ‘Draw Polygons’,

onselect : function() {

terminateShape();

drawingMode = ‘polygon’;

}

}];

Sandcastle.addToolbarMenu(options);

// Zoom in to an area with mountains

viewer.camera.lookAt(Cesium.Cartesian3.fromDegrees(-122.2058, 46.1955, 1000.0), new Cesium.Cartesian3(5000.0, 5000.0, 5000.0));

viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);

var startCartographicPoint = Cesium.Cartographic.fromCartesian(activeShapePoints);

var endCartographicPoint = Cesium.Cartographic.fromCartesian(activeShapePoints);

var ellipsoidGeodesic = new Cesium.EllipsoidGeodesic(startCartographicPoint,

endCartographicPoint );

var distance = ellipsoidGeodesic.surfaceDistance;

var distanceInKm = distance * 0.001;

console.log(‘Geodesic distance: ’ + distanceInKm + ’ Km’);

4. The Cesium version you’re using, your operating system and browser.

Cesium 1.47, Chrome, Window 8.1

Hi Akshay,

Have you considered using the turf.js library? It has functions to do these things.

http://turfjs.org/

Patrick

Thanks for the link.

Hi Akshay!

I am trying to do the same but without success. Did you find a solution for the measurement issue? I am not a Javascrip specialist, have you tried with Turfjs ?

See my 3D webmap and click on "Börja rita" ...

Best regards!
Abel Gonzalez

I would check out turf.js for any of this type of math. They have some great helper functions that can calculate this for you.

j