经纬度坐标如何转成three.js或者babylon.js中的三维坐标

本文探讨了如何在three.js中根据接口返回的经纬度坐标正确渲染,涉及坐标系转换、缩放和同步问题。作者提供了从Cesium坐标到three.js的转换方法,包括手动转换和使用proj4库,以及注意事项如缩放系数的确定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求

有如下需求,根据接口返回来的经纬度坐标,要正确的在three.js中的三维场景中将数据渲染出来,或者是根据经纬度坐标绘制出物体的运动轨迹

分析

我们都知道三维three.js的渲染用的是右手笛卡坐标,并没有像cesium那样给我们提供经纬度和笛卡尔坐标的转换方式,转换的时候注意坐标的方向(是否涉及到旋转),缩放坐标原点

那我们可以借助cesium的方法将经纬度转成的卡尔坐标,然后在three.js或者babylon.js进行渲染吗?

答案是可以的,但是存在一个问题,就是坐标轴指向、原点都是不一样的,光靠一个坐标点是没办法定位,还需要坐标系的信息,在这些坐标系中,一旦涉及到旋转,那么难度将以指数的形式增加。

在three.js右手笛卡尔中表示高度是Y值,但是在cesium的笛卡尔是没办法表示高度的,只能是用经纬度表示例如(lon,lat,height),坐标系信息可以看下面的图

cesium WGS84坐标系

cesium笛卡尔坐标系

three.js坐标系

举个例子,比如cesium开发的系统,用的是cesium的笛卡尔坐标系,一辆车朝着某个方向运动,比如朝着正北方向运动,而你的系统中,比如是three.js的系统,你很难根据经纬度或者cesium的笛卡尔坐标信息将两边的运动进行同步,那怎么办呢?不妨看看下面的方法吧

实现步骤如下

步骤一:设置原点,经纬度转墨卡托,平移,墨卡托转three.js的右手笛卡尔

既然如此那我们可以手动将经纬度转成墨卡托;然后将转换后的经度对应成three.js中位置的x,维度对应成three.js中的z值即可,但是用过cesium或者openlayers的兄弟都应该知道,经过转换的坐标,数值上是非常大的,这对我们的无论是计算还是啥的都不方便,我们可以先指定一个坐标原点,接下里输入的坐标,都以这个原点定位,相当于做了一个平移,这个才坐标转换是常用的手段

步骤二:正确缩放

在坐标轴指向和尺度上来看,首先是指向,当时向着正东方向运动时经纬度的经度会增加,此时对于的three.js中的x会增加,维度亦是如此

重点:WGS84坐标经纬度转成墨卡托,再放到三维场景定位存在一定的缩放,缩放系数要根据场景的大小,如何确定呢,比如在一些卫星底图下载软件,你要下载直径5公里的底图,但是发现得到的是大于5公里的,那缩放系数就是实际得到的直径出于输入的直径,当我们要一比一还原实际场景的时候,建模时也要按照这个系数进行缩放;

接下来是代码实现,代码每个方法的命名就是注释,应该挺好看懂的,分别有两个版本,一个是通过手动将经纬度转墨卡托(伪墨卡托3857),另一个是通过proj4

步骤三:旋转

这里不涉及到旋转,跳过

以下babylon.js版本(左手坐标系),three.js(右手坐标系)

export default class CoordinateConverter {
    private centerMercX: number;
    private centerMercY: number;

    constructor(private centerLng: number, private centerLat: number) {
        // 将中心点的经纬度转换成墨卡托坐标
        const { mercX, mercY } = this.latLngToMercator(centerLng, centerLat);
        this.centerMercX = mercX;
        this.centerMercY = mercY;
    }

    // 经纬度转换为 Web 墨卡托
    private latLngToMercator(lng: number, lat: number): { mercX: number, mercY: number } {
        const mercX = (lng * 20037508.34) / 180;
        let mercY = Math.log(Math.tan(((90 + lat) * Math.PI) / 360)) / (Math.PI / 180);
        mercY = (mercY * 20037508.34) / 180;
        return { mercX, mercY };
    }

    // 墨卡托坐标转换为 Babylon.js 的 xz 平面坐标
    private mercatorToBabylon(mercX: number, mercY: number): { x: number, z: number } {
        const x = (mercX - this.centerMercX ) * -2.53;
        const z = (mercY - this.centerMercY) * -2.53;
        return { x, z };
    }

    // 将经纬度转换为 Babylon.js 的 xz 平面坐标
    public latLngToBabylon(lng: number, lat: number): { x: number, z: number } {
        const { mercX, mercY } = this.latLngToMercator(lng, lat);
        return this.mercatorToBabylon(mercX, mercY);
    }
}

为什么上面说要乘以一个缩放系数-2.53,正负修正坐标系轴指向(babylon.js),three.js的方向不一样正负值要改一下,缩放值这个是手动调整的,建模的时候被缩放了吧

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奥德坤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值