UE4 C++ 通过gdal2.3.1插件读取矢量数据文件
程序员文章站
2022-06-10 23:27:19
...
此处读取的线类型的文件,不过其他类型的都相差不大,可作为参考。
#include <gdal.h>
#include <cpl_conv.h>
#include <gdal_priv.h>
#include <ogrsf_frmts.h>
#include <HAL/FileManager.h>
#include <HAL/FileManagerGeneric.h>
#include <ogr_spatialref.h>
bool readPolylineShp(const FString &filename, TArray<TArray<FVector>> &pts)
{
IFileManager& mgr = IFileManager::Get();
// if this file exist, else exit!
if (mgr.FileExists(*filename))
{
UE_LOG(LogTemp, Log, TEXT("This .shp file exist. %s"), *filename);
//注册所有的文件格式驱动,这个函数注册了GDAL/OGR支持的所有格式
GDALAllRegister();
CPLSetConfigOption("SHAPE_ENCODING", "");
//下一步我们将打开输入的OGR数据文件。数据文件可以是文件,关系型数据库,文件路径,甚至可能是远程的网络服务,这点取决于我们使用的驱动。
//但是,数据源的名字通常只是一个简单的字符串。既然这样拿我们就编写一个打开shapefile的程序。
//第二个参数(FLALSE)告诉OGRSFDriverRegistrar::Open() 函数我们不需要update access。如果失败返回NULL,并报错。
GDALDataset *poDS;
poDS = (GDALDataset*)GDALOpenEx(TCHAR_TO_UTF8(*filename), GDAL_OF_VECTOR, NULL, NULL, NULL);
if (poDS == NULL)
{
UE_LOG(LogTemp, Log, TEXT("Failed in opening adding shp file:%s"), *filename);
GDALDestroyDriver(poDS);
return false;
}
//一个OGRDataSource可能包含很多的层。所包含层的数量我们可以用过调 OGRDataSource::GetLayerCount()得到,
//并且其中每一个曾我们利用索引调用OGRDataSource::GetLayer()得到。也可以利用层的名字得到。
int layerN = poDS->GetLayerCount();
UE_LOG(LogTemp, Log, TEXT("layer count is::%d"), layerN);
OGRLayer *poLayer;
poLayer = poDS->GetLayer(0);
if (poLayer == NULL)
{
UE_LOG(LogTemp, Error, TEXT("Failed in getting layer in existing .shp file:%s"), *filename);
GDALDestroyDriver(poDS);
return false;
}
// get vertexes on lines
pts.Empty();
OGREnvelope rect;
poLayer->GetExtent(&rect);
//自从我们开始fresh with这个层,就没有这么严格了。很明智地我们需要调用Layer::ResetReading()来确保我们是从层的开头开始。
poLayer->ResetReading();
// 现在我们开始读取层里面的features。在开始之前我们需要指定一个attribute或者spatial filter来严格控制我们得到的feature。不过现在我们只是得到所有的features。
OGRSpatialReference *source = poLayer->GetSpatialRef(); // geographical projection information
//#设置输出坐标系为WGS84
// OGRSpatialReference target;
// OGRErr err2 = target.importFromEPSG(32650);//32650通过qgis软件查看得到epsg WGS84
// char* text = nullptr;
// source->exportToWkt(&text);//导出打印wkt
// UE_LOG(LogTemp, Log, TEXT("source: %s"), text);
// target.exportToWkt(&text);//导出打印wkt
// UE_LOG(LogTemp, Log, TEXT("target: %s"), text);
//
// if (err2 != OGRERR_NONE)
// {
// UE_LOG(LogTemp, Error, TEXT("target: %s"), text);
// return false;
// }
//初始化坐标转换类,防止文件中存储的不是wgs84坐标系
// OGRCoordinateTransformation *coord = OGRCreateCoordinateTransformation(source, &target);
//
// int iFeatureCount = poLayer->GetFeatureCount();
// pts.Reset(iFeatureCount);
OGRFeature *poFeature = NULL;
while ((poFeature = poLayer->GetNextFeature()) != NULL)
{
//feature里面提取出几何(geometry)数据
OGRGeometry *poGeometry = poFeature->GetGeometryRef();
OGRwkbGeometryType geotype;
geotype = poGeometry->getGeometryType();
OGRLineString *poLine = NULL;
//确定这个几何数据的类型,如果是点,我们将他标为点并且进行操作,如果是其他的内省我们write占位符。这里的类型是多段线
if (wkbLineString == geotype)
{
poLine = (OGRLineString*)poGeometry;
int pNUM = poLine->getNumPoints();
pts.Add(TArray<FVector>());
for (int i = 0; i < pNUM; ++i)
{
double X = poLine->getX(i);
double Y = poLine->getY(i);
double Z = poLine->getZ(i);
// 进行坐标转换
// coord->Transform(1, &X, &Y, &Z);
pts[flag_line].Add(FVector(X, Y, Z));
}
}
delete poLine;
}
//资源清理
GDALClose(poDS);
return true;
}
UE_LOG(LogTemp, Error, TEXT("This .shp file is not exist! %s"), *filename);
return false;
}