Cesium 坐标系

1,004 阅读5分钟

Cesium1.98 坐标系 --笔记

一、前提知识(角度经纬度、度分秒经纬度、弧度经纬度)

1、角度经纬度

  • Cesuim中没有具体的经纬度对象,要得到经纬度首先需要计算为弧度,再进行转换

  • 下图中以本初子午线作为x和z的面,建立了一个空间坐标系。可知在纬度方向上,角1的范围为-90到90,即南纬90°到北纬90°,角2的范围是-180到180,即东经180°到西经180° , 如 39.905556 116.424722

1666850225105.png

2、弧度经纬度

  • Cesium中的地理坐标单位默认是弧度制,用Cartographic变量表示
  • 弧度:弧的长度除以弧的半径得出的比值。如π对应180°,如0.6964833420389782 2.0319947296190777
    • 角度转弧度 π/180×角度
    • 弧度变角度 180/π×弧度

3、度分秒经纬度

  • ArcMap地理配准常见的度分秒经纬度:北纬39°54′20″,东经116°25′29″
  • 如有需要,可通过以下方式角度经纬度 <-> 度分秒经纬度得到度分秒经纬度
//度分秒 => 角度经纬度
function changeDu(du,fen,miao){
	var mFen = 0;
	if(miao != null && miao != ''){
		mFen = Number(miao / 60);
	}
	var fDu = 0;
	if(fen != null && fen != '' ){
		fDu = (Number(fen) + mFen) / 60;
	}else{
		fDu = mFen;
	}
	var lDu = 0;
	if(du != null && du != ''){
		lDu = (Number(du)+fDu).toFixed(6);
	}else{
		lDu = fDu.toFixed(6);
	}
	
	return lDu;
}

//角度经纬度 => 度分秒
//将度转换成为度分秒
function formatDegree(value) {  
	if(value != null && value != ''){
	    ///<summary>将度转换成为度分秒</summary>  
	    value = Math.abs(value);  //返回数的绝对值
	    var v1 = Math.floor(value);//度   //对数进行下舍入
	    var v2 = Math.floor((value - v1) * 60);//分  
	    var v3 = Math.round((value - v1) * 3600 % 60);//秒  //把数四舍五入为最接近的整数
	    return v1 + ';' + v2 + ';' + v3 + ';';  
	}else{
		return '' + ';' + '' + ';' + '' + ';';  
	}
}; 

二、Cartesian2 [kɑːˈtiːziən]屏幕坐标

  • Cesium使用Cartesian2描述屏幕坐标系

  • 构造函数

    new Cesium.Cartesian2(x, y)
    
  • 说明

    鼠标点击位置距离canvas左上角的像素值。屏幕左上角为原点(0.0),屏幕水平方向为X轴,向右为正,垂直方向为Y轴,向下为正,如图所示。

1666603262309.png

三、Cartesian3世界笛卡尔空间直角坐标系

  • Cesium使用Cartesian3描述世界坐标系

  • 构造函数

    //通过角度经纬度
    let cartesian3 = Cesium.Cartesian3.fromDegrees( 121.80348,29.8171504923588,2500)
    
    //通过弧度经纬度
    Cesium.Cartesian3.fromRadians(longitude,latitude,height,ellipsoid,result)
    
    //通过其他方式
    Cesium.Cartographic.toCartesian(cartographic, ellipsoid, result)
    
  • 说明

    • 以空间中O点为原点,建立三条两两垂直的数轴;X轴(横坐标)、Y轴(纵坐标)、Z轴(竖坐标),建立了空间直角坐标系0—XYZ
    • 笛卡儿空间直角坐标的原点就是椭球的中心,在计算机上进行绘图时,不方便使用经纬度直接进行绘图,一般会将坐标系转换为笛卡儿坐标系,使用计算机图形学中的知识进行绘图
      • Cesium.Matrix3(3x3矩阵,用于描述旋转变换)
      • Cesium.Matrix4(4x4矩阵,用于描述旋转加平移变换)
      • Cesium.Quaternion(四元数,用于描述围绕某个向量旋转一定角度的变换)
      • Cesium.Transforms (包含将位置转换为各种参考系的功能)

1666603773023.png

四、坐标转换

1.Cartesian2 <-> Cartesian3

注意这里屏幕坐标一定要在球上,否则生成出的cartesian对象是undefined

屏幕坐标 => 世界坐标

let pick1= new Cesium.Cartesian2(0,0);
let cartesian = viewer.scene.globe.pick(viewer.camera.getPickRay(pick1),viewer.scene);

世界坐标 => 屏幕坐标

let cartesian3=new Cesium.cartesian3(x,y,z);
let pick = Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, Cartesian3);

2.Cartesian3 <-> 角度经纬度 <-> 弧度经纬度

角度经纬度 => 世界坐标系(直接)

//方法一,直接转换
let cartesian3 = Cesium.Cartesian3.fromDegrees(longitude, latitude, height) 

//方法二,先转为地理弧度,再转为世界坐标系
let cartographic = Cesium.Cartographic.fromDegrees(lon, lat, height); //单位:度,度,米
let cartesian3 = ellipsoid.cartographicToCartesian(cartographic);

世界坐标系 => 角度经纬度

const ellipsoid=viewer.scene.globe.ellipsoid;  //首先获取场景中参考椭球体,因此表明可以更换椭球体
const cartesian3=new Cesium.cartesian3(x,y,z);   //创建一个初始的世界坐标系位置
const cartographic=ellipsoid.cartesianToCartographic(cartesian3);  //世界坐标系转为弧度经纬度
let lat=Cesium.Math.toDegrees(cartograhphic.latitude);  //弧度转为纬度
let lon=Cesium.Math.toDegrees(cartograhpinc.longitude);  //弧度转为经度
let height=cartographic.height;  //弧度转为高度

弧度经纬度 => 世界坐标系(直接)

let cartesian3 = Cesium.Cartesian3.fromRadians(cartographic)

世界坐标系 => 弧度经纬度(直接)

//方法一
let cartographic = Cesium.Cartographic.fromCartesian(cartesian3)
//方法二: 首先需要获取到当下场景中的ellipsoid对象
let cartographic = ellipsoid.cartesianToCartographic(cartesian3)

角度经纬度 => 弧度经纬度(直接)

let radians = Cesium.Math.toRadians(degrees)

弧度经纬度 => 角度经纬度(直接)

let degrees = Cesium.Math.toDegrees(radians)

五、拾取Cartesian3坐标 Demo

1、camera.globe.pick(ray, scene, result)

// 首先需要注册cesium鼠标事件,通过cesium的ScreenSpaceEventHandler函数处理用户输入事件
  let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
  // 设置要在输入事件上执行的功能,官方文档查询ScreenSpaceEventType可以看到所有的cesium鼠标事件
  handler.setInputAction((movement) => {
    const ray = viewer.camera.getPickRay(movement.position);
    if (!ray) return null;
    const cartesian3 = globe.pick(ray, viewer.scene);
    // 防止点击到地球之外报错,加个判断
    if (cartesian3 && Cesium.defined(cartesian3)) {
      let cartographic = Cartographic.fromCartesian(cartesian3!)
      let lng = Math.toDegrees(cartographic.longitude)
      let lat = Math.toDegrees(cartographic.latitude)
      let height = cartographic.height;
      console.log(lng, lat, height);
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

2、 camera.pickEllipsoid(windowCoordinates,ellipsoid)

// 首先需要注册cesium鼠标事件,通过cesium的ScreenSpaceEventHandler函数处理用户输入事件
  let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
  // 设置要在输入事件上执行的功能,官方文档查询ScreenSpaceEventType可以看到所有的cesium鼠标事件
  handler.setInputAction((movement) => {
    let cartesian3 = viewer.scene.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid)
    // 防止点击到地球之外报错,加个判断
    if (cartesian3 && Cesium.defined(cartesian3)) {
      let cartographic = Cartographic.fromCartesian(cartesian3!)
      let lng = Math.toDegrees(cartographic.longitude)
      let lat = Math.toDegrees(cartographic.latitude)
      let height = cartographic.height;
      console.log(lng, lat, height);
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

3、scene.pickPosition(windowCoordinates)

viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
     const pickedFeature = viewer.scene.pick(movement.position);
     if (!Cesium.defined(pickedFeature)) {
         // nothing picked
         return;
     }
     const worldPosition = viewer.scene.pickPosition(movement.position);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

六、矩阵转换

1、Cesium中物体的移动、缩放、平移都可以用变换矩阵来计算。

2、变换(tansformation)可是理解为一个函数,实现将一个空间坐标映射为另一个空间坐标,矩阵(matrix)是这种计算的一种方式,在三维开发中用途广泛。

blog.csdn.net/u011575168/…