海洋 / 军工 / 仿真
一、地形
ETOPO1
特点:
- 分辨率:1 arc-minute(≈1.8km)
- 许可证:开源,可商用
1.下载数据集
数据集:ETOPO1 Global Relief Model
由上图可见,首先有两种选择:Ice Surface(推荐) 与 Bedrock。前者是表面高度(视觉更自然),陆地、海洋连续,适合做地形影像;后者冰盖被“挖掉”,主要用于冰川研究。
选择了 Ice Surface 之后,又有两种选择:grid-registered(推荐)与 cell-registered。前者与经纬度网格严格对齐;后者是由前者衍生出来的,为做数值模拟而生,用它做可视化会有半个像素的偏移(该影像分辨率约1.8km,则半像素偏移大约是900m的偏移)。
点击georeferenced tiff链接后跳转到下载页面:
下载压缩包到本地,并解压,得到 ETOPO1_Ice_g_geotiff.tif。
2.数据集切片
可以使用 Cesium Terrain Builder(CTB) 来生成 .terrain 文件。我这里用的是 docker 版的CTB(tum-gis/cesium-terrain-builder-docker )。
- 下载docker并启动
- 拉取CTB镜像:
docker pull tumgis/ctb-quantized-mesh - 运行容器并将本机文件夹挂载到容器的data目录下:
docker run -it --name ctb -v "D:/path/to/ETopoFolder:/data" tumgis/ctb-quantized-mesh(这里 -v的参数是<本地路径>:<容器内路径>,后面跟着一个空格再加上<镜像名>,本地路径必须是绝对路径) - 上条命令执行完后,默认进入到容器的data目录,此时可以通过
ls查看当前目录下的文件,有个ETOPO1_Ice_g_geotiff.tif - 通过
mkdir -p tiles创建一个名为tiles的文件夹,用来存放切片后的数据 - 切片:
ctb-tile -f Mesh -C -N -o tiles ETOPO1_Ice_g_geotiff.tif。如果tif文件较大,这一过程会比较漫长,这里这个tif有445MB,切片花了将近1小时。正常切完是这样的输出:0...10...20...30...40...50...60...70...80...90...100 - done. 可以打开本机上刚刚挂载那个目录(D:/path/to/ETopoFolder/tiles)能看到切片后的文件夹与里面的文件 - 生成 layer.json 说明文件:
ctb-tile -f Mesh -C -N -l -o tiles ETOPO1_Ice_g_4326.tif。这条命令只是多了个-l的参数,跑完后可在本机刚刚挂载那个目录(D:/path/to/ETopoFolder/tiles)里看到有个layer.json文件
可能遇到的问题:
(1). ctb-tile -f Mesh -C -N -o tiles ETOPO1_Ice_g_geotiff.tif报错:Error: The source dataset does not have a spatial reference system assigned. 这是说文件没有SRS(spatial reference system,空间参考系),此时执行gdalinfo ETOPO1_Ice_g_geotiff.tif可以看到Coordinate System is 这样的空输出,可以执行gdal_translate -a_srs EPSG:4326 ETOPO1_Ice_g_geotiff.tif ETOPO1_Ice_g_4326.tif来指定SRS,此时通过gdalinfo ETOPO1_Ice_g_geotiff.tif查看新文件的信息,可以看到Coordinate System is: GEOGCS["WGS 84", DATUM["WGS_1984", SPHEROID["WGS 84",6378137,298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich",0], UNIT["degree",0.0174532925199433], AUTHORITY["EPSG","4326"]]这样的输出,然后可以拿这个新文件切片了。
(2). 切片时,如果文件较大,那么这一过程会比较漫长,而且CPU、内存占用较高,此时做其他操作很卡。例如之前我切过1个7GB的tif,花了两三个小时。而且最终只生成了2-10级的切片,也就是说0、1级切片没有,我检查了一下发现2级切片也不全,索性rm -r 2删除了2这个文件夹。接下来就是要单独生成0-2级切片:ctb-tile -f Mesh -C -N -o tiles ETOPO1_Ice_g_4326.tif -s 2 -e 0,参数的意义,可以通过ctb-tile --help来查看。然后我这条命令也报错了,这里官方文档也提到了:tum-gis/cesium-terrain-builder-docker, 他说,在处理大型数据集时,在低缩放级别上可能有溢出问题,建议使用 gdal_translate 由现在的7G的tif文件创建出一个低分辨率的、所占空间更小的tif文件,而后在新的tif文件上执行切片。按他说的来,执行gdal_translate -outsize 5% 5% ETOPO1_Ice_g_4326.tif ETOPO1_lower.tif将原文件的宽高各缩小至5%,再用新的tif生成低缩放级别的terrain文件:ctb-tile -f Mesh -C -N -o terrain ETOPO1_lower.tif -s 2 -e 0
3.nginx发布切片
server {
listen 8114;
server_name localhost;
root D:/Map/ETOPO/terrain;
autoindex on;
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
location ~* .terrain$ {
add_header Content-Disposition 'attachment;filename=$arg_filename';
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Content-Encoding "gzip";
add_header Content-Type "application/octet-stream";
}
}
}
4.Cesium加载地形
我这里用的cesium版本为1.83,里面有些API可能在新版本里弃用了。建议大家用旧版本的cesium,除非你用到了新版本中独有的特性。因为我在开发某个项目时,用了一个第三方对于cesium封装的库,该库使用了cesium@1.131,然后凡是有cesium的页面都卡顿,凡是没有cesium的页面就正常,而且我把cesium@1.131换成cesium@1.83就不卡顿了。
const viewer = new Cesium.Viewer('cesiumContainer', {
infoBox: false, // * Blocked script execution in 'about:blank' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.
geocoder: false, // * 右上角搜索按钮
homeButton: false, // * 右上角地图恢复到初始页面按钮
sceneModePicker: false, // * 右上角2D和3D之间的切换
baseLayerPicker: false, // * 右上角图层选择器
navigationHelpButton: false, // * 右上角帮助按钮
animation: false, // * 左下角圆盘 速度控制器
creditsDisplay: false, // * 商标版权与数据源
timeline: false, // * 页面下方的时间条
fullscreenButton: false, // * 右下角全屏按钮,
selectionIndicator: false, // 禁用选中指示器
imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
enablePickFeatures: false,
}),
terrainProvider: new Cesium.CesiumTerrainProvider({
url: 'http://localhost:8114/', // 自定义地形服务的 URL
})
});
// 地形夸张
viewer.scene.globe.terrainExaggeration = 10;
5.运行时效果
GEBCO
特点:
- 分辨率:15 arc-second(≈460m)
- 许可证:开源,可商用
1.下载数据集
下载压缩包 gebco_2025_geotiff.zip 到本地,解压后得到如下文件:
2.数据集切片
像前面一样,依然采用docker版的CTB来切片。
- 下载docker => 拉取CTB镜像 => 运行容器并挂载目录。这些跟前面一样不再赘述。
- 默认进入到容器的data目录,可以通过
ls命令查看当前目录下的文件,有8个tif,按 经纬度四象限 × 南北半球 切成 8 块。 - 虚拟拼接:
gdalbuildvrt tiles.vrt *.tif这条命令把所有tif文件拼接成一个总的虚拟的数据集。 - 切片:
ctb-tile -f Mesh -C -N -o tiles tiles.vrt由于这个数据集很大,我从13:48开始切片,到14:18用了半小时才切了5%,这么算下来得10个小时才能切完。 - 后续生成layer.json等操作跟前面一样。
可能遇到的问题:
(1). 0...10...20...30...40...50...60...70...80...90...Killed. 没有切完,AI说可能是可能内存不够导致的。打开切片观察最里层的文件,最里层最后一个是1024.terrain、512.terrain这种2的整数倍的文件,说明这几层是切完了的,我从10层检查到3层都没问题,第二层虽然是以4.terrain结束的,但是前面没有0-3的terrain文件,而第0层、第1层压根没有。那这样直接删除第二层并重新生成0-2层:ctb-tile -f Mesh -C -N -o tiles tiles.vrt -s 2 -e 0,0...10...20..Killed 这里也kill了。那按照前面ETOPO1问题(2)中所说的,先调低分辨率再试一下:gdal_translate -outsize 5% 5% tiles.vrt tiles_lower.vrt => ctb-tile -f Mesh -C -N -o tiles tiles_lower.vrt -s 2 -e 0这次成功了。别忘了生成layer.json文件。
3.nginx发布切片
同上
server {
listen 8116;
server_name localhost;
root D:/Map/GEBCO/terrain;
autoindex on;
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
location ~* .terrain$ {
add_header Content-Disposition 'attachment;filename=$arg_filename';
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Content-Encoding "gzip";
add_header Content-Type "application/octet-stream";
}
}
}
4.Cesium加载地形
同上
const viewer = new Cesium.Viewer('cesiumContainer', {
infoBox: false, // * Blocked script execution in 'about:blank' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.
geocoder: false, // * 右上角搜索按钮
homeButton: false, // * 右上角地图恢复到初始页面按钮
sceneModePicker: false, // * 右上角2D和3D之间的切换
baseLayerPicker: false, // * 右上角图层选择器
navigationHelpButton: false, // * 右上角帮助按钮
animation: false, // * 左下角圆盘 速度控制器
creditsDisplay: false, // * 商标版权与数据源
timeline: false, // * 页面下方的时间条
fullscreenButton: false, // * 右下角全屏按钮,
selectionIndicator: false, // 禁用选中指示器
imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
enablePickFeatures: false,
}),
terrainProvider: new Cesium.CesiumTerrainProvider({
url: 'http://localhost:8116/', // 自定义地形服务的 URL
})
});
// 地形夸张
viewer.scene.globe.terrainExaggeration = 10;
5.运行时效果
这个地形切片最大层级为10,ETOPO1切片最大层级为8,很明显下图中的山峰的棱角格外分明(相较于ETOPO1)。
二、影像
ETOPO1
1.下载数据集
同上,得到 ETOPO1_Ice_g_geotiff.tif ,但这是DEM(高程数据),不是影像(RGB/Byte),所以需要 DEM 先变影像,影像再切瓦片。
2.给地形上色
可以使用GDAL来上色,我这里用的是 docker 版的 gdal
- 下载docker并启动
- 拉取gdal镜像:
docker pull osgeo/gdal:ubuntu-full-3.6.3 - 运行容器并将本机文件夹挂载到容器的data目录下:
docker run -it --name gdal -v "D:/path/to/ETopoFolder:/data" osgeo/gdal:ubuntu-full-3.6.3(这里 -v的参数是<本地路径>:<容器内路径>,后面跟着一个空格再加上<镜像名>,本地路径必须是绝对路径) - 上条命令执行完后,默认进入到容器的根目录,通过
cd data进入data目录,可以通过ls查看当前目录下的文件,有个ETOPO1_Ice_g_geotiff.tif - 先解决坐标系的问题:
gdal_translate -a_srs EPSG:4326 ETOPO1_Ice_g_geotiff.tif ETOPO1_Ice_g_4326.tif - 然后创建颜色映射文件
执行完成后可以通过cat > color.txt << 'EOF' # 海洋突出配色方案 # 海洋:4级蓝色,详细分级 -10000 10 20 80 # 深海 -4000 40 70 130 # 中深海 -1000 80 130 180 # 浅海 0 120 180 220 # 海岸 # 陆地:5级,柔和颜色 1 200 210 170 # 沿海区(很窄) 50 170 180 140 # 低地(平原) 300 140 150 120 # 丘陵 1000 120 120 100 # 山地 2000 100 95 90 # 高山 4000 180 180 180 # 雪山 EOFcat color.txt看一眼是不是有了 - 染色:
gdaldem color-relief ETOPO1_Ice_g_4326.tif color.txt relief_color.tif,得到输出文件 relief_color.tif ,可以在本机查看这个tif(可以当成普通图片查看)
3.数据集切片
我用的是 osgearth_package 来切片,这个工具在后面我分享的链接里也有。
- 在
osgearth_package目录下创建.earth文件 map.earth(注意这里的相对路径要写好)<map name="SouthHemisphereMap"> <image name="MyTiffImage"> <driver>gdal</driver> <url>path/to/relief_color.tif</url> </image> </map> - 在
osgearth_package目录下打开cmd执行osgearth_packages.exe --tms map.earth --out D:/Map/output_tiles --max-level 6 --verbose - 执行完后便可在对应目录(我这里是D:/Map/output_tiles)下看到切片
也可以通过GDAL来切片,不过效果不是很好,还多出很多无用的kml文件:gdal2tiles.py -p geodetic -z 0-6 relief_color.tif tiles
4.nginx发布切片
server {
listen 8115;
server_name localhost;
location / {
root D:/Map/ETOPO/imagery;
autoindex on;
add_header Access-Control-Allow-Origin *;
add_header Cache-Control "no-cache,must-revalidate";
try_files $uri $uri/ /index.html;
}
}
5.Cesium加载影像
const viewer = new Cesium.Viewer('cesiumContainer', {
infoBox: false, // * Blocked script execution in 'about:blank' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.
geocoder: false, // * 右上角搜索按钮
homeButton: false, // * 右上角地图恢复到初始页面按钮
sceneModePicker: false, // * 右上角2D和3D之间的切换
baseLayerPicker: false, // * 右上角图层选择器
navigationHelpButton: false, // * 右上角帮助按钮
animation: false, // * 左下角圆盘 速度控制器
creditsDisplay: false, // * 商标版权与数据源
timeline: false, // * 页面下方的时间条
fullscreenButton: false, // * 右下角全屏按钮,
selectionIndicator: false, // 禁用选中指示器
imageryProvider: new Cesium.TileMapServiceImageryProvider({
url: 'http://localhost:8115/', // 自定义影像服务的 URL
fileExtension: 'png',
minimumLevel: 0,
maximumLevel: 6
}),
terrainProvider: new Cesium.CesiumTerrainProvider({
url: 'http://localhost:8114/', // 自定义地形服务的 URL
})
});
或者采用UrlTemplateImageryProvider:
const viewer = new Cesium.Viewer('cesiumContainer', {
infoBox: false, // * Blocked script execution in 'about:blank' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.
geocoder: false, // * 右上角搜索按钮
homeButton: false, // * 右上角地图恢复到初始页面按钮
sceneModePicker: false, // * 右上角2D和3D之间的切换
baseLayerPicker: false, // * 右上角图层选择器
navigationHelpButton: false, // * 右上角帮助按钮
animation: false, // * 左下角圆盘 速度控制器
creditsDisplay: false, // * 商标版权与数据源
timeline: false, // * 页面下方的时间条
fullscreenButton: false, // * 右下角全屏按钮,
selectionIndicator: false, // 禁用选中指示器
// imageryProvider: new Cesium.TileMapServiceImageryProvider({
// url: 'http://localhost:8115/',
// fileExtension: 'png',
// minimumLevel: 0,
// maximumLevel: 6
// }),
imageryProvider: new Cesium.UrlTemplateImageryProvider({
url: 'http://localhost:8115/{z}/{x}/{reverseY}.png',
minimumLevel: 0,
maximumLevel: 6,
// tilingScheme: new Cesium.WebMercatorTilingScheme(), // 默认采用投影坐标系(EPSG:3857)
tilingScheme: new Cesium.GeographicTilingScheme() // 实际该用地理坐标系(EPSG:4326)
}),
terrainProvider: new Cesium.CesiumTerrainProvider({
url: 'http://localhost:8114/', // 自定义地形服务的 URL
})
});
6.运行时效果
GEBCO
1.下载数据集
还是用的地形数据集,同样需要染色。
2.给地形上色
- 下载docker => 拉取CTB镜像 => 运行容器并挂载目录。这些跟ETOPO1处理方式一样不再赘述。
- 默认进入容器根目录,通过
cd data进入data目录,创建颜色映射文件:cat > color.txt << 'EOF' # 海洋突出配色方案 # 海洋:4级蓝色,详细分级 -10000 10 20 80 # 深海 -4000 40 70 130 # 中深海 -1000 80 130 180 # 浅海 0 120 180 220 # 海岸 # 陆地:5级,柔和颜色 1 200 210 170 # 沿海区(很窄) 50 170 180 140 # 低地(平原) 300 140 150 120 # 丘陵 1000 120 120 100 # 山地 2000 100 95 90 # 高山 4000 180 180 180 # 雪山 EOF - 染色:
gdaldem color-relief tiles.vrt color.txt relief_color.tif注意这里虽然输入是.vrt,但输出一定是.tif
3.数据集切片
跟ETOPO1一样,采用 osgearth_package 来切片,注意 .earth 文件里的路径。
4.nginx发布切片
server {
listen 8117;
server_name localhost;
location / {
root D:/Map/GEBCO/imagery;
autoindex on;
add_header Access-Control-Allow-Origin *;
add_header Cache-Control "no-cache,must-revalidate";
try_files $uri $uri/ /index.html;
}
}
5.Cesium加载影像
const viewer = new Cesium.Viewer('cesiumContainer', {
infoBox: false, // * Blocked script execution in 'about:blank' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.
geocoder: false, // * 右上角搜索按钮
homeButton: false, // * 右上角地图恢复到初始页面按钮
sceneModePicker: false, // * 右上角2D和3D之间的切换
baseLayerPicker: false, // * 右上角图层选择器
navigationHelpButton: false, // * 右上角帮助按钮
animation: false, // * 左下角圆盘 速度控制器
creditsDisplay: false, // * 商标版权与数据源
timeline: false, // * 页面下方的时间条
fullscreenButton: false, // * 右下角全屏按钮,
selectionIndicator: false, // 禁用选中指示器
// imageryProvider: new Cesium.TileMapServiceImageryProvider({
// url: 'http://localhost:8117/',
// fileExtension: 'png',
// minimumLevel: 0,
// maximumLevel: 6
// }),
imageryProvider: new Cesium.UrlTemplateImageryProvider({
url: 'http://localhost:8117/{z}/{x}/{reverseY}.png',
minimumLevel: 0,
maximumLevel: 6,
// tilingScheme: new Cesium.WebMercatorTilingScheme(), // 默认采用投影坐标系(EPSG:3857)
tilingScheme: new Cesium.GeographicTilingScheme() // 实际该用地理坐标系(EPSG:4326)
}),
terrainProvider: new Cesium.CesiumTerrainProvider({
url: 'http://localhost:8116/', // 自定义地形服务的 URL
})
});
6.运行时效果
由于染色文件跟前面ETOPO1相同,所以影像切片的结果也跟ETOPO1相同,换个染色方案就不一样了。
三、切片后的数据
大家可以用我切好的数据:Cesium离线地形影像