415 lines
12 KiB
JavaScript
415 lines
12 KiB
JavaScript
import Dialog from '../../../BaseDialog';
|
|
import { html } from "./_element";
|
|
import Tools from "../../../Tools";
|
|
// import CreatePolygon from "./CreatePolygon";
|
|
import DrawPolygon from "../../../Draw/drawPolygon"
|
|
|
|
class CutFillAnalysis {
|
|
/**
|
|
* @constructor 填挖方分析
|
|
* @param sdk
|
|
* **/
|
|
constructor(sdk, options = {}, _Dialog = {}) {
|
|
this.sdk = sdk;
|
|
this.viewer = sdk.viewer;
|
|
// if (!positions) throw new Error("no positions object!");
|
|
// this.positions = positions;
|
|
this.height = options.height || 70
|
|
this.maxHeigh = -1000000;
|
|
this.precision = options.precision || 125
|
|
this.Dialog = _Dialog
|
|
this.result = {
|
|
allArea: "",
|
|
cutArea: "",
|
|
cutVolume: "",
|
|
fillArea: "",
|
|
fillVolume: "",
|
|
noArea: "",
|
|
}
|
|
this.entities = []
|
|
this.tools = new Tools(this.sdk)
|
|
this.Draw = new DrawPolygon(this.sdk)
|
|
YJ.Analysis.AnalysesResults.push(this)
|
|
// CutFillAnalysis.EditBox(this)
|
|
}
|
|
|
|
create() {
|
|
this.clean()
|
|
this.Draw.start((a, positions) => {
|
|
if (!positions || positions.length < 3) {
|
|
let _error = '最少需要三个坐标!'
|
|
this.tools.message({
|
|
text: _error,
|
|
type: 'warning',
|
|
});
|
|
return
|
|
}
|
|
let fromDegreesArray = []
|
|
for (let i = 0; i < positions.length; i++) {
|
|
fromDegreesArray.push(positions[i].lng, positions[i].lat, positions[i].alt)
|
|
}
|
|
this.positions = Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray)
|
|
this.createPolygonGeo(this.positions);
|
|
this.result = this.VolumeAnalysis();
|
|
this.viewer.scene.screenSpaceCameraController.enableCollisionDetection = false; //允许相机进入地下
|
|
this.clickCallBack()
|
|
})
|
|
// const $this = this;
|
|
// if (!this.cp) {
|
|
// this.cp = new CreatePolygon(this.viewer)
|
|
// }
|
|
// this.cp.start(function () {
|
|
// console.log($this.cp.activeShapePoints)
|
|
// $this.positions = $this.cp.activeShapePoints;
|
|
// $this.createPolygonGeo($this.positions);
|
|
// $this.result = $this.VolumeAnalysis();
|
|
// $this.viewer.entities.remove($this.cp.polygon);
|
|
// $this.viewer.scene.screenSpaceCameraController.enableCollisionDetection = false; //允许相机进入地下
|
|
|
|
// });
|
|
}
|
|
createPolygonGeo(points) {
|
|
//计算网格粒度-精度
|
|
let granularity = Math.PI / Math.pow(2, 11);
|
|
granularity = granularity / this.precision;
|
|
let polygonGeometry = new Cesium.PolygonGeometry.fromPositions({
|
|
positions: points,
|
|
vertexFormat: Cesium.PerInstanceColorAppearance.FLAT_VERTEX_FORMAT,
|
|
granularity: granularity,
|
|
});
|
|
//创建自定义平面几何体
|
|
this.geom = new Cesium.PolygonGeometry.createGeometry(polygonGeometry);
|
|
}
|
|
VolumeAnalysis() {
|
|
let cutArea = 0,
|
|
cutVolume = 0,
|
|
fillArea = 0,
|
|
fillVolume = 0,
|
|
noArea = 0;
|
|
const indices = this.geom.indices; //获取顶点索引数据
|
|
if (!this.geom || !this.geom.attributes || !this.geom.attributes.position) {
|
|
return;
|
|
}
|
|
const positions = this.geom.attributes.position.values;
|
|
for (let index = 0; index < indices.length; index += 3) {
|
|
const pos0 = this.returnPosition(positions, indices[index]);
|
|
const pos1 = this.returnPosition(positions, indices[index + 1]);
|
|
const pos2 = this.returnPosition(positions, indices[index + 2]);
|
|
let entity = this.viewer.entities.add({
|
|
name: "三角面",
|
|
polygon: {
|
|
hierarchy: [pos0.heightPos, pos1.heightPos, pos2.heightPos],
|
|
perPositionHeight: true,
|
|
material: Cesium.Color.fromRandom(),
|
|
extrudedHeight: this.height,
|
|
outline: true,
|
|
outlineColor: Cesium.Color.BLACK,
|
|
},
|
|
});
|
|
this.entities.push(entity)
|
|
//水平状态下三角形面积
|
|
const area = this.computeArea4Triangle(
|
|
pos0.noHeightPos,
|
|
pos1.noHeightPos,
|
|
pos2.noHeightPos
|
|
);
|
|
//计算三个点的均高
|
|
const height = (pos0.height + pos1.height + pos2.height) / 3;
|
|
if (height < this.height) {
|
|
// 需要填方的部分
|
|
fillArea += area;
|
|
const volume = area * (this.height - height);
|
|
fillVolume += volume;
|
|
} else if (height == this.height) {
|
|
noArea += area;
|
|
} else {
|
|
// 需要挖方的部分
|
|
cutArea += area;
|
|
const volume = area * (height - this.height);
|
|
cutVolume += volume;
|
|
}
|
|
}
|
|
const allArea = cutArea + fillArea + noArea;
|
|
// this.result = {
|
|
// allArea,
|
|
// cutArea,
|
|
// cutVolume,
|
|
// fillArea,
|
|
// fillVolume,
|
|
// noArea,
|
|
// };
|
|
this.result.allArea = allArea
|
|
this.result.cutArea = cutArea
|
|
this.result.cutVolume = cutVolume
|
|
this.result.fillArea = fillArea
|
|
this.result.fillVolume = fillVolume
|
|
this.result.noArea = noArea
|
|
return this.result;
|
|
}
|
|
computeCentroid4Polygon(positions) {
|
|
let x = [],
|
|
y = [];
|
|
let allX = 0,
|
|
allY = 0;
|
|
for (let i = 0; i < positions.length; i++) {
|
|
let cartographic = Cesium.Cartographic.fromCartesian(positions[i]);
|
|
allX += cartographic.longitude;
|
|
allY += cartographic.latitude;
|
|
x.push(cartographic.longitude);
|
|
y.push(cartographic.latitude);
|
|
}
|
|
let centroidx = allX / positions.length;
|
|
let centroidy = allY / positions.length;
|
|
const Cartographic = new Cesium.Cartographic(centroidx, centroidy);
|
|
return Cesium.Cartesian3.fromRadians(
|
|
Cartographic.longitude,
|
|
Cartographic.latitude,
|
|
this.maxHeigh + 30
|
|
);
|
|
}
|
|
/**
|
|
* 海伦公式求取三角形面积
|
|
* @param {*} pos1
|
|
* @param {*} pos2
|
|
* @param {*} pos3
|
|
* @returns 三角形面积㎡
|
|
*/
|
|
computeArea4Triangle(pos1, pos2, pos3) {
|
|
let a = Cesium.Cartesian3.distance(pos1, pos2);
|
|
let b = Cesium.Cartesian3.distance(pos2, pos3);
|
|
let c = Cesium.Cartesian3.distance(pos3, pos1);
|
|
let S = (a + b + c) / 2;
|
|
return Math.sqrt(S * (S - a) * (S - b) * (S - c));
|
|
}
|
|
returnPosition(positions, index) {
|
|
let cartesian = new Cesium.Cartesian3(
|
|
positions[index * 3],
|
|
positions[index * 3 + 1],
|
|
positions[index * 3 + 2]
|
|
);
|
|
let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
|
|
let height = this.viewer.scene.sampleHeightSupported
|
|
? this.viewer.scene.sampleHeight(cartographic)
|
|
: this.viewer.scene.globe.getHeight(cartographic);
|
|
if (height > this.maxHeigh) {
|
|
this.maxHeigh = height;
|
|
}
|
|
return {
|
|
heightPos: Cesium.Cartesian3.fromRadians(
|
|
cartographic.longitude,
|
|
cartographic.latitude,
|
|
height
|
|
),
|
|
noHeightPos: Cesium.Cartesian3.fromRadians(
|
|
cartographic.longitude,
|
|
cartographic.latitude,
|
|
0
|
|
),
|
|
height: height,
|
|
};
|
|
}
|
|
|
|
static async EditBox(that) {
|
|
if (that._DialogObject && that._DialogObject.close) {
|
|
that._DialogObject.close()
|
|
that._DialogObject = null
|
|
}
|
|
that._DialogObject = await new Dialog(that.sdk.viewer._container, {
|
|
title: '土方分析', left: '180px', top: '100px',
|
|
closeCallBack: () => {
|
|
that.clean()
|
|
that.Dialog.closeCallBack && that.Dialog.closeCallBack()
|
|
},
|
|
})
|
|
await that._DialogObject.init()
|
|
let contentElm = document.createElement('div');
|
|
contentElm.innerHTML = html()
|
|
that._DialogObject.contentAppChild(contentElm)
|
|
that._DialogObject._element.body.className = that._DialogObject._element.body.className + ' cut-fill'
|
|
|
|
// 高度值
|
|
let e_height = contentElm.querySelector("input[name='height']")
|
|
e_height.value = that.height
|
|
e_height.addEventListener('blur', (e) => {
|
|
let value = e.target.value
|
|
if (e.data != '.' && (e.data != '-' || e.target.value)) {
|
|
value = Number(value)
|
|
if ((e.target.max) && value > Number(e.target.max)) {
|
|
value = Number(e.target.max)
|
|
}
|
|
if ((e.target.min) && value < Number(e.target.min)) {
|
|
value = Number(e.target.min)
|
|
}
|
|
e_height.value = value
|
|
that.height = e_height.value;
|
|
}
|
|
});
|
|
|
|
// 精度值
|
|
let e_precision = contentElm.querySelector("input[name='precision']")
|
|
e_precision.value = that.precision
|
|
e_precision.addEventListener('blur', (e) => {
|
|
let value = Number(e.target.value)
|
|
if ((e.target.max) && value > Number(e.target.max)) {
|
|
value = Number(e.target.max)
|
|
}
|
|
if ((e.target.min) && value < Number(e.target.min)) {
|
|
value = Number(e.target.min)
|
|
}
|
|
e_precision.value = value
|
|
that.precision = e_precision.value;
|
|
});
|
|
|
|
// 总分析面积
|
|
let e_allArea = contentElm.querySelector("span[name='allArea']")
|
|
e_allArea.innerHTML = that.result.allArea || 0
|
|
Object.defineProperty(that.result, 'allArea', {
|
|
get() {
|
|
return e_allArea.innerHTML
|
|
},
|
|
set(value) {
|
|
e_allArea.innerHTML = Number(value.toFixed(4))
|
|
}
|
|
})
|
|
// 填方面积
|
|
let e_fillArea = contentElm.querySelector("span[name='fillArea']")
|
|
e_fillArea.innerHTML = that.result.fillArea || 0
|
|
Object.defineProperty(that.result, 'fillArea', {
|
|
get() {
|
|
return e_fillArea.innerHTML
|
|
},
|
|
set(value) {
|
|
e_fillArea.innerHTML = Number(value.toFixed(4))
|
|
}
|
|
})
|
|
|
|
// 填方体积
|
|
let e_fillVolume = contentElm.querySelector("span[name='fillVolume']")
|
|
e_fillVolume.innerHTML = that.result.fillVolume || 0
|
|
Object.defineProperty(that.result, 'fillVolume', {
|
|
get() {
|
|
return e_fillVolume.innerHTML
|
|
},
|
|
set(value) {
|
|
e_fillVolume.innerHTML = Number(value.toFixed(4))
|
|
}
|
|
})
|
|
|
|
// 挖方面积
|
|
let e_cutArea = contentElm.querySelector("span[name='cutArea']")
|
|
e_cutArea.innerHTML = that.result.cutArea || 0
|
|
Object.defineProperty(that.result, 'cutArea', {
|
|
get() {
|
|
return e_cutArea.innerHTML
|
|
},
|
|
set(value) {
|
|
e_cutArea.innerHTML = Number(value.toFixed(4))
|
|
}
|
|
})
|
|
|
|
// 挖方体积
|
|
let e_cutVolume = contentElm.querySelector("span[name='cutVolume']")
|
|
e_cutVolume.innerHTML = that.result.cutVolume || 0
|
|
Object.defineProperty(that.result, 'cutVolume', {
|
|
get() {
|
|
return e_cutVolume.innerHTML
|
|
},
|
|
set(value) {
|
|
e_cutVolume.innerHTML = Number(value.toFixed(4))
|
|
}
|
|
})
|
|
|
|
// 无须填挖面积
|
|
let e_noArea = contentElm.querySelector("span[name='noArea']")
|
|
e_noArea.innerHTML = that.result.noArea || 0
|
|
Object.defineProperty(that.result, 'noArea', {
|
|
get() {
|
|
return e_noArea.innerHTML
|
|
},
|
|
set(value) {
|
|
e_noArea.innerHTML = Number(value.toFixed(4))
|
|
}
|
|
})
|
|
|
|
let newDivBtn = contentElm.getElementsByClassName('draw-btn')[0];
|
|
newDivBtn.addEventListener('click', () => {
|
|
that.create()
|
|
});
|
|
}
|
|
|
|
get heights() {
|
|
return this.height
|
|
}
|
|
set heights(val) {
|
|
this.height = val
|
|
}
|
|
get precisions() {
|
|
return this.precision
|
|
}
|
|
set precisions(val) {
|
|
this.precision = val
|
|
}
|
|
get allArea() {
|
|
return Number(this.result.allArea.toFixed(4))
|
|
}
|
|
set allArea(val) {
|
|
this.result.allArea = val
|
|
}
|
|
get fillArea() {
|
|
return Number(this.result.fillArea.toFixed(4))
|
|
}
|
|
set fillArea(val) {
|
|
this.result.fillArea = val
|
|
}
|
|
get fillVolume() {
|
|
return Number(this.result.fillVolume.toFixed(4))
|
|
}
|
|
set fillVolume(val) {
|
|
this.result.fillVolume = val
|
|
}
|
|
get cutArea() {
|
|
return Number(this.result.cutArea.toFixed(4))
|
|
}
|
|
set cutArea(val) {
|
|
this.result.cutArea = val
|
|
}
|
|
get cutVolume() {
|
|
return Number(this.result.cutVolume.toFixed(4))
|
|
}
|
|
set cutVolume(val) {
|
|
this.result.cutVolume = val
|
|
}
|
|
get noArea() {
|
|
return Number(this.result.noArea.toFixed(4))
|
|
}
|
|
set noArea(val) {
|
|
this.result.noArea = val
|
|
}
|
|
get onEnd() {
|
|
return this.clickCallBack
|
|
}
|
|
set onEnd(val) {
|
|
if (val && typeof val !== 'function') {
|
|
console.error('val:', val, '不是一个function')
|
|
} else {
|
|
this.clickCallBack = val
|
|
}
|
|
}
|
|
|
|
clean() {
|
|
this.Draw && this.Draw.end()
|
|
for (let i = 0; i < this.entities.length; i++) {
|
|
this.viewer.entities.remove(this.entities[i])
|
|
}
|
|
}
|
|
|
|
destroy() {
|
|
this.clean()
|
|
if (this._DialogObject && this._DialogObject.close) {
|
|
this._DialogObject.close()
|
|
this._DialogObject = null
|
|
}
|
|
}
|
|
}
|
|
export default CutFillAnalysis;
|