作者:kele
背景
前段時(shí)間看到一篇構(gòu)建隧道的文章(https://blog.csdn.net/supermapsupport/article/details/128453116),突然想到一個(gè)使用場(chǎng)景:隧道通常是建在山體下面,是否可以通過這種方式構(gòu)建出一條貫穿山體的隧道,來模擬實(shí)際的施工方案?答案是可以,效果圖如下:
一、實(shí)現(xiàn)思路
1、生成隧道模型
2、地形挖洞
3、把隧道模型放在洞口中
該方案的難點(diǎn)在于,如何根據(jù)隧道的截面坐標(biāo),將地形挖洞,使洞口與隧道模型完全吻合
由于地形服務(wù)無法做布爾運(yùn)算,這里采用地形開挖方式實(shí)現(xiàn),并不展示開挖底面與側(cè)面,這樣就相當(dāng)于給地形裁剪一個(gè)口子,關(guān)鍵接口:
二、實(shí)現(xiàn)過程
1、構(gòu)建管道模型
用鼠標(biāo)繪制一條折線代表隧道的走向
然后使用iServer放樣分析,輸入隧道截面坐標(biāo),分析出一條帶管壁厚度的隧道
var s3mInstanceColc = new Cesium.S3MInstanceCollection(scene._context);
scene.primitives.add(s3mInstanceColc);
var sqlParameter = {
"loftRegion":{"type":"REGION" , "parts":[8,8], "points":[{ x: -2.5, y: 7.5},
{ x: -6.5, y: 5.5 },
{ x: -10.5, y: 0 },
{ x: -10.5, y: -10.5 }, //隧道截面坐標(biāo),單位為米
{ x: 10.5, y: -10.5 },
{ x:10.5, y: 0},
{ x: 6.5, y: 5.5 },
{ x: 2.5, y: 7.5},
{ x: -1.5, y: 6.5},
{ x: 1.5, y: 6.5},
{ x: 5.5, y: 4.5 },
{ x: 9.5, y: 0},
{ x: 9.5, y: -9.5 },
{ x: -9.5, y: -9.5 },
{ x: -9.5, y: 0 },
{ x: -5.5, y: 4.5 }]},
"loftLine":{"type":"LINE3D", "parts":[2], "points":posArray},
"chamfer":"5",
"lonlat":"TRUE"
};
var url = "http://10.10.4.82:8090/iserver/services/spatialAnalysis-test/restjsr/spatialanalyst/geometry/3d/loft.json?returnContent=true";
var queryData = JSON.stringify(sqlParameter);
$.ajax({
type: "post",
url: url,
data: queryData,
success: function (result) {
var geometry = result.geometry;
if (!geometry) {
return;
}
var buffer = new Uint8Array(geometry.model).buffer;
var position = geometry.position;
var color = Cesium.Color.GRAY;
s3mInstanceColc.add('visibleBody', {
position: Cesium.Cartesian3.fromDegrees(position.x, position.y, position.z+10),
color: color,
attributes: 'test'
}, buffer);
viewer.flyTo(s3mInstanceColc);
},
error: function (msg) {
console.log(msg);
},
})
2、根據(jù)隧道給地形挖洞
2.1、去除挖洞封邊效果,去除側(cè)面與底面貼圖
scene.globe.showExcavationSide = false;
scene.globe.excavationBottomTextureUrl = null;
scene.globe.excavationSideTextureUrl = null;
2.2、開挖方案
從圖中可以看出,隧道口被堵死,我們需要拿到隧道與地形相交部分的節(jié)點(diǎn)坐標(biāo),然后將地形挖開。所以關(guān)鍵步驟就是如何得到相交坐標(biāo),如下圖所示:
第一步獲取隧道截面坐標(biāo)(紅色點(diǎn)),第二步利用隧道方向向量,繪制出基于截面坐標(biāo)且平行與隧道的線段(通視分析),第三步得到線段與地形的交點(diǎn)(藍(lán)色點(diǎn)),第四步用得到的交點(diǎn)坐標(biāo)將地形挖開
2.3、獲取截面坐標(biāo)點(diǎn)(紅色點(diǎn))
①在構(gòu)建隧道模型時(shí),我們可以根據(jù)傳入的平面坐標(biāo),計(jì)算每個(gè)端點(diǎn)與中心點(diǎn)的距離
②在繪制隧道走向時(shí),我們根據(jù)繪制坐標(biāo)計(jì)算出隧道的方向向量,從而獲取線的角度,在這個(gè)角度基礎(chǔ)上±90°,得到隧道垂直方向,方向+距離即可計(jì)算出目標(biāo)點(diǎn)的世界坐標(biāo)。利用不同距離得到多個(gè)點(diǎn)坐標(biāo),再給各個(gè)點(diǎn)設(shè)置高度,即可得到所有的隧道截面世界坐標(biāo)。向量與角度的計(jì)算可以參考這篇文章:Cesium計(jì)算向量、角度、距離
關(guān)鍵代碼:
this.getPointByDirectionAndLen = function (position, angle, len) {
let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position);
let mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(angle));
let rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
Cesium.Matrix4.multiply(matrix, rotationZ, matrix);
let result;
result = Cesium.Matrix4.multiplyByPoint(
matrix,
new Cesium.Cartesian3(0, len, 0),
new Cesium.Cartesian3()
);
return result;
};
2.4、獲取開挖點(diǎn)(藍(lán)色點(diǎn))
經(jīng)過上面的步驟,我們已經(jīng)得到隧道截面坐標(biāo)(下圖中C坐標(biāo))、隧道線向量(AB)。根據(jù)公式:D坐標(biāo)-C坐標(biāo) = 向量AB
可以得到D坐標(biāo)
得到C、D坐標(biāo)后,使用通視分析(sightline)得到觀察點(diǎn)C到目標(biāo)點(diǎn)D,之間與地形的障礙點(diǎn);依次對(duì)每個(gè)截面坐標(biāo)做以上操作,即可得到所有障礙點(diǎn)
關(guān)鍵代碼:
this.getBarrierArray = function (LonLatArr,sightline) {
let pointA = new Cesium.Cartesian3.fromDegrees(posArray[0].x,posArray[0].y,posArray[0].z);
let pointB = new Cesium.Cartesian3.fromDegrees(posArray[1].x,posArray[1].y,posArray[1].z);
let index = 0;
//向量AB
const positionvector = Cesium.Cartesian3.subtract(pointB, pointA, new Cesium.Cartesian3());
myfun(index);
let BarrierArray = [];
function myfun(index){
if(index < LonLatArr.length){
let cart = new Cesium.Cartesian3.fromDegrees(LonLatArr[index][0], LonLatArr[index][1], LonLatArr[index][2]);
let posD = {
x: cart.x + positionvector.x,
y: cart.y + positionvector.y,
z: cart.z + positionvector.z
};
let thisArray = [];
thisArray.push(cart);
thisArray.push(posD);
var name = "point" + index;
sightline.viewPosition = Cartesian2toDegrees(thisArray[0]);
sightline.addTargetPoint({
position: Cartesian2toDegrees(thisArray[1]),
name: name
});
setTimeout(()=>{
let barrp = sightline.getBarrierPoint(name);
console.log(barrp);
if(!barrp.isViewer){
BarrierArray.push(barrp.position.longitude * (180/Math.PI));
BarrierArray.push(barrp.position.latitude * (180/Math.PI));
BarrierArray.push(barrp.position.height);
}
sightline.removeAllTargetPoint();
},30);
index++;
setTimeout(()=>{
myfun(index)
},40)
}
}
function Cartesian2toDegrees(position) {
var cartographic = Cesium.Cartographic.fromCartesian(position);
var longitude = Cesium.Math.toDegrees(cartographic.longitude);
var latitude = Cesium.Math.toDegrees(cartographic.latitude);
var height = cartographic.height;
return [longitude, latitude, height];
}
return BarrierArray
};
2.5、地形開挖
得到所有障礙點(diǎn)后,通過這些點(diǎn)進(jìn)行地形開挖文章來源:http://www.zghlxwxcb.cn/news/detail-427221.html
viewer.scene.globe.addExcavationRegion({
name: 'ggg',
position: brruipos,
height: dep,
transparent: false
});
范例:
鏈接:https://pan.baidu.com/s/1sDwfmI6hBFIS3eCt7tBGug
提取碼:6655文章來源地址http://www.zghlxwxcb.cn/news/detail-427221.html
到了這里,關(guān)于SuperMap iClient3D for Cesium 構(gòu)建隧道的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!