OpenStreetMap (简称 OSM) 系列(3 / 5) --- dem-postgis 搭建
DEM(Digital Elevation Model,数字高程模型)是根据经纬度坐标来查询对应高度及精度的服务
- 安装依赖
apt install -y gdal-bin
验证依赖安装情况
gdal_translate --version 创建对应目录
mkdir -p /var/www/html/osm/dem && cd /var/www/html/osm/dem && mkdir raw tif postgresdem 目录
├── raw 原始 DEM
└── tif 转换后的 tif下载 dem 文件
cd raw && vi download_china_dem.shsh 脚本内容
#!/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 ../将下载的 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合并所有的 tif
gdal_merge.py -o /var/www/html/osm/dem/postgres/china_dem.tif tif/*.tif运行(根据自己机器的配置来调整
--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进入容器开启
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应用
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]); }
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭