javascript - How to add markers on cesium terrain - Stack Overflow

In order to add markers on terrain in cesium I used the sampleTerrain function to get the height.I'

In order to add markers on terrain in cesium I used the sampleTerrain function to get the height.

I'm able to add a marker on top of a mountain but the marker is located far from the mouse click. How can I add a marker on Cesium terrain so the marker will be added exactly in the clicked position?

For reference I'll put my code here:

async leftClickInputAction(event:{position: {x:number, y:number}}):Promise<any> {

let positionCartesian3 = this.cesium.viewer.camera.pickEllipsoid(event.position);
let positionCartographic = Cesium.Cartographic.fromCartesian(positionCartesian3);
await Cesium.sampleTerrain(this.cesium.viewer.terrainProvider, 9, [positionCartographic]);

let height = positionCartographic.height;
let cart3_with_height = Cesium.Cartesian3.fromRadians(positionCartographic.longitude, positionCartographic.latitude, positionCartographic.height );
let window_coordinates = this.cesium.calcService.toFixes7Obj(Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.cesium.viewer.scene,cart3_with_height));
positionCartesian3 = this.cesium.viewer.camera.pickEllipsoid(event.position);
positionCartographic = Cesium.Cartographic.fromCartesian(positionCartesian3);
positionCartographic.height = height;*/

let lngDeg:number = Cesium.Math.toDegrees(positionCartographic.longitude);
let latDeg:number = Cesium.Math.toDegrees(positionCartographic.latitude);
let position: [number, number, number] = [lngDeg, latDeg, positionCartographic.height];
let color:string = this.cesium.positionFormService.getSelectedColor();
let marker_picker = {position};
if(color != "blue") marker_picker['color'] = color;
this.cesium.queryParamsHelperService.addMarker(marker_picker);

In order to add markers on terrain in cesium I used the sampleTerrain function to get the height.

I'm able to add a marker on top of a mountain but the marker is located far from the mouse click. How can I add a marker on Cesium terrain so the marker will be added exactly in the clicked position?

For reference I'll put my code here:

async leftClickInputAction(event:{position: {x:number, y:number}}):Promise<any> {

let positionCartesian3 = this.cesium.viewer.camera.pickEllipsoid(event.position);
let positionCartographic = Cesium.Cartographic.fromCartesian(positionCartesian3);
await Cesium.sampleTerrain(this.cesium.viewer.terrainProvider, 9, [positionCartographic]);

let height = positionCartographic.height;
let cart3_with_height = Cesium.Cartesian3.fromRadians(positionCartographic.longitude, positionCartographic.latitude, positionCartographic.height );
let window_coordinates = this.cesium.calcService.toFixes7Obj(Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.cesium.viewer.scene,cart3_with_height));
positionCartesian3 = this.cesium.viewer.camera.pickEllipsoid(event.position);
positionCartographic = Cesium.Cartographic.fromCartesian(positionCartesian3);
positionCartographic.height = height;*/

let lngDeg:number = Cesium.Math.toDegrees(positionCartographic.longitude);
let latDeg:number = Cesium.Math.toDegrees(positionCartographic.latitude);
let position: [number, number, number] = [lngDeg, latDeg, positionCartographic.height];
let color:string = this.cesium.positionFormService.getSelectedColor();
let marker_picker = {position};
if(color != "blue") marker_picker['color'] = color;
this.cesium.queryParamsHelperService.addMarker(marker_picker);
Share Improve this question edited Feb 15, 2017 at 15:00 emackey 12.5k2 gold badges41 silver badges61 bronze badges asked Feb 15, 2017 at 13:04 Harel.LebelHarel.Lebel 2896 silver badges17 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

This line is your problem:

    let positionCartesian3 = this.cesium.viewer.camera.pickEllipsoid(event.position);

The pickEllipsoid function picks values off the WGS84 ellipsoid (think "similar to sea level" but don't confuse it with actual MSL). This function will never return a point from the top of a mountain.

Of course, you augmented this function by calling sampleTerrain, which is good but doesn't fix the problem. The "pick" misses the mountaintop, and ends up picking a spot on the ellipsoid far below and behind the mountain, not near where the user thought they clicked.

There's another function you can use, viewer.scene.pickPosition, that will return positions by reading them out of WebGL's depth buffer. This means the function is only reliable at close range, when the camera is near enough to see individual mountains for example, not zoomed out to the whole globe. But it does let you pick mountain tops and such.

Here's a Sandcastle demo. It uses code lifted from the Picking Demo and modified to work at Mount Everest.

var terrain = Cesium.createDefaultTerrainProviderViewModels();
var viewer = new Cesium.Viewer('cesiumContainer', {
    animation: false,
    timeline: false,
    geocoder : false,
    selectionIndicator : false,
    infoBox : false,
    terrainProviderViewModels: terrain,
    selectedTerrainProviderViewModel: terrain[1]
});

function lookAtMtEverest() {
    var target = new Cesium.Cartesian3(300770.50872389384, 5634912.131394585, 2978152.2865545116);
    var offset = new Cesium.Cartesian3(6344.974098678562, -793.3419798081741, 2499.9508860763162);
    viewer.camera.lookAt(target, offset);
    viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
}

lookAtMtEverest();

var labelEntity = viewer.entities.add({
    label : {
        show : false,
        showBackground : true,
        font : '14px monospace',
        horizontalOrigin : Cesium.HorizontalOrigin.LEFT,
        verticalOrigin : Cesium.VerticalOrigin.TOP,
        pixelOffset : new Cesium.Cartesian2(15, 0)
    }
});

var sceneModeWarningPosted = false;

// Mouse over the globe to see the cartographic position
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function(movement) {
    var foundPosition = false;
    var scene = viewer.scene;
    var pickedObject = scene.pick(movement.endPosition);
    if (scene.pickPositionSupported) {
        if (scene.mode === Cesium.SceneMode.SCENE3D) {
            var cartesian = viewer.scene.pickPosition(movement.endPosition);

            if (Cesium.defined(cartesian)) {
                var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
                var longitudeString = Cesium.Math.toDegrees(cartographic.longitude).toFixed(3);
                var latitudeString = Cesium.Math.toDegrees(cartographic.latitude).toFixed(3);
                var heightString = cartographic.height.toFixed(2);

                labelEntity.position = cartesian;
                labelEntity.label.show = true;
                labelEntity.label.text =
                    'Lon: ' + ('   ' + longitudeString).slice(-8) + '\u00B0' +
                    '\nLat: ' + ('   ' + latitudeString).slice(-8) + '\u00B0' +
                    '\nAlt: ' + ('   ' + heightString).slice(-7) + 'm';

                var camera = scene.camera;
                labelEntity.label.eyeOffset = new Cesium.Cartesian3(0.0, 0.0, camera.frustum.near * 1.5 - Cesium.Cartesian3.distance(cartesian, camera.position));

                foundPosition = true;
            }
        } else if (!sceneModeWarningPosted) {
            sceneModeWarningPosted = true;
            console.log("pickPosition is currently only supported in 3D mode.");
        }
    }

    if (!foundPosition) {
        labelEntity.label.show = false;
    }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

I used that :

     let ray = this.cesium.viewer.camera.getPickRay(event.position);
      let positionCartesian3 = this.cesium.viewer.scene.globe.pick(ray, this.cesium.viewer.scene);
      let positionCartographic = Cesium.Cartographic.fromCartesian(positionCartesian3);
      let lngDeg: number = Cesium.Math.toDegrees(positionCartographic.longitude);
      let latDeg: number = Cesium.Math.toDegrees(positionCartographic.latitude);
       position = [lngDeg, latDeg, positionCartographic.height];

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744770005a4592700.html

相关推荐

  • javascript - How to add markers on cesium terrain - Stack Overflow

    In order to add markers on terrain in cesium I used the sampleTerrain function to get the height.I'

    5小时前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信