<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.zhongkexingtu' }); 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>
源码