Use of mouse to define position and size of 3D figures on the map

Hi! I’m working on the development of a number of functions that should allow users to put 3D figures on the map by clicking and moving the mouse. The standard technology for that is the usage of “Cesium.CallbackProperty” that works well in most cases and I cannot understand why “polylineVolume” doesn’t follow the rule.

The code consists of three parts: firstly a global object is defined to enable common acceess to the parameters of the figure, secondly a polyline figure with call backs is declared, and lastly input actions are described to define mouse event instructions.

Right after the launch of the code the polyline appears as expected, but when I try to change its positon and size with mouse, the polyline object disappears and never shows up again.

Thank you in advance,

Oleg

//------------------------------- START VIEWER ---------------------------------

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

infoBox: true,

baseLayerPicker: false,

navigationHelpButton: false,

geocoder: true,

animation: false,

timeline: false,

homeButton: false,

vrButton: true,

scene3DOnly : true,

shadows: true,

terrainShadows : Cesium.ShadowMode.ENABLED

});

//---------------------------- SET UP ENVIRONMENT ------------------------------

var terrainProvider = new Cesium.CesiumTerrainProvider({

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

requestVertexNormals: true,

requestWaterMask: true

});

var scene = viewer.scene;

var globe = scene.globe;

var skyAtmosphere = scene.skyAtmosphere;

viewer.terrainProvider = terrainProvider;

globe.enableLighting = true;

globe.depthTestAgainstTerrain = true;

skyAtmosphere.brightnessShift = 1.0;

skyAtmosphere.saturationShift = 0.33;

viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(15.15, 25, 3000)});

//-------------------------------- Parameters ----------------------------------

var tubeParameters = {tubeEnds: [15, 25, 530, 15.3, 25, 530], r: 100};

//--------------------------------- Polyline -----------------------------------

function computeCircle(radius) {

var positions = ;

for (var i = 0; i < 360; i = i + 5) {

var radians = Cesium.Math.toRadians(i);

positions.push(new Cesium.Cartesian2(radius * Math.cos(radians), radius * Math.sin(radians)));

}

return positions;

}

var redTube = viewer.entities.add({

name : ‘Red tube’,

polylineVolume : {

positions : new Cesium.CallbackProperty(function() {

return Cesium.Cartesian3.fromDegreesArrayHeights(tubeParameters.tubeEnds);

}, false),

shape : new Cesium.CallbackProperty(function() {

return computeCircle(tubeParameters.r);

}, false),

shape : computeCircle(100),

material : Cesium.Color.RED

}

});

//-------------------------------- Input Actions -------------------------------

viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);

viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);

var tubeBuilt = true;

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

handlerA.setInputAction(

function (click) {

tubeBuilt = !tubeBuilt;

if(!tubeBuilt){

redTube.polylineVolume.shape = computeCircle(0);

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

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

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

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

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

var altitude = cartographic.height;

tubeParameters.tubeEnds[0] = longitude;

tubeParameters.tubeEnds[1] = latitude;

tubeParameters.tubeEnds[2] = altitude;

}

}

}, Cesium.ScreenSpaceEventType.RIGHT_CLICK

);

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

handlerB.setInputAction(

function (movement) {

if(!tubeBuilt){

var cartesian = scene.pickPosition(movement.endPosition);

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

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

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

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

var altitude = cartographic.height;

tubeParameters.tubeEnds[3] = longitude;

tubeParameters.tubeEnds[4] = latitude;

tubeParameters.tubeEnds[5] = tubeParameters.tubeEnds[2];

var pointA = Cesium.Cartesian3.fromDegrees(tubeParameters.tubeEnds[0], tubeParameters.tubeEnds[1], tubeParameters.tubeEnds[2]);

var pointB = Cesium.Cartesian3.fromDegrees(tubeParameters.tubeEnds[3], tubeParameters.tubeEnds[4], tubeParameters.tubeEnds[5]);

tubeParameters.r = Cesium.Cartesian3.distance(pointA, pointB);

}

}

}, Cesium.ScreenSpaceEventType.MOUSE_MOVE

);

Hi Oleg,

It looks like your polyline volume is disappearing because in your right click handler, you call “redTube.polylineVolume.shape = computeCircle(0);”, but computeCircle takes a radius, so your polyline takes a radius of 0. You probably want to set that to tubeParameters.r.

Also, in redTube, you declare the shape parameter twice – one of them should be deleted.

Hope that helps!

  • Rachel

Hi Rachel,
Thank you for the help! Calling “redTube.polylineVolume.shape = computeCircle(0);” was done on purpose, since by the first right click one indicates where the pipe is to begin, and then by moving off the mouse the user defines the length of the pipe to make it appear. Declaration of the shape twice is the bug, indeed. In the end, I added the line “redTube.polylineVolume.shape = computeCircle(tubeParameters.r);” in MOUSE_MOVE handler, so now it works as expected.

Br, Oleg