302 lines
12 KiB
JavaScript
302 lines
12 KiB
JavaScript
// 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; |