C2——cesium加载城市级三维管⽹模型的⽅案
**本⽅案及路线由“”GIS特战兵”⾃⼰想出来的,禁⽌抄袭。
创作⽬的是为感谢“蚂蚁管线”的盛哥提供的免费软件,希望有能⼒的兄弟能与他合作。
本⽅案可⽤于整个市区的管点和管线,实现shp官⽹数据数据⽣成三维obj再转3Dtiles最终在Cesium加载显⽰。另外⽤“”蚂蚁管
线“”⽣成的obj可以直接在3Dmax⾥查看
先上效果图:下图包括:(绿⾊) ⾬⽔ ;(紫⾊)污⽔;(棕⾊) ⾬污合流;综合管线等。双击可以查看属性,⿏标滑过可以查看ID。管⽹shp数据达2G,最终模型6G左右
/*************************分割线********************************/
具体步骤:
第⼀步:.准备好shp⽂件。和蚂蚁管线的软件。shp⽂件应该带有相关字段,具体参见蚂蚁管线的帮助⽂档,还不懂的可以私信我或者问盛哥,软件直接 “盛哥 QQ:441224629。邮箱:sgeoffrey@qq”申请或购买
特别说明:shp数据太⼤的话⼀次运⾏会失败,我⽤ARCGIS讲全市shp裁成了⼗⼏分分别⽣成obj模型。怎么操作接下⼀步。
第⼆步:因为管线数据全市涉密的再次就不贴图了。
shp裁剪arcgis加载全市shp⽂件,创建⾯框住所有管点管线,编辑⾯裁成若⼲⼩块,我的每个⼩块⾥⾯最多的⼀个线数据在⼀万多左右,太多了可能会出运⾏过程中软件崩溃的问题。
然后选择⼀个⼩块,按位置选择,将⼩块内的所有管点管线选中。
⽤arcgis的“要素类转shp批量”⼯具,将该镶块范围内的所有管点管线导出为shp1。以此类推……
第三步:⽤蚂蚁管线将每部份的管线管点⽣成obj模型。
注意:⽣成最后⼀步需要勾选 基于地理位置建模 这样每个obj最终能保持相对位置不变。⾄于颜⾊啥的⾃⼰调整,说明⽂档都有(最终模型属性⾃带id和⽂件名,但不包含属性,需要关联数据库进⾏查询)
成成的obj可以⽤3dmax直接打开看呃,也可以转为其他格式。最好⽤蚂蚁管线⾃带的查看器打开
第四步:⽤cesiumlab将所有obj⼀次性⽣成3Dtiles。
贴代码吧:
let pipeDazu1 = this.viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: "../src/data/3Dtiles/pipedazu1/tileset.json",
skipLevelOfDetail: true, //开启跳级加载
maximumMemoryUsage: 2000, //最⼤内存占⽤推荐显存的⼀般
preferLeaves: true,
maximumScreenSpaceError: 16,
// maximumNumberOfLoadedTiles: 2000,
})
);
let rotationX = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromRotationX(Radians(0)));
let rotationY = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromRotationY(Radians(0)));
let rotationZ = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromRotationZ(Radians(0)));
let m = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(1**.73427380132752, 2*.687039062817977, 245));    //旋转、平移矩阵相乘
Cesium.Matrix4.multiply(m, rotationX, m);
Cesium.Matrix4.multiply(m, rotationY, m);
Cesium.Matrix4.multiply(m, rotationZ, m);
pipeDazu1._ansform = m;
});
第六步:关联查看属性。ajax请求的逻辑,不同后端和数据库不⼀样⾃⼰选择吧。
// 管⽹3dtiles 选中及属性检测***********************************************
// 组装弹窗元素
let nameOverlay = ateElement('div');
nameOverlay.className = 'backdrop';
nameOverlay.style.display = 'none';
nameOverlay.style.position = 'absolute';
nameOverlay.style.bottom = '0';
nameOverlay.style.left = '0';
nameOverlay.style['pointer-events'] = 'none';
nameOverlay.style.padding = '4px';
nameOverlay.style.backgroundColor = 'yellowgreen';
/*⿏标移动选择管线*/
最适合居住的城市let selected = {
feature: undefined,
originalColor: new Cesium.Color()
};
let highlighted = {
feature: undefined,
originalColor: new Cesium.Color()
};
let selectedEntity = new Cesium.Entity();
let clickHandler = InputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
/*左键双击显⽰查看管线属性*/
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
if (Cesium.defined(selected.feature)) {
lor = iginalColor;
selected.feature = undefined;
}
let pickedFeature = viewer.scene.pick(movement.position);
if (!Cesium.defined(pickedFeature) || !Cesium.Property)) {
return;
}
if (selected.feature === pickedFeature) {
return;
}
selected.feature = pickedFeature;
if (pickedFeature === highlighted.feature) {
Cesium.Color.iginalColor, iginalColor);
highlighted.feature = undefined;
} else {
Cesium.Color.lor, iginalColor);
}
if (Property('file')) {//查询⽂件对应导数据库⾥边的tablename
$.ajax({
type: "GET",
url: "/guanwang/" + Property('file') + "/" + Property('id').split('_')[3],
success: function (data) {
let str = '<table class="cesium-infoBox-defaultTable"><tbody>';
for (let key in data) {
str += '<tr><th>' + _this.fieldsConversion(key) + '</th><td>' + data[key] + '</td></tr>';
}
str += '</tbody></table>';
if ($('#popup').is(':visible')) {  //如果node是显⽰的则隐藏node元素,否则显⽰
$('#popup').css("display", "none")
}
$("#popup-container").html(str);
$('#popup').css("left", "20%")
$('#popup').fadeIn(300);
},
error: function (data) {
console.log("Error: " + data.status);
}
});
}
}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
⼤功告成这波操作应该是⽐较溜的吧,技术路线都是⾃⼰想了很久试了很多⽅法才⾛通的。请不要抄袭,转载清注明原出处:
补充:主要是我在⽤的时候遇到的问题
1:⽣成的模型最后有部分点线丢失了这么办!。
原因:shp数据⾥管点的id和管线的id没对上。
处理:修改id。最好是检查⼀下shp属性表确保id都能对上,还有⾼程有没有为0的,管径有没有异常。
再来个技巧:⽐如我的管点id为00YS345、00WS786。中间可能出现有的应该是00YS*的被写成了00WS。 在arcgis属性表⾥“字段计算器”选python运⾏下⾯代码  :字段名.replace('WS','YS');  OK!