Files
sdk4.0_new/src/Obj/Analysis/ViewShed/index.js
2025-09-01 16:17:11 +08:00

773 lines
34 KiB
JavaScript

// ViewShed.js
import glsl from './glsl'
import glsl2 from './glsl2'
import Event from "../../../Event";
import MouseTip from "../../../MouseTip";
import Tools from "../../../Tools";
import EventBinding from '../../Element/Dialog/eventBinding';
import Controller from "../../../Controller";
import Dialog from '../../../BaseDialog';
import { html } from "./_element";
/**
* @constructor
* @description 可视域分析
* @param sdk
* @param {Object} options 选项。
* @param {Cesium.Cartesian3} options.viewPosition 观测点位置。
* @param {Cesium.Cartesian3} options.viewPositionEnd 最远观测点位置(如果设置了观测距离,这个属性可以不设置)。
* @param {Number} options.viewPointHeight=1.8 视点高度(单位`米`)。
* @param {Number} options.viewDistance 观测距离(单位`米`)。
* @param {Number} options.viewHeading 航向角(单位`度`)。
* @param {Number} options.viewPitch 俯仰角(单位`度`)。
* @param {Number} options.horizontalViewAngle=90 可视域水平夹角(单位`度`)。
* @param {Number} options.verticalViewAngle=60 可视域垂直夹角(单位`度`)。
* @param {String} options.visibleAreaColor=#008000 可视区域颜色(默认值`绿色`)。
* @param {String} options.invisibleAreaColor=#FF0000 不可视区域颜色(默认值`红色`)。
*/
class ViewShedStage extends Tools {
constructor(sdk, options = {}, _Dialog = {}) {
super(sdk, options)
// if (Object.hasOwn(options.viewPosition, 'lng') && Object.hasOwn(options.viewPosition, 'lat') && Object.hasOwn(options.viewPosition, 'alt')) {
// this.error = '请提供观测点位置!'
// window.ELEMENT && window.ELEMENT.Message({
// message: '请提供观测点位置!',
// type: 'warning',
// duration: 1500
// });
// return
// }
this.viewer = sdk.viewer;
this.options = {}
this.options.viewPosition = options.viewPosition;
this.options.viewPositionEnd = options.viewPositionEnd;
this.options.horizontalViewAngle = (options.horizontalViewAngle || options.horizontalViewAngle === 0) ? options.horizontalViewAngle : 90.0;
this.options.verticalViewAngle = (options.verticalViewAngle || options.verticalViewAngle === 0) ? options.verticalViewAngle : 60.0;
this.options.visibleAreaColor = options.visibleAreaColor || '#008000';
this.options.invisibleAreaColor = options.invisibleAreaColor || '#FF0000';
this._elms = {};
this.viewPointHeight = options.viewPointHeight
// this.enabled = (typeof options.enabled === "boolean") ? options.enabled : true;
// this.softShadows = (typeof options.softShadows === "boolean") ? options.softShadows : true;
// this.size = options.size || 10240; // 2048
this.ids = []
this.Dialog = _Dialog
this._EventBinding = new EventBinding()
this.html = null
YJ.Analysis.AnalysesResults.push(this)
ViewShedStage.edit(this)
// ViewShedStage.edit(this)
// this.update();
}
get viewPointHeight() {
return this.options.viewPointHeight
}
set viewPointHeight(v) {
let viewPointHeight = Math.floor(Number(v) * 10) / 10
if (isNaN(viewPointHeight)) {
viewPointHeight = 1.8
}
if (viewPointHeight < 0) {
viewPointHeight = 0
}
this.options.viewPointHeight = viewPointHeight
this._elms.viewPointHeight && this._elms.viewPointHeight.forEach((item) => {
item.value = viewPointHeight
})
}
get viewPosition() {
return this.options.viewPosition
}
set viewPosition(v) {
this.options.viewPosition = v
this.ids[0] && (this.viewer.entities.getById(this.ids[0]).position = new Cesium.Cartesian3.fromDegrees(v.lng, v.lat, v.alt))
this.update()
// let viewPosition3 = Cesium.Cartesian3.fromDegrees(this.options.viewPosition.lng, this.options.viewPosition.lat, this.options.viewPosition.alt)
}
get viewPositionEnd() {
return this.options.viewPositionEnd
}
set viewPositionEnd(v) {
this.options.viewPositionEnd = v
this.ids[1] && (this.viewer.entities.getById(this.ids[1]).position = new Cesium.Cartesian3.fromDegrees(v.lng, v.lat, v.alt))
this.update()
// let viewPositionEnd3 = Cesium.Cartesian3.fromDegrees(this.options.viewPositionEnd.lng, this.options.viewPositionEnd.lat, this.options.viewPositionEnd.alt)
// this.viewDistance = this.viewPositionEnd ? Cesium.Cartesian3.distance(this.viewPosition, this.viewPositionEnd) : (options.viewDistance || 100.0);
}
get horizontalViewAngle() {
return this.options.horizontalViewAngle
}
set horizontalViewAngle(v) {
this.options.horizontalViewAngle = v
if (this._DialogObject && this._DialogObject._element && this._DialogObject._element.content) {
let contentElm = this._DialogObject._element.content
let e_horizontalViewAngle = contentElm.querySelector("input[name='horizontalViewAngle']")
e_horizontalViewAngle.value = v
let rangeNodeActive = contentElm.getElementsByClassName('range-node-active')[0]
let rangeNodeActiveText = rangeNodeActive.getElementsByClassName('range-node-active-text')[0]
rangeNodeActiveText.innerHTML = v + '°';
let rangeProcess = contentElm.getElementsByClassName('range-process')[0]
rangeProcess.style.width = v / 180 * 100 + '%'
}
this.update()
}
get visibleAreaColor() {
return this.options.visibleAreaColor
}
set visibleAreaColor(v) {
this.options.visibleAreaColor = v
this.update()
}
get invisibleAreaColor() {
return this.options.invisibleAreaColor
}
set invisibleAreaColor(v) {
this.options.invisibleAreaColor = v
this.update()
}
get verticalViewAngle() {
return this.options.verticalViewAngle
}
set verticalViewAngle(v) {
this.options.verticalViewAngle = v
this.update()
}
get viewDistance() {
let viewPosition3 = Cesium.Cartesian3.fromDegrees(this.options.viewPosition.lng, this.options.viewPosition.lat, this.options.viewPosition.alt + this.viewPointHeight)
let viewPositionEnd3 = Cesium.Cartesian3.fromDegrees(this.options.viewPositionEnd.lng, this.options.viewPositionEnd.lat, this.options.viewPositionEnd.alt)
let distance = Cesium.Cartesian3.distance(viewPosition3, viewPositionEnd3)
return distance
}
get viewHeading() {
let viewPosition3 = Cesium.Cartesian3.fromDegrees(this.options.viewPosition.lng, this.options.viewPosition.lat, this.options.viewPosition.alt + this.viewPointHeight)
let viewPositionEnd3 = Cesium.Cartesian3.fromDegrees(this.options.viewPositionEnd.lng, this.options.viewPositionEnd.lat, this.options.viewPositionEnd.alt)
let heading = getHeading(viewPosition3, viewPositionEnd3)
return heading
}
get viewPitch() {
let viewPosition3 = Cesium.Cartesian3.fromDegrees(this.options.viewPosition.lng, this.options.viewPosition.lat, this.options.viewPosition.alt + this.viewPointHeight)
let viewPositionEnd3 = Cesium.Cartesian3.fromDegrees(this.options.viewPositionEnd.lng, this.options.viewPositionEnd.lat, this.options.viewPositionEnd.alt)
let pitch = getPitch(viewPosition3, viewPositionEnd3)
return pitch
}
static create(that) {
that.destroy()
let count = 0;
if (!YJ.Measure.GetMeasureStatus()) {
that.event = new Event(that.sdk)
that.tip = new MouseTip('左键选择观测点位置,右键取消', that.sdk)
YJ.Measure.SetMeasureStatus(true)
that.event.mouse_left((movement, cartesian) => {
if (!that.viewPosition) {
that.options.viewPosition = that.cartesian3Towgs84(cartesian, that.viewer)
that.ids.push(ViewShedStage.create_point(that, cartesian))
that.tip.set_text("左键选择最远观测点位置,右键取消")
}
count++
if (count === 2) {
that.options.viewPositionEnd = that.cartesian3Towgs84(cartesian, that.viewer)
that.ids.push(ViewShedStage.create_point(that, cartesian))
end()
that.update()
}
})
that.event.mouse_move((movement, cartesian) => {
that.tip.setPosition(cartesian, movement.endPosition.x, movement.endPosition.y)
})
that.event.mouse_right((movement, cartesian) => {
that.ids.forEach(id => {
that.viewer.entities.removeById(id)
})
that.ids = []
end()
})
that.event.gesture_pinck_start((movement, cartesian) => {
let startTime = new Date()
that.event.gesture_pinck_end(() => {
let endTime = new Date()
if (endTime - startTime >= 500) {
that.ids.forEach(id => {
that.viewer.entities.removeById(id)
})
that.ids = []
end()
}
})
})
}
else {
console.log('上一次测量未结束')
}
function end() {
that.ids.forEach(id => {
let entity = that.viewer.entities.getById(id)
entity.show = false
})
YJ.Measure.SetMeasureStatus(false)
that.tip.destroy()
that.event.destroy()
that.tip = null
that.event = null
}
}
static create_point(that, cartesian) {
let id = that.randomString()
let p = that.cartesian3Towgs84(cartesian, that.viewer)
let params = {
id: id,
position: Cesium.Cartesian3.fromDegrees(p.lng, p.lat, p.alt),
billboard: {
image: that.getSourceRootPath() + '/img/point.png',
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
color: Cesium.Color.WHITE.withAlpha(0.99)
}
}
that.viewer.entities.add(
new Cesium.Entity(params)
)
return id
}
add() {
this.createLightCamera();
this.createShadowMap();
this.createPostStage();
// this.drawFrustumOutline();
this.drawSketch();
ViewShedStage.getcanvas(this)
}
update() {
this.clear();
this.add();
}
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)
that.editevent && that.editevent.destroy()
that.ControllerObject && that.ControllerObject.destroy()
that.ids.forEach(id => {
that.viewer.entities.removeById(id)
})
},
})
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)
let resetBtn = that._DialogObject._element.body.getElementsByClassName('edit')[0];
resetBtn.addEventListener('click', () => {
that.nodeEdit()
})
let drawElm = document.createElement('button')
drawElm.innerHTML = '绘制'
drawElm.addEventListener('click', () => {
ViewShedStage.create(that)
})
that._DialogObject.footAppChild(drawElm)
that.html = contentElm
let all_elm = contentElm.getElementsByTagName("*")
that._EventBinding.on(that, all_elm)
that._elms = that._EventBinding.element
// //经度值
// let e_lng = contentElm.querySelector("span[name='lng']")
// e_lng.innerHTML = Number(that.options.viewPosition.lng.toFixed(8))
// //纬度值
// let e_lat = contentElm.querySelector("span[name='lat']")
// e_lat.innerHTML = Number(that.options.viewPosition.lat.toFixed(8))
// //高度值
// let e_alt = contentElm.querySelector("span[name='alt']")
// e_alt.innerHTML = Number(that.options.viewPosition.alt.toFixed(8))
// //偏航角
// let e_viewHeading = contentElm.querySelector("span[name='viewHeading']")
// e_viewHeading.innerHTML = Number(that.viewHeading.toFixed(8))
// //俯仰角
// let e_viewPitch = contentElm.querySelector("span[name='viewPitch']")
// e_viewPitch.innerHTML = Number(that.viewPitch.toFixed(8))
//视域夹角
let e_horizontalViewAngle = contentElm.querySelector("input[name='horizontalViewAngle']")
e_horizontalViewAngle.value = that.options.horizontalViewAngle
let rangeNodeActive = contentElm.getElementsByClassName('range-node-active')[0]
let rangeNodeActiveText = rangeNodeActive.getElementsByClassName('range-node-active-text')[0]
let rangeProcess = contentElm.getElementsByClassName('range-process')[0]
let percentage = that.horizontalViewAngle / 180 * 100
rangeNodeActive.style.left = percentage + '%';
rangeProcess.style.width = percentage + '%'
rangeNodeActiveText.innerHTML = that.horizontalViewAngle + '°';
let timeout
e_horizontalViewAngle.addEventListener('input', () => {
let percentage = e_horizontalViewAngle.value / 180 * 100
rangeNodeActive.style.left = percentage + '%';
rangeProcess.style.width = percentage + '%';
rangeNodeActiveText.innerHTML = e_horizontalViewAngle.value + '°';
})
e_horizontalViewAngle.addEventListener('change', () => {
clearTimeout(timeout)
timeout = setTimeout(() => {
that.horizontalViewAngle = e_horizontalViewAngle.value;
}, 300);
});
}
static getcanvas(that) {
if (!that.viewPosition) {
return
}
if (that.viewBillboardPrimitive) {
that.viewer.scene.primitives.remove(that.viewBillboardPrimitive)
that.viewBillboardPrimitive = null
}
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d')
canvas.width = 220
canvas.height = 180
canvas.style.background = "#000000"
let img = new Image();
const data = [
{
images: that.getSourceRootPath() + '/img/bubble/lng.png',
text: '经度:' + parseFloat(that.viewPosition.lng.toFixed(10)) + '°'
},
{
images: that.getSourceRootPath() + '/img/bubble/lat.png',
text: '纬度:' + parseFloat(that.viewPosition.lat.toFixed(10)) + '°'
},
{
images: that.getSourceRootPath() + '/img/bubble/h.png',
text: '高度:' + Number(((parseFloat(that.viewPosition.alt.toFixed(2)) + Number(that.viewPointHeight))).toFixed(2)) + ' m'
},
{
images: that.getSourceRootPath() + '/img/bubble/heading.png',
text: '偏航角:' + parseFloat(that.viewHeading.toFixed(10)) + '°'
},
{
images: that.getSourceRootPath() + '/img/bubble/pitch.png',
text: '俯仰角:' + parseFloat(that.viewPitch.toFixed(10)) + '°'
}
]
img.src = that.getSourceRootPath() + '/img/bubble/bubble.png';
let imagesLoaded = 0
img.onload = () => {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
data.forEach((item, index) => {
const img = new Image();
img.src = item.images;
img.onload = () => {
ctx.drawImage(img, 12, 12 + (index * 26));
ctx.fillStyle = "#fff";
ctx.font = "12px Arial";
ctx.fillText(item.text, 44, 28 + (index * 26));
imagesLoaded++;
if (imagesLoaded === data.length) {
that.viewBillboardPrimitive = that.viewer.scene.primitives.add(new Cesium.BillboardCollection())
that.viewBillboardPrimitive.add({
position: Cesium.Cartesian3.fromDegrees(that.viewPosition.lng, that.viewPosition.lat, that.viewPosition.alt + that.viewPointHeight),
image: canvas,
width: 200,
height: 180,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
})
}
};
})
};
}
clear() {
YJ.Measure.SetMeasureStatus(false)
this.tip && this.tip.destroy()
this.event && this.event.destroy()
this.tip = null
this.event = null
if (this.sketch) {
this.viewer.entities.removeById(this.sketch.id);
this.sketch = null;
}
if (this.frustumOutline) {
// this.frustumOutline.destroy();
this.viewer.entities.removeById(this.frustumOutline.id);
this.frustumOutline = null;
}
if (this.postStage) {
this.viewer.scene.postProcessStages.remove(this.postStage);
this.postStage = null;
}
}
destroy() {
this.clear()
this.editevent && this.editevent.destroy()
this.ControllerObject && this.ControllerObject.destroy()
this.ids.forEach(id => {
this.viewer.entities.removeById(id)
})
this.ids = []
if (this.viewBillboardPrimitive) {
this.viewer.scene.primitives.remove(this.viewBillboardPrimitive)
}
this.viewBillboardPrimitive = null
this.options.viewPosition = null
this.options.viewPositionEnd = null
YJ.Measure.SetMeasureStatus(false)
if (this._originalShadowMap) {
this.viewer.scene.shadowMap = this._originalShadowMap
this._originalShadowMap = null
}
this.viewer.shadows = this.viewer._shadows
}
nodeEdit() {
if (YJ.Measure.GetMeasureStatus()) {
console.log('上一次测量未结束')
}
else {
this.editevent && this.editevent.destroy()
this.ids.forEach(id => {
let entity = this.viewer.entities.getById(id)
entity.show = true
})
let selectPoint
YJ.Measure.SetMeasureStatus(true)
// this.tip = new MouseTip('左键选择要操作的观测点,右键取消', this.sdk)
this.editevent = new Event(this.sdk)
this.editevent.mouse_left((movement, cartesian) => {
let pick = this.viewer.scene.pick(movement.position);
if (pick && pick.id && pick.id.id && this.ids.indexOf(pick.id.id) != -1 && (!selectPoint || selectPoint.id != pick.id.id)) {
selectPoint = pick.id
// this.event.destroy()
// this.tip.destroy()
this.viewer.entities.getById(this.ids[0]).position = new Cesium.Cartesian3.fromDegrees(this.viewPosition.lng, this.viewPosition.lat, this.viewPosition.alt)
this.viewer.entities.getById(this.ids[1]).position = new Cesium.Cartesian3.fromDegrees(this.viewPositionEnd.lng, this.viewPositionEnd.lat, this.viewPositionEnd.alt)
this.ControllerObject && this.ControllerObject.destroy()
this.ControllerObject = new Controller(this.sdk, { position: { ...this.cartesian3Towgs84(selectPoint.position._value, this.sdk.viewer) } })
this.ControllerObject.controllerCallBack = (params, status) => {
if (params.position.alt < 0) {
params.position.alt = 0
}
selectPoint.position = new Cesium.Cartesian3.fromDegrees(params.position.lng, params.position.lat, params.position.alt)
if (status) {
if (this.ids.indexOf(pick.id.id) == 0) {
this.viewPosition = params.position
}
else {
this.viewPositionEnd = params.position
}
YJ.Measure.SetMeasureStatus(true)
}
}
this.ControllerObject.editTranslational()
}
})
this.editevent.mouse_right((movement, cartesian) => {
YJ.Measure.SetMeasureStatus(false)
this.editevent && this.editevent.destroy()
this.ControllerObject && this.ControllerObject.destroy()
this.ids.forEach(id => {
let entity = this.viewer.entities.getById(id)
entity.show = false
})
selectPoint = null
})
this.editevent.mouse_move((movement, cartesian) => {
// this.tip.setPosition(
// cartesian,
// movement.endPosition.x,
// movement.endPosition.y
// )
})
this.editevent.gesture_pinck_start((movement, cartesian) => {
let startTime = new Date()
this.editevent.gesture_pinck_end(() => {
let endTime = new Date()
if (endTime - startTime >= 500) {
YJ.Measure.SetMeasureStatus(false)
this.editevent && this.editevent.destroy()
this.ControllerObject && this.ControllerObject.destroy()
this.ids.forEach(id => {
let entity = this.viewer.entities.getById(id)
entity.show = false
})
selectPoint = null
}
})
})
}
}
createLightCamera() {
if (!this.options.viewPosition) {
return
}
let _this = this
this.lightCamera = new Cesium.Camera(this.viewer.scene);
this.lightCamera.position = Cesium.Cartesian3.fromDegrees(this.options.viewPosition.lng, this.options.viewPosition.lat, this.options.viewPosition.alt + this.viewPointHeight);
// if (this.viewPositionEnd) {
// let direction = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(this.viewPositionEnd, this.viewPosition, new Cesium.Cartesian3()), new Cesium.Cartesian3());
// this.lightCamera.direction = direction; // direction是相机面向的方向
// }
this.lightCamera.frustum.near = this.viewDistance * 0.001;
this.lightCamera.frustum.far = this.viewDistance;
const hr = Cesium.Math.toRadians(this.horizontalViewAngle);
const vr = Cesium.Math.toRadians(this.verticalViewAngle);
const aspectRatio =
(this.viewDistance * Math.tan(hr / 2) * 2) /
(this.viewDistance * Math.tan(vr / 2) * 2);
this.lightCamera.frustum.aspectRatio = aspectRatio;
if (hr > vr) {
this.lightCamera.frustum.fov = hr;
} else {
this.lightCamera.frustum.fov = vr;
}
this.lightCamera.setView({
destination: Cesium.Cartesian3.fromDegrees(this.options.viewPosition.lng, this.options.viewPosition.lat, this.options.viewPosition.alt + this.viewPointHeight),
orientation: {
heading: Cesium.Math.toRadians(this.viewHeading || 0),
pitch: Cesium.Math.toRadians(this.viewPitch || 0),
roll: 0
}
});
}
createShadowMap() {
this.shadowMap = new Cesium.ShadowMap({
context: (this.viewer.scene).context,
lightCamera: this.lightCamera,
enabled: true,
isPointLight: true,
pointLightRadius: this.viewDistance,
cascadesEnabled: false,
size: 2048, // 2048
softShadows: true,
normalOffset: false,
fromLightSource: false
});
if (!this._originalShadowMap) {
this._originalShadowMap = this.viewer.scene.shadowMap
}
this.viewer.scene.shadowMap = this.shadowMap;
// setTimeout(() => {
// this.viewer.shadows = this.viewer._shadows
// }, 0);
}
createPostStage() {
const fs = glsl
if (Number(Cesium.VERSION.split('.')[1]) >= 102) {
fs = glsl2
}
const postStage = new Cesium.PostProcessStage({
fragmentShader: fs,
uniforms: {
shadowMap_textureCube: () => {
this.shadowMap.update(Reflect.get(this.viewer.scene, "_frameState"));
return Reflect.get(this.shadowMap, "_shadowMapTexture");
},
shadowMap_matrix: () => {
this.shadowMap.update(Reflect.get(this.viewer.scene, "_frameState"));
return Reflect.get(this.shadowMap, "_shadowMapMatrix");
},
shadowMap_lightPositionEC: () => {
this.shadowMap.update(Reflect.get(this.viewer.scene, "_frameState"));
return Reflect.get(this.shadowMap, "_lightPositionEC");
},
shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness: () => {
this.shadowMap.update(Reflect.get(this.viewer.scene, "_frameState"));
const bias = this.shadowMap._pointBias;
return Cesium.Cartesian4.fromElements(
bias.normalOffsetScale,
this.shadowMap._distance,
this.shadowMap.maximumDistance,
0.0,
new Cesium.Cartesian4()
);
},
shadowMap_texelSizeDepthBiasAndNormalShadingSmooth: () => {
this.shadowMap.update(Reflect.get(this.viewer.scene, "_frameState"));
const bias = this.shadowMap._pointBias;
const scratchTexelStepSize = new Cesium.Cartesian2();
const texelStepSize = scratchTexelStepSize;
texelStepSize.x = 1.0 / this.shadowMap._textureSize.x;
texelStepSize.y = 1.0 / this.shadowMap._textureSize.y;
return Cesium.Cartesian4.fromElements(
texelStepSize.x,
texelStepSize.y,
bias.depthBias,
bias.normalShadingSmooth,
new Cesium.Cartesian4()
);
},
camera_projection_matrix: this.lightCamera.frustum.projectionMatrix,
camera_view_matrix: this.lightCamera.viewMatrix,
helsing_viewDistance: () => {
return this.viewDistance;
},
helsing_visibleAreaColor: Cesium.Color.fromCssColorString(this.visibleAreaColor),
helsing_invisibleAreaColor: Cesium.Color.fromCssColorString(this.invisibleAreaColor),
}
});
this.postStage = this.viewer.scene.postProcessStages.add(postStage);
}
drawFrustumOutline() {
const scratchRight = new Cesium.Cartesian3();
const scratchRotation = new Cesium.Matrix3();
const scratchOrientation = new Cesium.Quaternion();
const position = this.lightCamera.positionWC;
const direction = this.lightCamera.directionWC;
const up = this.lightCamera.upWC;
let right = this.lightCamera.rightWC;
right = Cesium.Cartesian3.negate(right, scratchRight);
let rotation = scratchRotation;
Cesium.Matrix3.setColumn(rotation, 0, right, rotation);
Cesium.Matrix3.setColumn(rotation, 1, up, rotation);
Cesium.Matrix3.setColumn(rotation, 2, direction, rotation);
let orientation = Cesium.Quaternion.fromRotationMatrix(rotation, scratchOrientation);
let instance = new Cesium.GeometryInstance({
geometry: new Cesium.FrustumOutlineGeometry({
frustum: this.lightCamera.frustum,
origin: Cesium.Cartesian3.fromDegrees(this.options.viewPosition.lng, this.options.viewPosition.lat, this.options.viewPosition.alt + this.viewPointHeight),
orientation: orientation
}),
id: Math.random().toString(36).substr(2),
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
Cesium.Color.YELLOWGREEN//new Cesium.Color(0.0, 1.0, 0.0, 1.0)
),
show: new Cesium.ShowGeometryInstanceAttribute(true)
}
});
this.frustumOutline = this.viewer.scene.primitives.add(
new Cesium.Primitive({
geometryInstances: [instance],
appearance: new Cesium.PerInstanceColorAppearance({
flat: true,
translucent: false
})
})
);
}
drawSketch() {
this.sketch = this.viewer.entities.add({
name: 'sketch',
position: Cesium.Cartesian3.fromDegrees(this.options.viewPosition.lng, this.options.viewPosition.lat, this.options.viewPosition.alt + this.viewPointHeight),
orientation: Cesium.Transforms.headingPitchRollQuaternion(
Cesium.Cartesian3.fromDegrees(this.options.viewPosition.lng, this.options.viewPosition.lat, this.options.viewPosition.alt + this.viewPointHeight),
Cesium.HeadingPitchRoll.fromDegrees(this.viewHeading - 90, this.viewPitch, 0.0)
),
ellipsoid: {
radii: new Cesium.Cartesian3(
this.viewDistance,
this.viewDistance,
this.viewDistance
),
// innerRadii: new Cesium.Cartesian3(2.0, 2.0, 2.0),
minimumClock: Cesium.Math.toRadians(-this.horizontalViewAngle / 2),
maximumClock: Cesium.Math.toRadians(this.horizontalViewAngle / 2),
minimumCone: Cesium.Math.toRadians(90 - (this.verticalViewAngle / 2)),
maximumCone: Cesium.Math.toRadians(90 + (this.verticalViewAngle / 2)),
fill: false,
outline: true,
subdivisions: 256,
stackPartitions: 64,
slicePartitions: 64,
outlineColor: Cesium.Color.YELLOWGREEN
}
});
this.frustumOutline = this.viewer.entities.add({
name: 'sketch',
position: Cesium.Cartesian3.fromDegrees(this.options.viewPosition.lng, this.options.viewPosition.lat, this.options.viewPosition.alt + this.viewPointHeight),
orientation: Cesium.Transforms.headingPitchRollQuaternion(
Cesium.Cartesian3.fromDegrees(this.options.viewPosition.lng, this.options.viewPosition.lat, this.options.viewPosition.alt + this.viewPointHeight),
Cesium.HeadingPitchRoll.fromDegrees(this.viewHeading - 90, this.viewPitch, 0.0)
),
ellipsoid: {
radii: new Cesium.Cartesian3(
this.viewDistance,
this.viewDistance,
this.viewDistance
),
innerRadii: new Cesium.Cartesian3(0.0001, 0.0001, 0.0001),
minimumClock: Cesium.Math.toRadians(-this.horizontalViewAngle / 2),
maximumClock: Cesium.Math.toRadians(this.horizontalViewAngle / 2),
minimumCone: Cesium.Math.toRadians(90 - (this.verticalViewAngle / 2)),
maximumCone: Cesium.Math.toRadians(90 + (this.verticalViewAngle / 2)),
fill: false,
outline: true,
subdivisions: 256,
stackPartitions: 1,
slicePartitions: 1,
outlineColor: Cesium.Color.YELLOWGREEN
}
});
}
}
function getHeading(fromPosition, toPosition) {
let finalPosition = new Cesium.Cartesian3();
let matrix4 = Cesium.Transforms.eastNorthUpToFixedFrame(fromPosition);
Cesium.Matrix4.inverse(matrix4, matrix4);
Cesium.Matrix4.multiplyByPoint(matrix4, toPosition, finalPosition);
Cesium.Cartesian3.normalize(finalPosition, finalPosition);
return Cesium.Math.toDegrees(Math.atan2(finalPosition.x, finalPosition.y));
}
function getPitch(fromPosition, toPosition) {
let finalPosition = new Cesium.Cartesian3();
let matrix4 = Cesium.Transforms.eastNorthUpToFixedFrame(fromPosition);
Cesium.Matrix4.inverse(matrix4, matrix4);
Cesium.Matrix4.multiplyByPoint(matrix4, toPosition, finalPosition);
Cesium.Cartesian3.normalize(finalPosition, finalPosition);
return Cesium.Math.toDegrees(Math.asin(finalPosition.z));
}
export default ViewShedStage;