![](/img/trans.png)
[英]Cesium - using camera to scale a polygon to match Lat-Lon positions while zoom-in/zoom-out
[英]Cesium how to scale a polygon to match Lat-Lon positions while zoom-in/zoom-out
我正在尋找Cesium Guru,以尋求所需的幫助。 我是Cesium的新手,但是我一直在使用教程和繼承的一些現有代碼。
在我的Cesium應用中,輸入我的地址,然后視圖放大到我的街道。 好極了! 然后將其放大,以便可以在房屋周圍繪制多邊形。 現有的代碼可以很好地做到這一點。 但是, 當我縮小然后再次放大時,我的多邊形不會一直保持到我家的Lat-Lon位置 。
Cesium是否包含將像素縮放為經緯度坐標的實用工具,還是我需要使用諸如distanceToBoundingSphere(boundingSphere)之類的東西自己計算? 我只想要x,y坐標; 我根本不在乎身高。
我一直在演示和教程中四處逛逛,到目前為止,還沒有找到我想找的東西。 也許我找到了一些接近的東西,但我還不知道我是否找到了它。 救命!
=========================== CODE ===================== =============
收集多邊形的位置:
當用戶將鼠標拖動到新點時,singleClick僅捕獲該點的坐標並繪制一條折線。 因此,有一束折線和每個點的坐標集合。
positionHandler.setInputAction(function (click) {
cartesian = scene.camera.pickEllipsoid(click.position, ellipsoid);
if (cartesian) {
var setCartographic = ellipsoid.cartesianToCartographic(cartesian);
asset.latlonalt.push(
Cesium.Math.toDegrees(setCartographic.latitude).toFixed(15),
Cesium.Math.toDegrees(setCartographic.longitude).toFixed(15),
Cesium.Math.toDegrees(setCartographic.height).toFixed(15)
);
lla.push(Cesium.Math.toDegrees(setCartographic.longitude), Cesium.Math.toDegrees(setCartographic.latitude));
if (lla.length >= 4) {
self.loggingMessage((lla.length / 2) + ' Points Added');
}
Cesium.sampleTerrain(terrainProvider, 11, [cartographic])
.then(function (updatedPositions) {
asset.latlonalt[2] = updatedPositions[0].height;
stage = 1;
});
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
然后,DoubleClick獲取在singleClick函數中捕獲的坐標,並調用self.createAsset('add',asset)創建多邊形。
positionHandler.setInputAction(function (doubleClick){
if (asset.shape == 'Polygon') {
var len = asset.latlonalt.length;
if(len > 9) {
asset.rad = (len / 3);
console.log("Creating Asset");
self.loggingMessage("Creating Asset");
socket.emit('newElement', asset.cType, asset);
self.createAsset('add', asset);
viewer.entities.remove(entity);
viewer.entities.remove(newCircle);
viewer.entities.remove(newPolygon);
viewer.entities.remove(newOutline);
positionHandler = positionHandler && positionHandler.destroy();
}else{
console.log('3+ Positions Required');
loggingMessage('3+ Positions Required.');
}
}
}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)
創建多邊形:
var newPolygon = viewer.entities.add({
name : asset.id,
polygon : {
hierarchy : Cesium.Cartesian3.fromDegreesArray(vertices),
material : rgba[0],
outline : true,
outlineColor : rgba[1]
}
});
var newLabel = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(asset.latlonalt[1], asset.latlonalt[0], 1000),
name: asset.id,
label: {
text: asset.name,
font : '16px Helvetica'
}
});
var newPoint = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(asset.latlonalt[1], asset.latlonalt[0], 0),
name: asset.id,
point : {
pixelSize : 5,
color : Cesium.Color.RED,
outlineColor : Cesium.Color.RED,
outlineWidth : 2
}
});
self.currentGeometry[asset.id] = {shape: newPolygon, label: newLabel, point: newPoint};
看來我們正在使用Terrain(我認為)。
我應該對哪些數字感興趣:
收集坐標時,只有第一個z不為零:
我采用該值並填充其他z值:
現在,我已經添加了z值,在createAsset方法中出現了一些錯誤。 我需要跟蹤該問題才能看到結果。 現在,它看起來像這樣:
確實很大,輪廓沒有被去除。
一個問題有很多事情要做,但是我將嘗試解決這個關鍵問題。
首先, Cartesian3
類本身。 在內部,構造之后,此類包含x, y, z
成員x, y, z
成員包含類似於314923.1
值。 您可能應該將它們視為黑匣子,不透明值。 實際上,它們表示距行星中心的笛卡爾位置(以米為單位),這是渲染引擎所需的,但通常對人類制圖師沒有用。 要理解的關鍵是z
總是會填充一個真實值,但這並不意味着在創建該值時是否考慮了高度。
有一個單獨的類Cartographic
,其中包含熟悉的經度(弧度),緯度(弧度)和海拔(以米為單位)值。 通常,在將它們傳遞給渲染引擎之前,必須將其轉換為Cartesian3
。 此轉換需要了解Ellipsoid
(默認為WGS84橢球體),因此,零高度值表示該橢球體上的一個點(通常意味着在打開地形時該點位於地下)。
各種輔助函數采用通用值(例如,度數的經度/緯度)並轉換為這兩種格式中的任一種。 這些輔助功能中的一些會忽略高度參數,而其他一些功能會包含它。 這兩個類的文檔列舉了這些幫助器。
當關閉地形時,通過鼠標單擊來獲取精確的經度/緯度很簡單,但由於使用了透視3D相機,因此在打開地形時更為復雜。 在沒有地形的情況下,您可以像在上面的第一個代碼示例中所做的那樣僅調用scene.camera.pickEllipsoid
,並獲得確切的位置。 但是,當地形處於打開狀態時,即使單擊平坦的平原也會計算出錯誤的坐標,從而在您要查看的地形的下方和后面找到一個地下點。
隨意搜索並沒有找到正確的代碼,但是這里似乎已經將黃金標准烘焙到了現有的相機控制器中 。 看起來像這樣:
var depthIntersection;
if (scene.pickPositionSupported) {
depthIntersection = scene.pickPosition(mousePosition, scratchDepthIntersection);
}
var ray = camera.getPickRay(mousePosition, pickGlobeScratchRay);
var rayIntersection = globe.pick(ray, scene, scratchRayIntersection);
var pickDistance = defined(depthIntersection) ?
Cartesian3.distance(depthIntersection, camera.positionWC) :
Number.POSITIVE_INFINITY;
var rayDistance = defined(rayIntersection) ?
Cartesian3.distance(rayIntersection, camera.positionWC) :
Number.POSITIVE_INFINITY;
if (pickDistance < rayDistance) {
return Cartesian3.clone(depthIntersection, result);
}
return Cartesian3.clone(rayIntersection, result);
此代碼嘗試采用兩種方法:與以前一樣,嘗試拾取橢球,並且還嘗試從“深度緩沖區”中進行拾取,“深度緩沖區”是3D圖形系統的一部分,允許Cesium檢查多邊形有多遠從相機渲染時。 將兩個結果進行比較,然后以更接近相機的為准。 這完全避免了sampleTerrain
調用的需要,因為鼠標位置已被用來直接拾取渲染多邊形的空間中的笛卡爾點(可能是地形,甚至可能是建築物的頂部,等等)。
在您的下一個代碼塊中,您使用asset.latlonalt
填充lon
和lat
,但是然后將alt
硬編碼為0
或1000
而不是來自相同的數據結構。 這可能是丟失高度信息的地方,如果它是從那里開始的(不是,如果您只是選擇橢球體,則不是),盡管稍后可能由sampleTerrain
添加它。請注意sampleTerrain
是異步的從服務器加載的地形圖)。 如果您決定嘗試深度選擇技術,它將直接產生Cartesian3
,因此您不必擔心轉換它或保留海拔等問題。
最后的評論是,最新版本的GroundPrimitive
確實支持GroundPrimitive
,該多邊形可以使多邊形覆蓋在地形上 。 這樣一來,您就不必從“拾取”正確的lon / lat(考慮到透視地形)中解脫出來,而是可以將多邊形放置在塊狀表面上並且不會穿過。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.