DEM(Digital Elevation Model,数字高程模型)是根据经纬度坐标来查询对应高度及精度的服务

  1. 安装依赖
    apt install -y gdal-bin
    验证依赖安装情况
    gdal_translate --version
  2. 创建对应目录
    mkdir -p /var/www/html/osm/dem && cd /var/www/html/osm/dem && mkdir raw tif postgres

    dem 目录
    ├── raw 原始 DEM
    └── tif 转换后的 tif
  3. 下载 dem 文件

    cd raw && vi download_china_dem.sh

    sh 脚本内容

    #!/bin/bash
    
    # 中国区域范围
    MIN_LAT=18
    MAX_LAT=54
    
    MIN_LON=73
    MAX_LON=136
    
    # 下载目录
    DIR="./china_hgt"
    mkdir -p $DIR
    cd $DIR
    
    for lat in $(seq $MIN_LAT $((MAX_LAT-1)))
    do
    
        for lon in $(seq $MIN_LON $((MAX_LON-1)))
        do
    
            # 纬度名称
            if [ $lat -ge 0 ]; then
                LAT_NAME="N$(printf "%02d" $lat)"
            else
                LAT_ABS=$(( -lat ))
                LAT_NAME="S$(printf "%02d" $LAT_ABS)"
            fi
    
            # 经度名称
            if [ $lon -ge 0 ]; then
                LON_NAME="E$(printf "%03d" $lon)"
            else
                LON_ABS=$(( -lon ))
                LON_NAME="W$(printf "%03d" $LON_ABS)"
            fi
    
            FILE=${LAT_NAME}${LON_NAME}.hgt.gz
            echo "Downloading $FILE"
            wget -c "https://s3.amazonaws.com/elevation-tiles-prod/skadi/N${lat}/${FILE}"
    
        done
    
    done
    

    执行下载

    chmod +x download_china_dem.sh && ./download_china_dem.sh
    cd china_hgt && gunzip *.hgt.gz && mv china_hgt/*.hgt ./ && rm -rf china_hgt && cd ../
    
  4. 将下载的 hgt 格式原始文件转换为 tif 格式

    vi convert.sh

    内容

    find ./raw -name "*.hgt" | while read file
    do
    
        name=$(basename $file .hgt)
        echo "Convert $name"
    
        gdal_translate \
        -of GTiff \
        $file \
        tif/${name}.tif
    
    done
    

    执行

    chmod +x convert.sh && ./convert.sh
    
  5. 合并所有的 tif

    gdal_merge.py -o /var/www/html/osm/dem/postgres/china_dem.tif tif/*.tif
    
  6. 运行(根据自己机器的配置来调整--shm-size)

    docker run -d \
     --name dem-postgis \
     --shm-size=4g \
     -e POSTGRES_USER=postgres \
     -e POSTGRES_PASSWORD=PGDBPWD123 \
     -e POSTGRES_DB=dem \
     -p 9082:5432 \
     -v /var/www/html/osm/dem/postgres:/var/lib/postgresql/data \
     postgis/postgis:16-3.4
    
  7. 进入容器开启PostGIS Raster及导入数据

    进入容器安装相关服务

    docker exec -it dem-postgis bash
    apt update
    apt install -y postgis postgresql-16-postgis-3
    

    进入数据库

    psql -U postgres -d dem
    

    开启 PostGIS Raster

    CREATE EXTENSION postgis_raster;
    

    退出数据库

    \q
    

    执行导入(还是在容器中)

    raster2pgsql -d -s 4326 -I -C -M -t 256x256 /var/lib/postgresql/data/china_dem.tif dem | psql -U postgres -d dem
    
  8. 应用

    public static function dem(float $lat, float $lng)
    {
        return DB::connection('pgsql_dem')->selectOne("
            SELECT
                ST_Value(
                    rast,
                    ST_SetSRID(
                        ST_Point(?, ?),
                        4326
                    )
                ) AS elevation
            FROM dem
            WHERE ST_Intersects(
                rast,
                ST_SetSRID(
                    ST_Point(?, ?),
                    4326
                )
            )
            LIMIT 1
        ", [$lng, $lat, $lng, $lat]);
    }