Place object at left click location

I have not had time to track down what changed. We have had code that places an ellipse at the location clicked by the user and then draws a line between that location and the next click location. This same code now places the ellipse quite some distance from where the user clicks, and I can’t figure out why.

How should I get the location the user clicks in order to draw an object at that location? Here’s the code we’ve been using:

cesiumScreenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
cesiumScreenSpaceEventHandler.setInputAction(measureToolPositionEventListener, Cesium.ScreenSpaceEventType.LEFT_DOWN);

measureToolPositionEventListener = function(movement) {
    if (blnMeasureToolLineDrawn) clearMeasureTool();
    
    if (!blnMeasureToolPt1Defined) {
        
        var ellipsoid = scene.globe.ellipsoid;
        var cartesian = scene.camera.pickEllipsoid(movement.position, ellipsoid);
        if (cartesian) {
            measureToolStartCartographic = ellipsoid.cartesianToCartographic(cartesian);
            dblMeasureToolPt1_Lat = Cesium.Math.toDegrees(measureToolStartCartographic.latitude); 
            dblMeasureToolPt1_Lon = Cesium.Math.toDegrees(measureToolStartCartographic.longitude);
            blnMeasureToolPt1Defined = true;
//            console.log("Pt1 = " + Cesium.Math.toDegrees(startCartographic.latitude).toFixed(6) + ", " + Cesium.Math.toDegrees(startCartographic.longitude).toFixed(6));
        }
        
        var distFromCamera = 1000;
        try {
            distFromCamera = cesiumDistance( new Cesium.Cartesian3.fromDegrees(dblMeasureToolPt1_Lon, dblMeasureToolPt1_Lat), scene.camera.position );
//            console.log("distFromCamera = " + distFromCamera);
        }
        catch (ex) {
            console.log("Error calculating distFromCamera in measureToolPositionEventListener.  Error = " + ex.toString());
        }
        
        var ptSize = distFromCamera / 300;
        
        measureToolFirstPt = cesiumViewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(dblMeasureToolPt1_Lon, dblMeasureToolPt1_Lat),
            name: "Measure tool first point",
            ellipse: {
                semiMinorAxis : ptSize,
                semiMajorAxis : ptSize,
                material : Cesium.Color.BLUE.withAlpha(1.0),
                clampToGround: true
            }
        });
        
    }
    else {
        
        var ellipsoid = scene.globe.ellipsoid;
        var cartesian = scene.camera.pickEllipsoid(movement.position, ellipsoid);
        if (cartesian) {
            measureToolEndCartographic = ellipsoid.cartesianToCartographic(cartesian);
            dblMeasureToolPt2_Lat = Cesium.Math.toDegrees(measureToolEndCartographic.latitude); 
            dblMeasureToolPt2_Lon = Cesium.Math.toDegrees(measureToolEndCartographic.longitude);
            blnMeasureToolPt2Defined = true;
//            console.log("Pt2 = " + Cesium.Math.toDegrees(endCartographic.latitude).toFixed(6) + ", " + Cesium.Math.toDegrees(endCartographic.longitude).toFixed(6));
        }

    }
    
    if (blnMeasureToolPt1Defined && blnMeasureToolPt2Defined) {
        
        try {
            if (cesiumViewer.entities.contains(measureToolFirstPt)) {
                cesiumViewer.entities.remove(measureToolFirstPt);
            }
        }
        catch (e) {}
        
        // Add a polyline to the scene.
        measureToolLine = cesiumViewer.entities.add({
            polyline: {
                positions: Cesium.Cartesian3.fromDegreesArray([dblMeasureToolPt1_Lon, dblMeasureToolPt1_Lat, dblMeasureToolPt2_Lon, dblMeasureToolPt2_Lat], Cesium.Ellipsoid.WGS84),
                width: 3,
                material: Cesium.Color.BLUE,
                clampToGround: true
            }
        });
        
        updateMeasureToolLabel();
        
        blnMeasureToolLineDrawn = true;
        
    }
    
};

Have you tried pickPosition? This forum discussion may help:

I’m not sure why your code stopped working. Have you updated to a new Cesium version recently?

I update to the latest version of Cesium every month because we regularly have the map tiles stop working if we don’t keep up with the latest version. However, I don’t know when this stopped working.

To be clear I get a value returned on the click event, but the location is not where the user clicks… for some reason it is offset above and to the left of the click location. And the location returned is different depending on how the globe is tilted.

I did see that post, but I don’t know how to hook up that listener for a left click instead of the right click (contextmenu)?:

viewer.scene.canvas.addEventListener(‘contextmenu’, ...

The issue you are facing might be related to this post, although you had it to work before so it might be something new. Please open a new issue if needed.

I believe it’s

viewer.scene.canvas.addEventListener('click', (event) => {

Thank you for the response. After following several links I decided to try getting my cartesian point using scene.globe.pick which seems to resolve my issue.

var ray = cesiumViewer.camera.getPickRay(movement.position);
var cartesian = cesiumViewer.scene.globe.pick(ray, cesiumViewer.scene);

However, I have another similar issue I’m trying to resolve. We provide another feature where the user clicks on an aircraft and then clicks on a point on the ground to display a line (and the distance) between the 2. When I first click the ground the line appears to be in the correct location, but when I tilt the globe the line appears to move (as if the line is actually penetrating the ground).

The line is drawn and the points for the line are calculated as follows:

var ellipsoid = scene.globe.ellipsoid;
var cartesian = scene.camera.pickEllipsoid(movement.position, ellipsoid);
slantDistancePointCartographic = ellipsoid.cartesianToCartographic(cartesian);
dblSlantDistancePt_Lat = Cesium.Math.toDegrees(slantDistancePointCartographic.latitude); 
dblSlantDistancePt_Lon = Cesium.Math.toDegrees(slantDistancePointCartographic.longitude);
dblSlantDistancePt_Height = Cesium.Math.toDegrees(slantDistancePointCartographic.height);
    
slantDistanceLine = cesiumViewer.entities.add({
    polyline: {
        positions: new Cesium.CallbackProperty(getSlantDistancePoints()),
        width: 3,
        material: Cesium.Color.BLUE
    }
});


function getSlantDistancePoints() {
return function() {

try {
    
    var ft = getSelectedFlight();
    if (ft === null) return null;

    return Cesium.Cartesian3.fromDegreesArrayHeights([dblSlantDistancePt_Lon, dblSlantDistancePt_Lat, 0, ft.lastModelPos.LON, ft.lastModelPos.LAT, ft.lastModelPos.ALT * dblFEET_TO_METERS], Cesium.Ellipsoid.WGS84);

}
catch (ex) {
    return null;
}

};
}

I’ve also tried passing in the “height” property from the “slantDistancePointCartographic.height” but the line still appears to move on the ground when the globe is tilted.

Are you able to provide a shorten Sandcastle example of this issue?

Hi dzung,

I’ve created a Sandcastle example here. However, I can’t seem to get the example to run using the callback function (getSlantDistancePoints) that returns the points used to draw the polyline.

When you run the demo just click on the globe and a polyline will be drawn…

When you tilt the globe with the code as it is everything looks fine. So the problem must have to do with the callback function. I use the callback function because the aircraft the user selects by clicking on it is animated, so the aircraft’s location is constantly updating.

I’m not sure why I get the error when I try to use the callback function in Sandcastle. But this gives an idea of the code I’m using. And when the callback function is being used the polyline appears to move at/through the ground when the globe is tilted.

Could the line be moving because you are using the plane’s position, which as you mentioned is constantly updating, in the callback function?

I’m not sure what you mean, but I believe the answer is no. Here are a couple of screen shots. I’ve paused animation in our site so that the plane is not flying (and it’s out of the viewing area). When I click on the ground to draw the line the end of the line on the ground is located exactly where I click. However, if I tilt or spin the globe the end of the line at the ground “moves”. In the screen shots below I have only clicked on the ground one time to place the line (1st screen shot) then I spun the globe a little (2nd screen shot) then I tilted the globe a little (3rd screen shot).