**本文档及路线由“”本人创作,禁止抄袭。
目的是感谢“蚂蚁管道”的盛哥提供免费软件,希望有能力的兄弟能够与他合作。
本文档可以针对整个城区的管点和管道,实现shp官网数据的数据生成生成3D obj然后传输到3Dtiles,最后在Cesium上加载显示。 另外,“ant pipeline”生成的obj可以直接在3Dmax中查看。
我们先来看效果图:下图包括:(绿色)雨水; (紫色)污水; (棕色)雨水和污水汇合处; 综合管道等。双击查看属性,鼠标悬停查看ID。管网shp数据达到2G,最终模型6G左右。
/*************************分向線********************** **********/
具体步骤:
第一步:准备shp文件。 和 Ant Pipeline 软件。 shp 文件应该有相关字段。 具体可以参考Ant Pipeline的帮助文档。 如果还有不明白的可以私信我或者问盛哥。 软件直接到“盛哥QQ:441224629.邮箱:sgeoffrey@qq.com”申请或购买。
特别注意:如果shp数据太大,一次运行就会失败。 我用ARCGIS把城市的shp切割成十多分钟,分别生成obj模型。 如何进行下一步。
第二步:由于管道数据在市内属于保密3d模板源码,因此不再贴出地图。
shp切割arcgis加载城市的shp文件,创建一个表面来框住所有管点和管道,并将编辑表面切割成几个小块。 每个小片的最大行数据约为10000条。 如果太多,可能会引起问题。 在此过程中软件崩溃。
然后选择一个小块,按位置选择,选择小块内的所有管点和管道。
使用arcgis的“要素类到shp批量”工具将块范围内的所有管道点和管道导出为shp1。 等等...
步骤3:使用Ant Pipeline为管道点的各个部分生成obj模型。
注意:在生成的最后一步,需要检查基于地理位置的建模,以便每个obj最终都能保持其相对位置。 至于自己调整颜色,有文档(最终的模型属性带有自己的ID和文件名,但不包含属性,需要关联数据库进行查询)
完成的obj可以直接用3dmax打开查看3d模板源码,也可以转成其他格式。最好用Ant Pipeline自带的查看器打开
第 4 步:使用 cesiumlab 一次性从所有 obj 生成 3Dtile。
第5步: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;
});
步骤6:关联视图属性。 ajax请求的逻辑因后端和数据库的不同而不同。 你可以自己选择。
pickFeature.getProperty('file') 这获取文件名。 我的文件名对应数据表名,例如:雨水管‘污水管点’
pickFeature.getProperty('id').split('_')[3]:获取ID,该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属性表,确保ids都正确,高程是否为0,管径是否异常。
另一个技巧:例如,我的管道 ID 是 00YS345 和 00WS786。 中间可能有一些应该是00YS*,写成00WS。 在arcgis属性表中,“字段计算器”中选择python,运行以下代码:field name.replace('WS','YS'); 好的!
2:上面提到了软件运行中途崩溃的问题。 再次打开并运行剩下的文件,最后发现后面生成的文件和前面的文件顺序乱了! ! ! 是不是很烦人。 多么破碎啊! ! !
列出我想到的解决方案:
场景假设:由于shp文件太大,所以将shp分为5个文件12345。当依次运行1234到第4个时,软件自动崩溃。 再次打开运行文件 45。 45和123生成的obj坐标原点不对应。 最后,它们在铯中叠加在一起。
方法一:使用obj123执行上面第四步生成3Dtiles1; 使用obj45执行上面第四步生成3Dtiles2。 分别在 cesium 中加载两个 3Dtile。 这种方法的问题是需要同时操作两个数据,并且指定两个瓦片的位置比较麻烦。
方法二:软件崩溃后,打开软件再次执行shp1,然后执行4和5。这样可以保证后面生成的45和前面的123是同一个坐标原点。 推荐推荐!