2025-07-03 13:54:01 +08:00
// 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 { Cesium . Cartesian3 } options . viewPosition 观测点位置 。
* @ param { Cesium . Cartesian3 } options . viewPositionEnd 最远观测点位置 ( 如果设置了观测距离 , 这个属性可以不设置 ) 。
* @ 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.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 . html = null
2025-07-03 18:18:08 +08:00
YJ . Analysis . AnalysesResults . push ( this )
2025-07-03 13:54:01 +08:00
ViewShedStage . create ( this )
// ViewShedStage.edit(this)
// this.update();
}
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 )
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 )
let viewPositionEnd3 = Cesium . Cartesian3 . fromDegrees ( this . options . viewPositionEnd . lng , this . options . viewPositionEnd . lat , this . options . viewPositionEnd . alt )
let heading = getHeading ( viewPosition3 , viewPositionEnd3 )
if ( this . html ) {
let e _viewHeading = this . html . querySelector ( "span[name='viewHeading']" )
e _viewHeading . innerHTML = Number ( heading . toFixed ( 8 ) )
}
return heading
}
get viewPitch ( ) {
let viewPosition3 = Cesium . Cartesian3 . fromDegrees ( this . options . viewPosition . lng , this . options . viewPosition . lat , this . options . viewPosition . alt )
let viewPositionEnd3 = Cesium . Cartesian3 . fromDegrees ( this . options . viewPositionEnd . lng , this . options . viewPositionEnd . lat , this . options . viewPositionEnd . alt )
let pitch = getPitch ( viewPosition3 , viewPositionEnd3 )
if ( this . html ) {
let e _viewPitch = this . html . querySelector ( "span[name='viewPitch']" )
e _viewPitch . innerHTML = Number ( pitch . toFixed ( 8 ) )
}
return pitch
}
static create ( that ) {
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
if ( count === 2 ) {
ViewShedStage . edit ( that )
}
}
}
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 ( ) ;
}
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 ( )
} )
that . html = contentElm
//经度值
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 ) ;
} ) ;
}
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 . frustumOutline = null ;
}
if ( this . FrustumBottomSurface ) {
this . FrustumBottomSurface . destroy ( ) ;
this . FrustumBottomSurface = 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 )
} )
YJ . Measure . SetMeasureStatus ( false )
}
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 . viewPosition
this . ControllerObject && this . ControllerObject . destroy ( )
console . log ( this . cartesian3Towgs84 ( selectPoint . position . _value , this . sdk . viewer ) )
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 ( ) {
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 ) ;
// 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 ) ,
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
} ) ;
this . viewer . scene . shadowMap = this . shadowMap ;
}
createPostStage ( ) {
const fs = glsl
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 ) ,
shadowMap : this . shadowMap ,
far : ( ) => {
return this . viewDistance ;
} ,
}
} ) ;
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 ) ,
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 )
}
} ) ;
let frustum = this . lightCamera . frustum . clone ( )
frustum . near = frustum . far - 100
let instance2 = new Cesium . GeometryInstance ( {
geometry : new Cesium . FrustumGeometry ( {
frustum : frustum ,
origin : Cesium . Cartesian3 . fromDegrees ( this . options . viewPosition . lng , this . options . viewPosition . lat , this . options . viewPosition . alt ) ,
orientation : orientation ,
vertexFormat : Cesium . VertexFormat . POSITION _ONLY ,
} ) ,
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
} )
} )
) ;
const radius = this . viewDistance ;
const angle = this . viewHeading ;
let Ea = 6378137 ; // 赤道半径
let Eb = 6356725 ; // 极半径
const lng = this . options . viewPosition . lng ,
lat = this . options . viewPosition . lat ;
let positionArr = [ ] ;
let boundaryPoints = [ ] ;
positionArr . push ( lng , lat ) ;
boundaryPoints . push ( [ lng , lat ] ) ;
//正北是0°
let start = angle + 45 > 360 ? angle - 45 - 360 : angle - 45 ;
let end = start + 90 ;
for ( let i = start ; i <= end ; i ++ ) {
let dx = radius * Math . sin ( ( i * Math . PI ) / 180.0 ) ;
let dy = radius * Math . cos ( ( i * Math . PI ) / 180.0 ) ;
let ec = Eb + ( ( Ea - Eb ) * ( 90.0 - lat ) ) / 90.0 ;
let ed = ec * Math . cos ( ( lat * Math . PI ) / 180 ) ;
let BJD = lng + ( ( dx / ed ) * 180.0 ) / Math . PI ;
let BWD = lat + ( ( dy / ec ) * 180.0 ) / Math . PI ;
positionArr . push ( BJD , BWD ) ;
}
let polygon = new Cesium . PolygonGeometry ( {
polygonHierarchy : new Cesium . PolygonHierarchy (
Cesium . Cartesian3 . fromDegreesArray ( positionArr )
) ,
height : 0.0 ,
extrudedHeight : 0.0 ,
vertexFormat : Cesium . PerInstanceColorAppearance . VERTEX _FORMAT ,
stRotation : 0.0 , // 纹理的旋转坐标(以弧度为单位),正旋转是逆时针方向
ellipsoid : Cesium . Ellipsoid . WGS84 ,
granularity : Cesium . Math . RADIANS _PER _DEGREE , // 每个纬度和经度之间的距离(以弧度为单位),确定缓冲区中的位置数
perPositionHeight : false , // 每个位置点使用的高度
closeTop : true ,
closeBottom : true ,
// NONE 与椭圆表面不符的直线;GEODESIC 遵循测地路径;RHUMB 遵循大黄蜂或恶魔般的道路。
arcType : Cesium . ArcType . GEODESIC , // 多边形边缘线型
} ) ;
let polygonInstance = new Cesium . GeometryInstance ( {
geometry : polygon ,
name : "ViewershedPolygon" ,
attributes : {
color : Cesium . ColorGeometryInstanceAttribute . fromColor (
Cesium . Color . BLUE
) ,
show : new Cesium . ShowGeometryInstanceAttribute ( true ) , //显示或者隐藏
} ,
} ) ;
// this.FrustumBottomSurface = this.viewer.scene.primitives.add(
// new Cesium.GroundPrimitive({
// geometryInstances: polygonInstance,
// appearance: new Cesium.PerInstanceColorAppearance({
// translucent: true, //false时透明度无效
// closed: 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 ) ,
orientation : Cesium . Transforms . headingPitchRollQuaternion (
Cesium . Cartesian3 . fromDegrees ( this . options . viewPosition . lng , this . options . viewPosition . lat , this . options . viewPosition . alt ) ,
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 ( this . verticalViewAngle + 7.75 ) ,
maximumCone : Cesium . Math . toRadians ( 180 - this . verticalViewAngle - 7.75 ) ,
fill : false ,
outline : true ,
subdivisions : 256 ,
stackPartitions : 64 ,
slicePartitions : 64 ,
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 ;