i3s,esri主推到ogc的一種三維開源GIS數據標準。html
版權聲明:原創。博客園/B站/小專欄/知乎/CSDN @秋意正寒node
轉載請標註原地址並聲明轉載: http://www.javashuo.com/article/p-dpnxyqcp-co.htmlpython
i3s是一種用樹結構來組織大致積量三維數據的數據格式標準,好比在位圖界的jpg格式同樣,只不過i3s是「標準」,具體實現的文件格式另有一說。git
i3s採用json文件來描述數據,採用二進制文件(格式爲.bin)來存儲三維地理數據。github
i3s是OGC規範,目前OGC版本是1.0,可是在Esri維護的社區項目中,i3s已經演進到1.7了。能夠說是「通常」與「特殊」的區別。編程
OGC標準一旦制定就不該該頻繁更改,可是社區維護版本能夠根據實際生產須要,基於OGC標準作結構優化等。json
i3s標準將三維地理數據切分,用「節點」的概念組織起來,而後這些節點被有序地寫在「節點頁」中。說白了就是樹形結構。api
i3s將三維地理數據組織起來後,能夠放在服務器上經過REST接口訪問。數組
i3s目前由slpk格式的文件實現。服務器
爲何不用bim文件、爲何不用現有的三維數據格式呢?
首先,商業軟件的三維數據格式並不開源,而i3s格式是開源的,只要熟讀標準能夠本身編程建立(難度比較大就是了)。
其次,開源的三維數據格式不具有地理信息。
最後,bim數據不面向地理信息系統。
因此,在三維GIS萌芽的今天(指這個年代),一種開源的三維地理數據規範就顯得十分重要。
在前文提到i3s使用的是樹結構組織數據,同時支持規則四叉樹或者R樹組織。每一個樹節點表明的地理數據的範圍,由外包圍球(mbs)或外包圍(obb)盒表示。
官方推薦使用外包圍盒表示範圍(和二維的外包矩形,相似),點雲數據僅支持外包圍盒。
一份三維地理數據應該合理的切分,i3s使用樹結構切分,以適應大量數據的快速分發、顯示。
切分的結果就是「節點(Node)」,組織這些節點的結構叫作「節點頁(NodePage)」。
在1.6及早期版本中,節點信息是寫在一個叫3DNodeIndexDocument.json.gz文件中的,即3DNodeIndexDocument文檔,節點一多,遍歷小文件頻率增長,對IO性能有不小的影響。
因此在1.7版本中,將這個3DNodeIndexDocument文檔聚合到「節點頁」中去了,相似於索引的功能(i3s的i就是index嘛)。
官方給出的樹狀結構示意圖。
節點由兩個部分構成:要素和節點資源。
即 Node = Feature + NodeResources
要素的概念和二維上的要素是同樣的,都表示一個地理實體,好比一棟建築。
節點資源,包括要素的幾何數據、屬性數據(這兩個數據見個人博客《聊聊GIS數據的四個分層》),以及三維數據中的材質紋理信息。
即 NodeResources = Geometry + Attributes + Textures
注意:並非全部的節點都包括這三大資源的。3d模型類型的地理數據和建築數據均包括這三大資源。
① Geometry
幾何數據在不一樣版本的i3s(社區版本)有不一樣的表達。在1.7版本中,3d模型和表面模型幾何數據用draco壓縮格式的二進制文件存儲。
在構造三角面時,順序爲逆時針方向(這點我不太清楚,圖形學的朋友能夠深刻一下)。
全部幾何頂點的座標均相對於1.1中說起的obb或者mbs的中心的。obb或者mbs的中心若爲零點原點,則還須要加上頂點偏移,使其偏移到正確的座標系上,這個偏移量在json文件中是有的。
應指定座標軸的正方向,默認是x-東,y-北,z-高程。
② Attribute
同一個要素的幾何數據和屬性數據分別存在兩個不一樣的二進制文件中。屬性數據的順序和幾何數據的順序同樣。
③ Texture
紋理就是指紋理圖像文件,被存儲爲二進制文件。
=============
爲了確保與1.6版本的兼容性,1.7的i3s標準還須要包括3dNodeIndexDocument.json描述文件,以及可用於任何節點的sharedResources目錄。
統計數據用來定義符號,這樣能夠避免讀取全部的數據。好比,你要用惟一值進行製圖,那就能夠從統計信息裏獲取惟一值,而不是遍歷一次節點的屬性數據進行統計。
固然,統計數據還能夠用來作空間過濾。
i3s使用WKT來指定座標系統。使用WKT1或者WKT2都可。
全局i3s數據僅支持WGS84座標系和中國國家2000座標系,注意是僅支持地理座標系,x和y表明十進制的經度、緯度。
局部小場景支持任意座標系統。若WKID不是4326或者4490,那就被視做局部小場景i3s數據。
1.5版本添加了對高程座標系的支持。
=====================================================
上面是i3s的廣泛定義,若是對i3s仍是很模糊,請閱讀下文的i3s實現——slpk文件。
根據第一節內容,咱們得知slpk是i3s規範的一種實現。
slpk是一種壓縮方法爲「存儲」的zip格式文件,後綴名是slpk(SceneLayer Package)。slpk內的json文件、二進制文件均使用gzip壓縮。
表示紋理材質的png、jpg文件不壓縮。
根據第一節的內容,能夠知道i3s有五種類型的切分,普通3d模型、點雲、建築等,因此slpk也有5種,雖然都是slpk文件,可是其內部組織不盡同樣。
就好像都是jpg文件,像素的顏色深度也能夠不盡同樣。不一樣i3s版本的slpk對這些類型的支持是不一樣的:
slpk主要由ArcGIS Pro來製做,在工具箱搜索slpk就能找到不少打包3d圖層爲slpk的工具。
Bentley的ContextCapture、Skyline的PhotoMesh也支持slpk。
存儲在geodatabase中的多面體三維數據能夠打包爲slpk,屬於3d模型的slpk。
ArcGIS Pro 2.5支持直接把rvt文件拖拽到3d圖層上進行顯示,而且直接打包爲slpk。
slpk能夠直接由ArcGIS Pro及上文說起的軟件讀取,也能夠由ArcGIS Earth讀取(Earth支持的i3s版本可能不過高)。
固然,slpk也能夠由ArcGIS Portal代爲託管存儲並解包發佈成場景服務,供ArcGIS jsAPI使用。
ArcGIS RuntimeSDK、CityEngine、Drone2Map for ArcGIS都支持slpk讀取,CityEngine還支持生產。
slpk只有一個文件,一般咱們說簡單就是美,slpk單文件方便傳遞。
目前,slpk用於ArcGIS Portal發佈場景服務是比較方便的,也能夠用於runtime sdk開發的輕量軟件或者ArcGIS Earth來讀取查看。惋惜Earth 1.9支持的i3s版本並非很高,期待2.0。
以3d模型和建築模型的slpk爲例,混雜1.6和1.7版本的來說。
這是一個1.7版本的3d模型類型slpk的結構,用zip打開就是四個文件夾和一個3dSceneLayer.json.gz文件,以及一個hash文件。
根目錄下還可能會有metadata.json文件,以下圖所示:
nodes目錄下有一個特殊的節點,即根節點root。1.7版本的i3s爲了保證與1.6的兼容,保留了shared目錄和3dNodeIndexDocument.json.gz文件(節點描述文件)。
那麼,如何查詢每一個json描述文件的各個屬性的定義呢?
官方github文檔中是有的:https://github.com/Esri/i3s-spec/tree/master/docs/1.7
以slpk根目錄下的3dSceneLayer.json爲例,這整個json文件的定義就寫在了這個文檔下:https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DSceneLayer.cmn.md
例如,spatialReference屬性就是座標系信息。可是若是是不太明白的屬性,例如store屬性:
咱們仍是去上面說的github官方文檔查詢store的文檔:https://github.com/Esri/i3s-spec/blob/master/docs/1.7/store.cmn.md
json文件很容易經過官方文檔+明文閱讀的方式瞭解每一個屬性的含義,若是是二進制文件,那就須要費一番功夫了。
以幾何數據二進制文件(0.bin)爲例,二進制幾何文件的文檔在這裏:
https://github.com/Esri/i3s-spec/blob/master/docs/1.7/geometryBuffer.cmn.md
https://github.com/Esri/i3s-spec/blob/master/docs/1.7/vertexAttribute.cmn.md
這兩個文檔講得並非很詳細,在個人實踐中,已知用python或者js的ArrayBuffer進行讀取,1~4字節是頂點數量,5~8是要素數量。
而後每4*3個字節爲一組3個Float32數字(x,y,z),一共「頂點數量」組。
緊接着即是下一個幾何數據,多是法線、uv等,要看3dSceneLayer.json內的store屬性下的defaultGeometrySchema屬性下的order屬性值。
這個建議看ogc的標準文檔:http://docs.opengeospatial.org/cs/17-014r5/17-014r5#69.html
8.2節就是幾何數據二進制文件的格式,雖然也比較簡陋,不過比esri的文檔好一些。
這張圖虛線框大概表達的是「非必要屬性」。
筆者不才,在3dSceneLayer.json中找到的vertexAttributes屬性並沒出現offset的值(plus:在每一個節點目錄下的feature目錄下的json裏!),儘管vertexAttributes每一個屬性在二進制文件中的的偏移量都可本身用已知數字計算,可是終究沒有直接給值來的方便,也沒有能力將讀取到的position。
往後有機會,還會介紹如何用python或js來讀取二進制文件內的vertexAttributes,甚至二進制要素屬性數據。
BIM數據是有多個分層的(樓板、機電、門窗、外立面等),每一個分層用子圖層(sublayers)表示。
每個sublayers至關於一個獨立的3d模型slpk:
此例爲1.6的slpk,因此沒有nodepages目錄,在每一個節點上,描述節點的文件仍舊是3dNodeIndexDocument.json。
這是一個BIM文件打包成slpk後的樹狀結構(發佈成場景服務,以URL訪問的形式)。由於沒有nodepages,因此在1.6版本中,節點文件夾的名稱會出現"0-1-1"的表示,即0節點下的1節點下的1節點。
①3dSceneLayerInfo.json.gz
位於slpk壓縮包內的根目錄,用於描述整個slpk的信息;能夠人爲繼續往這個json里加屬性,不影響已有屬性的查詢。
查詢文檔:https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DSceneLayer.cmn.md
②3dNodeIndexDocument.json.gz
位於slpk壓縮包內根目錄下nodes文件夾下的每一個頂點文件夾下,root節點也有,1.7爲了兼容1.6保留了這個文件,1.7改用nodepages來提升性能。
查詢文檔:https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md
③節點頁
slpk壓縮包根目錄下的nodepages下的*.json.gz(可能有多個)是節點頁信息,用來描述整個slpk節點樹形結構和每一個節點的大體信息。
查詢文檔(node的文檔,由於節點頁json就是節點json數組):https://github.com/Esri/i3s-spec/blob/master/docs/1.7/node.cmn.md
④統計數據
slpk壓縮包根目錄下的statistics目錄下的每一個字段文件夾(f_*)下的0.json.gz文件,用來描述這個字段的統計信息。
查詢文檔:https://github.com/Esri/i3s-spec/blob/master/docs/1.7/statsInfo.cmn.md
⑤要素數據
slpk壓縮包根目錄下的nodes文件夾下的每一個頂點文件夾下的features文件夾下的*.json.gz文件,描述的是要素的信息(要素包括幾何數據和屬性數據)。
查詢文檔:https://github.com/Esri/i3s-spec/blob/master/docs/1.7/featureData.cmn.md
⑥共享資源
1.7兼容1.6的json文檔,位於每一個頂點文件夾下的shared文件夾下,*.json.gz文件。
查詢文檔:https://github.com/Esri/i3s-spec/blob/master/docs/1.7/sharedResource.cmn.md
主要的json文件就是這麼多(以3d模型的slpk爲例,bim的slpk應該相似),二進制文件的讀寫主要一烤要素數據的json,這個之後再談(實際上是筆者沒有整理好)。
既然說到標準,就不得不提一下同類競爭對手。
cesium是一個作3dWebGIS的api,主推的標準是3dtiles/gltf,主要資料以下:
https://github.com/KhronosGroup/glTF
http://docs.opengeospatial.org/cs/18-053r2/18-053r2.html
https://github.com/AnalyticalGraphicsInc/3d-tiles
s3m是我國推進的三維地理數據標準,主要由超圖等公司建設設計,主要資料以下:
https://download.csdn.net/download/cRGBc/12082994
gltf/s3m/i3s/3dtiles我瞭解的很少,甚至不瞭解gltf和3dtiles的關係,可是它們的共同特色是:都使用樹結構描述一個三維數據(不必定是地理數據),都使用json文件描述數據,都使用二進制文件存儲數據。
將來,筆者還要更精細地研讀i3s,儘快學習3dtiles和gltf標準,簡單瞭解s3m標準。
不只僅要在文檔、類結構上熟悉,還要儘量地利用這些開源標準來獲取這些數據。