Cesium-Examples/examples/cesiumEx/4.1.8、透视分析.html
2025-06-12 14:10:21 +08:00

236 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--********************************************************************
* 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.eyJqdGkiOiIyMjBhMzcxMC0wNjBiLTRmYjItYjY1MC0wMzAwMzMyMGUyMmEiLCJpZCI6MzAzNzc3LCJpYXQiOjE3NDc2Mzk0NTV9.E_90aKtVdzRGlU2z48VwJ4mWvl-uuDkfQBCOO6zbzn4'
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>