i3s 一种开源的三维地理数据规范 简单解读
i3s,esri主推到ogc的一种三维开源GIS数据标准。
版权声明:原创。博客园/B站/小专栏/知乎/CSDN @秋意正寒
转载请标注原地址并声明转载: https://www.cnblogs.com/onsummer/p/12082584.html
1. i3s及其实现
i3s是一种用树结构来组织大体积量三维数据的数据格式标准,比如在位图界的jpg格式一样,只不过i3s是“标准”,具体实现的文件格式另有一说。
i3s采用json文件来描述数据,采用二进制文件(格式为.bin)来存储三维地理数据。
i3s是OGC规范,目前OGC版本是1.0,但是在Esri维护的社区项目中,i3s已经演进到1.7了。可以说是“一般”与“特殊”的区别。
OGC标准一旦制定就不应该频繁更改,但是社区维护版本可以根据实际生产需要,基于OGC标准做结构优化等。
i3s标准将三维地理数据切分,用“节点”的概念组织起来,然后这些节点被有序地写在“节点页”中。说白了就是树形结构。
i3s将三维地理数据组织起来后,可以放在服务器上通过REST接口访问。
i3s目前由slpk格式的文件实现。
附:i3s对三维地理数据的分类
- 3d模型——传统3d建模的精模转换数据
- 表面模型——倾斜摄影数据
- 三维点
- 三维点云
- 建筑——BIM数据
为什么不用bim文件、为什么不用现有的三维数据格式呢?
首先,商业软件的三维数据格式并不开源,而i3s格式是开源的,只要熟读标准可以自己编程创建(难度比较大就是了)。
其次,开源的三维数据格式不具备地理信息。
最后,bim数据不面向地理信息系统。
所以,在三维GIS萌芽的今天(指这个年代),一种开源的三维地理数据规范就显得十分重要。
1.1. i3s标准的数据组织和结构
在前文提到i3s使用的是树结构组织数据,同时支持规则四叉树或者R树组织。每个树节点代表的地理数据的范围,由外包围球(mbs)或外包围(obb)盒表示。
官方推荐使用外包围盒表示范围(和二维的外包矩形,类似),点云数据仅支持外包围盒。
1.1.1. 节点和节点页
一份三维地理数据应该合理的切分,i3s使用树结构切分,以适应大量数据的快速分发、显示。
切分的结果就是“节点(Node)”,组织这些节点的结构叫做“节点页(NodePage)”。
在1.6及早期版本中,节点信息是写在一个叫3DNodeIndexDocument.json.gz文件中的,即3DNodeIndexDocument文档,节点一多,遍历小文件频率增加,对IO性能有不小的影响。
所以在1.7版本中,将这个3DNodeIndexDocument文档聚合到“节点页”中去了,类似于索引的功能(i3s的i就是index嘛)。
官方给出的树状结构示意图。
1.1.2. 节点构成
节点由两个部分构成:要素和节点资源。
即 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目录。
1.2. i3s中的统计数据
统计数据用来定义符号,这样可以避免读取所有的数据。比如,你要用唯一值进行制图,那就可以从统计信息里获取唯一值,而不是遍历一次节点的属性数据进行统计。
当然,统计数据还可以用来做空间过滤。
1.3. 坐标系和高程
i3s使用WKT来指定坐标系统。使用WKT1或者WKT2均可。
全局i3s数据仅支持WGS84坐标系和中国国家2000坐标系,注意是仅支持地理坐标系,x和y代表十进制的经度、纬度。
局部小场景支持任意坐标系统。若WKID不是4326或者4490,那就被视作局部小场景i3s数据。
1.5版本添加了对高程坐标系的支持。
=====================================================
上面是i3s的普遍定义,如果对i3s还是很模糊,请阅读下文的i3s实现——slpk文件。
2. slpk
根据第一节内容,我们得知slpk是i3s规范的一种实现。
slpk是一种压缩方法为“存储”的zip格式文件,后缀名是slpk(SceneLayer Package)。slpk内的json文件、二进制文件均使用gzip压缩。
表示纹理材质的png、jpg文件不压缩。
根据第一节的内容,可以知道i3s有五种类型的切分,普通3d模型、点云、建筑等,所以slpk也有5种,虽然都是slpk文件,但是其内部组织不尽一样。
就好像都是jpg文件,像素的颜色深度也可以不尽一样。不同i3s版本的slpk对这些类型的支持是不同的:
- 1.7支持3d模型、表面模型、建筑场景
- 1.6支持3d模型、表面模型、建筑场景、点
- 2.0仅支持点云
2.1. slpk的生产
slpk主要由ArcGIS Pro来制作,在工具箱搜索slpk就能找到很多打包3d图层为slpk的工具。
Bentley的ContextCapture、Skyline的PhotoMesh也支持slpk。
存储在geodatabase中的多面体三维数据可以打包为slpk,属于3d模型的slpk。
ArcGIS Pro 2.5支持直接把rvt文件拖拽到3d图层上进行显示,并且直接打包为slpk。
2.2. slpk的读取
slpk可以直接由ArcGIS Pro及上文提及的软件读取,也可以由ArcGIS Earth读取(Earth支持的i3s版本可能不太高)。
当然,slpk也可以由ArcGIS Portal代为托管存储并解包发布成场景服务,供ArcGIS jsAPI使用。
ArcGIS RuntimeSDK、CityEngine、Drone2Map for ArcGIS都支持slpk读取,CityEngine还支持生产。
2.3. slpk有什么用
slpk只有一个文件,通常我们说简单就是美,slpk单文件方便传递。
目前,slpk用于ArcGIS Portal发布场景服务是比较方便的,也可以用于runtime sdk开发的轻量软件或者ArcGIS Earth来读取查看。可惜Earth 1.9支持的i3s版本并不是很高,期待2.0。
3. slpk的文件结构
以3d模型和建筑模型的slpk为例,混杂1.6和1.7版本的来讲。
3.1. i3s 1.7版本的3d模型slpk
这是一个1.7版本的3d模型类型slpk的结构,用zip打开就是四个文件夹和一个3dSceneLayer.json.gz文件,以及一个hash文件。
- 3dSceneLayer.json.gz描述的是整个slpk的信息
- nodePages目录存放“节点页”信息,节点页用json文件来记录
- nodes目录存放“节点”信息,每个节点用文件夹表示,文件夹名称即节点名
- statistics目录存放的是统计数据,每个要素一个文件夹,文件夹名即要素名,文件夹下是该要素的统计数据,用json文件来记录
根目录下还可能会有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,甚至二进制要素属性数据。
3.2. i3s 1.6版本 建筑slpk
BIM数据是有多个分层的(楼板、机电、门窗、外立面等),每个分层用子图层(sublayers)表示。
每一个sublayers相当于一个独立的3d模型slpk:
此例为1.6的slpk,所以没有nodepages目录,在每个节点上,描述节点的文件仍旧是3dNodeIndexDocument.json。
这是一个BIM文件打包成slpk后的树状结构(发布成场景服务,以URL访问的形式)。因为没有nodepages,所以在1.6版本中,节点文件夹的名称会出现”0-1-1″的表示,即0节点下的1节点下的1节点。
4. slpk中的主要json的类定义
①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,这个以后再谈(其实是笔者没有整理好)。
5. 同类标准3dtiles/gltf与s3m
既然说到标准,就不得不提一下同类竞争对手。
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文件描述数据,都使用二进制文件存储数据。
6. 三维标准博客展望
未来,笔者还要更精细地研读i3s,尽快学习3dtiles和gltf标准,简单了解s3m标准。
不仅仅要在文档、类结构上熟悉,还要尽可能地利用这些开源标准来获取这些数据。