Unity Cesium C# 调用GDAL库计算地形高度

需求说明:

在使用Cesium unity开发的时候,遇到一个需求需要根据经纬度获取对应的地形高度。经过查询资料,这个功能在Cesium网页端比较简单,但是在Unity端并没有相关的功能接口。于是需要自己通过其他方式实现。

经过查询资料,发现GDAL开源库可以直接实现该功能,并且性能极高。于是确定采用GDAL进行计算。

集成步骤:

网上有很多中集成方式,有自己下载源码编译的,有在Unity中试用NuGet for unity下载的,还有一些其他的,但是都很麻烦。

下面我介绍一下我使用的集成方式,非常简单方便,目前没有发现有什么问题,如果有谁知道这种方式有什么问题,还请留言交流。

1.新建一个c# VS工程:

2.打开NuGet的管理窗口

3.下载安装两个包:gdal、gdal.native

4.写个获取高度的代码运行一下:

using System;
using GDALTest;
using OSGeo.GDAL;
using OSGeo.OSR;

class Program
{
    static void Main()
    {
        GdalConfiguration.ConfigureGdal();
        Gdal.AllRegister();

        string demFilePath = "D:/gisdata/450mDEM.tif"; // 替换为实际的 DEM 文件路径
        double longitude = 120.0; // 替换为实际的经度
        double latitude = 30.0; // 替换为实际的纬度

        double height = CalculateHeight(demFilePath, longitude, latitude);
        Console.WriteLine($"指定经纬度的高度为: {height}");
        Console.ReadLine();
    }

    static double CalculateHeight(string filePath, double longitude, double latitude)
    {
        Dataset ds = Gdal.Open(filePath, Access.GA_ReadOnly);

        if (ds == null)
        {
            Console.WriteLine("无法打开文件");
            return -1;
        }

        double[] adfGeoTransform = new double[6];
        ds.GetGeoTransform(adfGeoTransform);

        double dTemp = adfGeoTransform[1] * adfGeoTransform[5] - adfGeoTransform[2] * adfGeoTransform[4];
        double dCol = (adfGeoTransform[5] * (longitude - adfGeoTransform[0]) - adfGeoTransform[2] * (latitude - adfGeoTransform[3])) / dTemp + 0.5;
        double dRow = (adfGeoTransform[1] * (latitude - adfGeoTransform[3]) - adfGeoTransform[4] * (longitude - adfGeoTransform[0])) / dTemp + 0.5;

        int dc = Convert.ToInt32(dCol);
        int dr = Convert.ToInt32(dRow);

        Band band = ds.GetRasterBand(1);
        float[] data = new float[1 * 1];
        CPLErr err = band.ReadRaster(dc, dr, 1, 1, data, 1, 1, 0, 0);
        band.Dispose();

        return (double)data[0];
    }
}

5.运行后,进入后生成的exe文件夹,将文件夹中的除了exe之外的其他文件全部复制,粘贴到Unity的Plugins文件夹中。

gdal文件夹里有x64和x86两个平台的库。进到Unity里后,你需要删除不用的那个

7.Unity中新建一个测试脚本,挂到场景里物体上运行:

using OSGeo.GDAL;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GDALTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Gdal.AllRegister();

        string demFilePath = "D:/gisdata/450mDEM.tif"; // 替换为实际的 DEM 文件路径
        double longitude = 120.0; // 替换为实际的经度
        double latitude = 30.0; // 替换为实际的纬度

        double height = CalculateHeight(demFilePath, longitude, latitude);
    }



    static double CalculateHeight(string filePath, double longitude, double latitude)
    {
        Dataset ds = Gdal.Open(filePath, Access.GA_ReadOnly);

        if (ds == null)
        {
            Console.WriteLine("无法打开文件");
            return -1;
        }

        double[] adfGeoTransform = new double[6];
        ds.GetGeoTransform(adfGeoTransform);

        double dTemp = adfGeoTransform[1] * adfGeoTransform[5] - adfGeoTransform[2] * adfGeoTransform[4];
        double dCol = (adfGeoTransform[5] * (longitude - adfGeoTransform[0]) - adfGeoTransform[2] * (latitude - adfGeoTransform[3])) / dTemp + 0.5;
        double dRow = (adfGeoTransform[1] * (latitude - adfGeoTransform[3]) - adfGeoTransform[4] * (longitude - adfGeoTransform[0])) / dTemp + 0.5;

        int dc = Convert.ToInt32(dCol);
        int dr = Convert.ToInt32(dRow);

        Band band = ds.GetRasterBand(1);
        float[] data = new float[1 * 1];
        CPLErr err = band.ReadRaster(dc, dr, 1, 1, data, 1, 1, 0, 0);
        band.Dispose();

        return (double)data[0];
    }
}

8.调用成功

9.总结

总的来说一共就3步:

第一步:在VS工程里下载好库,生成一下。

第二步:生成的文件放到Unity的Plugins文件夹下,并且删除不用的平台库文件。

第三步:成功。

在性能上,GDAL非常高校,经过测试,读取5个G的地形文件,一次性进行5万次高度计算获取,总耗时50ms,完全不会影响效率。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值