360 lines
11 KiB
JavaScript
360 lines
11 KiB
JavaScript
|
|
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
|
|||
|
|
}
|
|||
|
|
}
|