2017-02-15 41 views
2

爲了在銫地形上添加標記,我使用sampleTerrain函數來獲取高度。如何在銫地形上添加標記

我可以在山頂上添加標記,但標記位置遠離鼠標點擊。我怎樣才能在銫地形上添加標記,這樣標記將被精確添加到點擊位置?

僅供參考我會把我的代碼在這裏:

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); 

回答

1

這條線是你的問題:

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

pickEllipsoid功能挑選過的WGS84橢球的值(認爲「類似海平面「但不要將它與實際的MSL混淆)。這個功能永遠不會從山頂返回一個點。

當然,您通過調用sampleTerrain來增強此功能,這很好,但不能解決問題。這個「挑號」錯過了山頂,最終在遠離山下和山後的橢球體上選取了一個點,而不是靠近用戶認爲他們點擊的地方。

您還可以使用另一個函數viewer.scene.pickPosition,它將通過從WebGL的深度緩衝區中讀取位置來返回位置。這意味着該功能在近距離時纔可靠,例如當攝像機接近足以看到單個山脈時,不會縮小到全球範圍。但它確實讓你選擇山頂等。

這是一個演示,使用代碼從Picking Demo解除,並修改後在珠穆朗瑪峯工作。點擊底部的「運行代碼片段」。此後,您可能還想單擊「完整頁面」彈出式鏈接。

var terrain = Cesium.createDefaultTerrainProviderViewModels(); 
 
var viewer = new Cesium.Viewer('cesiumContainer', { 
 
    navigationInstructionsInitiallyVisible: false, 
 
    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);
html, body, #cesiumContainer { 
 
    width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; 
 
    font-family: sans-serif; 
 
}
<link href="http://cesiumjs.org/releases/1.30/Build/Cesium/Widgets/widgets.css" 
 
     rel="stylesheet"/> 
 
<script src="http://cesiumjs.org/releases/1.30/Build/Cesium/Cesium.js"> 
 
</script> 
 
<div id="cesiumContainer"></div>

+0

感謝!!!!!! BTW是否有可能沒有baseLayerPicker? –

+0

是的,你可以關閉baseLayerPicker,但是你應該使用地形來源,這樣山脈就可以繼續使用。當地形不見時,Scene.pickPosition將無法正常工作。 – emackey

+0

我使用https://assets.agi.com/stk-terrain/world的地形來源,並且在baseLayerPicker = false時不起作用 –

1

我用的是:

 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]; 
相關問題