원클릭으로
minemap-terrain-and-analysis
MineMap 地形设置(setTerrain)、DEM 高程查询、地形分析、TerrainLeveling、相机碰撞高度与 terrain 相关约束。
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
MineMap 地形设置(setTerrain)、DEM 高程查询、地形分析、TerrainLeveling、相机碰撞高度与 terrain 相关约束。
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
MineMap 3D 公告板(Billboard)专题。覆盖 BillboardMaterial / BillboardGeometry / BillboardInstance 动画、拾取高亮、动态纹理更新与轨迹对象联动;不与 DOM 覆盖物 Marker 混淆。
MineMap 云与大气渲染链。用于启用体积云(多层 CloudLayer)、单片实例化云(map.cloudCollection)、大气散射与太阳 / 天空辐照度,重点说明主分支公开参数与禁用字段。
MineMap 事件订阅模型、图层事件代理、once/off 管理、矢量与三维对象拾取。
MineMap 热力图(heatmap)专题。用于二维 / 三维热力图、贴地热力、聚合权重、热力色阶与 3D 显示模式,重点说明 paint/layout 参数边界与典型失败场景。
MineMap KML 数据源。用于加载 KML / KMZ 文件,解析 LineStyle / IconStyle / LabelStyle / PolyStyle 等样式继承,并把 KML 属性映射为 line / circle / fill / symbol 派生图层。
MineMap 材质与着色规范。覆盖 `StandardMaterial`、`PhongMaterial`、`PhysicalMaterial`、`LambertMaterial`、`PolylineMaterial` 等主流材质的选型与调参。
| name | minemap-terrain-and-analysis |
| description | MineMap 地形设置(setTerrain)、DEM 高程查询、地形分析、TerrainLeveling、相机碰撞高度与 terrain 相关约束。 |
const map = new minemap.Map({
container: "map",
style,
position: [89.11, 27.4, 15000],
pitch: 55,
projection: minemap.ProjectionType.MERCATOR,
minHeightToDemSurface: 5,
terrainSkirtHeight: -1
});
map.on("load", () => {
map.setTerrain({
tiles: ["https://example.com/dem/{z}/{r}/{c}/{z}_{x}_{y}.terrain"],
availabilities: ["https://example.com/dem/layer.json"],
tileSize: 512,
maxzoom: 14,
extensions: {
requestVertexNormals: false,
requestWaterMask: false,
requestHeightFieldNormals: false
}
});
map.addSource("imagery", {
type: "raster",
tiles: ["https://example.com/satellite/{z}/{r}/{c}/{z}_{x}_{y}.jpg"],
tileSize: 512
});
map.addLayer({
id: "imagery",
type: "raster",
source: "imagery"
});
const height = map.queryDEMHeightByLngLat([89.11316, 27.40665]);
console.log(height.z);
});
map.setTerrain(...) 的本质不是“再叠一层 DEM 图层”。
它做的是:
所以要记住:
raster source/layermap.setTerrain() 管这就是为什么 MineMap 4.x 已不推荐继续用旧式 terrainTiles + renderWithTerrain 那套 source/layer 写法。
setTerrain() 背后实际做了什么map.setTerrain(options) 是 MineMap 4.x 推荐 DEM 接口。
源码里能确认的实际行为有:
symbolHeightExtraction 缓存style.rasterSourceCache.setTerrain(options) 切换 terrain sourceproxySourceCache 的 layer order,保证矢量贴地缓存状态刷新所以正确理解是:
setTerrain() 是一个全局场景切换动作TerrainTileSource 是内部 terrain 数据源。
从源码可确认:
quantizedheightmap_terrainTiles_tempTerrainTiles,用来减轻切换时闪烁maxzoom 时,不再继续请求更细 DEM,而是走上采样 upsample这决定了两个开发结论:
maxzoom 不是越大越好,取决于你实际 DEM 精度只开 setTerrain() 还不够,它只负责地表几何。
通常你还需要再加一个普通影像或栅格底图:
典型组合:
map.setTerrain(...)map.addSource("imagery", { type: "raster", ... })map.addLayer({ type: "raster", source: "imagery" })地形开启后,只是让地图有真实起伏。
要不要贴地,还要看对象本身:
adaptTerrainMarker / Popup 要看 setAltitude() 与 terrain pick不要把“开启 terrain”误解成“所有对象自动贴地完成”。
setTerrain() Parameter Surfacetiles: string[] | nulltileSize: numbermaxzoom: numberavailabilities: string[] | nullextensionstilesterrain 瓦片 URL 模板。
常见形式是 .terrain 文件:
tiles: ["https://example.com/dem/{z}/{r}/{c}/{z}_{x}_{y}.terrain"];
语义:
tiles: null 表示回退到平面/椭球地表源码实现上,传 falsy 也会退回 ellipsoid;但稳定文档写法仍建议显式用:
map.setTerrain({ tiles: null });
tileSizeDEM 瓦片大小。
MineMap 4.x terrain 相关示例和源码默认使用:
512建议:
512 组织maxzoomDEM 数据的最高请求层级。
源码注释明确给出了经验值:
1416注意:
availabilities,源码注释说明 maxzoom 不再是最高精度遍历的主要依据availabilities地形索引文件列表,常见是 layer.json。
它的价值很大:
queryAccurateDEMHeightByPoint() 想拿到“最高精度”结果时,推荐配置它maxzoom推荐:
layer.json,就加上extensionsterrain 扩展对象,源码里可确认的 3 个字段:
requestVertexNormalsrequestWaterMaskrequestHeightFieldNormals默认都为 false。
requestVertexNormals请求顶点法线扩展。
适用:
requestWaterMask请求水面掩膜扩展。
适用:
requestHeightFieldNormals请求区域场法线扩展。
这个在地形分析里尤其有意义。源码和 demo 都表明:
zeroTileRequestUrl这是一个非常值得写进 skill 的“半隐藏参数”。
虽然 map.setTerrain() 的当前类型注释里没有完整展开,但:
queryAccurateDEMHeightByPoint() 的示例里出现了它TerrainTileSource 构造函数里也明确支持它作用:
适合:
terrainSkirtHeight地图构造参数和运行时属性都支持它。
语义:
规则:
< 0:按级别动态计算>= 0:固定值源码里动态值的实际逻辑是:
getLevelMaximumGeometricError(z) * 5.0建议:
-1运行时也可直接改:
map.terrainSkirtHeight = 80;
改完会重新按当前 terrain 配置刷新 terrain source。
minHeightToDemSurface这个参数非常关键,但经常被忽略。
语义:
默认值:
5适用:
运行时可直接调:
map.minHeightToDemSurface = 5;
enableUnderGround地下模式。注意:enableUnderGround 在主分支上是一个属性赋值,不是方法,调用方式与 enableLight / enableClouds 不同。
来源:source/api/map.js line 4999+。
两种开启方式:
// 方式 A:构造选项(推荐一次性开启)
var map = new minemap.Map({
container: "map",
style,
enableUnderGround: true, // 地下模式
position: [108.96, 34.21, 338],
pitch: 90,
maxZoom: 100, // 地下模式要尽量大于 24
logDepth: true // 必须配 logDepth
});
// 方式 B:运行时动态切换
map.enableUnderGround = true; // 开启
map.enableUnderGround = false; // 关闭
开启后行为:
raster / 影像)继续渲染,需要显式关闭 depth-test 避免被地形遮挡配套设置:
| 配套项 | 推荐值 | 说明 |
|---|---|---|
logDepth | true | 源码注释:否则进入地下后地形会闪烁(z-fighting) |
maxZoom | >= 24 | 地下模式要求 maxZoom 至少大于 24,否则可能报错 |
pitch | >= 80 | 高俯仰角更利于观察地下场景 |
raster depth-test | false | 影像层在地下时需关闭深度测试,否则会被地形遮住 |
示例(参考 demo/html/Underground.html):
var map = new minemap.Map({
container: "map",
style,
position: [108.96, 34.21, 338],
bearing: 90,
pitch: 90,
roll: 0,
maxZoom: 100,
minZoom: 1,
projection: "MERCATOR",
logDepth: true,
enableUnderGround: true
});
map.enableLight();
map.setTerrain({
tiles: ["https://.../dem/{z}/{r}/{c}/{z}_{x}_{y}.terrain"],
tileSize: 512,
maxzoom: 14
});
map.on("load", function () {
map.addSource("IMAGERY_SOURCE", {
type: "raster",
tiles: ["https://.../satellite/{z}/{r}/{c}/{z}_{x}_{y}.jpg"],
tileSize: 512
});
map.addLayer({
id: "IMAGERY",
type: "raster",
source: "IMAGERY_SOURCE",
minzoom: 0,
maxzoom: 23,
"depth-test": false, // 地下时影像不能被地形挡住
paint: { "raster-opacity": 1 }
});
// 地下管廊 / 隧道 / 设施
map.addSceneComponent({
id: "pipeline",
type: "3d-model",
data: "../data/UndergroundTube/pipeline.gltf",
modelFolder: "../data/UndergroundTube/",
rotation: [90, 0, 0],
position: [108.965, 34.218, 360] // z 大于 0 仍然显示为"在地下"
});
});
注意事项:
enableUnderGround 是属性赋值,不是 enableUnderGround() 方法调用;map.enableUnderGround() 会报错position 第三项(z/alt)填负值也可以工作,但源码注释提醒:未开启 enableUnderGround 时传负高度,会被定位到 [0, 0, 6378137*6]Sky 自动隐藏,相机飞到地下不会渲染天空盒适用场景:
requestInterval地图构造参数中的请求重试/等待间隔,源码注释明确写了:
60适用:
常见查询:
queryDEMHeightByPoint(...)queryAccurateDEMHeightByPoint(...)queryDEMHeightByLngLat(...)queryDEMSourceHeightByPoint(...)使用建议:地图稳定后(idle)再做高频批量查询。
queryDEMHeightByPoint(queryGeometry)输入:
过程:
sampleTerrain(...) 采样高程返回:
Vector3特点:
适合:
queryAccurateDEMHeightByPoint(queryGeometry)输入仍然是屏幕像素坐标,但内部会调用:
sampleTerrainMostDetailed(...)特点:
availabilities适合:
queryDEMHeightByLngLat(lnglat)输入:
输出:
Vector3适合:
queryDEMSourceHeightByPoint(e, source)这是更低层的“指定 DEM source”查询入口。
当前项目里更常用的还是前三个方法;只有你明确在做 DEM source 级控制时再使用它。
map.on("load", () => {
map.setTerrain({
tiles: [terrainUrl],
tileSize: 512,
maxzoom: 14
});
map.addSource("imagery", {
type: "raster",
tiles: [imageryUrl],
tileSize: 512
});
map.addLayer({
id: "imagery",
type: "raster",
source: "imagery"
});
});
这是最标准的 terrain 起图模式。
map.on("click", async (e) => {
const point = await map.queryAccurateDEMHeightByPoint(e.point);
console.log(point.z);
});
前提:
availabilitiesconst point = map.queryDEMHeightByLngLat([116.39, 39.9]);
const z = point.z;
适合在放模型、marker、分析点之前先拿地表高度。
terrain 打开后,Marker 拖拽会走 terrain pick。
这意味着:
适合:
terrain 开启后,如果 primitive 本身支持:
adaptTerrain: true就可以让线面对象沿地表起伏。
但这依赖对象本身的 geometry/material 支持,不是 terrain 自动替你完成的。
map.setTerrainAnalysis(options) 是 terrain 栅格分析入口。
当前源码可确认:
property 支持 SLOPE、ASPECT、ELEVATIONtype 支持 EXPONENTIAL、INTERVAL、CATEGORICALbasestopsdefaultregionhasArrowproperty决定分析的地形属性:
SLOPE:坡度ASPECT:坡向ELEVATION:高程带type颜色插值方式:
EXPONENTIALINTERVALCATEGORICAL如果用 EXPONENTIAL,可再配:
base默认 base = 1.0,也就是线性插值感。
stops分析值到颜色的映射表。
要求:
Color 名称default不命中 stops 时的默认颜色。
region区域分析时的掩膜区域。
不传时:
传入时:
hasArrow是否显示方向箭头。
源码注释写的是“目前仅有坡度分析有效”,而 demo 用它表达坡向指示,所以更稳妥的理解是:
map.setTerrainAnalysis({
type: minemap.InterpolationType.EXPONENTIAL,
property: minemap.TerrainAnalysisType.SLOPE,
stops: [
[0, "#00FF00"],
[30, "#FFFF66"],
[60, "#FF8000"],
[90, "#FF0000"]
],
default: "rgba(0,0,255,1)",
region: region,
hasArrow: true
});
TerrainLeveling:地形平整TerrainLeveling 不是简单的“盖一个面”。
从源码看,它会:
region 和平整深度 depthonAdd(map) 时找出与区域相交的 terrain tilecartographicListreferenceHeight也就是说,它本质是:
region: number[]:[lng, lat, lng, lat, ...]depth: number它是 scene object,不是 layer,也不是普通 analysis API。
推荐写法:
const leveling = new minemap.TerrainLeveling({
region: [89.1, 27.4, 89.2, 27.4, 89.2, 27.3, 89.1, 27.3],
depth: 50
});
map.addSceneComponent(leveling);
运行时可调:
leveling.setDepth(80);
console.warn 并禁用map.analysis 下默认挂载:
cutFillCollectionexcavationCollectionhighlightCollectionsightlineCollectionviewDomeCollectionviewshed3DCollectioninterferenceCollectionshadowAnalysisCollectionfloodAnalysisCollectionfloodAnalysisOfflineCollectionindex.js 已导出的其他分析类除了可视域、通视、淹没、阴影,公开导出里还包括:
HighlightCutFillExcavationViewDomeInterferenceInterferenceConjoinedProfilePlayer当前空间分析相关能力已按职责拆成 4 个 skill,不再只放在一个总包里:
minemap-terrain-and-analysis
map.analysis 容器入口minemap-business-visibility-analysis
Viewshed3DSightlineminemap-business-flood-and-shadow
FloodAnalysisFloodAnalysisOfflineShadowAnalysisminemap-business-measurement
Measurement3Dminemap-business-spatial-analysis-suite
setTerrainAnalysis(...)CutFillExcavationLimitHeightViewDomeInterferenceInterferenceConjoinedProfile文档策略:
Viewshed3D、Sightline、FloodAnalysis)切换项目/场景时统一 removeAll(),避免分析对象残留。
Highlight / CutFill / Excavation 更偏地形或对象表达修饰ViewDome / Interference / InterferenceConjoined 更偏视场与干扰表达Profile / Player 更偏剖切、播放或过程辅助推荐做法:按业务模块维护自己的分析对象引用,并同步挂入 map.analysis.*Collection,不要创建后失去控制句柄。
if (map.isTerrain()) {
console.log("terrain enabled");
}
map.setTerrain({ tiles: null });
虽然实现层面对 falsy 也有兼容,但文档化写法推荐保持显式。
queryDEMHeightByPoint() 而不是总是走 queryAccurateDEMHeightByPoint()availabilities 能配就配,尤其是高精度查询和大范围分析terrainSkirtHeight 优先保留动态值,除非你明确在调接缝问题TerrainLeveling 依赖 WebGL2,不要把它当成所有终端都能稳定开启的通用效果terrain 相关资料建议交叉看:
https://minedata.cn/https://minedata.cn/nce-support/guide-3D-Ultrahttps://minedata.cn/nce-support/api-3D-Ultrahttps://minedata.cn/nce-support/demoCenter-3D-Ultra本地 demo 里和 terrain 强相关的证据源包括:
demo/html/QueryDEMHeight.htmldemo/html/DemAnalysis.htmldemo/html/TerrainLeveling.htmldemo/html/MarkerDraggableOnTerrain.htmldemo/html/RasterTerrainChange.html查 terrain 时推荐顺序:
source/api/map.js、source/data-source/source-cache/TerrainTileSource.js 看真实行为minemap-official-resources-and-onboardingminemap-fundamentalsminemap-2d-3d-overlay-and-classificationminemap-marker-and-popupminemap-primitives-and-materialsminemap-business-visibility-analysisminemap-business-flood-and-shadowminemap-business-measurementminemap-business-spatial-analysis-suiteminemap-performance-and-backend