1. Cesium中的常用坐標系(Transform)
Cesium的坐標系統,可以認為在常用的三維坐標系統上,增加了一套專門的地理坐標系統。常用的webGL相關的坐標系統有:世界坐標系(笛卡爾坐標)、屏幕坐標系、相機坐標系以及模型坐標系。地理坐標系統有:經緯度坐標系以及用弧度方式表達的地理坐標系。本篇文章主要涉及宏觀層面坐標系的介紹與相互轉換,對于相機坐標系以及模型坐標系暫且不表,有興趣可以參考大神的openGL教程。
1.1 笛卡爾三維坐標(Cartesian3世界坐標系)
定義一個三維空間,需要有三根相互垂直的軸線,這樣組成的三維空間稱之為笛卡爾坐標系。有兩種不同的三維坐標系,分別為左手坐標系與右手坐標系。
左手坐標系:以Unity3D、Direct3D為代表
右手坐標系:以3DMax、OpenGL為代表
Cesium采用的為右手坐標系
x: 2492703.426543796
y: 4552333.5377671
z: 3694768.946592552
var c3 = new Cesium.Cartesian3(x, y, z)
1.2 屏幕坐標WindowCoordinates
指顯示器上的屏幕坐標,以左上角為0,0原點,橫軸為X軸,豎軸為Y軸,坐標值為屏幕像素坐標。
1.3 Cartographic坐標(地理坐標系下經緯度的弧度表示)
相當于是一個中間轉換的坐標系,主要用于將笛卡爾坐標系的坐標轉換為經緯度坐標、經緯度坐標轉換為笛卡爾坐標
height: 0
latitude: 0.6218352629073777
longitude: 1.0698236893823745
var cart = new Cesium.Cartographic(longitude, latitude, height)
1.4 經緯度坐標
經緯度坐標為以英國格林威治天文臺為0度經線,以赤道為0度緯線,將地球延經度剖分360度,延緯度剖分180度而產生的坐標系。
longitude:61.2963822247248
latitude:35.62853611700069
longitude:經度
latitude:緯度
弧度與角度:
角度:1° = π / 180 ≈ 0.01745 rad
弧度:1rad = 180 / π = 57.30°
角度制:就是用角的大小來度量角的大小的方法。在角度制中,把周角的1/360看作1度,那么,半周就是180度,一周就是360度。由于1度的大小不因為圓的大小而改變,所以角度大小是一個與圓的半徑無關的量。
弧度制:顧名思義,就是用弧的長度來度量角的大小的方法。單位弧度定義為圓周上長度等于半徑的圓弧與圓心構成的角。由于圓弧長短與圓半徑之比,不因為圓的大小而改變,所以弧度數也是一個與圓的半徑無關的量。角度以弧度給出時,通常不寫弧度單位,有時記為rad或R。
1.5 笛卡爾二維坐標Cartesian2(平面坐標)
二維笛卡爾坐標,包括X與Y。
var c2 = new Cesium.Cartesian2(x, y)
可以通過distance方法計算兩點之間的距離
var d = Cesium.Cartesian2.distance(new Cesium.Cartesian2(1.0, 0.0), new Cesium.Cartesian2(2.0, 0.0));
1.6 Cartesian4四維坐標
例子:飛機巡航,增加出X\Y\Z外的W軸,較少使用。
2 坐標之間的相互轉換
涉及到坐標轉換的主要有以下幾個對象:
- Cartesian3→ Cartesian2,
Cesium.Cartesian2.fromCartesian3(cartesian, result)
→ Cartesian2- 經緯度坐標→ Cartesian3,
Cesium.Cartesian3.fromDegrees(longitude, latitude, height, ellipsoid, result)
→ Cartesian3- 弧度坐標 → Cartesian3,
Cesium.Cartesian3.fromRadians(longitude, latitude, height, ellipsoid, result)
→ Cartesian3- Cartesian3→ Cartographic,
Cesium.Cartographic.fromCartesian(cartesian, ellipsoid, result)
→ Cartographic- 經緯度坐標→ Cartographic,
Cesium.Cartographic.fromDegrees(longitude, latitude, height, result)
→ Cartographic- Cartographic → 經緯度,
Cesium.Math.toDegrees(carto.longitude);
2.1 經緯度、Cartesian3世界坐標系互轉
//經緯度轉換Cartesian3坐標
var pos = Cesium.Cartesian3.fromDegrees(61.296382224724795,35.628536117000692);
//Cartesian3轉經緯度坐標
//Cartographic坐標
var carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic(pos);
//經緯度
var lon = Cesium.Math.toDegrees(carto.longitude);
var lat = Cesium.Math.toDegrees(carto.latitude);
2.2 屏幕坐標獲取經緯度坐標
交互上,一般都是通過鼠標點擊與三維地球進行交互。鼠標點擊獲取到的是屏幕坐標的位置,那么如何通過屏幕坐標的位置獲得三維地球經緯度坐標位置呢?把大象裝進冰箱里,攏共分三步:
- 根據鼠標點擊屏幕位置獲取Cartesian3坐標
- 將Cartesian3解析為Cartographic弧度坐標
- 弧度坐標轉換為經緯度坐標
// 方法1. 獲取橢球體表面的經緯度坐標,
var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function(evt) {
var cartesian = viewer.camera.pickEllipsoid(evt.position,viewer.scene.globe.ellipsoid);
var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
var lng = Cesium.Math.toDegrees(cartographic.longitude);//經度值
var lat = Cesium.Math.toDegrees(cartographic.latitude);//緯度值
var mapPosition = {x:lng,y:lat,z:cartographic.height};//cartographic.height的值始終為零。
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//方法2. 獲取地形表面的經緯度高程坐標
var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function(evt) {
var ray = viewer.camera.getPickRay(evt.position);
var cartesian = viewer.scene.globe.pick(ray,viewer.scene);
var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
var lng = Cesium.Math.toDegrees(cartographic.longitude);//經度值
var lat = Cesium.Math.toDegrees(cartographic.latitude);//緯度值
var mapPosition={x:lng,y:lat,z:cartographic.height};//cartographic.height的值為地形高度。
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//方法3. 獲取模型或者其他要素
var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function(evt) {
var cartesian = viewer.scene.pickPosition(evt.position);
var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
var lng = Cesium.Math.toDegrees(cartographic.longitude);//經度值
var lat = Cesium.Math.toDegrees(cartographic.latitude);//緯度值
var mapPosition={x:lng,y:lat,z:cartographic.height};//
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);