init
This commit is contained in:
354
src/Obj/Analysis/CutFill/index.js
Normal file
354
src/Obj/Analysis/CutFill/index.js
Normal file
@ -0,0 +1,354 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user