Cesium项目中常常涉及到模型加载、浏览以及不一样数据之间的坐标转换,弄明白Cesium中采用的坐标系以及各个坐标系之间的转换,是咱们迈向三维GIS大门的前提,本文详细的介绍了Cesium中采用的两大坐标系以及之间转换的各类方法。git
Cesium中经常使用的坐标有两种WGS84地理坐标系和笛卡尔空间坐标系,咱们平时经常使用的以经纬度来指明一个地点就是用的WGS84坐标,笛卡尔空间坐标系经常使用来作一些空间位置变换如平移旋转缩放等等。两者的联系以下图。canvas
其中,WGS84地理坐标系包括 WGS84经纬度坐标系(没有实际的对象)和 WGS84弧度坐标系(Cartographic);数组
笛卡尔空间坐标系包括 笛卡尔空间直角坐标系(Cartesian3)、平面坐标系(Cartesian2),4D笛卡尔坐标系(Cartesian4)。函数
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×经纬度角度。spa
笛卡尔空间坐标的原点就是椭球的中心,咱们在计算机上进行绘图时,不方便使用经纬度直接进行绘图,通常会将坐标系转换为笛卡尔坐标系,使用计算机图形学中的知识进行绘图。这里的Cartesian3,有点相似于三维系统中的Point3D对象,new Cesium.Cartesian3(x, y, z),里面三个份量x、y、z。3d
平面坐标系也就是平面直角坐标系,是一个二维笛卡尔坐标系,与Cartesian3相比少了一个z的份量,new Cesium.Cartesian2(x, y)。Cartesian2常常用来描述屏幕坐标系,好比鼠标在电脑屏幕上的点击位置,返回的就是Cartesian2,返回了鼠标点击位置的xy像素点份量。code
var radians=Cesium.CesiumMath.toRadians(degrees);//经纬度转弧度 var degrees=Cesium.CesiumMath.toDegrees(radians);//弧度转经纬度
//方法一: var longitude = Cesium.CesiumMath.toRadians(longitude1); //其中 longitude1为角度 var latitude= Cesium.CesiumMath.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为弧度
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)。orm
具体过分原理能够参考上边的注意事项。
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)必须在三维球上,不然返回的是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 );
经过本文,介绍了各个坐标系间的转换问题,在具体项目中,可结合实际需求,灵活组合解决具体的实际问题。注意,博文是参照网上相关博客及结合本身的实践总结得来,但愿本文对你有所帮助,后续会更新更多内容,感兴趣的朋友能够加关注,欢迎留言交流!