Files
sdk4.0_new/src/Obj/Analysis/CutFill/index.js

354 lines
11 KiB
JavaScript
Raw Normal View History

2025-09-01 16:17:11 +08:00
import Dialog from '../../../BaseDialog';
import { html } from "./_element";
// 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.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 = '最少需要三个坐标!'
console.warn(_error)
window.ELEMENT && window.ELEMENT.Message({
message: _error,
type: 'warning',
duration: 1500
});
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; //允许相机进入地下
})
// 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()
});
}
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;