mirror of
https://github.com/jiawanlong/Cesium-Examples.git
synced 2025-07-04 15:17:36 +00:00
456 lines
18 KiB
JavaScript
456 lines
18 KiB
JavaScript
/**
|
|
* @class DEUGlobe.Analysis.measureVolume
|
|
* @category 分析
|
|
* @classdesc 方量分析直接调用new DEUGlobe.Analysis.measureVolume()即可,左键画线,右键停止
|
|
* @param {Object} viewer - Cesium.viewer。
|
|
* @param {Object} options - 参数。
|
|
* @param {Boolean} options.terrainLevel - terrainLevel。 查询当前地形级别(默认 13)
|
|
*/
|
|
class MeasureVolume{
|
|
constructor(viewer,options){
|
|
var _this = this;
|
|
this.viewer = viewer;
|
|
this.optS = options ||{};
|
|
this.handler = null;
|
|
this.polygon = null;
|
|
this.wall = null;
|
|
this.initHeight = 0;
|
|
this.minHeight = 0;
|
|
this.maxHeight =0;
|
|
this.volumn = 0;
|
|
this.label = null;
|
|
this.cartesian = null;
|
|
this.poly = null;
|
|
this.area = null;
|
|
this.cellsize = null;
|
|
this.centroid = null;
|
|
this.planeHeight = 0;
|
|
this.positions = [];
|
|
this.Cartesian2Array = [];
|
|
this.floatingPointLis = [];
|
|
viewer.scene.globe.depthTestAgainstTerrain = true;
|
|
this.data = [];
|
|
this.PolygonPrimitive = (function () {
|
|
function _(positions) {
|
|
this.options = {
|
|
name: '多边形',
|
|
polygon: {
|
|
show: true,
|
|
perPositionHeight: true,
|
|
material: Cesium.Color.CHARTREUSE.withAlpha(0.5),
|
|
}
|
|
};
|
|
this.hierarchy = positions;
|
|
this._init();
|
|
}
|
|
_.prototype._init = function () {
|
|
var _self = this;
|
|
var _update = function () {
|
|
return new Cesium.PolygonHierarchy(_self.hierarchy);
|
|
};
|
|
//实时更新polygon.positions
|
|
this.options.polygon.hierarchy = new Cesium.CallbackProperty(_update, false);
|
|
_this.polygon = _this.viewer.entities.add(this.options);
|
|
};
|
|
return _;
|
|
})();
|
|
|
|
var tooltip = document.createElement('div');
|
|
tooltip.setAttribute('class','roamWidget_tooltip')
|
|
var tooltipArrow = document.createElement('div');
|
|
tooltipArrow.setAttribute('class','roamWidget_tooltip_arrow')
|
|
tooltip.appendChild(tooltipArrow);
|
|
var tooltipInner = document.createElement('div');
|
|
tooltipInner.setAttribute('class','roamWidget_tooltip_inner')
|
|
tooltip.appendChild(tooltipInner);
|
|
tooltipInner.innerHTML = "单击 开始绘制";
|
|
this.tooltip = tooltip;
|
|
this.tooltipInner = tooltipInner;
|
|
}
|
|
/**
|
|
* @classdesc 方量分析
|
|
* @param {function} callback - 绘制完成回调
|
|
*/
|
|
initMeasureVolume(callback){
|
|
var _this = this;
|
|
_this.positions = []
|
|
_this.Cartesian2Array = []
|
|
_this.handler = new Cesium.ScreenSpaceEventHandler(_this.viewer.scene._imageryLayerCollection);
|
|
_this.tooltip.style.left = "-100000px";
|
|
_this.tooltip.style.top = "-100000px";
|
|
document.getElementsByTagName('body')[0].appendChild(_this.tooltip);
|
|
_this.viewer.scene.canvas.style.cursor='crosshair';
|
|
_this.handler.setInputAction(function (movement) {
|
|
var ray = _this.viewer.camera.getPickRay(movement.endPosition);
|
|
_this.cartesian = _this.viewer.scene.globe.pick(ray,_this.viewer.scene);
|
|
if (_this.positions.length >= 2) {
|
|
if (!Cesium.defined(_this.poly)) {
|
|
_this.poly = new _this.PolygonPrimitive(_this.positions);
|
|
} else {
|
|
if(_this.cartesian != null){
|
|
_this.positions.pop();
|
|
_this.cartesian.y += (1 + Math.random());
|
|
_this.positions.push(_this.cartesian);
|
|
}
|
|
}
|
|
};
|
|
|
|
_this.tooltip.style.left = movement.endPosition.x + 20 + "px";
|
|
_this.tooltip.style.top = movement.endPosition.y - 10 + "px";
|
|
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
|
|
|
|
_this.handler.setInputAction(function (movement) {
|
|
var ray = _this.viewer.camera.getPickRay(movement.position);
|
|
_this.cartesian = _this.viewer.scene.globe.pick(ray,_this.viewer.scene);
|
|
if (_this.positions.length == 0) {
|
|
_this.positions.push(_this.cartesian.clone());
|
|
}
|
|
// console.log(_this.positions)
|
|
_this.positions.push(_this.cartesian);
|
|
_this.tooltipInner.innerHTML = "单击增加点,右键结束";
|
|
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
|
|
|
_this.handler.setInputAction(function (movement) {
|
|
_this.viewer.entities.remove(_this.polygon);
|
|
document.getElementsByTagName('body')[0].removeChild(_this.tooltip);
|
|
_this.viewer.scene.canvas.style.cursor=''
|
|
_this.handler.destroy();//关闭事件句柄
|
|
_this.positions.pop();//最后一个点无效
|
|
var ellipsoid = _this.viewer.scene.globe.ellipsoid;
|
|
_this.positions.forEach(element => {
|
|
var cartographic=ellipsoid.cartesianToCartographic(element);
|
|
var lat=Cesium.Math.toDegrees(cartographic.latitude);
|
|
var lng=Cesium.Math.toDegrees(cartographic.longitude);
|
|
_this.Cartesian2Array.push([lng,lat])
|
|
});
|
|
_this.Cartesian2Array.push(_this.Cartesian2Array[0]);
|
|
|
|
let polygon = turf.polygon([ _this.Cartesian2Array]);
|
|
_this.cellsize = Math.sqrt(turf.area(polygon) / 10000);
|
|
|
|
let enveloped = turf.envelope(polygon);
|
|
_this.area = turf.area(polygon);
|
|
_this.centroid = turf.centroid(polygon);
|
|
|
|
let bbox = turf.bbox(enveloped);
|
|
let grid = turf.pointGrid(bbox, _this.cellsize, { units: 'meters' });
|
|
let ptsWithin = turf.pointsWithinPolygon(grid, polygon);
|
|
let lonlats = [];
|
|
let features = ptsWithin.features;
|
|
for (let i = 0; i < features.length; i++) {
|
|
lonlats.push({
|
|
lon: features[i].geometry.coordinates[0],
|
|
lat: features[i].geometry.coordinates[1]
|
|
})
|
|
}
|
|
TerrainToolCopy.LonlatPointsTerrainData( _this.viewer.terrainProvider, lonlats, _this.optS.terrainLevel, (positions) => {
|
|
_this.getVolumn(positions);
|
|
callback({
|
|
planeHeight:_this.minHeight,
|
|
wallMinHeight:_this.minHeight,
|
|
wallMaxHeight:_this.maxHeight
|
|
})
|
|
})
|
|
|
|
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
|
|
};
|
|
initMeasure(positions) {
|
|
var _this = this;
|
|
_this.positions = []
|
|
_this.Cartesian2Array = []
|
|
_this.tooltip.style.left = "-100000px";
|
|
_this.tooltip.style.top = "-100000px";
|
|
var ellipsoid = _this.viewer.scene.globe.ellipsoid;
|
|
|
|
_this.positions = positions
|
|
_this.positions.forEach(element => {
|
|
var cartographic=ellipsoid.cartesianToCartographic(element);
|
|
var lat=Cesium.Math.toDegrees(cartographic.latitude);
|
|
var lng=Cesium.Math.toDegrees(cartographic.longitude);
|
|
_this.Cartesian2Array.push([lng,lat])
|
|
});
|
|
_this.Cartesian2Array.push(_this.Cartesian2Array[0]);
|
|
_this.minHeight = 3000;
|
|
_this.initHeight = 4000;
|
|
_this.maxHeight = 5000;
|
|
let polygon = turf.polygon([ _this.Cartesian2Array]);
|
|
_this.cellsize = Math.sqrt(turf.area(polygon) / 10000);
|
|
|
|
let enveloped = turf.envelope(polygon);
|
|
_this.area = turf.area(polygon);
|
|
_this.centroid = turf.centroid(polygon);
|
|
|
|
let bbox = turf.bbox(enveloped);
|
|
let grid = turf.pointGrid(bbox, _this.cellsize, { units: 'meters' });
|
|
let ptsWithin = turf.pointsWithinPolygon(grid, polygon);
|
|
let lonlats = [];
|
|
let features = ptsWithin.features;
|
|
for (let i = 0; i < features.length; i++) {
|
|
lonlats.push({
|
|
lon: features[i].geometry.coordinates[0],
|
|
lat: features[i].geometry.coordinates[1]
|
|
})
|
|
}
|
|
TerrainToolCopy.LonlatPointsTerrainData( _this.viewer.terrainProvider, lonlats, _this.optS.terrainLevel, (positions) => {
|
|
_this.getVolumn(positions,true);
|
|
callback({
|
|
planeHeight:_this.minHeight,
|
|
wallMinHeight:_this.minHeight,
|
|
wallMaxHeight:_this.maxHeight
|
|
})
|
|
})
|
|
|
|
};
|
|
getVolumn(data,flag) {
|
|
var _this = this;
|
|
_this.data = data;
|
|
let positions = [];
|
|
var ellipsoid=_this.viewer.scene.globe.ellipsoid;
|
|
_this.positions.forEach(element => {
|
|
var cartographic=ellipsoid.cartesianToCartographic(element);
|
|
let haiba = _this.viewer.scene.globe.getHeight(cartographic);
|
|
positions.push(haiba)
|
|
_this.floatingPoint = _this.viewer.entities.add({
|
|
position: element,
|
|
label: {
|
|
text: "海拔:" + haiba.toFixed(2) + "米",
|
|
font: '19px sans-serif',
|
|
fillColor: Cesium.Color.GOLD,
|
|
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
|
outlineWidth: 2,
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
|
pixelOffset: new Cesium.Cartesian2(0.0, -20)
|
|
}
|
|
});
|
|
_this.floatingPointLis.push(_this.floatingPoint);
|
|
});
|
|
if (!flag) {
|
|
_this.minHeight = findMinHeight(positions);
|
|
_this.initHeight = _this.planeHeight = _this.minHeight;
|
|
_this.maxHeight = findMaxHeight(positions);
|
|
}
|
|
_this.volumn = 0;
|
|
let a1 = 0,a2 = 0;
|
|
for (let i = 0; i < data.length; i++) {
|
|
_this.volumn += (data[i]['height'] - _this.minHeight) * _this.cellsize * _this.cellsize;
|
|
}
|
|
let Cartesian3Array = [];
|
|
let minimumHeights = [];
|
|
let maximumHeights = [];
|
|
_this.Cartesian2Array.forEach(element => {
|
|
console.log(element)
|
|
element.forEach((element1,index) => {
|
|
Cartesian3Array.push(element1);
|
|
if(index==1){
|
|
Cartesian3Array.push(0);
|
|
}
|
|
})
|
|
minimumHeights.push(_this.minHeight);
|
|
maximumHeights.push(_this.maxHeight);
|
|
});
|
|
_this.wall = _this.viewer.entities.add({
|
|
wall: {
|
|
positions: Cesium.Cartesian3.fromDegreesArrayHeights(Cartesian3Array),
|
|
minimumHeights:minimumHeights,
|
|
maximumHeights:maximumHeights,
|
|
outline:true,
|
|
outlineColor: Cesium.Color.WHITE.withAlpha(0.7),
|
|
material: Cesium.Color.CYAN.withAlpha(0.7),
|
|
},
|
|
});
|
|
_this.polygon = _this.viewer.entities.add({
|
|
polygon: {
|
|
show: true,
|
|
hierarchy:new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArrayHeights(Cartesian3Array)),
|
|
height:_this.minHeight,
|
|
material: Cesium.Color.CHARTREUSE.withAlpha(0.5),
|
|
}
|
|
});
|
|
let volumn = 0;
|
|
let area = 0;
|
|
if( _this.volumn/10000 > 0.01){
|
|
volumn = ( _this.volumn/10000).toFixed(2) +'万立方米';
|
|
}else{
|
|
volumn = _this.volumn.toFixed(2) +'立方米';
|
|
}
|
|
if( _this.area/10000 > 0.01){
|
|
area = ( _this.area/10000).toFixed(2) +'万平方米';
|
|
}else{
|
|
area = _this.area.toFixed(2) +'平方米';
|
|
}
|
|
_this.label = _this.viewer.entities.add({
|
|
name: "飞机",
|
|
position: Cesium.Cartesian3.fromDegrees(_this.centroid.geometry.coordinates[0], _this.centroid.geometry.coordinates[1], _this.maxHeight),
|
|
label: {
|
|
text:"挖方体积:" + volumn +'\n'+ "横切面积:" + area,
|
|
font: '18px sans-serif',
|
|
showBackground: true,
|
|
fillColor: Cesium.Color.WHITE,
|
|
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
pixelOffset: new Cesium.Cartesian2(0.0, -80)
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* @classdesc 设置参数
|
|
* @param {Object} options - 参数。
|
|
* @param {function} callback - 绘制完成回调
|
|
*/
|
|
setParameters(opt,callback){
|
|
this.planeHeight = opt.planeHeight == undefined ? this.planeHeight : opt.planeHeight;
|
|
this.minHeight = opt.wallMinHeight == undefined ? this.minHeight : opt.wallMinHeight;
|
|
this.maxHeight = opt.wallMaxHeight == undefined ? this.maxHeight : opt.wallMaxHeight;
|
|
if(this.planeHeight < this.minHeight){
|
|
this.minHeight = this.planeHeight;
|
|
}
|
|
|
|
if(this.planeHeight > this.maxHeight){
|
|
this.maxHeight = this.planeHeight;
|
|
}
|
|
if (Cesium.defined(this.polygon)){
|
|
this.polygon.polygon.height.setValue(this.planeHeight);
|
|
}
|
|
if (Cesium.defined(this.wall)){
|
|
let minimumHeights = [];
|
|
for (let index = 0; index < this.wall.wall.minimumHeights.getValue().length; index++) {
|
|
minimumHeights.push(this.minHeight)
|
|
}
|
|
this.wall.wall.minimumHeights.setValue(minimumHeights);
|
|
let maximumHeights = [];
|
|
for (let index = 0; index < this.wall.wall.maximumHeights.getValue().length; index++) {
|
|
maximumHeights.push(this.maxHeight)
|
|
}
|
|
this.wall.wall.maximumHeights.setValue(maximumHeights);
|
|
}
|
|
this.calculateBulk();
|
|
callback({
|
|
planeHeight:this.planeHeight,
|
|
wallMinHeight:this.minHeight,
|
|
wallMaxHeight:this.maxHeight
|
|
});
|
|
}
|
|
//计算体积
|
|
calculateBulk(){
|
|
//基准面下的体积
|
|
let planeBulk = this.area * (this.planeHeight - this.minHeight);
|
|
//挖方体积
|
|
let volumn = 0;
|
|
this.volumn = 0;
|
|
for (let i = 0; i < this.data.length; i++) {
|
|
this.volumn += (this.data[i]['height'] - this.minHeight) * this.cellsize * this.cellsize;
|
|
if(this.data[i]['height'] > this.planeHeight){
|
|
volumn += (this.data[i]['height'] - this.planeHeight) * this.cellsize * this.cellsize;
|
|
}
|
|
}
|
|
let fillInBulk = 0;
|
|
if(this.initHeight <= this.planeHeight){
|
|
//填方体积
|
|
fillInBulk = planeBulk - (this.volumn - volumn);
|
|
}
|
|
|
|
if(fillInBulk > 0){
|
|
if( fillInBulk/10000 > 0.01){
|
|
fillInBulk = ( fillInBulk/10000).toFixed(2) +'万立方米';
|
|
}else{
|
|
fillInBulk = fillInBulk.toFixed(2) +'立方米';
|
|
}
|
|
fillInBulk = "填方体积:"+ fillInBulk+'\n';
|
|
}else{
|
|
fillInBulk ='';
|
|
}
|
|
if(volumn >0){
|
|
if( volumn/10000 > 0.01){
|
|
volumn = ( volumn/10000).toFixed(2) +'万立方米';
|
|
}else{
|
|
volumn = volumn.toFixed(2) +'立方米';
|
|
}
|
|
volumn = "挖方体积:"+ volumn +'\n';
|
|
}else{
|
|
volumn ='';
|
|
}
|
|
let area = this.area
|
|
if( area/10000 > 0.01){
|
|
area = ( area/10000).toFixed(2) +'万平方米';
|
|
}else{
|
|
area = area.toFixed(2) +'平方米';
|
|
}
|
|
this.label.label.text.setValue(fillInBulk+volumn+"横切面积:"+area)
|
|
}
|
|
//清除
|
|
clear(){
|
|
if(this.floatingPointLis.length>0){
|
|
this.floatingPointLis.forEach(element => {
|
|
this.viewer.entities.remove(element);
|
|
});
|
|
}
|
|
if(Cesium.defined(this.wall)){
|
|
this.viewer.entities.remove(this.wall);
|
|
}
|
|
if(Cesium.defined(this.polygon)){
|
|
this.viewer.entities.remove(this.polygon);
|
|
}
|
|
if(Cesium.defined(this.label)){
|
|
this.viewer.entities.remove(this.label);
|
|
}
|
|
}
|
|
}
|
|
|
|
function findMinHeight(e) {
|
|
e = e.sort((a, b) => a - b);
|
|
// let minHeight = 0;
|
|
// let minPoint = null;
|
|
// for (let i = 0; i < e.length; i++) {
|
|
// let height = e[i];
|
|
// if (height < minHeight) {
|
|
// minHeight = height;
|
|
// }
|
|
// }
|
|
return e[0];
|
|
}
|
|
function findMaxHeight(e) {
|
|
e = e.sort((a, b) => b - a);
|
|
return e[0];
|
|
}
|
|
//获取高程
|
|
var TerrainToolCopy = (
|
|
function () {
|
|
|
|
function _() {
|
|
|
|
}
|
|
|
|
//传入lonlat数组 角度制的lon lat
|
|
_.LonlatPointsTerrainData = function (terrainProvider,lonlats, terrainLevel = 13, callback) {
|
|
var pointArrInput = [];
|
|
for (var i = 0; i < lonlats.length; i++) {
|
|
pointArrInput.push(Cesium.Cartographic.fromDegrees(lonlats[i].lon, lonlats[i].lat));
|
|
}
|
|
// var promise = Cesium.sampleTerrain(terrainProvider, terrainLevel, pointArrInput);//pointArrInput
|
|
// Cesium.when(promise, function (updatedPositions) {
|
|
// callback(updatedPositions);
|
|
// });
|
|
var p1 = Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, pointArrInput)
|
|
Promise.all([p1]).then((samples) => {
|
|
callback(samples[0]);
|
|
})
|
|
|
|
};
|
|
|
|
//传入Cartographic类型数组 弧度制经纬度
|
|
_.CartographicPointsTerrainData = function (terrainProvider,Cartographics, callback) {
|
|
if (Cartographics.length && Cartographics.length > 0) { } else { return; }
|
|
// var promise = Cesium.sampleTerrain(terrainProvider, terrainLevel, Cartographics);//pointArrInput
|
|
// Cesium.when(promise, function (updatedPositions) {
|
|
// callback(updatedPositions);
|
|
// });
|
|
var p1 = Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, Cartographics)
|
|
Promise.all([p1]).then((samples) => {
|
|
callback(samples[0]);
|
|
})
|
|
|
|
};
|
|
return _;
|
|
}
|
|
)(); |