Dynamic polygons callback sets heights of previous points to 0.

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

I’m trying to dynamically draw polygons as the user moves their mouse. However, whenever a new point is selected after the 2nd point, it seems to reset the heights of all previous points to 0, while keeping the height of the most recent point. I’m not editing the height of the points anywhere, so I’m not sure what could be causing this. I believe it might be something to do with the callback function, since the heights of points are not edited if the callback function is replaced with static data for the polygon positions.

Below I’ve included code that is compatible with sandcastle to help debugging. I’ve also added helper functions for logging the heights of all points in the array to the console and to fetch the maximum height of the points.

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

var viewer = new Cesium.Viewer(‘cesiumContainer’);
viewer.terrainProvider = Cesium.createWorldTerrain();
var polyShapePoints = ;
var mousePoint = null;
var polyShapeEntity = null;

function getMaxHeight(points) {
var maxHeight = Cesium.Cartographic.fromCartesian(points[0]).height;
points.forEach((point) => {
if (Cesium.Cartographic.fromCartesian(point).height > maxHeight) {
maxHeight = Cesium.Cartographic.fromCartesian(point).height;
}
});
return maxHeight;
}

function logHeights(points) {
points.forEach((point) => {
console.log(Cesium.Cartographic.fromCartesian(point));
console.log("point height: " + Cesium.Cartographic.fromCartesian(point).height);
});
}

function addEnt() {
var maxHeight = getMaxHeight(polyShapePoints);
console.log("max height: " + maxHeight);
polyShapeEntity = viewer.entities.add({
polygon: {
hierarchy: new Cesium.CallbackProperty(function() {
return […polyShapePoints, mousePoint];
}, false),
material: Cesium.Color.WHITE,
height: maxHeight
}
});
}

new Cesium.ScreenSpaceEventHandler(viewer.canvas).setInputAction(function (event) {
var cartesianPosition = viewer.scene.pickPosition(event.position);
if (polyShapePoints.length === 0) {
polyShapePoints.push(cartesianPosition);
addEnt();
} else {
viewer.entities.remove(polyShapeEntity);
polyShapePoints.push(cartesianPosition);
addEnt();
}

logHeights(polyShapePoints);

}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

new Cesium.ScreenSpaceEventHandler(viewer.canvas).setInputAction(function (event) {
mousePoint = viewer.scene.pickPosition(event.endPosition);
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

``

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

I’m trying to dynamically draw a polygon as the user moves their mouse and left clicks to add permanent positions

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

Cesium Version: 1.52

OS: Ubuntu

Browser: Chrome

Thanks for providing your code! It looks like the act of creating a polygon will mutate the provided points.You can see it happens here:

https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Core/PolygonGeometryLibrary.js#L227

Where the engine will scale the points up to the surface, and store the result in the same location. I think this is intentionally to prevent too many objects from being created all the time. You can prevent it from doing this scaling by setting perPositionHeight to true:

https://cesiumjs.org/Cesium/Build/Documentation/PolygonGraphics.html?classFilter=PolygonGr#perPositionHeight

Alternatively, you could just clone all the points before you send them to the polygon to keep an original copy.

I hope this helped! I also want to make sure you’ve seen the the drawing on terrain Sandcastle, which also has an example of dynamically creating a polygon on click:

What I did there to make it more responsive is use one callback property that doesn’t change, and continually add points to it. This avoids creating a new polygon on each click which will have a few second lag because it’s done asynchronously.