Cesium 实战功能指南:三维网格剖分 + 无人机飞行仿真(开源可落地)

Cesium 实战功能指南:三维网格剖分 + 无人机飞行仿真(开源可落地)

在 Cesium 三维 GIS、数字孪生、低空无人机仿真项目中,空域网格剖分动态飞行推演是高频刚需功能。很多开源项目只实现了基础的航线绘制、简单点位移动,存在功能零散、无标准化网格、无状态回调、无法业务落地等问题。

今天给大家分享一套功能全覆盖、解耦可复用、商业级可用 的 Cesium 工具类,整合5种三维空域网格剖分全流程无人机动态仿真实时状态数据回调网格动态可视化推演核心能力,所有功能独立可单独调用,适配绝大多数低空GIS业务场景。

一、整体功能架构

整套工具类分为两大核心功能板块,所有方法解耦独立,支持按需引入、单独调用,无需冗余依赖:

  • 三维网格剖分功能:支持点、线、面、圆柱、立方体全空域剖分,自定义精度层级

  • 无人机仿真推演功能:支持飞行、暂停、续飞、重置,实时数据回调+网格动态高亮

核心优势:不绑定地图、不污染全局、无硬编码配置,Vue / React / 原生 JS 项目均可直接集成。

二、核心功能一:全场景三维网格剖分

网格剖分是空域分析、航线检测、巡检覆盖统计的基础。本工具内置10级精度网格,支持从大范围概览到精细化厘米级剖分,同时内置数量限制,杜绝页面卡顿。下面逐一讲解每一项实用功能。

2.1 单点网格剖分

针对任意经纬度、高度点位,精准匹配对应的三维网格,适用于单点空域核查、点位网格定位、坐标网格映射场景。

功能效果:自动定位点位所在立体网格,高亮展示网格范围,返回网格编码、空间范围、中心点等完整数据。

对应功能实战代码(可直接运行):

javascript 复制代码
// 单点网格剖分:查询指定坐标、高度对应的三维网格
// 定义目标点位坐标与高度
const pointParam = {
  lat: 39.9080,    // 纬度
  lon: 116.3960,   // 经度
  alt: 120         // 高度(米)
};

// 调用工具方法,7级精度剖分
// 先通过编码解析获取网格范围
const gridCode = gridSim.encode(pointParam.lat, pointParam.lon, pointParam.alt, 7);
const gridBounds = gridSim.gridInfo(gridCode);

// 绘制单点网格并获取结果
const pointGridRes = gridSim.drawPointGrid(gridBounds);

// 打印网格完整信息
console.log('单点匹配网格数据:', pointGridRes.list);
console.log('网格编码:', gridBounds.code);

2.2 航线线状网格剖分

最常用的核心功能,传入无人机起止航线点位,自动采样整条航线,生成航线全覆盖三维网格。完美适配无人机巡检航线预演、航迹覆盖统计、航线空域筛查业务。

功能亮点:自动去重网格、精准贴合飞行路径、支持自定义网格精度,可直接用于统计整条航线的覆盖空域数量。

对应功能实战代码(可直接运行):

javascript 复制代码
// 航线线状网格剖分:生成整条航线覆盖网格
// 定义航线起止点位
const lineStart = { lat: 39.9080, lon: 116.3960, alt: 120 };
const lineEnd = { lat: 39.9095, lon: 116.3980, alt: 120 };

// 7级精度剖分航线网格
const lineGridRes = gridSim.drawLineGrid(lineStart, lineEnd, 7);

// 打印航线网格结果
console.log('航线覆盖网格总数:', lineGridRes.list.length);
console.log('航线网格列表:', lineGridRes.list);

2.3 多边形面域网格剖分

支持自定义任意多边形轮廓+高度区间,实现面域立体全覆盖剖分。适用于不规则作业区域、地块巡检、自定义禁飞区网格分析。

底层采用射线法点包含算法,精准筛选多边形内部网格,剔除边缘无效网格,保证剖分结果精准无冗余。

对应功能实战代码(可直接运行):

javascript 复制代码
// 多边形面域网格剖分:不规则作业区立体网格全覆盖
// 自定义多边形轮廓点位
const polygonPoints = [
  { lat: 39.9085, lon: 116.3955 },
  { lat: 39.9095, lon: 116.3975 },
  { lat: 39.9075, lon: 116.3985 },
  { lat: 39.9065, lon: 116.3965 }
];
// 定义作业高度区间
const minAlt = 80;
const maxAlt = 150;

// 7级精度剖分多边形网格
const prismGridRes = gridSim.drawPrismGrid(polygonPoints, minAlt, maxAlt, 7);

// 打印面域网格数据
console.log('多边形面域网格总数:', prismGridRes.list.length);

2.4 圆柱空域网格剖分

传入中心点、半径、高度区间,生成圆形空域网格,适配雷达扫描范围、圆形警戒空域、定点环绕飞行空域场景,是低空安防、警戒分析的核心功能。

对应功能实战代码(可直接运行):

javascript 复制代码
// 圆柱空域网格剖分:圆形警戒/雷达空域网格
// 定义圆形空域参数
const cylinderCenter = { lat: 39.9080, lon: 116.3960 };
const radius = 80; // 空域半径 80米
const cylMinAlt = 60;
const cylMaxAlt = 200;

// 7级精度生成圆柱网格
const cylinderGridRes = gridSim.drawCylinderGrid(cylinderCenter, radius, cylMinAlt, cylMaxAlt, 7);

console.log('圆柱空域网格总数:', cylinderGridRes.list.length);

2.5 立方体空域网格剖分

通过经纬度极值+高度区间构建立体空域,实现规整矩形空域剖分,适用于固定作业区块、空域区块划分、批量网格统计。

对应功能实战代码(可直接运行):

javascript 复制代码
// 立方体空域网格剖分:矩形规整空域批量剖分
// 定义矩形经纬度范围 & 高度范围
const cuboidParams = {
  minLat: 39.9060,
  maxLat: 39.9100,
  minLon: 116.3940,
  maxLon: 116.3990,
  minAlt: 50,
  maxAlt: 180
};

// 7级精度立方体网格剖分
const cuboidGridRes = gridSim.drawCuboidGrid(
  cuboidParams.minLat,
  cuboidParams.maxLat,
  cuboidParams.minLon,
  cuboidParams.maxLon,
  cuboidParams.minAlt,
  cuboidParams.maxAlt,
  7
);

console.log('立方体空域网格总数:', cuboidGridRes.list.length);

2.6 通用功能配套

  • 10级网格精度自由切换,适配不同场景精度需求

  • 自动视角定位,剖分完成自动飞行至目标空域

  • 网格数量上限拦截,防止超高精度剖分导致性能崩溃

  • 统一返回网格编码、坐标范围、中心点数据,方便二次开发统计

三、核心功能二:无人机动态飞行仿真

摒弃网上简陋的匀速点位平移动画,基于球面真实距离计算,实现物理级贴合真实飞行的仿真效果,支持完整生命周期交互与数据回调。

3.1 全生命周期仿真控制

完整支持无人机飞行仿真全套操作,覆盖项目所有交互需求:

  • 启动仿真:加载航线、生成网格、开始动态飞行

  • 暂停仿真:定格当前位置,记录暂停时间

  • 继续飞行:补偿暂停时长,无缝接续飞行,无位置偏移

  • 重置仿真:清空场景、重置所有状态、恢复初始状态

3.2 动态网格高亮推演(特色功能)

行业可视化最优方案,全程三色网格动态切换,直观展示飞行进度:

  • 未飞行网格:绿色半透明,代表待覆盖空域

  • 当前飞行网格:红色高亮,实时定位无人机所在空域

  • 已飞过网格:蓝色固化,记录已覆盖空域

可视化效果直观专业,可直接用于数字孪生大屏、项目演示、方案汇报。

3.3 全量实时状态回调(业务核心)

仿真全程对外抛出完整可落地的业务数据,无需二次计算,直接用于页面渲染、数据统计、日志记录、进度展示。

所有回调字段功能详解:

3.3.1 飞行进度数据
  • travelled:实时已飞行距离(米)

  • totalDistance:航线总里程(米)

  • percent:飞行完成百分比,可直接绑定进度条

3.3.2 无人机位置数据
  • lat / lon / alt:实时经纬度、飞行高度,精准定位无人机空间位置
3.3.3 网格统计数据
  • currentGridCode:当前所在网格唯一编码,用于空域标识

  • currentGridIndex:当前网格序号

  • passedGrids:已覆盖网格数量

  • totalGrids:航线总网格数量

  • remainingGrids:剩余未覆盖网格数量

3.3.4 仿真状态类型
  • start:仿真启动

  • running:飞行中(实时帧更新)

  • pause:仿真暂停

  • resume:恢复飞行

  • finish:飞行完成

3.4 自定义参数配置

支持自由配置飞行高度、飞行速度、仿真速率、网格精度,适配不同无人机机型、不同巡检场景的仿真需求。

四、功能落地业务场景

这套工具所有功能均为业务落地设计,适配当下主流低空、数字孪生GIS项目:

  • 无人机巡检仿真:航线预演、覆盖范围核验、飞行进度可视化

  • 低空空域分析:空域网格拆分、容量统计、禁飞区冲突检测

  • 数字孪生大屏:三维场景+实时数据双向联动,可视化展示航迹与空域

  • 教学与方案演示:分步演示飞行逻辑、空域覆盖,支持暂停复盘

五、快速调用示例(功能实战)

极简调用方式,一键启动仿真,监听所有状态,直接对接UI交互:

javascript 复制代码
// 初始化仿真工具
const gridSim = new GridSimulation(viewer);

// 自定义航线点位
const route = [
  { lat: 39.9080, lon: 116.3960 },
  { lat: 39.9095, lon: 116.3980 }
];

// 启动仿真,配置高度、速度,监听全量状态
gridSim.startSimulation(route, { alt: 120, speed: 8 }, (status) => {
  // 打印实时飞行数据
  console.log('飞行状态数据:', status);

  // 暂停状态自定义UI提示
  if(status.type === 'pause'){
    document.getElementById('sim-status').innerHTML += 
      '<br><i style="color:#ffa726">已暂停(点击 ▶ 开始 继续)</i>';
  }
})

// 暂停仿真调用
// gridSim.pauseSim();

// 重置仿真调用
// gridSim.resetSim();

六、完整开源源码

以下为全套无删减商用级源码,包含所有网格剖分、无人机仿真、状态回调核心功能,注释完整、可直接复制集成项目:

javascript 复制代码
/**
 * 三维网格分析 + 无人机仿真工具类
 * 核心功能:多形态三维网格剖分、无人机动态飞行仿真、全生命周期状态回调、网格高亮推演
 * 适配场景:无人机巡检、低空空域分析、数字孪生航迹推演、三维GIS可视化
 * 特点:解耦设计、无硬编码、高性能、可直接商用
 */
import * as Cesium from 'cesium';

/** 地球每度对应的米数常量 */
const M_PER_DEG = 111319.49079327357;

/** 10级网格精度配置(1-10级) */
const LEVELS = [
  null,
  { lon: 6.0, lat: 4.0, cols: 60, rows: 22 },
  { lon: 0.5, lat: 0.5, cols: 12, rows: 8 },
  { lon: 0.25, lat: 0.25, cols: 2, rows: 2 },
  { lon: 1 / 60, lat: 1 / 60, cols: 15, rows: 15 },
  { lon: 4 / 3600, lat: 4 / 3600, cols: 15, rows: 15 },
  { lon: 2 / 3600, lat: 2 / 3600, cols: 2, rows: 2 },
  { lon: 0.25 / 3600, lat: 0.25 / 3600, cols: 8, rows: 8 },
  { lon: 1 / 32 / 3600, lat: 1 / 32 / 3600, cols: 8, rows: 8 },
  { lon: 1 / 256 / 3600, lat: 1 / 256 / 3600, cols: 8, rows: 8 },
  { lon: 1 / 2048 / 3600, lat: 1 / 2048 / 3600, cols: 8, rows: 8 }
];

/** 最大网格数量限制,性能防护 */
const MAX_GRIDS = 50000;

/** 仿真全局状态管理 */
const sim = {
  running: false,
  paused: false,
  startMs: 0,
  totalPausedMs: 0,
  pauseStartMs: 0,
  routeMeters: 0,
  segments: [],
  grids: [],
  codeToIdx: new Map(),
  entities: [],
  drone: null,
  route: null,
  alt: 100,
  speed: 10,
  rate: 5,
  level: 7,
  currentIdx: -1,
  lastPos: null,
  onStatusUpdate: null
};

export default class GridSimulation {
  constructor(viewer) {
    if (!viewer) throw new Error("必须传入 Cesium Viewer 实例");
    this.map = viewer;
  }

  // 工具方法:结果摘要生成
  showResult(html) {
    console.log(html);
    return html;
  }

  listSummary(list) {
    let h = '<b>共 ' + list.length + ' 个网格</b><br>';
    list.slice(0, 30).forEach((g, i) => {
      h += i + 1 + '. <code>' + g.code + '</code><br>';
    });
    if (list.length > 30) h += '... 仅显示前 30 条';
    return h;
  }

  // 1. 单点网格剖分
  drawPointGrid(bounds) {
    this.clearAll();
    this.drawGrid(bounds, Cesium.Color.YELLOW.withAlpha(0.5));
    this.flyToGrids([bounds]);
    const list = [bounds];
    const html = this.showResult(this.listSummary(list));
    return { list, html };
  }

  // 2. 航线线状网格剖分
  drawLineGrid(start, end, level = 7) {
    this.clearAll();
    const list = this.queryLineGrids(start, end, level);
    list.forEach(g => this.drawGrid(g, Cesium.Color.LIME.withAlpha(0.35)));
    this.map.entities.add({
      polyline: {
        positions: Cesium.Cartesian3.fromDegreesArrayHeights([
          start.lon, start.lat, start.alt,
          end.lon, end.lat, end.alt
        ]),
        width: 3,
        material: Cesium.Color.RED
      }
    });
    this.flyToGrids(list);
    const html = this.showResult(this.listSummary(list));
    return { list, html };
  }

  // 3. 圆柱空域网格剖分
  drawCylinderGrid(center, radius, minAlt, maxAlt, level = 7) {
    this.clearAll();
    const list = this.queryCylinderGrids(center, radius, minAlt, maxAlt, level);
    list.forEach(g => this.drawGrid(g, Cesium.Color.ORANGE.withAlpha(0.35)));
    this.map.entities.add({
      position: Cesium.Cartesian3.fromDegrees(center.lon, center.lat, (minAlt + maxAlt) / 2),
      cylinder: {
        length: maxAlt - minAlt,
        topRadius: radius,
        bottomRadius: radius,
        material: Cesium.Color.RED.withAlpha(0.12),
        outline: true,
        outlineColor: Cesium.Color.RED
      }
    });
    this.flyToGrids(list);
    const html = this.showResult(this.listSummary(list));
    return { list, html };
  }

  // 4. 多边形面域网格剖分
  drawPrismGrid(points, minAlt, maxAlt, level = 7) {
    this.clearAll();
    const list = this.queryPrismGrids(points, minAlt, maxAlt, level);
    list.forEach(g => this.drawGrid(g, Cesium.Color.MAGENTA.withAlpha(0.35)));
    const arr = [];
    points.forEach(p => arr.push(p.lon, p.lat, maxAlt));
    arr.push(points[0].lon, points[0].lat, maxAlt);
    this.map.entities.add({
      polyline: {
        positions: Cesium.Cartesian3.fromDegreesArrayHeights(arr),
        width: 3,
        material: Cesium.Color.RED
      }
    });
    this.flyToGrids(list);
    const html = this.showResult(this.listSummary(list));
    return { list, html };
  }

  // 5. 立方体空域网格剖分
  drawCuboidGrid(minLat, maxLat, minLon, maxLon, minAlt, maxAlt, level = 7) {
    this.clearAll();
    const list = this.queryCuboidGrids(minLat, maxLat, minLon, maxLon, minAlt, maxAlt, level);
    list.forEach(g => this.drawGrid(g, Cesium.Color.BLUE.withAlpha(0.35)));
    this.map.entities.add({
      rectangle: {
        coordinates: Cesium.Rectangle.fromDegrees(minLon, minLat, maxLon, maxLat),
        material: Cesium.Color.RED.withAlpha(0.12),
        outline: true,
        outlineColor: Cesium.Color.RED,
        height: minAlt,
        extrudedHeight: maxAlt
      }
    });
    this.flyToGrids(list);
    const html = this.showResult(this.listSummary(list));
    return { list, html };
  }

  // 启动无人机仿真
  startSimulation(routePoints, options = {}, onStatusUpdate = null) {
    if (!this.map) return;
    sim.onStatusUpdate = onStatusUpdate;

    // 暂停恢复逻辑
    if (sim.paused) {
      sim.paused = false;
      sim.totalPausedMs += performance.now() - sim.pauseStartMs;
      this.pushStatus('resume');
      requestAnimationFrame(() => this.simTick());
      return;
    }

    if (sim.running) return;

    // 初始化配置参数
    const { alt = 100, speed = 10, rate = 5, level = 7 } = options;
    sim.alt = alt;
    sim.speed = speed;
    sim.rate = rate;
    sim.level = level;
    sim.lastPos = { ...routePoints[0], alt };

    this.resetSim();
    const pts = routePoints;
    if (pts.length < 2) {
      alert('航线至少需要2个点');
      return;
    }

    // 计算航线里程与航线段
    let cum = 0;
    for (let i = 0; i < pts.length - 1; i++) {
      const a = pts[i];
      const b = pts[i + 1];
      const d = this.distM(a.lat, a.lon, b.lat, b.lon);
      sim.segments.push({ a, b, dist: d, start: cum });
      cum += d;
    }
    sim.route
相关推荐
南知意-1 小时前
MonkeyCode:长亭开源的企业级AI开发平台,GitHub 3.2k Star!
人工智能·ai·开源·github·ai编程·开源项目
sbjdhjd2 小时前
04 (下) | K8S微服务实战:从 Service 到金丝雀发布
运维·微服务·云原生·kubernetes·开源·云计算·excel
沐曦股份MetaX3 小时前
沐曦芯生,开源共创 | 沐曦股份 × SGLang联合举办技术交流Meetup,共同探索AI推理落地新路径
人工智能·开源·sglang
狂奔solar3 小时前
Page-Agent:阿里开源的页面内 GUI Agent
开源
时光追逐者3 小时前
一个基于 .NET 与 Avalonia 构建、面向 TrinityCore 的开源 WoW 数据库编辑器
数据库·开源·.net
开源推荐官3 小时前
2026 商城系统源码实测,真正适合二开的系统有哪些?
java·架构·开源
YOLO数据集集合3 小时前
无人机航拍光伏板状态识别数据集 | 太阳能板异常检测、智能巡检、深度学习模型训练素材第10340期
人工智能·深度学习·yolo·目标检测·无人机
sensen_kiss3 小时前
CPT304 SoftwareEngineeringII 软件工程 2 Pt.7 开源开发 (Open Source Development)
开源·软件工程
可别3903 小时前
cesium实现网格化
游戏引擎·cocos2d