淹没分析是三维分析常用的的其中一种分析,本文借鉴已有资料通过在地形图上动态拉伸polygon达到淹没分析的效果,下面给出淹没分析的主要代码:
效果:
一、容器创建&添加地形服务、
var currentHeight = null, maxValue=null;
//创建地形图层
var rectangle = new Cesium.Rectangle(Cesium.Math.toRadians(5.9993076), Cesium.Math.toRadians(-0.00025749207),
Cesium.Math.toRadians(7.00078), Cesium.Math.toRadians(1.001215));
var terrainLayer = new Cesium.CesiumTerrainProvider({
url: 'http://localhost:9002/api/wmts/terrain/671bf0e4425e421a8fbe701e2b4db959',
requestWaterMask: true,
credit: 'http://www.bjxbsj.cn',
});
//创建容器
var viewer = new Cesium.Viewer('cesiumContainer', {
selectionIndicator: false,
infoBox: false,
terrainProvider: terrainLayer
});
viewer.scene.globe.depthTestAgainstTerrain = true;
//定位到目标地形
viewer.scene.camera.flyTo({ destination: rectangle });
二、动态画贴地面(借鉴官网)
var entityPolygon = null;
var points = null;
//取消左键双击事件
var drawingMode = 'polygon';
var activeShapePoints = [];
var activeShape;
var floatingPoint;
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
//淹没分析entity
function createPoint(worldPosition) {
var point = viewer.entities.add({
position: worldPosition,
point: {
pixelSize: 10,
color: Cesium.Color.YELLOW,
//disableDepthTestDistance: Number.POSITIVE_INFINITY,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
},
});
points = point;
return point;
}
function drawShape(positionData) {
var shape;
if (drawingMode === 'line') {
shape = viewer.entities.add({
polyline: {
positions: positionData,
clampToGround: true,
arcType: Cesium.ArcType.RHUMB,
material: Cesium.Color.GREEN,
width: 5,
//zIndex:1
}
});
}
else if (drawingMode === 'polygon') {
shape = viewer.entities.add({
polygon: {
hierarchy: positionData,
material: new Cesium.ColorMaterialProperty(Cesium.Color.LIGHTSKYBLUE.withAlpha(0.7))
}
});
}
else if (drawingMode === 'point') {
shape= viewer.entities.add({
position: worldPosition,
point: {
pixelSize: 10,
color: Cesium.Color.YELLOW,
//disableDepthTestDistance: Number.POSITIVE_INFINITY,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND//是否贴地
},
});
}
return shape;
}
var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(function (event) {
if (!Cesium.Entity.supportsPolylinesOnTerrain(viewer.scene)) {
console.log('This browser does not support polylines on terrain.');
return;
}
// 使用viewer.scene.pickPosition` 来代替`viewer.camera.pickEllipsoid` 这样当鼠标掠过terrain能得到正确的坐标
var earthPosition = viewer.scene.pickPosition(event.position);
if (Cesium.defined(earthPosition)) {
if (activeShapePoints.length === 0) {
floatingPoint = createPoint(earthPosition);
activeShapePoints.push(earthPosition);
var dynamicPositions = new Cesium.CallbackProperty(function () {
return activeShapePoints;
}, false);
activeShape = drawShape(dynamicPositions);
}
activeShapePoints.push(earthPosition);
createPoint(earthPosition);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function (event) {
if (Cesium.defined(floatingPoint)) {
var newPosition = viewer.scene.pickPosition(event.endPosition);
if (Cesium.defined(newPosition)) {
floatingPoint.position.setValue(newPosition);
activeShapePoints.pop();
activeShapePoints.push(newPosition);
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// Redraw the shape so it's not dynamic and remove the dynamic shape.
function terminateShape() {
activeShapePoints.pop();
entityPolygon = drawShape(activeShapePoints);
if (entityPolygon.polygon!=null) {
thisWidget.drawOk(entityPolygon);
}
viewer.entities.remove(floatingPoint);
viewer.entities.remove(activeShape);
entityPolygon = null;
floatingPoint = undefined;
activeShape = undefined;
activeShapePoints = [];
}
handler.setInputAction(function (event) {
terminateShape();
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
三、淹没分析核心代码(借鉴火星科技)
//淹没分析核心代码
var thisWidget = {
entity: null,
drawOk: function (e) {
this.entity = e;
var t = this.computePolygonHeightRange(e.polygon.hierarchy.getValue());
currentHeight = t.minHeight, maxValue = t.maxHeight;
},
computePolygonHeightRange: function (e) {
var t = []
for (var i = 0; i < e.length; i++) t.push(e[i].clone());
var a, n, r, o, s, u, l, h = 0,
g = 9999,
c = Math.PI / Math.pow(2, 11) / 64,
m = new Cesium.PolygonGeometry.fromPositions({
positions: t,
vertexFormat: Cesium.PerInstanceColorAppearance.FLAT_VERTEX_FORMAT,
granularity: c
}),
d = new Cesium.PolygonGeometry.createGeometry(m);
for (i = 0; i < d.indices.length; i += 3) a = d.indices[i],
n = d.indices[i + 1],
r = d.indices[i + 2],
l = new Cesium.Cartesian3(d.attributes.position.values[3 * a], d.attributes.position.values[3 * a + 1], d.attributes.position.values[3 * a + 2]),
(o = viewer.scene.globe.getHeight(Cesium.Cartographic.fromCartesian(l))) < g && (g = o),
h < o && (h = o),
l = new Cesium.Cartesian3(d.attributes.position.values[3 * n], d.attributes.position.values[3 * n + 1], d.attributes.position.values[3 * n + 2]),
(s = viewer.scene.globe.getHeight(Cesium.Cartographic.fromCartesian(l))) < g && (g = s),
h < s && (h = s),
l = new Cesium.Cartesian3(d.attributes.position.values[3 * r], d.attributes.position.values[3 * r + 1], d.attributes.position.values[3 * r + 2]),
(u = viewer.scene.globe.getHeight(Cesium.Cartographic.fromCartesian(l))) < g && (g = u),
h < u && (h = u);
return {
maxHeight: h,
minHeight: g
}
},
startFx: function (e) {
viewer.scene.globe.depthTestAgainstTerrain = !0;
var t = this;
this.extrudedHeight = e,
this.entity.polygon.extrudedHeight = new Cesium.CallbackProperty(function (e) {
return t.extrudedHeight
}, false);
for (var i = this.entity.polygon.hierarchy.getValue(), a = [], n = 0; n < i.length; n++) {
var r = Cesium.Ellipsoid.WGS84.cartesianToCartographic(i[n]),
o = {
lon: Cesium.Math.toDegrees(r.longitude),
lat: Cesium.Math.toDegrees(r.latitude),
hgt: e
},
s = [o.lon, o.lat, o.hgt];
a = a.concat(s)
}
return i = Cesium.Cartesian3.fromDegreesArrayHeights(a),
this.entity.polygon.hierarchy = new Cesium.CallbackProperty(function (e) {
return i;
},false),
!0
},
clear: function () {
viewer.scene.globe.depthTestAgainstTerrain = !1,
this.entity = null
},
updateHeight: function (e) {
this.entity.polygon.extrudedHeight = e
}
}
function stopFX() {
self.clearInterval(int);
}
window.flood = function () {
currentHeight > maxValue ? stopFX() : (thisWidget.updateHeight(currentHeight), currentHeight += 1);
};
四、调用示例
$("#drawplygon").click(function () {
//thisWidget.clear();
viewer.entities.remove(thisWidget.entity);
entityPolygon = null;
viewer.entities.remove(points);
//terminateShape();
drawingMode = 'polygon';
entityPolygon = null;
});
$("#floodanalyis").click(function () {
console.log(viewer.entities.values.length);
int = self.setInterval(flood, 100);
});
五、防止首次模拟淹没分析闪屏
//为了防止第一次分析闪屏
var greenCylinder = viewer.entities.add({
name: 'Green cylinder with black outline',
position: Cesium.Cartesian3.fromDegrees(-100.0, 40.0, 200000.0),
cylinder: {
length: 400000.0,
topRadius: 200000.0,
bottomRadius: 200000.0,
material: Cesium.Color.GREEN.withAlpha(0.5),
outline: true,
outlineColor: Cesium.Color.DARK_GREEN
},
show:false
});
参考文章:
1、https://blog.csdn.net/sunycnb/article/details/85047605
2、http://support.supermap.com.cn:8090/webgl/examples/editor.html#floodex