可视域 球形-源代码示例 运行 重置

                    <html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <link href='http://bigemap.com:9000/bigemap-gl.js/v1.1.0/Widgets/widgets.css' rel='stylesheet'/>
    <script src='http://bigemap.com:9000/bigemap-gl.js/v1.1.0/bigemap-gl.js'></script>
    <title>可视域</title>
</head>
<style type="text/css">
    * {
        padding: 0;
        margin: 0;
    }
    html, body, #map {
        width: 100%;
        height: 100%;
    }
    #start {
        position: absolute;
        left: 50px;
        top: 50px;
        z-index: 9999;
    }
    #step {
        position: absolute;
        left:120px;
        top: 50px;
        z-index: 9999;
    }
    .info{
        position: fixed;
        top:0;
        color: #8a6d3b;
        z-index: 99;
        margin: 0;
        background-color: #fcf8e3;
        border-color: #faebcc;
        left: 0;
        right: 0;
        text-align: center;
    }
</style>
<body>
<div id="map"></div>
<div class="info">
    先点击开始,然后再次单击地图,即可实现可视域分析功能
</div>
<button id="start">
    开始
</button>
<button id="step">
    进度
</button>
</body>
</html>
<script type="text/javascript">
    bmgl.Config.HTTP_URL = 'http://bigemap.com:9000';
    var viewer = new bmgl.Viewer('map', {
        terrainId: 'bigemap.9af15d8e',
        requestRenderMode:false,
        mapId: 'bigemap.amap-satellite'
    });
    var config = initConfig();
    function initConfig() {
        let base = {
            lng: 86,
            lat: 28,
            sum: 50,
            start: 0,
            done: 0,
            height: 5,
            loaded: 0,
            delta: 100,
            all_seen: 0,
            width: 5000,
            click: 0,
            draw: false,
            calc_width: [],
            edge: [],
            min: [],
            inner: [],
        };
        return base;
        // return JSON.parse(JSON.stringify(base));
    }

    // viewer.entities.add({
    //     position:bmgl.Cartesian3.fromDegrees(config.lng,config.lat),
    //     label:{
    //         text:'C',
    //         heightReference:bmgl.HeightReference.CLAMP_TO_GROUND,
    //     }
    // });
    viewer.scene.globe.depthTestAgainstTerrain = true;
    //获取最新的位置
    viewer.camera.setView({
        destination: bmgl.Cartesian3.fromDegrees(103.59526245619938,30.9814012061604,3837.4144546),
        orientation: {"heading":6.282150327905171,"roll":6.279635689524259,"pitch":-0.6993902253931052}
    });
    function startDraw() {
        // var pp=bmgl.Transforms.eastNorthUpToFixedFrame(bmgl.Cartesian3.fromDegrees(config.lng,config.lat));
        document.getElementById('step').innerHTML='0/'+config.sum;
        for (let i = 0; i < config.sum; i++) {
            var tmp_edge = [];
            var tmp_inner = [];
            for (let j = 0; j < config.sum; j++) {
                var center = bmgl.Cartesian3.fromDegrees(config.lng, config.lat);
                var heading = bmgl.Math.PI * 2 * j / config.sum;
                var hpr = new bmgl.HeadingPitchRoll(heading, 0.0, 0);
                var transform = bmgl.Transforms.headingPitchRollToFixedFrame(center, hpr);
                var p = bmgl.Matrix4.multiplyByPoint(transform, new bmgl.Cartesian3(config.width * Math.cos(bmgl.Math.toRadians(90 * i / config.sum)), 0, config.width * Math.sin(bmgl.Math.toRadians(90 * i / config.sum))), new bmgl.Cartesian3());
                // var p2=bmgl.Matrix4.multiplyByPoint(transform,new bmgl.Cartesian3(config.width*Math.cos(bmgl.Math.toRadians(90*i/config.sum)),0,0),new bmgl.Cartesian3());
                // viewer.entities.add({
                //     position:p2,
                //     label:{
                //         heightReference:bmgl.HeightReference.CLAMP_TO_GROUND,
                //         text:'b',
                //         font:'14px arial',
                //     }
                // });
                // tmp_inner.push({p:p2});
                tmp_edge.push({p, height: config.width * Math.sin(bmgl.Math.toRadians(90 * i / config.sum))});
            }
            // config.calc_width.push(config.width * Math.cos(bmgl.Math.toRadians(90 * i / config.sum)));
            tmp_edge.push(tmp_edge[0]);
            config.edge.push(tmp_edge);
            // config.inner.push(tmp_inner);
            // viewer.entities.add({
            //     polyline:{
            //         width:new bmgl.ConstantProperty(2),
            //         material:bmgl.Color.BLUE,
            //         // clampToGround:true,
            //         positions:tmp_edge.map(v=>v.p)
            //     }
            // });
        }
        console.log(config);
        calcShow();
    }
    // viewer.flyTo(viewer.entities);
    let handler = new bmgl.ScreenSpaceEventHandler(viewer.canvas);
    handler.setInputAction(function (e) {
        if (!config.draw) return;
        if (config.click === 0) {
            viewer.entities.removeAll();
        }
        let ray = viewer.camera.getPickRay(e.position);
        if (!ray) return;
        let cartesian3 = viewer.scene.globe.pick(ray, viewer.scene);
        config.click++;
        let p = bmgl.Cartographic.fromCartesian(cartesian3);
        switch (config.click) {
            case 1:
                viewer.entities.add({
                    position: cartesian3,
                    label: {
                        text: 'Start',
                        verticalOrigin:bmgl.VerticalOrigin.BOTTOM,
                        heightReference: bmgl.HeightReference.CLAMP_TO_GROUND,
                    }
                });
                config.lng = bmgl.Math.toDegrees(p.longitude);
                config.lat = bmgl.Math.toDegrees(p.latitude);
                config.mouse={lng:config.lng,lat:config.lat};
                config.tmp_label=viewer.entities.add({
                    position:new bmgl.CallbackProperty(function (){
                        return bmgl.Cartesian3.fromDegrees(config.mouse.lng,config.mouse.lat);
                    }),
                    label:{
                        text:'',
                        verticalOrigin:bmgl.VerticalOrigin.BOTTOM,
                        heightReference:bmgl.HeightReference.CLAMP_TO_GROUND,
                        font:'16px arial',
                    }
                });
                config.tmp_line=viewer.entities.add({
                    polyline:{
                        positions:new bmgl.CallbackProperty(function (){
                            return bmgl.Cartesian3.fromDegreesArray([config.lng,config.lat,config.mouse.lng,config.mouse.lat]);
                        }),
                        clampToGround:true,
                        material:bmgl.Color.RED.withAlpha(0.8),
                    }
                });
                config.tmp_line2=viewer.entities.add({
                    polyline:{
                        positions:new bmgl.CallbackProperty(function (){
                            let  p=[];
                            let dd=bmgl.Cartesian3.distance(bmgl.Cartesian3.fromDegrees(config.lng,config.lat),bmgl.Cartesian3.fromDegrees(config.mouse.lng,config.mouse.lat)).toFixed(2);
                            for (let i=0;i<40;i++){
                                var center = bmgl.Cartesian3.fromDegrees(config.lng, config.lat);
                                var heading = bmgl.Math.PI * 2 * i / 40;
                                var hpr = new bmgl.HeadingPitchRoll(heading, 0.0, 0);
                                var transform = bmgl.Transforms.headingPitchRollToFixedFrame(center, hpr);
                                var p1 = bmgl.Matrix4.multiplyByPoint(transform, new bmgl.Cartesian3(dd, 0, 0), new bmgl.Cartesian3());
                                p.push(p1);
                            }
                            p.push(p[0]);
                            return p;
                        }),
                        clampToGround:true,
                        material:bmgl.Color.RED.withAlpha(0.8),
                    }
                });
                break;
            case 2:
                let dd = bmgl.Cartesian3.distance(bmgl.Cartesian3.fromDegrees(config.lng, config.lat), cartesian3);
                // console.log(dd);
                config.width = dd;
                viewer.entities.add({
                    position: cartesian3,
                    label: {
                        text: 'End',
                        verticalOrigin:bmgl.VerticalOrigin.BOTTOM,
                        heightReference: bmgl.HeightReference.CLAMP_TO_GROUND,
                    }
                });
                break;
        }

        if (config.click > 1) {
            //说明已经点击了两次,绘制完成了
            viewer.entities.remove(config.tmp_label);
            viewer.entities.remove(config.tmp_line);
            viewer.entities.remove(config.tmp_line2);
            startDraw();
            config.draw = false;
            config.click = 0;
        }
    }, bmgl.ScreenSpaceEventType.LEFT_CLICK);

    handler.setInputAction(function (e){
        if (!config.draw) return;
        if (config.click===1){
            let ray=viewer.camera.getPickRay(e.endPosition);
            if (!ray) return;
            let pp=viewer.scene.globe.pick(ray,viewer.scene);
            pp=bmgl.Cartographic.fromCartesian(pp);
            config.mouse={
                lng:bmgl.Math.toDegrees(pp.longitude),
                lat:bmgl.Math.toDegrees(pp.latitude)
            }
            config.tmp_label.label.text=bmgl.Cartesian3.distance(bmgl.Cartesian3.fromDegrees(config.lng,config.lat),bmgl.Cartesian3.fromDegrees(config.mouse.lng,config.mouse.lat)).toFixed(2)+'米';
        }

    },bmgl.ScreenSpaceEventType.MOUSE_MOVE);
    document.getElementById('start').addEventListener('click', function () {
        config = initConfig();
        config.draw = true;
        //config=initConfig();
    });

    function calcShow() {
        if (!config.edge[config.start]) {
            console.log('all over');
            document.getElementById('step').innerHTML=config.sum+'/'+config.sum;
            return;
        }
        config.edge[config.start].map((v, ii) => {
            var end = bmgl.Cartographic.fromCartesian(v.p);
            end.lng = bmgl.Math.toDegrees(end.longitude);
            end.lat = bmgl.Math.toDegrees(end.latitude);
            let p = [];
            for (let j = 0; j < config.delta; j++) {
                let tp = {
                    lng: config.lng + (end.lng - config.lng) * j / config.delta,
                    lat: config.lat + (end.lat - config.lat) * j / config.delta
                };
                // debugger;
                // if (config.start===6){
                //     viewer.entities.add({
                //         position:bmgl.Cartesian3.fromDegrees(tp.lng,tp.lat),
                //         label:{
                //             text:'k'+j,
                //             heightReference:bmgl.HeightReference.CLAMP_TO_GROUND,
                //         }
                //     });
                // }
                p.push(bmgl.Cartographic.fromCartesian(bmgl.Cartesian3.fromDegrees(tp.lng, tp.lat)));
            }
            let hh = v.height;
            getTerrain(p, ii, (ter, iii) => {
                // debugger;
                ter[ter.length - 1]['height'] = hh;
                config.loaded++;
                let result = showVisible(ter);
                config.edge[config.start][iii]['v'] = result[result.length - 1];
                // viewer.entities.add({
                //     position: config.edge[config.start][iii]['p'],
                //     label: {
                //         text: result[result.length - 1] ? '1' : '0',
                //         heightReference: bmgl.HeightReference.CLAMP_TO_GROUND,
                //     }
                // });

                // var a = bmgl.Cartographic.fromCartesian(config.edge[config.start][iii]['p']);
                // viewer.entities.add({
                //     position: bmgl.Cartesian3.fromDegrees(bmgl.Math.toDegrees(a.longitude), bmgl.Math.toDegrees(a.latitude), hh),
                //     label: {
                //         fillColor: config.edge[config.start][iii]['v'] ? bmgl.Color.BLUE : bmgl.Color.RED,
                //         text: 'X',
                //     }
                // });
                if (config.loaded === config.edge[config.start].length) {
                    //本次圆内已经计算完了
                    let ttt = [];
                    config.edge[config.start].map(v1 => {
                        ttt.push(v1.v);
                    });
                    console.log('index: ' + config.start);
                    document.getElementById('step').innerHTML=config.start+'/'+config.sum;
                    let all_seen = Array.from(new Set(ttt));
                    if (all_seen[0] && all_seen.length === 1) {
                        config.all_seen = config.start;
                        document.getElementById('step').innerHTML=config.sum+'/'+config.sum;
                        for (let j=config.start;j<config.edge.length;j++){
                            drawLine(config.edge[j].map(v=>{
                                v.v=true;
                                return v;
                            }));
                        }
                        //第二次绘画
                        for (let i=0;i<config.sum;i++){
                            let tmp=[];
                            for (let j=0;j<config.sum;j++){
                                tmp.push(config.edge[j][i]);
                            }
                            tmp.push({v:true,p:bmgl.Cartesian3.fromDegrees(config.lng,config.lat,config.width)});
                            drawLine(tmp);
                            // console.log(tmp);
                        }
                        return;
                    }
                    drawLine(config.edge[config.start]);
                    config.loaded = 0;
                    config.start++;
                    calcShow();
                }
            });
            // viewer.entities.add({
            //     position:v.p,
            //     label:{
            //         text:'c',
            //         heightReference:bmgl.HeightReference.CLAMP_TO_GROUND,
            //     }
            // })
        });
    }


    function drawLine(data) {
        // console.log(data);
        let path = [];
        let tmp = [data[0]];
        let prev = data[0]['v'];
        for (let j = 1; j < data.length; j++) {
            let v = data[j];
            tmp.push(v);
            if (prev !== v.v) {
                if (tmp.length > 1) {
                    let m;
                    if (prev) {
                        m = bmgl.Color.BLUE;
                    } else {
                        m = bmgl.Color.RED;
                    }
                    console.log('tmp index length : ' + tmp.length);
                    viewer.entities.add({
                        polyline: {
                            material: m,
                            positions: tmp.map(v => v.p),
                        }
                    });
                    // path.push({v:start,path:[...JSON.parse(JSON.stringify(tmp))]});
                    tmp.length = 0;
                    tmp.push(v);
                }
                prev = v.v;
            }
        }

        if (tmp.length > 1) {
            let m;
            if (prev) {
                m = bmgl.Color.BLUE;
            } else {
                m = bmgl.Color.RED;
            }
            console.log('tmp index' + tmp.length);
            viewer.entities.add({
                polyline: {
                    material: m,
                    positions: tmp.map(v => v.p),
                }
            });
        }
        console.log(path);
    }

    function getTerrain(position, i, callback) {
        // bmgl.sampleTerrain(viewer.terrainProvider,8,position).then(data=>{
        //     try {
        //         if (data.length > 0) callback(data, i);
        //     } catch (e) {
        //         console.log(e);
        //     }
        // });
        bmgl.sampleTerrainMostDetailed(viewer.terrainProvider, position).then(data => {
            try {
                if (data.length > 0) callback(data, i);
            } catch (e) {
                console.log(e);
            }
        })
    }

    function showVisible(terrainData) {
        var preVisible = true;
        var cartesiansLine = [];
        var colors = [true];
        for (var j = 1; j < terrainData.length; j++) {
            //逐点计算可见性
            var visible = true;//该点可见性
            if (j > 1) {
                var cartographicCenterHV = new bmgl.Cartographic(terrainData[0].longitude, terrainData[0].latitude, terrainData[0].height + config.height);
                if (preVisible) {
                    var curPoint = InterpolateIndexLineHeightCartographic(cartographicCenterHV, terrainData[j], j, j - 1);
                    if (curPoint.height >= terrainData[j - 1].height) {
                        preVisible = true;
                        visible = true;
                    } else {
                        preVisible = false;
                        visible = false;
                    }
                } else {
                    //插值到当前
                    var curPointArr = Interpolate2IndexLineHeightCartographic(cartographicCenterHV, terrainData[j], j, j - 1);
                    for (var k = 0; k < curPointArr.length; k++) {
                        if (curPointArr[k].height >= terrainData[k].height) {
                            preVisible = true;
                            visible = true;
                        } else {
                            preVisible = false;
                            visible = false;
                            break;
                        }
                    }
                }
            }
            // var cartesianTemp = bmgl.Cartesian3.fromRadians(terrainData[j].longitude, terrainData[j].latitude, terrainData[j].height + 0.10);
            // cartesiansLine.push(cartesianTemp);
            //绘制点
            colors.push(visible);
        }
        return colors;

    }

    function Interpolate2IndexLineHeightCartographic(start, end, num, curIndex) {
        if (start && end) {
        } else {
            return null;
        }
        if (start.longitude && start.latitude && end.longitude && end.latitude) {
        } else {
            return null;
        }
        var result = [];
        result.push(new bmgl.Cartographic(start.longitude, start.latitude, start.height));
        var stepLon = (end.longitude - start.longitude) / num;
        var stepLat = (end.latitude - start.latitude) / num;
        var stepHeight = (end.height - start.height) / num;
        for (var i = 0; i < curIndex; i++) {
            var lon = start.longitude + (i + 1) * stepLon;
            var lat = start.latitude + (i + 1) * stepLat;
            var hieght = start.height + (i + 1) * stepHeight;
            result.push(new bmgl.Cartographic(lon, lat, hieght));
        }
        return result;
    }

    function InterpolateIndexLineHeightCartographic(start, end, num, index) {
        if (start && end) {
        } else {
            return null;
        }
        if (start.longitude && start.latitude && end.longitude && end.latitude) {

        } else {
            return null;
        }
        //var delta = _Delta && (typeof _Delta === 'number') ? _Delta : DeltaRadian;
        var stepLon = (end.longitude - start.longitude) / num;
        var stepLat = (end.latitude - start.latitude) / num;
        var stepHeight = (end.height - start.height) / num;
        var lon = start.longitude + index * stepLon;
        var lat = start.latitude + index * stepLat;
        var hieght = start.height + index * stepHeight;
        var result = new bmgl.Cartographic(lon, lat, hieght);
        return result;
    }
</script>
                                                                                            
源码