import * as Cesium from "cesium";
export default class ProfileAnalysis {
constructor(viewer) {
this.viewer = viewer;
this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.profileItem = []
this.positionsCartographic = []
this.positions_Inter = []
this.poly = null;
this.floatingPointList = []
}
//世界坐标转换为经纬度
getDegrees(cart) {
let lat = Cesium.Math.toDegrees(cart.latitude);
let lng = Cesium.Math.toDegrees(cart.longitude);
let alt = cart.height;
return {x:lng, y:lat, z:alt};
}
//空间两点距离计算
getSpaceDistance(positions) {
this.profileItem = [
{
point: 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: positions[i+1],
distance: distance
};
this.profileItem.push(m_Item);
}
return distance.toFixed(2);
}
//线段插值点
interPoints(positions) {
this.positionsCartographic = [];
var terrainSamplePositions = [];
for (let index = 0; index < positions.length - 1; index++) {
const element = positions[index];
var ellipsoid = this.viewer.scene.globe.ellipsoid;
var cartographic = ellipsoid.cartesianToCartographic(element);
this.positionsCartographic.push(cartographic);
}
for (let i = 0; i < this.positionsCartographic.length; i++) {
const m_Cartographic0 = this.positionsCartographic[i];
const m_Cartographic1 = this.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;
//等分采样
let length = 10
//按照距离等距采样
// let d =0
// var point1cartographic = Cesium.Cartographic.fromCartesian(positions[0]);
// var point2cartographic = Cesium.Cartographic.fromCartesian(positions[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));
// d = d + s;
// let length = Math.ceil(d/50)
//采样
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);
}
}
this.positions_Inter = [];
for (var n = 0; n < terrainSamplePositions.length; n++) {
//地理坐标(弧度)转经纬度坐标
var m_cartographic = terrainSamplePositions[n];
var height = this.viewer.scene.globe.getHeight(m_cartographic);
var point = Cesium.Cartesian3.fromDegrees(m_cartographic.longitude / Math.PI * 180, m_cartographic.latitude / Math.PI * 180, height);
this.positions_Inter.push(point);
}
}
//剖面分析
profileAnalysis() {
this.viewer.scene.globe.depthTestAgainstTerrain = true
var positions = [];
var distance = 0;
var cartesian = null;
var DistanceArray = [];
const tempViewer = this.viewer
this.handler.setInputAction((movement)=> {
cartesian = this.viewer.scene.pickPosition(movement.endPosition);
if (positions.length >= 2) {
if (!Cesium.defined(this.poly)) {
this.poly = new PolyLinePrimitive(positions);
} else {
positions.pop();
positions.push(cartesian);
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
this.handler.setInputAction((movement) => {
cartesian = this.viewer.camera.pickEllipsoid(movement.position, this.viewer.scene.globe.ellipsoid);
if (positions.length == 0) {
positions.push(cartesian.clone());
}
positions.push(cartesian);
if (this.poly) {
//进行插值计算
this.interPoints(this.poly.positions);
//计算两点间距
distance = this.getSpaceDistance(this.positions_Inter);
} else {
distance = this.getSpaceDistance(positions);
}
var textDisance = distance + "米";
DistanceArray.push(distance);
this.floatingPoint = this.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 === '0.00米' ? '' : 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
}
});
this.floatingPointList.push(this.floatingPoint)
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.setInputAction((movement) =>{
this.handler.destroy();//关闭事件句柄
positions.pop();//最后一个点无效
let data = this.profileItem.map(e=>{
let cartographic = Cesium.Cartographic.fromCartesian(e.point);
// 弧度转为角度(经纬度)
let lon = Cesium.Math.toDegrees(cartographic.longitude); //经度值
let lat = Cesium.Math.toDegrees(cartographic.latitude); //纬度值
let height2 = this.viewer.scene.globe.getHeight(cartographic)
return {
distance: e.distance,
point: [lon,lat,height2],
}
})
window.startPanintDarw(data)
this.viewer.scene.globe.depthTestAgainstTerrain = false
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
var PolyLinePrimitive = (function () {
function _(positions) {
this.options = {
id: 'pmfx_line',
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);
tempViewer.entities.add(this.options);
};
return _;
})();
}
}
参考其他人的写法,但是其他人写的东西不是很全,不全的东西需要自己写完整。这个是取到完整的点,展示需要通过echarts折线图去绘制
如果针对需要固定距离描点(例如每隔5米的距离就展示一个点这种情况)解决办法如下:
//每五米向线段里填充一个点
let d = 0
var point1cartographic = Cesium.Cartographic.fromCartesian(positions[0]);
var point2cartographic = Cesium.Cartographic.fromCartesian(positions[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));
d = d + s;
let position1 = Cesium.Cartesian3.fromDegrees(m_Cartographic0.longitude / Math.PI * 180, m_Cartographic0.latitude / Math.PI * 180, m_Cartographic0.height)
let position2 = Cesium.Cartesian3.fromDegrees(m_Cartographic1.longitude / Math.PI * 180, m_Cartographic1.latitude / Math.PI * 180, m_Cartographic1.height)
let pot = Cesium.Cartesian3.subtract(position2, position1, new Cesium.Cartesian3());//方向
var dir = Cesium.Cartesian3.normalize(pot, new Cesium.Cartesian3());//向量归一化
var ray = new Cesium.Ray(position1, dir);
let length = Math.floor(d/5)
for (let index = 1; index < length; index++) {
let np = Cesium.Ray.getPoint(ray, index*5);//计算延长点
let npCartographic = Cesium.Cartographic.fromCartesian(np);
terrainSamplePositions.push(npCartographic)
}
注意,返回的数据横轴距离也要进行相对应的改动,抛开最后一个点都是5的倍数来计算距离的