基于cesium和vue的大疆司空模仿程序

项目技术架构与模块详解

一、项目整体结构概览

本项目采用前后端分离架构,前端基于 Vue2 + Element Plus + Cesium 实现三维航线可视化与交互,后端基于 Flask 提供航线数据、文件生成、数据库存储等服务。项目目录主要分为 src(前端)和 application(后端)两大部分。

1.1 目录结构

复制代码
/c:/aaa/learn/vue2/
├── src/                # 前端源码目录
│   ├── components/     # Vue组件
│   ├── modules/        # 业务逻辑与工具模块
│   ├── utils/          # 工具函数
│   ├── stores/         # Pinia状态管理
│   ├── views/          # 页面视图
│   ├── assets/         # 静态资源
│   ├── types/          # 类型定义
│   ├── router/         # 路由配置
│   ├── main.js         # 入口文件
│   └── App.vue         # 根组件
└── backend/application/
    ├── routes/         # Flask路由
    ├── generateKml/    # KML文件生成
    ├── generateWpml/   # WPML文件生成
    ├── database.py     # 数据库连接
    ├── app.py          # Flask应用入口
    └── ...

二、前端模块详解(src目录)

2.1 组件层(components)

2.1.1 典型组件举例
  • SimulatedFlight.vue:模拟飞行主界面,负责航线点的展示、模拟飞行控制、与三维模型的联动。
  • DroneLen.vue:无人机镜头视角控制,响应模拟飞行过程中的相机参数变化。
  • ModelAdd.vue:模型导入与管理界面。
  • Upload.vue:航线导出与下载界面。
  • ImportRoute.vue:航线文件导入界面。
2.1.2 组件代码片段分析

Upload.vue 为例,展示如何通过 axios 请求后端接口并下载航线压缩包:

js 复制代码
const downloadKmz = async () => {
  try {
    const response = await axios.get('http://localhost:8080/download_kmz', {
      responseType: 'blob'
    });
    const blob = new Blob([response.data], { type: 'application/vnd.google-earth.kmz' });
    const url = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = 'airline.kmz';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    window.URL.revokeObjectURL(url);
  } catch (error) {
    ElMessage.error('下载KMZ失败: ' + (error.message || error));
  }
};

该函数实现了前端对后端生成的 KMZ 文件的下载,体现了前后端文件流交互的典型用法。

2.2 业务逻辑层(modules)

2.2.1 航线点与行为管理
  • punctateRoute/punctateRoute.js:负责航线点的绘制、编辑、行为组(actionGroup)组装、与 Cesium 三维场景的交互。
  • collectData/airlineCollect.js:航线点、无人机类型、航线名称等数据的集中存储与获取。
  • netRequest/downloadAirline.jsdownloadAirline_wpml.js:负责与后端的航线文件生成、下载相关的 API 请求。
2.2.2 关键代码片段分析

punctateRoute.js 的航点行为组组装为例:

js 复制代码
const pointInfo = {
  longitude: Cesium.Math.toDegrees(cartographic.longitude),
  latitude: Cesium.Math.toDegrees(cartographic.latitude),
  height: cartographic.height - terrainHeight,
  ellipsoidHeight: cartographic.height,
  actionGroup: index > 0 && AllPointActions[index - 1] && AllPointActions[index - 1].actions ? (() => {
    // ...
    return {
      actionGroupId: index - 1,
      actionGroupStartIndex: 1,
      actionGroupMode: 'sequence',
      actionTrigger: { actionTriggerType: 'reachPoint' },
      actions: AllPointActions[index - 1].actions.map((action, actionIndex) => ({
        actionId: actionIndex,
        actionActuatorFunc: action.actionActuatorFunc,
        actionActuatorFuncParam: {
          param: action.actionActuatorFuncParam,
        }
      }))
    };
  })() : null
};

该片段展示了如何将前端行为按钮的参数组装为后端可识别的 actionGroup 结构。

2.3 工具与状态管理

  • utils/:如 viewerManager.js 管理 Cesium Viewer 实例,cesUtil.js 提供三维空间相关工具函数。
  • stores/:如 actionButtonStore.jsflightControlStore.js,基于 Pinia 实现航点行为、飞行参数等全局状态管理。

三、后端模块详解(application目录)

3.1 路由与接口层(routes)

  • upload.py:核心路由文件,包含航线文件上传、下载、数据库存储、KMZ 压缩包生成等接口。
3.1.1 典型接口代码片段

/download_kmz 接口为例:

python 复制代码
@upload_bp.route('/download_kmz', methods=['GET'])
def download_kmz():
    try:
        base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        kml_path = os.path.join(base_dir, 'generateKml', 'output', 'airline.kml')
        wpml_path = os.path.join(base_dir, 'generateWpml', 'output', 'airline.wpml')
        
        if os.path.exists(wpmz_dir):
            shutil.rmtree(wpmz_dir)
        os.makedirs(wpmz_dir, exist_ok=True)
        shutil.copy(kml_path, os.path.join(wpmz_dir, 'template.kml'))
        shutil.copy(wpml_path, os.path.join(wpmz_dir, 'waylines.wpml'))
        zip_path = os.path.join(base_dir, 'airline.zip')
        
        with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
            for root, dirs, files in os.walk(wpmz_dir):
                for file in files:
                    file_path = os.path.join(root, file)
                    arcname = os.path.relpath(file_path, os.path.dirname(wpmz_dir))
                    zipf.write(file_path, arcname)
                    
        kmz_path = os.path.join(base_dir, 'airline.kmz')
        if os.path.exists(kmz_path):
            os.remove(kmz_path)
        os.rename(zip_path, kmz_path)
        return send_file(
            kmz_path,
            mimetype='application/vnd.google-earth.kmz',
            as_attachment=True,
            download_name='airline.kmz'
        )
    except Exception as e:
        return jsonify({'code': 500, 'message': f'生成KMZ失败: {str(e)}', 'data': None})

该接口实现了后端对航线文件的整合、压缩与下载,体现了 Python 文件操作与 Flask 文件流响应的结合。

3.2 文件生成模块

  • generateKml/kml_generator.py:负责将前端传来的航点、行为组等数据生成 DJI 兼容的 KML 文件。
  • generateWpml/wpml_generate.py:负责生成 WPML 文件,结构与 KML 类似但参数更丰富。
3.2.1 KML 生成核心代码片段
python 复制代码
def add_waypoint_action(self, placemark_element, waypoint):
    try:
        if 'actionGroup' not in waypoint or waypoint['actionGroup'] is None:
            return
        action_group_data = waypoint['actionGroup']
        if not isinstance(action_group_data, dict):
            return
        ET.SubElement(action_group, 'wpml:actionGroupId').text = str(self.action_group_index)
        self.action_group_index += 1
        trigger_data = action_group_data.get('actionTrigger', {})
        actions = action_group_data.get('actions', [])
        for action in actions:
            action_element = ET.SubElement(action_group, 'wpml:action')
            action_func = action.get('actionActuatorFunc')
            if not action_func:
                continue
            action_params = action.get('actionActuatorFuncParam', {})
            param1 = action_params.get('param1', 0)
            param2 = action_params.get('param2', 0)
            # ... 省略不同类型的参数写入 ...
    except Exception as e:
        print(f"Error in add_waypoint_action: {str(e)}")

3.3 数据库与配置

  • database.py:封装 MySQL 数据库连接,供路由层调用。
  • routes/upload.py:部分接口支持将航线点、任务配置等数据存入数据库,便于后续查询与管理。

四、前后端交互流程

  1. 用户在前端界面绘制航线、配置行为,通过 API 提交数据到后端。
  2. 后端根据数据生成 KML、WPML 文件,并存储于指定目录。
  3. 用户点击"下载"按钮,前端请求 /download_kmz,后端将 KML、WPML 整合压缩为 KMZ 返回。
  4. 用户可通过"导入"功能上传 KMZ 文件,前端解析后可还原航线。

五、技术难点与亮点分析

5.1 三维航线点与行为组的动态组装

  • 前端通过 Vue 响应式数据流,动态维护航点、行为组、参数等,确保每次导出都能反映最新配置。
  • 行为组(actionGroup)结构需严格对齐后端生成器要求,涉及多层嵌套与参数校验。

5.2 文件流与大文件处理

  • 前后端均采用流式处理,避免大文件下载时内存溢出。
  • 后端压缩包生成采用 Python 标准库 zipfile,支持多文件夹、多格式灵活打包。

5.3 跨端数据一致性

  • 前端与后端均有详细的参数注释与类型校验,减少数据结构不一致导致的 bug。
  • 通过接口文档与代码注释,团队成员可快速定位数据流向与结构。
相关推荐
moshuying10 小时前
别让AI焦虑,偷走你本该有的底气
前端·人工智能
GIS之路11 小时前
ArcPy,一个基于 Python 的 GIS 开发库简介
前端
可夫小子13 小时前
OpenClaw基础-为什么会有两个端口
前端
喝拿铁写前端13 小时前
Dify 构建 FE 工作流:前端团队可复用 AI 工作流实战
前端·人工智能
用户83562907805114 小时前
无需 Office:Python 批量转换 PPT 为图片
后端·python
喝咖啡的女孩14 小时前
React 合成事件系统
前端
从文处安14 小时前
「九九八十一难」组合式函数到底有什么用?
前端·vue.js
前端Hardy14 小时前
面试官:JS数组的常用方法有哪些?这篇总结让你面试稳了!
javascript·面试
用户59625857360614 小时前
戴上AI眼镜逛花市——感受不一样的体验
前端
yuki_uix14 小时前
Props、Context、EventBus、状态管理:组件通信方案选择指南
前端·javascript·react.js