meface/docs/article/gis/cesiumjs/03coordinate.md

232 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 坐标系统
author: ac
date: 2022-01-22
tags:
- CesiumJS
- 坐标系
categories:
- GIS
---
## Cesium 坐标系
`Cesium` 具有真实地理坐标的三维球体,用户通过二维屏幕与 `Cesium` 进行操作,如果要将三维模型绘制到球体上,需要在地理坐标和屏幕坐标之间进行换算。 `Cesium` 中有以下五种坐标系:
- WGS84 经纬度坐标系(没有实际的对象)
- WGS84 弧度坐标系Cartographic
- 笛卡尔空间直角坐标系Cartesian3
- 屏幕坐标系Cartesian2
- 4D 笛卡尔坐标系Cartesian4
---
### 1. WGS84 经纬度坐标系
> 参考椭球体:将地球抽象城一个规则逼近原始自然地球表面的球体,成为参考椭球体。
在大地测量中,通过以参考椭球面为基准面,再确定其大小,给其定位和定向就可以建立一个大地坐标系。大地坐标系是一种伪地理坐标系。
![img](./images/img1.jpeg)
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坐标系为根据的。
**基于椭球体表示空间点的位置**
<img src="./images/dadi.jpeg" alt="img" style="zoom: 25%;" />
大地坐标系中点的位置通过大地经度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. |
例如:一个经纬度为[2178]大地高为5000的点。
```javascript
const position = new Cesium.Cartographic(
Cesium.Math.toRadians(21),
Cesium.Math.toRadians(78),
5000
);
```
### 3. 笛卡尔空间直角坐标系
<img src="./images/img20.jpeg" alt="img" style="zoom:33%;" />
`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. 屏幕坐标系
![img](./images/2026842-af2319653d68d64e.png)
屏幕坐标系也叫平面直角坐标系,它是一个二维的笛卡尔坐标系。 `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