代码迁移
This commit is contained in:
89
src/Obj/AirLine/DrawTakeOff.js
Normal file
89
src/Obj/AirLine/DrawTakeOff.js
Normal file
@ -0,0 +1,89 @@
|
||||
import MouseTip from '../../MouseTip/index'
|
||||
import MouseEvent from '../../Event/index'
|
||||
import Draw from '../../Draw/draw'
|
||||
|
||||
class DrawTakeOff extends Draw {
|
||||
/**
|
||||
* @constructor
|
||||
* @desc 获取坐标点
|
||||
* */
|
||||
constructor(sdk, options = {}) {
|
||||
super(sdk, options)
|
||||
this.options.tipText = options.tipText
|
||||
? options.tipText
|
||||
: '左键确定,右键结束;'
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 开始动态获取坐标点
|
||||
* @method start
|
||||
* @param cb {function} 回调函数
|
||||
* @memberOf DrawPoint
|
||||
* @example draw.start((err,position)=>{
|
||||
*
|
||||
* })
|
||||
* */
|
||||
|
||||
start(cb) {
|
||||
// eslint-disable-next-line no-undef
|
||||
if (YJ.Measure.GetMeasureStatus()) {
|
||||
cb('上一次测量未结束')
|
||||
} else {
|
||||
let car = undefined
|
||||
// eslint-disable-next-line no-undef
|
||||
YJ.Measure.SetMeasureStatus(true)
|
||||
// this.options
|
||||
this.tip = new MouseTip(this.options.tipText, this.sdk)
|
||||
this.event = new MouseEvent(this.sdk)
|
||||
this.isEntity = false
|
||||
this.event.mouse_left((movement, cartesian) => {
|
||||
this.end()
|
||||
let p = this.cartesian3Towgs84(car || cartesian, this.viewer)
|
||||
var pickedObject = this.viewer.scene.pick(movement.position)
|
||||
if (
|
||||
Cesium.defined(pickedObject) &&
|
||||
Cesium.defined(pickedObject.id) &&
|
||||
pickedObject.id.id === window.airportEntity.options.id
|
||||
) {
|
||||
this.isEntity = true
|
||||
}
|
||||
cb(null, p, this.isEntity)
|
||||
})
|
||||
this.event.mouse_right((movement, cartesian) => {
|
||||
this.end()
|
||||
cb(false)
|
||||
})
|
||||
this.event.mouse_move((movement, cartesian) => {
|
||||
car = cartesian
|
||||
this.tip.setPosition(
|
||||
cartesian,
|
||||
movement.endPosition.x,
|
||||
movement.endPosition.y
|
||||
)
|
||||
})
|
||||
|
||||
this.event.gesture_pinck_start((movement, cartesian) => {
|
||||
let startTime = new Date()
|
||||
this.event.gesture_pinck_end(() => {
|
||||
let endTime = new Date()
|
||||
if (endTime - startTime >= 500) {
|
||||
this.end()
|
||||
cb(false)
|
||||
} else {
|
||||
this.end()
|
||||
let p = this.cartesian3Towgs84(car || cartesian, this.viewer)
|
||||
cb(null, p)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
end() {
|
||||
YJ.Measure.SetMeasureStatus(false)
|
||||
this.event.destroy()
|
||||
this.tip.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
export default DrawTakeOff
|
112
src/Obj/AirLine/GenerateRoute.js
Normal file
112
src/Obj/AirLine/GenerateRoute.js
Normal file
@ -0,0 +1,112 @@
|
||||
// 根据米生成航线
|
||||
function flyLine(earth, positions, unit) {
|
||||
let arr = []
|
||||
positions.forEach(item => {
|
||||
arr.push([item.lng, item.lat])
|
||||
})
|
||||
arr.push(arr[0])
|
||||
// eslint-disable-next-line no-undef
|
||||
const turfPolygon = turf.polygon([arr])
|
||||
// 获取四至
|
||||
// eslint-disable-next-line no-undef
|
||||
const turfExtent = turf.bbox(turfPolygon)
|
||||
// 在turfPolygon中按网格取样点,网格间距3米
|
||||
// eslint-disable-next-line no-undef
|
||||
const turfSamplePoints = turf.pointGrid(turfExtent, unit / 1000, {
|
||||
units: 'kilometers',
|
||||
mask: turfPolygon
|
||||
})
|
||||
// 将turf取样点转为Cesium的取样点
|
||||
const cesiumSamplePoints = []
|
||||
for (let i = 0; i < turfSamplePoints.features.length; i++) {
|
||||
const coord = turfSamplePoints.features[i].geometry.coordinates
|
||||
cesiumSamplePoints.push([coord[0], coord[1]])
|
||||
}
|
||||
// 计算两点的距离
|
||||
function fromTo(point1, point2) {
|
||||
if (!point2) {
|
||||
return
|
||||
}
|
||||
// eslint-disable-next-line no-undef
|
||||
let from = turf.point(point1)
|
||||
// eslint-disable-next-line no-undef
|
||||
let to = turf.point(point2)
|
||||
// eslint-disable-next-line no-undef
|
||||
return Math.round(turf.distance(from, to) * 1000)
|
||||
}
|
||||
// 进行分组并进行奇数反转
|
||||
let polylinePosition = []
|
||||
let flag = 0
|
||||
let index = -1
|
||||
for (let i = 0; i < cesiumSamplePoints.length; i++) {
|
||||
if (fromTo(cesiumSamplePoints[i], cesiumSamplePoints[i + 1]) > unit) {
|
||||
index++
|
||||
let arr = cesiumSamplePoints.slice(flag, i + 1)
|
||||
if (index % 2 !== 0) {
|
||||
arr.reverse()
|
||||
}
|
||||
polylinePosition.push(arr)
|
||||
flag = i + 1
|
||||
}
|
||||
}
|
||||
let arr2 = cesiumSamplePoints.slice(flag, cesiumSamplePoints.length)
|
||||
if ((index + 1) % 2 !== 0) {
|
||||
arr2.reverse()
|
||||
}
|
||||
polylinePosition.push(arr2)
|
||||
return polylinePosition.flat()
|
||||
}
|
||||
// 获取高程
|
||||
function sampleHeightMostDetailed(earth, positions) {
|
||||
return earth.viewer.scene.sampleHeightMostDetailed([
|
||||
new Cesium.Cartographic.fromDegrees(positions[0], positions[1])
|
||||
])
|
||||
}
|
||||
// 计算高程
|
||||
async function countHeight(earth, item) {
|
||||
return await sampleHeightMostDetailed(earth, item)
|
||||
}
|
||||
function cartesian3Towgs84(earth, cartesian) {
|
||||
const viewer = earth.viewer
|
||||
var ellipsoid = viewer.scene.globe.ellipsoid
|
||||
var cartesian3 = new Cesium.Cartesian3(cartesian.x, cartesian.y, cartesian.z)
|
||||
var cartographic = ellipsoid.cartesianToCartographic(cartesian3)
|
||||
var lat = Cesium.Math.toDegrees(cartographic.latitude)
|
||||
var lng = Cesium.Math.toDegrees(cartographic.longitude)
|
||||
var alt = cartographic.height < 0 ? 0 : cartographic.height
|
||||
return {
|
||||
longitude: lng,
|
||||
latitude: lat,
|
||||
height: alt
|
||||
}
|
||||
}
|
||||
//更新路径高度
|
||||
async function updateHeight(earth, height, positions, cb) {
|
||||
let Cartesian = []
|
||||
let locationList = []
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
const element = positions[i]
|
||||
let Cartographic = await countHeight(earth, element)
|
||||
if (isNaN(Cartographic[0].height)) {
|
||||
Cartographic[0].height = 0
|
||||
}
|
||||
Cartographic[0].height = Cartographic[0].height + height
|
||||
Cartesian.push(Cesium.Cartographic.toCartesian(Cartographic[0]))
|
||||
if (i < positions.length) {
|
||||
cb({
|
||||
cur: i + 1,
|
||||
total: positions.length
|
||||
})
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < Cartesian.length; i++) {
|
||||
locationList.push(cartesian3Towgs84(earth, Cartesian[i]))
|
||||
}
|
||||
let arr = [locationList, Cartesian]
|
||||
cb(arr)
|
||||
}
|
||||
let GenerateRoute = {
|
||||
flyLine,
|
||||
updateHeight
|
||||
}
|
||||
export default GenerateRoute
|
272
src/Obj/AirLine/billord_point_line.js
Normal file
272
src/Obj/AirLine/billord_point_line.js
Normal file
@ -0,0 +1,272 @@
|
||||
export default class BillordPointLine {
|
||||
constructor(options, viewer) {
|
||||
this.options = { ...options }
|
||||
this.pointEntity = null
|
||||
this.billboardEntity = null
|
||||
this.lineEntity = null
|
||||
this.updatedPosition = []
|
||||
this.pointUpdatedPosition = []
|
||||
this.viewer = viewer
|
||||
this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
|
||||
this.pinBuilder = new Cesium.PinBuilder()
|
||||
this.index = null
|
||||
//定义屏幕点击事件处理器
|
||||
BillordPointLine.setDefaultValue(this)
|
||||
BillordPointLine.init(this)
|
||||
}
|
||||
static setDefaultValue(that) {
|
||||
that.options.positions = that.options.positions || {}
|
||||
that.options.normalHeight = that.options.normalHeight || 100
|
||||
that.options.airHeight = that.options.airHeight || 100
|
||||
that.options.image = that.options.image || '/static/img/cluster2.png'
|
||||
that.options.show = that.options.show || true
|
||||
that.options.index = that.options.index || 1
|
||||
that.options.saveFun = that.options.saveFun || null
|
||||
that.options.selectFun = that.options.selectFun || null
|
||||
that.options.keyboard = that.options.keyboard ?? true
|
||||
that.options.updateFrustumFun = that.options.updateFrustumFun || null
|
||||
that.options.frustum = that.options.frustum || null
|
||||
}
|
||||
static init(that) {
|
||||
let positions = that.options.positions
|
||||
// 添加一个Point,稍微偏离地面高度,使其完全可见
|
||||
that.pointEntity = that.viewer.entities.add({
|
||||
show: that.options.show,
|
||||
position: Cesium.Cartesian3.fromDegrees(positions.lng, positions.lat, 0), // 地面上
|
||||
point: {
|
||||
pixelSize: 8,
|
||||
color: Cesium.Color.WITHE,
|
||||
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // 使用相对地面或贴地,
|
||||
disableDepthTestDistance: 0
|
||||
}
|
||||
})
|
||||
//
|
||||
let pinIndex = that.pinBuilder
|
||||
.fromText(
|
||||
that.options.index,
|
||||
Cesium.Color.fromCssColorString('#00d590'),
|
||||
36
|
||||
)
|
||||
.toDataURL()
|
||||
let altitude = 0
|
||||
if (positions.altitude) {
|
||||
altitude = positions.altitude
|
||||
} else {
|
||||
altitude = that.options.normalHeight
|
||||
}
|
||||
// 添加一个Billboard
|
||||
that.billboardEntity = that.viewer.entities.add({
|
||||
show: that.options.show,
|
||||
position: Cesium.Cartesian3.fromDegrees(
|
||||
positions.lng,
|
||||
positions.lat,
|
||||
positions.alt + that.options.normalHeight
|
||||
),
|
||||
// 判断altitude是否有值
|
||||
|
||||
label: {
|
||||
text: `Lat: ${positions.lng.toFixed(8)}\nLon: ${positions.lat.toFixed(
|
||||
8
|
||||
)}\nAlt: ${altitude.toFixed(8)}m`,
|
||||
font: '14px sans-serif',
|
||||
fillColor: Cesium.Color.YELLOW,
|
||||
outlineColor: Cesium.Color.BLACK,
|
||||
outlineWidth: 2,
|
||||
pixelOffset: new Cesium.Cartesian2(0, -60), // 标签偏移量,防止重叠
|
||||
heightReference: Cesium.HeightReference.RELATIVE_TO_TERRAIN, // 确保标签与地面贴合
|
||||
show: false
|
||||
},
|
||||
billboard: {
|
||||
image: pinIndex, // 示例图像路径
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 图像底部对齐
|
||||
width: 36,
|
||||
height: 36
|
||||
},
|
||||
index: that.options.index
|
||||
})
|
||||
|
||||
// 创建一个连接Point和Billboard的竖线
|
||||
that.lineEntity = that.viewer.entities.add({
|
||||
show: that.options.show,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
return [
|
||||
that.pointEntity.position.getValue(),
|
||||
that.billboardEntity.position.getValue()
|
||||
]
|
||||
}, false),
|
||||
width: 1,
|
||||
material: new Cesium.PolylineOutlineMaterialProperty({
|
||||
outlineColor: Cesium.Color.GAINSBORO,
|
||||
outlineWidth: 1,
|
||||
color: Cesium.Color.WITHE
|
||||
}),
|
||||
zIndex: 99999999
|
||||
}
|
||||
})
|
||||
if (that.options.keyboard) {
|
||||
that.changeAltitude()
|
||||
}
|
||||
that.handler.setInputAction(function(movement) {
|
||||
var pickedObject = that.viewer.scene.pick(movement.position)
|
||||
if (
|
||||
Cesium.defined(pickedObject) &&
|
||||
Cesium.defined(pickedObject.id) &&
|
||||
pickedObject.id === that.billboardEntity
|
||||
) {
|
||||
if (that.options.selectFun) {
|
||||
that.options.selectFun(that.billboardEntity.index - 1)
|
||||
}
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
|
||||
}
|
||||
// 改变高度
|
||||
changeAltitude() {
|
||||
var isMouseDown = false
|
||||
var startPosition
|
||||
var initialHeight
|
||||
let that = this
|
||||
let HHH = false
|
||||
// 标识Alt键是否被按下
|
||||
document.addEventListener('keydown', function(event) {
|
||||
const key = event.key // 获取按下的键名
|
||||
// 检查特定键是否被按下
|
||||
if (key === 'h') {
|
||||
HHH = true
|
||||
}
|
||||
})
|
||||
document.addEventListener('keyup', function(event) {
|
||||
HHH = false
|
||||
})
|
||||
// 按下鼠标左键
|
||||
this.handler.setInputAction(function(movement) {
|
||||
var pickedObject = that.viewer.scene.pick(movement.position)
|
||||
if (
|
||||
Cesium.defined(pickedObject) &&
|
||||
Cesium.defined(pickedObject.id) &&
|
||||
pickedObject.id === that.billboardEntity
|
||||
) {
|
||||
isMouseDown = true
|
||||
startPosition = movement.position
|
||||
|
||||
// 获取Billboard当前的地理高度
|
||||
var positionCartographic = Cesium.Cartographic.fromCartesian(
|
||||
that.billboardEntity.position.getValue()
|
||||
)
|
||||
initialHeight = positionCartographic.height
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_DOWN)
|
||||
// 移动鼠标
|
||||
this.handler.setInputAction(function(movement) {
|
||||
if (isMouseDown && HHH == false) {
|
||||
// 移动位置
|
||||
var newCartesian = that.viewer.scene.pickPosition(movement.endPosition)
|
||||
that.disableCameraDrag(that.viewer, false)
|
||||
if (newCartesian) {
|
||||
var newCartographic = Cesium.Cartographic.fromCartesian(newCartesian)
|
||||
// 保持高度不变
|
||||
var newLongitude = newCartographic.longitude
|
||||
var newLatitude = newCartographic.latitude
|
||||
var updatedPosition = Cesium.Cartesian3.fromRadians(
|
||||
newLongitude,
|
||||
newLatitude,
|
||||
initialHeight
|
||||
)
|
||||
var pointUpdatedPosition = Cesium.Cartesian3.fromRadians(
|
||||
newLongitude,
|
||||
newLatitude,
|
||||
0
|
||||
)
|
||||
that.billboardEntity.position = new Cesium.CallbackProperty(() => {
|
||||
return updatedPosition
|
||||
}, false)
|
||||
that.billboardEntity.label.text = `Lat: ${Cesium.Math.toDegrees(
|
||||
newLongitude
|
||||
).toFixed(6)}\nLon: ${Cesium.Math.toDegrees(newLatitude).toFixed(
|
||||
6
|
||||
)}\nAlt: ${initialHeight.toFixed(2)}m`
|
||||
that.pointEntity.position = new Cesium.CallbackProperty(() => {
|
||||
return pointUpdatedPosition
|
||||
}, false)
|
||||
}
|
||||
}
|
||||
if (isMouseDown && HHH) {
|
||||
console.log(HHH)
|
||||
// 改变高度
|
||||
var endPosition = movement.endPosition
|
||||
var deltaY = startPosition.y - endPosition.y // 计算Y轴方向上的移动距离
|
||||
// 根据鼠标移动的距离来调整高度
|
||||
var newHeight = initialHeight + deltaY
|
||||
// 更新billboard位置
|
||||
var positionCartographic = Cesium.Cartographic.fromCartesian(
|
||||
that.billboardEntity.position.getValue()
|
||||
)
|
||||
var newPosition = Cesium.Cartesian3.fromDegrees(
|
||||
Cesium.Math.toDegrees(positionCartographic.longitude),
|
||||
Cesium.Math.toDegrees(positionCartographic.latitude),
|
||||
newHeight
|
||||
)
|
||||
// 禁用相机
|
||||
that.disableCameraDrag(that.viewer, false)
|
||||
that.billboardEntity.position = new Cesium.CallbackProperty(() => {
|
||||
return newPosition
|
||||
}, false)
|
||||
that.billboardEntity.label.text = `Lat: ${Cesium.Math.toDegrees(
|
||||
positionCartographic.longitude
|
||||
).toFixed(6)}\nLon: ${Cesium.Math.toDegrees(
|
||||
positionCartographic.latitude
|
||||
).toFixed(6)}\nAlt: ${newHeight.toFixed(2)}m`
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
|
||||
// 松开鼠标左键
|
||||
this.handler.setInputAction(function(movement) {
|
||||
var pickedObject = that.viewer.scene.pick(movement.position)
|
||||
isMouseDown = false // 禁用相机
|
||||
HHH = false //
|
||||
that.disableCameraDrag(that.viewer, true)
|
||||
// 更新frustum的位置
|
||||
if (
|
||||
Cesium.defined(pickedObject) &&
|
||||
Cesium.defined(pickedObject.id) &&
|
||||
pickedObject.id === that.billboardEntity
|
||||
) {
|
||||
if (that.options.saveFun) {
|
||||
that.options.saveFun(null, false)
|
||||
}
|
||||
if (that.options.selectFun) {
|
||||
that.options.selectFun(that.billboardEntity.index - 1)
|
||||
}
|
||||
that.options.frustum.updatePositionHeight(
|
||||
that.billboardEntity.position.getValue()
|
||||
)
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_UP)
|
||||
}
|
||||
|
||||
disableCameraDrag(viewer, bool) {
|
||||
viewer.scene.screenSpaceCameraController.enableRotate = bool
|
||||
viewer.scene.screenSpaceCameraController.enableTranslate = bool
|
||||
viewer.scene.screenSpaceCameraController.enableZoom = bool
|
||||
viewer.scene.screenSpaceCameraController.enableTilt = bool
|
||||
viewer.scene.screenSpaceCameraController.enableLook = bool
|
||||
}
|
||||
get show() {
|
||||
return this.options.show
|
||||
}
|
||||
/**
|
||||
* @param {boolean} bool
|
||||
*/
|
||||
set show(bool) {
|
||||
if (typeof bool === 'boolean') {
|
||||
this.pointEntity.show = bool
|
||||
this.billboardEntity.show = bool
|
||||
this.lineEntity.show = bool
|
||||
}
|
||||
}
|
||||
|
||||
remove() {
|
||||
this.viewer.entities.remove(this.pointEntity)
|
||||
this.viewer.entities.remove(this.billboardEntity)
|
||||
this.viewer.entities.remove(this.lineEntity)
|
||||
}
|
||||
}
|
673
src/Obj/AirLine/frustum.js
Normal file
673
src/Obj/AirLine/frustum.js
Normal file
@ -0,0 +1,673 @@
|
||||
export default class Frustum {
|
||||
constructor(options, viewer, viewer1) {
|
||||
this.options = { ...options }
|
||||
this.viewer = viewer
|
||||
this.viewer1 = viewer1
|
||||
this.head = 0
|
||||
this.pitch = 90
|
||||
this.po = 0.00001
|
||||
this.position = null
|
||||
this.hpr = null
|
||||
this.currentFrustumOutline = null
|
||||
this.frustum = null
|
||||
this.setInterval1 = null
|
||||
this.webrtc = null
|
||||
|
||||
// 设置默认值
|
||||
Frustum.setDefaultValue(this)
|
||||
this.create()
|
||||
}
|
||||
|
||||
static setDefaultValue(that) {
|
||||
that.options.position = that.options.position || {}
|
||||
that.options.fov = that.options.fov || 30
|
||||
that.options.aspectRatio = that.options.aspectRatio || 1
|
||||
that.options.near = that.options.near || 1
|
||||
that.options.far = that.options.far || 120
|
||||
that.options.heading = that.options.heading || 0
|
||||
that.options.pitch = that.options.pitch || 90
|
||||
that.options.roll = that.options.roll || 0
|
||||
that.options.show = that.options.show ?? true
|
||||
that.options.videoUrl = that.options.videoUrl || ''
|
||||
that.options.index = that.options.index || 0
|
||||
that.options.arr = that.options.arr || []
|
||||
that.options.normalHeight = that.options.normalHeight || 100
|
||||
}
|
||||
|
||||
// 初始化视锥体
|
||||
create() {
|
||||
this.frustum = new Cesium.PerspectiveFrustum({
|
||||
fov: Cesium.Math.toRadians(this.options.fov),
|
||||
aspectRatio: this.options.aspectRatio,
|
||||
near: this.options.near,
|
||||
far: this.options.far
|
||||
})
|
||||
|
||||
const { lng, lat, alt } = this.options.position
|
||||
const { heading, pitch, roll } = this.options
|
||||
this.position = Cesium.Cartesian3.fromDegrees(
|
||||
lng,
|
||||
lat,
|
||||
alt + this.options.normalHeight
|
||||
)
|
||||
this.hpr = new Cesium.HeadingPitchRoll(
|
||||
Cesium.Math.toRadians(heading),
|
||||
Cesium.Math.toRadians(pitch),
|
||||
Cesium.Math.toRadians(roll)
|
||||
)
|
||||
|
||||
this.drawFrustumOutline()
|
||||
this.drawFrustumFilled()
|
||||
this.monitorKeyboard()
|
||||
this.updateFrustumSquareBase(40)
|
||||
this.syncHpr()
|
||||
if (this.options.videoUrl) {
|
||||
this.addVideoToFrustumTop2()
|
||||
}
|
||||
}
|
||||
|
||||
// 监听键盘事件
|
||||
monitorKeyboard() {
|
||||
const keyActions = {
|
||||
KeyQ: () => this.setIntervalhpr(-0.45),
|
||||
KeyE: () => this.setIntervalhpr(0.45),
|
||||
KeyB: () => this.setIntervalhprr(-0.45),
|
||||
KeyN: () => this.setIntervalhprr(0.45),
|
||||
KeyW: () => this.updateFrustumPosition('move', -0.00001),
|
||||
KeyS: () => this.updateFrustumPosition('move', 0.00001),
|
||||
KeyA: () => this.updateFrustumPosition('move', -0.00001, 0),
|
||||
KeyD: () => this.updateFrustumPosition('move', 0.00001, 0),
|
||||
KeyC: () => this.updateFrustumHeight(1), // 增加高度
|
||||
KeyZ: () => this.updateFrustumHeight(-1) // 降低高度
|
||||
}
|
||||
|
||||
this.keydownHandler = event => {
|
||||
if (keyActions[event.code]) keyActions[event.code]()
|
||||
}
|
||||
|
||||
this.keyupHandler = () => this.stopFrustumRotation()
|
||||
|
||||
document.addEventListener('keydown', this.keydownHandler)
|
||||
|
||||
document.addEventListener('keyup', this.keyupHandler)
|
||||
}
|
||||
// 渲染视频
|
||||
addVideoToFrustumTop() {
|
||||
// 创建视频元素
|
||||
const videoElement = document.createElement('video')
|
||||
videoElement.width = 640
|
||||
videoElement.height = 360
|
||||
videoElement.autoplay = true
|
||||
videoElement.loop = true
|
||||
videoElement.muted = true
|
||||
// videoElement.style.display = 'none'; // 隐藏视频元素
|
||||
document.body.appendChild(videoElement)
|
||||
|
||||
// 使用 flv.js 播放 FLV 视频
|
||||
if (flvjs.isSupported()) {
|
||||
const flvPlayer = flvjs.createPlayer({
|
||||
// url: 'http://zmkg.cqet.top:9991/live/2pUbcgTrly3mIDuxsDXN9h3hqcEKU6TlsV_YeIDyqHqXGzXafqWokXdU1q6j_S7hTCP7HynZQIsuNM6KQ5l-ag==.flv',
|
||||
type: 'flv',
|
||||
isLive: true,
|
||||
hasAudio: false,
|
||||
enableStashBuffer: true, //
|
||||
enableWorker: true,
|
||||
autoCleanupSourceBuffer: true, //自动清除缓存
|
||||
url: this.options.videoUrl
|
||||
})
|
||||
flvPlayer.attachMediaElement(videoElement)
|
||||
flvPlayer.load()
|
||||
flvPlayer.play()
|
||||
} else {
|
||||
console.error('FLV.js is not supported in this browser.')
|
||||
}
|
||||
|
||||
const corners = this.computeFrustumCorners(
|
||||
this.frustum,
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
// 创建 PolygonGeometry 并应用视频作为纹理
|
||||
const polygonHierarchy = new Cesium.PolygonHierarchy([
|
||||
corners.bottomLeft,
|
||||
corners.bottomRight,
|
||||
corners.topRight,
|
||||
corners.topLeft
|
||||
])
|
||||
this.videoEntity = this.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: '22222222',
|
||||
show: true,
|
||||
polygon: {
|
||||
hierarchy: polygonHierarchy
|
||||
}
|
||||
})
|
||||
)
|
||||
videoElement.addEventListener('loadeddata', () => {
|
||||
this.videoEntity.polygon.material = videoElement // 确保视频纹理加载后再设置
|
||||
})
|
||||
}
|
||||
// 渲染视频
|
||||
async addVideoToFrustumTop2() {
|
||||
// 创建视频元素
|
||||
const videoElement = document.createElement('video')
|
||||
videoElement.width = 640
|
||||
videoElement.height = 360
|
||||
videoElement.autoplay = true
|
||||
videoElement.loop = true
|
||||
videoElement.muted = true
|
||||
// videoElement.style.display = 'none'; // 隐藏视频元素
|
||||
document.body.appendChild(videoElement)
|
||||
await this.startPlay(videoElement, this.options.videoUrl)
|
||||
const corners = this.computeFrustumCorners(
|
||||
this.frustum,
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
// 创建 PolygonGeometry 并应用视频作为纹理
|
||||
const polygonHierarchy = new Cesium.PolygonHierarchy([
|
||||
corners.bottomLeft,
|
||||
corners.bottomRight,
|
||||
corners.topRight,
|
||||
corners.topLeft
|
||||
])
|
||||
this.videoEntity = this.viewer.entities.add(
|
||||
new Cesium.Entity({
|
||||
id: '22222222',
|
||||
show: true,
|
||||
polygon: {
|
||||
hierarchy: polygonHierarchy
|
||||
}
|
||||
})
|
||||
)
|
||||
videoElement.addEventListener('loadeddata', () => {
|
||||
this.videoEntity.polygon.material = videoElement // 确保视频纹理加载后再设置
|
||||
})
|
||||
}
|
||||
async startPlay(element, url) {
|
||||
// Close existing SDK instance if any
|
||||
if (this.webrtc) {
|
||||
this.webrtc.close()
|
||||
}
|
||||
|
||||
// Initialize a new SDK instance
|
||||
this.webrtc = new SrsRtcWhipWhepAsync()
|
||||
|
||||
// Bind the video player to the SDK stream
|
||||
element.srcObject = this.webrtc.stream
|
||||
|
||||
try {
|
||||
const session = await this.webrtc.play(url)
|
||||
console.log(session)
|
||||
// this.sessionId = session.sessionid
|
||||
// this.simulatorUrl = `${session.simulator}?drop=1&username=${session.sessionid}`
|
||||
} catch (error) {
|
||||
// console.error('Error playing stream:', error)
|
||||
this.webrtc.close()
|
||||
// this.playerVisible = false
|
||||
}
|
||||
}
|
||||
// 计算视锥体远裁剪面(大面)的四个角点
|
||||
computeFrustumCorners(frustum, position, hpr) {
|
||||
const tanFov = Math.tan(frustum.fov * 0.5)
|
||||
const farHeight = frustum.far * tanFov
|
||||
const farWidth = farHeight * frustum.aspectRatio
|
||||
|
||||
const topLeft = new Cesium.Cartesian3(-farWidth, farHeight, -frustum.far)
|
||||
const topRight = new Cesium.Cartesian3(farWidth, farHeight, -frustum.far)
|
||||
const bottomLeft = new Cesium.Cartesian3(
|
||||
-farWidth,
|
||||
-farHeight,
|
||||
-frustum.far
|
||||
)
|
||||
const bottomRight = new Cesium.Cartesian3(
|
||||
farWidth,
|
||||
-farHeight,
|
||||
-frustum.far
|
||||
)
|
||||
const transform = Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
position,
|
||||
hpr
|
||||
)
|
||||
// console.log('transform111111111111111111111111', transform)
|
||||
return {
|
||||
topLeft: Cesium.Matrix4.multiplyByPoint(
|
||||
transform,
|
||||
topLeft,
|
||||
new Cesium.Cartesian3()
|
||||
),
|
||||
topRight: Cesium.Matrix4.multiplyByPoint(
|
||||
transform,
|
||||
topRight,
|
||||
new Cesium.Cartesian3()
|
||||
),
|
||||
bottomLeft: Cesium.Matrix4.multiplyByPoint(
|
||||
transform,
|
||||
bottomLeft,
|
||||
new Cesium.Cartesian3()
|
||||
),
|
||||
bottomRight: Cesium.Matrix4.multiplyByPoint(
|
||||
transform,
|
||||
bottomRight,
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
}
|
||||
}
|
||||
// 封装的函数:更新 Polygon 面的位置
|
||||
updatePolygonPosition() {
|
||||
const corners = this.computeFrustumCorners(
|
||||
this.frustum,
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
|
||||
this.videoEntity.polygon.hierarchy = new Cesium.CallbackProperty(e => {
|
||||
return new Cesium.PolygonHierarchy([
|
||||
corners.bottomLeft,
|
||||
corners.bottomRight,
|
||||
corners.topRight,
|
||||
corners.topLeft
|
||||
])
|
||||
})
|
||||
}
|
||||
// 更新锥体底部为正方形的方法
|
||||
updateFrustumSquareBase(value) {
|
||||
// 将输入值范围从 56 到 1 映射到面积范围 10000 到 100
|
||||
const minArea = 100 // 最小面积
|
||||
const maxArea = 10000 // 最大面积
|
||||
|
||||
// 映射公式(反转映射)
|
||||
const newArea = ((56 - value) / (56 - 1)) * (maxArea - minArea) + minArea
|
||||
|
||||
// 确保aspectRatio保持为1(正方形)
|
||||
this.frustum.aspectRatio = 1
|
||||
|
||||
// 根据面积计算正方形边长
|
||||
const sideLength = Math.sqrt(newArea)
|
||||
|
||||
// 远平面距离
|
||||
const far = this.frustum.far
|
||||
|
||||
// 计算新的fov
|
||||
const fov = 2 * Math.atan(sideLength / (2 * far))
|
||||
|
||||
// 更新视锥体的fov
|
||||
this.frustum.fov = fov
|
||||
|
||||
// 重新绘制视锥体轮廓和填充
|
||||
this.drawFrustumOutline()
|
||||
this.drawFrustumFilled()
|
||||
this.syncHpr()
|
||||
}
|
||||
updateFrustumHeight(deltaHeight) {
|
||||
const cartographic = Cesium.Cartographic.fromCartesian(this.position)
|
||||
cartographic.height += deltaHeight // 更新高度
|
||||
this.position = Cesium.Cartesian3.fromDegrees(
|
||||
Cesium.Math.toDegrees(cartographic.longitude),
|
||||
Cesium.Math.toDegrees(cartographic.latitude),
|
||||
cartographic.height
|
||||
)
|
||||
this.options.position.alt = cartographic.height
|
||||
// this.options.arr[
|
||||
// this.options.index
|
||||
// ] = this.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic)
|
||||
this.syncHpr()
|
||||
this.drawFrustumOutline() // 重新绘制视锥体轮廓
|
||||
this.drawFrustumFilled()
|
||||
}
|
||||
// 更新position变化后的视锥体属性
|
||||
updatePositionHeight(p) {
|
||||
this.options.position = this.cartesian3Towgs84(p)
|
||||
this.syncHpr()
|
||||
this.drawFrustumOutline() // 重新绘制视锥体轮廓
|
||||
this.drawFrustumFilled()
|
||||
}
|
||||
cartesian3Towgs84(cartesian) {
|
||||
var ellipsoid = this.viewer.scene.globe.ellipsoid
|
||||
var cartesian3 = new Cesium.Cartesian3(
|
||||
cartesian.x,
|
||||
cartesian.y,
|
||||
cartesian.z
|
||||
)
|
||||
var cartographic = ellipsoid.cartesianToCartographic(cartesian3)
|
||||
var lat = Cesium.Math.toDegrees(cartographic.latitude)
|
||||
var lng = Cesium.Math.toDegrees(cartographic.longitude)
|
||||
var alt = cartographic.height < 0 ? 0 : cartographic.height
|
||||
return {
|
||||
lng: lng,
|
||||
lat: lat,
|
||||
alt: alt
|
||||
}
|
||||
}
|
||||
setIntervalhpr(num) {
|
||||
this.stopFrustumRotation() // 先停止当前的定时器
|
||||
this.setInterval1 = setInterval(() => {
|
||||
this.head += num
|
||||
this.updateFrustumHPR(Cesium.Math.toRadians(this.head), this.pitch)
|
||||
}, 10)
|
||||
}
|
||||
setIntervalhprr(num) {
|
||||
this.stopFrustumRotation() // 先停止当前的定时器
|
||||
this.setInterval1 = setInterval(() => {
|
||||
// 限制 pitch 在 [60, 180] 范围内
|
||||
this.pitch = Math.max(60, Math.min(180, this.pitch + num))
|
||||
this.updateFrustumHPR(this.head, Cesium.Math.toRadians(this.pitch))
|
||||
}, 10)
|
||||
}
|
||||
// 停止视锥体旋转
|
||||
stopFrustumRotation() {
|
||||
if (this.setInterval1) {
|
||||
clearInterval(this.setInterval1)
|
||||
this.setInterval1 = null
|
||||
}
|
||||
}
|
||||
// 新增:绘制填充的视锥体
|
||||
drawFrustumFilled() {
|
||||
let that = this
|
||||
// console.log('that.options.show', that.options.show)
|
||||
|
||||
const transform = Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
|
||||
const frustumGeometry = new Cesium.FrustumGeometry({
|
||||
frustum: this.frustum,
|
||||
origin: Cesium.Matrix4.getTranslation(transform, new Cesium.Cartesian3()),
|
||||
orientation: Cesium.Quaternion.fromRotationMatrix(
|
||||
Cesium.Matrix4.getRotation(transform, new Cesium.Matrix3())
|
||||
)
|
||||
})
|
||||
|
||||
if (this.currentFrustumFilled) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumFilled)
|
||||
}
|
||||
|
||||
this.currentFrustumFilled = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: frustumGeometry,
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.fromAlpha(Cesium.Color.YELLOW, 0.4) // 半透明黄色填充
|
||||
)
|
||||
}
|
||||
}),
|
||||
appearance: new Cesium.MaterialAppearance({
|
||||
material: Cesium.Material.fromType('Color', {
|
||||
color: Cesium.Color.fromAlpha(Cesium.Color.YELLOW, 0.4) // 填充颜色
|
||||
}),
|
||||
translucent: true
|
||||
}),
|
||||
asynchronous: false,
|
||||
// show: false
|
||||
show: that.options.show
|
||||
})
|
||||
|
||||
this.viewer.scene.primitives.add(this.currentFrustumFilled)
|
||||
}
|
||||
// 绘制视锥体轮廓
|
||||
drawFrustumOutline() {
|
||||
let that = this
|
||||
// console.log('that.options.show', that.options.show)
|
||||
|
||||
const transform = Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
|
||||
const frustumOutlineGeometry = new Cesium.FrustumOutlineGeometry({
|
||||
frustum: this.frustum,
|
||||
origin: Cesium.Matrix4.getTranslation(transform, new Cesium.Cartesian3()),
|
||||
orientation: Cesium.Quaternion.fromRotationMatrix(
|
||||
Cesium.Matrix4.getRotation(transform, new Cesium.Matrix3())
|
||||
)
|
||||
})
|
||||
|
||||
if (this.currentFrustumOutline) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumOutline)
|
||||
}
|
||||
|
||||
this.currentFrustumOutline = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: frustumOutlineGeometry,
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.YELLOW
|
||||
)
|
||||
}
|
||||
}),
|
||||
appearance: new Cesium.PolylineColorAppearance({
|
||||
translucent: false
|
||||
}),
|
||||
asynchronous: false,
|
||||
show: that.options.show
|
||||
// show: false
|
||||
})
|
||||
|
||||
this.viewer.scene.primitives.add(this.currentFrustumOutline)
|
||||
}
|
||||
// 更新视锥体位置
|
||||
updateFrustumPosition(type = 'move', p, deg = 90, flag = true) {
|
||||
if (type === 'move') {
|
||||
// eslint-disable-next-line no-undef
|
||||
const point = turf.point([
|
||||
this.options.position.lng,
|
||||
this.options.position.lat
|
||||
])
|
||||
const degreesValue = Cesium.Math.toDegrees(this.hpr.heading)
|
||||
const bearing = degreesValue + deg
|
||||
const options = { units: 'degrees' }
|
||||
// eslint-disable-next-line no-undef
|
||||
const destination = turf.destination(point, p, bearing, options).geometry
|
||||
.coordinates
|
||||
|
||||
this.position = Cesium.Cartesian3.fromDegrees(
|
||||
destination[0],
|
||||
destination[1],
|
||||
this.options.position.alt + this.options.normalHeight
|
||||
)
|
||||
this.options.position.lng = destination[0]
|
||||
this.options.position.lat = destination[1]
|
||||
|
||||
this.viewer.camera.setView({
|
||||
destination: Cesium.Cartesian3.fromDegrees(
|
||||
destination[0],
|
||||
destination[1],
|
||||
this.viewer.camera.positionCartographic.height
|
||||
)
|
||||
})
|
||||
}
|
||||
if (type === 'update') {
|
||||
this.position = p
|
||||
this.options.videoUrl && this.updatePolygonPosition()
|
||||
}
|
||||
if (flag) {
|
||||
this.syncHpr()
|
||||
this.updateFrustumAttributes()
|
||||
}
|
||||
}
|
||||
// 同步视角
|
||||
syncHpr() {
|
||||
// console.log('this.viewer1', this.viewer1);
|
||||
if (this.viewer1) {
|
||||
const { lng, lat, alt } = this.options.position
|
||||
let pitch = -this.hpr.pitch - Cesium.Math.toRadians(-90.0)
|
||||
this.viewer1.camera.setView({
|
||||
destination: Cesium.Cartesian3.fromDegrees(
|
||||
lng,
|
||||
lat,
|
||||
alt + this.options.normalHeight
|
||||
),
|
||||
orientation: {
|
||||
heading: this.hpr.heading + Cesium.Math.toRadians(-90.0),
|
||||
pitch,
|
||||
roll: this.hpr.roll
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// 更新视锥体的 HeadingPitchRoll
|
||||
updateFrustumHPR(
|
||||
h = this.head,
|
||||
p = this.pitch,
|
||||
r = 0,
|
||||
flag = true,
|
||||
type = ''
|
||||
) {
|
||||
function degreesToRadians(degrees) {
|
||||
return (degrees * Math.PI) / 180.0
|
||||
}
|
||||
if (type == 'alone') {
|
||||
this.hpr.heading = degreesToRadians(h)
|
||||
this.hpr.pitch = degreesToRadians(p)
|
||||
this.hpr.roll = degreesToRadians(r)
|
||||
} else {
|
||||
this.hpr.heading = Cesium.Math.negativePiToPi(h)
|
||||
this.hpr.pitch = Cesium.Math.negativePiToPi(p)
|
||||
this.hpr.roll = Cesium.Math.negativePiToPi(r)
|
||||
}
|
||||
if (flag) {
|
||||
this.syncHpr()
|
||||
this.updateFrustumAttributes()
|
||||
}
|
||||
}
|
||||
// 用于更新
|
||||
updateFrustumAttributes() {
|
||||
let that = this
|
||||
// 检查 position 和 hpr 是否已初始化
|
||||
if (!this.position || !this.hpr) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Position or HPR is not defined:', this.position, this.hpr)
|
||||
return
|
||||
}
|
||||
|
||||
// 生成变换矩阵
|
||||
const transform = Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
|
||||
if (!transform) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Transform generation failed.')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// 准备轮廓几何体和外观
|
||||
const outlineGeometry = new Cesium.FrustumOutlineGeometry({
|
||||
frustum: this.frustum,
|
||||
origin: Cesium.Matrix4.getTranslation(
|
||||
transform,
|
||||
new Cesium.Cartesian3()
|
||||
),
|
||||
orientation: Cesium.Quaternion.fromRotationMatrix(
|
||||
Cesium.Matrix4.getRotation(transform, new Cesium.Matrix3())
|
||||
)
|
||||
})
|
||||
|
||||
const outlineAppearance = new Cesium.PolylineColorAppearance({
|
||||
translucent: false
|
||||
})
|
||||
const outlineColor = Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.YELLOW
|
||||
)
|
||||
|
||||
// 准备填充几何体和外观
|
||||
const filledGeometry = new Cesium.FrustumGeometry({
|
||||
frustum: this.frustum,
|
||||
origin: Cesium.Matrix4.getTranslation(
|
||||
transform,
|
||||
new Cesium.Cartesian3()
|
||||
),
|
||||
orientation: Cesium.Quaternion.fromRotationMatrix(
|
||||
Cesium.Matrix4.getRotation(transform, new Cesium.Matrix3())
|
||||
)
|
||||
})
|
||||
|
||||
const filledAppearance = new Cesium.MaterialAppearance({
|
||||
material: Cesium.Material.fromType('Color', {
|
||||
color: Cesium.Color.YELLOW.withAlpha(0.5)
|
||||
}),
|
||||
translucent: true
|
||||
})
|
||||
const filledColor = Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.RED.withAlpha(0.5)
|
||||
)
|
||||
|
||||
// 删除旧的 Primitive
|
||||
if (this.currentFrustumOutline) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumOutline)
|
||||
}
|
||||
if (this.currentFrustumFilled) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumFilled)
|
||||
}
|
||||
|
||||
// 创建并添加新的轮廓 Primitive
|
||||
this.currentFrustumOutline = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: outlineGeometry,
|
||||
attributes: { color: outlineColor }
|
||||
}),
|
||||
appearance: outlineAppearance,
|
||||
asynchronous: false,
|
||||
show: that.options.show
|
||||
})
|
||||
this.viewer.scene.primitives.add(this.currentFrustumOutline)
|
||||
|
||||
// 创建并添加新的填充 Primitive
|
||||
this.currentFrustumFilled = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: filledGeometry,
|
||||
attributes: { color: filledColor }
|
||||
}),
|
||||
appearance: filledAppearance,
|
||||
asynchronous: false,
|
||||
show: that.options.show
|
||||
})
|
||||
this.viewer.scene.primitives.add(this.currentFrustumFilled)
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error in drawFrustum:', error)
|
||||
}
|
||||
}
|
||||
// 调整视锥体的 near 和 far 平面
|
||||
updateFrustumNearFar(newNear, newFar) {
|
||||
this.frustum.near = newNear
|
||||
this.frustum.far = newFar
|
||||
this.drawFrustumOutline()
|
||||
this.drawFrustumFilled()
|
||||
}
|
||||
// 调整视锥体的 fov
|
||||
updateFrustumFov(newFov) {
|
||||
this.frustum.fov = Cesium.Math.toRadians(newFov)
|
||||
this.drawFrustumOutline()
|
||||
this.drawFrustumFilled()
|
||||
}
|
||||
|
||||
get show() {
|
||||
return this.options.show
|
||||
}
|
||||
|
||||
set show(bool) {
|
||||
if (typeof bool === 'boolean') {
|
||||
this.options.show = bool
|
||||
this.currentFrustumOutline.show = bool
|
||||
this.currentFrustumFilled.show = bool
|
||||
}
|
||||
}
|
||||
|
||||
remove() {
|
||||
document.removeEventListener('keydown', this.keydownHandler)
|
||||
document.removeEventListener('keyup', this.keyupHandler)
|
||||
if (this.currentFrustumFilled) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumFilled)
|
||||
}
|
||||
if (this.currentFrustumOutline) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumOutline)
|
||||
}
|
||||
if (this.videoEntity) {
|
||||
this.viewer.entities.remove(this.videoEntity)
|
||||
}
|
||||
}
|
||||
}
|
257
src/Obj/AirLine/frustum2.js
Normal file
257
src/Obj/AirLine/frustum2.js
Normal file
@ -0,0 +1,257 @@
|
||||
export default class FRUSTUN {
|
||||
constructor(options, viewer, viewer1) {
|
||||
this.options = { ...options }
|
||||
this.viewer = viewer
|
||||
this.viewer1 = viewer1
|
||||
this.head = 0
|
||||
this.po = 0.00001
|
||||
this.position = null
|
||||
this.hpr = null
|
||||
this.currentFrustumOutline = null
|
||||
this.frustum = null
|
||||
this.setInterval = null
|
||||
FRUSTUN.setDefaultValue(this)
|
||||
this.create()
|
||||
}
|
||||
static setDefaultValue(that) {
|
||||
that.options.position = that.options.position || {}
|
||||
that.options.fov = that.options.fov || 20
|
||||
that.options.aspectRatio = that.options.aspectRatio || 1
|
||||
that.options.near = that.options.near || 1
|
||||
that.options.far = that.options.far || 100
|
||||
that.options.heading = that.options.heading || 0
|
||||
that.options.pitch = that.options.pitch || 90
|
||||
that.options.roll = that.options.roll || 0
|
||||
that.options.show = that.options.show || true
|
||||
}
|
||||
// 初始化视锥体
|
||||
create() {
|
||||
this.frustum = new Cesium.PerspectiveFrustum()
|
||||
this.frustum.fov = Cesium.Math.toRadians(this.options.fov)
|
||||
this.frustum.aspectRatio = 1.0 // 保持 aspectRatio 不变
|
||||
this.frustum.near = 1.0
|
||||
this.frustum.far = 50.0
|
||||
// 设置初始视锥体位置和方向
|
||||
let { lng, lat, alt } = this.options.position
|
||||
let { heading, pitch, roll } = this.options
|
||||
this.position = Cesium.Cartesian3.fromDegrees(lng, lat, alt + 100)
|
||||
this.hpr = new Cesium.HeadingPitchRoll(
|
||||
Cesium.Math.toRadians(heading),
|
||||
Cesium.Math.toRadians(pitch),
|
||||
Cesium.Math.toRadians(roll)
|
||||
)
|
||||
console.log(heading)
|
||||
this.drawFrustumOutline()
|
||||
this.monitorKeyboard()
|
||||
}
|
||||
|
||||
setIntervalhpr(num) {
|
||||
if (!this.setInterval1) {
|
||||
this.setInterval1 = setInterval(() => {
|
||||
this.head += num
|
||||
this.updateFrustumHPR(Cesium.Math.toRadians(this.head))
|
||||
}, 10)
|
||||
}
|
||||
}
|
||||
// 监听 键盘事件
|
||||
// monitorKeyboard() {
|
||||
// let that = this;
|
||||
// document.addEventListener("keydown", function (event) {
|
||||
// switch (event.code) {
|
||||
// case "KeyQ":
|
||||
// that.setIntervalhpr(-0.45);
|
||||
// break;
|
||||
// case "KeyE":
|
||||
// that.setIntervalhpr(0.45);
|
||||
// break;
|
||||
// case "KeyW":
|
||||
// that.updateFrustumPosition("move", -0.00001);
|
||||
// break;
|
||||
// case "KeyS":
|
||||
// that.updateFrustumPosition("move", 0.00001);
|
||||
// break;
|
||||
// case "KeyA":
|
||||
// that.updateFrustumPosition("move", -0.00001, 0);
|
||||
// break;
|
||||
// case "KeyD":
|
||||
// that.updateFrustumPosition("move", 0.00001, 0);
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// });
|
||||
// document.addEventListener("keyup", function (event) {
|
||||
// clearInterval(that.setInterval1);
|
||||
// that.setInterval1 = null; // 重置 interval
|
||||
// });
|
||||
// }
|
||||
// 监听键盘事件
|
||||
monitorKeyboard() {
|
||||
const keyActions = {
|
||||
KeyQ: () => this.setIntervalhpr(-0.45),
|
||||
KeyE: () => this.setIntervalhpr(0.45),
|
||||
KeyW: () => this.updateFrustumPosition('move', -0.00001),
|
||||
KeyS: () => this.updateFrustumPosition('move', 0.00001),
|
||||
KeyA: () => this.updateFrustumPosition('move', -0.00001, 0),
|
||||
KeyD: () => this.updateFrustumPosition('move', 0.00001, 0),
|
||||
KeyC: () => this.updateFrustumHeight(1), // 增加高度
|
||||
KeyZ: () => this.updateFrustumHeight(-1) // 降低高度
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', event => {
|
||||
if (keyActions[event.code]) keyActions[event.code]()
|
||||
})
|
||||
|
||||
document.addEventListener('keyup', () => this.stopFrustumRotation())
|
||||
}
|
||||
// 停止视锥体旋转
|
||||
stopFrustumRotation() {
|
||||
clearInterval(this.setInterval1)
|
||||
this.setInterval1 = null
|
||||
}
|
||||
// 使用 HeadingPitchRoll 创建视锥体轮廓
|
||||
drawFrustumOutline() {
|
||||
const transform = Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
this.position,
|
||||
this.hpr
|
||||
)
|
||||
const frustumOutlineGeometry = new Cesium.FrustumOutlineGeometry({
|
||||
frustum: this.frustum,
|
||||
origin: Cesium.Matrix4.getTranslation(transform, new Cesium.Cartesian3()),
|
||||
orientation: Cesium.Quaternion.fromRotationMatrix(
|
||||
Cesium.Matrix4.getRotation(transform, new Cesium.Matrix3())
|
||||
)
|
||||
})
|
||||
|
||||
if (this.currentFrustumOutline) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumOutline)
|
||||
}
|
||||
|
||||
this.currentFrustumOutline = new Cesium.Primitive({
|
||||
geometryInstances: new Cesium.GeometryInstance({
|
||||
geometry: frustumOutlineGeometry,
|
||||
attributes: {
|
||||
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
||||
Cesium.Color.YELLOW
|
||||
)
|
||||
}
|
||||
}),
|
||||
appearance: new Cesium.PolylineColorAppearance({
|
||||
translucent: false
|
||||
}),
|
||||
asynchronous: false
|
||||
})
|
||||
|
||||
this.viewer.scene.primitives.add(this.currentFrustumOutline)
|
||||
}
|
||||
// 更新视锥体位置
|
||||
updateFrustumPosition(type = 'move', p, deg = 90) {
|
||||
if (type == 'move') {
|
||||
var point = turf.point([
|
||||
this.options.position.lng,
|
||||
this.options.position.lat
|
||||
])
|
||||
const degreesValue = Cesium.Math.toDegrees(this.hpr.heading)
|
||||
var distance = p
|
||||
var bearing = degreesValue + deg
|
||||
var options = { units: 'degrees' }
|
||||
|
||||
var destination = turf.destination(point, distance, bearing, options)
|
||||
.geometry.coordinates
|
||||
this.position = Cesium.Cartesian3.fromDegrees(
|
||||
destination[0],
|
||||
destination[1],
|
||||
this.options.position.alt + 100
|
||||
)
|
||||
this.options.position.lng = destination[0]
|
||||
this.options.position.lat = destination[1]
|
||||
|
||||
this.viewer.camera.setView({
|
||||
destination: Cesium.Cartesian3.fromDegrees(
|
||||
destination[0],
|
||||
destination[1],
|
||||
this.viewer.camera.positionCartographic.height
|
||||
),
|
||||
orientation: {
|
||||
heading: this.viewer.camera.heading,
|
||||
pitch: this.viewer.camera.pitch,
|
||||
roll: this.viewer.camera.roll
|
||||
}
|
||||
})
|
||||
}
|
||||
if (type == 'update') {
|
||||
this.position = p
|
||||
}
|
||||
// this.tongbuHpr();
|
||||
this.drawFrustumOutline()
|
||||
}
|
||||
// 同步视角
|
||||
tongbuHpr() {
|
||||
const { lng, lat, alt } = this.options.position
|
||||
this.viewer1.camera.setView({
|
||||
destination: new Cesium.Cartesian3.fromDegrees(lng, lat, alt + 100),
|
||||
orientation: {
|
||||
heading: this.hpr.heading + Cesium.Math.toRadians(-90.0),
|
||||
pitch: this.hpr.pitch + Cesium.Math.toRadians(-90.0),
|
||||
roll: this.hpr.roll
|
||||
}
|
||||
})
|
||||
}
|
||||
updateFrustumHeight(deltaHeight) {
|
||||
const cartographic = Cesium.Cartographic.fromCartesian(this.position)
|
||||
cartographic.height += deltaHeight // 更新高度
|
||||
this.position = Cesium.Cartesian3.fromDegrees(
|
||||
Cesium.Math.toDegrees(cartographic.longitude),
|
||||
Cesium.Math.toDegrees(cartographic.latitude),
|
||||
cartographic.height
|
||||
)
|
||||
this.options.position.alt = cartographic.height
|
||||
// this.tongbuHpr();
|
||||
this.drawFrustumOutline() // 重新绘制视锥体轮廓
|
||||
}
|
||||
// 更新视锥体的 HeadingPitchRoll
|
||||
updateFrustumHPR(h = 0, p = Cesium.Math.toRadians(90), r = 0) {
|
||||
this.hpr.heading = Cesium.Math.negativePiToPi(h)
|
||||
this.hpr.pitch = Cesium.Math.negativePiToPi(p)
|
||||
this.hpr.roll = Cesium.Math.negativePiToPi(r)
|
||||
// this.tongbuHpr();
|
||||
this.drawFrustumOutline()
|
||||
}
|
||||
// 封装的函数:调整视锥体的 near 和 far 平面
|
||||
updateFrustumNearFar(newNear, newFar) {
|
||||
this.frustum.near = newNear
|
||||
this.frustum.far = newFar
|
||||
this.drawFrustumOutline()
|
||||
}
|
||||
// 封装的函数:调整视锥体的 fov(远裁剪面的大小)
|
||||
updateFrustumFov(newFov) {
|
||||
this.frustum.fov = Cesium.Math.toRadians(newFov)
|
||||
this.drawFrustumOutline()
|
||||
this.viewer.scene.requestRender() // 强制重新渲染场景
|
||||
}
|
||||
// 封装的函数:调整视锥体的高度
|
||||
updateFrustumHeight(deltaHeight) {
|
||||
const cartographic = Cesium.Cartographic.fromCartesian(this.position)
|
||||
cartographic.height += deltaHeight
|
||||
this.position = Cesium.Cartesian3.fromDegrees(
|
||||
Cesium.Math.toDegrees(cartographic.longitude),
|
||||
Cesium.Math.toDegrees(cartographic.latitude),
|
||||
cartographic.height
|
||||
)
|
||||
this.drawFrustumOutline()
|
||||
this.viewer.scene.requestRender() // 强制重新渲染场景
|
||||
}
|
||||
get show() {
|
||||
return this.options.show
|
||||
}
|
||||
set show(bool) {
|
||||
if (typeof bool == 'boolean') {
|
||||
this.currentFrustumOutline.show = bool
|
||||
}
|
||||
}
|
||||
remove() {
|
||||
if (this.currentFrustumOutline) {
|
||||
this.viewer.scene.primitives.remove(this.currentFrustumOutline)
|
||||
}
|
||||
}
|
||||
}
|
290
src/Obj/AirLine/index.js
Normal file
290
src/Obj/AirLine/index.js
Normal file
@ -0,0 +1,290 @@
|
||||
import { closeRotateAround, closeViewFollow} from '../../Global/global'
|
||||
export default class AirLine {
|
||||
constructor(options, earth) {
|
||||
this.earth = earth
|
||||
this.positions = null
|
||||
this.options = { ...options }
|
||||
this.Model = null
|
||||
this.pointCollection = null
|
||||
this.entity = null
|
||||
this.dataSouce = new Cesium.CustomDataSource('airLineSource' + options.id)
|
||||
AirLine.setDefaultValue(this)
|
||||
AirLine.add(this)
|
||||
}
|
||||
static setDefaultValue(that) {
|
||||
that.options.id = that.options.id || Cesium.createGuid()
|
||||
that.options.positions = that.options.positions || []
|
||||
that.options.width = that.options.width || 5
|
||||
that.options.show = that.options.show || true
|
||||
that.options.color = that.options.color || '#00FFFF'
|
||||
that.options.height = that.options.height || 20
|
||||
that.options.url = that.options.url || ''
|
||||
that.options.modelShow = that.options.modelShow || false
|
||||
that.options.flag = that.options.flag || true
|
||||
that.options.speed = that.options.speed || 1
|
||||
that.options.billboard.show = that.options.billboard.show || true
|
||||
that.options.billboard.image = that.options.billboard.image || ''
|
||||
that.options.billboard.scale = that.options.billboard.scale || 1
|
||||
that.options.billboard.width = that.options.billboard.width || 64
|
||||
that.options.billboard.height = that.options.billboard.height || 64
|
||||
that.options.billboard.near = that.options.billboard.near ?? 1000
|
||||
that.options.billboard.far = that.options.billboard.far ?? 10000
|
||||
}
|
||||
static add(that) {
|
||||
if (that.options.positions.length < 3) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('坐标数量至少需要3个')
|
||||
return
|
||||
}
|
||||
that.pointCollection = that.earth.viewer.scene.primitives.add(
|
||||
new Cesium.PointPrimitiveCollection()
|
||||
)
|
||||
for (let i = 0; i < that.options.positions.length - 1; i++) {
|
||||
let entity = that.createLine([
|
||||
that.options.positions[i],
|
||||
that.options.positions[i + 1]
|
||||
])
|
||||
that.dataSouce.entities.add(entity)
|
||||
}
|
||||
that.earth.viewer.dataSources.add(that.dataSouce).then(r => {})
|
||||
that.createPoint()
|
||||
that.createModel()
|
||||
}
|
||||
// 创建线条
|
||||
createLine(positions) {
|
||||
let entity = new Cesium.Entity({
|
||||
id: Cesium.createGuid(),
|
||||
polyline: {
|
||||
positions: positions,
|
||||
clampToGround: false,
|
||||
width: this.options.width,
|
||||
material: new Cesium.PolylineArrowMaterialProperty(
|
||||
Cesium.Color.fromCssColorString(this.options.color)
|
||||
),
|
||||
zIndex: 99999999
|
||||
},
|
||||
show: true,
|
||||
})
|
||||
return entity
|
||||
}
|
||||
// 生成点
|
||||
createPoint() {
|
||||
this.options.positions.forEach((item, index) => {
|
||||
this.pointCollection.add({
|
||||
show: true,
|
||||
position: item,
|
||||
pixelSize: 10.0,
|
||||
color: Cesium.Color.GREENYELLOW,
|
||||
id: index
|
||||
})
|
||||
})
|
||||
}
|
||||
get show() {
|
||||
return this.entity.show
|
||||
}
|
||||
set show(status) {
|
||||
if (typeof status == 'boolean') this.entity.show = status
|
||||
}
|
||||
get modelShow() {
|
||||
return this.Model.show
|
||||
}
|
||||
set modelShow(status) {
|
||||
if (typeof status == 'boolean') this.Model.show = status
|
||||
}
|
||||
// 添加一个模型
|
||||
createModel() {
|
||||
let scaleByDistance = new Cesium.NearFarScalar(
|
||||
this.options.billboard.near,
|
||||
1,
|
||||
this.options.billboard.far,
|
||||
0
|
||||
)
|
||||
const position = this.options.positions[0]
|
||||
const heading = Cesium.Math.toRadians(0)
|
||||
const pitch = 0
|
||||
const roll = 0
|
||||
const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll)
|
||||
const orientation = Cesium.Transforms.headingPitchRollQuaternion(
|
||||
position,
|
||||
hpr
|
||||
)
|
||||
this.Model = this.earth.viewer.entities.add({
|
||||
name: this.options.billboard.image,
|
||||
position,
|
||||
// orientation,
|
||||
billboard: {
|
||||
show: this.options.billboard.show,
|
||||
image: this.options.billboard.image,
|
||||
scale: this.options.billboard.scale,
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
width: this.options.billboard.width,
|
||||
height: this.options.billboard.height,
|
||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||
scaleByDistance,
|
||||
pixelOffsetScaleByDistance: scaleByDistance
|
||||
},
|
||||
// model: {
|
||||
// uri: this.options.url,
|
||||
// minimumPixelSize: 128,
|
||||
// maximumScale: 20000
|
||||
// },
|
||||
show: this.options.modelShow
|
||||
})
|
||||
}
|
||||
// 开始飞行
|
||||
start() {
|
||||
if (!this.options.positions) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('请先绘制并且生成航线')
|
||||
return
|
||||
}
|
||||
let i
|
||||
let that = this
|
||||
this.timer = setInterval(function() {
|
||||
if (this.index) {
|
||||
i = this.index
|
||||
} else {
|
||||
i = 0
|
||||
}
|
||||
i++
|
||||
this.index = i
|
||||
if (i > that.options.positions.length) {
|
||||
clearInterval(this.timer)
|
||||
} else {
|
||||
let position = that.options.positions[i]
|
||||
if (position) {
|
||||
that.Model.position = new Cesium.CallbackProperty(e => {
|
||||
return position
|
||||
})
|
||||
that.Model.orientation = that.direction(
|
||||
that.options.positions[i - 1],
|
||||
that.options.positions[i]
|
||||
).orientation
|
||||
}
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
// 停止飞行
|
||||
stop() {
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
}
|
||||
}
|
||||
// 飞入
|
||||
flyTo() {
|
||||
closeRotateAround(this.earth)
|
||||
closeViewFollow(this.earth)
|
||||
let positionArray = []
|
||||
for (let i = 0; i < this.options.positions.length; i++) {
|
||||
let item = this.options.positions[i]
|
||||
positionArray.push(item.x, item.y, item.z)
|
||||
}
|
||||
// console.log('cartesian',cartesian);
|
||||
// let position = Cesium.Cartographic.fromCartesian(cartesian)
|
||||
// console.log('position',position);
|
||||
let BoundingSphere = Cesium.BoundingSphere.fromVertices(positionArray)
|
||||
this.earth.viewer.camera.flyToBoundingSphere(BoundingSphere, {
|
||||
offset: {
|
||||
heading: Cesium.Math.toRadians(0.0),
|
||||
pitch: Cesium.Math.toRadians(-90.0),
|
||||
roll: Cesium.Math.toRadians(0.0)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 计算一个到另一个点的方向
|
||||
direction(pointA, pointB) {
|
||||
//向量AB
|
||||
const vector2 = Cesium.Cartesian3.subtract(
|
||||
pointB,
|
||||
pointA,
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
//归一化
|
||||
const normal = Cesium.Cartesian3.normalize(vector2, new Cesium.Cartesian3())
|
||||
//旋转矩阵 rotationMatrixFromPositionVelocity源码中有,并未出现在cesiumAPI中
|
||||
const rotationMatrix3 = Cesium.Transforms.rotationMatrixFromPositionVelocity(
|
||||
pointA,
|
||||
normal,
|
||||
Cesium.Ellipsoid.WGS84
|
||||
)
|
||||
const modelMatrix4 = Cesium.Matrix4.fromRotationTranslation(
|
||||
rotationMatrix3,
|
||||
pointA
|
||||
)
|
||||
// 获取getHeadingPitchRoll
|
||||
let m1 = Cesium.Transforms.eastNorthUpToFixedFrame(
|
||||
Cesium.Matrix4.getTranslation(modelMatrix4, new Cesium.Cartesian3()),
|
||||
Cesium.Ellipsoid.WGS84,
|
||||
new Cesium.Matrix4()
|
||||
)
|
||||
// 矩阵相除
|
||||
let m3 = Cesium.Matrix4.multiply(
|
||||
Cesium.Matrix4.inverse(m1, new Cesium.Matrix4()),
|
||||
modelMatrix4,
|
||||
new Cesium.Matrix4()
|
||||
)
|
||||
// 得到旋转矩阵
|
||||
let mat3 = Cesium.Matrix4.getMatrix3(m3, new Cesium.Matrix3())
|
||||
// 计算四元数
|
||||
let q = Cesium.Quaternion.fromRotationMatrix(mat3)
|
||||
// 计算旋转角(弧度)
|
||||
let hpr = Cesium.HeadingPitchRoll.fromQuaternion(q)
|
||||
// hpr.pitch = hpr.pitch + 3.14 / 2 + 3.14;
|
||||
hpr.pitch = 0
|
||||
let orientation = Cesium.Transforms.headingPitchRollQuaternion(pointA, hpr)
|
||||
return { hpr, orientation }
|
||||
}
|
||||
// 删除
|
||||
remove() {
|
||||
this.earth.viewer.entities.remove(this.entity)
|
||||
this.dataSouce.entities.removeAll()
|
||||
this.pointCollection && this.pointCollection.destroy()
|
||||
this.Model && this.earth.viewer.entities.remove(this.Model)
|
||||
this.timer && clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
// 返回照片数量 航点数
|
||||
getInfo() {
|
||||
return {
|
||||
length: this.countLength(),
|
||||
time: this.countTime(),
|
||||
waypoint: this.options.positions.length,
|
||||
photos: this.options.positions.length
|
||||
}
|
||||
}
|
||||
//计算航线得长度
|
||||
countLength() {
|
||||
let totalDistance = 0
|
||||
for (let i = 0; i < this.options.positions.length - 1; i++) {
|
||||
const start = this.options.positions[i]
|
||||
const end = this.options.positions[i + 1]
|
||||
const distance = Cesium.Cartesian3.distance(start, end)
|
||||
totalDistance += distance
|
||||
}
|
||||
return totalDistance.toFixed(2) // 返回保留两位小数的距离
|
||||
}
|
||||
//计算航线时间
|
||||
countTime() {
|
||||
let time = Math.floor(Number(this.countLength())) / this.options.speed
|
||||
let s = Math.floor(time % 60)
|
||||
let m = Math.floor(time / 60)
|
||||
let str = m + '分' + s + '秒'
|
||||
return str
|
||||
}
|
||||
//显示隐藏
|
||||
isShow(status) {
|
||||
if (typeof status === 'boolean') {
|
||||
this.modelShow = status
|
||||
this.dataSouce.show = status
|
||||
let len = this.pointCollection.length
|
||||
for (let i = 0; i < len; ++i) {
|
||||
let p = this.pointCollection.get(i)
|
||||
p.show = status
|
||||
}
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('参数须为Boolean类型!')
|
||||
}
|
||||
}
|
||||
}
|
359
src/Obj/AirLine/pointRoute.js
Normal file
359
src/Obj/AirLine/pointRoute.js
Normal file
@ -0,0 +1,359 @@
|
||||
import FRUSTUN from './frustum.js'
|
||||
import BillordPointLine from './billord_point_line'
|
||||
|
||||
export default class PointRoute {
|
||||
constructor(options = {}, viewer, viewer1) {
|
||||
this.options = { ...options }
|
||||
this.viewer = viewer
|
||||
this.viewer1 = viewer1
|
||||
this.entity = null
|
||||
this.frustum = null
|
||||
this.billordPointLineMaps = []
|
||||
this.index = 0
|
||||
this.positions = []
|
||||
PointRoute.setDefaultValue(this)
|
||||
this.create()
|
||||
}
|
||||
static setDefaultValue(that) {
|
||||
that.options.positions = that.options.positions || []
|
||||
that.options.show = that.options.show || true
|
||||
that.options.color = that.options.color || '#00d590'
|
||||
that.options.height = that.options.height || 500
|
||||
that.options.speed = that.options.speed || 1
|
||||
that.options.frustumShow = that.options.frustumShow ?? true
|
||||
that.options.saveFun = that.options.saveFun || null
|
||||
that.options.selectFun = that.options.selectFun || null
|
||||
that.options.keyboard = that.options.keyboard ?? true
|
||||
that.options.normalHeight = that.options.normalHeight || 100
|
||||
that.options.airHeight = that.options.airHeight || 100
|
||||
}
|
||||
create() {
|
||||
if (this.options.positions.length < 2) {
|
||||
return
|
||||
}
|
||||
let that = this
|
||||
let { frustumShow } = that.options
|
||||
this.entity = this.viewer.entities.add({
|
||||
show: this.options.show,
|
||||
polyline: {
|
||||
positions: new Cesium.CallbackProperty(() => {
|
||||
let positions = []
|
||||
for (let i = 0; i < this.billordPointLineMaps.length; i++) {
|
||||
const element = this.billordPointLineMaps[i]
|
||||
positions.push(element.billboardEntity.position.getValue())
|
||||
}
|
||||
return positions
|
||||
}, false),
|
||||
width: 3,
|
||||
material: Cesium.Color.fromCssColorString(this.options.color)
|
||||
}
|
||||
})
|
||||
// 创建点、线、billbord
|
||||
for (let i = 0; i < this.options.positions.length; i++) {
|
||||
const element = this.options.positions[i]
|
||||
// console.log("elementelementelement", element);
|
||||
if (frustumShow && i == this.index) {
|
||||
this.frustum = new FRUSTUN(
|
||||
{
|
||||
position: element,
|
||||
show: false,
|
||||
arr: this.options.positions,
|
||||
index: i,
|
||||
normalHeight: this.options.normalHeight
|
||||
},
|
||||
this.viewer,
|
||||
this.viewer1
|
||||
)
|
||||
}
|
||||
let op = new BillordPointLine(
|
||||
{
|
||||
positions: element,
|
||||
index: i + 1,
|
||||
saveFun: that.options.saveFun,
|
||||
selectFun: that.options.selectFun,
|
||||
keyboard: that.options.keyboard,
|
||||
updateFrustumFun: that.updateFrustumPosition,
|
||||
normalHeight: that.options.normalHeight,
|
||||
frustum: that.frustum,
|
||||
airHeight: that.options.airHeight
|
||||
},
|
||||
this.viewer
|
||||
)
|
||||
this.billordPointLineMaps.push(op)
|
||||
}
|
||||
this.onKey()
|
||||
}
|
||||
get show() {
|
||||
return this.options.show
|
||||
}
|
||||
set show(bool) {
|
||||
if (typeof bool === 'boolean') {
|
||||
this.frustum.currentFrustumOutline.show = bool
|
||||
this.billordPointLineMaps.forEach(item => {
|
||||
item.show = bool
|
||||
})
|
||||
this.entity.show = bool
|
||||
}
|
||||
}
|
||||
// 监听键盘事件
|
||||
onKey() {
|
||||
let that = this
|
||||
document.addEventListener('keydown', function(event) {
|
||||
switch (event.key) {
|
||||
case 'ArrowUp':
|
||||
that.index += 1
|
||||
that.updateFrustum(true)
|
||||
break
|
||||
case 'ArrowDown':
|
||||
that.index -= 1
|
||||
that.updateFrustum(false)
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
// 更新frustum
|
||||
updateFrustum(flag) {
|
||||
console.log(this.index)
|
||||
let obj
|
||||
if (this.index > this.options.positions.length - 1 || this.index < 0) {
|
||||
let str = this.index > 0 ? '已选中最后一个航点' : '已选中第一个航点'
|
||||
alert(str)
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < this.billordPointLineMaps.length; i++) {
|
||||
const element = this.billordPointLineMaps[i]
|
||||
const hpr = null
|
||||
if (i == this.index) {
|
||||
let position = element.billboardEntity.position.getValue()
|
||||
if (this.index !== 0) {
|
||||
obj = this.direction(
|
||||
this.billordPointLineMaps[
|
||||
i - 1
|
||||
].billboardEntity.position.getValue(),
|
||||
element.billboardEntity.position.getValue()
|
||||
)
|
||||
hpr = obj.hpr
|
||||
}
|
||||
if (this.index == 0) {
|
||||
obj = this.direction(
|
||||
this.billordPointLineMaps[0].billboardEntity.position.getValue(),
|
||||
this.billordPointLineMaps[1].billboardEntity.position.getValue()
|
||||
)
|
||||
hpr = obj.hpr
|
||||
}
|
||||
if (hpr) {
|
||||
this.frustum.updateFrustumHPR(
|
||||
hpr.heading,
|
||||
this.frustum.pitch,
|
||||
hpr.roll
|
||||
)
|
||||
}
|
||||
if (position) {
|
||||
this.frustum.updateFrustumPosition('update', position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cartesian3Towgs84(cartesian) {
|
||||
var ellipsoid = this.viewer.scene.globe.ellipsoid
|
||||
var cartesian3 = new Cesium.Cartesian3(
|
||||
cartesian.x,
|
||||
cartesian.y,
|
||||
cartesian.z
|
||||
)
|
||||
var cartographic = ellipsoid.cartesianToCartographic(cartesian3)
|
||||
var lat = Cesium.Math.toDegrees(cartographic.latitude)
|
||||
var lng = Cesium.Math.toDegrees(cartographic.longitude)
|
||||
var alt = cartographic.height < 0 ? 0 : cartographic.height
|
||||
return {
|
||||
lng: lng,
|
||||
lat: lat,
|
||||
alt: alt
|
||||
}
|
||||
}
|
||||
// 计算一个到另一个点的方向
|
||||
direction(pointA, pointB) {
|
||||
//向量AB
|
||||
const vector2 = Cesium.Cartesian3.subtract(
|
||||
pointA,
|
||||
pointB,
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
//归一化
|
||||
const normal = Cesium.Cartesian3.normalize(vector2, new Cesium.Cartesian3())
|
||||
//旋转矩阵 rotationMatrixFromPositionVelocity源码中有,并未出现在cesiumAPI中
|
||||
const rotationMatrix3 = Cesium.Transforms.rotationMatrixFromPositionVelocity(
|
||||
pointA,
|
||||
normal,
|
||||
Cesium.Ellipsoid.WGS84
|
||||
)
|
||||
const modelMatrix4 = Cesium.Matrix4.fromRotationTranslation(
|
||||
rotationMatrix3,
|
||||
pointA
|
||||
)
|
||||
// 获取getHeadingPitchRoll
|
||||
let m1 = Cesium.Transforms.eastNorthUpToFixedFrame(
|
||||
Cesium.Matrix4.getTranslation(modelMatrix4, new Cesium.Cartesian3()),
|
||||
Cesium.Ellipsoid.WGS84,
|
||||
new Cesium.Matrix4()
|
||||
)
|
||||
// 矩阵相除
|
||||
let m3 = Cesium.Matrix4.multiply(
|
||||
Cesium.Matrix4.inverse(m1, new Cesium.Matrix4()),
|
||||
modelMatrix4,
|
||||
new Cesium.Matrix4()
|
||||
)
|
||||
// 得到旋转矩阵
|
||||
let mat3 = Cesium.Matrix4.getMatrix3(m3, new Cesium.Matrix3())
|
||||
// 计算四元数
|
||||
let q = Cesium.Quaternion.fromRotationMatrix(mat3)
|
||||
// 计算旋转角(弧度)
|
||||
let hpr = Cesium.HeadingPitchRoll.fromQuaternion(q)
|
||||
// hpr.pitch = hpr.pitch + 3.14 / 2 + 3.14;
|
||||
hpr.pitch = 90
|
||||
let orientation = Cesium.Transforms.headingPitchRollQuaternion(pointA, hpr)
|
||||
return { hpr, orientation }
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {index} 索引
|
||||
*/
|
||||
// 删除航点
|
||||
delPosition(index) {
|
||||
this.options.positions.splice(index, 1)
|
||||
// this.options.positions = this.options.positions.filter((item, index) => index !== i);
|
||||
this.remove()
|
||||
this.create()
|
||||
}
|
||||
// 获取最新的positions
|
||||
getNewPositions() {
|
||||
let positions = []
|
||||
for (let i = 0; i < this.billordPointLineMaps.length; i++) {
|
||||
const element = this.billordPointLineMaps[i]
|
||||
let position = this.cartesian3Towgs84(
|
||||
element.billboardEntity.position.getValue()
|
||||
)
|
||||
positions.push(position)
|
||||
}
|
||||
return positions
|
||||
}
|
||||
// 删除
|
||||
remove() {
|
||||
this.billordPointLineMaps.forEach((item, i) => {
|
||||
item.remove()
|
||||
})
|
||||
if (this.frustum) {
|
||||
this.frustum.remove()
|
||||
}
|
||||
this.viewer.entities.remove(this.entity)
|
||||
this.billordPointLineMaps = []
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {String} type
|
||||
* @param {Number} index
|
||||
* @param {Array} position
|
||||
*/
|
||||
// 新增航点 (before,after,end)
|
||||
addPoint(positions) {
|
||||
this.options.positions = positions
|
||||
this.remove()
|
||||
this.create()
|
||||
}
|
||||
// 根据选中的点更新视锥的位置
|
||||
updateFrustumPosition(index) {
|
||||
if (!this.billordPointLineMaps || this.billordPointLineMaps.length === 0)
|
||||
return
|
||||
if (this.frustum) {
|
||||
this.frustum.show = true
|
||||
}
|
||||
let current = this.billordPointLineMaps[
|
||||
index
|
||||
].billboardEntity.position.getValue()
|
||||
if (index !== 0) {
|
||||
let obj
|
||||
let after =
|
||||
index === this.billordPointLineMaps.length - 1
|
||||
? this.billordPointLineMaps[
|
||||
index - 1
|
||||
].billboardEntity.position.getValue() // 获取前一个位置
|
||||
: this.billordPointLineMaps[
|
||||
index + 1
|
||||
].billboardEntity.position.getValue() // 获取下一个位置
|
||||
obj = this.direction(
|
||||
index === this.billordPointLineMaps.length - 1 ? after : current,
|
||||
index === this.billordPointLineMaps.length - 1 ? current : after
|
||||
)
|
||||
let { hpr } = obj
|
||||
this.frustum.updateFrustumHPR(
|
||||
hpr.heading,
|
||||
Cesium.Math.toRadians(this.frustum.pitch),
|
||||
hpr.roll
|
||||
)
|
||||
} else {
|
||||
let obj
|
||||
let after = this.billordPointLineMaps[1].billboardEntity.position.getValue()
|
||||
obj = this.direction(current, after)
|
||||
let { hpr } = obj
|
||||
this.frustum.updateFrustumHPR(
|
||||
hpr.heading,
|
||||
Cesium.Math.toRadians(this.frustum.pitch),
|
||||
hpr.roll
|
||||
)
|
||||
}
|
||||
if (current) {
|
||||
this.frustum.updateFrustumPosition('update', current)
|
||||
}
|
||||
let position = this.cartesian3Towgs84(current)
|
||||
this.billordPointLineMaps.forEach(item => {
|
||||
item.billboardEntity.label.show = false // 先将所有元素的 label.show 设置为 false
|
||||
})
|
||||
const targetItem = this.billordPointLineMaps.find(
|
||||
item => item.billboardEntity.index == index + 1
|
||||
)
|
||||
if (targetItem) {
|
||||
targetItem.billboardEntity.label.show = true // 然后找到匹配的 index 设置为 true
|
||||
}
|
||||
return position
|
||||
}
|
||||
flyTo() {
|
||||
let positionArray = []
|
||||
for (let i = 0; i < this.options.positions.length; i++) {
|
||||
let a = Cesium.Cartesian3.fromDegrees(
|
||||
this.options.positions[i].lng,
|
||||
this.options.positions[i].lat,
|
||||
this.options.positions[i].alt + this.options.height
|
||||
)
|
||||
positionArray.push(a.x, a.y, a.z)
|
||||
}
|
||||
let BoundingSphere = Cesium.BoundingSphere.fromVertices(positionArray)
|
||||
this.viewer.camera.flyToBoundingSphere(BoundingSphere, {
|
||||
offset: {
|
||||
heading: Cesium.Math.toRadians(0.0),
|
||||
pitch: Cesium.Math.toRadians(-80.0),
|
||||
roll: Cesium.Math.toRadians(0.0)
|
||||
}
|
||||
})
|
||||
}
|
||||
//计算航线的长度
|
||||
countLength() {
|
||||
if (this.options.positions.length < 2) {
|
||||
return 0
|
||||
} else {
|
||||
let lineString = []
|
||||
this.options.positions.forEach(item => {
|
||||
lineString.push([item.lng, item.lat])
|
||||
})
|
||||
var line = turf.lineString(lineString)
|
||||
return (turf.length(line) * 1000).toFixed(2)
|
||||
}
|
||||
}
|
||||
//计算航线时间
|
||||
countTime() {
|
||||
let time = Math.floor(Number(this.countLength())) / this.options.speed
|
||||
let s = Math.floor(time % 60)
|
||||
let m = Math.floor(time / 60)
|
||||
let str = m + '分' + s + '秒'
|
||||
return str
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user