本人现在使用的cesium版本1.61
功能实现:鼠标点击绘制剖面线(左键开始,右键终止),实时显示剖面线地表距离;剖面线绘制结束后计算、绘制并输出剖面图;剖面图展示所画剖面线的地表最高点和最低点,鼠标放置在绘制好的剖面图线段上时,显示该点高程值。
实现思路:剖面线和剖面图的绘制输出整体建立在地表空间量测(我的其他博客也有记录Cesium空间测量-空间距离和地表距离实现)的基础之上,通过获取到的地表高程系列点,实现剖面线制作。
效果图:
代码实现:
① 剖面实现,并获取到绘图所需数据,交给方法createProfileChart来处理。
/*
* @Author: Wang JianLei
* @Date: 2020-04-08 10:55:43
* @Last Modified by: Wang JianLei
* @Last Modified time: 2020-04-20 09:49:37
*/
//剖面分析
/******************************************* **
剖面分析直接调用Profile()即可,左键画线,右键停止
createProfileChart()方法绘制剖面图
** ****************************************** */
var Profile = function () {
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene._imageryLayerCollection);
var positions = [];
var positionsCartographic = [];
var positions_Inter = [];
var poly = null;
var distance = 0;
var cartesian = null;
var floatingPoint;
var DistanceArray = [];
var profileItem = [];
let $menuBox = $('#SideBar');
let outerW = $menuBox.outerWidth();
handler.setInputAction(function (movement) {
movement.endPosition.x = movement.endPosition.x - outerW;
cartesian = viewer.scene.pickPosition(movement.endPosition);
if (positions.length >= 2) {
if (!Cesium.defined(poly)) {
poly = new PolyLinePrimitive(positions);
} else {
positions.pop();
positions.push(cartesian);
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction(function (movement) {
movement.position.x = movement.position.x - outerW;
cartesian = viewer.scene.pickPosition(movement.position);
if (positions.length == 0) {
positions.push(cartesian.clone());
}
positions.push(cartesian);
if (poly) {
//进行插值计算
interPoints(poly.positions);
distance = getSpaceDistance(positions_Inter);
} else {
distance = getSpaceDistance(positions);
}
var textDisance = distance + "米";
DistanceArray.push(distance);
floatingPoint = viewer.entities.add({
position: positions[positions.length - 1],
point: {
pixelSize: 5,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
heightReference: Cesium.HeightReference.NONE
},
label: {
text: textDisance,
font: '18px sans-serif',
fillColor: Cesium.Color.GOLD,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(20, -20),
heightReference: Cesium.HeightReference.NONE
}
});
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function (movement) {
handler.destroy();//关闭事件句柄
positions.pop();//最后一个点无效
createProfileChart(profileItem);
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
var PolyLinePrimitive = (function () {
function _(positions) {
this.options = {
polyline: {
show: true,
positions: [],
material: Cesium.Color.CHARTREUSE,
width: 2,
clampToGround: true
}
};
this.positions = positions;
this._init();
}
_.prototype._init = function () {
var _self = this;
var _update = function () {
return _self.positions;
};
//实时更新polyline.positions
this.options.polyline.positions = new Cesium.CallbackProperty(_update, false);
viewer.entities.add(this.options);
};
return _;
})();
//空间两点距离计算函数
function getSpaceDistance(positions) {
profileItem = [
{
point: cartesian3ToDegrees(positions[0]),
distance: 0
}
];
var distance = 0;
for (var i = 0; i < positions.length - 1; i++) {
var point1cartographic = Cesium.Cartographic.fromCartesian(positions[i]);
var point2cartographic = Cesium.Cartographic.fromCartesian(positions[i + 1]);
/**根据经纬度计算出距离**/
var geodesic = new Cesium.EllipsoidGeodesic();
geodesic.setEndPoints(point1cartographic, point2cartographic);
var s = geodesic.surfaceDistance;
//返回两点之间的距离
s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2));
distance = distance + s;
var m_Item = {
point: cartesian3ToDegrees(positions[i + 1]),
distance: distance
};
profileItem.push(m_Item);
}
return distance.toFixed(2);
}
//线段插值点
function interPoints(positions) {
positionsCartographic = [];
var terrainSamplePositions = [];
for (let index = 0; index < positions.length - 1; index++) {
const element = positions[index];
var ellipsoid = viewer.scene.globe.ellipsoid;
var cartographic = ellipsoid.cartesianToCartographic(element);
positionsCartographic.push(cartographic);
}
for (let i = 0; i < positionsCartographic.length; i++) {
const m_Cartographic0 = positionsCartographic[i];
const m_Cartographic1 = positionsCartographic[i + 1];
if (m_Cartographic1) {
var a = Math.abs(m_Cartographic0.longitude - m_Cartographic1.longitude) * 10000000;
var b = Math.abs(m_Cartographic0.latitude - m_Cartographic1.latitude) * 10000000;
//等距采样
if (a > b) b = a;
var length = parseInt(b / 2);
if (length > 1000) length = 1000;
if (length < 2) length = 2;
// var length = 4;//等分采样
for (var j = 0; j < length; j++) {
terrainSamplePositions.push(
new Cesium.Cartographic(
Cesium.Math.lerp(m_Cartographic0.longitude, m_Cartographic1.longitude, j / (length - 1)),
Cesium.Math.lerp(m_Cartographic0.latitude, m_Cartographic1.latitude, j / (length - 1))
)
);
}
terrainSamplePositions.pop();
} else {
terrainSamplePositions.push(m_Cartographic0);
}
}
positions_Inter = [];
for (var n = 0; n < terrainSamplePositions.length; n++) {
//地理坐标(弧度)转经纬度坐标
var m_cartographic = terrainSamplePositions[n];
var height = viewer.scene.globe.getHeight(m_cartographic);
var point = Cesium.Cartesian3.fromDegrees(m_cartographic.longitude / Math.PI * 180, m_cartographic.latitude / Math.PI * 180, height);
positions_Inter.push(point);
}
}
};
②Echart绘制剖面图
/*
* @Author: Wang JianLei
* @Date: 2020-04-20 10:47:46
* @Last Modified by: Wang JianLei
* @Last Modified time: 2020-04-20 10:48:27
*/
//Echart绘制剖面图
/******************************************* **
调用分析结果createProfileChart()方法绘制剖面图
** ****************************************** */
function createProfileChart(Positions) {
console.log(Positions);
var x_Range = parseInt(Positions[Positions.length - 1].distance);
console.log(x_Range);
var ProfileData = [];
var ProfileData_Lon = [];
var y_Min = 100000000;
for (let index = 0; index < Positions.length; index++) {
const element = Positions[index];
var m_distance = element.distance.toFixed(2);
var m_Lon = element.point[0].toFixed(5);
var m_Lat = element.point[1].toFixed(5);
var m_height = element.point[2].toFixed(2);
if (m_height < y_Min) {
y_Min = m_height;
}
var m_data = [m_distance, m_height];
ProfileData.push(m_data);
ProfileData_Lon.push([m_Lon, m_Lat]);
}
console.log(ProfileData);
var lineChart = echarts.init(document.getElementById("profileChart"));
// background: rgba(255, 255, 255, 1);
var lineoption = {
title: {
text: '剖面分析'
},
tooltip: {
trigger: 'axis',
formatter(params) {
// console.log(params['data']);
return "当前高度:" + params['data'][1];
}
},
legend: {
data: ['剖面线']
},
grid: {
x: 40,
x2: 40,
y2: 24
},
calculable: true,
xAxis: [
{
type: 'value',
max: 'dataMax',
scale: true
}
],
yAxis: [
{
type: 'value',
min: y_Min,
scale: true
}
],
series: [
{
name: '剖面线',
type: 'line',
data: ProfileData,
markPoint: {
data: [
{ type: 'max', name: '最高点' },
{ type: 'min', name: '最低点' }
]
}
}
]
};
lineChart.setOption(lineoption);
document.getElementById("profileChart").style.backgroundColor = 'rgba(255, 255, 255, 1)';
document.getElementById("profileChart").style.visibility = 'visible';
$(window).resize(lineChart.resize);
}
运行效果: