坐标转换
三维开发的核心就是坐标转换和矩阵变换,熟悉坐标系非常重要。
three-tile 中包含地理坐标系、世界坐标系、模型坐标系、屏幕坐标系等。上节调整摄像机位置就是用到了经纬度到世界坐标系的转换。
TIP
与 cesium 等使用球心坐标系不同,three-tile 内部采用 EPSG:3857 地图坐标系,坐标轴为东北上。
1. 坐标系介绍
地理坐标系
地理坐标一般指经纬度海拔高度,或投影坐标等。经纬度海拔作为坐标更加直观,但三维场景中并不能直接使用它,需要将它转换为三维世界坐标或模型坐标才能使用。
世界坐标系
世界坐标是 WebGL(OpenGL)中的概念,一般采用右手坐标系,原点为世界中心,这个坐标是全局唯一的,也叫全局坐标系。threejs 的世界坐标 X 指向右,y 轴指向上,z 轴指向屏幕外。
模型坐标系
模型坐标系也叫局地坐标系,一般是指相对于模型中心的坐标。
屏幕坐标系
屏幕坐标系是二维坐标,这个容易理解,但在三维场景中,坐标原点在屏幕左下角,y 轴向上。
three-tile 地图模型坐标
threejs 使用的右手坐标系,默认 y 轴是指向上的,可以看做指向天顶,x 轴指向右,也就是东,z 轴指向北。
为符合人类习惯,three-tile 中地图坐标系定义 x 轴指向东,y 轴指向北,z 轴指向天顶。
所以将地图模型加入场景时,可以看到一行代码:
tsmap.rotateX(-Math.PI / 2);
这句代码就是将地图旋转到世界坐标系的 xz 平面。
2. 坐标转换
上面的概念大概明白即可,threejs 提供了世界坐标、模型坐标、地理坐标之间的转换方法:
| 名称 | 参数 | 返回 | 功能 |
|---|---|---|---|
| geo2map(geo: Vector3) | geo: 地理坐标(经纬度高度) | Vector3:地图模型局地坐标 | 地理坐标转地图模型坐标 |
| map2geo(pos: Vector3) | pos: 地图模型局地坐标 | Vector3:地理坐标(经度、纬度、高度) | 地图模型坐标转地理坐标 |
| geo2world(geo:Vector3) | geo: 地理坐标(经纬度高度) | Vector3:世界坐标系坐标 | 地理坐标转世界坐标 |
| world2geo(world:Vector) | world:世界坐标系坐标 | Vector3:地理坐标(经度、纬度、高度) | 世界坐标转地理坐标 |
前面移动摄像机到指定经纬度,就是使用了 geo2world 方法:
// 地图中心经纬度高度(m)转为世界坐标
const centerPostion = map.geo2world(new THREE.Vector3(110, 35, 0));
// 摄像机经纬度高度(m)转为世界坐标
const cameraPosition = map.geo2world(new THREE.Vector3(116.39199596764485, 39.91047669278009, 1000 * 1000));还有模型坐标到与世界坐标的转换、屏幕坐标与世界坐标的转换等,是 threejs 的自带方法,这里就不啰嗦了。
注意
three-tile V0.10.3 版本开始,应广大网友要求,地图坐标单位由公里改为米,以与主流 GIS 类软件保持一致。
3. 坐标转换示例
如:要向地图上指定经纬度添加物体,先用 map.geo2world 将经纬度转换为世界坐标,再将物体的 position 设置为该世界坐标即可。
下面的示例地图上添加标注:
上面的代码使用 threejs 的 CSS2DRenderer 类添加标签到地图上: https://threejs.org/docs/index.html?q=css#examples/zh/renderers/CSS2DRenderer