ronghaoZHI/ronghaoZHI.github.io

地理坐标中的 经纬度 / 弧度 / 世界坐标 / 屏幕坐标转换

Opened this issue · 0 comments

首先介绍一下相关涉及到的 相关坐标系统

1、平面坐标系(Cartesian2)

cartesian2 = { x: x || 0.0,  y: y || 0.0} 
/*
* cesium 中表示 , A 2D Cartesian point
*/
new Cesium.Cartesian2(x, y)  

2、笛卡尔空间直角坐标系 - 世界坐标(Cartesian3)

cartesian3 = { x: x || 0.0,  y: y || 0.0, z: z || 0.0 }
/*
* cesium 中表示 , A 3D Cartesian point.
*/
new Cesium.Cartesian3(x, y, z)

3、地理坐标系 / 经纬度 [longitude,latitude] / 弧度 Cartographic

地理坐标系,坐标原点在椭球的质心。
经度:参考椭球面上某点的大地子午面与本初子午面间的两面角。东正西负。
纬度:参考椭球面上某点的法线与赤道平面的夹角。北正南负。
cartographic = { longitude: longitude || 0.0, latitude: latitude || 0.0, height: height || 0.0  }

/*
* cesium 中表示 ,  A position defined by longitude, latitude, and height.
* 注:这里的经纬度是用弧度表示的,经纬度其实就是角度。弧度即角度对应弧长是半径的倍数。
*/
new Cesium.Cartographic(longitude, latitude, height)  

/*
* 经纬度转弧度:
*/
Cesium.CesiumMath.toRadians(degrees) 
// 等同于  (degrees) =>  degrees * Math.PI / 180

/*  
* 弧度转经纬度:
*/
Cesium.CesiumMath.toDegrees(radians) 
// 等同于  (radians) =>  radians * 180 / Math.PI  

注:认识与理解 世界坐标(Cartesian3)与 地理坐标(cartographic)与 经纬度 / 弧度 是往下面看的必备基础。


常用的坐标转换

1、 经纬度 转 世界坐标

/*
* cesium 中转换公式
* ellipsoid:
* A quadratic surface defined in Cartesian coordinates by the equation
* <code>(x / a)^2 + (y / b)^2 + (z / c)^2 = 1</code>.  Primarily used
* by Cesium to represent the shape of planetary bodies.
* Cartographic:
* A position defined by longitude, latitude, and height.
*/
var ellipsoid = viewer.scene.globe.ellipsoid;
var cartographic = Cesium.Cartographic.fromDegrees(lng, lat, alt);
var cartesian3 = ellipsoid.cartographicToCartesian(cartographic);

2、世界坐标 转 经纬度

/*
* cesium 中转换公式
* @param   { cartesian3(x,  y,  z) }
*  @retrun  { latitude,  longitude }
*/
var ellipsoid = viewer.scene.globe.ellipsoid;
var cartesian3 = new Cesium.cartesian3(x, y, z);
var cartographic = ellipsoid.cartesianToCartographic(cartesian3);
var latitude = Cesium.Math.toDegrees(cartograhphic.latitude);
var longitude = Cesium.Math.toDegrees(cartograhpinc.longitude);

3、屏幕坐标 转 世界坐标

/*
* cesium 中转换公式
* @param { event }
* @return [lng, lat]
*/
// event 鼠标事件
var { clientX, clientY } = event
var cartesian = window.viewer.scene.pickGlobe({
  x: clientX,
  y: clientY
})
if(cartesian) {
  var { longitude, latitude, height }	= Cesium.Cartographic.fromCartesian(cartesian)
  var lng = Cesium.Math.toDegrees(longitude)
  var lat = Cesium.Math.toDegrees(latitude)
  return [lng, lat]
}

4、世界坐标 转 屏幕坐标

/*
* cesium 中转换公式
*/
Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, Cartesian3);

---

### 其他方法
1、 已知经纬度 获取 地表高度 (需要异步执行 ,待地形加载完成)
```js
/*
* cesium 中转换公式
*/
var ellipsoid = viewer.scene.globe.ellipsoid;
var cartographic = Cesium.Cartographic.fromDegrees(lng, lat, alt);
var cartesian3 = ellipsoid.cartographicToCartesian(cartographic);
var cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(cartesian3);
// 经纬度
var [ longitude, latitude ] = [ cartographic.longitude,  cartographic.latitude ];
// 地表高度 / 视点高度
var height = Cesium.Cartographic.fromCartesian(viewer.scene.clampToHeight(cartesian3)).height;
// 中心点距离
const distance = Cesium.Cartesian3.distance(result, viewer.scene.camera.position);
var sinAngle = Math.sin(Math.abs(viewer.scene.camera.pitch));
distance = distance /sinAngle;

2、屏幕中心点 转 世界坐标

/*
* cesium 中转换公式
*/
var screenCenter = new Cesium.Cartesian2(viewer.canvas.clientWidth / 2, viewer.canvas.clientHeight / 2);
var cartesian3 = viewer.camera.pickEllipsoid(screenCenter);

2、 经纬度 转换成 度分秒表示法

/*
* @param  { longitude  }
* @return  string 
*/
function (longitude) {
  var label;
  var _long = formatRad(longitude);
  longitude > 0 ? (label = 'E') : (label = 'W');
  return `${label}${_long[0]}°${_long[1]}'${_long[2]}"`;
  function formatRad(v) {
      const v0 = Math.abs(+v)
      const v1 = Math.floor(v0) //度
      const v2 = Math.floor((v0 - v1) * 60) //分
      const v3 = Math.round((v0 - v1) * 3600 % 60) //秒
      return [v1, v2, v3];
    }
}