UE4根据真实地图来生成行走道路

Posted monocular

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE4根据真实地图来生成行走道路相关的知识,希望对你有一定的参考价值。

上一节我们完成了数据的基础获取,现在我们需要在UE4中新建一个空白插件类,然后把上一节python文件和txt文件放在该插件类里的Content文件夹里面(作用是让UE4只需要读取相对位置就行,便于打包和其他项目使用)。

创建好C++插件工程后,我们需要创建一个函数用于读取txt里面的数据,我们可以看到txt生成的数据是double型,UE4的FVector2D位置坐标结构体是float型,所以我们需要创建一个结构体储存数据里面的double型数据,而且我们在每个拐弯处都分了段,所以创建了一个简单的结构体,用于储存每段结构的数据:

技术图片
struct FVector2D_Double

    double X;
    double Y;

    FVector2D_Double operator-(const FVector2D_Double& Other) const
    
        return FVector2D_Double(X - Other.X, Y - Other.Y);
    

    FVector2D_Double operator+(const FVector2D_Double& Other) const
    
        return FVector2D_Double(X + Other.X, Y + Other.Y);
    

    FVector2D_Double operator/(const FVector2D_Double& Other) const
    
        return FVector2D_Double(X * Other.X, Y * Other.Y);
    

    FVector2D_Double operator*(const float& Other) const
    
        return FVector2D_Double(X * Other, Y * Other);
    

    FVector2D_Double operator/(const float& Other) const
    
        return FVector2D_Double(X / Other, Y / Other);
    

    FVector2D_Double operator/(const FVector2D& Other) const
    
        return FVector2D_Double(X / Other.X, Y / Other.Y);
    

    FVector2D_Double operator*(const FVector2D& Other) const
    
        return FVector2D_Double(X * Other.X, Y * Other.Y);
    

    FVector2D_Double()
        :X(0.f), Y(0.f)
    

    FVector2D_Double(double X,double Y)
        :X(X),Y(Y)
    

    double Size() const
    
        return sqrt(X * X + Y * Y);
    
;
.h
技术图片
struct LevelArray

    unsigned int ID = 0;
    TArray<FVector2D_Double> Array;
;
.h

其中我重载了一些运算符,便于后面需要的计算,现在我们已经有了储存数据的结构,现在就需要读取txt里面的数据,我使用的是C++原生库里面的读取方法:

技术图片
#include <iostream>
#include <fstream>
#include <cassert>
#include <string>
.h
技术图片
TArray<LevelArray> LevelBaiData;
TArray<int> BaiduDataTimeAndDistance;
std::string file = TCHAR_TO_UTF8(*FPaths::ProjectPluginsDir()) + std::string("XXXXPlugins/Content/walking.txt");
    
    std::ifstream infile;
    infile.open(file.data());   //将文件流对象与文件连接起来 

    unsigned int AID = 0;

    if (infile.is_open())
    

        std::string s;
        while (getline(infile, s))
        
            std::string s1, s2, s3;
            
            std::size_t pos = s.find(",");
            if (s._Equal("------"))
            
                LevelArray A;
                AID += 1;
                A.ID = AID;
                LevelBaiData.Add(A);
            
            if (pos != std::string::npos)
            
                s1 = s.substr(0, pos);
                s2 = s.substr(pos + 1, s.size());

                FVector2D_Double v2lf = FVector2D_Double(atof(s1.c_str()), atof(s2.c_str()));
                
                FVector2D_Double A = IBToXY(v2lf); // 把经纬度转化为平面坐标
                
                LevelBaiData[LevelBaiData.Num() - 1].Array.Add(A);
            
            std::size_t pos_1 = s.find(":");
            if (pos_1 != std::string::npos)
            
                s3 = s.substr(pos_1 + 1, s.size());
                BaiduDataTimeAndDistance.Add(atoi(s3.c_str()));
            
        
        infile.close();
    
.cpp

这样我们就可以把数据存储在结构体LevelBaiDataBaiduDataTimeAndDistance里面。

我还创建了一个函数,用于把经纬度坐标转化为平面坐标,我使用的是米勒投影转换:

FVector2D_Double MyClass::IBToXY(FVector2D_Double IB)


    double L = 6378000 * PI * 2;//地球周长
    double W = L;// 平面展开后,x轴等于周长 
    double H = L / 2;// y轴约等于周长一半  
    double Mill = 2.3;// 米勒投影中的一个常数,范围大约在正负2.3之间  
    double x = IB.X * PI / 180;// 将经度从度数转换为弧度  
    double y = IB.Y * PI / 180;// 将纬度从度数转换为弧度  
    
    y = 1.25 * log(tan(0.25 * PI + 0.4 * y));// 米勒投影的转换 

    // 弧度转为实际距离  
    x = (W / 2) + (W / (2 * PI)) * x;
    y = (H / 2) - (H / (2 * Mill)) * y;

    return FVector2D_Double(x,y);

现在我们已经取得地球上的坐标数据,然后把该数据转化为UE4里的的float型数据,我们只需要知道UE4中起点位置,和缩放比例就可以实现该效果,起点位置好找,直接可以用Actor世界位置,可是缩放比例就有点难,我们可以知道UE4终点终点位置求得,也可以知道UE4地图比例就得,我使用的是获取另一个点的终点位置求得:

技术图片
FVector Delate = EndActor - StartActor;
BaiduDataXY = UpDataLevelArrayData(LevelBaiData, Number, IsIgnoreSamllLen, Number <= 0);

    FVector2D_Double StartEndVector2D = (BaiduDataXY[BaiduDataXY.Num() - 1] - BaiduDataXY[0]); //米勒投影坐标向量

    double Scale = StartEndVector2D.Size() / FVector2D(Delate.X, Delate.Y).Size();
    
    for (auto &Item : BaiduDataXY)
    
        FVector2D_Double p = (Item - BaiduDataXY[0]) / Scale;
        /*
        p.X = DistanceLngLat(BaiduData[0].X, Item.X, BaiduData[0].Y, BaiduData[0].Y) / Scale;
        p.Y = DistanceLngLat(BaiduData[0].X, BaiduData[0].X, BaiduData[0].Y, Item.Y) / Scale;
        */
        UE4Data.Add(FVector2D(p.X, p.Y));
        
    
.cpp

UpDataLevelArrayData函数用于数据均匀分段,不会出现过多或者过少的拐点,这个算法不是当堂重点,当然你们需要参考可以在后面我贴出的源码里查看。

数据我们可以读取并且可在UE4中使用,但是如果我们需要在UE4中输入经纬度,然后C++调用python函数,获取的函数在UE4中显示出来,那就在下一节我讲解一下。

项目插件源码:https://github.com/a948022284/UE4RealRoadPlanning

以上是关于UE4根据真实地图来生成行走道路的主要内容,如果未能解决你的问题,请参考以下文章

UE4从零开始制作数字孪生道路监测平台

根据谷歌地图的行车路线

UE4 性能及分析

绘制折线捕捉到道路Android谷歌地图应用程序

根据道路名称获取道路上所有经纬度解决办法

百度地图怎么设置