**本文档及路线由”自己想出来的,禁止抄袭。
目的是为感谢“蚂蚁管线”的盛哥提供的免费软件,希望有能力的兄弟能与他合作。
本文档可用于整个市区的管点和管线,实现shp官网数据数据生成三维obj再转3Dtiles最终在Cesium加载显示。另外用“”蚂蚁管线“”生成的obj可以直接在3Dmax里查看。
先上效果图:下图包括:(绿色) 雨水 ;(紫色)污水;(棕色) 雨污合流;综合管线等。双击可以查看属性,鼠标滑过可以查看ID。管网shp数据达2G,最终模型6G左右
/*************************分割线********************************/
具体步骤:
第一步:.准备好shp文件。和蚂蚁管线的软件。shp文件应该带有相关字段,具体参见蚂蚁管线的帮助文档,还不懂的可以私信我或者问盛哥,软件直接找 “盛哥 QQ:441224629。邮箱:[email protected]”申请或购买
特别说明:shp数据太大的话一次运行会失败,我用ARCGIS讲全市shp裁成了十几分分别生成obj模型。怎么操作接下一步。
第二步:因为管线数据全市涉密的再次就不贴图了。
shp裁剪arcgis加载全市shp文件,创建面框住所有管点管线,编辑面裁成若干小块,我的每个小块里面最多的一个线数据在一万多左右,太多了可能会出运行过程中软件崩溃的问题。
然后选择一个小块,按位置选择,将小块内的所有管点管线选中。
用arcgis的“要素类转shp批量”工具,将该镶块范围内的所有管点管线导出为shp1。以此类推……
第三步:用蚂蚁管线将每部份的管线管点生成obj模型。
注意:生成最后一步需要勾选 基于地理位置建模 这样每个obj最终能保持相对位置不变。至于颜色啥的自己调整,说明文档都有(最终模型属性自带id和文件名,但不包含属性,需要关联数据库进行查询)
成成的obj可以用3dmax直接打开看呃,也可以转为其他格式。最好用蚂蚁管线自带的查看器打开
第四步:用cesiumlab将所有obj一次性生成3Dtiles。
第五步:cesium加载3Dtiles。(我上面的3Dtiles位置不能选,否则失败。但可以在cesium里自己确定坐标,而且这样是最好的)
贴代码吧:
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,
})
);
pipeDazu1.readyPromise.then(function (argument) {
let rotationX = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(0)));
let rotationY = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(0)));
let rotationZ = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(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._root.transform = m;
});
第六步:关联查看属性。ajax请求的逻辑,不同后端和数据库不一样自己选择吧。
pickedFeature.getProperty('file') 这个拿到文件名我这文件名对应数据表名比如:雨水管线‘污水管点’
pickedFeature.getProperty('id').split('_')[3]:这个拿到ID,对应查询条件。
// 管网3dtiles 选中及属性检测***********************************************
// 组装弹窗元素
let nameOverlay = document.createElement('div');
viewer.container.appendChild(nameOverlay);
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 = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
/*左键双击显示查看管线属性*/
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
if (Cesium.defined(selected.feature)) {
selected.feature.color = selected.originalColor;
selected.feature = undefined;
}
let pickedFeature = viewer.scene.pick(movement.position);
if (!Cesium.defined(pickedFeature) || !Cesium.defined(pickedFeature.getProperty)) {
return;
}
if (selected.feature === pickedFeature) {
return;
}
selected.feature = pickedFeature;
if (pickedFeature === highlighted.feature) {
Cesium.Color.clone(highlighted.originalColor, selected.originalColor);
highlighted.feature = undefined;
} else {
Cesium.Color.clone(pickedFeature.color, selected.originalColor);
}
pickedFeature.color = Cesium.Color.fromCssColorString('#0000FF');
if (pickedFeature.getProperty('file')) {//查询文件对应导数据库里边的tablename
$.ajax({
type: "GET",
url: "/guanwang/" + pickedFeature.getProperty('file') + "/" + pickedFeature.getProperty('id').split('_')[3],
success: function (data) {
let str = '';
for (let key in data) {
str += '' + _this.fieldsConversion(key) + ' ' + data[key] + ' ';
}
str += '
';
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);
大功告成!!!这波操作应该是比较溜的吧,技术路线都是自己想了很久试了很多方法才走通的。请不要抄袭,转载清注明原出处:cesium城市级管网加载策略
补充:主要是我在用的时候遇到的问题
1:生成的模型最后有部分点线丢失了这么办!。
原因:shp数据里管点的id和管线的id没对上。
处理:修改id。最好是检查一下shp属性表确保id都能对上,还有高程有没有为0的,管径有没有异常。
再来个技巧:比如我的管点id为00YS345、00WS786。中间可能出现有的应该是00YS*的被写成了00WS。 在arcgis属性表里“字段计算器”选python运行下面代码 :字段名.replace('WS','YS'); OK!
2:上面说到运行到一半软件崩溃的问题。再次代开运行剩下的文件最终发现后面生成的文件和之前的位置发生错乱了!!!是不是很气人。怎么破!!!
列出我想到的处理办法:
情景假设:由于shp文件太大,把shp分为五个文件12345.依次运行1234 到第4的时候软件自动闪退了。再次打开运行文件45。出现45生成的obj和123的坐标原点不对应。最终在cesium里就叠加到一起了。
方法一:用obj123执行上面的第四步,生成3Dtiles1;用obj45执行上面的第四步生成3Dtiles2.在cesium里分别加载两个3Dtiles。这种方法有个问题是操作数据要同时操作两个,还有需要指定两个tiles的位置比较麻烦。
方法二:软件崩溃后,打开软件先重新执行一次shp1,在执行4和5。这样就能保证后面生成的45和前面的123是同一个坐标原点。推荐推荐!