| | |
| | | data: data |
| | | }); |
| | | } |
| | | |
| | | // 查询参数详细 |
| | | export function getPointInfo(id) { |
| | | return request({ |
| | | url: '/tower/point/' + id, |
| | | method: 'get' |
| | | }); |
| | | } |
| | | |
| | | // 根据设备di获取设备的飞行航线模版 |
| | | export function obtainRealData(flightTemplateId, deviceId) { |
| | | return request({ |
| | | url: `/tower/route/getTrueBearing/${flightTemplateId}/${deviceId}`, |
| | | method: 'get' |
| | | }); |
| | | } |
| | | |
| | | // 根据设备di获取设备的飞行航线模版 |
| | | export function flyDataInfo(deviceId) { |
| | | return request({ |
| | | url: '/tower/point/device/' + deviceId, |
| | | method: 'get' |
| | | }); |
| | | } |
| | |
| | | let viewerM; |
| | | let viewerC; |
| | | let counter = 0; |
| | | let globalon = 0 |
| | | let globalat = 0 |
| | | let globalon = 0 |
| | | let globalat = 0 |
| | | let pois = [globalon, globalat,0] |
| | | |
| | | // let pois = [0, 0,0] |
| | |
| | | } |
| | | }, |
| | | mounted(){ |
| | | console.log('111111111111111111') |
| | | this.initCesium(); |
| | | }, |
| | | beforeDestroy() { |
| | | counter = 0 |
| | | this.removeKeyboardEvents(); |
| | | if (this.animationFrameId) cancelAnimationFrame(this.animationFrameId); |
| | | if (viewerC) viewerC.destroy(); |
| | |
| | | initCesium() { |
| | | viewerM = this.initViewer(this.$refs.cesiumContainer.id); |
| | | viewerC = this.initViewer(this.$refs.cesiumCamera.id); |
| | | window.viewerM = viewerM; |
| | | window.viewerC = viewerC; |
| | | // 💡 在这里继续调用 measure.js / camera.js / botton.js 等逻辑 |
| | | // 例如:window.registerMeasureTools(viewerM) |
| | | setTimeout(()=>{ |
| | |
| | | |
| | | // // 关闭光照效果 |
| | | // viewer.scene.globe.enableLighting = false; // 关闭光照效果 |
| | | window.viewer = viewer; |
| | | |
| | | // viewer.imageryLayers.add(bdtvectoranoimagery); |
| | | viewer._cesiumWidget._creditContainer.style.display="none"; |
| | | return viewer; |
| | |
| | | this.resetForm("form"); |
| | | |
| | | if (ids) { |
| | | this.getModel() |
| | | // 编辑 |
| | | this.$api.detail('/tower/device', ids).then(res => { |
| | | console.log(res) |
| | | this.form = res.data |
| | | this.open = true |
| | | this.$nextTick(() => { |
| | | console.log(this.form) |
| | | this.$refs.cesiumMapSelctPoint.showPickPoint({ |
| | | longitude: +this.form.longitude, |
| | | latitude: +this.form.latitude, |
| | | altitude: +this.form.altitude, |
| | | height: +this.form.height, |
| | | }) |
| | | console.log(this.modelListData) |
| | | let url = this.modelListData.filter(item=>item.id == this.form.modelId)[0].modelRoute |
| | | console.log(url) |
| | | this.modelUrl = url |
| | | const position = Cesium.Cartesian3.fromDegrees(this.form.longitude, this.form.latitude, this.form.altitude); |
| | | const position = Cesium.Cartesian3.fromDegrees(this.form.longitude, this.form.latitude, this.form.height); |
| | | console.log(position) |
| | | // 设置模型方向(可选) |
| | | let model = viewer.entities.getById("MyModel"); |
| | | const heading = Cesium.Math.toRadians(this.form.face); // 朝东南方向 |
| | |
| | | } |
| | | }, |
| | | handleSelectAddress(data) { |
| | | console.log(data) |
| | | this.$set(this.form, 'longitude', data.longitude) |
| | | this.$set(this.form, 'latitude', data.latitude) |
| | | this.$set(this.form, 'altitude', data.altitude) |
| | | this.$set(this.form, 'height', data.altitude) |
| | | this.$refs.form.validateField('longitude') |
| | | this.$refs.form.validateField('latitude') |
| | | this.$refs.form.validateField('altitude') |
| | | this.$refs.form.validateField('height') |
| | | }, |
| | | submitForm() { |
| | | this.$refs["form"].validate(valid => { |
| | | console.log(this.form) |
| | | this.form.longitude = Number(this.form.longitude) |
| | | this.form.latitude = Number(this.form.latitude) |
| | | this.form.altitude = Number(this.form.altitude) |
| | | this.form.height = Number(this.form.height) |
| | | this.form.face = Number(this.form.face) |
| | | if (valid) { |
| | | this.$api.save('tower/device/', 'id', Object.assign({}, this.form)).then(res => { |
| | |
| | | this.$message.error("请输入纬度"); |
| | | return; |
| | | } |
| | | if (!this.form.altitude) { |
| | | if (!this.form.height) { |
| | | this.$message.error("请输入高度"); |
| | | return; |
| | | } |
| | | //动态经纬度朝向 加载模型位置预览 |
| | | // const position = Cesium.Cartesian3.fromDegrees(0, 0, 0); |
| | | const position = Cesium.Cartesian3.fromDegrees(this.form.longitude, this.form.latitude, this.form.altitude); |
| | | const position = Cesium.Cartesian3.fromDegrees(this.form.longitude, this.form.latitude, this.form.height); |
| | | // 设置模型方向(可选) |
| | | // const heading = Cesium.Math.toRadians(135); // 朝东南方向 |
| | | let model = viewer.entities.getById("MyModel"); |
| | |
| | | :value="dict.value"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="模型高度" prop="modelHeight"> |
| | | <el-input v-model="form.modelHeight" placeholder="请输入模型高度" /> |
| | | </el-form-item> |
| | | <el-form-item label="文件上传" prop="modelRoute"> |
| | | <el-upload class="upload-demo" action="" :auto-upload="false" accept=".glb" |
| | | :on-change="getFile" :limit="1"> |
| | |
| | | modelName: [ |
| | | { required: true, message: '请输入模型名称', trigger: 'blur' } |
| | | ], |
| | | deptId: [ |
| | | { required: true, message: '归属部门' } // trigger监听不到 使用@input单独校验vue-treeSelect表单项 |
| | | ] |
| | | modelHeight: [ |
| | | { required: true, message: '请输入模型名称', trigger: 'blur' } |
| | | ], |
| | | }, |
| | | // 部门数据 |
| | | deptOptions: null, |
| | |
| | | this.open = true |
| | | this.$nextTick(() => { |
| | | this.$refs.cesiumMapNoSelect.clearMap() |
| | | this.addModel() |
| | | this.addModel(this.form) |
| | | }) |
| | | }) |
| | | } else { |
| | |
| | | } |
| | | }); |
| | | }, |
| | | addModel(){ |
| | | addModel(row){ |
| | | console.log(window) |
| | | console.log(window.viewer) |
| | | // viewer.entities.add({ |
| | | // position: Cesium.Cartesian3.fromDegrees(0, 0, 0), |
| | | // model: { |
| | | // uri: "/Model/tower.glb", |
| | | // scale: 10000, |
| | | // minimumPixelSize: 50, |
| | | // }, |
| | | // }); |
| | | // const position = Cesium.Cartesian3.fromDegrees(139.745433, 35.658581, 0); |
| | | const position = Cesium.Cartesian3.fromDegrees(0, 0, 0); |
| | | |
| | | // 设置模型方向(可选) |
| | | const heading = Cesium.Math.toRadians(135); // 朝东南方向 |
| | | const heading = Cesium.Math.toRadians(0); // 朝东南方向 |
| | | const pitch = 0; |
| | | const roll = 0; |
| | | const orientation = Cesium.Transforms.headingPitchRollQuaternion( |
| | | position, |
| | | new Cesium.HeadingPitchRoll(heading, pitch, roll) |
| | | ); |
| | | if(row){ |
| | | const entity = viewer.entities.add({ |
| | | name: "MyModel", |
| | | position: position, |
| | | orientation: orientation, |
| | | model: { |
| | | uri: row.modelRoute, // 替换成你的模型路径 |
| | | }, |
| | | }); |
| | | console.log(entity) |
| | | |
| | | // 加载 glTF 模型 |
| | | const entity = viewer.entities.add({ |
| | | name: "MyModel", |
| | | position: position, |
| | | orientation: orientation, |
| | | model: { |
| | | uri: "/Model/tower.glb", // 替换成你的模型路径 |
| | | }, |
| | | }); |
| | | console.log(entity) |
| | | |
| | | // 飞行到模型位置 |
| | | viewer.flyTo(entity) |
| | | // 飞行到模型位置 |
| | | viewer.flyTo(entity) |
| | | } |
| | | }, |
| | | cancel() { |
| | | this.$refs.cesiumMapNoSelect.clearMap() |
| | |
| | | <el-col :span=6> |
| | | <el-card class="noScroll"> |
| | | <div class="chooseModel"> |
| | | <!-- <el-button type="primary" @click='chooseModel'>添加设备</el-button> --> |
| | | <div class="fontJust">设备列表</div> |
| | | <el-button @click="addDevice"> 新增</el-button> |
| | | <el-button @click="draw"> 渲染</el-button> |
| | | <el-button @click="test"> 转换</el-button> |
| | | <el-button @click="huixian"> 0.0</el-button> |
| | | <el-table |
| | | :data="tableData" |
| | | max-height = '180' |
| | |
| | | import CesiumMap from "../../../../utils/components/cesium-map.vue"; |
| | | import chooseDeviceDialog from './chooseDeviceDialog.vue'; |
| | | import chooseModelDialog from './chooseModelDialog.vue'; |
| | | import { obtainRealData} from "@/api/system/template" |
| | | |
| | | export default{ |
| | | components: { |
| | | CesiumMap, |
| | |
| | | return{ |
| | | dialogVisible :true, |
| | | tableData: [], |
| | | treeData:[ |
| | | { |
| | | "createBy": null, |
| | | "createTime": null, |
| | | "updateBy": null, |
| | | "updateTime": null, |
| | | "remark": null, |
| | | "id": "3c5fc76c46c54c1187ff0bbcc092194b", |
| | | "modelId": "6257cf734cf94c7caae0dee2ac2231d1", |
| | | "deviceName": "设备3", |
| | | "deviceType": null, |
| | | "longitude": 125.01255362568844, |
| | | "latitude": 46.40803605631184, |
| | | "altitude": -0.029793403136164368, |
| | | "belongingRoute": "线路3", |
| | | "face": 30, |
| | | "label": "设备3", |
| | | "children":[ |
| | | { |
| | | "id": "197f211797aa9f32", |
| | | "label": "地面点0", |
| | | "longitude": 125.01254690233337, |
| | | "latitude": 46.408037041988585, |
| | | "height": 5.517266389025914, |
| | | "children": [ |
| | | { |
| | | "id": "197f211797afb196", |
| | | "label": "空中点0", |
| | | "longitude": 125.01240358310912, |
| | | "latitude": 46.40814584281285, |
| | | "height": 6.971525719304772 |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "id": "197f211797af91d9", |
| | | "label": "地面点1", |
| | | "longitude": 125.01254808759698, |
| | | "latitude": 46.4080365594918, |
| | | "height": 7.385339183474696, |
| | | "children": [ |
| | | { |
| | | "id": "197f211797afdb9a", |
| | | "label": "空中点1", |
| | | "longitude": 125.0125163640242, |
| | | "latitude": 46.407960727919516, |
| | | "height": 10.451384666363694 |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "id": "197f211797afab31", |
| | | "label": "地面点2", |
| | | "longitude": 125.01255947706582, |
| | | "latitude": 46.408036885119245, |
| | | "height": 7.42469267651616, |
| | | "children": [ |
| | | { |
| | | "id": "197f211797a61300", |
| | | "label": "空中点2", |
| | | "longitude": 125.0128655208287, |
| | | "latitude": 46.4080332165472, |
| | | "height": 14.51791089195843 |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "id": "197f211797af21e7", |
| | | "label": "地面点3", |
| | | "longitude": 125.01256023273389, |
| | | "latitude": 46.408036999460684, |
| | | "height": 5.5171023712317435, |
| | | "children": [ |
| | | { |
| | | "id": "197f211797a19b34", |
| | | "label": "空中点3", |
| | | "longitude": 125.01277085845463, |
| | | "latitude": 46.40822397536244, |
| | | "height": 16.06139535507995 |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "createBy": null, |
| | | "createTime": null, |
| | | "updateBy": null, |
| | | "updateTime": null, |
| | | "remark": null, |
| | | "id": "5d7c595466094e369c6ed9fdcab6ba50", |
| | | "modelId": "416a0c3361a9409495623eff5c19fb41", |
| | | "deviceName": "设备2", |
| | | "deviceType": null, |
| | | "longitude": 124.98495711631958, |
| | | "latitude": 46.60913669289758, |
| | | "altitude": -0.010649270561847658, |
| | | "belongingRoute": "线路2", |
| | | "face": 30, |
| | | "label": "设备2", |
| | | "children": [ |
| | | { |
| | | "id": "197f2157b83d1d1e", |
| | | "label": "地面点0", |
| | | "longitude": 124.98495046473204, |
| | | "latitude": 46.60913764437918, |
| | | "height": 5.517192953851729, |
| | | "children": [ |
| | | { |
| | | "id": "197f2157b833e7e6", |
| | | "label": "空中点0", |
| | | "longitude": 124.98487290823232, |
| | | "latitude": 46.609159110536, |
| | | "height": 8.492315413669576 |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "id": "197f2157b83cb37c", |
| | | "label": "地面点1", |
| | | "longitude": 124.98495132002881, |
| | | "latitude": 46.609137518901555, |
| | | "height": 7.424720940488529, |
| | | "children": [ |
| | | { |
| | | "id": "197f2157b83dbf31", |
| | | "label": "空中点1", |
| | | "longitude": 124.984847808066, |
| | | "latitude": 46.60911367086078, |
| | | "height": 8.37839897370324 |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "id": "197f2157b831259d", |
| | | "label": "地面点2", |
| | | "longitude": 124.98496295996078, |
| | | "latitude": 46.60913752946039, |
| | | "height": 7.424330357264399, |
| | | "children": [ |
| | | { |
| | | "id": "197f2157b837245b", |
| | | "label": "空中点2", |
| | | "longitude": 124.98502199892675, |
| | | "latitude": 46.60913926099941, |
| | | "height": 12.416325107963392 |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "id": "197f2157b83112ee", |
| | | "label": "地面点3", |
| | | "longitude": 124.9849638899571, |
| | | "latitude": 46.60913769557282, |
| | | "height": 5.51721178277007, |
| | | "children": [ |
| | | { |
| | | "id": "197f2157b8349c7d", |
| | | "label": "空中点3", |
| | | "longitude": 124.98502033157477, |
| | | "latitude": 46.609152323278046, |
| | | "height": 4.804689162058357 |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "createBy": null, |
| | | "createTime": null, |
| | | "updateBy": null, |
| | | "updateTime": null, |
| | | "remark": null, |
| | | "id": "f796896ac1c445c183456c500502bef0", |
| | | "modelId": "1bd29eedeaaf4a3da83212fbb1793fd5", |
| | | "deviceName": "设备1", |
| | | "deviceType": null, |
| | | "longitude": 125.14336018333184, |
| | | "latitude": 46.558980802047344, |
| | | "altitude": -0.0019061848373990704, |
| | | "belongingRoute": "线路1", |
| | | "face": 60, |
| | | "label": "设备1", |
| | | "children": [ |
| | | { |
| | | "id": "197f21d1d1a28cf6", |
| | | "label": "地面点0", |
| | | "longitude": 125.14335344922452, |
| | | "latitude": 46.558982037049276, |
| | | "height": 5.556334669315725, |
| | | "children": [ |
| | | { |
| | | "id": "197f21d1d1adcbe6", |
| | | "label": "空中点0", |
| | | "longitude": 125.14330233595797, |
| | | "latitude": 46.55904743869546, |
| | | "height": 6.468726016875199 |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "id": "197f21d1d1a4aa12", |
| | | "label": "地面点1", |
| | | "longitude": 125.14335458905991, |
| | | "latitude": 46.558981268478746, |
| | | "height": 7.384477227891685, |
| | | "children": [ |
| | | { |
| | | "id": "197f21d1d1a846ae", |
| | | "label": "空中点1", |
| | | "longitude": 125.14298096389273, |
| | | "latitude": 46.558969173376134, |
| | | "height": 22.10867400719622 |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "id": "197f21d1d1a52190", |
| | | "label": "地面点2", |
| | | "longitude": 125.14336589537841, |
| | | "latitude": 46.558981709304724, |
| | | "height": 7.424676991507425, |
| | | "children": [ |
| | | { |
| | | "id": "197f21d1d1a6a4fe", |
| | | "label": "空中点2", |
| | | "longitude": 125.14339720378332, |
| | | "latitude": 46.5590446327473, |
| | | "height": 16.720685909327106 |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "id": "197f21d1d1a272b1", |
| | | "label": "地面点3", |
| | | "longitude": 125.14336689453488, |
| | | "latitude": 46.558981604123645, |
| | | "height": 5.516875737104807, |
| | | "children": [ |
| | | { |
| | | "id": "197f21d1d1af7638", |
| | | "label": "空中点3", |
| | | "longitude": 125.14397230855407, |
| | | "latitude": 46.55882377669704, |
| | | "height": 45.87173852318548 |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | treeData:[], |
| | | defaultProps: { |
| | | children: 'children', |
| | | label: 'label' |
| | |
| | | }, |
| | | methods:{ |
| | | handleClose(){ |
| | | console.log("close") |
| | | this.dialogVisible = false |
| | | this.$emit('close') |
| | | }, |
| | | flyToLocal(row){ |
| | | console.log(row) |
| | | console.log(viewer) |
| | | // const position = Cesium.Cartesian3.fromDegrees(row.longitude,row.latitude, row.altitude); |
| | | const position = Cesium.Cartesian3.fromDegrees(0,0,0); |
| | | const position = Cesium.Cartesian3.fromDegrees(row.longitude,row.latitude, row.altitude); |
| | | |
| | | // 设置模型方向(可选) |
| | | const heading = Cesium.Math.toRadians(row.face); // 朝东南方向 |
| | |
| | | position: position, |
| | | orientation: orientation, |
| | | model: { |
| | | uri: "http://192.168.1.5:9000/tower/2025/07/11/铁塔_20250711093701A001.glb", // 替换成你的模型路径 |
| | | uri: row?.ardTowerModel.modelRoute, // 替换成你的模型路径 |
| | | scale: 1, |
| | | }, |
| | | label: { |
| | |
| | | type: 'warning' |
| | | }) |
| | | } |
| | | this.tableData = this.tableData.concat(arr) |
| | | this.tableData = this.treeData.concat(arr) |
| | | } |
| | | const dealTreeData =this.dealTee() |
| | | // this.treeData = dealTreeData |
| | | console.log(this.treeData) |
| | | this.treeData = dealTreeData |
| | | }, |
| | | dealTee(){ |
| | | console.log(this.tableData) |
| | | return this.tableData.map(item => ({ |
| | | ...item, |
| | | label: item.deviceName, |
| | | children: [] |
| | | })); |
| | | }, |
| | | deleteData(row){ |
| | | // 找到 id 为 "1" 的元素索引 |
| | | const index = this.tableData.findIndex(item => item.id === row.id); |
| | | |
| | | // 如果找到了,删除该元素 |
| | | if (index !== -1) { |
| | | this.tableData.splice(index, 1); |
| | | } |
| | | const dealTreeData = this.dealTee() |
| | | // this.treeData = dealTreeData |
| | | this.treeData = dealTreeData |
| | | }, |
| | | chooseModel(row){ |
| | | this.deviceId = row.id |
| | |
| | | receiveModel(obj){ |
| | | //deal逻辑 |
| | | console.log(obj) |
| | | let flightTemplateId =obj.modelObj.id |
| | | let deviceId = obj.deviceId |
| | | this.dealTableTemplate(obj) |
| | | // let |
| | | obtainRealData(flightTemplateId,deviceId).then(res=>{ |
| | | console.log(res) |
| | | let treeDealData = this.transformFlightData(res.data?.coordinateSystemVoS || []) |
| | | console.log(treeDealData) |
| | | this.dealTreeMerge(obj,treeDealData) |
| | | // const aaa = this.rotateAllPoints(this.treeData || [],res.data.longitude,res.data.latitude,res.data.height) |
| | | this.drawConnectionsWithLabels(this.treeData) |
| | | }) |
| | | // this.dealTreeMerge(obj) |
| | | }, |
| | | //返回数据转换树结构 |
| | | transformFlightData(data) { |
| | | const result = []; |
| | | |
| | | data.forEach(item => { |
| | | // 找到第一个 groundPoint,作为代表 |
| | | const groundPoint = item.groundPointVo?.[0]; |
| | | |
| | | // 生成 children 节点 |
| | | const children = groundPoint ? [{ |
| | | id: groundPoint.id, |
| | | label: groundPoint.targetName, |
| | | longitude: groundPoint.longitude, |
| | | latitude: groundPoint.latitude, |
| | | height: groundPoint.height |
| | | }] : []; |
| | | |
| | | // 生成空中点 |
| | | result.push({ |
| | | id: item.id, |
| | | label: item.targetName, |
| | | longitude: item.longitude, |
| | | latitude: item.latitude, |
| | | height: item.altitude, |
| | | children |
| | | }); |
| | | }); |
| | | |
| | | return result; |
| | | }, |
| | | dealTableTemplate(obj){ |
| | | const target = this.tableData.find(item => item.id === obj.deviceId) |
| | | if (target) { |
| | | this.$set(target, 'mode', obj.modelObj.name) // ✅ Vue2 需要使用 $set 以确保响应式 |
| | | const targetTableData = this.tableData.find(item => item.id === obj.deviceId) |
| | | const targetTreeData = this.treeData.find(item => item.id === obj.deviceId) |
| | | if (targetTableData) { |
| | | this.$set(targetTableData, 'mode', obj.modelObj.templateName) // ✅ Vue2 需要使用 $set 以确保响应式 |
| | | } |
| | | if (targetTreeData) { |
| | | this.$set(targetTreeData, 'mode', obj.modelObj.templateName) // ✅ Vue2 需要使用 $set 以确保响应式 |
| | | } |
| | | }, |
| | | dealTreeMerge(obj){ |
| | | let newChildrenData= [ |
| | | { id: 100, label: '新子节点A',children:[{id: 1001,label: '新子节点A-1'}]}, |
| | | { id: 101, label: '新子节点B' } |
| | | ] |
| | | dealTreeMerge(obj,data){ |
| | | this.treeData.forEach(item => { |
| | | if(item.id == obj.deviceId) { |
| | | // 替换第一层每个节点的 children |
| | | this.$set(item, 'children', JSON.parse(JSON.stringify(newChildrenData))); |
| | | this.$set(item, 'children', JSON.parse(JSON.stringify(data))); |
| | | } |
| | | }); |
| | | }, |
| | | drawConnectionsWithLabels1111(devices) { |
| | | const airPoints = []; |
| | | |
| | | devices.forEach(device => { |
| | | if (!Array.isArray(device.children)) return; |
| | | |
| | | device.children.forEach(groundPoint => { |
| | | console.log(groundPoint) |
| | | const groundPos = Cesium.Cartesian3.fromDegrees( |
| | | groundPoint.longitude, |
| | | groundPoint.latitude, |
| | | groundPoint.height |
| | | ); |
| | | |
| | | // ✅ 地面点:添加实体 + label |
| | | viewer.entities.add({ |
| | | position: groundPos, |
| | | point: { |
| | | pixelSize: 6, |
| | | color: Cesium.Color.BLUE |
| | | }, |
| | | label: { |
| | | text: groundPoint.label || '', |
| | | font: '14px sans-serif', |
| | | fillColor: Cesium.Color.WHITE, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | outlineWidth: 2, |
| | | outlineColor: Cesium.Color.BLACK, |
| | | verticalOrigin: Cesium.VerticalOrigin.BOTTOM, |
| | | pixelOffset: new Cesium.Cartesian2(0, -12) |
| | | } |
| | | }); |
| | | |
| | | // 遍历空中点 |
| | | if (Array.isArray(groundPoint.children)) { |
| | | groundPoint.children.forEach(airPoint => { |
| | | console.log(airPos) |
| | | const airPos = Cesium.Cartesian3.fromDegrees( |
| | | airPoint.longitude, |
| | | airPoint.latitude, |
| | | airPoint.height |
| | | ); |
| | | |
| | | // ✅ 空中点:添加实体 + label |
| | | viewer.entities.add({ |
| | | position: airPos, |
| | | point: { |
| | | pixelSize: 6, |
| | | color: Cesium.Color.YELLOW |
| | | }, |
| | | label: { |
| | | text: airPoint.label || '', |
| | | font: '14px sans-serif', |
| | | fillColor: Cesium.Color.YELLOW, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | outlineWidth: 2, |
| | | outlineColor: Cesium.Color.BLACK, |
| | | verticalOrigin: Cesium.VerticalOrigin.BOTTOM, |
| | | pixelOffset: new Cesium.Cartesian2(0, -12) |
| | | } |
| | | }); |
| | | |
| | | // ✅ 地面点 ➜ 空中点 蓝色虚线 |
| | | viewer.entities.add({ |
| | | polyline: { |
| | | positions: [groundPos, airPos], |
| | | width: 2, |
| | | material: new Cesium.PolylineDashMaterialProperty({ |
| | | color: Cesium.Color.BLUE, |
| | | dashLength: 8 |
| | | }) |
| | | } |
| | | }); |
| | | |
| | | airPoints.push(airPos); |
| | | }); |
| | | } |
| | | }); |
| | | }); |
| | | |
| | | // ✅ 所有空中点 ➜ 黄色实线连接 |
| | | if (airPoints.length > 1) { |
| | | viewer.entities.add({ |
| | | polyline: { |
| | | positions: airPoints, |
| | | width: 3, |
| | | material: Cesium.Color.YELLOW |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | drawConnectionsWithLabels(devices) { |
| | | const airPoints = []; |
| | |
| | | }); |
| | | } |
| | | }, |
| | | draw(){ |
| | | this.drawConnectionsWithLabels(this.treeData) |
| | | }, |
| | | test(){ |
| | | this.treeData = this.swapGroundAir(this.treeData); |
| | | }, |
| | | swapGroundAir(data) { |
| | | |
| | | return data.map(device => { |
| | | const newChildren = []; |
| | | |
| | | device.children.forEach(ground => { |
| | | const air = ground.children && ground.children[0]; |
| | | if (air) { |
| | | newChildren.push({ |
| | | ...air, |
| | | children: [ |
| | | { |
| | | ...ground, |
| | | children: undefined |
| | | } |
| | | ] |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | return { |
| | | ...device, |
| | | children: newChildren |
| | | rotateAllPoints(dataList,towerLongitude,towerLatitude,towerhHight) { |
| | | return dataList.map(item => { |
| | | console.log(item) |
| | | console.log(towerLongitude) |
| | | console.log(towerLatitude) |
| | | console.log(towerhHight) |
| | | const groundPoint = Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude, item.height); |
| | | const towerPoint = Cesium.Cartesian3.fromDegrees(towerLongitude, towerLatitude, towerhHight); |
| | | let rotationAngle = Cesium.Math.toRadians(135) |
| | | // 旋转地面点本身(会变,但绕自身旋转不会移动) |
| | | const newGroundPoint = this.rotateAroundPoint( groundPoint,towerPoint, rotationAngle); |
| | | const newGroundCarto = Cesium.Cartographic.fromCartesian(newGroundPoint); |
| | | const newGround = { |
| | | ...item, |
| | | longitude: Cesium.Math.toDegrees(newGroundCarto.longitude), |
| | | latitude: Cesium.Math.toDegrees(newGroundCarto.latitude), |
| | | height: newGroundCarto.height |
| | | }; |
| | | }); |
| | | }, |
| | | huixian(){ |
| | | let data=[ |
| | | { |
| | | "altitude": 35.09683139439875, |
| | | "ardGroundPoint": [ |
| | | { |
| | | "height": 35.0960134603141, |
| | | "latitude": 0.000032899894086000126, |
| | | "longitude": 3.2789183307897707e-7, |
| | | "pointNumber": 1, |
| | | "targetName": "地面点0" |
| | | } |
| | | ], |
| | | "latitude": 0.0009372188427979371, |
| | | "longitude": 0.000009340650264268872, |
| | | "pointNumber": 1, |
| | | "targetName": "空中点0" |
| | | }, |
| | | { |
| | | "altitude": 40.057437157900914, |
| | | "ardGroundPoint": [ |
| | | { |
| | | "height": 40.05662385374772, |
| | | "latitude": 0.00002759265968150938, |
| | | "longitude": 7.877836487599675e-7, |
| | | "pointNumber": 1, |
| | | "targetName": "地面点1" |
| | | } |
| | | ], |
| | | "latitude": 0.0009315830781716235, |
| | | "longitude": 0.000026597143043885405, |
| | | "pointNumber": 2, |
| | | "targetName": "空中点1" |
| | | }, |
| | | { |
| | | "altitude": 90.05743715790092, |
| | | "ardGroundPoint": [ |
| | | { |
| | | "height": 40.05662385374772, |
| | | "latitude": 0.00002759265968150938, |
| | | "longitude": 7.877836487599675e-7, |
| | | "pointNumber": 1, |
| | | "targetName": "地面点1-加高" |
| | | } |
| | | ], |
| | | "latitude": 0.0009315830781716235, |
| | | "longitude": 0.000026597143043885405, |
| | | "pointNumber": 3, |
| | | "targetName": "空中点1-加高" |
| | | }, |
| | | { |
| | | "altitude": 85.4017386642163, |
| | | "ardGroundPoint": [ |
| | | { |
| | | "height": 35.09000336658791, |
| | | "latitude": -0.0000329911085806409, |
| | | "longitude": 4.656954257439534e-7, |
| | | "pointNumber": 1, |
| | | "targetName": "地面点2" |
| | | } |
| | | ], |
| | | "latitude": -0.0009372610742669285, |
| | | "longitude": 0.000013144727598247196, |
| | | "pointNumber": 4, |
| | | "targetName": "空中点2-加高" |
| | | }, |
| | | { |
| | | "altitude": 35.401738664216296, |
| | | "ardGroundPoint": [ |
| | | { |
| | | "height": 35.09000336658791, |
| | | "latitude": -0.0000329911085806409, |
| | | "longitude": 4.656954257439534e-7, |
| | | "pointNumber": 1, |
| | | "targetName": "地面点2" |
| | | } |
| | | ], |
| | | "latitude": -0.0009372610742669285, |
| | | "longitude": 0.000013144727598247196, |
| | | "pointNumber": 5, |
| | | "targetName": "空中点2" |
| | | } |
| | | ] |
| | | let aaa = this.convertToTree(data) |
| | | console.log(aaa) |
| | | this.drawLines(aaa) |
| | | }, |
| | | convertToTree(data) { |
| | | return data.map((item, index) => { |
| | | const parentId = 'air_' + index; |
| | | return { |
| | | id: parentId, |
| | | label: item.targetName, |
| | | longitude: item.longitude, |
| | | latitude: item.latitude, |
| | | height: item.altitude, |
| | | children: (item.ardGroundPoint || []).map((g, i) => { |
| | | return { |
| | | id: parentId + '_ground_' + i, |
| | | label: g.targetName, |
| | | longitude: g.longitude, |
| | | latitude: g.latitude, |
| | | height: g.height |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }, |
| | | drawLines(treeData) { |
| | | console.log(treeData) |
| | | // 收集空中点位置 |
| | | const airPositions = treeData.map(point => { |
| | | return Cesium.Cartesian3.fromDegrees( |
| | | point.longitude, |
| | | point.latitude, |
| | | point.height |
| | | ); |
| | | }); |
| | | console.log(newGround) |
| | | // 处理子空中点 |
| | | newGround.children = item.children.map(child => { |
| | | const airPoint = Cesium.Cartesian3.fromDegrees(child.longitude, child.latitude, child.height); |
| | | const rotatedAirPoint = this.rotateAroundPoint( airPoint,towerPoint, rotationAngle); |
| | | const rotatedAirCarto = Cesium.Cartographic.fromCartesian(rotatedAirPoint); |
| | | |
| | | // 1. 空中点之间用黄色实线连接 |
| | | viewer.entities.add({ |
| | | polyline: { |
| | | positions: airPositions, |
| | | width: 2, |
| | | material: Cesium.Color.YELLOW |
| | | } |
| | | }); |
| | | |
| | | // 2. 每个空中点与地面点用蓝色虚线连接 |
| | | treeData.forEach(point => { |
| | | const airPos = Cesium.Cartesian3.fromDegrees(point.longitude, point.latitude, point.height); |
| | | point.children.forEach(child => { |
| | | const groundPos = Cesium.Cartesian3.fromDegrees(child.longitude, child.latitude, child.height); |
| | | viewer.entities.add({ |
| | | polyline: { |
| | | positions: [airPos, groundPos], |
| | | width: 1, |
| | | material: new Cesium.PolylineDashMaterialProperty({ |
| | | color: Cesium.Color.BLUE, |
| | | dashLength: 8 |
| | | }) |
| | | } |
| | | }); |
| | | return { |
| | | ...child, |
| | | longitude: Cesium.Math.toDegrees(rotatedAirCarto.longitude), |
| | | latitude: Cesium.Math.toDegrees(rotatedAirCarto.latitude), |
| | | height: rotatedAirCarto.height |
| | | }; |
| | | }); |
| | | |
| | | return newGround; |
| | | }); |
| | | }, |
| | | // 计算点A绕点B逆时针旋转指定角度后的新位置 |
| | | // 空中点或者地面点笛卡尔坐标 塔的笛卡尔坐标 塔的朝向值 |
| | | rotateAroundPoint(startPoint,pivotPoint,rotationAngle) { |
| | | // 创建一个从B点到本地坐标系的转换矩阵(东方向为X轴,北方向为Y轴,垂直方向为Z轴) |
| | | const transformationMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(pivotPoint); |
| | | // 获取世界坐标系到本地坐标系的转换矩阵 |
| | | const inverseTransformationMatrix = Cesium.Matrix4.inverse(transformationMatrix,new Cesium.Matrix4()); |
| | | // 将A点转换到局部坐标系中 |
| | | const localStartPoint = Cesium.Matrix4.multiplyByPoint(inverseTransformationMatrix, startPoint,new Cesium.Cartesian3()); |
| | | // 计算A点在局部坐标系中逆时针旋转指定角度后的新位置 |
| | | const rotatedX = localStartPoint.x * Math.cos(rotationAngle) + localStartPoint.y * Math.sin(rotationAngle); |
| | | const rotatedY = localStartPoint.y * Math.cos(rotationAngle) - localStartPoint.x * Math.sin(rotationAngle); |
| | | const rotatedZ = localStartPoint.z; // Z轴坐标保持不变 |
| | | // 将旋转后的局部坐标转换回世界坐标系 |
| | | return Cesium.Matrix4.multiplyByPoint(transformationMatrix, new Cesium.Cartesian3(rotatedX, rotatedY, rotatedZ), new Cesium.Cartesian3()); |
| | | } |
| | | } |
| | | } |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="选择模板" |
| | | title="选择飞行模板" |
| | | :visible.sync="dialogVisible" |
| | | @close="cancel" |
| | | width="20%"> |
| | | <el-form ref="form" :model="form" label-width="80px" :rules="rules"> |
| | | <el-form-item label="模板"> |
| | | <el-select v-model="form.modelObj" placeholder="请选择模板"> |
| | | <el-form-item label="飞行模板"> |
| | | <el-select v-model="form.modelObj" placeholder="请选择飞行模板" @change="handleChange"> |
| | | <el-option |
| | | v-for="item in templateArr" |
| | | :key="item.id" |
| | | :label="item.name" |
| | | :value="item"> |
| | | :label="item.templateName" |
| | | :value="item.id"> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | |
| | | </el-form> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import { flyDataInfo} from "@/api/system/template" |
| | | export default { |
| | | name:'chooseModelDialog', |
| | | components: { |
| | |
| | | }, |
| | | ], |
| | | selectArr:[], |
| | | form:{}, |
| | | templateArr:[ |
| | | { |
| | | id:111, |
| | | name:'模板1' |
| | | }, |
| | | { |
| | | id:222, |
| | | name:'模板2' |
| | | }, |
| | | { |
| | | id:333, |
| | | name:'模板3' |
| | | } |
| | | ], |
| | | form:{ |
| | | }, |
| | | templateArr:[], |
| | | rules:{ |
| | | modelObj: [ |
| | | { required: true, message: '请选择模板', trigger: 'change' } |
| | |
| | | mounted() { |
| | | console.log(this.deviceId) |
| | | if(this.deviceId){ |
| | | flyDataInfo(this.deviceId).then(res=>{ |
| | | console.log(res) |
| | | if(res.code == 200 ) { |
| | | this.templateArr = res.rows |
| | | } |
| | | }) |
| | | //点击模板查询设备下的关联模型的所有模板 |
| | | } |
| | | }, |
| | |
| | | cancel(){ |
| | | this.$emit('cancelModel') |
| | | }, |
| | | handleChange(value){ |
| | | this.form.deviceId = this.deviceId |
| | | this.form.modelObj =this.templateArr.find(item => item.id === value) |
| | | }, |
| | | submit(){ |
| | | // this.selectArr |
| | | //反显参数传递option对象 |
| | | this.form.deviceId = this.deviceId |
| | | console.log(this.form) |
| | | // //反显参数传递option对象 |
| | | // this.form.deviceId = this.deviceId |
| | | // console.log(this.form) |
| | | this.$emit('receiveModel',this.form) |
| | | this.$emit('cancelModel') |
| | | }, |
| | |
| | | <div class="app-container"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span=24 :xs="24"> |
| | | <AppTable ref="AppTable" selection :showDeptSearch="false" :url="'tower/point/list'" :tableColumns="tableColumns" |
| | | <AppTable ref="AppTable" selection :showDeptSearch="false" :url="'tower/project/list'" :tableColumns="tableColumns" |
| | | :tableFilter="tableFilter"> |
| | | <template #operatorBox="{ row }"> |
| | | <el-button type="primary" plain icon="el-icon-plus" size="mini" |
| | |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import { compileToFunctions } from "vue-template-compiler"; |
| | | import CesiumMap from "../../../../utils/components/cesium-map.vue"; |
| | | import InitMap from "../../../../utils/components/init-map.vue"; |
| | | import ChooseModelDialog from './chooseModelDialog.vue'; |
| | | import { addPoint} from "@/api/system/template" |
| | | let globalon = 0 |
| | | import { addPoint , getPointInfo} from "@/api/system/template" |
| | | let globalon = 0 |
| | | let globalat = 0 |
| | | let towerHeight = 47.47 |
| | | const centerCartesian = Cesium.Cartesian3.fromDegrees(globalon,globalat , 0) |
| | | //塔的朝向算法所用到的 旋转度数 |
| | | let rotationAngle = Cesium.Math.toRadians(0) |
| | | let relativeData |
| | | export default{ |
| | | name:'shootPointDialog', |
| | | components: { |
| | | CesiumMap, |
| | | ChooseModelDialog, |
| | | InitMap |
| | | }, |
| | | props: { |
| | | templateId: { |
| | | type: String, |
| | | defaule: null |
| | | } |
| | | }, |
| | | data(){ |
| | | return{ |
| | |
| | | } |
| | | }, |
| | | mounted(){ |
| | | if(this.templateId) { |
| | | //预览逻辑 |
| | | getPointInfo(this.templateId).then(res=>{ |
| | | if(res.code == 200 ) { |
| | | this.getRowData(res.data) |
| | | let drawArr = this.convertToTree(res.data.ardListWayPointsLS) |
| | | setTimeout(() => { |
| | | //渲染时间问题 加个延时器 |
| | | this.drawLines(drawArr) |
| | | }, 500); |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | methods:{ |
| | | convertToTree(data) { |
| | | return data.map((item, index) => { |
| | | const parentId = 'air_' + index; |
| | | return { |
| | | id: parentId, |
| | | label: item.targetName, |
| | | longitude: item.longitude, |
| | | latitude: item.latitude, |
| | | height: item.altitude, |
| | | children: (item.ardGroundPoint || []).map((g, i) => { |
| | | return { |
| | | id: parentId + '_ground_' + i, |
| | | label: g.targetName, |
| | | longitude: g.longitude, |
| | | latitude: g.latitude, |
| | | height: g.height |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }, |
| | | drawLines(treeData) { |
| | | console.log(treeData) |
| | | console.log(window) |
| | | console.log(window.viewerM) |
| | | let viewer = window.viewerM |
| | | |
| | | // 收集空中点位置 |
| | | const airPositions = treeData.map(point => { |
| | | return Cesium.Cartesian3.fromDegrees( |
| | | point.longitude, |
| | | point.latitude, |
| | | point.height |
| | | ); |
| | | }); |
| | | |
| | | // 1. 空中点之间用黄色实线连接 |
| | | viewer.entities.add({ |
| | | polyline: { |
| | | positions: airPositions, |
| | | width: 2, |
| | | material: Cesium.Color.YELLOW |
| | | } |
| | | }); |
| | | |
| | | // 2. 每个空中点与地面点用蓝色虚线连接 |
| | | treeData.forEach(point => { |
| | | const airPos = Cesium.Cartesian3.fromDegrees(point.longitude, point.latitude, point.height); |
| | | point.children.forEach(child => { |
| | | const groundPos = Cesium.Cartesian3.fromDegrees(child.longitude, child.latitude, child.height); |
| | | viewer.entities.add({ |
| | | polyline: { |
| | | positions: [airPos, groundPos], |
| | | width: 1, |
| | | material: new Cesium.PolylineDashMaterialProperty({ |
| | | color: Cesium.Color.BLUE, |
| | | dashLength: 8 |
| | | }) |
| | | } |
| | | }); |
| | | }); |
| | | }); |
| | | }, |
| | | addPoint(viewer, position, color, label) { |
| | | viewer.entities.add({ |
| | | name: label, |
| | |
| | | return newGround; |
| | | }); |
| | | }, |
| | | //合并逻辑 将附近n米范围内的点合并 并且处理成数据 |
| | | mergePoint(arr,mergeNumber,viewer){ |
| | | this.treeData = arr |
| | | const result = this.replaceCloseChildrenWithHighestPoint(this.treeData,mergeNumber); |
| | |
| | | console.log(row) |
| | | this.modelName = row.modelName |
| | | this.templateType = row.modelType |
| | | if(this.templateId){ |
| | | this.form.templateName = row.templateName || '' |
| | | } |
| | | this.chooseModelId = row.id |
| | | towerHeight = row.towerHeight || 47.47 |
| | | this.showMap =false |
| | | this.$nextTick(()=>{ |
| | | // this.towerUrl = row.modelRoute |
| | | this.towerUrl = row.modelRoute |
| | | this.showMap = true |
| | | }) |
| | |
| | | @click="handleAdd">新增模板</el-button> |
| | | </template> |
| | | <template #operator="{ row }"> |
| | | <el-button size="mini" type="text" icon="el-icon-view" |
| | | @click="preview(row)">预览</el-button> |
| | | <el-button size="mini" type="text" icon="el-icon-delete" |
| | | @click="handleDelete(row)">删除</el-button> |
| | | </template> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <shootPointDialog @on-submit="$refs.AppTable.getData()" v-if="showDialog" @close="close"></shootPointDialog> |
| | | <shootPointDialog @on-submit="$refs.AppTable.getData()" v-if="showDialog" @close="close" :templateId="templateId"></shootPointDialog> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | } |
| | | ], |
| | | showMap:false, |
| | | showDialog:false |
| | | showDialog:false, |
| | | templateId:null |
| | | }; |
| | | }, |
| | | watch: { |
| | |
| | | methods: { |
| | | // 添加数据 |
| | | handleAdd() { |
| | | this.templateId = null |
| | | this.showMap = false |
| | | this.showDialog = true |
| | | // this.$refs.shootPointDialog.show() |
| | |
| | | // }, |
| | | close(){ |
| | | this.showDialog =false |
| | | this |
| | | }, |
| | | preview(row){ |
| | | console.log(row) |
| | | this.templateId = row.id |
| | | this.showDialog = true |
| | | } |
| | | }, |
| | | }; |