Cesium剖面分析,根据地形dem 生成剖面,高度通过echart展示。
前端实现代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
<meta name="description" content="Generate procedural heightmap terrain." />
<meta name="cesium-sandcastle-labels" content="Showcases" />
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script type="text/javascript" src="../../../Build/CesiumUnminified/Cesium.js" nomodule></script>
<script type="module" src="../load-cesium-es6.js"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.3.3/dist/echarts.js"></script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay">
<h1>Loading...</h1>
</div>
<div id="toolbar"></div>
<div id="echartsView1" style="background-color: #000000; width: 500px;height: 500px;position: absolute;left: 0px;top: 0px;z-index: 999999;">
</div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
"use strict";
//Sandcastle_Begin
var width = 32;
var height = 32;
// /terrain/xwMm1WEy/layer.json
const terrainProvider = new Cesium.CesiumTerrainProvider({
url: 'http://192.168.11.173:9003/terrain/Qde9nSaC',
});
Cesium.Ion.defaultAccessToken =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhYzIwODVjYi0wN2JmLTRkMDEtOWU2Mi04OTU2OWY3YjE3YmUiLCJpZCI6MTA0MDAwLCJpYXQiOjE2Nzc4MDU1NzZ9.Zi7vxzDxArXCQ3UazBiHVPBJHM0mYIuB6bfheKPOZro'
var viewer = new Cesium.Viewer("cesiumContainer", {
terrainProvider: terrainProvider//noiseTerrainProvider,
});
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
var timer1 = null;
var pointArr = []
var argArr = []
var profile = {
arrHB: [],
arrPoint: [],
ponits: [],
}
var start;
var end;
//设置鼠标左键单击回调事件
handler.setInputAction(function(e) {
clearInterval(timer1)
//首先移除之前添加的点
viewer.entities.removeAll();
//获取点击位置笛卡尔坐标
var position = viewer.scene.pickPosition(e.position);
// let
//将笛卡尔坐标转化为经纬度坐标
var cartographic = Cesium.Cartographic.fromCartesian(position);
var longitude = Cesium.Math.toDegrees(cartographic.longitude);
var latitude = Cesium.Math.toDegrees(cartographic.latitude);
var height = cartographic.height;
argArr.push(longitude)
argArr.push(latitude)
argArr.push(height)
if(pointArr.length == 0){
start = position;
pointArr.push(position)
profile = {
disc:[],
arrHB: [],
arrPoint: [],
ponits: [],
}
}else if(pointArr.length == 1){
end = position
pointArr = []
// 开始剖面分析
profileAnalyse(start, end)
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
function profileAnalyse(start, end) {
var scene = viewer.scene;
var startPoint = Cesium.Cartographic.fromCartesian(start)
var endPoint = Cesium.Cartographic.fromCartesian(end)
// 插值100个点,点越多模拟越精确,但是效率会低
var count = 100;
var arrHeight = []
for (var i = 0; i < count; i++) {
var cart = (Cesium.Cartesian3.lerp(
start,
end,
i / count,
new Cesium.Cartesian3()
))
// debugger
// let samplePoss = scene.clampToHeight(cart) // Cesium.Ellipsoid.WGS84.cartographicToCartesian(property[i])
arrHeight.push(cart)
}
console.log('arrHeight',arrHeight)
//scene.clampToHeightMostDetailed获取模型样本高度,详情可查看cesium文档
profile.ponits.push(start)
profile.arrPoint.push(getDegrees(startPoint))
profile.arrHB.push(startPoint.height)
scene.clampToHeightMostDetailed(arrHeight).then(function (clampedCartesians) {
for (var i = 0; i < count; i++) {
debugger
let point1 = profile.ponits[i];
let point2 = clampedCartesians[i];
let distance = Cesium.Cartesian3.distance(
Cesium.Cartesian3.fromDegrees(Cesium.Math.toDegrees(point1.x), Cesium.Math.toDegrees(point1.y), point1.z),
Cesium.Cartesian3.fromDegrees(Cesium.Math.toDegrees(point2.x), Cesium.Math.toDegrees(point2.y), point2.z))
profile.disc.push(distance.toFixed(2))
profile.ponits.push(clampedCartesians[i])
profile.arrPoint.push(getXYDegrees(clampedCartesians[i]))
profile.arrHB.push(Cesium.Cartographic.fromCartesian(clampedCartesians[i]).height)
}
profile.ponits.push(end)
profile.arrPoint.push(getDegrees(endPoint))
profile.arrHB.push(endPoint.height)
setEchartsData(profile)
})
}
var ellipsoid = viewer.scene.globe.ellipsoid
//计算两点间的距离
function distance(point1, point2) {
debugger
/**根据经纬度计算出距离**/
// var geodesic = new Cesium.EllipsoidGeodesic()
// geodesic.setEndPoints(point1, point2)
// var s = geodesic.surfaceDistance
// //返回两点之间的距离
// s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2.height - point1.height, 2))
let distance = Cesium.Cartesian3.distance(
Cesium.Cartesian3.fromDegrees(Cesium.Math.toDegrees(point1.x), Cesium.Math.toDegrees(point1.y), point1.z),
Cesium.Cartesian3.fromDegrees(Cesium.Math.toDegrees(point2.x), Cesium.Math.toDegrees(point2.y), point2.z))
console.log('121',distance)
return distance
}
//世界坐标转换为经纬度
function getDegrees(cart) {
var cartographic = cart //Cesium.Cartographic.fromCartesian(cart);
var lat = Cesium.Math.toDegrees(cartographic.latitude)
var lng = Cesium.Math.toDegrees(cartographic.longitude)
var alt = cartographic.height
return { x: lng, y: lat, z: alt }
}
function getXYDegrees(cart) {
var cartographic = cart //Cesium.Cartographic.fromCartesian(cart);
var lat = Cesium.Math.toDegrees(cartographic.x)
var lng = Cesium.Math.toDegrees(cartographic.y)
var alt = cartographic.height
return { x: lng, y: lat, z: alt }
}
//经纬度保留两位小数
function strFormat(str) {
var strString = str.toString()
var strs = strString.slice(0, strString.indexOf('.') + 3)
return strs
}
var myChartBox;
function setEchartsData(e) {
console.log('datachart', e);
if (null != e && null != e.arrPoint) {
if(myChartBox){
myChartBox.clear()
}
var myChart = echarts.init(document.getElementById("echartsView1"), 'dark');
myChartBox = myChart
var t = e.arrPoint,
chartData = {
grid: {
left: 10,
right: 10,
bottom: 10,
containLabel: !0,
},
tooltip: {
trigger: 'axis',
formatter: function (e) {
var htmldiv = '';
var r = t[e[0].dataIndex];
return(
htmldiv +=
'所在位置:'+strFormat(r.x)+','+strFormat(r.y)+'<br/>'+
'高程值:'+haoutil.str.formatLength(e[0].value)+'<br/>'
)
},
},
xAxis:
{
name: '距离',
type: 'category',
// boundaryGap: !1,
// axisLabel: {
// show: !1,
// },
data: e.disc,
},
yAxis:
{
type: 'value',
axisLabel: {
rotate: 0,
formatter: '{value} 米',
},
min:200
},
series: [
{
name: '高程值',
type: 'line',
smooth: !0,
symbol: 'none',
sampling: 'average',
itemStyle: {
normal: {
color: 'rgb(255, 70, 131)',
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgb(255, 158, 68)',
},
{
offset: 1,
color: 'rgb(255, 70, 131)',
},
]),
},
},
data: e.arrHB,
},
],
}
myChart.setOption(chartData)
}
}
viewer.camera.setView({
destination: {
x: -2812172.053828897,
y: 4858882.446838023,
z: 3018219.238032221
},
orientation: {
heading: 5.734820212190274,
pitch: -0.4850847932499902,
roll: 6.283179091692488
}
// {heading: 0.5078352572069921, pitch: -0.8543352723531186, roll: 0.11051965413821604}
})
//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== "undefined") {
window.startupCalled = true;
startup(Cesium);
}
</script>
</body>
</html>