import EventBinding from '../../Element/Dialog/eventBinding'; import Base from "../index"; import MouseEvent from '../../../Event/index' import Controller from "../../../Controller/index"; import MouseTip from '../../../MouseTip' import { setActiveViewer, closeRotateAround } from '../../../Global/global' class TrajectoryMotionObject extends Base { #lineEdit = false /** * @constructor * @description 轨迹运动 * @param options {object} * @param options.name {string} 名称 * @param options.speed=1 {number} 运行速度(米/每秒) * @param options.delay=0 {number} 运动延迟时间(毫秒) * @param options.loop=true {boolean} 循环 * @param options.height {number} 起始点高度 * @param options.ground=false {boolean} 贴地 * @param options.state=true {boolean} 模型运动 * @param options.routeDirection=true {boolean} 路径方向 * @param options.viewFollow=false {boolean} 视角跟随 * @param options.line {object} 路径参数 * @param options.line.show=true {boolean} 路径显隐 * @param options.line.smooth=false {boolean} 路径圆滑 * @param options.line.noseToTail=false {boolean} 路径收尾相联 * @param {Array.} options.line.positions 经纬度和高度的列表,值交替 [{lon,lat,alt},...] * @param _Dialog {object} 弹框事件 * @param _Dialog.confirmCallBack {function} 弹框确认时的回调 * */ constructor(sdk, options = {}, _Dialog = {}) { super(sdk, options); this.options.name = options.name || '' this.options.show = (options.show || options.show === false) ? options.show : true this.options.speed = (options.speed || options.speed === 0) ? options.speed : 1 this.options.totalTime = options.totalTime if(options.totalTime || options.totalTime===0) { this.totalTime = options.totalTime } this.options.delay = options.delay || 0 this.options.loop = options.loop || options.loop === false ? options.loop : true this.options.line = options.line = options.line || {} this.options.line.positions = options.line.positions || [] this.options.height = (options.height || options.height === 0) ? options.height : (this.options.line.positions[0] ? this.options.line.positions[0].alt : 0) this.options.line.show = options.line.show || options.line.show === false ? options.line.show : true this.options.line.smooth = options.line.smooth ? options.line.smooth : false this.options.line.noseToTail = options.line.noseToTail ? options.line.noseToTail : false this.positions_smooth = [] this.options.ground = options.ground || false this.options.state = (options.state || options.state === false) ? options.state : true this.options.routeDirection = (options.routeDirection || options.routeDirection === false) ? options.routeDirection : true this.keyPoints = [] this.realTimePositions = [] this._elms = {}; this.Dialog = _Dialog this.realTimeRouteArray = [] // this._initial = {} this._current = { heading: 0, pitch: 0, roll: 0 } // this.options.firstPerson = false this.distance // this.addModel() if (this.options.line.positions.length < 2) { this._error = '最少需要两个坐标!' console.warn(this._error) window.ELEMENT && window.ELEMENT.Message({ message: this._error, type: 'warning', duration: 1500 }); } else { this.ControllerObject = new Controller(this.sdk) this._EventBinding = new EventBinding() TrajectoryMotionObject.addLine(this) this.firstPersonView = false this.options.viewFollow = false } // animateUpdate() // function animateUpdate() { // requestAnimationFrame(animateUpdate); // TWEEN.update(); // } } get type() { return 'TrajectoryMotionObject' } get show() { return this.options.show } set show(v) { if (typeof v === "boolean") { this.options.show = v if (v) { this.line.show = this.lineShow for (let i = 0; i < this.keyPoints.length; i++) { this.keyPoints[i].show = this.keyPointShow } } else { this.line.show = v for (let i = 0; i < this.keyPoints.length; i++) { this.keyPoints[i].show = v } } if (this._DialogObject && this._DialogObject.showBtn) { this._DialogObject.showBtn.checked = v } } else { console.error("参数必须为boolean") } } get height() { return this.options.height } set height(v) { this.options.height = v if (this.line) { if (this.ground) { this.line.polyline.clampToGround = true for (let i = 0; i < this.keyPoints.length; i++) { this.sdk.viewer.scene.clampToHeightMostDetailed([new Cesium.Cartesian3.fromDegrees(this.options.line.positions[i].lng, this.options.line.positions[i].lat)]).then((result) => { this.keyPoints[i].position = result[0] }) } } else { let dvalue = this.options.height - this.options.line.positions[0].alt this.line.polyline.clampToGround = false for (let i = 0; i < this.keyPoints.length; i++) { this.options.line.positions[i].alt += dvalue this.keyPoints[i].position = Cesium.Cartesian3.fromDegrees(this.options.line.positions[i].lng, this.options.line.positions[i].lat, this.options.line.positions[i].alt) } } } let positions_smooth = this._renewLine(this.options.line.positions) this.line.polyline.positions = positions_smooth this._elms.height && this._elms.height.forEach((item) => { item.value = v }) } get ground() { return this.options.ground } set ground(v) { this.lineEdit = false this.options.ground = v this.realTimeLine.polyline.clampToGround = v this.height = this.options.height this._elms.ground && this._elms.ground.forEach((item) => { item.checked = v }) } get speed() { return this.options.speed } set speed(v) { if (v <= 0) { v = 0.01 } this.options.speed = v if (this.distance || this.distance === 0) { this.options.totalTime = (this.distance*1000) / this.options.speed // this.TweenAnimate._object.distance/this.TweenAnimate._valuesEnd.distance if(this.TweenAnimate && this.state) { this.TweenAnimate && (this.setMovePositionByDistance(this.TweenAnimate._object.distance)) } this._elms.speed && this._elms.speed.forEach((item) => { item.value = v }) this._elms.totalTime && this._elms.totalTime.forEach((item) => { item.value = this.options.totalTime }) } } get totalTime() { return this.options.totalTime } set totalTime(v) { this.options.totalTime = v if (this.distance || this.distance === 0) { this.options.speed = (this.distance*1000) / this.options.totalTime this.TweenAnimate && (this.setMovePositionByDistance(this.TweenAnimate._object.distance)) this._elms.totalTime && this._elms.totalTime.forEach((item) => { item.value = v }) this._elms.speed && this._elms.speed.forEach((item) => { item.value = this.options.speed }) } } get smooth() { return this.options.line.smooth } set smooth(v) { this.lineEdit = false this.options.line.smooth = v let positions = this._renewLine(this.options.line.positions) this.line.polyline.positions = positions this.modelMove(positions) this._elms.smooth && this._elms.smooth.forEach((item) => { item.checked = v }) } get delay() { return this.options.delay } set delay(v) { this.options.delay = v if (this.TweenAnimate) { this.TweenAnimate.delay(this.delay) } this._elms.delay && this._elms.delay.forEach((item) => { item.value = v }) } get state() { return this.options.state } set state(v) { this.options.state = v if (this.editObj) { this.editObj.destroy() this.editObj = null } if (this.TweenAnimate) { if (v) { this.speed = this.speed } else { this.TweenAnimate.pause() } } else { if (v) { let positions = this._renewLine(this.options.line.positions) this.modelMove(positions) } } this._elms.state && this._elms.state.forEach((item) => { item.checked = v }) } get noseToTail() { return this.options.line.noseToTail } set noseToTail(v) { this.lineEdit = false this.options.line.noseToTail = v let fromDegreesArrayHeights = [] for (let i = 0; i < this.options.line.positions.length; i++) { fromDegreesArrayHeights.push(this.options.line.positions[i].lng, this.options.line.positions[i].lat, this.options.line.positions[i].alt) } let nosmooth = Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArrayHeights) if (this.line) { let positions_smooth = this._renewLine(this.options.line.positions) this.line.polyline.positions = positions_smooth this.modelMove(positions_smooth) } this._elms.noseToTail && this._elms.noseToTail.forEach((item) => { item.checked = v }) } get lineShow() { return this.options.line.show } set lineShow(v) { if (v) { this.realTimeRoute = false } this.options.line.show = v if (this.line && this.show) { this.line.show = v } this._elms.lineShow && this._elms.lineShow.forEach((item) => { item.checked = v }) } get realTimeRoute() { return this.options.realTimeRoute } set realTimeRoute(v) { if (v) { this.lineShow = false this.keyPointShow = false } this.options.realTimeRoute = v if (this.realTimeLine && this.show) { this.realTimeLine.show = v } this._elms.realTimeRoute && this._elms.realTimeRoute.forEach((item) => { item.checked = v }) } get keyPointShow() { return this.options.line.keyPoint } set keyPointShow(v) { this.options.line.keyPoint = v for (let i = 0; i < this.keyPoints.length; i++) { if (this.show) { this.keyPoints[i].show = v } } this._elms.keyPointShow && this._elms.keyPointShow.forEach((item) => { item.checked = v }) if (!v && this.lineEdit) { // 关闭线编辑 this.#lineEdit = v YJ.Measure.SetMeasureStatus(false) this.event && this.event.destroy() this.ControllerObject && this.ControllerObject.destroy() this.tip && this.tip.destroy() this.tip = null this._elms.lineEdit && this._elms.lineEdit.forEach((item) => { item.checked = v }) } } get lineEdit() { return this.#lineEdit } set lineEdit(v) { let linePositions = [] let computePositionsSmooth = (positions) => { linePositions = this._renewLine(positions) this.modelMove(linePositions) } if (v) { this.viewFollow = false if (YJ.Measure.GetMeasureStatus()) { console.warn('上一次测量未结束') this.lineEdit = false return } else { this.ground = false this.smooth = false this.state = false YJ.Measure.SetMeasureStatus(true) this.tip = new MouseTip('请选择一个顶点,右键取消', this.sdk) this.event = new MouseEvent(this.sdk) let selectPoint computePositionsSmooth([...this.options.line.positions]) this.event.mouse_left((movement, cartesian) => { let pick = this.sdk.viewer.scene.pick(movement.position); if (pick && pick.id && pick.id.name && pick.id.name === 'node-secondary-edit-point') { for (let i = 0; i < this.keyPoints.length; i++) { if (this.keyPoints[i].id === pick.id.id) { // this.keyPoints[i].show = false selectPoint = pick.id this.ControllerObject.position = this.options.line.positions[selectPoint.index] this.ControllerObject.editTranslational() this.tip && this.tip.destroy() this.tip = null this.ControllerObject.controllerCallBack = (params) => { // console.log('params', params) this.options.line.positions[selectPoint.index] = params.position selectPoint.position = Cesium.Cartesian3.fromDegrees(params.position.lng, params.position.lat, params.position.alt) computePositionsSmooth([...this.options.line.positions]) } break } } // originalPosition = this.cartesian3Towgs84(cartesian, this.sdk.viewer) } }) this.event.mouse_right((movement, cartesian) => { // if (selectPoint) { // let positions = [...this.options.line.positions] // selectPoint.position = Cesium.Cartesian3.fromDegrees(positions[selectPoint.index].lng, positions[selectPoint.index].lat, positions[selectPoint.index].alt) // computePositionsSmooth(positions) // } this.keyPointShow = false YJ.Measure.SetMeasureStatus(false) this.event.destroy() this.tip && this.tip.destroy() this.tip = null this.ControllerObject.destroy() }) this.event.mouse_move((movement, cartesian) => { // if (selectPoint) { // let positions = [...this.options.line.positions] // positions[selectPoint.index] = this.cartesian3Towgs84(cartesian, this.sdk.viewer) // selectPoint.position = cartesian // computePositionsSmooth(positions) // // that.options.positions[selectPoint.index] = that.cartesian3Towgs84(cartesian, that.sdk.viewer) // // let positions = that.options.positions // // let fromDegreesArray = [] // // for (let i = 0; i < positions.length; i++) { // // fromDegreesArray.push(positions[i].lng, positions[i].lat, positions[i].alt) // // } // // newpositions = Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray) // // if (that.options.positions.length === 1) { // // that.label.position = [that.options.positions[0].lng, that.options.positions[0].lat, that.options.height] // // } // } this.tip && this.tip.setPosition( cartesian, movement.endPosition.x, movement.endPosition.y ) }) this.line.polyline.positions = new Cesium.CallbackProperty(function () { return linePositions }, false) } // 显示关键点 this.keyPointShow = v } else { if (this.lineEdit) { YJ.Measure.SetMeasureStatus(false) this.event.destroy() this.tip && this.tip.destroy() this.tip = null } // 隐藏关键点 this.keyPointShow = v this.ControllerObject.destroy() } this.#lineEdit = v this._elms.lineEdit && this._elms.lineEdit.forEach((item) => { item.checked = v }) } get routeDirection() { return this.options.routeDirection } set routeDirection(v) { this.options.routeDirection = v this._elms.routeDirection && this._elms.routeDirection.forEach((item) => { item.checked = v }) } get loop() { return this.options.loop } set loop(v) { this.options.loop = v if (v) { this.TweenAnimate.repeat(Infinity) } else { this.TweenAnimate.repeat() } this._elms.loop && this._elms.loop.forEach((item) => { item.checked = v }) } get firstPersonView() { return this.options.firstPersonView } set firstPersonView(v) { // this.state = true this.sdk.viewer._firstPersonView = v this.options.firstPersonView = v if (this.options.firstPersonView) { if (this._DialogObject && this._DialogObject._element.content) { let e_firstPerson = this._DialogObject._element.content.querySelectorAll("button[name='firstPerson']") e_firstPerson[0].className = 'btn is-active' e_firstPerson[1].className = 'btn' } if (this.sdk.viewer.trackedEntity) { this.sdk.viewer.entities.remove(this.sdk.viewer.trackedEntity) this.sdk.viewer.trackedEntity = null } } else { if (this._DialogObject && this._DialogObject._element.content) { let e_firstPerson = this._DialogObject._element.content.querySelectorAll("button[name='firstPerson']") if (e_firstPerson[0] && e_firstPerson[1]) { e_firstPerson[0].className = 'btn' e_firstPerson[1].className = 'btn is-active' } } if (this.viewFollow) { if (this.sdk.viewer.trackedEntity) { this.sdk.viewer.entities.remove(this.sdk.viewer.trackedEntity) } let pointEntity = this.sdk.viewer.entities.add({ // show: false, position: this.positions_smooth[0], // position of the point point: { color: Cesium.Color.RED.withAlpha(0), // color of the point pixelSize: 0 } }); this.sdk.viewer.trackedEntity = pointEntity; } } } get viewFollow() { return this.options.viewFollow } set viewFollow(v) { this.options.viewFollow = v if (!this.options.viewFollow) { this.firstPersonView = false } else { this.lineEdit = false } if (this.options.firstPersonView) { if (this.sdk.viewer.trackedEntity) { this.sdk.viewer.entities.remove(this.sdk.viewer.trackedEntity) this.sdk.viewer.trackedEntity = null } if (this._DialogObject && this._DialogObject._element.content) { let e_firstPerson = this._DialogObject._element.content.querySelectorAll("button[name='firstPerson']") if (e_firstPerson[0] && e_firstPerson[1]) { e_firstPerson[0].className = 'btn' e_firstPerson[1].className = 'btn is-active' } } } else { if (this.sdk.viewer.trackedEntity) { this.sdk.viewer.entities.remove(this.sdk.viewer.trackedEntity) this.sdk.viewer.trackedEntity = null } if (v) { let pointEntity = this.sdk.viewer.entities.add({ // show: false, position: this.current.position, // position of the point point: { color: Cesium.Color.RED.withAlpha(0), // color of the point pixelSize: 0 } }); this.sdk.viewer.trackedEntity = pointEntity; } } this._elms.viewFollow && this._elms.viewFollow.forEach((item) => { item.checked = v }) } moveCallBack(that) { // if((that.lng || that.lng == 0) && (that.lat || that.lat == 0) && (that.alt || that.lat == 0)) { // this._initial.position = { // lng: that.lng, // lat: that.lat, // alt: that.alt, // } // } // if(that.rotateX || that.rotateX == 0 ) { // this._initial.pitch = that.rotateX // } // if(that.rotateY || that.rotateY == 0) { // this._initial.roll = that.rotateY // } // if(that.rotateZ || that.rotateZ == 0) { // this._initial.heading = that.rotateZ // } this.setPosition = that.setPosition.bind(that) } // get moveCallBack() { // return this.options.moveCallBack // } // set moveCallBack(v) { // this.options.moveCallBack = v // } get current() { return this._current } set current(v) { this._current = v let pos = this.cartesian3Towgs84(this._current.position, this.sdk.viewer) this.setPosition && this.setPosition({ ...this._current, position: { ...pos } }) } // 创建路径 static addLine(that) { let positions_smooth = that._renewLine(that.options.line.positions) that.current.position = positions_smooth[0] that.line = that.sdk.viewer.entities.add({ id: that.options.id + '-2', show: that.options.show ? that.options.line.show : false, polyline: { positions: positions_smooth, width: 2, clampToGround: that.ground, material: Cesium.Color.fromCssColorString('#ffffff'), zIndex: that.sdk._entityZIndex }, }) that.realTimeLine = that.sdk.viewer.entities.add({ id: that.options.id + '-3', show: that.options.realTimeRoute ? that.options.realTimeRoute : false, polyline: { positions: new Cesium.CallbackProperty(function () { return that.realTimePositions }, false), width: 2, clampToGround: that.ground, zIndex: that.sdk._entityZIndex, material: Cesium.Color.fromCssColorString('#ff0000') }, }) that.sdk._entityZIndex++ let event = new MouseEvent(that.sdk) event.mouse_right((movement, cartesian) => { that.viewFollow = false }) TrajectoryMotionObject.addKeyPoint(that) that.noseToTail = that.options.line.noseToTail that.smooth = that.options.line.smooth } // 创建模型 static addModel(that) { // that.model = that.sdk.viewer.scene.primitives.add( // Cesium.Model.fromGltf({ // id: that.options.id, // url: that.options.model.url, // show: that.options.show ? that.options.model.show : false, // scale: that.options.model.scale, // // minimumPixelSize: that.options.model.pixelSize, // // maximumScale: 100000, // // allowPicking: false // }) // ); // let cartographic = Cesium.Cartographic.fromDegrees(103, 65, 100); // let position = that.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic); // // 设置模型的旋转角度,使其水平放置于地面 // let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(that.positions_smooth[0]) // that.model.modelMatrix = matrix // that.model.position = that.positions_smooth[0] // // 模型大小比例 // // Cesium.Matrix4.multiplyByScale(matrix, new Cesium.Cartesian3(0.1, 0.1, 0.1), this.entity.modelMatrix) // let positions = that.options.line.positions // let fromDegreesArrayHeights = [] // for (let i = 0; i < positions.length; i++) { // fromDegreesArrayHeights.push(positions[i].lng, positions[i].lat, positions[i].alt) // } // let pos = that.smooth ? that.positions_smooth : Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArrayHeights) // that.modelMove(pos) // that.model.readyPromise.then(() => { // that.modelAnimate = that.options.model.animate // }) // that.entity = that.model } // 创建关键点 static async addKeyPoint(that) { for (let i = 0; i < that.options.line.positions.length; i++) { let height = await that.getClampToHeight(that.options.line.positions[i]) let result = await Cesium.Cartesian3.fromDegrees(that.options.line.positions[i].lng, that.options.line.positions[i].lat, height) let entity = that.sdk.viewer.entities.add({ name: 'node-secondary-edit-point', index: i, show: that.options.line.keyPoint || false, position: that.ground ? result : Cesium.Cartesian3.fromDegrees(that.options.line.positions[i].lng, that.options.line.positions[i].lat, that.options.line.positions[i].alt), billboard: { image: that.getSourceRootPath() + '/img/point.png', width: 15, height: 15, disableDepthTestDistance: Number.POSITIVE_INFINITY, color: Cesium.Color.WHITE.withAlpha(0.99) }, }) that.keyPoints.push(entity) } } // 模型移动 async modelMove(positions, option = { time: 0 }) { let _this = this let time = option.time || 0 let startDistance = option.distance || 0 let viewer = this.sdk.viewer this.removeModelAnimate() let lineString = [] for (let i = 0; i < positions.length; i++) { let position = this.cartesian3Towgs84(positions[i], viewer) lineString.push([position.lng, position.lat, position.alt]) } // console.log(lineString) let line = turf.lineString(lineString); this.distance = turf.length(line, { units: 'kilometers' }); if(!this.totalTime) { this.totalTime = (this.distance*1000) / this.options.speed // 总耗时(秒) } let totalTime = this.totalTime if (time) { if (time > totalTime) { time = totalTime } startDistance = (time / totalTime) * this.distance } else { // this._initial.position && (this._current.position = this.positions_smooth[0]) // if(this._initial.pitch || this._initial.pitch === 0) { // this._current.pitch = this._initial.pitch // } // if(this._initial.roll || this._initial.roll === 0) { // this._current.roll = this._initial.roll // } // if(this._initial.heading || this._initial.heading === 0) { // this._current.heading = this._initial.heading // } } let lastDistance = 0 let motionArray = [] let HeadingPitchRoll let HeadingPitchRoll2 let previous = {} let m = 0 let modelArray = [] for (let [key, value] of this.sdk.entityMap) { if (value.type && value.type === 'glb') { modelArray.push(value.entity) } } let first = true this.TweenAnimate = new TWEEN.Tween({ distance: startDistance }).to({ distance: this.distance }, (totalTime - time)*1000). delay(this.delay).easing(TWEEN.Easing.Linear.None).repeat(this.options.loop ? Infinity : 0).onRepeat(() => { if (time) { this.modelMove(positions) } }).onUpdate(async (r, a) => { if (this.TweenAnimate._duration == Infinity) { return } m++ if (!this.sdk.viewer) { this.removeModelAnimate() return } setPosition(r.distance) }).onEveryStart(() => { this.realTimeRouteArray = [] }).onComplete((d) => { this.state = false this.removeModelAnimate() // let runtimeAnimation = this.model._activeAnimations._runtimeAnimations // // let animations = await this.model.readyPromise // for (let i = runtimeAnimation.length - 1; i >= 0; i--) { // switch (runtimeAnimation[i].name) { // case '跑': // this.model.activeAnimations.remove(runtimeAnimation[i]) // break; // default: // } // } }); if (this.state) { this.TweenAnimate.start() } else { setPosition(startDistance) } async function setPosition(distance) { let start = 0; let stop = distance; let coordinates let sliced = line if (stop) { let sliced = await turf.lineSliceAlong(line, start, stop, { units: 'kilometers' }); // _this.realTimeRouteArray = sliced+ coordinates = [...sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1]] } else { coordinates = [...line.geometry.coordinates[0]] } let position let positionCamera if (_this.ground) { // if (viewer.terrainProvider.availability) { // let result = await new Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, [Cesium.Cartographic.fromDegrees(coordinates[0], coordinates[1])]); // position = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], result[0].height) // positionCamera = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], result[0].height + 1) // } // else { // position = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1]) // positionCamera = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], 1) // } let result = await _this.sdk.viewer.scene.clampToHeight(new Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1]), modelArray) position = result if (!position) { position = new Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1]) } let pos3 = _this.cartesian3Towgs84(position, viewer); let height2 = 0 try { let position2 = await Cesium.sampleTerrainMostDetailed( _this.sdk.viewer.scene.terrainProvider, [Cesium.Cartographic.fromDegrees(pos3.lng, pos3.lat)] ) height2 = position2[0].height } catch (error) { height2 = 0 } if (pos3.alt < height2) { pos3.alt = height2 } pos3.alt = Number(pos3.alt.toFixed(1)) position = Cesium.Cartesian3.fromDegrees(pos3.lng, pos3.lat, pos3.alt) positionCamera = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], _this.cartesian3Towgs84(position, _this.sdk.viewer).alt + 1) let fromDegreesArray = [] for (let i = 0; i < sliced.geometry.coordinates.length; i++) { fromDegreesArray.push(sliced.geometry.coordinates[i][0], sliced.geometry.coordinates[i][1]) } _this.realTimePositions = Cesium.Cartesian3.fromDegreesArray(fromDegreesArray) // _this.realTimeLine.polyline.positions = } else { let cartesian3 = _this.spline.evaluate(distance / _this.distance) coordinates = _this.cartesian3Towgs84(cartesian3, viewer); position = Cesium.Cartesian3.fromDegrees(coordinates.lng, coordinates.lat, coordinates.alt) positionCamera = Cesium.Cartesian3.fromDegrees(coordinates.lng, coordinates.lat, coordinates.alt + 1) let positions_smooth = [] for (let i = 0; i <= 100; i++) { if ((i / 100) > (distance / _this.distance)) { break } let cartesian3 = _this.spline.evaluate(i / 100); positions_smooth.push(cartesian3); } positions_smooth.push(cartesian3) _this.realTimePositions = positions_smooth } HeadingPitchRoll = getHeadingPitchRoll(_this.current.position, position) if (previous && previous.position) { HeadingPitchRoll2 = getHeadingPitchRoll(previous.position, position) HeadingPitchRoll.pitch = HeadingPitchRoll2.pitch } previous.position = _this.current.position let modeHeadingPitchRoll = Cesium.HeadingPitchRoll.fromDegrees(_this.current.heading, _this.current.pitch, _this.current.roll) let heading = 0 let pitch = 0 let roll = 0 if (_this.options.routeDirection) { heading = (HeadingPitchRoll.heading - modeHeadingPitchRoll.heading) * (180 / Math.PI) - 90 + _this.current.heading pitch = HeadingPitchRoll.pitch * (180 / Math.PI) } else { heading = _this.current.heading pitch = _this.current.pitch } roll = _this.current.roll // console.log((HeadingPitchRoll.heading - modeHeadingPitchRoll.heading) * (180 / Math.PI)) if (isNaN(heading) || isNaN(pitch) || isNaN(roll)) { return } if (heading < 0 || heading > 180) { pitch = -pitch } _this.current = { position: position, heading: heading, pitch: pitch, roll: roll } if (first) { first = false _this._first = { position: position, heading: heading, pitch: pitch, roll: roll } } lastDistance = distance // console.log(position) _this.realTimeRouteArray.push(position) if (_this.viewFollow) { // console.log(heading) if (_this.options.firstPersonView) { _this.sdk.viewer.camera.setView({ destination: positionCamera, orientation: { heading: _this.sdk.viewer.camera.heading, pitch: _this.sdk.viewer.camera.pitch, roll: _this.sdk.viewer.camera.roll } }) } else { if (_this.sdk.viewer.trackedEntity) { _this.sdk.viewer.trackedEntity.position = position // _this.sdk.viewer.camera.position = position } } } } // function executeAnimate() { // } // setTimeout(() => { // let i = 0 // function animate() { // if (i < motionArray.length) { // let result = motionArray[i].result; // console.log(result) // result.then((res) => { // let position = Cesium.Cartesian3.fromDegrees(motionArray[i].lng, motionArray[i].lat, res[0].height) // let HeadingPitchRoll = getHeadingPitchRoll(_this.model.position, position) // let modeHeadingPitchRoll = Cesium.HeadingPitchRoll.fromDegrees(_this.options.model.heading, _this.options.model.pitch, _this.options.model.roll) // let heading = 0 // let pitch = 0 // let roll = 0 // if (_this.options.routeDirection) { // heading = (HeadingPitchRoll.heading - modeHeadingPitchRoll.heading) * (180 / Math.PI) - 90 // pitch = (HeadingPitchRoll.pitch - modeHeadingPitchRoll.pitch) * (180 / Math.PI) // } // else { // heading = - _this.options.model.heading // pitch = - _this.options.model.pitch // } // roll = - _this.options.model.roll // // console.log(heading) // let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position) // _this.model.modelMatrix = Cesium.Matrix4.multiplyByMatrix3(matrix, Cesium.Matrix3.fromHeadingPitchRoll(Cesium.HeadingPitchRoll.fromDegrees(heading, pitch, roll)), _this.model.modelMatrix) // _this.model.position = position // if (_this.sdk.viewer.trackedEntity) { // _this.sdk.viewer.trackedEntity.position = position // } // i++ // requestAnimationFrame(animate); // }) // } // } // animate(); // }, 2000); // 根据两个坐标点,获取Heading(朝向) function getHeadingPitchRoll(pointA, pointB) { // console.log(distance, _this.cartesian3Towgs84(pointA, viewer), _this.cartesian3Towgs84(pointB, viewer)) //建立以点A为原点,X轴为east,Y轴为north,Z轴朝上的坐标系 const transform = Cesium.Transforms.eastNorthUpToFixedFrame(pointA); //向量AB if (!pointB) { return } const positionvector = Cesium.Cartesian3.subtract(pointB, pointA, new Cesium.Cartesian3()); //因transform是将A为原点的eastNorthUp坐标系中的点转换到世界坐标系的矩阵 //AB为世界坐标中的向量 //因此将AB向量转换为A原点坐标系中的向量,需乘以transform的逆矩阵。 const vector = Cesium.Matrix4.multiplyByPointAsVector( Cesium.Matrix4.inverse(transform, new Cesium.Matrix4()), positionvector, new Cesium.Cartesian3() ); //归一化 const direction = Cesium.Cartesian3.normalize(vector, new Cesium.Cartesian3()); //heading const heading = Math.atan2(direction.y, direction.x) - Cesium.Math.PI_OVER_TWO; let pitch = Cesium.Math.PI_OVER_TWO - Cesium.Math.acosClamped(direction.z); let a = pitch * (180 / Math.PI) if (a < 0) { // a = (-a) } pitch = a * (Math.PI / 180) const roll = Cesium.Math.fastApproximateAtan2(direction.x, direction.z); // console.log({heading: heading * (180 / Math.PI), pitch: pitch * (180 / Math.PI), roll: roll * (180 / Math.PI)}) return { heading: Cesium.Math.TWO_PI - Cesium.Math.zeroToTwoPi(heading), pitch: pitch, roll: roll }; } } setMovePositionByDistance(distance) { let positions_smooth = this._renewLine(this.options.line.positions) this.modelMove(positions_smooth, { distance: distance }) } setMovePositionByTime(time) { let positions_smooth = this._renewLine(this.options.line.positions) this.modelMove(positions_smooth, { time: time }) if (!this.state) { this.modelMove(positions_smooth, { time: time+0.01 }) } } // 暂停 pause() { this.state = false } // 继续 resume() { this.state = true } async flyTo(options = {}) { setActiveViewer(0) closeRotateAround(this.sdk) if (this.options.customView && this.options.customView.relativePosition && this.options.customView.orientation) { let orientation = { heading: Cesium.Math.toRadians(this.options.customView.orientation.heading || 0.0), pitch: Cesium.Math.toRadians(this.options.customView.orientation.pitch || -60.0), roll: Cesium.Math.toRadians(this.options.customView.orientation.roll || 0.0) } let lng = this.options.customView.relativePosition.lng let lat = this.options.customView.relativePosition.lat let alt = this.options.customView.relativePosition.alt let destination = Cesium.Cartesian3.fromDegrees(lng, lat, alt) let position = { lng: 0, lat: 0 } position = { ...this.options.line.positions[0] } // 如果没有高度值,则获取紧贴高度计算 if (!position.hasOwnProperty('alt')) { position.alt = await this.getClampToHeight(position) } lng = this.options.customView.relativePosition.lng + position.lng lat = this.options.customView.relativePosition.lat + position.lat alt = this.options.customView.relativePosition.alt + position.alt destination = Cesium.Cartesian3.fromDegrees(lng, lat, alt) this.sdk.viewer.camera.flyTo({ destination: destination, orientation: orientation }) } else { this.line && this.sdk.viewer.flyTo(this.line, { offset: options.orientation || { heading: Cesium.Math.toRadians(0.0), pitch: Cesium.Math.toRadians(-60.0), roll: Cesium.Math.toRadians(0.0) } }) } } remove() { // this.sdk.viewer.scene.primitives.remove(this.model) this.event && this.event.destroy() this.tip && this.tip.destroy() this.sdk.viewer.entities.remove(this.line) this.line = null this.removeModelAnimate() } reset() { this.modelMove(this.line.polyline.positions._value) this.state = false this.current = this._first } // viewFollow(e) { // if (e.target.checked) { // var pointEntity = this.sdk.viewer.entities.add({ // // show: false, // position: this.positions_smooth[0], // position of the point // point: { // color: Cesium.Color.RED.withAlpha(0), // color of the point // pixelSize: 0 // } // }); // this.sdk.viewer.trackedEntity = pointEntity; // } // else { // this.sdk.viewer.entities.remove(this.sdk.viewer.trackedEntity) // this.sdk.viewer.trackedEntity = null // } // } // 移除动画 removeModelAnimate() { if (this.TweenAnimate) { clearTimeout(this.TweenAnimate.timeout) TWEEN.remove(this.TweenAnimate) this.TweenAnimate = null } // if (modelPrimitive && modelPrimitive._activeAnimations && modelPrimitive._activeAnimations._runtimeAnimations) { // let runtimeAnimation = modelPrimitive._activeAnimations._runtimeAnimations // for (let i = runtimeAnimation.length - 1; i >= 0; i--) { // switch (runtimeAnimation[i].name) { // case '跑': // modelPrimitive.activeAnimations.remove(runtimeAnimation[i]) // break; // default: // } // } // } } _renewLine(pos) { this.options.line.positions = pos let positions = pos if (this.noseToTail) { positions = [...pos, pos[0]] } let fromDegreesArrayHeights = [] let time = [] let positions_smooth = [] for (let i = 0; i < positions.length; i++) { fromDegreesArrayHeights.push(positions[i].lng, positions[i].lat, positions[i].alt) time.push(i / (positions.length - 1)) } if (this.smooth) { this.spline = new Cesium.CatmullRomSpline({ times: time, points: Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArrayHeights) }); } else { this.spline = new Cesium.LinearSpline({ times: time, points: Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArrayHeights) }); } for (let i = 0; i <= 100; i++) { let cartesian3 = this.spline.evaluate(i / 100); positions_smooth.push(cartesian3); } this.positions_smooth = positions_smooth return positions_smooth } // 更新坐标 renewLinePositions(pos) { this.options.line.positions = pos let positions = pos if (this.noseToTail) { positions = [...pos, pos[0]] } let fromDegreesArrayHeights = [] let time = [] let positions_smooth = [] for (let i = 0; i < positions.length; i++) { fromDegreesArrayHeights.push(positions[i].lng, positions[i].lat, positions[i].alt) time.push(i / (positions.length - 1)) } if (this.smooth) { this.spline = new Cesium.CatmullRomSpline({ times: time, points: Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArrayHeights) }); } else { this.spline = new Cesium.LinearSpline({ times: time, points: Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArrayHeights) }); } for (let i = 0; i <= 100; i++) { let cartesian3 = this.spline.evaluate(i / 100); positions_smooth.push(cartesian3); } this.positions_smooth = positions_smooth if (this.line && this.line.polyline) { this.line.polyline.positions = positions_smooth } return positions_smooth } flicker() { } } export default TrajectoryMotionObject