OSGearth开发

OSGearth城市可视化功能详解

本文详细解析了 3D 城市可视化中 12 个核心功能的实现原理与应用场景


目录

  1. [鹰眼(Mini-map / Overview Camera)](#鹰眼(Mini-map / Overview Camera))
  2. [城市(City Generation / Building System)](#城市(City Generation / Building System))
  3. [漫游(Roaming / Fly-Through)](#漫游(Roaming / Fly-Through))
  4. [经纬线(Latitude/Longitude Grid)](#经纬线(Latitude/Longitude Grid))
  5. [坡度分析(Slope Analysis)](#坡度分析(Slope Analysis))
  6. [飞线(Flow Lines / Arc Lines)](#飞线(Flow Lines / Arc Lines))
  7. [动态纹理(Dynamic Textures)](#动态纹理(Dynamic Textures))
  8. [卫星模拟(Satellite Simulation)](#卫星模拟(Satellite Simulation))
  9. [航拍模拟(Aerial Photography Simulation)](#航拍模拟(Aerial Photography Simulation))
  10. [绘制坐标点(Point Drawing)](#绘制坐标点(Point Drawing))
  11. [绘制图形(Shape Drawing)](#绘制图形(Shape Drawing))
  12. [下雪(Snow Effect)](#下雪(Snow Effect))
  13. [剖面分析(Section / Profile Analysis)](#剖面分析(Section / Profile Analysis))

1. 鹰眼(Mini-map / Overview Camera)

实现原理

鹰眼功能本质是一个独立的小地图渲染系统,主要步骤:

  1. 创建独立摄像机:在场景正上方设置一个俯视摄像机,位置固定在高空(如 y = 100)
  2. 独立渲染器:创建小尺寸的 WebGLRenderer(如 200×200),覆盖在主窗口角落
  3. 位置同步:小地图摄像机跟随主摄像机在 XZ 平面的位置,保持俯视视角
  4. 标记绘制:在小地图上用不同颜色的点或图标标记主摄像机位置和朝向

核心技术

复制代码
- 双渲染器(Multi-Renderer)
- 摄像机位置同步(Camera Position Sync)
- Mini-map 标记(CSS2DRenderer 或 Sprite)

应用场景

  • 导航辅助:在大场景中快速定位自身位置
  • 城市漫游辅助:实时显示摄像机在城市中的相对位置
  • 游戏/模拟器:战略地图、雷达图

2. 城市(City Generation / Building System)

实现原理

城市生成通常分为程序化生成数据驱动两种方式:

  1. 地块划分:将城市区域划分为若干街区(Block),每个街区有尺寸和位置属性
  2. 建筑生成 :在每个街区内随机放置建筑,参数包括:
    • 宽度/深度(5~25 单位)
    • 高度(10~80 单位,产生天际线变化)
    • 颜色(HSL 色相变化)
  3. 纹理细节
    • 使用 Canvas 生成窗户纹理(随机亮暗表示灯光)
    • 建筑贴图(LOD 多级细节)
  4. 性能优化
    • InstancedMesh 批量渲染同类型建筑
    • LOD(Level of Detail)远距离简化
    • Frustum Culling 视锥裁剪

核心技术

复制代码
- BoxGeometry / InstancedMesh
- CanvasTexture 程序化纹理
- LOD 多级细节
- 随机化算法

应用场景

  • 数字孪生城市:智慧城市可视化
  • 城市规划:建筑密度、天际线仿真
  • 游戏开放世界:程序化城市生成

3. 漫游(Roaming / Fly-Through)

实现原理

  1. 路径定义:设置一系列路点(Waypoints),每个路点包含位置(Position)和注视点(LookAt)
  2. 插值运动:在两路点之间进行线性插值或贝塞尔曲线插值
  3. 摄像机控制
    • 位置插值:camera.position.lerpVectors(current, next, progress)
    • 朝向插值:camera.lookAt(lookTarget)
  4. 路径类型
    • 直线路径(线性插值)
    • 曲线路径(Catmull-Rom / Bezier 曲线)
    • 环绕路径(Orbit Controls 自动旋转)

核心技术

复制代码
- 线性插值(Lerp)
- CatmullRomCurve3 曲线路径
- 摄像机动画系统
- Tween.js / GSAP 动画库

应用场景

  • 城市宣传片:自动生成的飞行游览路径
  • 建筑漫游:室内/室外漫游展示
  • 游戏过场动画:脚本化摄像机运动

4. 经纬线(Latitude/Longitude Grid)

实现原理

  1. 纬线(Latitude Lines)

    • 在球面上沿纬度方向(φ)等间距取点
    • 每个纬度圈的水平圆周由 64+ 个顶点构成
    • 通过 sin(φ)*cos(θ), cos(φ), sin(φ)*sin(θ) 计算顶点位置
  2. 经线(Longitude Lines)

    • 在球面上沿经度方向(θ)等间距取点
    • 每条经线是从南极到北极的弧线
  3. 视觉效果

    • 赤道线高亮(不同颜色/粗度)
    • 透明度区分(经线透明度低于纬线)
    • 可点击交互(拾取经纬度坐标)

核心技术

复制代码
- SphereGeometry 参数化
- BufferGeometry.setFromPoints()
- LineBasicMaterial(透明度/颜色区分)

应用场景

  • 地球/星球可视化:经纬度参考网格
  • 气象数据展示:全球数据分析
  • 卫星轨道模拟:定位参考系统

5. 坡度分析(Slope Analysis)

实现原理

坡度分析通过计算地形三角面的法向量与水平面的夹角来实现:

  1. 法向量计算

    复制代码
    edge1 = v2 - v1
    edge2 = v3 - v1
    normal = edge1 × edge2(归一化)
  2. 坡度角度

    复制代码
    angle = acos(|normal · up|)
    slope = angle * 180 / π
  3. 分级着色(两种实现方式):

    CPU 方式

    • 遍历所有三角面,计算坡度
    • 按坡度分级赋予颜色(绿→黄→橙→红)

    GPU 方式(Shader)

    • 在顶点着色器中计算法向量
    • 在片元着色器中实时计算坡度并着色
    • 性能更高,支持实时更新

坡度分级标准

坡度范围 颜色 等级 描述
0°~5° 绿色 #22cc44 Ⅰ级 平坦
5°~15° 黄色 #cccc22 Ⅱ级 缓坡
15°~30° 橙色 #cc6622 Ⅲ级 陡坡
>30° 红色 #cc2222 Ⅳ级 极陡

应用场景

  • 地形分析:建筑用地适宜性评估
  • 道路规划:选线方案比选
  • 地质灾害评估:滑坡风险区域识别

6. 飞线(Flow Lines / Arc Lines)

实现原理

飞线用于表示两点之间的数据流动,核心是弧形轨迹 + 动态流动效果

  1. 弧线生成

    • 起点(startPos)和终点(endPos)
    • 计算中点:mid = (startPos + endPos) / 2
    • 弧高控制:mid.y += distance * 0.3
    • 使用 QuadraticBezierCurve3 生成贝塞尔曲线
  2. 流动动画

    • CPU 方式:更新顶点透明度,形成光点沿路径移动的效果
    • GPU 方式(Shader)
      • 使用 aProgress 属性表示每个顶点在路径上的进度
      • 片元着色器中计算流动位置:flowPos = mod(vProgress + time * speed, 1.0)
      • 亮度随流动位置变化,产生拖尾效果
  3. 多线渲染优化

    • 使用 LineSegments 批处理
    • 颜色编码(不同数据类别使用不同颜色)

核心技术

复制代码
- QuadraticBezierCurve3(贝塞尔弧线)
- ShaderMaterial 流动效果
- 透明度混合(AdditiveBlending)

应用场景

  • 数据流向可视化:人口迁移、物流路线
  • 网络拓扑展示:通信数据流
  • 交通流量:航线、车流轨迹

7. 动态纹理(Dynamic Textures)

实现原理

动态纹理是通过实时更新纹理内容实现的视觉效果:

方式一:Canvas 纹理
  1. 创建 HTML Canvas 元素
  2. 使用 Canvas 2D API 绘制内容
  3. 创建 THREE.CanvasTexture(canvas)
  4. 在动画循环中更新 Canvas 内容并设置 texture.needsUpdate = true
方式二:Video 纹理
  1. 创建 HTML Video 元素,加载视频源
  2. 创建 THREE.VideoTexture(video)
  3. 视频自动播放,纹理实时更新
方式三:DataTexture(像素级操作)
  1. 创建 THREE.DataTexture(data, width, height)
  2. 直接操作像素缓冲区(Uint8Array)
  3. 适用于粒子系统、噪声生成等

动态纹理类型示例

类型 实现方式 更新频率
水波纹 Canvas 绘制椭圆弧线 每帧更新
建筑灯光 像素级随机闪烁 每帧更新
信息流动 Canvas 绘制移动文字/图形 每帧更新
视频播放 VideoTexture 视频帧率

应用场景

  • 水面/流体模拟:实时水纹理
  • 信息展示屏:数据大屏动态内容
  • 特效制作:动态光效、LED屏幕

8. 卫星模拟(Satellite Simulation)

实现原理

地球模型
  1. 球体创建SphereGeometry(radius, 64, 64)
  2. 纹理映射:地表贴图 + 法线贴图 + 高光贴图
  3. 大气层
    • 略大于地球的半透明球体(radius × 1.02)
    • Shader 实现边缘发光效果(Fresnel 效应)
    • 混合模式:AdditiveBlending
卫星轨道
  1. 轨道参数

    • 半长轴(a)、偏心率(e)
    • 轨道倾角(i)、升交点赤经(Ω)
    • 真近点角(θ)
  2. 轨道计算

    复制代码
    r = a * (1 - e²) / (1 + e * cos(θ))
    x = r * cos(θ)
    z = r * sin(θ)
    // 应用倾角和升交点赤经旋转
  3. 卫星模型

    • 主体(BoxGeometry)
    • 太阳能板(两侧展开)
    • 朝向运动方向(Quaternion 旋转)
动画逻辑
  • 卫星沿轨道点移动
  • 位置插值平滑运动
  • 速度可配置(不同卫星不同速度)

应用场景

  • 航天任务可视化:卫星轨道模拟
  • 天基观测:卫星覆盖区域分析
  • 教育科普:轨道力学教学

9. 航拍模拟(Aerial Photography Simulation)

实现原理

无人机模拟
  1. 三维模型:机身 + 旋翼臂(简化模型)
  2. 飞行路径
    • 环绕飞行(Orbit):圆心 + 半径 + 高度
    • 航线飞行(Waypoints):预设路径点
    • 自由飞行(Free):用户控制
摄像机参数模拟
复制代码
- 焦距(focalLength):模拟真实相机镜头
- 地面采样距离(GSD)= (高度 × 传感器宽度) / (焦距 × 1000)
- 快门速度:影响运动模糊
- ISO:模拟噪声效果
视觉效果
  1. 大气雾效FogExp2 模拟空气透视
  2. 摄像机抖动:添加微小随机偏移,模拟真实航拍
  3. 光晕/眩光:镜头光晕效果(Lens Flare)

应用场景

  • 影视预可视化:航拍镜头规划
  • 测绘模拟:无人机航测路径规划
  • 游戏/VR:飞行体验

10. 绘制坐标点(Point Drawing)

实现原理

屏幕坐标转世界坐标
  1. 射线检测(Raycaster)

    javascript 复制代码
    mouse.x = (event.clientX / width) * 2 - 1
    mouse.y = -(event.clientY / height) * 2 + 1
    raycaster.setFromCamera(mouse, camera)
    raycaster.ray.intersectPlane(groundPlane, intersectPoint)
  2. 地面平面检测:与水平面(y=0)求交

标记点的三种实现方式
方式 优势 劣势
Sprite(精灵) 始终面向摄像机,性能好 不能立体显示
3D 几何体(Cone/Sphere) 立体感强,可加光照 远距离变小
CSS2DRenderer 可渲染 HTML 标签,交互性强 渲染层分离
标记功能
  • 脉冲动画scale = 1 + sin(time) * 0.2 实现呼吸效果
  • 颜色编码:不同类别使用不同颜色
  • 文本标签:使用 CSS2DRenderer 或 Sprite 显示文字

应用场景

  • 地图标注:POI 点标记
  • 数据可视化:事件位置标记
  • 测量工具:坐标采集

11. 绘制图形(Shape Drawing)

实现原理

多边形绘制
  1. 交互绘制

    • 鼠标点击收集顶点
    • 实时预览当前绘制状态
    • 双击/右键完成绘制
  2. 3D 几何体生成

    复制代码
    Shape(2D轮廓)→ ExtrudeGeometry(挤压成3D)
    → 旋转至水平(rotation.x = -π/2)
    → 设置透明度填充
  3. 边框绘制

    • 将顶点连接为 LineLoop
    • 可设置不同颜色和粗细
图形类型
类型 实现方式 应用
矩形 对角两点定义 选择框、区域标注
圆形 圆心+半径 缓冲区、覆盖范围
多边形 多点序列 任意区域标注
箭头 方向向量+箭头计算 方向指示
曲线 贝塞尔/样条 路径标注
交互功能
  • 拖拽调整:拖动顶点修改形状
  • 吸附功能:顶点吸附到网格或其他顶点
  • 面积/周长计算:实时显示测量数据

应用场景

  • 地理标注:区域划定、地物标注
  • 测量工具:距离、面积测量
  • 规划设计:建筑红线、用地范围

12. 下雪(Snow Effect)

实现原理

下雪效果使用**粒子系统(Points/PointsMaterial)**实现:

1. 粒子初始化
javascript 复制代码
const particleCount = 10000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const velocities = new Float32Array(particleCount);

// 在三维空间随机分布
for (let i = 0; i < particleCount; i++) {
  positions[i * 3] = (Math.random() - 0.5) * 200;     // X
  positions[i * 3 + 1] = Math.random() * 100;          // Y
  positions[i * 3 + 2] = (Math.random() - 0.5) * 200;  // Z
  velocities[i] = 0.5 + Math.random() * 1.5;           // 下落速度
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
2. 粒子材质
javascript 复制代码
const texture = createSnowflakeTexture(); // Canvas绘制雪花形状
const material = new THREE.PointsMaterial({
  size: 0.5,
  map: texture,
  transparent: true,
  opacity: 0.8,
  blending: THREE.AdditiveBlending,
  depthWrite: false,
});
3. 雪花纹理(Canvas绘制)
  • 绘制六角形雪花形状
  • 边缘模糊处理产生透明度渐变
  • 可随机生成多种雪花形态
4. 动画循环
javascript 复制代码
// 每个粒子向下移动
positions[i * 3 + 1] -= velocities[i] * deltaTime;

// 添加水平飘动
positions[i * 3] += Math.sin(time + i) * 0.02;
positions[i * 3 + 2] += Math.cos(time * 0.7 + i * 0.3) * 0.02;

// 超出底部则重置到顶部
if (positions[i * 3 + 1] < -10) {
  positions[i * 3 + 1] = 100;
  positions[i * 3] = (Math.random() - 0.5) * 200;
  positions[i * 3 + 2] = (Math.random() - 0.5) * 200;
}
5. 风效果(可选)
  • 添加风向向量,粒子沿风向偏移
  • 风速变化产生飘忽感
  • 旋转粒子产生旋转效果

优化技巧

  • 使用 BufferGeometry 而非 Geometry
  • 粒子数量控制在合理范围(5000~20000)
  • 使用 frustumCulled = false 避免裁剪问题
  • LOD:远景减少粒子数

应用场景

  • 天气模拟:降雪可视化
  • 场景氛围:冬季城市效果
  • 特效制作:粒子系统教学

13. 剖面分析(Section / Profile Analysis)

实现原理

剖面分析用于展示地形或模型在某一截面上的高程变化

方法一:切割平面(Clipping Plane)
  1. 定义切割平面 :使用 THREE.Plane 定义切割位置和方向

  2. 渲染器启用裁剪

    javascript 复制代码
    renderer.localClippingEnabled = true;
    material.clippingPlanes = [clippingPlane];
    material.clipShadows = true;
  3. 截面填充 :使用 Stencil Buffer 在切割面处绘制填充颜色

方法二:采样插值(适合地形)
  1. 定义剖面线:在水平面上定义一条直线或折线

  2. 高程采样

    • 沿剖面线等距采样点
    • 对每个采样点,获取地形高度(通过射线检测或高度图采样)
  3. 生成剖面图

    复制代码
    采样点 (x, z) → 获取 y(高度)
    展平为 2D:横坐标 = 沿路径距离,纵坐标 = 高程
  4. 绘制剖面曲线:使用 Line 或 AreaChart 绘制

方法三:Shader 实现(实时切割)
复制代码
- 在片元着色器中判断像素是否在切割面一侧
- 丢弃另一侧的片段(discard)
- 在切割边缘绘制高亮线

剖面图内容

元素 说明
地形曲线 沿剖面线的高程变化
地质分层 不同地质材料的分层显示
标注信息 最高点、最低点、坡度标注
比例尺 水平和垂直比例尺
网格线 参考网格

应用场景

  • 地形分析:山谷、山脊、坡度变化分析
  • 道路设计:纵断面设计、填挖方计算
  • 地质勘探:地层结构可视化
  • 管线规划:地下管线剖面展示

总结

功能 核心技术 主要应用
鹰眼 双渲染器 + 摄像机同步 导航辅助
城市 InstancedMesh + 程序化纹理 数字孪生
漫游 路径插值 + 摄像机动画 自动游览
经纬线 球面参数化 + LineSegments 参考网格
坡度分析 法向量计算 + Shader着色 地形评估
飞线 贝塞尔曲线 + Shader流动 数据流向
动态纹理 Canvas/Video/DataTexture 特效展示
卫星模拟 轨道力学 + 地球渲染 航天可视化
航拍模拟 飞行路径 + 相机参数模拟 航拍规划
绘制坐标点 Raycaster + Sprite/几何体 地图标注
绘制图形 Shape + ExtrudeGeometry 区域标记
下雪 粒子系统 + PointsMaterial 天气模拟
剖面分析 ClippingPlane / 高程采样 地形分析