坐标转换
三维可视化,玩的就是坐标转换和矩阵变换,熟悉坐标系非常重要。three-tile 中包含地理坐标系、世界坐标系、模型坐标系、屏幕坐标系等。上节调整摄像机位置就是用到了经纬度到世界坐标系的转换。
拿到一个坐标,必须搞清楚它是基于哪个坐标系的,比如拿到经纬度,我们知道它是以地球中心为原点的。
1. 坐标系介绍
地理坐标系
地理坐标一般指经纬度海拔高度,或投影坐标等。经纬度海拔作为坐标更加直观,但三维场景中并不能直接使用它,需要将它转换为三维世界坐标或模型坐标才能使用。
世界坐标系
世界坐标是 WebGL(OpenGL)中的概念,一般采用右手坐标系,原点为世界中心,这个坐标是全局唯一的,也叫全局坐标系。threejs 的世界坐标 X 指向右,y 轴指向上,z 轴指向屏幕外。
模型坐标系
另一种坐标是模型坐标,也叫局地坐标系,一般是指相对于模型中心的坐标。
屏幕坐标系
屏幕坐标系是二维坐标,这个容易理解,但在三维场景中,坐标原点在屏幕左下角,y 轴向上。
three-tile 地图模型坐标
右手坐标系默认情况 y 轴是指向上的,可以看做指向天顶,z 轴指向右,也就是东。为符合人类习惯,three-tile 的模型坐标系定义 x 轴指向东,y 轴指向北,z 轴指向天顶,所以将地图模型加入场景时,可以看到一行代码:
tsmap.rotateX(-Math.PI / 2);
这句代码就是将地图旋转到世界坐标系的 xz 平面。
2. 坐标转换
threejs 提供了世界坐标、模型坐标、地理坐标之间的转换方法,three-tile 增加了一些方法用于地理坐标与这些坐标之间的转换。
名称 | 参数 | 返回 | 功能 |
---|---|---|---|
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. 坐标转换示例
一个在地图上标注位置的示例:
上面的代码使用 threejs 的 CSS2DRenderer 类添加标签到地图上: https://threejs.org/docs/index.html?q=css#examples/zh/renderers/CSS2DRenderer
TIP
CSS2DRenderer 是通过通过添加 DOM 标签到场景中实现的,使用比较简单,但如果添加的标签太多会影响速度,更好效果可以使用 sprite 或 canvas 等方式。只要理解了坐标转换,实现方式都一样。