<!DOCTYPE html> <html> <head> <meta charset='UTF-8'/> <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no'/> <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> <style> body { margin: 0; padding: 0; } #container { position: absolute; top: 0; bottom: 0; width: 100%; } .info{ position: absolute; top:0; left: 0; right: 0; z-index: 9; text-align: center; height: 30px; line-height: 30px; color: #909399; background: #f4f4f5; } </style> <title>part_test</title> </head> <body> <div class="info"> 点击地图可以获取当前位置的可视域分析(蓝色表示可见,红色不为可见) </div> <div id='container'></div> <script> bmgl.Config.HTTP_URL = 'http://bigemap.com:9000'; var viewer = new bmgl.Viewer('container', {mapId: 'bigemap.zhongkexingtu',requestRenderMode:false,terrainId: 'bigemap.9af15d8e'}); //设置初始位置 viewer.camera.setView({ destination: bmgl.Cartesian3.fromDegrees(103.59526245619938,30.9814012061604,3837.4144546), orientation: {"heading":6.282150327905171,"roll":6.279635689524259,"pitch":-0.6993902253931052} }); //当前的视点坐标 var startPoint={ lng:103.5898409037154, lat:31.012823472619534 }; var clickAble=true; viewer.screenSpaceEventHandler.setInputAction(function (e) { var ray=viewer.camera.getPickRay(e.position); var c=viewer.scene.globe.pick(ray,viewer.scene); if (!clickAble||!bmgl.defined(c))return; clickAble=false; setTimeout(()=>{ clickAble=true; },1000); c=bmgl.Cartographic.fromCartesian(c); startPoint.lng=bmgl.Math.toDegrees(c.longitude) startPoint.lat=bmgl.Math.toDegrees(c.latitude); drawLine(); },bmgl.ScreenSpaceEventType.LEFT_CLICK); var pointArr=[]; viewer.scene.globe.depthTestAgainstTerrain=true; setTimeout(function () { //1秒后开始画视角 drawLine(); },1000); function drawLine() { pointArr.map(v=>v.remove()); pointArr.length=0; var viewHeight = 1.5;//视角高度 var cartographicCenter = bmgl.Cartographic.fromDegrees(startPoint.lng, startPoint.lat); var cartesianCenterH0 = bmgl.Cartesian3.fromRadians(cartographicCenter.longitude, cartographicCenter.latitude); var cartesianPointH0 = bmgl.Cartesian3.fromDegrees(startPoint.lng+0.02, startPoint.lat+0.01); var ab = bmgl.Cartesian3.distance(cartesianCenterH0, cartesianPointH0); var eopt = {}; eopt.semiMinorAxis = ab; eopt.semiMajorAxis = ab; eopt.rotation = 0; eopt.center = cartesianCenterH0; eopt.granularity = Math.PI / 20;//间隔 var ellipse = computeEllipseEdgePositions(eopt); for (var i = 0; i < ellipse.outerPositions.length; i += 3) { //逐条计算可视域 var cartesian = new bmgl.Cartesian3(ellipse.outerPositions[i], ellipse.outerPositions[i + 1], ellipse.outerPositions[i + 2]); var cartographic = bmgl.Cartographic.fromCartesian(cartesian); var deltaRadian = 0.00005 * Math.PI / 180.0; var cartographicArr = InterpolateLineCartographic(cartographicCenter, cartographic, deltaRadian); getTerrain(cartographicArr,terrainData=>{ try { if (terrainData.length > 0) { var preVisible = true; var cartesiansLine = []; var colors = []; 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 + viewHeight); // 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); //绘制点 if (visible) { colors.push(0); colors.push(0); colors.push(1); colors.push(1); } else { colors.push(1); colors.push(0); colors.push(0); colors.push(1); } } //绘制结果 var pointsKSY = new PrimitivePoints({ 'viewer': viewer, 'Cartesians': cartesiansLine, 'Colors': colors }); pointArr.push(pointsKSY); } else { console.log("高程异常!"); } }catch (e) { console.log(e); } }) } } function getTerrain(arr,callback) { bmgl.sampleTerrainMostDetailed(viewer.terrainProvider,arr).then(data=>{ callback(data); }) } /** * options.semiMinorAxis:短半轴 * options.semiMajorAxis:长半轴 * options.rotation:旋转角度 弧度 * options.center:中心点 笛卡尔坐标 * options.granularity:粒度 弧度 * Returns an array of positions that make up the ellipse. * @private */ function computeEllipseEdgePositions(options) { var unitPosScratch = new bmgl.Cartesian3(); var eastVecScratch = new bmgl.Cartesian3(); var northVecScratch = new bmgl.Cartesian3(); var scratchCartesian1 = new bmgl.Cartesian3(); var semiMinorAxis = options.semiMinorAxis; var semiMajorAxis = options.semiMajorAxis; var rotation = options.rotation;//法线 var center = options.center; var granularity = options.granularity && (typeof options.granularity === "number") ? options.granularity : (Math.PI / 180.0);// 角度间隔 if (granularity > Math.PI / 12.0) { granularity = Math.PI / 12.0; }//最小分24 if (granularity < Math.PI / 180.0) { granularity = Math.PI / 180.0; }//最大分360 var aSqr = semiMinorAxis * semiMinorAxis; var bSqr = semiMajorAxis * semiMajorAxis; var ab = semiMajorAxis * semiMinorAxis; var mag = bmgl.Cartesian3.magnitude(center);// var unitPos = bmgl.Cartesian3.normalize(center, unitPosScratch); var eastVec = bmgl.Cartesian3.cross(bmgl.Cartesian3.UNIT_Z, center, eastVecScratch); eastVec = bmgl.Cartesian3.normalize(eastVec, eastVec); var northVec = bmgl.Cartesian3.cross(unitPos, eastVec, northVecScratch); var numPts = Math.ceil(bmgl.Math.PI*2 / granularity); var deltaTheta = granularity; var theta = 0; var position = scratchCartesian1; var i; var outerIndex = 0; var outerPositions = []; for (i = 0; i < numPts; i++) { theta = i * deltaTheta; position = pointOnEllipsoid(theta, rotation, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, position); outerPositions[outerIndex++] = position.x; outerPositions[outerIndex++] = position.y; outerPositions[outerIndex++] = position.z; } var r = {}; r.numPts = numPts; r.outerPositions = outerPositions; return r; }; /* 线段插值 经纬度坐标插值 Cartographic start.longitude start.latitude 单位:弧度 return [Cartographic,...] */ function InterpolateLineCartographic(start, end, _Delta) { 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)); var interval = Math.sqrt(Math.pow((end.longitude - start.longitude), 2) + Math.pow((end.latitude - start.latitude), 2)); var delta = _Delta && (typeof _Delta === 'number') ? _Delta : DeltaRadian; if (interval <= delta) { //小于最小间隔 result.push(new bmgl.Cartographic(end.longitude, end.latitude)); return result; } else { var num = interval / delta; var stepLon = (end.longitude - start.longitude) / num; var stepLat = (end.latitude - start.latitude) / num; for (var i = 0; i < num; i++) { var lon = start.longitude + (i + 1) * stepLon; var lat = start.latitude + (i + 1) * stepLat; result.push(new bmgl.Cartographic(lon, lat));//与最后一个点有偏差 } result.push(new bmgl.Cartographic(end.longitude, end.latitude, end.height)); } 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; } /* 线段插值 经纬度高程插值 Cartographic start.longitude start.latitude 单位:弧度 start.height 高程单位m num:分总段数 传入数组长度-1 index:获取到第index点的所有插值 0点是开始点 return [Cartographic,...] */ 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)); } //result.push(new bmgl.Cartographic(end.longitude, end.latitude, end.height)); return result; } function pointOnEllipsoid(theta, rotation, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, result) { var rotAxis = new bmgl.Cartesian3(); var tempVec = new bmgl.Cartesian3(); var unitQuat = new bmgl.Quaternion(); var rotMtx = new bmgl.Matrix3(); var azimuth = theta + rotation; bmgl.Cartesian3.multiplyByScalar(eastVec, Math.cos(azimuth), rotAxis); bmgl.Cartesian3.multiplyByScalar(northVec, Math.sin(azimuth), tempVec); bmgl.Cartesian3.add(rotAxis, tempVec, rotAxis); var cosThetaSquared = Math.cos(theta); cosThetaSquared = cosThetaSquared * cosThetaSquared; var sinThetaSquared = Math.sin(theta); sinThetaSquared = sinThetaSquared * sinThetaSquared; var radius = ab / Math.sqrt(bSqr * cosThetaSquared + aSqr * sinThetaSquared); var angle = radius / mag; // Create the quaternion to rotate the position vector to the boundary of the ellipse. bmgl.Quaternion.fromAxisAngle(rotAxis, angle, unitQuat); bmgl.Matrix3.fromQuaternion(unitQuat, rotMtx); bmgl.Matrix3.multiplyByVector(rotMtx, unitPos, result); bmgl.Cartesian3.normalize(result, result); bmgl.Cartesian3.multiplyByScalar(result, mag, result); return result; } var PrimitivePoints = ( function () { var vertexShader; var fragmentShader; var geometry; var appearance; var viewer; function _(options) { viewer = options.viewer; vertexShader = VSPolylie(); fragmentShader = FSPolyline(); if (options.Cartesians && options.Cartesians.length >= 2) { var postionsTemp = []; var colorsTemp = []; var indicesTesm = []; if (options.Colors && options.Colors.length === options.Cartesians.length * 4) { for (var i = 0; i < options.Cartesians.length; i++) { postionsTemp.push(options.Cartesians[i].x); postionsTemp.push(options.Cartesians[i].y); postionsTemp.push(options.Cartesians[i].z); } colorsTemp = options.Colors; } else { for (var i = 0; i < options.Cartesians.length; i++) { postionsTemp.push(options.Cartesians[i].x); postionsTemp.push(options.Cartesians[i].y); postionsTemp.push(options.Cartesians[i].z); // colorsTemp.push(0.0); colorsTemp.push(0.0); colorsTemp.push(1.0); colorsTemp.push(1.0); } } for (var i = 0; i < options.Cartesians.length; i++) { indicesTesm.push(i); } this.positionArr = new Float64Array(postionsTemp); this.colorArr = new Float32Array(colorsTemp); this.indiceArr = new Uint16Array(indicesTesm); } else { // if (options.Cartesians && options.Cartesians.length >= 2) { var p1 = bmgl.Cartesian3.fromDegrees(0, 0, -10); var p2 = bmgl.Cartesian3.fromDegrees(0, 0.001, -10); this.positionArr = new Float64Array([ p1.x, p1.y, p1.z, p2.x, p2.y, p2.z ]); //默认蓝色 this.colorArr = new Float32Array([ 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0 ]); this.indiceArr = new Uint16Array([0, 1]); } geometry = CreateGeometry(this.positionArr, this.colorArr, this.indiceArr); appearance = CreateAppearence(fragmentShader, vertexShader); this.primitive = viewer.scene.primitives.add(new bmgl.Primitive({ geometryInstances: new bmgl.GeometryInstance({ geometry: geometry }), appearance: appearance, asynchronous: false })); } function CreateGeometry(positions, colors, indices) { return new bmgl.Geometry({ attributes: { position: new bmgl.GeometryAttribute({ componentDatatype: bmgl.ComponentDatatype.DOUBLE, componentsPerAttribute: 3, values: positions }), color: new bmgl.GeometryAttribute({ componentDatatype: bmgl.ComponentDatatype.FLOAT, componentsPerAttribute: 4, values: colors }) }, indices: indices, primitiveType: bmgl.PrimitiveType.POINTS, boundingSphere: bmgl.BoundingSphere.fromVertices(positions) }); } function CreateAppearence(fs, vs) { return new bmgl.Appearance({ renderState: { blending: bmgl.BlendingState.PRE_MULTIPLIED_ALPHA_BLEND, depthTest: { enabled: true }, depthMask: true }, fragmentShaderSource: fs, vertexShaderSource: vs }); } function VSPolylie() { return "attribute vec3 position3DHigh;\ attribute vec3 position3DLow;\ attribute vec4 color;\ varying vec4 v_color;\ attribute float batchId;\ void main()\ {\ vec4 p = czm_computePosition();\ v_color =color;\ p = czm_modelViewProjectionRelativeToEye * p;\ gl_Position = p;\ gl_PointSize=4.0;\ }\ "; } function FSPolyline() { return "varying vec4 v_color;\ void main()\ {\ float d = distance(gl_PointCoord, vec2(0.5,0.5));\ if(d < 0.5){\ gl_FragColor = v_color;\ }else{\ discard;\ }\ }\ "; } _.prototype.remove = function () { if (this.primitive != null) { viewer.scene.primitives.remove(this.primitive); this.primitive = null; } } _.prototype.updateCartesianPosition = function (cartesians) { if (this.primitive != null) { viewer.scene.primitives.remove(this.primitive); if (cartesians && cartesians.length < 2) { return; } if (cartesians.length === this.positionArr.length / 3) { var p1 = cartesians[0]; var p2 = cartesians[1]; this.positionArr = new Float64Array([ p1.x, p1.y, p1.z, p2.x, p2.y, p2.z ]); geometry = CreateGeometry(this.positionArr, this.colorArr, this.indiceArr); } else { //默认蓝色 var postionsTemp = []; var colorsTemp = []; var indicesTesm = []; for (var i = 0; i < cartesians.length; i++) { postionsTemp.push(cartesians[i].x); postionsTemp.push(cartesians[i].y); postionsTemp.push(cartesians[i].z); colorsTemp.push(0.0); colorsTemp.push(0.0); colorsTemp.push(1.0); colorsTemp.push(1.0); } for (var i = 0; i < cartesians.length; i++) { indicesTesm.push(i); } this.positionArr = new Float64Array(postionsTemp); this.colorArr = new Float32Array(colorsTemp); this.indiceArr = new Uint16Array(indicesTesm); geometry = CreateGeometry(this.positionArr, this.colorArr, this.indiceArr); appearance = CreateAppearence(fragmentShader, vertexShader); } this.primitive = viewer.scene.primitives.add(new bmgl.Primitive({ geometryInstances: new bmgl.GeometryInstance({ geometry: geometry }), appearance: appearance, asynchronous: false })); } else { return; } } _.prototype.updateCartesianPositionColor = function (cartesians, colors) { if (colors.length === cartesians.length * 4) { } else { return; } if (this.primitive != null) { viewer.scene.primitives.remove(this.primitive); if (cartesians && cartesians.length < 2) { return; } if (cartesians.length === this.positionArr.length / 3) { var p1 = cartesians[0]; var p2 = cartesians[1]; this.positionArr = new Float64Array([ p1.x, p1.y, p1.z, p2.x, p2.y, p2.z ]); this.colorArr = new Float32Array(colors); geometry = CreateGeometry(this.positionArr, this.colorArr, this.indiceArr); } else { var postionsTemp = []; var indicesTesm = []; for (var i = 0; i < cartesians.length; i++) { postionsTemp.push(cartesians[i].x); postionsTemp.push(cartesians[i].y); postionsTemp.push(cartesians[i].z); } for (var i = 0; i < cartesians.length; i++) { indicesTesm.push(i); } this.positionArr = new Float64Array(postionsTemp); this.colorArr = new Float32Array(colors); this.indiceArr = new Uint16Array(indicesTesm); geometry = CreateGeometry(this.positionArr, this.colorArr, this.indiceArr); appearance = CreateAppearence(fragmentShader, vertexShader); } this.primitive = viewer.scene.primitives.add(new bmgl.Primitive({ geometryInstances: new bmgl.GeometryInstance({ geometry: geometry }), appearance: appearance, asynchronous: false })); } else { return; } } return _; })(); </script> </body> </html>
源码