mirror of
				https://github.com/jiawanlong/Cesium-Examples.git
				synced 2025-11-04 01:04:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			236 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			236 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!--********************************************************************
 | 
						||
* by jiawanlong
 | 
						||
*********************************************************************-->
 | 
						||
<!DOCTYPE html>
 | 
						||
<html>
 | 
						||
 | 
						||
<head>
 | 
						||
    <meta charset="UTF-8" />
 | 
						||
    <link rel="stylesheet" href="./../../libs/cesium/Cesium1.98/Widgets/widgets.css">
 | 
						||
    <script type="text/javascript" src="./../../libs/cesium/Cesium1.98/Cesium.js"></script>
 | 
						||
    <script src="./turf.min.js"></script>
 | 
						||
    <script src="./latlng.js"></script>
 | 
						||
    <style>
 | 
						||
        #menu {
 | 
						||
            position: absolute;
 | 
						||
            top: 20px;
 | 
						||
            left: 20px;
 | 
						||
            padding: 10px;
 | 
						||
            background: #72a8eafa;
 | 
						||
            border-radius: 3px;
 | 
						||
            border: 1px solid rgba(128, 128, 128, 0.5);
 | 
						||
            color: #ffffff;
 | 
						||
            background: rgba(0, 0, 0, 0.4);
 | 
						||
            box-shadow: 0 3px 14px rgba(128, 128, 128, 0.5);
 | 
						||
            z-index: 9999;
 | 
						||
        }
 | 
						||
    </style>
 | 
						||
</head>
 | 
						||
 | 
						||
<body style="margin: 0; overflow: hidden; background: #fff; width: 100%; height: 100%; position: absolute; top: 0">
 | 
						||
    <div id="map" style="margin: 0 auto; width: 100%; height: 100%"></div>
 | 
						||
 | 
						||
    <div id="menu">
 | 
						||
        <button onclick="load()">加载</button>
 | 
						||
        <button onclick="clears()">clears</button>
 | 
						||
        <span>
 | 
						||
            空间距离,水平距离,垂直距离,等可以用turf计算
 | 
						||
        </span>
 | 
						||
    </div>
 | 
						||
    <script type="text/javascript">
 | 
						||
 | 
						||
        Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJjM2EzNGJmNy02N2RmLTQ0MDMtYjI2MS1hZTJiMTIwZGYwMTYiLCJpZCI6MzA0MzEyLCJpYXQiOjE3NDc3MjM3MTV9.ePQNhuoVuDsi_z00lTm5W26wyW1Adcr1AWetGM6WSXI'
 | 
						||
        const viewer = new Cesium.Viewer('map', {
 | 
						||
        });
 | 
						||
        // 开启帧率
 | 
						||
        viewer.scene.debugShowFramesPerSecond = true;
 | 
						||
        // 深度监测
 | 
						||
        viewer.scene.globe.depthTestAgainstTerrain = true;
 | 
						||
 | 
						||
        // 加载默认地形
 | 
						||
        viewer.terrainProvider = Cesium.createWorldTerrain({
 | 
						||
            requestWaterMask: true, // 请求水掩膜以实现水体效果
 | 
						||
            requestVertexNormals: true // 请求法线以实现光照效果
 | 
						||
        });
 | 
						||
        // 目的地带方向
 | 
						||
        viewer.camera.setView({
 | 
						||
            destination: Cesium.Cartesian3.fromDegrees(98.685331, 27.780325, 7318.6),
 | 
						||
            orientation: {
 | 
						||
                heading: Cesium.Math.toRadians(73),
 | 
						||
                pitch: Cesium.Math.toRadians(-52.2),
 | 
						||
                roll: 0.0
 | 
						||
            }
 | 
						||
        });
 | 
						||
        `
 | 
						||
    https://blog.csdn.net/lying_19/article/details/125101050
 | 
						||
    实现思路:仍然是“分而治之”,将观察点与被观察点连成的线段,分割成无限多的小段。获取每一段端点的实际高程值,与线段上该点的理论高程值。比较二者大小。
 | 
						||
                                                                        若 实际高程值>理论高程值,则不通视,且理论高程值为障碍点。
 | 
						||
    技术关键点:(1)将线段分割为很多小段,并获取每一段的端点。
 | 
						||
               (2)线段上的点,需要同时获取屏幕坐标和真实世界坐标
 | 
						||
    
 | 
						||
    `
 | 
						||
 | 
						||
        var start = Cesium.Cartesian3.fromDegrees(98.71707797694049, 27.777299704639537, 2800.0);
 | 
						||
        // var start = Cesium.Cartesian3.fromDegrees(98.71707797694049, 27.777299704639537, 3500.0);
 | 
						||
        var end = Cesium.Cartesian3.fromDegrees(98.71707797694049, 27.807299704639537, 3500.0);
 | 
						||
        var hello = viewer.entities.add({
 | 
						||
            name: '观测点',
 | 
						||
            position: start,
 | 
						||
            point: {
 | 
						||
                pixelSize: 5,
 | 
						||
                color: Cesium.Color.RED,
 | 
						||
                outlineColor: Cesium.Color.WHITE,
 | 
						||
                outlineWidth: 2,
 | 
						||
            },
 | 
						||
            label: {
 | 
						||
                text: '观测点',
 | 
						||
                font: '14pt monospace',
 | 
						||
                outlineWidth: 2,
 | 
						||
            }
 | 
						||
        });
 | 
						||
 | 
						||
        var word = viewer.entities.add({
 | 
						||
            name: '目的点',
 | 
						||
            position: end,
 | 
						||
            point: {
 | 
						||
                pixelSize: 5,
 | 
						||
                color: Cesium.Color.RED,
 | 
						||
                outlineColor: Cesium.Color.WHITE,
 | 
						||
                outlineWidth: 2,
 | 
						||
            },
 | 
						||
            label: {
 | 
						||
                text: '目的点',
 | 
						||
                font: '14pt monospace',
 | 
						||
                outlineWidth: 2,
 | 
						||
            }
 | 
						||
        });
 | 
						||
        var line1;
 | 
						||
        var line2;
 | 
						||
        function load() {
 | 
						||
            var center = sightline(start, end)
 | 
						||
            console.log("障碍点坐标-------------------------" + center)
 | 
						||
            if (center.x == 0 && center.y == 0 && center.z == 0) {
 | 
						||
                alert("可视")
 | 
						||
                line1 = viewer.entities.add({
 | 
						||
                    polyline: {
 | 
						||
                        positions: [start, end],
 | 
						||
                        width: 3,
 | 
						||
                        material: Cesium.Color.GREEN,
 | 
						||
                        clampToGround: false,
 | 
						||
                    }
 | 
						||
                });
 | 
						||
            } else {
 | 
						||
                alert("不可视")
 | 
						||
 | 
						||
                line1 = viewer.entities.add({
 | 
						||
                    polyline: {
 | 
						||
                        positions: [start, center],
 | 
						||
                        width: 3,
 | 
						||
                        material: Cesium.Color.GREEN,
 | 
						||
                        clampToGround: false,
 | 
						||
                    }
 | 
						||
                });
 | 
						||
                line2 = viewer.entities.add({
 | 
						||
                    polyline: {
 | 
						||
                        positions: [center, end],
 | 
						||
                        width: 3,
 | 
						||
                        material: Cesium.Color.RED,
 | 
						||
                        clampToGround: false,
 | 
						||
                    }
 | 
						||
                });
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
        function clears() {
 | 
						||
            viewer.entities.remove(line1);
 | 
						||
            viewer.entities.remove(line2);
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        function sightline(startWorldPoint, endWorldPoint) {
 | 
						||
            var barrierPoint = Cesium.Cartesian3.ZERO;
 | 
						||
            var startPoint = convertCartesian3ToCartesian2(viewer, startWorldPoint);
 | 
						||
            var endPoint = convertCartesian3ToCartesian2(viewer, endWorldPoint);
 | 
						||
            var worldLength = calculateSpatialDistance(startWorldPoint, endWorldPoint);
 | 
						||
            var windowLength = calculateWindowDistance(startPoint, endPoint);
 | 
						||
            var worldInterval = worldLength / 100.0;
 | 
						||
            var windowInterval = windowLength / 100.0;
 | 
						||
            for (var i = 1; i < 100; i++) {
 | 
						||
                var tempWindowPoint = findWindowPositionByPixelInterval(startPoint, endPoint, windowInterval * i);
 | 
						||
                var tempPoint = findCartesian3ByDistance(startWorldPoint, endWorldPoint, worldInterval * i);
 | 
						||
                var surfacePoint = pickCartesian(viewer, tempWindowPoint);
 | 
						||
                var tempRad = Cesium.Cartographic.fromCartesian(tempPoint);
 | 
						||
                var surfaceRad = Cesium.Cartographic.fromCartesian(surfacePoint.cartesian);
 | 
						||
                if (surfaceRad.height > tempRad.height) {
 | 
						||
                    barrierPoint = tempPoint;
 | 
						||
                    break;
 | 
						||
                }
 | 
						||
            }
 | 
						||
            return barrierPoint;
 | 
						||
        }
 | 
						||
 | 
						||
        function convertCartesian3ToCartesian2(viewer, position) {
 | 
						||
            return Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, position);
 | 
						||
        }
 | 
						||
        function calculateSpatialDistance(startPoint, endPoint) {
 | 
						||
            return Math.sqrt(Math.pow(endPoint.x - startPoint.x, 2) + Math.pow(endPoint.y - startPoint.y, 2) + Math.pow(endPoint.z - startPoint.z, 2));
 | 
						||
        }
 | 
						||
        function calculateWindowDistance(startPoint, endPoint) {
 | 
						||
            return Math.sqrt(Math.pow(endPoint.y - startPoint.y, 2) + Math.pow(endPoint.x - startPoint.x, 2));
 | 
						||
        }
 | 
						||
        function findWindowPositionByPixelInterval(startPosition, endPosition, interval) {
 | 
						||
            var result = new Cesium.Cartesian2(0, 0);
 | 
						||
            var length = Math.sqrt(Math.pow(endPosition.x - startPosition.x, 2) + Math.pow(endPosition.y - startPosition.y, 2));
 | 
						||
            if (length < interval) {
 | 
						||
                return result;
 | 
						||
            }
 | 
						||
            else {
 | 
						||
                var x = (interval / length) * (endPosition.x - startPosition.x) + startPosition.x;
 | 
						||
                var y = (interval / length) * (endPosition.y - startPosition.y) + startPosition.y;
 | 
						||
                result.x = x;
 | 
						||
                result.y = y;
 | 
						||
            }
 | 
						||
            return result;
 | 
						||
        }
 | 
						||
        function findCartesian3ByDistance(startPosition, endPosition, interval) {
 | 
						||
            var result = new Cesium.Cartesian3(0, 0, 0);
 | 
						||
            var length = Math.sqrt(Math.pow(endPosition.z - startPosition.z, 2) + Math.pow(endPosition.x - startPosition.x, 2) + Math.pow(endPosition.y - startPosition.y, 2));
 | 
						||
            if (length < interval) {
 | 
						||
                return result;
 | 
						||
            }
 | 
						||
            else {
 | 
						||
                var x = (interval / length) * (endPosition.x - startPosition.x) + startPosition.x;
 | 
						||
                var y = (interval / length) * (endPosition.y - startPosition.y) + startPosition.y;
 | 
						||
                var z = (interval / length) * (endPosition.z - startPosition.z) + startPosition.z;
 | 
						||
                result.x = x;
 | 
						||
                result.y = y;
 | 
						||
                result.z = z;
 | 
						||
            }
 | 
						||
            return result;
 | 
						||
        }
 | 
						||
        function pickCartesian(viewer, windowPosition) {
 | 
						||
            //根据窗口坐标,从场景的深度缓冲区中拾取相应的位置,返回笛卡尔坐标。
 | 
						||
            var cartesianModel = viewer.scene.pickPosition(windowPosition);
 | 
						||
            //场景相机向指定的鼠标位置(屏幕坐标)发射射线
 | 
						||
            var ray = viewer.camera.getPickRay(windowPosition);
 | 
						||
            //获取射线与三维球相交的点(即该鼠标位置对应的三维球坐标点,因为模型不属于球面的物体,所以无法捕捉模型表面)
 | 
						||
            var cartesianTerrain = viewer.scene.globe.pick(ray, viewer.scene);
 | 
						||
            // var result = new PickResult();
 | 
						||
            var result = {};
 | 
						||
            if (typeof (cartesianModel) !== 'undefined' && typeof (cartesianTerrain) !== 'undefined') {
 | 
						||
                result.cartesian = cartesianModel || cartesianTerrain;
 | 
						||
                result.CartesianModel = cartesianModel;
 | 
						||
                result.cartesianTerrain = cartesianTerrain;
 | 
						||
                result.windowCoordinates = windowPosition.clone();
 | 
						||
                //坐标不一致,证明是模型,采用绝对高度。否则是地形,用贴地模式。
 | 
						||
                result.altitudeMode = cartesianModel.z.toFixed(0) !== cartesianTerrain.z.toFixed(0) ? Cesium.HeightReference.NONE : Cesium.HeightReference.CLAMP_TO_GROUND;
 | 
						||
            }
 | 
						||
            return result;
 | 
						||
        }
 | 
						||
 | 
						||
    </script>
 | 
						||
</body>
 | 
						||
 | 
						||
</html> |