大家好,我是日拱一卒的
攻城师不浪
,致力于前沿科技探索,摸索小而美工作室,这是2025年输出的第49/100篇原创文章。
效果预览
www.bilibili.com/video/BV19z...
在三维GIS应用中,地形分析是一项基础而关键的功能。通过对地形的精确分析,我们可以获取地表形态的重要特征信息,为工程建设、环境评估、灾害预防等领域提供强有力的数据科学依据。
其中,坡度坡向分析是地形分析中最常用的一种方法,它能够直观地展示地形的倾斜程度和方向,帮助我们理解地形特征与地表过程之间的关系。
坡度坡向分析
坡度坡向分析是对地形表面几何特征的定量分析方法。简单来说:
-
坡度 :表示地表的
倾斜程度
,通常用角度或百分比表示 -
坡向:表示地表倾斜的方向,通常用方位角表示(如北为0°,东为90°)

这两个参数共同描述了地形的三维几何特征,是地形分析的基础指标。
功能作用
坡度坡向分析的主要作用包括:
-
提供地形倾斜程度的量化指标
-
展示地表水流可能的运动方向
-
辅助判断地形的侵蚀与堆积特征
-
为工程建设提供地形适宜性评价依据
-
帮助预测自然灾害风险区域
在里实现坡度坡向分析,可以将这些抽象的数值直观地展现在三维场景中,大大提高分析结果的可读性和实用性。
应用场景
坡度坡向分析在众多领域都有广泛应用:
工程建设与选址
在建筑、道路、桥梁等工程项目选址过程中,坡度信息直接影响工程的难度和成本。通过坡度分析,可以快速筛选出适宜建设的平缓区域,避开陡峭地带,优化工程设计方案。
生态环境评估
地形坡度和坡向影响着阳光辐射、水分分布和土壤侵蚀等生态环境因素。通过坡度坡向分析,可以评估生态系统的稳定性和脆弱性,为生态保护提供依据。
水文分析与流域管理
坡度坡向直接决定了地表水流的方向和速度。通过分析,可以模拟降水后的径流路径,预测洪水风险区域,辅助水利工程规划和防洪减灾。
灾害风险评估
坡度是触发滑坡、泥石流等地质灾害的重要因素。通过分析特定区域的坡度分布,可以识别潜在的灾害风险区,为防灾减灾提供决策支持。
核心实现原理
要在Cesium
中实现坡度坡向分析,核心原理主要涉及以下几个方面:
地形网格划分
首先需要将分析区域划分为一系列规则网格。这些网格可以是等距 的(按固定距离划分)或等分的(将区域分为固定数量的网格)。
地形高程采样
对每个网格中的关键点(中心点、边界点等)进行地形高程采样,获取这些点的三维坐标。在Cesium
中,这一过程通过sampleTerrainMostDetailed
方法实现,该方法能够获取地形表面上指定点的精确高程值。
坡度计算
坡度计算的基本原理是:
-
确定网格中心点和周围点的三维坐标
-
计算中心点与周围点之间的高度差
-
计算中心点与周围点的水平距离
-
坡度值 = 高度差 / 水平距离
在代码实现中,我们找到高度差最大的点,用它与中心点之间的关系计算坡度,这种方法简化了计算过程,能够快速反映出区域内最陡峭的方向。
坡向确定
坡向的确定基于高度差最大的方向。代码中通过向量计算和坐标系转换,确定坡度最大的方向,并用箭头表示出来。具体涉及:
-
计算局部坐标系(ENU)与全球坐标系之间的转换
-
计算方向向量并归一化
-
计算向量与X轴的夹角,确定方向角(heading)
可视化表达
坡度采用不同颜色进行表示,一般遵循从绿到红的渐变,表示从平缓到陡峭:
-
平原(0°~0.5°):浅绿色
-
微斜坡(0.5°~2°):淡绿色
-
缓斜坡(2°~5°):黄绿色
-
斜坡(5°~15°):黄色
-
陡坡(15°~35°):橙色
-
峭坡(35°~55°):橙红色
-
垂直壁(55°~90°):红色
坡向则通过箭头方向表示,箭头指向地形下降最陡的方向。
5. 代码实现详解
网格划分方法
代码提供了两种网格划分方法:
javascript
// 等距切分
equalDistance(distance = 0.1) {
distance = distance; // 默认0.1km
let width = distance * 200 > 35 ? 35 : distance * 200;
this.arrowWidth = width < 15 ? 15 : width;
// ...
let grid = turf.squareGrid(bbox, distance, { mask: mask });
this.createEllipse(grid);
}
// 等分切分,切分成n*n的网格
EqualDivision(num) {
// ...
const step = b / num;
// ...
let grid = turf.squareGrid(bbox, step, {
units: "degrees",
mask: mask,
});
this.createEllipse(grid);
}
这两个方法都使用了turf.js
库的squareGrid
函数来生成网格,区别在于一个基于固定距离,一个基于网格数量。通过mask
参数,确保网格仅在用户绘制的多边形区域内生成。
地形高程采样
javascript
// 使用Cesium的地形采样函数获取所有点的高度信息
Cesium.sampleTerrainMostDetailed(
this.viewer.scene.terrainProvider, // 场景的地形提供者
boxResults // 需要采样的坐标
).then((updatePositions) => {
// 处理采样结果...
});
通过sampleTerrainMostDetailed
方法,获取所有采样点的精确高程值,这些高程数据是后续坡度计算的基础。
坡度计算与颜色映射
寻找最大高度差的点
javascript
let heightDifference = 0;
let maxIndex = 0;
for (let i = 1; i < ellipse.length - 1; i++) {
const point = ellipse[i];
let curHD = point.height - center.height;
if (Math.abs(curHD) > heightDifference) {
heightDifference = curHD;
maxIndex = i;
}
}
// 计算两点三维的距离
let distance = Cesium.Cartesian3.distance(
Cesium.Cartographic.toCartesian(pos0),
Cesium.Cartographic.toCartesian(pos1)
);
// 计算斜率(高度差/距离)
let curSlope = Math.abs(heightDifference / distance);
这段代码首先找出与中心点高度差最大的点,然后计算这两点之间的三维距离,最后用高度差除以距离得到坡度值。
根据计算出的坡度值,映射到不同的颜色(根据我们文章上边一开始给出的范围进行设定):
javascript
setColor(value, alpha) {
if (value < 0.00872686779075879) {
return "rgba(85,182,43," + alpha + ")";
} else if (value < 0.03492076949174773) {
return "rgba(135,211,43," + alpha + ")";
}
// ...
}
这种颜色映射方案符合地形分析的常规表达方式,便于直观理解不同区域的坡度特征。
坡向箭头绘制
javascript
let worldToLocalMatrix = Cesium.Matrix4.inverse(localToWorldMatrix, new Cesium.Matrix4());
// 计算向量
let worldVector = Cesium.Cartesian3.subtract(positions1[1], positions1[0], new Cesium.Cartesian3());
// 计算世界坐标系下的向量转换到 ENU 坐标系下的向量
let localVector = Cesium.Matrix4.multiplyByPointAsVector(
worldToLocalMatrix,
worldVector,
new Cesium.Cartesian3()
);
// 归一化
let direction = Cesium.Cartesian3.normalize(localVector, new Cesium.Cartesian3());
// 计算 localVector 向量与 X 轴之间的角度(弧度制)
let angleToX = Math.atan2(direction.y, direction.x);
// 弧度转度数
let heading = Cesium.Math.toDegrees(angleToX);
这段代码通过坐标变换和向量计算,确定了坡向的方位角。最终通过PolylineArrow
材质绘制箭头,直观表示坡向方向。
最后
OK,希望通过这篇技术分享能够帮助更多开发者理解和实现三维地形分析功能,也能够促进Cesium
技术在各行业的应用与创新。
完整源码在不浪的教程
《Cesium从入门到实战》
,将Cesium的知识点进行串联,让不了解Cesium的小伙伴拥有一个完整的学习路线,并最终完成一个智慧城市的完整项目,关注公众号:攻城师不浪,即可收到教程介绍,还可+作者:brown_7778(备注来意)。
有需要进可视化&Webgis交流群
可以加我:brown_7778(备注来意)。