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;