import { getHost, getToken } from "../../../on"; import tools from '../../../Tools' import { html } from "./_element"; import Dialog from '../../Element/Dialog'; import EventBinding from '../../Element/Dialog/eventBinding'; import ControllerObject from '../../../Controller' import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../Global/global' export default class LoadObjModel extends tools { constructor(sdk, options, _Dialog = {}) { super() // eslint-disable-next-line no-undef this.sdk = sdk this.viwer = sdk.viewer this.options = { ...options } this.options.host = options.host || getHost() this.options.name = options.name || '未命名对象' this.options.show = (options.show || options.show === false) ? options.show : true if (typeof options.scale === 'number') { this.options.scale = {} this.options.scale.x = options.scale this.options.scale.y = options.scale this.options.scale.z = options.scale } else { this.options.scale = options.scale || {} this.options.scale.x = (this.options.scale.x || this.options.scale.x === 0) ? this.options.scale.x : 1 this.options.scale.y = (this.options.scale.y || this.options.scale.y === 0) ? this.options.scale.y : 1 this.options.scale.z = (this.options.scale.z || this.options.scale.z === 0) ? this.options.scale.z : 1 } this.primitive = null this._loadEvent = void 0 this._loaded = false this._elms = {}; this.Dialog = _Dialog this._EventBinding = new EventBinding() LoadObjModel.setDefaultValue(this) this.requestResource() this.ControllerObject = new ControllerObject(this.sdk, { position: { ...this.options.position }, rotate: { x: (360 + (this.options.roll % 360)) % 360, y: (360 + (-this.options.pitch % 360)) % 360, z: (360 + (-this.options.heading % 360)) % 360 }, }) this.ControllerObject.controllerCallBack = this.controllerCallBack this.HeadingPitchRollCallBack = this.Dialog.HeadingPitchRollCallBack // this.viwer.camera.moveEnd.addEventListener(() => { // if (this.options.show && this.primitive && this.primitive.video && this.primitive.video.player && this.options.position) { // const position1 = Cesium.Cartesian3.fromDegrees(this.options.position.lng, this.options.position.lat, this.options.position.alt); // const position2 = this.viwer.camera.position // const distance = Cesium.Cartesian3.distance(position1, position2); // if (this.options.playDistance && distance > this.options.playDistance) { // this.primitive.video.player.getVueInstance().pause() // } // else { // this.primitive.video.player.getVueInstance().play() // } // } // }) } requestResource() { this.addResource().then(r => { }) } static setDefaultValue(that) { that.options.id = that.options.id || that.randomString() that.options.position = that.options.position that.options.objUrl = that.options.objUrl || '' that.options.videoUrl = that.options.videoUrl || '' that.options.xmlURL = that.options.xmlURL || '' that.options.heading = that.options.heading || 0 that.options.pitch = that.options.pitch || 0 that.options.roll = that.options.roll || 0 } async addResource() { let that = this that.options.xmlURL = that.options.objUrl.replace('.obj', '.xml') if (that.options.xmlURL !== '') { const xml = await fetch(that.options.xmlURL) if (xml.ok) { const xmlString = await xml.text() const parser = new DOMParser() const xmlDoc = parser.parseFromString(xmlString, 'text/xml') // console.log('xmlDocxmlDocxmlDoc', xmlDoc) const position = xmlDoc .getElementsByTagName('Position')[0] .textContent.split(',') // const bbox = xmlDoc.getElementsByTagName('bbox')[0] const crs = xmlDoc.getElementsByTagName('Crs')[0].textContent const result = that.convert( [{ x: position[0], y: position[1], z: position[2] }], crs, 'EPSG:4326' ) that.options.position = that.options.position || { lng: result.points[0].x, lat: result.points[0].y, alt: result.points[0].z } that.ControllerObject.position = that.options.position const scene = that.viwer.scene const origin = Cesium.Cartesian3.fromDegrees( that.options.position.lng, that.options.position.lat, that.options.position.alt ) const obj_modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame( origin, new Cesium.HeadingPitchRoll( Cesium.Math.toRadians(0.85), Cesium.Math.toRadians(0), Cesium.Math.toRadians(0) ) ) let obj = await window.objLoader.Load(that.options.objUrl) obj.show = that.options.show obj.modelMatrix = obj_modelMatrix obj.setFlvVideo(that.options.videoUrl) scene.primitives.add(obj) that.primitive = obj that.controllerCallBack({ rotate: { x: that.options.roll, y: -that.options.pitch, z: -that.options.heading }, position: { ...that.options.position } }) this.loaded = true this._loaded = true if (this._loadEvent) { this._loadEvent() } } } else { // eslint-disable-next-line no-console console.error('请填写xml路径') return } if (that.options.objUrl === '') { // eslint-disable-next-line no-console console.error('请填写obj模型路径') return } } async flyTo(options = {}) { if (this._error) { return } setActiveViewer(0) closeRotateAround(this.sdk) closeViewFollow(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 } if (this.options.position) { position = { ...this.options.position } } else if (this.options.positions) { position = { ...this.options.positions[0] } } else if (this.options.center) { position = { ...this.options.center } } else if (this.options.start) { position = { ...this.options.start } } else { if (this.options.hasOwnProperty('lng')) { position.lng = this.options.lng } if (this.options.hasOwnProperty('lat')) { position.lat = this.options.lat } if (this.options.hasOwnProperty('alt')) { position.alt = this.options.alt } } // 如果没有高度值,则获取紧贴高度计算 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 { let a = 100 * Math.tan(60) let latitude = a / 111319.55 this.sdk.viewer.camera.flyTo({ destination: new Cesium.Cartesian3.fromDegrees( this.options.position.lng, this.options.position.lat - latitude, this.options.position.alt + 100 ), orientation: options.orientation || { heading: Cesium.Math.toRadians(0.0), pitch: Cesium.Math.toRadians(-60.0), roll: Cesium.Math.toRadians(0.0) } }) } } async edit(state = false) { let equal = false this.originalOptions = this.deepCopyObj(this.options) if (this._DialogObject && this._DialogObject.close) { this._DialogObject.close() this._DialogObject = null } this._DialogObject = await new Dialog(this.sdk, this.options, { title: '编辑属性', left: '180px', top: '100px', confirmCallBack: (options) => { this.name = this.name.trim() if (!this.name) { this.name = '未命名对象' } this.originalOptions = this.deepCopyObj(this.options) this._DialogObject.close() this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions) }, // resetCallBack: () => { // this.name = this.originalOptions.name // this.Dialog.resetCallBack && this.Dialog.resetCallBack() // }, resetCallBack: () => { this.reset() this.Dialog.resetCallBack && this.Dialog.resetCallBack() }, removeCallBack: () => { this.Dialog.removeCallBack && this.Dialog.removeCallBack() }, closeCallBack: () => { this.reset() this.positionEditing = false this.Dialog.closeCallBack && this.Dialog.closeCallBack() }, rotateCallBack: () => { if (this.rotationEditing) { this.rotationEditing = false } else { this.rotationEditing = true } }, translationalCallBack: () => { if (this.positionEditing) { this.positionEditing = false } else { this.positionEditing = true } } }, true) let contentElm = document.createElement('div') contentElm.style.width = '448px' contentElm.innerHTML = html() this._DialogObject.contentAppChild(contentElm) let equalSwitchElm = this._DialogObject._element.content.getElementsByClassName('checkbox-box')[0].querySelector('input') let equalBoxElm = this._DialogObject._element.content.getElementsByClassName('equal')[0] let noEqualBoxElm = this._DialogObject._element.content.getElementsByClassName('no-equal')[0] equalSwitchElm.checked = equal equalSwitchElm.addEventListener('change', (e) => { equal = e.target.checked if (equal) { equalBoxElm.style.display = 'flex' noEqualBoxElm.style.display = 'none' } else { equalBoxElm.style.display = 'none' noEqualBoxElm.style.display = 'flex' } }) let equalElms = equalBoxElm.getElementsByTagName('input') equalElms[0].value = this.scaleX equalElms[1].value = this.scaleX equalElms[0].addEventListener('input', (e) => { this.scaleX = e.target.value this.scaleY = e.target.value this.scaleZ = e.target.value }) equalElms[1].addEventListener('input', (e) => { this.scaleX = e.target.value this.scaleY = e.target.value this.scaleZ = e.target.value }) if (equal) { equalBoxElm.style.display = 'flex' noEqualBoxElm.style.display = 'none' } else { equalBoxElm.style.display = 'none' noEqualBoxElm.style.display = 'flex' } setTimeout(() => { if (this._DialogObject._element.foot) { let translationalElm = this._DialogObject._element.foot.getElementsByClassName('rotate')[0] if (translationalElm) { translationalElm.style.position = 'absolute' translationalElm.style.left = '100px' } } }, 0); let all_elm = contentElm.getElementsByTagName("*") for (let i = 0; i < all_elm.length; i++) { all_elm[i].addEventListener('input', (e) => { if (e.target.value === '0' && e.target.min === '0') { switch (e.target.className) { case 'scale-x': this.scaleX = 0.0001 break; case 'scale-y': this.scaleY = 0.0001 break; case 'scale-z': this.scaleZ = 0.0001 case 'scale-all': this.scaleX = 0.0001 this.scaleY = 0.0001 this.scaleZ = 0.0001 break; case 3: } } }) } this._EventBinding.on(this, all_elm) this._elms = this._EventBinding.element this._elms.scaleX.push(equalElms[0], equalElms[1]) } reset() { this.ControllerObject.destroy() this.options = this.deepCopyObj(this.originalOptions) this.name = this.options.name if (!this.primitive) { return } let m = Cesium.Transforms.eastNorthUpToFixedFrame( new Cesium.Cartesian3.fromDegrees(this.options.position.lng, this.options.position.lat, this.options.position.alt) ) this.primitive.modelMatrix = m // 旋转 this.primitive.modelMatrix = Cesium.Matrix4.multiplyByMatrix3( this.primitive.modelMatrix, Cesium.Matrix3.fromHeadingPitchRoll( Cesium.HeadingPitchRoll.fromDegrees(this.options.heading, this.options.pitch, this.options.roll) ), this.primitive.modelMatrix ) // 缩放 let scaleX = this.options.scale.x let scaleY = this.options.scale.y let scaleZ = this.options.scale.z if (scaleX === 0) { scaleX = 0.00001 } if (scaleY === 0) { scaleY = 0.00001 } if (scaleZ === 0) { scaleZ = 0.00001 } Cesium.Matrix4.multiplyByScale(this.primitive.modelMatrix, new Cesium.Cartesian3(scaleX, scaleY, scaleZ), this.primitive.modelMatrix) } remove() { this.sdk.viewer.scene.primitives.remove(this.primitive) this.primitive = null if (this._DialogObject && !this._DialogObject.isDestroy) { this._DialogObject.close() this._DialogObject = null } } set controllerCallBack(callback) { this._controllerCallBack = callback } get controllerCallBack() { return params => { this.options.heading = -params.rotate.z this.options.pitch = -params.rotate.y this.options.roll = params.rotate.x this.HeadingPitchRollCallBack && this.HeadingPitchRollCallBack(params) let lng = Number(Number(params.position.lng).toFixed(8)) let lat = Number(Number(params.position.lat).toFixed(8)) let alt = Number(Number(params.position.alt).toFixed(2)) this.options.position = { lng, lat, alt } // 平移 let m = Cesium.Transforms.eastNorthUpToFixedFrame( new Cesium.Cartesian3.fromDegrees(params.position.lng, params.position.lat, params.position.alt) ) this.primitive.modelMatrix = m // 旋转 Cesium.Matrix4.multiplyByMatrix3( this.primitive.modelMatrix, Cesium.Matrix3.fromHeadingPitchRoll( Cesium.HeadingPitchRoll.fromDegrees(-params.rotate.z, -params.rotate.y, params.rotate.x) ), this.primitive.modelMatrix ) // 缩放 let scaleX = this.options.scale.x let scaleY = this.options.scale.y let scaleZ = this.options.scale.z if (scaleX === 0) { scaleX = 0.00001 } if (scaleY === 0) { scaleY = 0.00001 } if (scaleZ === 0) { scaleZ = 0.00001 } Cesium.Matrix4.multiplyByScale(this.primitive.modelMatrix, new Cesium.Cartesian3(scaleX, scaleY, scaleZ), this.primitive.modelMatrix) this._elms.lng && this._elms.lng.forEach((item) => { item.value = this.options.position.lng }) this._elms.lat && this._elms.lat.forEach((item) => { item.value = this.options.position.lat }) this._elms.alt && this._elms.alt.forEach((item) => { item.value = this.options.position.alt }) } } get name() { return this.options.name } set name(v) { this.options.name = v this._elms.name && this._elms.name.forEach((item) => { item.value = v }) } /** * @desc 打开模型旋转功能 * @param status {boolean} * @methodOf Source * */ set rotationEditing(status) { if (status) { this.ControllerObject.editRtation() } else { this.ControllerObject.destroy() } } get scaleX() { return this.options.scale.x } set scaleX(v) { this.options.scale.x = Number(Number(v).toFixed(4)) this.controllerCallBack( { position: { ...this.options.position }, rotate: { x: (360 + (this.options.roll % 360)) % 360, y: (360 + (-this.options.pitch % 360)) % 360, z: (360 + (-this.options.heading % 360)) % 360 }, } ) this._elms.scaleX && this._elms.scaleX.forEach((item) => { item.value = this.options.scale.x }) } get scaleY() { return this.options.scale.y } set scaleY(v) { this.options.scale.y = Number(Number(v).toFixed(4)) this.controllerCallBack( { position: { ...this.options.position }, rotate: { x: (360 + (this.options.roll % 360)) % 360, y: (360 + (-this.options.pitch % 360)) % 360, z: (360 + (-this.options.heading % 360)) % 360 }, } ) this._elms.scaleY && this._elms.scaleY.forEach((item) => { item.value = this.options.scale.y }) } get scaleZ() { return this.options.scale.z } set scaleZ(v) { this.options.scale.z = Number(Number(v).toFixed(4)) this.controllerCallBack( { position: { ...this.options.position }, rotate: { x: (360 + (this.options.roll % 360)) % 360, y: (360 + (-this.options.pitch % 360)) % 360, z: (360 + (-this.options.heading % 360)) % 360 }, } ) this._elms.scaleZ && this._elms.scaleZ.forEach((item) => { item.value = this.options.scale.z }) } /** * @desc 获取模型旋转状态 * @method rotationEditing * @return boolean * @methodOf Source * */ get rotationEditing() { if (this.ControllerObject.getActiveState() === 'rtation') { return true } return false } /**@desc 打开平移模型功能 * * @memberOf Source *@param status {boolean} * * */ set positionEditing(status) { if (!this.sdk || !this.sdk.viewer || !this.ControllerObject) { return } if (status) { this.ControllerObject.editTranslational() } else { this.ControllerObject.destroy() } } get positionEditing() { if (this.ControllerObject.getActiveState() === 'translational') { return true } return false } get lng() { return this.options.position.lng } set lng(v) { this.options.position.lng = v this.ControllerObject.position = {lng: this.options.position.lng, lat: this.options.position.lat, alt: this.options.position.alt} this.controllerCallBack( { position: { ...this.options.position }, rotate: { x: (360 + (this.options.roll % 360)) % 360, y: (360 + (-this.options.pitch % 360)) % 360, z: (360 + (-this.options.heading % 360)) % 360 }, } ) } get lat() { return this.options.position.lat } set lat(v) { this.options.position.lat = v this.ControllerObject.position = {lng: this.options.position.lng, lat: this.options.position.lat, alt: this.options.position.alt} this.controllerCallBack( { position: { ...this.options.position }, rotate: { x: (360 + (this.options.roll % 360)) % 360, y: (360 + (-this.options.pitch % 360)) % 360, z: (360 + (-this.options.heading % 360)) % 360 }, } ) } get alt() { return this.options.position.alt } set alt(v) { this.options.position.alt = v this.ControllerObject.position = {lng: this.options.position.lng, lat: this.options.position.lat, alt: this.options.position.alt} this.controllerCallBack( { position: { ...this.options.position }, rotate: { x: (360 + (this.options.roll % 360)) % 360, y: (360 + (-this.options.pitch % 360)) % 360, z: (360 + (-this.options.heading % 360)) % 360 }, } ) } get show() { return this.options.show } set show(v) { if (typeof v === "boolean") { this.options.show = v this.primitive.show = v } else { console.error("参数必须为boolean") } } get playDistance() { return this.options.playDistance } set playDistance(v) { this.options.playDistance = v // this._elms.playDistance && this._elms.playDistance.forEach((item) => { // item.value = this.options.playDistance // }) // if (this.options.show && this.primitive && this.primitive.video && this.primitive.video.player && this.options.position) { // const position1 = Cesium.Cartesian3.fromDegrees(this.options.position.lng, this.options.position.lat, this.options.position.alt); // const position2 = this.viwer.camera.position // const distance = Cesium.Cartesian3.distance(position1, position2); // if (this.options.playDistance && distance > this.options.playDistance) { // this.primitive.video.player.getVueInstance().pause() // } // else { // this.primitive.video.player.getVueInstance().play() // } // } } flicker() { } load(callback) { if (this._loaded) { callback(); } else { this._loadEvent = callback } } get customView() { this.options.customView } // 设置视角 setCustomView(val) { if (val) { this.options.customView = val } else { let camera = this.sdk.viewer.camera this.options.customView = { orientation: { heading: camera.heading, pitch: camera.pitch, roll: camera.roll }, position: { x: camera.position.x, y: camera.position.y, z: camera.position.z } } this.originalOptions && (this.originalOptions.customView = this.options.customView) } } // 重置视角 resetCustomView() { this.options.customView = undefined } }