当前位置: 首页 > news >正文

Cesium 曲线管道教程

曲线管道 ·Curve Pipe· ▶ 在线运行案例

  • 案例合集:三维可视化功能案例(threehub.cn)
  • 开源仓库github地址:https://github.com/z2586300277/three-cesium-examples
  • 400个案例代码:网盘链接

你将学到什么

  • Cesium Entity 高层实体 API

效果说明

本案例演示曲线管道效果:基于 WebGL 实现「曲线管道」可视化效果,附完整可运行源码;核心用到 Cesium。建议先打开文首在线案例查看动态画面,再对照下方源码逐步理解。

核心概念

  • Viewer聚合 Scene、Camera、Clock 与渲染循环,是 Cesium 应用入口。
  • Entity面向点线面/模型/标签的高层 API;与 Primitive 相比更适合交互与属性驱动。
  • 阅读下方完整源码时,建议从init/load/animate三条主线入手,再深入 shader 与工具函数。

实现步骤

  • 创建 Viewer,配置地形/影像(若案例需要)并设置初始相机
  • requestAnimationFrame循环中更新状态并 render(Cesium 为viewer.render或自动渲染)
  • 代码要点

    import * as Cesium from 'cesium'

    import { Color, defined, Event, Material, Property } from 'cesium'

    const box = document.getElementById('box')

    const viewer = new Cesium.Viewer(box, {

    animation: false,//是否创建动画小器件,左下角仪表

    baseLayerPicker: false,//是否显示图层选择器,右上角图层选择按钮

    baseLayer: Cesium.ImageryLayer.fromProviderAsync(Cesium.ArcGisMapServerImageryProvider.fromUrl(GLOBAL_CONFIG.getLayerUrl())),

    fullscreenButton: false,//是否显示全屏按钮,右下角全屏选择按钮

    timeline: false,//是否显示时间轴

    infoBox: false,//是否显示信息框

    })

    viewer._cesiumWidget._creditContainer.style.display = "none"

    viewer.clock.shouldAnimate = true

    //定位北京 viewer.camera.flyTo({

    destination: Cesium.Cartesian3.fromDegrees(116.41, 36.91, 1000000),

    orientation: {

    heading: Cesium.Math.toRadians(0),

    pitch: Cesium.Math.toRadians(-90),

    roll: 0

    }

    })

    /飞线材质类/ class PolylineTrailLinkMaterialProperty {

    constructor(image, color = Color.WHITE, duration = 1000, repeat = 60) {

    this._definitionChanged = new Event()

    this._color = undefined

    this.color = color

    this.duration = duration

    this._time = new Date().getTime()

    this.image = image

    Material._materialCache.addMaterial('PolylineTrailLink', {

    fabric: {

    type: 'PolylineTrailLink',

    uniforms: {

    color: color.withAlpha(1.0),

    image: image,

    time: 0,

    repeat

    },

    source:czm_material czm_getMaterial(czm_materialInput materialInput) { czm_material material = czm_getDefaultMaterial(materialInput); vec2 st = materialInput.st; vec4 sampledColor = texture(image, vec2(fract(repeat*st.s - time), st.t)); material.alpha = sampledColor.a * color.a; material.diffuse = (sampledColor.rgb + color.rgb) / 2.0; return material; }

    },

    translucent: () => true

    })

    }

    get isConstant() { return false }

    get definitionChanged() { return this._definitionChanged }

    getType(_) { return 'PolylineTrailLink' }

    getValue(time, result) {

    if (!defined(result)) result = {}

    result.color = Property.getValueOrClonedDefault(this._color, time, Color.WHITE, result.color)

    result.image = this.image

    result.time = (new Date().getTime() - this._time) % this.duration / this.duration

    return result

    }

    equals(other) { return this === other || Property.equals(this._color, other._color) }

    }

    // 生成一组飞线动画 [ [[116.41, 36.91], [130.40, 45.39]], [[116.41, 36.91], [114.11, 39.44]], [[116.41, 36.91], [109.62, 25.72]], [[116.41, 36.91], [121.48, 31.22]], [[116.41, 36.91], [13.78, 12.31]], [[116.41, 36.91], [74.12, 33.50]], ].forEach(([p1, p2]) => createPlaneCurve(p1, p2))

    // 组合 function createPlaneCurve(p1, p2) {

    const { curvePoints } = getGenerateCurve(p1, p2, { maxHeight: 100000 })

    viewer.entities.add({ polylineVolume: createCurvePipe(curvePoints)

    })

    }

    /生成曲线/ function getGenerateCurve(start, end, params = {}) {

    const [startLongitude, startLatitude] = start

    const [endLongitude, endLatitude] = end

    const startCartographic = Cesium.Cartographic.fromDegrees(startLongitude, startLatitude)

    const endCartographic = Cesium.Cartographic.fromDegrees(endLongitude, endLatitude)

    const geodesic = new Cesium.EllipsoidGeodesic(startCartographic, endCartographic)

    const curvePoints = []

    for (let t = 0; t <= 1; t += (params.step || 0.01)) {

    const pointCartographic = geodesic.interpolateUsingFraction(t)

    pointCartographic.height = (params.maxHeight || 400000)Math.sin(Math.PIt)

    const pointCartesian = Cesium.Cartographic.toCartesian(pointCartographic)

    curvePoints.push(pointCartesian)

    }

    endCartographic.height = 0

    const endPointCartesian = Cesium.Cartographic.toCartesian(endCartographic)

    curvePoints.push(endPointCartesian)

    function getCurvePointAtTime(t) {

    const pointCartographic = geodesic.interpolateUsingFraction(t)

    pointCartographic.height = (params.maxHeight || 400000)Math.sin(Math.PIt)

    return Cesium.Cartographic.toCartesian(pointCartographic)

    }

    return { curvePoints, getCurvePointAtTime }

    }

    function createCurvePipe(curvePoints, params = {}) {

    const getShape = (radius) => {

    const positions = [];

    for (let i = 0; i < 360; i++) {

    if (i % 1 === 0) {

    const radians = Cesium.Math.toRadians(i);

    positions.push(

    new Cesium.Cartesian2(

    (radius / 2) * Math.cos(radians),

    (radius / 2) * Math.sin(radians)

    )

    );

    }

    }

    return positions;

    }

    const radius = 16000.0

    const _ps = curvePoints.map(i => {

    const [longitude, latitude, height] = cartesian3ToDegrees(i)

    return Cesium.Cartesian3.fromDegrees(longitude, latitude, height - radius)

    })

    return {

    positions: _ps,

    shape: getShape(2 * radius),

    cornerType: Cesium.CornerType.ROUNDED,

    material: new PolylineTrailLinkMaterialProperty(FILE_HOST + 'images/channels/lmap.png', Cesium.Color.RED, 2000)

    }

    }

    function cartesian3ToDegrees(cartesian3, type = 'Array') {

    const cartographic = Cesium.Cartographic.fromCartesian(cartesian3) // 笛卡尔坐标转经纬度

    const longitude = Cesium.Math.toDegrees(cartographic.longitude) // 弧度转度

    const latitude = Cesium.Math.toDegrees(cartographic.latitude) // 弧度转度

    const height = cartographic.height // 高度

    return type === 'Array' ? [longitude, latitude, height] : { longitude, latitude, height }

    }

    完整源码:GitHub

    小结

    • 本文提供曲线管道完整 Cesium.js 源码与在线 Demo,建议先运行案例再改 uniform/参数做二次实验
    • 更多 Cesium.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库
http://www.jsqmd.com/news/1173376/

相关文章:

  • VAR模型入门:多变量时间序列建模的核心原理与实战
  • 微信小店和微信商户号的注销流程 2026年版
  • STM32G0B1RE与ADS131M02的高精度数据采集方案
  • Meta Muse模型突破文字渲染,AI图像生成进入实用新阶段
  • 终极Windows驱动管理神器:一键清理释放10GB空间
  • 基于压电蜂鸣器的智能环境警报系统设计与实现
  • MA12070音频放大器与PIC18F86J16主控方案设计解析
  • 劳力士中国区官方售后服务中心|官方售后电话及地址权威公告(2026年7月最新) - 劳力士中国服务中心
  • 5分钟掌握深蓝词库转换:打破输入法壁垒的终极指南
  • 蓝牙5.4 LE Audio低延迟方案设计与优化
  • 建筑师如何用LangGraph构建可追溯的深度研究Agent
  • TB6593FNG与ATSAME70的直流电机控制方案设计
  • 劳力士中国区官方售后服务中心|官网认证地址及电话全新启用(2026年7月最新) - 劳力士中国服务中心
  • 终极Windows游戏控制器模拟指南:5分钟让任何设备变身专业手柄
  • 三大运营商5G承载网技术路线解析:SPN、M-OTN、智能城域网架构与部署差异
  • ncmdump完整教程:3分钟解锁网易云音乐NCM格式,实现音乐自由播放
  • 重庆黄金回收避坑指南:7 家正规机构报价透明当场结清 - 奢侈品回收中心
  • 大模型训练卡顿、显存爆炸、收敛异常——Transformer底层计算图解密(2024最新内核剖析)
  • 2026年沧州性价比高的门窗品牌有哪些:西格米克门窗阳光房专业靠谱 - 优企甄选
  • 劳力士中国区官方售后服务中心|最新维修地址及电话权威收录(2026年7月最新) - 劳力士中国服务中心
  • OpenEuler Computing-docs深度解析:sysBoost如何提升程序性能30%以上
  • ASan vs Valgrind:Windows/Linux C++内存检测3大维度性能与精度对比
  • 如何利用Flappy Bird游戏资源快速构建你的像素游戏项目?[特殊字符]
  • 5分钟快速上手:小红书无水印批量下载工具终极指南
  • Linux操作系统 --- 开发工具
  • FreeMove终极指南:三步安全迁移程序目录,彻底解决C盘空间不足
  • VNC Server 与 Viewer 6.22 对比:3 种主流 Linux 桌面环境性能实测
  • 原生 JS 实现自定义单选日历组件(无 UI 库、纯手写、禁用过去日期)
  • 3个核心模块深度解析:如何用UABEA解锁Unity资源编辑的无限可能
  • 神经算子:从传统神经网络到科学计算的AI革命