G
Q
Q
and
M
E

cesium.js入门基础教程三 (地形)

地形简介

Cesium默认是不包含地形的,准确的说应该是Cesium默认加载的地形是没有起伏效果的,如下图所示,在包含山脉的地区是看不到地形起伏的:

默认使用的地形为 "WGS84 Ellipsoid":

地形提供者 TerrainProvider

与影像类似,在Cesium中包含了一些地形提供者TerrainProvider用于加载各类地形,举例如下,具体情况可参阅官方文档:

  • ArcGISTiledElevationTerrainProvider:由ArcGIS提供的地形服务;
  • CesiumTerrainProvider:由Cesium官方提供的地形服务;
  • CustomHeightmapTerrainProvider:自定义高程的地形服务;
  • EllipsoidTerrainProvider:高程为 0 的地形服务,如果初始化时不指定地形,那么默认的就是使用的该地形服务;
  • GoogleEarthEnterpriseTerrainProvider:由GoogleEarth提供的地形服务;
  • VRTheWorldTerrainProvider:由VRTheWorld提供的地形服务。

加载地形的方法

与加载影像图层十分类似,加载地形的方法也有两种:

  • 在初始化viewer的时候添加;
  • 通过viewer.terrainProvider赋值添加

注意,一个视图下只能加载一个地形
而影像图层是可以加载多个的,同一视图下可以叠加多个影像;
另外,从语义上来说,每一个影像图层都是一个imageryLayer,所有的imageryLayer都是通过ImageryLayerCollection来管理,添加一个影像图层用的方法是addImageryProvider,注意add
而对于地形来说,是直接给viewer.terrainProvider赋值的

初始化Viewer时添加地形

在初始化Viewer时在第二个参数Viewer.ConstructorOptions中添加terrainProvider属性并提供一个TerrainProvider对象:

const viewer = new Cesium.Viewer("cesiumContainer", {
  terrainProvider: new Cesium.ArcGISTiledElevationTerrainProvider({
    url: 'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer',
  })
})

通过viewer.terrainProvider赋值添加

通过viewer.terrainProvider赋值添加的代码如下:

const viewer = new Cesium.Viewer("cesiumContainer")
const ArcGisTerrainProvider = new Cesium.ArcGISTiledElevationTerrainProvider({
  url: 'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer',
})
viewer.terrainProvider = ArcGisTerrainProvider

地形提供者示例

与影像类似,在Cesium中提供了一些地形提供者TerrainProvider用于加载各类地形,列举如下,具体情况请参阅官方文档:

  • ArcGISTiledElevationTerrainProvider:由ArcGIS提供的地形服务;
  • CesiumTerrainProvider:由Cesium官方提供的地形服务;
  • CustomHeightmapTerrainProvider:自定义高程的地形服务;
  • EllipsoidTerrainProvider:高程为 0 的地形服务,如果初始化时不指定地形,那么默认的就是使用的该地形服务;
  • GoogleEarthEnterpriseTerrainProvider:由GoogleEarth提供的地形服务;
  • VRTheWorldTerrainProvider:由VRTheWorld提供的地形服务。

ArcGISTiledElevationTerrainProvider

加载Arcgis地形服务的代码如下:

const viewer = new Cesium.Viewer("cesiumContainer")
const terrainProvider = new Cesium.ArcGISTiledElevationTerrainProvider({
  url: 'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer',
})
viewer.terrainProvider = terrainProvider

加载后的效果如下:

CesiumTerrainProvider

CesiumTerrainProvider用于加载自行发布的地形服务或其他地形服务商发布的地形服务

自行发布的地形服务

加载自行发布的地形服务代码如下,其中https://localhost/terrain为地形服务的URL

const viewer = new Cesium.Viewer("cesiumContainer")
viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
  url: "https://localhost/terrain" 
})
火星科技地形 版权归火星科技所有,在此仅作为学习交流所用,侵删。

加载火星科技地形的代码如下:

const viewer = new Cesium.Viewer("cesiumContainer")
viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
  url: 'http://data.marsgis.cn/terrain',
})

加载后的效果如下:

maptiler地形

加载maptiler地形的伪代码如下,需要访问maptiler官网注册账号获取key:

const viewer = new Cesium.Viewer("cesiumContainer")
const maptilerKey = 'xxx'
viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
  url: `https://api.maptiler.com/tiles/terrain-quantized-mesh/?key=${maptilerKey}`,
  requestVertexNormals: true
})

加载后的效果如下:

CustomHeightmapTerrainProvider

加载自定义高程地形的代码如下,通过回调函数callback获取高程,这个TerrainProvider用的很少:

const viewer = new Cesium.Viewer("cesiumContainer")
let width = 64
let height = 64
viewer.terrainProvider = new Cesium.CustomHeightmapTerrainProvider({
  callback: (x, y, level) => {
    let buffer = new Float32Array(width * height)
    for (let yy = 0; yy < height; yy++) {
      for (let xx = 0; xx < width; xx++) {
        let v = (y + yy / (height - 1)) / Math.pow(2, level)
        let heightValue = 8000 * (Math.sin(4000 * v) * 0.5 + 0.5)
        let index = yy * width + xx
        buffer[index] = heightValue
      }
    }
    return buffer
  },
  width: width,
  height: height,
})

EllipsoidTerrainProvider

EllipsoidTerrainProvider是高程为 0 的地形,若初始化时不指定地形,那么默认的就是使用的该地形服务,加载EllipsoidTerrainProvider的代码如下:

const viewer = new Cesium.Viewer("cesiumContainer")
viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider()

Cesium ion 地形

加载Cesium ion提供的地形代码如下:

viwer.terrainProvider = Cesium.createWorldTerrain();

加载后的效果,能看到明显的起伏:

使用参数requestWaterMask还可以为虚拟地球的海面添加流动效果,代码如下:

const viewer = new Cesium.Viewer("cesiumContainer")
const terrainProvider = Cesium.createWorldTerrain({
  requestWaterMask: true, // 请求水体效果所需要的海岸线数据
})
viewer.terrainProvider = terrainProvider

地形等高线

开启地形等高线后的效果如下:

开启地形等高线的代码如下:

/**
 * @description: 
 * @param {*} width 等高线的线宽,单位px
 * @param {*} spacing 等高线的高度间隔,单位m
 * @param {*} color 等高线的颜色,Cesium.Color
 * @return {*}
 */    
function contourLine(width, spacing, color) {
  let material = Cesium.Material.fromType("ElevationContour")
  material.uniforms.width = width
  material.uniforms.spacing = spacing
  material.uniforms.color = color
  viewer.scene.globe.material = material
}

// 等高线的线宽为2px,高度间隔为100m,颜色为红色
contourLine(2.0, 100, Cesium.Color.RED)
posted @ 2023-12-14 10:33  sy0313  阅读(753)  评论(0编辑  收藏  举报