---
title: 坐标系统
author: ac
date: 2022-01-22
tags:
- CesiumJS
- 坐标系
categories:
- GIS
---
## Cesium 坐标系
`Cesium` 具有真实地理坐标的三维球体,用户通过二维屏幕与 `Cesium` 进行操作,如果要将三维模型绘制到球体上,需要在地理坐标和屏幕坐标之间进行换算。 `Cesium` 中有以下五种坐标系:
- WGS84 经纬度坐标系(没有实际的对象)
- WGS84 弧度坐标系(Cartographic)
- 笛卡尔空间直角坐标系(Cartesian3)
- 屏幕坐标系(Cartesian2)
- 4D 笛卡尔坐标系(Cartesian4)
---
### 1. WGS84 经纬度坐标系
> 参考椭球体:将地球抽象城一个规则逼近原始自然地球表面的球体,成为参考椭球体。
在大地测量中,通过以参考椭球面为基准面,再确定其大小,给其定位和定向就可以建立一个大地坐标系。大地坐标系是一种伪地理坐标系。

WGS-84坐标系(World Geodetic System一1984 Coordinate System)是一种国际上采用的[地心坐标系](https://baike.baidu.com/item/地心坐标系/5155013)。坐标原点为[地球质心](https://baike.baidu.com/item/地球质心/7013007),其地心[空间直角坐标系](https://baike.baidu.com/item/空间直角坐标系/10743618)的Z轴指向BIH (国际时间服务机构)1984.0定义的协议地球极(CTP)方向,X轴指向BIH 1984.0的零[子午面](https://baike.baidu.com/item/子午面/9688202)和CTP赤道的交点,Y轴与Z轴、X轴垂直构成[右手坐标系](https://baike.baidu.com/item/右手坐标系/2562697),称为1984年世界[大地坐标系统](https://baike.baidu.com/item/大地坐标系统/6131526)。
> GPS[广播星历](https://baike.baidu.com/item/广播星历/1365627)是以WGS-84坐标系为根据的。
**基于椭球体表示空间点的位置**
大地坐标系中点的位置,通过大地经度L、大地纬度B和[大地高](https://baike.baidu.com/item/大地高)H这3个坐标分量表示。
在 `Cesium` 中没有实际的对象来描述 WGS84 经纬度坐标系的,都是以弧度的方式来进行运用的。
### 2. WGS84 弧度坐标系
> 因为度不是标准的长度单位,不可以直接测量长度和面积。方便计算, Cesium都是以弧度来描述点位坐标的。
`Cartographic` 类就是 `Cesium` 用来表示 `WGS84` 点位的。
```javascript
new Cesium.Cartographic(longitude, latitude, height)
```
| Name | Type | Default | Description |
| :---------- | :----- | :------ | :--------------------------------------------------- |
| `longitude` | Number | `0.0` | optional The longitude, in radians. |
| `latitude` | Number | `0.0` | optional The latitude, in radians. |
| `height` | Number | `0.0` | optional The height, in meters, above the ellipsoid. |
例如:一个经纬度为[21,78],大地高为5000的点。
```javascript
const position = new Cesium.Cartographic(
Cesium.Math.toRadians(21),
Cesium.Math.toRadians(78),
5000
);
```
### 3. 笛卡尔空间直角坐标系
`Cesium` 中笛卡尔空间直角坐标系的原点就是椭球的中心,以 `Cartesian3` 类来表示笛卡尔空间中的点位。
```javascript
new Cesium.Cartesian3(x, y, z)
```
| Name | Type | Default | Description |
| :--- | :----- | :------ | :------------------------ |
| `x` | Number | `0.0` | optional The X component. |
| `y` | Number | `0.0` | optional The Y component. |
| `z` | Number | `0.0` | optional The Z component. |
### 4. 屏幕坐标系

屏幕坐标系也叫平面直角坐标系,它是一个二维的笛卡尔坐标系。 `Cesium` 中使用 `Cartesian2`类来表示其点位,构造函数为:
```javascript
new Cesium.Cartesian2(x, y)
```
`Cartesian2` 的实例表示鼠标点击位置距离**canvas左上角**的像素值。
### 5. 坐标之间的转换
**经纬度和弧度的相互转换**
1. 通过 Math 类中的函数进行转换
```javascript
// 经纬度转弧度
var radians = Cesium.Math.toRadians(degree)
// 弧度转经纬度
var degree = Cesium.Math.toDegrees(radians)
```
2. 直接计算
弧度 = Math.PI/180 * 经纬度
经纬度 = 180/Math.PI * 弧度
**WGS84坐标和笛卡尔空间直角坐标系的转换**
1. 构造函数法
```javascript
// --------------WGS84弧度 转 笛卡尔空间坐标--------
// Cesium.Cartesian3.fromDegrees(longitude, latitude, ?height, ?ellipsoid, ?result)
// height为大地高
const position = Cesium.Cartesian3.fromDegrees(-115.0, 37.0);
// Cesium.Cartesian3.fromDegreesArray(coordinates, ?ellipsoid, ?result)
// coordinates 格式为不带大地高的数组:[112.11 ,22.71 ,12.21 ,22.9]
const positions = Cesium.Cartesian3.fromDegreesArray([-115.0, 37.0, -107.0, 33.0]);
// Cesium.Cartesian3.fromDegreesArrayHeights(coordinates, ?ellipsoid, ?result)
// coordinates 格式为带大地高的数组
const positions = Cesium.Cartesian3.fromDegreesArrayHeights([-115.0, 37.0, 100000.0, -107.0, 33.0, 150000.0]);
// --------------笛卡尔空间坐标 转 WGS84弧度--------
//Cesium.Cartographic.fromCartesian(cartesian, ?ellipsoid, ?result) → Cartographic
```
2. 通过椭球体进行转换
根据椭球体参数将WGS84经纬度坐标或其他地理坐标转为笛卡尔空间直角坐标。
```javascript
const ellipsoid84 = Cesium.Ellipsoid.wgs84
//笛卡尔空间坐标转WGS84弧度.
const position = new Cesium.Cartesian3(17832.12, 83234.52, 952313.73);
const cartographicPosition = ellipsoid84.cartesianToCartographic(position);
// WGS84 转 笛卡尔空间坐标
const position = new Cesium.Cartographic(Cesium.Math.toRadians(21), Cesium.Math.toRadians(78), 5000);
const cartesianPosition = ellipsoid84.cartographicToCartesian(position);
```
**屏幕坐标和笛卡尔空间直角坐标的转换**
> 屏幕坐标与笛卡尔空间直角坐标常用与三维场景开发中。
屏幕坐标转笛卡尔坐标
cesium根据不同的场景设定了三类屏幕坐标转笛卡尔坐标:
1. 屏幕坐标转**场景**空间直角坐标。包含地形、倾斜摄影测量模型等三维模型坐标。
```javascript
// cartesian2 ==> cartesian3
let cartesian3 = viewer.scene.pickPosition(cartesian2)
```
2. 屏幕坐标转**地表**笛卡尔空间坐标。包含地形,不包含三维模型。
```javascript
let cartesian3 = viewer.scene.globe.pick(viewer.camera.getPickRay(cartesian2),viewer.scene)
```
3. 屏幕坐标转**椭球面**笛卡尔空间坐标。不包含地形和三维模型。
```javascript
let cartesian3 = viewer.scene.camera.pickEllipsoid(cartesian2)
```
笛卡尔坐标转屏幕坐标
```javascript
Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, position, ?result) → Cartesian2
```
常用的点击事件中还有:
- `viewer.scene.drillPick(cartesian2)`:根据屏幕坐标返回,该位置的所有primitive实例的集合。
- `viewer.scene.pick(cartesian2)`:返回最上面的primitive
> 点击事件的事件源中`position`属性是屏幕坐标`cartesian2`。
```javascript
// On mouse over, color the feature yellow.
handler.setInputAction(function(evt) {
//Returns a list of objects, each containing a `primitive` property, for all primitives at a particular window coordinate position.
var picks = viewer.scene.drillPick(evt.position);
//Returns an object with a `primitive` property that contains the first (top) primitive in the scene at a particular window coordinate or undefined if nothing is at the location.
const feature = scene.pick(evt.endPosition);
if (feature instanceof Cesium.Cesium3DTileFeature) {
feature.color = Cesium.Color.YELLOW;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
```
## 参考文章
[1] cesium-坐标系统 https://jackie-sun.blog.csdn.net/article/details/122769126
[2] WGS-84坐标系 https://baike.baidu.com/item/WGS-84%E5%9D%90%E6%A0%87%E7%B3%BB/730443
[3] Cesium的坐标与转换 https://www.bilibili.com/video/BV16R4y1M7xc?p=6