3D地图倾斜后模型位置偏移该怎么解决?
我在用Three.js和Mapbox结合做3D地图时,设置了地图倾斜(pitch),但模型的位置完全偏移了,看起来像是没跟着地形走。尝试过调整模型的z坐标和投影矩阵,控制台还报错”坐标转换超出范围”,这是怎么回事?
代码是这样写的,设置视角时:map.setPitch(60),然后用这个函数转换坐标:
function convertWGS84ToMapbox(coords) {
const {lng, lat} = coords;
const mbcoords = map.project(
new mapboxgl.LngLat(lng, lat),
map.getZoom()
);
return {x: mbcoords.x, y: mbcoords.y};
}
调整pitch后模型直接飞到屏幕外了,检查过模型坐标数据没问题,是标准的WGS84格式。是不是坐标转换需要考虑三维投影?
map.project方法上。这个方法本质上是把经纬度坐标转换成屏幕上的二维像素坐标,但它并不考虑地图的倾斜角度(pitch)和高度信息。当地图设置了一个较大的倾斜角时,模型的三维位置就不能单纯用二维投影来计算了,否则就会出现偏移甚至飞出屏幕的情况。要解决这个问题,需要引入三维空间的坐标转换,而不是仅仅依赖二维投影。具体来说,可以借助
map.unproject或者直接使用 Three.js 的场景坐标系来处理。这里推荐一个更靠谱的思路:通过 Mapbox 提供的自定义图层功能,将 Three.js 的场景与地图的相机同步起来。下面是一个改进的代码示例:
关键点在于:
1. 通过
map.unproject方法将屏幕坐标反向映射到世界坐标系,同时带上高度信息。2. 使用 Mapbox 的自定义图层功能,让 Three.js 的相机与 Mapbox 的相机保持同步。
3. 如果你的模型需要贴合地形,还需要从地形数据中获取具体的海拔高度,并将其作为第三个参数传入。
这种做法能确保模型在地图倾斜时仍然正确地贴合在地形上,不会飞出去或者偏移。调试起来可能稍微有点复杂,但效果会很稳定。如果还有问题,可以再细聊。
project方法只返回屏幕上的xy坐标,但倾斜视角下还需要考虑高度信息,也就是z轴。试试这个方法:在转换坐标时,除了xy平面,还要加上地形高度或海拔数据。可以通过Mapbox的
queryTerrainElevation方法获取指定点的高程值,然后将这个值作为模型的z坐标。具体可以这么改你的代码:
另外,记得检查模型的缩放比例和单位是否和Mapbox一致。Mapbox用的是米为单位,如果你的模型是厘米或者其他单位,还需要做一次单位转换。
最后吐槽一句,处理三维投影真是个坑,我之前也被这个问题折腾过好几次,尤其是地形数据不准的时候更头疼。不过加上高程后应该能解决你的问题了。