cesium之淹没分析

news/2024/7/24 13:14:25 标签: vue.js

发现最近成长很多,之前测距测面于我来说,做起来遥不可及,现在不到半天的工作时间便做出了淹没分析,当然也是参考的了

参考:mumu122 - 博客园

前提地图要设置了地形~

1、vue 前端代码

<div class="sub_ana_container" v-show="showFlowTool">
      <div class="saclose" @click="closeFlowTool">x</div>
      <label>最大高度:</label>
      <input type="number" v-model="height_max">
      <label>最小高度:</label>
      <input type="number" v-model="height_min">
      <label>淹没速度:</label>
      <input type="number" v-model="speed">
      <button class="btn" v-on:click="startFlowing()">开始</button>
      <button class="btn" v-on:click="clearFlowing()">清除</button>
      <button class="btn" v-on:click="draw_ymfw()">绘制淹没范围</button>
    </div>

2、css样式

.sub_ana_container {
  position: absolute;
  right: 20%;
  top: 1%;
  width: auto;
  height: auto;
  border: solid 1px;
  padding: 12px;
  color: rgb(221, 218, 218);
  background-color: rgba(6, 89, 161, 0.8);
}
.saclose{
  position: absolute;
  right: 5px;
  top: 3px;
  cursor: pointer;
}
.btn {
  color: white;
  background-color: #555758;
  border: #555758;
  margin: 6px;
}
input {
  width: 100px;
}
label {
  margin: 8px;
  color: rgb(221, 218, 218);
}
input[type="radio"] {
  width: 30px;
}

3、methods方法使用

// 淹没分析------------------------
    closeFlowTool() {
      this.showFlowTool = false
    },
    drawFlowingPolygon() {
      const flowing_draw = new SubmergenceAnalysis()
    },
    draw_polygon() {
      const _this = this
      var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
      // 取消双击事件-追踪该位置
      viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
        Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
      )
      // 鼠标事件
      handler = new Cesium.ScreenSpaceEventHandler(
        viewer.scene._imageryLayerCollection
      )
      var positions = []
      var tempPoints = []
      var polygon = null
      var cartesian = null
      var floatingPoint

      handler.setInputAction(function (movement) {
        const ray = viewer.camera.getPickRay(movement.endPosition)
        cartesian = viewer.scene.globe.pick(ray, viewer.scene)
        // cartesian = viewer.scene.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid);
        if (positions.length >= 2) {
          if (!Cesium.defined(polygon)) {
            polygon = new PolygonPrimitive(positions)
          } else {
            positions.pop()
            positions.push(cartesian)
          }
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)

      handler.setInputAction(function (movement) {
        const ray = viewer.camera.getPickRay(movement.position)
        cartesian = viewer.scene.globe.pick(ray, viewer.scene)
        // cartesian = viewer.scene.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
        if (positions.length == 0) {
          positions.push(cartesian.clone())
        }
        // positions.pop();
        positions.push(cartesian)
        // 在三维场景中添加点
        var cartographic = Cesium.Cartographic.fromCartesian(
          positions[positions.length - 1]
        )
        var longitudeString = Cesium.Math.toDegrees(cartographic.longitude)
        var latitudeString = Cesium.Math.toDegrees(cartographic.latitude)
        var heightString = cartographic.height
        tempPoints.push({
          lon: longitudeString,
          lat: latitudeString,
          hei: heightString
        })
        _this.tempPoints.push(longitudeString)
        _this.tempPoints.push(latitudeString)
        // floatingPoint = viewer.entities.add({
        //   name: '多边形面积',
        //   position: positions[positions.length - 1],
        //   point: {
        //     pixelSize: 5,
        //     color: Cesium.Color.WHITE,
        //     outlineColor: Cesium.Color.DEEPSKYBLUE,
        //     outlineWidth: 3
        //   }
        // })
        // measureFeature_polygon.push(floatingPoint)
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

      handler.setInputAction(function (movement) {
        handler.destroy()
        positions.pop()
        // var polyCenter = Cesium.BoundingSphere.fromPoints(positions).center
        // var textArea = getArea(tempPoints) + 'km²'
        // const _label = viewer.entities.add({
        //   name: '多边形面积',
        //   position: polyCenter,
        //   // position: positions[positions.length - 1],
        //   label: {
        //     text: textArea,
        //     font: '16px sans-serif',
        //     fillColor: Cesium.Color.DARKORANGE,
        //     heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
        //   }
        // })
        // measureFeature_polygon.push(_label)
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)

      var radiansPerDegree = Math.PI / 180.0 // 角度转化为弧度(rad)
      var degreesPerRadian = 180.0 / Math.PI // 弧度转化为角度

      // 计算多边形面积
      function getArea(points) {
        var res = 0
        // 拆分三角曲面
        for (var i = 0; i < points.length - 2; i++) {
          var j = (i + 1) % points.length
          var k = (i + 2) % points.length
          var totalAngle = Angle(points[i], points[j], points[k])

          var dis_temp1 = distance(positions[i], positions[j])
          var dis_temp2 = distance(positions[j], positions[k])
          res += dis_temp1 * dis_temp2 * Math.abs(Math.sin(totalAngle))
          console.log(res)
        }

        return (res / 1000000.0).toFixed(4)
      }
      function logPosition (position) {
        var ray = viewer.camera.getPickRay(position)
        var cartesian = viewer.scene.globe.pick(ray, viewer.scene)
        var cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(cartesian)
        var long2 = Cesium.Math.toDegrees(cartographic.longitude)
        var lat2 = Cesium.Math.toDegrees(cartographic.latitude)
        console.log(long2 + ',' + lat2)
      }

      /* 角度 */
      function Angle(p1, p2, p3) {
        var bearing21 = Bearing(p2, p1)
        var bearing23 = Bearing(p2, p3)
        var angle = bearing21 - bearing23
        if (angle < 0) {
          angle += 360
        }
        return angle
      }
      /* 方向 */
      function Bearing(from, to) {
        var lat1 = from.lat * radiansPerDegree
        var lon1 = from.lon * radiansPerDegree
        var lat2 = to.lat * radiansPerDegree
        var lon2 = to.lon * radiansPerDegree
        var angle = -Math.atan2(
          Math.sin(lon1 - lon2) * Math.cos(lat2),
          Math.cos(lat1) * Math.sin(lat2) -
            Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2)
        )
        if (angle < 0) {
          angle += Math.PI * 2.0
        }
        angle = angle * degreesPerRadian // 角度
        return angle
      }

      var PolygonPrimitive = (function () {
        function _(positions) {
          this.options = {
            name: '多边形',
            polygon: {
              hierarchy: [],
              // perPositionHeight : true,
              material: new Cesium.Color(0, 124 / 255, 247 / 255, 0.2)
              // material: Cesium.Color.GREEN.withAlpha(0.5)
              // heightReference:20000
            }
          }

          this.hierarchy = { positions }
          this._init()
        }

        _.prototype._init = function () {
          var _self = this
          var _update = function () {
            return _self.hierarchy
          }
          // 实时更新polygon.hierarchy
          this.options.polygon.hierarchy = new Cesium.CallbackProperty(
            _update,
            false
          )
          const _polygon = viewer.entities.add(this.options)
          measureFeature_polygon.push(_polygon)
        }

        return _
      })()

      function distance(point1, point2) {
        var point1cartographic = Cesium.Cartographic.fromCartesian(point1)
        var point2cartographic = Cesium.Cartographic.fromCartesian(point2)
        /** 根据经纬度计算出距离**/
        var geodesic = new Cesium.EllipsoidGeodesic()
        geodesic.setEndPoints(point1cartographic, point2cartographic)
        var s = geodesic.surfaceDistance
        // console.log(Math.sqrt(Math.pow(distance, 2) + Math.pow(endheight, 2)));
        // 返回两点之间的距离
        s = Math.sqrt(
          Math.pow(s, 2) +
            Math.pow(point2cartographic.height - point1cartographic.height, 2)
        )
        return s
      }
    },
    draw_ymfw() {
      this.draw_polygon()
    },
    startFlowing() {
      if (!this.obj) {
        this.obj = new SubmergenceAnalysis(
          viewer,
          true,
          this.height_max,
          this.height_min,
          this.speed,
          true,
          this.tempPoints
        )
      }
      this.obj.tempPoints = this.tempPoints
      this.obj.start()
    },
    clearFlowing() {
      this.obj && this.obj.clear()
      this.clearMeasureFeature()
      this.tempPoints = []
      this.obj = null
    }

4、淹没分析的js文件   submerg-analysis.js

引入js

import SubmergenceAnalysis from '../../public/static/cesium/submerg-analysis'

submerg-analysis.js

// 淹没分析
export default class SubmergenceAnalysis {
    constructor(viewer, isTerrain = true, height_max, height_min, speed, map_type, tempPoints) {
        debugger
        this.viewer = viewer
        this.isTerrain = isTerrain
        this.handler = null
        this.tempEntities = []
        this.polygonEntities = []
        this.linePositionList = []

        this.pointArr = []
        this.lineEntities = []

        this.tempPoints = []
        this.extrudedHeight = height_min
        this.height_max = height_max
        this.height_min = height_min
        this.speed = speed
        // 默认是范围图/深度图
        this.map_type = map_type
        this.polygon_degrees = tempPoints
        // this.polygon_degrees = [
        //     117.8396128404095, 24.758688509239484,
        //     118.0106511230382, 24.797143096351466,
        //     117.8429783463796, 24.651905270780798,
        //     118.03641195329993, 24.68701116597361
        //     // 115.8784, 40.0198,
        //     // 115.9473, 40.0381,
        //     // 115.9614, 40.0073,
        //     // 115.9042, 39.9912
        // ]
        this._initViewStatus(this.viewer)
        this._addDisListener()
    }

    _initViewStatus(viewer) {
        var scene = viewer.scene
        scene.globe.depthTestAgainstTerrain = true
        // scene.camera.setView({
        //     // 摄像头的位置
        //     destination: Cesium.Cartesian3.fromDegrees(117.80189427650359, 24.700148777225785, 1500.0),
        //     // destination: Cesium.Cartesian3.fromDegrees(115.9216, 39.9870, 1500.0),
        //     orientation: {
        //         heading: Cesium.Math.toRadians(0.0), // 默认朝北0度,顺时针方向,东是90度
        //         pitch: Cesium.Math.toRadians(-20), // 默认朝下看-90,0为水平看,
        //         roll: Cesium.Math.toRadians(0)// 默认0
        //     }
        // })
        viewer.skyAtmosphere = false
    }

    // 根据矩形范围得到行列数点坐标和高程信息
    _getPoints(xmin, xmax, ymin, ymax) {
        const x_count = 10
        const y_count = 10
        const cartesians = new Array(x_count * y_count)
        const x_d = (xmax - xmin) / x_count
        for (var i = 0; i < x_count; ++i) {
            const start_pt = { x: xmin + i * x_d, y: ymax }
            const end_pt = { x: xmin + i * x_d, y: ymin }
            for (let j = 0; j < y_count; j++) {
                const offset = j / (y_count - 1)
                const x = Cesium.Math.lerp(start_pt.x, end_pt.x, offset)
                const y = Cesium.Math.lerp(start_pt.y, end_pt.y, offset)
                cartesians[j + i * y_count] = Cesium.Cartographic.fromDegrees(x, y)
            }
        }
        return cartesians

    }

    _getHeights(cartesians, extrudedHeight, callback) {
        debugger
        var terrainProvider = new Cesium.CesiumTerrainProvider({
            url: 'http://localhost:8080/o_lab'
        })
        // 根据地形计算某经纬度点的高度
        var promise = Cesium.sampleTerrainMostDetailed(terrainProvider, cartesians)
        Cesium.when(promise, function (updatedPositions) {

            let positions = updatedPositions.filter(d => {
                const cartographic = d
                if (cartographic) {
                    const h_d = extrudedHeight - cartographic.height
                    return h_d > 0
                }
            })
            positions = positions.map(d => {
                const cartographic = d
                const h = extrudedHeight - cartographic.height
                return {
                    x: Cesium.Math.toDegrees(cartographic.longitude),
                    y: Cesium.Math.toDegrees(cartographic.latitude),
                    value: h
                }

            })

            if (callback) {

                callback(positions)
            }
        })
    }

    _addDisListener() {
        const viewer = this.viewer
        const scene = viewer.scene
        const linePositionList = this.linePositionList
        viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)
        this.handler = new Cesium.ScreenSpaceEventHandler(scene.canvas)
        // 绘制线
        this._drawLine(linePositionList)
        // this.loadGrandCanyon()
        // 绘制面
        if (this.map_type) {
            this._drawPoly(this.polygon_degrees)
        } else {
            // 得到插值网格
            const bounds = {
                west: 115.8784,
                east: 115.9614,
                south: 39.9912,
                north: 40.0381
            }
            
            const positions_cartesian = this._getPoints(bounds.east, bounds.west, bounds.south, bounds.north)
            this._getHeights(positions_cartesian, this.extrudedHeight, (d) => {
                // this.heatMapObj = new HeatMap(this.viewer, d, bounds)
            })
        }

    }

    _reDraw() {
        this.tempPoints = []
        this.linePositionList.length = 0
        this.areaPositionList.length = 0
        for (const entity of this.tempEntities) {
            this.viewer.entities.remove(entity)
        }
        this.tempEntities = []
    }

    _drawLine(linePositionList) {
        const lineStyle = {
            width: 2,
            material: Cesium.Color.CHARTREUSE
        }

        const entity = this.viewer.entities.add({
            polyline: lineStyle
        })

        entity.polyline.positions = new Cesium.CallbackProperty(function () {
            return linePositionList
        }, false)

        this.polygonEntities.push(entity)
    }

    _drawPoint(point_Cartesian3) {
        const entity =
            this.viewer.entities.add({
                position: point_Cartesian3,
                point: {
                    pixelSize: 10,
                    color: Cesium.Color.GOLD
                    // disableDepthTestDistance: Number.POSITIVE_INFINITY,
                    // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
                }
            })
        this.tempEntities.push(entity)
    }


    _drawPoly(degrees) {
        const that = this
        const entity =
            this.viewer.entities.add({
                polygon: {
                    hierarchy: {},
                    material: new Cesium.Color.fromBytes(64, 157, 253, 100),
                    perPositionHeight: true

                }
            })
        entity.polygon.hierarchy = new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(degrees))
        entity.polygon.extrudedHeight = new Cesium.CallbackProperty(() => that.extrudedHeight, false)
        this.polygonEntities.push(entity)
    }

    // 世界坐标转经纬坐标
    _car3ToLatLon(cartesian) {
        const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
        const longitudeString = Cesium.Math.toDegrees(cartographic.longitude)
        const latitudeString = Cesium.Math.toDegrees(cartographic.latitude)
        return {
            lon: longitudeString,
            lat: latitudeString,
            height: cartographic.height
        }
    }


    // 移除整个资源
    remove() {
        const viewer = this.viewer
        for (const tempEntity of this.tempEntities) {
            viewer.entities.remove(tempEntity)
        }
        for (const lineEntity of this.polygonEntities) {
            viewer.entities.remove(lineEntity)
        }
        this.handler.destroy()
    }

    start() {
        const that = this
        this.timer = window.setInterval(() => {
            if ((that.height_max > that.extrudedHeight) && (that.extrudedHeight >= that.height_min)) {
                that.extrudedHeight = that.extrudedHeight + that.speed
            } else {
                that.extrudedHeight = that.height_min
            }
            if (!that.map_type) {
                if (this.heatMapObj) {
                    const bounds = {
                        west: 115.8784,
                        east: 115.9614,
                        south: 39.9912,
                        north: 40.0381
                    }
                    const positions_cartesian = this._getPoints(bounds.east, bounds.west, bounds.south, bounds.north)
                    this._getHeights(positions_cartesian, this.extrudedHeight, (d) => {
                        this.heatMapObj.update(d)
                    })
                }
            }

        }, 500)
        if (that.map_type) {
            that._drawPoly(that.polygon_degrees)
        } else {
            if (this.heatMapObj) { }

        }

    }

    clear() {
        const viewer = this.viewer
        if (this.timer) {
            window.clearInterval(this.timer)
            this.timer = null
        }
        this.extrudedHeight = this.height_min
        if (this.heatMapObj) { this.heatMapObj.show(false) }
        for (const entity of this.polygonEntities) {
            viewer.entities.remove(entity)
        }
        viewer.skyAtmosphere = true
    }

    changeMapType(type) {
        if (!type) {
            if (!this.heatMapObj) {
                // 得到插值网格
                const bounds = {
                    west: 115.8784,
                    east: 115.9614,
                    south: 39.9912,
                    north: 40.0381
                }
                const positions_cartesian = this._getPoints(bounds.east, bounds.west, bounds.south, bounds.north)
                this._getHeights(positions_cartesian, this.extrudedHeight, (d) => {
                    // this.heatMapObj = new HeatMap(this.viewer, d, bounds)
                })
            }

            this.heatMapObj && this.heatMapObj.show(true)
            for (const entity of this.polygonEntities) {
                entity.show = false
            }
        } else {
            this.heatMapObj.show(false)
            for (const entity of this.polygonEntities) {
                entity.show = true
            }
        }
    }

    // 切割一部分地形
    loadGrandCanyon() {
        var globe = this.viewer.scene.globe
        const viewer = this.viewer
        // viewer.skyAtmosphere = false,
        // Pick a position at the Grand Canyon
        var position = Cesium.Cartographic.toCartesian(new Cesium.Cartographic.fromDegrees(115.9165534, 40.0139345, 100))
        var distance = 3000.0
        var boundingSphere = new Cesium.BoundingSphere(position, distance)

        globe.clippingPlanes = new Cesium.ClippingPlaneCollection({
            modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(position),
            planes: [
                new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0.0), distance),
                new Cesium.ClippingPlane(new Cesium.Cartesian3(-1.0, 0.0, 0.0), distance),
                new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), distance),
                new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, -1.0, 0.0), distance)
            ],

            unionClippingRegions: true
        })
        globe.clippingPlanes.enabled = true
        viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.5, -0.5, boundingSphere.radius * 5.0))
        viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
    }

}

5、结果

点击绘制淹没范围,在地图上绘制需要进行分析的范围

点击开始,即进行淹没分析


http://www.niftyadmin.cn/n/1205605.html

相关文章

微软宣布将推迟ASP.NET Core的发布日期

几周之前&#xff0c;微软对于新版本的ASP.NET发布了一篇声明。Jeffrey T. Fritz是微软的程序经理&#xff0c;他在这篇博客文章中解释了发布日期变化的原因&#xff0c;并提供了新版本的命名从ASP.NET 5转变为ASP.NET Core 1.0的一些细节信息。 几周之前&#xff0c;微软将下一…

印度选定首批20座智慧城市

印度政府日前公布了首批20座智慧城市名单&#xff0c;其中包括新德里、金奈等印度传统大城市。 印度城市住房开发、城市扶贫和议会事务部长卡亚奈杜表示&#xff0c;印度未来5年将会为这20座城市投资5080亿卢比&#xff08;约合75亿美元&#xff09;。据了解&#xff0c;全印度…

“6月新规”为个人信息上了一把“安全锁”

《最高人民法院、最高人民检察院关于办理侵犯公民个人信息刑事案件适用法律若干问题的解释》将于2017年6月1日起施行。对于刑法相关规定中“情节严重”的认定标准&#xff0c;此次司法解释明确规定了十种情形&#xff0c;其中规定&#xff0c;贩卖50条公民个人信息&#xff0c;…

福建联通开通全国首个标准化NB-IoT(窄带物联网)规模化商用局

福建联通NB-IoT&#xff08;窄带物联网&#xff09;规模化商用局验收汇报会18日在福州召开。会上透露&#xff0c;全国首个带业务运行的标准化NB-IoT规模化商用局正式开通。 国家工业和信息化部支持福州市结合窄带物联网&#xff08;NB-IoT&#xff09;技术研发、试验应用&…

保障G20峰会网络空间安全阿里云给出云计算和大数据药方

G20杭州峰会期间&#xff0c;网络空间的安保上升到与实体空间的安保同等重要的地位&#xff0c;两个维度齐头并进&#xff0c;共建杭州全方位立体化的安全防护网。 在云安全领域&#xff0c;阿里旗下的阿里云计算有限公司积极贡献技术力量&#xff0c;不仅以崭新的中国方案保证…

百家运营商采用爱立信无线点系统增强室内应用覆盖

我们几乎90%的时间都是在室内度过的&#xff0c;然而&#xff0c;爱立信消费者研究室的调查结果显示&#xff0c;只有30%的智能手机用户认为室内语音质量、覆盖和可靠性是良好的。智能手机流量预计会在2015年至2021年间激增11倍&#xff0c;并且&#xff0c;到2021年底将占移动…

IDC预言被打脸 2016年WP系统将超越iOS?

随着时间的推移&#xff0c;IDC已经成为整个移动行业市场分析预测的领导者。即使是著名的市场预测分析机构&#xff0c;但是他们也做过糟糕的预测。 图为 2012年IDC的预测 早在2012年&#xff0c;IDC预测在2016年微软Windows Phone系统的市场份额将会超越苹果iOS。这是一个看似…

地铁WIFI值28亿?运营商终于不用背锅了

据说&#xff0c;一家地铁WiFi运营商上市了&#xff0c;价值28亿&#xff0c;仅仅是计划在上海、广州、深圳等7个城市的地铁上,向乘客提供免费WiFi信号。 运营WIFI能挣钱&#xff1f;好像以前也有过不少的尝试&#xff0c;甚至还得到过大资本的青睐&#xff0c;但最后都偃旗息鼓…