基于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。
  • 通过接口文档与代码注释,团队成员可快速定位数据流向与结构。
相关推荐
用户69371750013843 小时前
Google 正在“收紧侧加载”:陌生 APK 安装或需等待 24 小时
android·前端
蓝帆傲亦3 小时前
Web 前端搜索文字高亮实现方法汇总
前端
用户69371750013843 小时前
Room 3.0:这次不是升级,是重来
android·前端·google
qq_417695054 小时前
机器学习与人工智能
jvm·数据库·python
漫随流水4 小时前
旅游推荐系统(view.py)
前端·数据库·python·旅游
yy我不解释5 小时前
关于comfyui的mmaudio音频生成插件时时间不一致问题(一)
python·ai作画·音视频·comfyui
踩着两条虫6 小时前
VTJ.PRO 核心架构全公开!从设计稿到代码,揭秘AI智能体如何“听懂人话”
前端·vue.js·ai编程
紫丁香6 小时前
AutoGen详解一
后端·python·flask
FreakStudio6 小时前
不用费劲编译ulab了!纯Mpy矩阵micronumpy库,单片机直接跑
python·嵌入式·边缘计算·电子diy
jzlhll1237 小时前
kotlin Flow first() last()总结
开发语言·前端·kotlin