1、实例
//createWorldTerrain(options)
//创建一个Cesium世界地形的一个CesiumTerrainProvider实例
//options的键值对:
//1、requestVertexNormals:bool类型,可选参数,默认值为false,指示客户端是否应从服务器请求其他照明信息(如果可用)的标志。
//2、requestWaterMask:bool类型,可选参数,默认值为false,指示客户端是否应该从服务器请求每个瓦片的水掩码(如果可用)
var worldTerrain = Cesium.createWorldTerrain({
requestWaterMask: true,
requestVertexNormals: true,
});
var viewer = new Cesium.Viewer("cesiumContainer", {
terrainProvider: worldTerrain,
});
//enableLighting
//指示是否使用常见光源照亮地球
//默认值false
viewer.scene.globe.enableLighting = true;
//new Cesium.EllipsoidTerrainProvider(options)
//TerrainProvider接口的一个实现类,通过镶嵌椭球面来生成地形
//options的键值对:
//1、tilingScheme
//2、ellipsoid
var ellipsoidProvider = new Cesium.EllipsoidTerrainProvider();
//new Cesium.VRTheWorldTerrainProvider(options)
//TerrainProvider接口的一个实现类,通过对从VT MAK VR TheWorld服务器检索到的高度地图进行细分来生成地形几何图形
//options的键值对:
//1、url:Resource或String类型,虚拟世界瓦片地图的URL地址
//2、ellipsoid
//3、credit
var vrTheWorldProvider = new Cesium.VRTheWorldTerrainProvider({
url: "http://www.vr-theworld.com/vr-theworld/tiles1.0.0/73/",
credit: "Terrain data courtesy VT MÄK",
});
//new Cesium.ArcGISTiledElevationTerrainProvider(options)
//TerrainProvider接口的一个实现类,通过对从ArcGIS ImageService的图块中检索到的地图进行镶嵌来生成地形几何图形
//options的键值对:
//1、url:Resource或String或Promise类型,ArcGIS ImageServer的URL地址
//2、token
//3、ellipsoid
var arcGisProvider = new Cesium.ArcGISTiledElevationTerrainProvider({
url:
"https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer",
});
Sandcastle.addToolbarMenu(
[
{
text: "CesiumTerrainProvider - Cesium World Terrain",
onselect: function () {
viewer.terrainProvider = worldTerrain;
viewer.scene.globe.enableLighting = true;
},
},
{
text: "CesiumTerrainProvider - Cesium World Terrain - no effects",
onselect: function () {
viewer.terrainProvider = Cesium.createWorldTerrain();
},
},
{
text: "CesiumTerrainProvider - Cesium World Terrain w/ Lighting",
onselect: function () {
viewer.terrainProvider = Cesium.createWorldTerrain({
requestVertexNormals: true,
});
viewer.scene.globe.enableLighting = true;
},
},
{
text: "CesiumTerrainProvider - Cesium World Terrain w/ Water",
onselect: function () {
viewer.terrainProvider = Cesium.createWorldTerrain({
requestWaterMask: true,
});
},
},
{
text: "EllipsoidTerrainProvider",
onselect: function () {
viewer.terrainProvider = ellipsoidProvider;
},
},
{
text: "VRTheWorldTerrainProvider",
onselect: function () {
viewer.terrainProvider = vrTheWorldProvider;
},
},
{
text: "ArcGISTerrainProvider",
onselect: function () {
viewer.terrainProvider = arcGisProvider;
},
},
],
"terrainMenu"
);
Sandcastle.addDefaultToolbarMenu(
[
{
text: "Mount Everest",
onselect: function () {
lookAtMtEverest();
},
},
{
text: "Half Dome",
onselect: function () {
var target = new Cesium.Cartesian3(
-2489625.0836225147,
-4393941.44443024,
3882535.9454173897
);
var offset = new Cesium.Cartesian3(
-6857.40902037546,
412.3284835694358,
2147.5545426812023
);
//lookAt(target, offset)
//使用目标和偏移设置相机位置和方向,目标必须以世界坐标表示。偏移(offset)可以是以目标为中心得本地东北向上参考帧中得笛卡尔坐标或航向/俯仰/范围。如果偏移量是笛卡尔坐标系,则它是从变换矩阵定义得参考坐标系中心得偏移量。如果偏移量是航向/俯仰/范围,则航向和俯仰角在由变换矩阵定义得参考坐标系中定义。航向是与y轴得角度,并向x轴增加。俯仰是从xy平面得旋转。正俯仰角低于平面。负俯仰角在平面得上方。范围是距离中心得距离。在二维中,必须有一个自顶向下得视图。摄像机将放在目标上方向下看。目标上方得高度将是偏移量得大小。航向将根据偏移量确定。如果无法从偏移量确定航向,则航向为北
//target:Cartesian3类型,目标在世界坐标系中得位置
//offset:Cartesian3或HeadingPitchRange类型,在以目标为中心的本地“东-北-上”参照系中与目标的偏移量
viewer.camera.lookAt(target, offset);
//lookAtTransform(transform, offset)
//使用目标和变换矩阵设置相机位置和方向。偏移可以是笛卡尔坐标或航向/俯仰/范围。如果偏移量是笛卡尔坐标系,则它是从变换矩阵定义的参考坐标系中心的偏移量。如果偏移量是航向/俯仰/范围,则航向和俯仰角在由变换矩阵定义的参考坐标系中定义。航向是与y轴的角度,并向x轴增加。俯仰是从xy平面的旋转。正俯仰角低于平面。负俯仰角在平面上方。范围是距离中心的距离。在2D中,必须有一个自顶向下的视图。相机将放置在参考框架的中心上方。目标上方的高度将是偏移量的大小。航向将根据偏移量确定。如果无法从偏移量确定航向,则航向为北
//transform:Matrix4类型,定义参考系的变换矩阵
//offset:Cartesian3或HeadingPitchRange类型,可选参数,在以目标为中心的参照系中与目标的偏移量。
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);//Cesium.Matrix4.IDENTITY,初始化为标识矩阵的不可变矩阵4实例
},
},
{
text: "San Francisco Bay",
onselect: function () {
var target = new Cesium.Cartesian3(
-2708814.85583248,
-4254159.450845907,
3891403.9457429945
);
var offset = new Cesium.Cartesian3(
70642.66030209465,
-31661.517948317807,
35505.179997143336
);
viewer.camera.lookAt(target, offset);
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
},
},
],
"zoomButtons"
);
var terrainSamplePositions;
function lookAtMtEverest() {
var target = new Cesium.Cartesian3(
300770.50872389384,
5634912.131394585,
2978152.2865545116
);
var offset = new Cesium.Cartesian3(
6344.974098678562,
-793.3419798081741,
2499.9508860763162
);
viewer.camera.lookAt(target, offset);
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
}
function sampleTerrainSuccess(terrainSamplePositions) {
var ellipsoid = Cesium.Ellipsoid.WGS84;//wgs84参考椭球
//depthTestAgainstTerrain
//如果基本体(如广告牌、多段线、标签等)应根据地形表面进行深度测试,则为True;如果这些基本体应始终绘制在地形顶部,则为false,除非它们位于地球的另一侧。针对地形的深度测试原语的缺点是,轻微的数值噪声或地形细节级别切换有时会使应在表面上的原语在其下方消失
//默认值为false
viewer.scene.globe.depthTestAgainstTerrain = true;
//suspendEvents()
//停止对实体集合得任何操作,配合resmeEvents事件,可以一次性更新大量实体
viewer.entities.suspendEvents();
//清除实体集合内容
viewer.entities.removeAll();
for (var i = 0; i < terrainSamplePositions.length; ++i) {
var position = terrainSamplePositions[i];
//在实体集合中添加实体
viewer.entities.add({
name: position.height.toFixed(1),
//cartographicToCartesian(cartographic, result)
//将提供的地图表示转换为笛卡尔表示
//cartographic:Cartographic类型,地图位置
//result:Cartesian3类型,可选参数,存储结果得对象
//返回值同上面得result
position: ellipsoid.cartographicToCartesian(position),
//获取或设置实体得billboard
billboard: {
//verticalOrigin
//指定垂直方向的属性
//VerticalOrigin类型,可选参数,默认值为VerticalOrigin.CENTER
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
//scale
//指定要应用于图像大小的比例的数字属性
//Number类型,可选参数,默认值为1
scale: 0.7,
//image
//指定用于公告牌的图像、URI或画布的属性
//string类型或HTMLCanvasElement
image: "../images/facility.gif",
},
//获取或设置实体得标签
//描述位于包含实体位置的二维标签
label: {
//text
//指定标签得文本,支持换行符
//string类型
text: position.height.toFixed(1),
//font
//指示标签得字体属性,可选,默认值'30px sans-serif'
//string类型
font: "10pt monospace",
//horizontalOrigin
//指示标签得水平原点
//HorizontalOrigin类型,可选,默认值HorizontalOrigin.CENTER
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
//pixelOffset
//指定像素偏移量得二维坐标点
//Cartesian2类型,可选,默认值Cartesian2.ZERO
pixelOffset: new Cesium.Cartesian2(0, -14),
//fillColor
//填充颜色
//Color类型,可选,默认值Color.WHITE
fillColor: Cesium.Color.BLACK,
//fillColor
//外边框颜色
//Color类型,可选,默认值Color.BLACK
outlineColor: Cesium.Color.BLACK,
//showBackground
//是否显示背景
//bool类型,默认值false
showBackground: true,
//背景颜色
//默认值new Color(0.165, 0.165, 0.165, 0.8)
backgroundColor: new Cesium.Color(0.9, 0.9, 0.9, 0.7),
//指定以像素为单位的水平和垂直背景填充
//默认值new Cartesian2(7, 5)
backgroundPadding: new Cesium.Cartesian2(4, 3),
},
});
}
//恢复对实体集合得增删改操作,可以一次性更新大量实体
viewer.entities.resumeEvents();
}
function createGrid(rectangleHalfSize) {
var gridWidth = 41;
var gridHeight = 41;
var everestLatitude = Cesium.Math.toRadians(27.988257);
var everestLongitude = Cesium.Math.toRadians(86.925145);
//new Cesium.Rectangle(west, south, east, north)
var e = new Cesium.Rectangle(
everestLongitude - rectangleHalfSize,
everestLatitude - rectangleHalfSize,
everestLongitude + rectangleHalfSize,
everestLatitude + rectangleHalfSize
);
var terrainSamplePositions = [];
for (var y = 0; y < gridHeight; ++y) {
for (var x = 0; x < gridWidth; ++x) {
//Cesium.Math.lerp(p, q, time)
//计算两个值的线性插值
//p:插值起点
//q:插值终点
//time:插值时间一般在[0.0,1.0]范围内
//返回值:插值结果
var longitude = Cesium.Math.lerp(
e.west,
e.east,
x / (gridWidth - 1)
);
var latitude = Cesium.Math.lerp(
e.south,
e.north,
y / (gridHeight - 1)
);
//new Cesium.Cartographic(longitude, latitude, height)
//由经度、纬度和高度定义的位置
var position = new Cesium.Cartographic(longitude, latitude);
terrainSamplePositions.push(position);
}
}
return terrainSamplePositions;
}
Sandcastle.addToggleButton(
"Enable Lighting",
viewer.scene.globe.enableLighting,
function (checked) {
viewer.scene.globe.enableLighting = checked;
}
);
Sandcastle.addToggleButton(
"Enable fog",
viewer.scene.fog.enabled,
function (checked) {
//fog.enable
//是否显示雾
//默认值true
viewer.scene.fog.enabled = checked;
}
);
Sandcastle.addToolbarButton(
"Sample Everest Terrain at Level 9",
function () {
var terrainSamplePositions = createGrid(0.005);
Cesium.when(
//sampleTerrain(terrainProvider, level, positions)
//通过从地形提供者请求分幅、采样和插值,为地图位置数组启动地形高度查询。插值匹配用于在指定级别渲染地形的三角形。查询是异步进行的,因此此函数返回一个在查询完成时解析的承诺。每个点的高度都会修改到位。如果由于该位置没有指定标高的地形数据或发生其他错误而无法确定高度,则高度将设置为“未定义”。与典型的制图类型一样,提供的高度是参考椭球体上方的高度(例如椭球体.WGS84)而不是高于平均海平面的高度。换句话说,如果在海洋中取样,不一定是0.0。此函数需要地形详细程度作为输入,如果需要尽可能精确地获得地形高度(即具有最大详细程度),请使用sampleTerrainMostDetailed。
//terrainProvider
//level:从中查询地形高度得地形详细级别
//postions:要随地形高度更新的位置
Cesium.sampleTerrain(
viewer.terrainProvider,
9,
terrainSamplePositions
),
sampleTerrainSuccess
);
lookAtMtEverest();
},
"sampleButtons"
);
Sandcastle.addToolbarButton(
"Sample Most Detailed Everest Terrain",
function () {
//TerrainProvider.availability
//get地形提供程序性得可用性
if (!Cesium.defined(viewer.terrainProvider.availability)) {
window.alert(
"sampleTerrainMostDetailed is not supported for the selected terrain provider"
);
return;
}
var terrainSamplePositions = createGrid(0.0005);
Cesium.when(
// sampleTerrainMostDetailed(terrainProvider, positions)
//在地形数据集的最大可用平铺级别启动sampleTerrain()请求
Cesium.sampleTerrainMostDetailed(
viewer.terrainProvider,
terrainSamplePositions
),
sampleTerrainSuccess
);
lookAtMtEverest();
},
"sampleButtons"
);
2、亲测
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<script src='https://cesium.com/downloads/cesiumjs/releases/1.79.1/Build/Cesium/Cesium.js'></script>
<link href='https://cesium.com/downloads/cesiumjs/releases/1.79.1/Build/Cesium/Widgets/widgets.css'
rel='stylesheet'>
<title>Document</title>
<style>
html,
body,
#container {
margin: 0;
padding: 0;
height: 100%;
}
</style>
</head>
<body>
<div id='container'>
<div style="position: fixed;background-color:rgba(255,255,255,0.5);z-index: 2000;">
<select id="select1" onchange="select1(this)">
<option value="1">CesiumTerrainProvider - Cesium World
Terrain</option>
<option value="2">CesiumTerrainProvider - Cesium
- no effects
World Terrain</option>
<option value="3">CesiumTerrainProvider - Cesium
World
Terrain w/ Lighting</option>
<option value="4">CesiumTerrainProvider - Cesium
World
Terrain w/ Water</option>
<option value="5">EllipsoidTerrainProvider</option>
<option value="6">VRTheWorldTerrainProvider</option>
<option value="7">ArcGISTerrainProvider</option>
</select>
<br>
<select id="select2" onchange="select2(this)">
<option value="1">珠穆朗玛峰</option>
<option value="2">半圆顶</option>
<option value="3">旧金山湾</option>
</select>
<br>
<button onclick="btn1()" style="margin-right: 50px;">9级珠穆朗玛峰地形示例</button><button
onclick="btn2()">最详细的珠穆朗玛峰地形样本</button>
<br>
<input type="checkbox" id="chk1"
onchange="viewer.scene.globe.enableLighting=document.getElementById('chk1').checked" checked>启用照明
<input type="checkbox" onchange="viewer.scene.fog.enabled=document.getElementById('chk2').checked"
id="chk2">启用雾
</div>
</div>
</body>
<script>
let worldTerrain = Cesium.createWorldTerrain({
//requestWaterMask和requestVertexNormals是可选的配置项,
//告诉Cesium是否需要请求额外的水、光数据。这两个选项默认是设为false的。
requestWaterMask: true,
requestVertexNormals: true
})
let viewer = new Cesium.Viewer('container', {
terrainProvider: worldTerrain
})
//启用光照
viewer.scene.globe.enableLighting = true
let ellipsoidProvider = new Cesium.EllipsoidTerrainProvider()
let vrTheWorldProvider = new Cesium.VRTheWorldTerrainProvider({
url: "http://www.vr-theworld.com/vr-theworld/tiles1.0.0/73/",
credit: "Terrain data courtesy VT MÄK",
});
let arcGisProvider = new Cesium.ArcGISTiledElevationTerrainProvider({
url: "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer",
});
</script>
<script>
function lookAtMtEverest() {
let target = new Cesium.Cartesian3(
300770.50872389384,
5634912.131394585,
2978152.2865545116
)
let offset = new Cesium.Cartesian3(
6344.974098678562,
-793.3419798081741,
2499.9508860763162
);
//设置相机的位置和偏移
viewer.camera.lookAt(target, offset);
}
function select1(e) {
switch (e.value) {
case '1':
viewer.terrainProvider = worldTerrain
viewer.scene.globe.enableLighting = true
break
case '2':
viewer.terrainProvider = Cesium.createWorldTerrain()
break
case '3':
viewer.terrainProvider = Cesium.createWorldTerrain({
requestVertexNormals: true
})
viewer.scene.globe.enableLighting = true
break
case '4':
viewer.terrainProvider = Cesium.createWorldTerrain({
requestWaterMask: true
})
break
case '5':
viewer.terrainProvider = ellipsoidProvider
break
case '6':
viewer.terrainProvider = vrTheWorldProvider
break
case '7':
viewer.terrainProvider = arcGisProvider
break
}
}
function select2(e) {
let target, offset
switch (e.value) {
case '1':
lookAtMtEverest()
break
case '2':
console.log('2')
target = new Cesium.Cartesian3(
-2489625.0836225147,
-4393941.44443024,
3882535.9454173897
);
offset = new Cesium.Cartesian3(
-6857.40902037546,
412.3284835694358,
2147.5545426812023
);
viewer.camera.lookAt(target, offset);
break
case '3':
target = new Cesium.Cartesian3(
-2708814.85583248,
-4254159.450845907,
3891403.9457429945
);
offset = new Cesium.Cartesian3(
70642.66030209465,
-31661.517948317807,
35505.179997143336
);
viewer.camera.lookAt(target, offset);
break
}
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
}
function createGrid(rectangleHalfSize) {
let gridWidth = 41
let gridHeight = 41
//珠峰纬度
let everestLatitude = Cesium.Math.toRadians(27.988257)
//珠峰经度
let everestLongitude = Cesium.Math.toRadians(86.925145)
let e = new Cesium.Rectangle(
everestLongitude - rectangleHalfSize,
everestLatitude - rectangleHalfSize,
everestLongitude + rectangleHalfSize,
everestLatitude + rectangleHalfSize
)
let terrainSamplePositions = []
for (let y = 0; y < gridHeight; ++y) {
for (let x = 0; x < gridWidth; ++x) {
//两点间的线性插值
let longitude = Cesium.Math.lerp(
e.west,
e.east,
x / (gridWidth - 1)
)
let latitude = Cesium.Math.lerp(
e.south,
e.north,
y / (gridHeight - 1)
)
//Cartographic(longitude,latitude,height) 由经度、维度和高度定义的位置
let position = new Cesium.Cartographic(longitude, latitude)
terrainSamplePositions.push(position)
}
}
return terrainSamplePositions
}
function sampleTerrainSuccess(terrainSamplePostions) {
let ellipsoid = Cesium.Ellipsoid.WGS84
//我们需要更多的线条来使得地形数据背后的objects能够正确地显示,
//只有最前面、最上面的objects才能是可见的。
viewer.scene.globe.depthTestAgainstTerrain = true
//暂时停止entities的所有增删改操作
viewer.entities.suspendEvents()
//清除entities中的所有实体
viewer.entities.removeAll()
for (let i = 0; i < terrainSamplePostions.length; ++i) {
let position = terrainSamplePostions[i]
viewer.entities.add({
name: position.height.toFixed(1),
position: ellipsoid.cartographicToCartesian(position),
billboard: {
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
scale: 0.7,
image: '../cesium学习/05加载和样式化实体/img/facility.gif'
},
//设置实体的标注
label: {
text: position.height.toFixed(1), //标注名称
font: '10pt monospace',
horizontalOrigin: Cesium.HorizontalOrigin.CENTER, //标注文字所在位置
pixelOffset: new Cesium.Cartesian2(0, -14),
fillColor: Cesium.Color.BLACK,
outlineColor: Cesium.Color.RED,
showBackground: true,
backgroundColor: Cesium.Color.YELLOW,
backgroundPadding: new Cesium.Cartesian2(4, 3)
}
})
}
//把队列中的所有对entities的操作,一次性执行
viewer.entities.resumeEvents()
}
function btn1() {
let terrainSamplePositions = createGrid(0.005)
//Cesium.sampleTerrain 地形高度查询
//第一个参数:地形图层加载函数
//第二个参数:从中查询地形高度的地形详细级别
//第三个参数:要查询高度的位置集合
//返回值是一个promise
Cesium.sampleTerrain(viewer.terrainProvider, 9, terrainSamplePositions).then((data) => {
sampleTerrainSuccess(data)
})
lookAtMtEverest()
}
function btn2() {
//因为地形详细级别需要最高,因此这里createGrid参数要足够小,即创建的位置集合要密集
let terrainSamplePositions = createGrid(0.0005)
//Cesium.sampleTerrainMostDetailed 地形高度查询,地形详细级别为最高
//第一个参数:地形图层加载函数
//第二个参数:要查询高度的位置集合
//返回值是一个promise
Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, terrainSamplePositions).then((data) => {
sampleTerrainSuccess(data)
})
lookAtMtEverest()
}
</script>
</html>
3、显示地形高度
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<script src='https://cesium.com/downloads/cesiumjs/releases/1.79.1/Build/Cesium/Cesium.js'></script>
<link href='https://cesium.com/downloads/cesiumjs/releases/1.79.1/Build/Cesium/Widgets/widgets.css'
rel='stylesheet'>
<title>Document</title>
<style>
html,
body,
#container {
margin: 0;
padding: 0;
height: 100%;
}
</style>
</head>
<body>
<div id='container'>
<div style="z-index: 2000;position: fixed;background-color: rgba(255, 255, 255, 0.5);">
<select onchange="selectChange(this)">
<option value="1">地点1</option>
<option value="2">地点2</option>
<option value="3">地点3</option>
</select>
</div>
</div>
</body>
<script>
let viewer = new Cesium.Viewer('container', {
//获取用于放大地形的标量
terrainExaggeration: 2,
terrainProvider: Cesium.createWorldTerrain()
})
</script>
<script>
function selectChange(e) {
switch (e.value) {
case '1':
//设置相机位置、 方向和变换
viewer.camera.setView({
destination: new Cesium.Cartesian3(
277096.634865404,
5647834.481964232,
2985563.7039122293
),
orientation: {
heading: 4.731089976107251,
pitch: -0.32003481981370063,
},
})
break
case '2':
viewer.camera.setView({
destination: new Cesium.Cartesian3(
-2497565.707296549,
-4393815.215148996,
3886033.5140598584
),
orientation: {
heading: 1.6690385899673323,
pitch: -0.32086751043096884,
},
});
break
case '3':
viewer.camera.setView({
destination: new Cesium.Cartesian3(
-2696570.092794883,
-4276051.411224011,
3887257.288168422
),
orientation: {
heading: 5.193128432412409,
pitch: -0.3996479673257727,
},
});
var target = new Cesium.Cartesian3(
-2708814.85583248,
-4254159.450845907,
3891403.9457429945
);
var offset = new Cesium.Cartesian3(
70642.66030209465,
-31661.517948317807,
35505.179997143336
);
viewer.camera.lookAt(target, offset);
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
break
}
}
</script>
</html>