使用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);

效果图:

python淹没分析 cesium淹没分析_回调函数

二、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>

整体页面

python淹没分析 cesium淹没分析_回调函数_02

waterNormals.jpg

python淹没分析 cesium淹没分析_python淹没分析_03