本節(jié)我們講一下Cesium中常用的測(cè)量工具和針對(duì)開(kāi)發(fā)人員使用的調(diào)試工具。
量測(cè)工具
量測(cè)工具可以說(shuō),不管是二維GIS還是三維GIS中都必須具備的功能枚驻,只不過(guò)是在空間上是否有貼地游盲、是否有高度上的距離差別之分。Cesium是三維GIS引擎甫何,所以距離量測(cè)支持直線距離、水平距離遇伞、垂直距離以及地表距離辙喂,面積量測(cè)支持水平面積、地表面積以及模型表面積等鸠珠。不管是哪種類型的距離測(cè)量還是面積測(cè)量巍耗,實(shí)現(xiàn)思路基本是一樣的,都是按照如下思路實(shí)現(xiàn)的渐排。
1)點(diǎn)擊按鈕開(kāi)始測(cè)量炬太,偵聽(tīng)鼠標(biāo)LEFT_CLICK事件,記錄坐標(biāo)驯耻,繪制節(jié)點(diǎn)和折線(多邊形)亲族;
2)偵聽(tīng)鼠標(biāo)移動(dòng)事件炒考,鼠標(biāo)點(diǎn)擊后即復(fù)制一個(gè)浮動(dòng)點(diǎn),在MOUSE_MOVE事件中不斷更新最后一個(gè)浮動(dòng)點(diǎn)霎迫,動(dòng)態(tài)更新折線(多邊形)繪制斋枢;
3)偵聽(tīng)鼠標(biāo)右擊事件,RIGHT_CLICK觸發(fā)時(shí)銷毀測(cè)量相關(guān)事件句柄(ScreenSpaceEventHandler)知给,刪除多余的浮動(dòng)點(diǎn)瓤帚;
4)折線(多邊形)的動(dòng)態(tài)繪制通過(guò)CallbackProperty屬性綁定positions屬性實(shí)現(xiàn)。
如下為實(shí)現(xiàn)距離量測(cè)部分核心代碼:
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
let ray = viewer.camera.getPickRay(movement.position);
cartesian = viewer.scene.globe.pick(ray, viewer.scene);
if (positions.length == 0) {
positions.push(cartesian.clone());
}
positions.push(cartesian);
//在三維場(chǎng)景中添加Label
var textDisance = distance + "米";
floatingPoint = viewer.entities.add({
name: "空間直線距離",
position: positions[positions.length - 1],
point: {
pixelSize: 5,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
},
label: {
text: textDisance,
font: "18px sans-serif",
fillColor: Cesium.Color.GOLD,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(20, -20),
},
});
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function (movement) {
let ray = viewer.camera.getPickRay(movement.endPosition);
cartesian = viewer.scene.globe.pick(ray, viewer.scene);
if (positions.length >= 2) {
if (!Cesium.defined(poly)) {
poly = new PolyLinePrimitive(positions);
} else {
positions.pop();
positions.push(cartesian);
}
distance = getSpaceDistance(positions);
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction(function (movement) {
handler.destroy(); //關(guān)閉事件句柄
positions.pop(); //最后一個(gè)點(diǎn)無(wú)效
// viewer.entities.remove(floatingPoint);
// tooltip.style.display = "none";
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
//空間兩點(diǎn)距離計(jì)算函數(shù)
function getSpaceDistance(positions) {
var distance = 0;
for (var i = 0; i < positions.length - 1; i++) {
var point1cartographic = Cesium.Cartographic.fromCartesian(
positions[i]
);
var point2cartographic = Cesium.Cartographic.fromCartesian(
positions[i + 1]
);
/**根據(jù)經(jīng)緯度計(jì)算出距離**/
var geodesic = new Cesium.EllipsoidGeodesic();
geodesic.setEndPoints(point1cartographic, point2cartographic);
var s = geodesic.surfaceDistance;
//返回兩點(diǎn)之間的距離
s = Math.sqrt(
Math.pow(s, 2) +
Math.pow(point2cartographic.height - point1cartographic.height, 2)
);
distance = distance + s;
}
return distance.toFixed(2);
}
如下為實(shí)現(xiàn)面積測(cè)量的部分核心代碼:
handler.setInputAction(function (movement) {
let ray = viewer.camera.getPickRay(movement.position);
cartesian = viewer.scene.globe.pick(ray, viewer.scene);
if (positions.length == 0) {
positions.push(cartesian.clone());
}
positions.push(cartesian);
//在三維場(chǎng)景中添加點(diǎn)
var cartographic = Cesium.Cartographic.fromCartesian(
positions[positions.length - 1]
);
var longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
var latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
var heightString = cartographic.height;
tempPoints.push({
lon: longitudeString,
lat: latitudeString,
hei: heightString,
});
floatingPoint = viewer.entities.add({
name: "多邊形面積",
position: positions[positions.length - 1],
point: {
pixelSize: 5,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
});
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function (movement) {
handler.destroy();
positions.pop();
var textArea = getArea(tempPoints) + "平方公里";
viewer.entities.add({
name: "多邊形面積",
position: positions[positions.length - 1],
label: {
text: textArea,
font: "18px sans-serif",
fillColor: Cesium.Color.GOLD,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(20, -40),
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
});
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
//計(jì)算多邊形面積
function getArea(points) {
var res = 0;
//拆分三角曲面
for (var i = 0; i < points.length - 2; i++) {
var j = (i + 1) % points.length;
var k = (i + 2) % points.length;
var totalAngle = Angle(points[i], points[j], points[k]);
var dis_temp1 = distance(positions[i], positions[j]);
var dis_temp2 = distance(positions[j], positions[k]);
res += dis_temp1 * dis_temp2 * Math.abs(Math.sin(totalAngle));
console.log(res);
}
return (res / 1000000.0).toFixed(4);
}
完整代碼請(qǐng)查看gitHub地址https://github.com/ls870061011/cesium_training/blob/main/examples/3_4_1measure.html涩赢,實(shí)現(xiàn)的示意圖如下所示缘滥。
調(diào)試面板
Cesium中比較常用的調(diào)試面板是用于了解Cesium渲染效果以及性能調(diào)優(yōu)的CesiumInspector和用于監(jiān)視3D Tiles數(shù)據(jù)的監(jiān)視器Cesium3DTilesInspector。
CesiumInspector
該控件是針對(duì)開(kāi)發(fā)人員來(lái)說(shuō)谒主,雖然不能提供功能的實(shí)現(xiàn)朝扼,但對(duì)于了解渲染效果和性能調(diào)優(yōu)是非常有幫助的,特別是解決一些渲染狀態(tài)下的問(wèn)題時(shí)非常的有價(jià)值霎肯。使用該控件非常的簡(jiǎn)單擎颖,只需如下一行代碼就能實(shí)現(xiàn)該控件的加載。
viewer.extend(Cesium.viewerCesiumInspectorMixin);
控件里面有很多的功能观游,每一個(gè)都很專業(yè)搂捧,包括渲染幀數(shù)、Primitive外包圍球懂缕、Primitive參考框架允跑、線框模式等等,這里就不一一給大家介紹了搪柑,感興趣的同學(xué)可以自己嘗試一下聋丝。
Cesium3DTilesInspector
面對(duì)大場(chǎng)景下的大規(guī)模、大體量的3D Tiles數(shù)據(jù)工碾,Cesium提供了一個(gè)監(jiān)視3D Tiles數(shù)據(jù)的監(jiān)視器弱睦,用于監(jiān)視、觀察3D Tiles數(shù)據(jù)的效果渊额。加載該空間也非常的簡(jiǎn)單况木,只需一行簡(jiǎn)單代碼即可,結(jié)果控件展示如下:
viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin);
包括3D Tiles瓦片是否可拾妊!火惊;顯示顏色、線框奔垦、瓦片邊界范圍框屹耐、瓦片內(nèi)容邊界范圍框、觀察者請(qǐng)求體宴倍、點(diǎn)云渲染等张症;還包括一些動(dòng)態(tài)屏幕誤差設(shè)置、最大屏幕誤差設(shè)置鸵贬、樣式修改等俗他。對(duì)3D Tiles不熟悉的可閱讀3D Tiles介紹及加載這篇文章。感興趣的同學(xué)阔逼,可以親自嘗試此控件兆衅,體驗(yàn)一下控件的強(qiáng)大。