使用cesium进行淹没分析,其实就是绘制一个PolygonGraphics,然后改变高度(extrudedHeight),(高度可以随时间改变)。
首先先绘制一个多边形,这里有两种方式实现
一、使用Primitive的方式,这种可以做出水波的效果,但是其geometry的extrudedHeight高度不能修改,不能做出淹没分析发效果。可以使用这个绘制水波效果的多边形,另外再使用Entity方式创建一个多边形,修改其extrudedHeight,做出淹没效果。
//primitive方式创建.可以制作出水波纹效果。adapCoordi
let waterPrimitive = new Cesium.Primitive({
allowPicking: false,
asynchronous: false,
geometryInstances: new Cesium.GeometryInstance({
id: 'floodGeoInstance',
geometry: new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(points),
vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
extrudedHeight: 1,
height: 0,
}),
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
//当为 true 时,几何体应位于椭圆体的表面上,不是在其上方的恒定高度
aboveGroud: true,
material: new Cesium.Material({
fabric: {
type: 'Water',
uniforms: {
blendColor: new Cesium.Color(0, 0, 1, 0.3),
normalMap: 'http://localhost/package/纹理/waterNormals.jpg',
//频率速度设置
frequency: 200,
animationSpeed: 0.01,
amplitude: 10
}
},
})
})
});
viewer.scene.primitives.add(waterPrimitive);
效果图:
二、Entity方式
let entity = viewer.entities.add({
id: "floodEntity",
polygon: {
//hierarchy: Cesium.Cartesian3.fromDegreesArrayHeights(adapCoordi),
hierarchy: adapCoordi, //Cartesian3 点数组
closeTop: true,
closeBottom: true,
fill: true,
//获取或设置分类类型属性,指定此多边形在地面上时是否对地形、3D瓷砖或两者进行分类。
classificationType: Cesium.ClassificationType.BOTH,
material: Cesium.Color.fromAlpha(Cesium.Color.fromCssColorString("#7EA4B3"), 0.9),
perPositionHeight: true,
//一个属性,其值由回调函数延迟评估。time, result
extrudedHeight: 0,
},
});
设置extrudedHeight随时间变化,这里通过setInterval定时器和Cesium.CallbackProperty结合实现。
//设置高度随时间变化
var setFlood = setInterval(() => {
if (currentHeight < maxHeight) {
currentHeight += speed / 30; //同时除30,
//这个方法不能设置变化时间,所以将其放在setInterval里面设置执行时间间隔。
//这个参数time应该是回调函数执行的当前的朱丽叶时间,
entity.polygon.extrudedHeight = new Cesium.CallbackProperty(function(time, result) {
return currentHeight;
}, false);
if (currentHeight > maxHeight) {
currentHeight = maxHeight;
clearInterval(setFlood);
}
}
}, 1000 / 30); //同时除30,使其高度变化变得丝滑一些,避免变化太快。
全部代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="http://localhost/package/Cesium-1.81/Build/CesiumUnminified/Cesium.js"></script>
<style>
@import url(http://localhost/package/Cesium-1.81/Build/CesiumUnminified/Widgets/widgets.css);
html,
body,
#cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
#eye {
position: absolute;
width: 20%;
height: 20%;
bottom: 0;
right: 0;
z-index: 999;
background: red;
border: 1px solid burlywood;
}
#sun {
position: absolute;
width: 20%;
height: 20%;
top: 0;
left: 0;
z-index: 999;
background: rgb(250, 146, 146);
border: 1px solid burlywood;
}
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<div id="sun">
<p style="display:inline">最大高度(米):</p><input type="text" value="150" id="maxHeight">
</br>
<p style="display:inline">最小高度(米):</p><input type="text" value="0" id="minHeight">
</br>
<p style="display:inline">淹没时间(秒):</p><input type="text" value="1" id="floodSpeed">
</br>
<button onclick="drawPolygon()">绘制多边形</button>
<button onclick="flood()">淹没分析</button>
<button onclick="clean()">清除</button>
</div>
</body>
</html>
<script>
let osm = new Cesium.OpenStreetMapImageryProvider({
url: 'https://a.tile.openstreetmap.org/'
});
let viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider: osm,
contextOptions: {
webgl: {
alpha: true
}
},
selectionIndicator: false,
animation: false, //是否显示动画控件
baseLayerPicker: false, //是否显示图层选择控件
geocoder: false, //是否显示地名查找控件
timeline: false, //是否显示时间线控件
sceneModePicker: false, //是否显示投影方式控件
navigationHelpButton: false, //是否显示帮助信息控件
infoBox: false, //是否显示点击要素之后显示的信息
fullscreenButton: false
});
//取消双击事件
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
//设置homebutton的位置
Cesium.Camera.DEFAULT_VIEW_RECTANGLE =
Cesium.Rectangle.fromDegrees(110.15, 34.54, 110.25, 34.56);
//设置初始位置
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(110.20, 34.55, 3000000)
});
//开启深度检测
viewer.scene.globe.depthTestAgainstTerrain = true;
let tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: 'http://localhost/package/model/building/tileset.json'
}));
tileset.readyPromise.then(function(tileset) {
viewer.scene.primitives.add(tileset);
viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.5, -0.2, tileset.boundingSphere.radius * 1.0));
}).otherwise(function(error) {
console.log(error);
});
//清除几何
function clean() {
viewer.entities.removeAll();
};
//绘制的点数组
var adapCoordi;
var tileset1;
//淹没分析
function flood() {
viewer.scene.primitives.remove(tileset1);
if (Cesium.defined(adapCoordi)) {
//viewer.flyTo(viewer.entities.getById("floodPolygon"));
} else {
alert("请先绘制淹没范围");
return;
}
var currentHeight = parseFloat(document.getElementById("minHeight").value);
var maxHeight = parseFloat(document.getElementById("maxHeight").value);
var times = parseFloat(document.getElementById("floodSpeed").value);
var speed = (maxHeight - currentHeight) / times;
//entity方式创建.
let entity = viewer.entities.add({
id: "floodEntity",
polygon: {
//hierarchy: Cesium.Cartesian3.fromDegreesArrayHeights(adapCoordi),
hierarchy: adapCoordi,
closeTop: true,
closeBottom: true,
fill: true,
//获取或设置分类类型属性,指定此多边形在地面上时是否对地形、3D瓷砖或两者进行分类。
classificationType: Cesium.ClassificationType.BOTH,
material: Cesium.Color.fromAlpha(Cesium.Color.fromCssColorString("#7EA4B3"), 0.9),
perPositionHeight: true,
//一个属性,其值由回调函数延迟评估。time, result
extrudedHeight: 0,
},
});
//设置高度随时间变化
var setFlood = setInterval(() => {
if (currentHeight < maxHeight) {
currentHeight += speed / 30;
entity.polygon.extrudedHeight = new Cesium.CallbackProperty(function(time, result) {
return currentHeight;
}, false);
if (currentHeight > maxHeight) {
currentHeight = maxHeight;
clearInterval(setFlood);
}
}
}, 1000 / 30);
}
//绘制多边形
function drawPolygon() {
var actPoints = [];
let floatPoint;
let dynamicShape;
var handle = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
//左键
handle.setInputAction(function(movement) {
var position = viewer.scene.pickPosition(movement.position);
if (Cesium.defined(position)) {
actPoints.push(position);
if (actPoints.length < 2) {
actPoints.push(position);
}
// if (actPoints.length > 2) {
// createPolygon(actPoints)
// viewer.entities.remove(viewer.entities.getById("tempPolyline"));
// }
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//右键
handle.setInputAction(function(movement) {
var position = viewer.scene.pickPosition(movement.position);
if (Cesium.defined(position)) {
actPoints.push(position);
floatPoint = actPoints;
viewer.entities.removeAll();
actPoints = [];
createPolygon(floatPoint);
adapCoordi = floatPoint;
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK); // LEFT_DOUBLE_CLICK、RIGHT_CLICK
//移动
handle.setInputAction(function(movement) {
if (actPoints.length > 0) {
var position = viewer.scene.pickPosition(movement.endPosition);
if (Cesium.defined(position)) {
actPoints.pop();
actPoints.push(position);
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
viewer.entities.add({
id: "tempPolyline",
polyline: {
positions: new Cesium.CallbackProperty(function() {
return actPoints;
}, false),
width: 2,
extrudedHeight: 100,
material: Cesium.Color.RED.withAlpha(1),
}
});
};
//创建多边形
function createPolygon(points) {
//primitive方式创建.可以制作出水波纹效果。adapCoordi
let waterPrimitive = new Cesium.Primitive({
allowPicking: false,
asynchronous: false,
geometryInstances: new Cesium.GeometryInstance({
id: 'floodGeoInstance',
geometry: new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(points),
vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
extrudedHeight: 1,
height: 0,
}),
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
//当为 true 时,几何体应位于椭圆体的表面上,不是在其上方的恒定高度
aboveGroud: true,
material: new Cesium.Material({
fabric: {
type: 'Water',
uniforms: {
blendColor: new Cesium.Color(0, 0, 1, 0.3),
normalMap: 'http://localhost/package/纹理/waterNormals.jpg',
//频率速度设置
frequency: 200,
animationSpeed: 0.01,
amplitude: 10
}
},
})
})
});
tileset1=viewer.scene.primitives.add(waterPrimitive);
// waterPrimitive.update();
// var sui = waterPrimitive.getGeometryInstanceAttributes('floodGeoInstance');
};
</script>
整体页面
waterNormals.jpg