基于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.js、downloadAirline_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.js、flightControlStore.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。
  • 通过接口文档与代码注释,团队成员可快速定位数据流向与结构。
相关推荐
人邮异步社区9 小时前
C语言好学,还是Python好学?
c语言·开发语言·python
MoRanzhi12039 小时前
122.四平方和(暴力枚举)
python·数学·算法·蓝桥杯·完全平方数·暴力枚举·四平方和定理
迪幻9 小时前
封装自己的 npm 依赖并存储到个人 GitHub
前端·npm·github
鱼宵9 小时前
工厂模式实战:消灭魔法数字,把写死的 new 收进一个厂里
开发语言·python
deepseek239 小时前
GitHub 停发 push 邮件后,自动通知怎么接?用 Python 做验签、去重与可靠入队
python·github·webhook
u0111026759 小时前
WebP 转成 PNG 后为什么更大?图片格式转换不等于压缩
前端·javascript·vue.js
万少9 小时前
Qoder sonus模型 20分钟,复刻 马斯克 飞天汽车
前端·后端·算法
昔我往昔9 小时前
chromadb 这个query_texts 查询的是基于分词还是基于向量查询的
python·chromadb
深蓝学院10 小时前
浙大高飞团队DiffWAM:不生成视频也能导航,机载延迟1.08秒,让无人机导航更快更轻
无人机·高飞
鸿业远图科技10 小时前
抚顺市_公交站点
python