Unity实用功能之经纬度和Unity坐标之间转换| 8月更文挑战

3,381 阅读4分钟

概述

在做模拟仿真的项目时,有时候需要加载地图上某一块的地貌和建筑,这时候我们只知道这些建筑在地图上的经纬度坐标,并不知道其在Unity中的世界坐标,那么如何才能将所有建筑按照真实地图显示出来就成了一个问题,本篇文章主要介绍的就是,如何通过经纬度,计算出其在Unity中的世界坐标。

注:因为Unity中的Vector3是float,所以本文中使用的是float类型的数据,精准度会有些许偏差,如果对精准度要求比较高,还请自己重写下Unity的Vector,将其重写为double类型的,在换算过程中我将使用double,只是最后返回值得时候会转成float。

思路分析

经纬度组合起来就是一个Vector2类型的数据。我们首先在Unity中创建两个点,两个点的位置就是一个正方形(长方形等)的对角线的位置即可,分别在地图上找到两个点的经纬度,也就是使用这两点,在地图上圈出来一个范围,将找到的这个两个点的经纬度,分别赋给在Unity中创建的两个点,这样我们在Unity中的范围位置,就和显示地图中的位置相对应了起来,在通过其坐标的X,Z轴的值和经纬度的差值,从而计算出坐标。具体示意图如下:

image.png

image.png 上图中,只要将图二中的AB点的经纬度,赋值给图一种AB点,即可通过坐标差,实时计算出由AB两点组成的正方形内的所有点的坐标

功能实现

上图中两个球就是确定位置的关键点。如果这两个点都没有确定好,那么一切都是白扯。 说通俗一点就是,已知A,B的位置和对应的数值,和 C 的位置,让你求 C 对应的值,是一个道理。 而我们在程序中们可以使用动态设置这两个定位点的位置,而不用一遍遍使用手动调节。

在程序中,我们还可以通过获取中心点的经纬度,通过向左右加减的方式,确定两角的坐标,这样做的好处就是不论是什么样的经纬度都可以计算出,并且不超出定位点单的范围。

首先进行程序的初始化,先确定两个定位点的坐标,以及两个坐标点在Unity中的经纬度的差

//本案例中是直接确定经纬度,不是通过中间点加减确定的
//点1
BottomRightSai = new Vector2(113.98071f, 22.52864f);
//点2
TopLeftSai = new Vector2(80.15071f, 40.56864f);
z_offset = BottomRightSai.y - TopLeftSai.y;//地图中的维度差  
x_offset = BottomRightSai.x - TopLeftSai.x;//地图中的经度差  
z_w_offset = BottomRightPoint.position.z - TopLeftPoint.position.z;//unity中的维度差  
x_w_offset = BottomRightPoint.position.x - TopLeftPoint.position.x;//unity中的经度差

接下来是通过已知的经纬度,计算出该点在Unity中的坐标

注:此方法没法计算出在Unity中的高度,所有物体的Y轴是固定的,同定位点。如果想要使用高度,需要Unity读取灰度图才能够获取到高度

    /// <summary>
    /// 由经纬度得到位置点  
    /// </summary>
    /// <param name="se"></param>
    /// <returns></returns>
    public Vector3 GetWorldPoint(Vector2 se)
    {
        double tempX = se.x - TopLeftSai.x;
        double tempZ = se.y - BottomRightSai.y;
        double _tempX = (tempX * x_w_offset / x_offset + TopLeftPoint.position.x);//计算X轴
        double _tempZ = (tempZ * z_w_offset / z_offset + BottomRightPoint.position.z);//计算Z轴
        //获取该点世界坐标
        return new Vector3((float)_tempX, 0, (float)_tempZ);
    }

由Unity坐标逆推经纬度同样的原理,还是上面提到的问题,经纬度一般都是double数据,此方法中使用的是float,精准度会有偏差,如果定位点范围较大可能不会有大影响,但是范围如果很小偏差可能会比较明显

    /// <summary>
    /// 由位置点得到经纬度  
    /// </summary>
    /// <param name="curPoint"></param>
    /// <returns></returns>
    public Vector3 GetLatLon(Vector3 curPoint)
    {
        //坐标偏差
        double _x_offset = (curPoint.x - BottomRightPoint.position.x) * x_offset / x_w_offset;
        double _z_offset = (curPoint.z - TopLeftPoint.position.z) * z_offset / z_w_offset;
        double resultX = _x_offset + BottomRightSai.x;
        double resultZ = _z_offset + TopLeftSai.y;
        return new Vector2((float)resultX, (float)resultZ);
    }

到这里在Unity中经纬度转和世界坐标互转的功能就实现了,如果还有不明白的可以多研究下代码,其实原理还是很好理解的,案例源代码会在之后整理好之后放出。

注意

此案例功能比较单一,精准度由于float和double之间的转换,会有些许偏差,介意的同学请绕道。

写在最后

整体项目案例会在后期整理好之后分享给大家,如有错误之处还请多多指出。