import * as mars3d from "mars3d" import { TilesEditor } from "./TilesEditor.js" export let map // mars3d.Map三维地图对象 export let tiles3dLayer export let tilesEditor // 自定义事件 export const eventTarget = new mars3d.BaseClass() // 事件对象,用于抛出事件到面板中 /** * 初始化地图业务,生命周期钩子函数(必须) * 框架在地图初始化完成后自动调用该函数 * @param {mars3d.Map} mapInstance 地图对象 * @returns {void} 无 */ export function onMounted(mapInstance) { map = mapInstance // 记录map map.fixedLight = true // 固定光照,避免gltf模型随时间存在亮度不一致。 // 鼠标拖拽编辑,定义在js/TilesEditor.js tilesEditor = new TilesEditor({ map: map, moveImg: "img/icon/move.png", rotateImg: "img/icon/rotate.png" }) tilesEditor.on("change", function (data) { tilesEditor.enabled = true eventTarget.fire("tilesEditor", { data }) }) } /** * 释放当前地图业务的生命周期函数 * @returns {void} 无 */ export function onUnmounted() { map = null } // 查看构件 export function showCompTree(model) { querySceneTreeData(model) .then(function (scene) { const data = [] if (scene.scenes) { for (let i = 0; i < scene.scenes.length; i++) { const node = scene.scenes[i] name2text(node) data.push(node) } } else { name2text(scene) data.push(scene) } eventTarget.fire("compTree", { data }) }) .catch(function (error) { console.log("加载JSON出错", error) }) } export function compModelChange(nodeid, nodesphere) { if (nodesphere[3] <= 0) { return } // 构件节点位置 let center = new Cesium.Cartesian3(nodesphere[0], nodesphere[1], nodesphere[2]) // 获取构件节点位置,现对于原始矩阵变化后的新位置 center = tiles3dLayer.getPositionByOrginMatrix(center) // 飞行过去 const sphere = new Cesium.BoundingSphere(center, nodesphere[3]) map.camera.flyToBoundingSphere(sphere, { offset: new Cesium.HeadingPitchRange(map.camera.heading, map.camera.pitch, nodesphere[3] * 1.5), duration: 0.5 }) // 设置tileset的样式 tiles3dLayer.style = new Cesium.Cesium3DTileStyle({ color: { conditions: [ ["${id} ==='" + nodeid + "'", "rgb(255, 255, 255)"], ["true", "rgba(255, 200, 200,0.2)"] ] } }) } export function checkedTree() { tiles3dLayer.tileset.style = undefined } /** * * * @param {string} url 面板中传入的url模型地址 * @return {*} 无 */ export function showModel(url) { removeLayer() if (!url) { alert("请输入图层URL!") return } tiles3dLayer = new mars3d.layer.TilesetLayer({ url: url, // 高亮时的样式 highlight: { type: mars3d.EventType.click, // 默认为鼠标移入高亮,也可以指定click单击高亮 outlineEffect: true, // 采用OutlineEffect方式来高亮 color: "#00FF00" }, popup: "all", flyTo: true }) map.addLayer(tiles3dLayer) // 加载完成事件 tiles3dLayer.on(mars3d.EventType.load, function (event) { const data = event.tileset if (tiles3dLayer.transform) { tilesEditor.range = data.boundingSphere.radius * 0.9 tilesEditor.heading = tiles3dLayer.rotation_z tilesEditor.position = tiles3dLayer.position } else { tilesEditor.enabled = false } // 触发自定义事件,更改面板中的值 eventTarget.fire("tiles3dLayerLoad", { data, tiles3dLayer }) }) } // 异步求准确高度 export function getDefined(data) { const params = getConfig(data) // 求地面海拔 (异步) if (Cesium.defined(params.position) && Cesium.defined(params.position.alt)) { // 存在历史设置的高度时不用处理 } else { mars3d.PointUtil.getSurfaceTerrainHeight(map.scene, tiles3dLayer.orginCenterPosition, { asyn: true, // 是否异步求准确高度 callback: function (newHeight) { if (newHeight == null) { return } const offsetZ = Math.ceil(newHeight - tiles3dLayer.orginCenterPoint.alt + 1) console.log("地面海拔:" + newHeight.toFixed(2) + ",需要偏移" + offsetZ) data.txtZ = offsetZ tiles3dLayer.height = offsetZ } }) } } export function editor(event, txtZ) { if (Cesium.defined(event.position)) { const pos = event.position const thisZ = txtZ const position = mars3d.PointUtil.setPositionsHeight(pos, thisZ) tilesEditor.position = position tiles3dLayer.center = position const point = mars3d.LngLatPoint.fromCartesian(position) eventTarget.fire("changePoition", { point }) } else if (Cesium.defined(event.heading)) { tiles3dLayer.rotation_z = event.heading eventTarget.fire("changeHeading", { tiles3dLayer }) } } /** * 通过面板修改模型,将面板中的参数进行修改 * * @param {object} pannelData 面板改变的值 * @return {object} params 模型的参数 */ export function getConfig(pannelData) { let url, maximumScreenSpaceError let tf = false if (pannelData) { url = pannelData.txtModel maximumScreenSpaceError = mars3d.Util.formatNum(pannelData.maximumScreenSpaceError, 1) } else { url = "//data.mars3d.cn/3dtiles/max-fsdzm/tileset.json" maximumScreenSpaceError = 8 tf = true } const params = { name: "模型名称", type: "3dtiles", url: url, maximumScreenSpaceError: maximumScreenSpaceError, // 【重要】数值加大,能让最终成像变模糊 maximumMemoryUsage: 1024, // 【重要】内存分配变小有利于倾斜摄影数据回收,提升性能体验 // center: map.getCameraView(), show: true } if (tf) { return params } const x = mars3d.Util.formatNum(pannelData.txtX, 6) if (x) { params.position = params.position || {} params.position.lng = x } const y = mars3d.Util.formatNum(pannelData.txtY, 6) if (y) { params.position = params.position || {} params.position.lat = y } const z = mars3d.Util.formatNum(pannelData.txtZ, 6) if (z) { params.position = params.position || {} params.position.alt = z } const rotation_x = mars3d.Util.formatNum(pannelData.rotationX, 1) if (rotation_x) { params.rotation = params.rotation || {} params.rotation.x = rotation_x } const rotation_y = mars3d.Util.formatNum(pannelData.rotationY, 1) if (rotation_y) { params.rotation = params.rotation || {} params.rotation.y = rotation_y } const rotation_z = mars3d.Util.formatNum(pannelData.rotationZ, 1) if (rotation_z) { params.rotation = params.rotation || {} params.rotation.z = rotation_z } const luminanceAtZenith = mars3d.Util.formatNum(pannelData.luminanceAtZenith, 1) if (luminanceAtZenith !== 0.2) { params.luminanceAtZenith = luminanceAtZenith } const scale = mars3d.Util.formatNum(pannelData.scale || 1, 1) if (scale > 0) { params.scale = scale } const axis = pannelData.axis params.axis = axis const isProxy = pannelData.chkProxy if (isProxy) { params.proxy = "//server.mars3d.cn/proxy/" } return params } // 修改更改后的参数 export function updateModel(pannelData) { // 获取参数 const params = getConfig(pannelData) params.rotation = params.rotation || {} params.rotation.x = params.rotation.x || 0 params.rotation.y = params.rotation.y || 0 params.rotation.z = params.rotation.z || 0 if (tiles3dLayer.transform) { tilesEditor.heading = tiles3dLayer.rotation_z tilesEditor.position = tiles3dLayer.position } tiles3dLayer.tileset.maximumScreenSpaceError = pannelData.maximumScreenSpaceError tiles3dLayer.tileset.luminanceAtZenith = pannelData.luminanceAtZenith tiles3dLayer.opacity = pannelData.opacity tiles3dLayer.setOptions(params) // 深度检测 map.scene.globe.depthTestAgainstTerrain = pannelData.depthTestAgainstTerrain // 鼠标拖拽编辑 tilesEditor.enabled = pannelData.tilesEditorEnabled } export function locate() { if (tiles3dLayer.tileset?.boundingSphere) { map.camera.flyToBoundingSphere(tiles3dLayer.tileset.boundingSphere, { offset: new Cesium.HeadingPitchRange(map.camera.heading, map.camera.pitch, tiles3dLayer.tileset.boundingSphere.radius * 2) }) } else { map.flyToPoint(tiles3dLayer.position, { radius: tiles3dLayer.tileset.boundingSphere.radius * 2 }) } } // 保存GeoJSON export function saveBookmark(params) { if (params.axis === "") { delete params.axis } mars3d.Util.downloadFile("3dtiles图层配置.json", JSON.stringify(getConfig(params))) } function removeLayer() { if (tiles3dLayer) { map.basemap = 2021 // 切换到默认卫星底图 map.removeLayer(tiles3dLayer, true) tiles3dLayer = null } } // 取构件树数据 function querySceneTreeData(url) { const scenetree = url.substring(0, url.lastIndexOf("/") + 1) + "scenetree.json" return mars3d.Util.fetchJson({ url: scenetree }) } function name2text(o) { o.text = o.name // 这块为了避免tree控件里的id不统一,所以加改变一下 o.eleid = o.id o.id = undefined if ((!o.text || o.text.trim() === "") && o.type) { o.text = o.type } if (o.children) { for (let i = 0; i < o.children.length; i++) { name2text(o.children[i]) } } }