admin管理员组文章数量:1391798
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
2 Answers
Reset to default 4This 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];
本文标签: javascriptHow to add markers on cesium terrainStack Overflow
版权声明:本文标题:javascript - How to add markers on cesium terrain - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744770004a2624280.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论