// ViewShed.js import glsl from './glsl' import Event from "../../../Event"; import MouseTip from "../../../MouseTip"; import Tools from "../../../Tools"; import Controller from "../../../Controller"; import Dialog from '../../../BaseDialog'; import { html } from "./_element"; /** * @constructor * @description 圆形可视域分析(--方块) * @param sdk * @param {Object} options 选项。 * @param {String} options.visibleAreaColor=#008000 可视区域颜色(默认值`绿色`)。 * @param {String} options.invisibleAreaColor=#FF0000 不可视区域颜色(默认值`红色`)。 */ class ViewShedStage extends Tools { constructor(sdk, options = {}, _Dialog = {}) { super(sdk, options) this.viewer = sdk.viewer; this.options = {} let precision = Math.floor(options.precision) if (isNaN(precision)) { this.precision = 40 } else if (precision < 10) { this.precision = 10 } else { this.precision = precision } this.options.visibleAreaColor = options.visibleAreaColor || '#008000'; this.options.invisibleAreaColor = options.invisibleAreaColor || '#FF0000'; this.ids = [] this.primitives = [] this.viewpointPrimitive = null this.Dialog = _Dialog this.html = null YJ.Analysis.AnalysesResults.push(this) ViewShedStage.create(this) } static create(that) { let count = 0; if (!YJ.Measure.GetMeasureStatus()) { let Draw = new YJ.Draw.DrawCircle(that.sdk) Draw.start((a, options) => { that.center = options.center that.radius = options.radius that.analyse() }) } else { console.log('上一次测量未结束') } } static async edit(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.Dialog.closeCallBack && that.Dialog.closeCallBack() YJ.Measure.SetMeasureStatus(false) }, }) await that._DialogObject.init() that._DialogObject._element.body.className = that._DialogObject._element.body.className + ' view-shed' let contentElm = document.createElement('div'); contentElm.innerHTML = html() that._DialogObject.contentAppChild(contentElm) } analyse() { this.destroy() let center = [this.center.lng, this.center.lat]; let radius = this.radius / 1000; let circle = turf.circle(center, radius, { steps: 180, units: 'kilometers', properties: { foo: 'bar' } }); let pointPrimitives = null;// 申明点渲染集合 this.viewpointPrimitive = this.viewer.scene.primitives.add(new Cesium.PointPrimitiveCollection()); console.log('circle', circle) let bbox = turf.bbox(circle); console.log(bbox) let bboxPolygon = turf.bboxPolygon(bbox); console.log(bboxPolygon) let cellSide = radius / this.precision; let grid = turf.pointGrid(bbox, cellSide, { units: 'kilometers' }); console.log(grid) let ptsWithin = turf.pointsWithinPolygon(grid, circle); console.log('ptsWithin', ptsWithin) let viewPoint = Cesium.Cartesian3.fromDegrees(this.center.lng, this.center.lat, this.center.alt + 2); this.viewpointPrimitive.add({ position: viewPoint, color: Cesium.Color.AQUA.withAlpha(1), pixelSize: 6 }) let instances = [] let xp = (bbox[2] - bbox[0]) / (this.precision * 4) let yp = (bbox[3] - bbox[1]) / (this.precision * 4) let _this = this let item = 200 let m = 0 let total = ptsWithin.features.length let intervalEvent = setInterval(() => { if (m >= ptsWithin.features.length) { clearInterval(intervalEvent) return } else { InBatches(m) m += 200 } }, 30); function InBatches(k) { let instances = [] let length = k + 200 if (length >= ptsWithin.features.length) { length = ptsWithin.features.length } for (let i = k; i < length; i++) { let positionArr = [] let pt = ptsWithin.features[i].geometry.coordinates; let cartographic = Cesium.Cartographic.fromDegrees(pt[0], pt[1]); let height = _this.viewer.scene.globe.getHeight(cartographic) let pt3d = Cesium.Cartesian3.fromDegrees(pt[0], pt[1], height); // let position = this.viewer.scene.clampToHeight(pt3d) let targetPoint = pt3d; let direction = Cesium.Cartesian3.normalize( Cesium.Cartesian3.subtract( targetPoint, viewPoint, new Cesium.Cartesian3() ), new Cesium.Cartesian3() ); let ray = new Cesium.Ray(viewPoint, direction); let pickedObjects = _this.viewer.scene.drillPickFromRay(ray); let result for (let i = 0; i < pickedObjects.length; i++) { if (pickedObjects[i].position) { result = pickedObjects[i] break } } let color = Cesium.Color.LIME if (result && Math.abs(result.position.x - pt3d.x) > 0.01 && Math.abs(result.position.y - pt3d.y) > 0.01 && Math.abs(result.position.z - pt3d.z) > 0.01) { color = Cesium.Color.RED } positionArr.push(pt[0] - xp, pt[1] + yp, pt[0] + xp, pt[1] + yp, pt[0] + xp, pt[1] - yp, pt[0] - xp, pt[1] - yp) let polygon = new Cesium.PolygonGeometry({ polygonHierarchy: new Cesium.PolygonHierarchy( Cesium.Cartesian3.fromDegreesArray(positionArr) ), height: 0.0, extrudedHeight: 0.0, vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT, ellipsoid: Cesium.Ellipsoid.WGS84, granularity: Cesium.Math.RADIANS_PER_DEGREE, // 每个纬度和经度之间的距离(以弧度为单位),确定缓冲区中的位置数 perPositionHeight: false, // 每个位置点使用的高度 closeTop: true, closeBottom: true, }); let polygonInstance = new Cesium.GeometryInstance({ geometry: polygon, name: "ViewershedPolygon", attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor( color.withAlpha(0.6) ), show: new Cesium.ShowGeometryInstanceAttribute(true), //显示或者隐藏 }, }); instances.push(polygonInstance) } _this.primitives.push(_this.viewer.scene.primitives.add( new Cesium.GroundPrimitive({ geometryInstances: instances, appearance: new Cesium.PerInstanceColorAppearance({ translucent: true, //false时透明度无效 closed: false, }), }) )); } // for (let i = 0; i < ptsWithin.features.length; i++) { // let positionArr = [] // let pt = ptsWithin.features[i].geometry.coordinates; // let cartographic = Cesium.Cartographic.fromDegrees(pt[0], pt[1]); // let height = this.viewer.scene.globe.getHeight(cartographic) // let pt3d = Cesium.Cartesian3.fromDegrees(pt[0], pt[1], height); // // let position = this.viewer.scene.clampToHeight(pt3d) // let targetPoint = pt3d; // let direction = Cesium.Cartesian3.normalize( // Cesium.Cartesian3.subtract( // targetPoint, // viewPoint, // new Cesium.Cartesian3() // ), // new Cesium.Cartesian3() // ); // let ray = new Cesium.Ray(viewPoint, direction); // let pickedObjects = this.viewer.scene.drillPickFromRay(ray); // let result // for (let i = 0; i < pickedObjects.length; i++) { // if (pickedObjects[i].position) { // result = pickedObjects[i] // break // } // } // let color = Cesium.Color.LIME // if (result && Math.abs(result.position.x - pt3d.x) > 1 && Math.abs(result.position.y - pt3d.y) > 1 && Math.abs(result.position.z - pt3d.z) > 1) { // color = Cesium.Color.RED // // this.viewer.entities.add({ // // polyline: { // // positions: [viewPoint, result.position], // // material: Cesium.Color.GREEN.withAlpha(0.1), // // // clampToGround: true, // // width: 1, // // zIndex: 99999999 // // }, // // }); // // this.viewer.entities.add({ // // polyline: { // // positions: [result.position, targetPoint], // // material: Cesium.Color.RED.withAlpha(0.1), // // // clampToGround: true, // // width: 1, // // zIndex: 99999999 // // }, // // }); // // pointPrimitives.add({ // // position: result.position, // // color: Cesium.Color.AQUA.withAlpha(0.5), // // pixelSize: 6 // // }) // } // positionArr.push(pt[0] - xp, pt[1] + yp, pt[0] + xp, pt[1] + yp, pt[0] + xp, pt[1] - yp, pt[0] - xp, pt[1] - yp) // let polygon = new Cesium.PolygonGeometry({ // polygonHierarchy: new Cesium.PolygonHierarchy( // Cesium.Cartesian3.fromDegreesArray(positionArr) // ), // height: 0.0, // extrudedHeight: 0.0, // vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT, // ellipsoid: Cesium.Ellipsoid.WGS84, // granularity: Cesium.Math.RADIANS_PER_DEGREE, // 每个纬度和经度之间的距离(以弧度为单位),确定缓冲区中的位置数 // perPositionHeight: false, // 每个位置点使用的高度 // closeTop: true, // closeBottom: true, // }); // let polygonInstance = new Cesium.GeometryInstance({ // geometry: polygon, // name: "ViewershedPolygon", // attributes: { // color: Cesium.ColorGeometryInstanceAttribute.fromColor( // color.withAlpha(0.5) // ), // show: new Cesium.ShowGeometryInstanceAttribute(true), //显示或者隐藏 // }, // }); // instances.push(polygonInstance) // } // this.viewer.scene.primitives.add( // new Cesium.GroundPrimitive({ // geometryInstances: instances, // appearance: new Cesium.PerInstanceColorAppearance({ // translucent: true, //false时透明度无效 // closed: false, // }), // }) // ); } destroy() { for (let i = 0; i < this.primitives.length; i++) { this.viewer.scene.primitives.remove(this.primitives[i]) } this.primitives = [] this.viewpointPrimitive && this.viewer.scene.primitives.remove(this.viewpointPrimitive) YJ.Measure.SetMeasureStatus(false) } } export default ViewShedStage;