2023-01-04 最近想用Cesium給學校做一個類似智慧校園的東西,要做的東西很多,首先是獲取學校模型的問題,然後怎麼用Cesium載入3Dtile 1.獲取學校模型 想到之前被老師抓苦力去做春熙路的圖,於是決定用比較熟悉的OSM數據集 https://www.openstreetmap.or ...
2023-01-04
最近想用Cesium給學校做一個類似智慧校園的東西,要做的東西很多,首先是獲取學校模型的問題,然後怎麼用Cesium載入3Dtile
1.獲取學校模型
想到之前被老師抓苦力去做春熙路的圖,於是決定用比較熟悉的OSM數據集
https://www.openstreetmap.org/ 需要梯子
進入後很容易就可以下載到所需區域的矢量數據
後續選擇用ArcMap處理數據,但下載的OSM需要一個插件才能用ArcMap打開
https://github.com/Esri/arcgis-osm-editor
選擇對應版本就可以了
在ArcMap里清洗並加上高度屬性就可以了,大概是這個樣子
如何變成3dtile格式呢,搜索了一下發現用CesiumLab最方便
下載過後會在瀏覽器打開一個視窗
如果要將shp文件轉換為3dtile,裡面有文檔跟著操作就可以了,上圖那種數據量一秒就轉換好了
2.Cesium載入3dtile
我是在vue里用的cesium,直接將剛纔生成的3dtile放在static下
載入3dtile代碼如下:
var tileset = new Cesium.Cesium3DTileset({ url: "../../../static/3DModel/sicauOSM/tileset.json", }); viewer.scene.primitives.add(tileset); console.log(tileset);
因為生成模型時候的問題,導致模型在地底下去了,調整模型位置代碼如下:
//3dtile載入完成後執行 tileset.readyPromise.then(function(tileset) { //高度偏差,向上是正數,向下是負數 var heightOffset = 500.0; //計算tileset的綁定範圍 var boundingSphere = tileset.boundingSphere; //計算中心點位置 /** * fromCartesian 方法是用經緯度和高度定義一個位置 * A position defined by longitude, latitude, and height. */ var cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center); //計算中心點位置的地表坐標 /** * Cartesian3 是一個3D點 * fromRadians 方法 Returns a Cartesian3 position from longitude and latitude values given in radians(弧度). * @param longitude * @param latitude * @param height * 因為建築模型沒他所在高度信息,所以填0 */ var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0); //偏移後的坐標,也就是中心點本應在的高度(海拔) var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset); /** * subtract 方法 Computes the componentwise difference of two Cartesians. * 計算兩個笛卡爾坐標的成分差異 * @param 就是兩個要計算的坐標 * @param 第三個參數是要保存的結果 */ var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3()); console.log(`translation長這樣: ${translation}`); // (-102.97917011496611, 417.3715669941157, 255.33559404686093) //tileset.modelMatrix轉換 /** * Creates a Matrix4 instance from a Cartesian3 representing the translation. * @param {Cartesian3} translation - The upper right portion of the matrix representing the translation. * @param { Matrix4} result - The object in which the result will be stored, if undefined a new instance will be created. * Cesium中使用Matrix4作為處理線性變換和位移變換的仿射矩陣 * 三維空間的轉換矩陣通常是3x3的就可以 * 但是為了同時滿足位移的需要增加了一個維度使用4x4的矩陣 */ console.log(`變化前的tileset.modelMatrix為: ${tileset.modelMatrix}`); // (1, 0, 0, 0) // (0, 1, 0, 0) // (0, 0, 1, 0) // (0, 0, 0, 1) tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation); console.log(`變化後的tileset.modelMatrix為: ${tileset.modelMatrix}`); // (1, 0, 0, -102.97917011496611) // (0, 1, 0, 417.3715669941157) // (0, 0, 1, 255.33559404686093) // (0, 0, 0, 1) /** * 定位到3dtiles的位置,也就是讓攝像頭對準這個區域 * viewBoundingSphere 方法 * Sets the camera so that the current view contains the provided bounding sphere. * @param boundingSphere - The bounding sphere to view, in world coordinates. * @param offset - The offset from the target in the local east-north-up reference frame centered at the target. */ viewer.camera.viewBoundingSphere(tileset.boundingSphere, new Cesium.HeadingPitchRange(0, -20, 0)); });
註意區分橢球坐標、笛卡爾坐標、屏幕坐標