SuperMap iClient3D for Cesium等高线标注
kele
前言
在三维地形分析中,等高线分析是一种非常重要的分析方法,它能直观的表达出地形的高低起伏特征,在三维系统中受到广泛应用。在SuperMap iClient3D for Cesium中,等高线分析是前端GPU分析,能够分析并渲染出等高线,但是无法获取高程标注,这对三维项目来说缺少一个重要的地形高度指标。那么如何实现等高线的高程数值展示呢?我们一起来看下吧
一、效果展示
二、实现方法
1、激活鼠标绘制类,绘制分析范围
//绘制多边形
var tooltip = createTooltip(document.body);
var polygonHandler = new Cesium.DrawHandler(viewer, Cesium.DrawMode.Polygon);
polygonHandler.activeEvt.addEventListener(function (isActive) {
if (isActive == true) {
viewer.enableCursorStyle = false;
viewer._element.style.cursor = '';
$('body').removeClass('drawCur').addClass('drawCur');
} else {
viewer.enableCursorStyle = true;
$('body').removeClass('drawCur');
}
});
polygonHandler.movingEvt.addEventListener(function (windowPosition) {
tooltip.showAt(windowPosition, '<p>开始绘制分析区域,右键结束绘制</p>');
});
polygonHandler.drawEvt.addEventListener(function (polygon) {
polygonHandler.polygon.show = false;
polygonHandler.polyline.show = false;
tooltip.setVisible(false);
var array = [].concat(polygon.object.positions);
let positions = [],geometries = [];
for (var i = 0, len = array.length; i < len; i++) {
var cartographic = Cesium.Cartographic.fromCartesian(array[i]);
var longitude = Cesium.Math.toDegrees(cartographic.longitude);
var latitude = Cesium.Math.toDegrees(cartographic.latitude);
var h = cartographic.height;
if (positions.indexOf(longitude) == -1 && positions.indexOf(latitude) == -1) {
positions.push(longitude);
positions.push(latitude);
positions.push(h);
var queryPoint = { // 查询点对象
x: longitude,
y: latitude
};
geometries.push(queryPoint)
}
}
floodUpdate(positions); //分层设色绘制等值线
doQuery(geometries); //根据范围进行空间分析,返回结果高程,前端绘制entity-label展示
polygonHandler.deactivate();
});
2、根据绘制范围进行前端GPU分层设色,得到等高线效果
function floodUpdate(positions){
//创建分层设色对象
hyp = new Cesium.HypsometricSetting();
//设置分层设色的显示模式为线
hyp.DisplayMode = Cesium.HypsometricSettingEnum.DisplayMode.LINE;
//设置线颜色为红色
hyp._lineColor = new Cesium.Color(1.0, 0.0, 0.0, 1.0);
//等高线间隔为100m
hyp.LineInterval = 100.0;
//设置分层设色的最大/最小可见高度
hyp.MaxVisibleValue = 9000;
hyp.MinVisibleValue = 0;
//设置分层设色颜色表的最大/最小key值,表示在此高度范围内显示颜色表
hyp.ColorTableMinKey = 2736.88110351563;
hyp.ColorTableMaxKey = 5597.06640625;
//新建颜色表
var colorTable = new Cesium.ColorTable();
colorTable.insert(4262.3132649739609,new Cesium.Color(102/255, 255/255, 153/255));
//设置分层设色的颜色表
hyp.ColorTable = colorTable;
//设置分层设色的透明度
hyp.Opacity = 0.4;
hyp.CoverageArea = positions;
hyp.DisplayMode = Cesium.HypsometricSettingEnum.DisplayMode.LINE; //以等值线方式展示
viewer.scene.globe.HypsometricSetting = {
hypsometricSetting : hyp,
analysisMode : Cesium.HypsometricSettingEnum.AnalysisRegionMode.ARM_REGION //自定义分析范围
};
}
3、使用SuperMap iServer将dem数据集发布为空间分析服务,根据绘制范围进行数据集的等高线分析。需要注意的是,SuperMap iServer等高线分析的分析间距需要和第二步中分层设色等高线间隔保持一致
function doQuery(geometries) {
var queryObj = {
"extractParameter":{
"datumValue":0,
"interval":100, //等高线见距
"resampleTolerance":0.7,
"smoothMethod":"BSPLINE",
"smoothness":3,
"clipRegion":{
"points":geometries, //分析范围
"type":"REGION"}
},
"resultSetting":{
"dataset":"",
"dataReturnMode":"RECORDSET_ONLY",
"expectCount":100,
"deleteExistResultDataset":true
}
};
var queryData = JSON.stringify(queryObj); // 转化为JSON字符串作为查询参数
$.ajax({
type: "post",
url: "http://localhost:8090/iserver/services/spatialAnalysis-DengGaoXian/restjsr/spatialanalyst/datasets/BeijingTerrain@BeijingTerrain/isoline.rjson?returnContent=true",
data: queryData,
success: function (result) {
},
error: function (msg) {
console.log(msg);
},
})
}
4、分析结果中包含等高线节点以及对应的高度,由于以上步骤已经通过GPU分层设色实现了等高线的渲染,这里只需添加高度标注即可。
在标注过程中有这样一个困扰,分析结果等值线可能为复合对象并且有很多节点,高程标注放在哪个节点位置合适呢?小编的做法是将复合等值线对象进行拆分为简单对象,在每个简单对象的第一个节点上进行标注,以下是实现代码
var resultObj = JSON.parse(result);
let features = resultObj.recordset.features;
for(let fea of features){
let num = fea.geometry.parts.length; //parts长度表示子对象数量,parts内容表示每个子对象的节点数量
for(let i=0;i<num;i++){
let index = 0;
if(i === 0){
index = 0
}else{
index = fea.geometry.parts[i-1];
}
viewer.entities.add({
position: new Cesium.Cartesian3.fromDegrees(fea.geometry.points[index].x,fea.geometry.points[index].y,Number(fea.fieldValues[5])),
label:{
text: fea.fieldValues[5],
fillColor: Cesium.Color.ORANGE,
scaleByDistance: new Cesium.NearFarScalar(1000, 1, 100000, 0.1)
}
})
}
}