GIS知識點——GIS三維開發相關座標系

轉至:https://www.cnblogs.com/yaohuimo/p/10826378.html 很好的文章轉過來學習,感謝原博主的付出

個人總結:笛卡爾座標可以以任何體爲參考指定中心點和xyz方向來建立,wgs84只是一地球爲參考建立的笛卡爾座標。

在把shader往three上加,或者three疊加到Cesium/Mapbox上時,就是在統一他們的參考。理解這點很關鍵。

一、座標系介紹
我們先來列舉下Cesium中的座標系:WGS84經緯度座標系(沒有實際的對象)、WGS84弧度座標系(Cartographic)、笛卡爾空間直角座標系(Cartesian3)、平面座標系(Cartesian2),4D笛卡爾座標系(Cartesian4)
1、WGS84座標系
World Geodetic System 1984,是爲GPS全球定位系統使用而建立的座標系統,座標原點爲地球質心,其地心空間直角座標系的Z軸指向BIH (國際時間服務機構)1984.O定義的協議地球極(CTP)方向,X軸指向BIH 1984.0的零子午面和CTP赤道的交點,Y軸與Z軸、X軸垂直構成右手座標系。我們平常手機上的指南針顯示的經緯度就是這個座標系下當前的座標,進度範圍[-180,180],緯度範圍[-90,90]。
我們都知道Cesium目前支持兩種座標系WGS84和WebMercator,但是在Cesium中沒有實際的對象來描述WGS84座標,都是以弧度的方式來進行運用的也就是Cartographic類:new Cesium.Cartographic(longitude, latitude, height),這裏的參數也叫longitude、latitude,就是經度和緯度,計算方法:弧度= π/180×經緯度角度。

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

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

4、4D笛卡爾座標系(Cartesian4)
到目前來說,還沒有用過,等後續有用到的時候再更新吧
二、幾種座標系的使用及轉換方法
經緯度和弧度的轉換
**經緯度轉弧度:**var radians=Cesium.CesiumMath.toRadians(degrees);
**弧度轉經緯度:**var degrees=Cesium.CesiumMath.toDegrees(radians);
我們來看下Cesium中源碼的轉換方法,其實就是:弧度= π/180×經緯度角度;經緯度角度=180/π×弧度。

CesiumMath.RADIANS_PER_DEGREE = Math.PI / 180.0;
CesiumMath.DEGREES_PER_RADIAN = 180.0 / Math.PI;
CesiumMath.toRadians = function(degrees) {
        //>>includeStart('debug', pragmas.debug);
        if (!defined(degrees)) {
            throw new DeveloperError('degrees is required.');
        }
        //>>includeEnd('debug');
        return degrees * CesiumMath.RADIANS_PER_DEGREE;
    };
CesiumMath.toDegrees = function(radians) {
        //>>includeStart('debug', pragmas.debug);
        if (!defined(radians)) {
            throw new DeveloperError('radians is required.');
        }
        //>>includeEnd('debug');
        return radians * CesiumMath.DEGREES_PER_RADIAN;
    };

WGS84經緯度座標和WGS84弧度座標系(Cartographic)的轉換
**1.直接轉換:**通過上面提到的方法,將經緯度轉換爲弧度後,直接new Cesium.Cartographic(longitude弧度, latitude弧度, height米)
**2.間接轉換:**通過var cartographic= Cesium.Cartographic.fromDegrees(longitude, latitude, height)直接轉換;
類似的還有var cartographic= Cesium.Cartographic.fromRadians(longitude, latitude, height)方法,傳入的是弧度。
WGS84座標系和笛卡爾空間直角座標系(Cartesian3)的轉換
WGS84轉爲笛卡爾空間直角座標系
1.通過經緯度或弧度進行轉換:
var c3= Cesium.Cartesian3.fromDegrees(longitude, latitude, height) ;高度height可不填寫。
var c3s=Cesium.Cartesian3.fromDegreesArray(coordinates);coordinates格式爲不帶高度的數組。例如:[-115.0, 37.0, -107.0, 33.0]
var c3s=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等方法,用法和上面一樣,只是度需要轉換爲弧度,這裏不再講這些方法。

其實fromDegrees內部也是用的fromRadians方法,這點大家可以瞭解下,另外WGS84座標系轉笛卡爾空間直角座標系代碼如下,大家可以瞭解下轉換過程:

Cartesian3.fromRadians = function(longitude, latitude, height, ellipsoid, result) {
        //>>includeStart('debug', pragmas.debug);
        Check.typeOf.number('longitude', longitude);
        Check.typeOf.number('latitude', latitude);
        //>>includeEnd('debug');
 
        height = defaultValue(height, 0.0);
        var radiiSquared = defined(ellipsoid) ? ellipsoid.radiiSquared : wgs84RadiiSquared;
 
        var cosLatitude = Math.cos(latitude);
        scratchN.x = cosLatitude * Math.cos(longitude);
        scratchN.y = cosLatitude * Math.sin(longitude);
        scratchN.z = Math.sin(latitude);
        scratchN = Cartesian3.normalize(scratchN, scratchN);
 
        Cartesian3.multiplyComponents(radiiSquared, scratchN, scratchK);
        var gamma = Math.sqrt(Cartesian3.dot(scratchN, scratchK));
        scratchK = Cartesian3.divideByScalar(scratchK, gamma, scratchK);
        scratchN = Cartesian3.multiplyByScalar(scratchN, height, scratchN);
 
        if (!defined(result)) {
            result = new Cartesian3();
        }
        return Cartesian3.add(scratchK, scratchN, result);
    };

2.通過度來進行轉換
var position = Cesium.Cartographic.fromDegrees(longitude, latitude, height);
var c3 = Cesium.Ellipsoid.WGS84.cartographicToCartesian(position);
var c3s=Cesium.Ellipsoid.WGS84.cartographicArrayToCartesianArray([position1,position2,position3])
弧度同理
笛卡爾空間直角座標系轉換爲WGS84
1.直接轉換
var cartographic= Cesium.Cartographic.fromCartesian(cartesian3)
轉換得到WGS84弧度座標系後再使用經緯度和弧度的轉換,進行轉換到目標值
2、間接轉換
var cartographic= Cesium.Ellipsoid.WGS84.cartesianToCartographic(cartesian3)
var cartographics= Cesium.Ellipsoid.WGS84.cartesianArrayToCartographicArray([cartesian1,cartesian2,cartesian3])

平面座標系(Cartesian2)和笛卡爾空間直角座標系(Cartesian3)的轉換
平面座標系轉笛卡爾空間直角座標系
這裏需要說明的是當前的點必須在三維球上,否則返回的是undefined,我們在ScreenSpaceEventHandler回調會取到的座標都是Cartesian2,大家可以測試觀察下。
1.屏幕座標轉場景WGS84座標,這裏的場景座標是包含了地形、傾斜、模型的座標。
轉換方法爲:var cartesian3= viewer.scene.pickPosition(Cartesian2)
2.屏幕座標轉地表座標,這裏是地球表面的WGS84座標,包含地形,不包括模型、傾斜攝影表面。
轉換方法爲:var cartesian3= viewer.scene.globe.pick(viewer.camera.getPickRay(Cartesian2),viewer.scene);
3.屏幕座標轉橢球面座標,這裏的橢球面座標是參考橢球的WGS84座標,不包含地形、模型、傾斜攝影表面。
轉換方法爲:var cartesian3= viewer.scene.camera.pickEllipsoid(Cartesian2)
笛卡爾空間直角座標系轉平面座標系
var cartesian2= Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene,cartesian3)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章