[英]How to add markers on cesium terrain
為了在 cesium 中的地形上添加標記,我使用了sampleTerrain
函數來獲取高度。
我可以在山頂上添加一個標記,但該標記離鼠標點擊很遠。 如何在 Cesium 地形上添加標記,以便將標記准確添加到單擊位置?
作為參考,我將把我的代碼放在這里:
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);
這一行是你的問題:
let positionCartesian3 = this.cesium.viewer.camera.pickEllipsoid(event.position);
pickEllipsoid
函數從 WGS84 橢球pickEllipsoid
取值(認為“類似於海平面”,但不要將其與實際 MSL 混淆)。 這個函數永遠不會從山頂返回一個點。
當然,您通過調用sampleTerrain
增強了此功能,這很好,但並沒有解決問題。 “pick”沒有到達山頂,最終在遠離山峰下方和后方的橢圓體上挑選一個點,而不是用戶認為他們點擊的位置附近。
您可以使用另一個函數viewer.scene.pickPosition
,它將通過從 WebGL 的深度緩沖區中讀取位置來返回位置。 這意味着該功能僅在近距離時可靠,例如當相機足夠近以看到單個山脈時,而不是縮小到整個地球。 但它確實讓你選擇山頂之類的。
這是一個 Sandcastle 演示。 它使用從Picking Demo 中提取並經過修改以在珠穆朗瑪峰上工作的代碼。
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);
我用過:
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];
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.