【Unity】坐标转换经纬度方法(原理篇)

Unity坐标转换经纬度方法(线性变换)

Demo下载
Demo的使用方法

解决问题

针对缩放,旋转,翻转的两套坐标系转换。

线性变换原理

所有的线性坐标转换都是其基坐标的缩放和旋转。

变换公式

∣ a b c d ∣ ∣ O i O j ∣ = ∣ T i T j ∣ \begin{vmatrix} a & b \\ c & d\end{vmatrix}\begin{vmatrix} O_i \\ O_j\end{vmatrix}=\begin{vmatrix} T_i\\T_j\end{vmatrix} acbd OiOj = TiTj

T i = a ∗ O i + b ∗ O j T_i=a* O_i+b* O_j Ti=aOi+bOj
T j = c ∗ O i + d ∗ O j T_j= c* O_i+d* O_j Tj=cOi+dOj

Oi和Oj是变换前的坐标系的基坐标

Ti和Tj是变换后的坐标系的基坐标

所以,只有求出变换的二项式
∣ a b c d ∣ \begin{vmatrix} a & b \\ c & d \end{vmatrix} acbd

就可以完成坐标转换。

行列式创建

求取二项式,至少要知道两组变换前后的向量,且不能为平行向量,求解方法如下

        /// <summary>
        /// 求变换行列式
        /// </summary>
        /// <param name="T1">转换后向量1</param>
        /// <param name="T2">转换后向量2</param>
        /// <param name="M1">转换前向量1</param>
        /// <param name="M2">转换前向量2</param>
        /// <returns></returns>
DoubleVector4 GetChangeMatrix(DoubleVector2 T1, DoubleVector2 T2, DoubleVector2 O1, DoubleVector2 O2)
        {
            DoubleVector4 my_Matrix = new DoubleVector4();
            DoubleVector2 AB = GetVec(T1.x, T2.x, O1, O2);
            DoubleVector2 CD = GetVec(T1.y, T2.y, O1, O2);
            my_Matrix.x = AB.x;
            my_Matrix.y = AB.y;
            my_Matrix.z = CD.x;
            my_Matrix.w = CD.y;
            return my_Matrix;
        }
        #region 求变换行列式
        /// <summary>
        /// 求二维行列式的一行的两个值,用两个点反求
        /// </summary>
        /// <param name="T1">转换后向量1的x或者y</param>
        /// <param name="T2">转换后向量2的x或者y</param>
        /// <param name="M1">转换前向量1</param>
        /// <param name="M2">转换前向量2</param>
        /// <returns></returns>
        DoubleVector2 GetVec(double  T1, double T2, DoubleVector2 O1, DoubleVector2 O2)
        {
            DoubleVector2 vector = new DoubleVector2();
            double BD = ((O2.x * T1) - (T2 * O1.x)) / ((O1.y * O2.x) - (O2.y * O1.x));
            double AC = (T1 - (BD * O1.y)) / O1.x;
            vector.x = AC;
            vector.y = BD;
            return vector;
        }

这里是把ab和cd分开求解,既二个二元一次方程组
{ T 1 i = a ∗ O 1 i + b ∗ O 1 j T 2 i = a ∗ O 2 i + b ∗ O 2 j \begin{cases} T_1i=a* O_1i+b* O_1j\\ T_2i=a* O_2i+b* O_2j \end{cases} {T1i=aO1i+bO1jT2i=aO2i+bO2j
{ T 1 j = c ∗ O 1 i + d ∗ O 1 j T 2 j = c ∗ O 2 i + d ∗ O 2 j \begin{cases} T_1j=c* O_1i+d* O_1j\\ T_2j=c* O_2i+d* O_2j \end{cases} {T1j=cO1i+dO1jT2j=cO2i+dO2j

行列式应用

      #region 变换行列式应用
        /// <summary>
        /// 得到变换后的坐标
        /// </summary>
        /// <param name="Vector">变换前向量</param>
        /// <param name="ChangeMatrix">变换行列式</param>
        /// <param name="VecZero">变换后原点坐标</param>
        /// <param name="VecZero">变换前原点坐标</param>
        /// <returns></returns>
        public DoubleVector2 GetChangeVector(DoubleVector2 Vector, DoubleVector4 ChangeMatrix, DoubleVector2  TZero, DoubleVector2 OZero)
        {
            DoubleVector2 OVector2 = Vector - OZero;
            double x = (OVector2.x * ChangeMatrix.x) + (OVector2.y * ChangeMatrix.y)+ TZero.x;
            double y = (OVector2.x * ChangeMatrix.z) + (OVector2.y * ChangeMatrix.w) + TZero.y;
            DoubleVector2 vector = new DoubleVector2(x, y);
            return vector;
        }
        #endregion

实际测试

设置控制点和原点

using FrameWorkSong;
using UnityEngine;

public class ChangePoint : MonoBehaviour
{
    public DoubleVector2 TPoint;
    public DoubleVector2 OPoint { get => GetOPoint();}
    DoubleVector2 GetOPoint()
    {
        return new DoubleVector2(transform.position.x, transform.position.z);
    }
}

在地图中设置控制

将经纬度坐标填入控制点的转换结果T,求出变换二项式

最后用一个测试点乘上变换二项式。测试结果。

误差取决于控制点和原点

using UnityEngine;
using FrameWorkSong;
using System.Collections.Generic;

public class ChangeMatrixMgr : MonoBehaviour
{
    public ChangePoint Zreo;
    public ChangePoint[] Points;
    public ChangePoint test;
    List<DoubleVector2> T;//转换后的向量
    List<DoubleVector2> O;//转换前的向量
    ChangeMatrixUtil changeMatrixUtil;
    public DoubleVector4 TMatrix;
    public DoubleVector4 OMatrix;
    /// <summary>
    /// 抽取坐标
    /// </summary>
    void ExtractionCoordinate()
    {
        T = new List<DoubleVector2>();
        O = new List<DoubleVector2>();
        int length = Points.Length;
        for (int i = 0; i < length; i++)
        {
            T.Add(Points[i].TPoint - Zreo.TPoint);
            O.Add(Points[i].OPoint - Zreo.OPoint);
        }
    }
    void Start()
    {
        ExtractionCoordinate();
        changeMatrixUtil = new ChangeMatrixUtil(T, O, 1);
        TMatrix = changeMatrixUtil.TMatrix;
        OMatrix = changeMatrixUtil.OMatrix;

        test.TPoint = changeMatrixUtil.GetChangeVector(test.OPoint , changeMatrixUtil.TMatrix, Zreo.TPoint, Zreo.OPoint);
    }
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            ReadPiont();
        }
        if (Input.GetKeyDown(KeyCode.A))
        {
            test.TPoint= changeMatrixUtil.GetChangeVector(test.OPoint, changeMatrixUtil.TMatrix, Zreo.TPoint, Zreo.OPoint);
        }
    }
    void ReadPiont()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if (Physics.Raycast(ray,out hit))
        {
            DoubleVector2 vector2 = changeMatrixUtil.GetChangeVector(GetVector(hit.point), changeMatrixUtil.TMatrix, Zreo.TPoint,Zreo.OPoint);
            Debug.Log(vector2.x+"/"+ vector2.y);
        }
    }
    DoubleVector2 GetVector(Vector3 vector3)
    {
        DoubleVector2 vector2 = new DoubleVector2(vector3.x, vector3.z);
        return vector2;
    }
}



  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: 在Unity游戏开发中,有时候需要将经纬度Unity坐标进行相互转换。经纬度是用来表示地球上某一点位置的地理坐标,而Unity坐标则是用来表示游戏场景中各个对象的位置。 首先,我们来看如何将经纬度转换为Unity坐标。这个过程涉及到地球模型和坐标系的转换。首先需要了解Unity中使用的坐标系,Unity引擎使用的是左手坐标系,其中X轴是向右的,Y轴是向上的,而Z轴是向前的。 假设我们已经获得了一个地理位置的经纬度,可以通过Unity提供的API将经纬度转换为空间坐标。可以使用Unity的LocationService类来获取设备当前的地理位置信息,其中有一个属性latitude是用来表示纬度的,另一个属性longitude是用来表示经度的。 Unity中的LocationService类还提供了方法经纬度转换为Unity的空间坐标。具体的转换过程可以使用LocationService的方法:Input.compass.trueHeading可以获取真北指向的方向,然后通过一些数学计算和转换矩阵可以将经纬度转换为Unity坐标。 反过来,如果我们已经有了一个Unity坐标,想要转换为经纬度,也是可以的。可以使用Unity提供的方法Unity坐标转换为屏幕坐标,然后可以通过一些数学和地理计算,将屏幕坐标转换经纬度。 总结一下,经纬度Unity坐标之间的转换是一个比较常见的需求,在Unity游戏开发中可以使用Unity提供的LocationService类和一些数学计算方法来实现。同时,也可以利用一些第三方库来简化这个转换过程。 ### 回答2: Unity是一款流行的游戏引擎,它提供了许多实用功能来帮助开发者创建游戏。其中一个实用功能是经纬度Unity坐标之间的转换。 经纬度是地球上地理位置的表示方式,由纬度(latitude)和经度(longitude)组成。在许多应用中,我们可能需要将经纬度坐标转换Unity中的坐标系统,以便在游戏中定位和展示地理位置。 在Unity中,可以使用提供的API函数来进行经纬度Unity坐标之间的转换。首先,我们可以使用"LocationService"类来获取设备的经纬度信息。通过调用"Input.location.Start()"函数和"Input.location.lastData.latitude"和"Input.location.lastData.longitude"属性,我们可以获取到当前设备的经纬度。 接下来,我们可以将获得的经纬度信息转换为Unity坐标。这可以通过将经纬度映射到Unity的坐标系范围内来实现。一种常见的映射方式是将地球的纬度范围[-90, 90]转换为Unity的Y坐标范围[-10, 10],将地球的经度范围[-180, 180]转换为Unity的X坐标范围[-10, 10]。可以使用简单的比例缩放来完成这个映射过程。 通过将经纬度转换为Unity坐标,我们可以在游戏中使用这些坐标来定位和展示地理位置。例如,我们可以在游戏世界中创建一个物体,并将其放置在经纬度对应的Unity坐标上,以此在游戏中呈现地理位置。这对于开发基于地理位置的游戏和应用程序非常有用。 总之,Unity提供了经纬度Unity坐标之间转换的实用功能,使得开发者可以方便地在游戏中定位和展示地理位置。通过将经纬度转换为Unity坐标,我们可以使用这些坐标来在游戏中呈现地球上的地理位置。 ### 回答3: 在Unity中,经纬度Unity坐标之间的转换是一个相当实用的功能,尤其在开发地理位置相关的应用程序时。 首先,我们来看经纬度转换为Unity坐标的过程。经度表示了地球上某个点的东西方向位置,而纬度表示了地球上某个点的南北方向位置。在Unity中,我们可以使用脚本来将经纬度转换为Unity中的坐标。我们可以使用标准的经纬度坐标系,其中纬度的范围是-90到90,经度的范围是-180到180。首先,我们需要确定Unity世界中一个参考点的经纬度,然后计算指定经纬度点与参考点之间的水平和垂直距离,将其转换为Unity坐标的单位。 另一方面,Unity坐标转换经纬度也是一个常见的需求。在这种情况下,我们需要使用Unity中的Unity API来获取场景中某个物体的位置坐标,然后将其转换为经纬度值。首先,我们需要确定一个参考点的经纬度作为原点,然后计算指定点与参考点之间的水平和垂直距离。最后,通过一些数学运算和公式,我们可以将该距离转换为对应的经度和纬度值。 总结起来,经纬度Unity坐标之间的转换可以通过一些简单的数学运算和公式实现。这个功能在开发地理位置相关的应用程序时非常有用,例如在虚拟现实游戏中创建基于真实地理位置的游戏世界,或者在实际物理位置点周围放置虚拟对象等等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小生云木

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

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

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

打赏作者

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

抵扣说明:

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

余额充值