1. 程式人生 > >Cesium座標系及座標轉換詳解

Cesium座標系及座標轉換詳解

前言

Cesium專案中經常涉及到模型載入、瀏覽以及不同資料之間的座標轉換,弄明白Cesium中採用的座標系以及各個座標系之間的轉換,是我們邁向三維GIS大門的前提,本文詳細的介紹了Cesium中採用的兩大座標系以及之間轉換的各種方法。

Cesium中的座標系

Cesium中常用的座標有兩種WGS84地理座標系和笛卡爾空間座標系,我們平時常用的以經緯度來指明一個地點就是用的WGS84座標,笛卡爾空間座標系常用來做一些空間位置變換如平移旋轉縮放等等。二者的聯絡如下圖。

其中,WGS84地理座標系包括 WGS84經緯度座標系(沒有實際的物件)和 WGS84弧度座標系(Cartographic);

         笛卡爾空間座標系包括 笛卡爾空間直角座標系(Cartesian3)、平面座標系(Cartesian2),4D笛卡爾座標系(Cartesian4)。

WGS84座標系

World Geodetic System 1984,是為GPS全球定位系統使用而建立的座標系統,座標原點為地球質心,其地心空間直角座標系的Z軸指向BIH (國際時間服務機構)1984.O定義的協議地球極(CTP)方向,X軸指向BIH 1984.0的零子午面和CTP赤道的交點,Y軸與Z軸、X軸垂直構成右手座標系。我們平常手機上的指南針顯示的經緯度就是這個座標系下當前的座標,進度範圍[-180,180],緯度範圍[-90,90]。

WGS84座標系

Cesium目前支援兩種座標系WGS84和WebMercator,但是在Cesium中沒有實際的物件來描述WGS84座標,都是以弧度的方式來進行運用的也就是Cartographic類:

new Cesium.Cartographic(longitude, latitude, height),這裡的引數也叫longitude、latitude,就是經度和緯度,計算方法:弧度= π/180×經緯度角度。

 笛卡爾空間直角座標系(Cartesian3)

笛卡爾空間座標的原點就是橢球的中心,我們在計算機上進行繪圖時,不方便使用經緯度直接進行繪圖,一般會將座標系轉換為笛卡爾座標系,使用計算機圖形學中的知識進行繪圖。這裡的Cartesian3,有點類似於三維繫統中的Point3D物件,new Cesium.Cartesian3(x, y, z),裡面三個分量x、y、z。

笛卡爾空間直角座標系

平面座標系(Cartesian2)

平面座標系也就是平面直角座標系,是一個二維笛卡爾座標系,與Cartesian3相比少了一個z的分量,new Cesium.Cartesian2(x, y)。Cartesian2經常用來描述螢幕座標系,比如滑鼠在電腦螢幕上的點選位置,返回的就是Cartesian2,返回了滑鼠點選位置的xy畫素點分量。

平面座標系

座標轉換

經緯度和弧度的轉換

var radians=Cesium.Math.toRadians(degrees);//經緯度轉弧度
var degrees=Cesium.Math.toDegrees(radians);//弧度轉經緯度

WGS84經緯度座標和WGS84弧度座標系(Cartographic)的轉換

//方法一:
var longitude = Cesium.Math.toRadians(longitude1); //其中 longitude1為角度

var latitude= Cesium.Math.toRadians(latitude1); //其中 latitude1為角度

var cartographic = new Cesium.Cartographic(longitude, latitude, height);

//方法二:
var cartographic= Cesium.Cartographic.fromDegrees(longitude, latitude, height);//其中,longitude和latitude為角度

//方法三:
var cartographic= Cesium.Cartographic.fromRadians(longitude, latitude, height);//其中,longitude和latitude為弧度

WGS84座標系和笛卡爾空間直角座標系(Cartesian3)的轉換

通過經緯度或弧度進行轉換
var position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);//其中,高度預設值為0,可以不用填寫;longitude和latitude為角度

var positions = Cesium.Cartesian3.fromDegreesArray(coordinates);//其中,coordinates格式為不帶高度的陣列。例如:[-115.0, 37.0, -107.0, 33.0]

var positions = Cesium.Cartesian3.fromDegreesArrayHeights(coordinates);//coordinates格式為帶有高度的陣列。例如:[-115.0, 37.0, 100000.0, -107.0, 33.0, 150000.0]

//同理,通過弧度轉換,用法相同,具體有Cesium.Cartesian3.fromRadians,Cesium.Cartesian3.fromRadiansArray,Cesium.Cartesian3.fromRadiansArrayHeights等方法

注意:上述轉換函式中最後均有一個預設引數ellipsoid(預設值為Ellipsoid.WGS84)。

通過過度進行轉換

具體過度原理可以參考上邊的注意事項。

var position = Cesium.Cartographic.fromDegrees(longitude, latitude, height);
var positions = Cesium.Ellipsoid.WGS84.cartographicToCartesian(position);
var positions = Cesium.Ellipsoid.WGS84.cartographicArrayToCartesianArray([position1,position2,position3]);

笛卡爾空間直角座標系轉換為WGS84

直接轉換
var cartographic= Cesium.Cartographic.fromCartesian(cartesian3);

轉換得到WGS84弧度座標系後再使用經緯度和弧度的轉換,進行轉換到目標值

間接轉換
var cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(cartesian3);
var cartographics = Cesium.Ellipsoid.WGS84.cartesianArrayToCartographicArray([cartesian1,cartesian2,cartesian3]);

平面座標系(Cartesian2)和笛卡爾空間直角座標系(Cartesian3)的轉換

平面座標系轉笛卡爾空間直角座標系

這裡注意的是當前的點(Cartesian2)必須在三維球上,否則返回的是undefined;通過ScreenSpaceEventHandler回撥會取到的座標都是Cartesian2。

螢幕座標轉場景座標-獲取傾斜攝影或模型點選處的座標

這裡的場景座標是包含了地形、傾斜攝影表面、模型的座標。

通過viewer.scene.pickPosition(movement.position)獲取,根據視窗座標,從場景的深度緩衝區中拾取相應的位置,返回笛卡爾座標。

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
     var position = viewer.scene.pickPosition(movement.position);
     console.log(position);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

注:若螢幕座標處沒有傾斜攝影表面、模型時,獲取的笛卡爾座標不準,此時要開啟地形深度檢測(viewer.scene.globe.depthTestAgainstTerrain = true; //預設為false)。

螢幕座標轉地表座標-獲取載入地形後對應的經緯度和高程

這裡是地球表面的世界座標,包含地形,不包括模型、傾斜攝影表面。

通過viewer.scene.globe.pick(ray, scene)獲取,其中ray=viewer.camera.getPickRay(movement.position)。

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
     var ray = viewer.camera.getPickRay(movement.position);
     var position = viewer.scene.globe.pick(ray, viewer.scene);
     console.log(position);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

注:通過測試,此處得到的座標通過轉換成wgs84後,height的為該點的地形高程值。

螢幕座標轉橢球面座標-獲取滑鼠點的對應橢球面位置

這裡的橢球面座標是參考橢球的WGS84座標(Ellipsoid.WGS84),不包含地形、模型、傾斜攝影表面。

通過 viewer.scene.camera.pickEllipsoid(movement.position, ellipsoid)獲取,可以獲取當前點選視線與橢球面相交處的座標,其中ellipsoid是當前地球使用的橢球物件:viewer.scene.globe.ellipsoid,預設為Ellipsoid.WGS84。

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
     var position = viewer.scene.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
     console.log(position);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

注:通過測試,此處得到的座標通過轉換成wgs84後,height的為0(此值應該為地表座標減去地形的高程)。

笛卡爾空間直角座標系轉平面座標系

var cartesian2= Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene,cartesian3)

空間位置變換

經緯度轉換到笛卡爾座標系後就能運用計算機圖形學中的仿射變換知識進行空間位置變換如平移旋轉縮放。

Cesium為我們提供了很有用的變換工具類:Cesium.Cartesian3(相當於Point3D)Cesium.Matrix3(3x3矩陣,用於描述旋轉變換)Cesium.Matrix4(4x4矩陣,用於描述旋轉加平移變換),Cesium.Quaternion(四元數,用於描述圍繞某個向量旋轉一定角度的變換)。

下面舉個例子:

      一個區域性座標為p1(x,y,z)的點,將它的區域性座標原點放置到loc(lng,lat,alt)上,區域性座標的z軸垂直於地表,區域性座標的y軸指向正北,並圍繞這個z軸旋轉d度,求此時p1(x,y,z)變換成全域性座標笛卡爾坐p2(x1,y1,z1)是多少?

var rotate = Cesium.Math.toRadians(d);//轉成弧度
var quat = Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Z, rotate); //quat為圍繞這個z軸旋轉d度的四元數
var rot_mat3 = Cesium.Matrix3.fromQuaternion(quat);//rot_mat3為根據四元數求得的旋轉矩陣
var v = new Cesium.Cartesian3(x, y, z);//p1的區域性座標
var m = Cesium.Matrix4.fromRotationTranslation(rot_mat3, Cesium.Cartesian3.ZERO);//m為旋轉加平移的4x4變換矩陣,這裡平移為(0,0,0),故填個Cesium.Cartesian3.ZERO
m = Cesium.Matrix4.multiplyByTranslation(m, v);//m = m X v
var cart3 = ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(lng, lat, alt)); //得到區域性座標原點的全域性座標
var m1 = Cesium.Transforms.eastNorthUpToFixedFrame(cart3);//m1為區域性座標的z軸垂直於地表,區域性座標的y軸指向正北的4x4變換矩陣
m = Cesium.Matrix4.multiplyTransformation(m, m1);//m = m X m1
var p2 = Cesium.Matrix4.getTranslation(m);//根據最終變換矩陣m得到p2
console.log('x=' + p2.x + ',y=' + p2.y + ',z=' + p2.z );

總結

通過本文,介紹了各個座標系間的轉換問題,在具體專案中,可結合實際需求,靈活組合解決具體的實際問題。注意,博文是參照網上相關部落格及結合自己的實踐總結得來,希望本文對你有所幫助,後續會更新更多內容,感興趣的朋友可以加關注,歡迎留言交