原创做者:flowell,转载请标明出处:http://www.javashuo.com/article/p-zercrwgn-r.htmlhtml
IFC是建筑信息模型(BIM)数据开放的国际标准,在建筑行业或设施管理行业的各个参与者使用的软件应用程序之间做为中间媒介交换和共享。该标准涵盖建筑物生命周期所需数据的定义和管理流程,对建筑信息进行有组织的高效管理。node
对于本文而言,IFC更重要的特性之一即是IFC做为一种平台中立的开放文件格式规范,不受单个供应商或供应商组的控制。它是一种基于对象的文件格式,具备由特殊组织BuildingSMART(之前称为国际互操做性联盟,IAI)开发的数据模型,以促进组织架构,工程和构造(AEC)行业中的互操做性,而且是建筑信息中经常使用的协做格式。基于建筑建模(BIM)的项目。这意味着IFC模型规范是开放的而且是可重用的。研究IFC格式对于增强不一样行业的建模或是不一样建模软件之间的交流都有极为重要的意义。设计模式
例如,因为丹麦政府专一于软件平台之间的互操做性,所以丹麦政府已将IFC格式强制用于公共辅助建筑项目。此外,芬兰国有设施管理公司Senate Properties要求在全部项目中使用IFC兼容软件和BIM。[3]挪威政府,卫生和国防客户组织也要求在全部项目中使用IFC BIM,以及许多市政当局,私人客户,承包商和设计师在其业务中整合了IFC BIM。IFC做为一种通用的建模信息交流中间媒介,在建筑建模和模型展现之间起到了承上启下的重要意义。数组
IFC能够以多种格式编码,每种格式都具备软件支持,可伸缩性和可读性的益处和权衡。这些格式表示数据如何以电子形式编码。因为建筑数据可能很是大(即千兆字节),所以格式的选择可能具备实际考虑因素。本文参考的IFC文件是基于Revit项目导出的IFC文件,具备.ifc拓展名的后缀,是IFC在实践中使用最普遍的格式,同时也是做为文本读取的格式中最紧凑的格式,而且还具备最大的兼容性和支持性。架构
IFC数据以对象实例为结点构成层次结构,其中全部可识别对象都派生自IfcRoot类。每一个对象都有一个128位数字(GUID)形式的GlobalID,它永远不会在整个生命周期中发生变化,一个用于人类识别的名称(Name)或将在施工计划中显示的名称,一个用于捕获杂项信息的描述(Description),以及一个可使用的全部者历史记录(Tag)。指示对象的建立和最后修改的对象,时间和方式,以及指示锁定状态和合并状态(建立,修改,删除或无更改)的版本控制属性。IFC中的实体(Entity)涵盖了建筑生命流程中所必需的绝大部分元素,包括IfcActor,表示承包商或建筑物占用者等我的或组织。IfcControl表示指令,例如工单,许可,工做计划或投标提交。IfcGroup表示相关产品的集合,例如机械系统。IfcProduct表示在空间中构件的实例,例如物理产品或建筑物中的房间。IfcProcess指示当时发生的事情,例如任务或事件。IfcResource表示使用材料,人工或设备等可用性有限的东西。IfcRelationShip表示对象是如何组织起来的,如汇集,包含,链接,依赖等概念上或空间上的组织关系。由于本文关注的是BIM三维模型在转换处理过程当中的数据流向,因此本文将重点关注于IFC中的物理实体(IfcProduct)和关系实体(IfcRelationShip)。经过遍历单个IFC文件中的关系层次树,咱们将依次抵达一个个链接在一块儿的物理实体,经过输出物理实体的模型信息和属性信息,同时输出物理实体间的组织关系,咱们将能够经过IFC重构原有的建筑模型信息。工具
IFC Schema规定的700多个类里,继承自IfcElement的类和建筑行业的具体构建对应,好比继承自IfcSpatialElement的类和建筑中的空间部件对应。在咱们要处理的IFC文件中,主要关注属于物理实体类型的继承自IfcElement的类和继承自IfcSpatialElement的类,此类均属于建筑场景中的建筑构件或空间构建,咱们将其称之为IFC物理实体。例如,IfcWall的实例就是建筑空间中的一堵墙,IfcSpace实例表明一个建筑空间。在提取IFC文件时,咱们重点关注IFC物理实体。特别的,继承自IfcElement的物理实体都有对应的Type表示该实体拥有的属性,材质信息,几何展现等相关信息,在提取IFC文件时也要一并关注这些信息。动画
图1 IFC物理实体的继承树ui
IFC遵循面向对象的设计模式,除了IFC物理实体以外,IFC还定义了IFC关系实体来表达物理实体或其余实体之间的关联,依赖,聚合,组合,包含等关系。IFC关系实体一般以“IfcRel”前缀开头,它对应的实例为IFC关系实例。编码
图2 IFC关系实体的继承树设计
例如,IfcRelAggregates是IfcRelComposes的子类,用以表达聚合关系,一般是一对多。经过解析IfcRelAggregates实例的链接上级的RelatingObject和链接下级的RelatedObject属性能够获取在聚合关系两端的实体,空间实例一般以聚合关系链接起来。而IfcRelContainedInSpatialStructure这个关系实体是咱们要重点关注的,它表明了建筑的包含关系,用以将一个建筑元素(物理实体)分配给空间上的某个部件,以链接物理实体中IfcSpatialElement和IfcElement,。而且任何元素只能分配给某个级别的空间结构惟一一次,使得元素只能被包含于单个空间结构中。相似的关系实体还有表示引用关系的IfcRelReferencedInSpatialStructure,可是引用关系没必要是一对一的,它能够引用零个,一个或者多个。
图3 IFC关系实体的应用
如图3所示,图中的场景实例包含了表明建筑空间的三个IfcBuilding实例,以及两个IfcBuildingSteroy实例和表明建筑关系的两个IfcAggregates实例,表明包含关系的两个IfcRelContainedInSpatialStructure实例。而做为建筑元素之一的两个IfcWall实例和IfcStair实例经过建筑关系被包含于建筑空间中。由此可知,IFC标准经过IFC的关系实例将模型组织成井井有理的空间层次关系,全部的建筑信息和构建信息都能有被有效地组织和管理,所以IFC标准为BIM模型的信息描述和信息交换都提供了坚实的保障。而由此也能够提出,基于构件之间的包含和汇集关系,本文若是立足于IFC的根节点,按照关系层次一层一层地去遍历IFC节点树,是能够作到将IFC的每个构件生成在同一棵节点树内,从而实现IFC文件中全部构件按层次地导出。IFC标准中对构件之间的关系的定义,将是本文模型提取的理论前提。
GLTF(GL TransmissionFormat)即图形语言交换格式,它是一种3D内容的格式标准,由Khronos Group管理(Khronos Group还管理着OpenGL系列、OpenCL等重要的行业标准)。GLTF用于应用之间的模型高效传输和加载3D场景和模型。GLTF最大限度地减小了3D模型的大小,以及解压缩和使用模型所需的运行时处理,同时以最大的限度保障模型信息的完整度。GLTF为三维内容工具和服务定义了一种可扩展的通用发布格式,可简化创做的工做流程并实现整个行业内容的可互操做使用。GLTF一直致力于成为三维图形界的JPEG,可见它在信息传输和存储中所包含的强大特性和无穷的发展力。
GLTF格式将易于解析的JSON场景描述与一个或多个几何的表示,与动画和其余丰富数据的二进制文件相结合。数据以二进制的方式存储,即它能够直接加载到GPU缓冲区中而无需额外的解析或其余操做。同时结构信息又以JSON格式组织,即保证了可读性又保证了解析的快速性。使用这种方法,GLTF可以在具备Node,Mesh,Camera,Material和Animation的完整分层展现场景,同时实现高效传输和快速加载。
图4 GLTF实体间的组织关系
GLTF按照Scene-Node-Mesh-Accessor-BufferView-Buffer由高到低的层次关系来组织三维模型信息。
Scene:GLTF包括场景定义数据,使用一棵场景树来组织定义场景。Scene中的节点包含Transform矩阵(也就是位置、旋转、缩放)以及场景节点父子关系的描述,以及该场景包含的功能(mesh、camera等);一般意义上的Scene是一种经常使用的场景对象组织方式。咱们把场景中的对象,按照必定的规则(一般是空间关系)组织成一棵树,树上的每一个节点表明场景中的一个对象。每一个节点均可以有零到多个子节点,但只有一个父节点。 每一个节点都包含多个对“空间的定义”的属性,如Transform属性,经过一个 4x4 的矩阵表示,也能够经过位置、旋转、缩放三个份量来表示,它表明该场景相对世界坐标系的转换。如Nodes属性,则表明该场景中的子节点,根据Node的索引指向同一个GLTF文件中的Node数组中的某个或多个Node。
Node:Node是场景中的节点,被Scene包含或指向,一般对应于模型中的一个建筑构件。若是Scene表明一个建筑场景,如一个房子及房子周边的场地,那么Node的细度就是这个房子里的一把椅子,一张桌子,一扇门,甚至这件房子在总体上也能够当作是一个Nod。Node能够主要包含的属性有Children,定义了该节点所包含的子节点。Mesh属性则是该节点所包含的模型信息,具体地说能够包含顶点,法向量,材质,纹理等信息。延续刚才的例子来说,若是房子是一个Node,那么它的Children属性应该指向房子里的构件好比椅子,桌子等。而这些椅子,桌子自己也是Node,它被房子的Node指向,同时也能够指向更细层次的子节点,如椅子的椅子腿,椅子的靠背等。一般高层次的Node都不包含Mesh属性,最深层次的Node节点,也就是叶节点,会包含Mesh属性,它指向同一个GLTF文件中的Mesh数组中的某个Mesh,它包含了刻画该节点的模型的信息。
Mesh:Mesh在GLTF中表明要渲染的三维空间中的物体的模型信息。具体表明三维空间中表示物体的造型。GLTF按照目前图形学中最经常使用的方法边界表示法,即用一组多边形或者曲面来定义物体的边界,并用以区分了空间中哪些部分是物体的内部和物体的外部。构造一个物体边界的一组多边形就被称为Mesh。在GLTF中,Mesh主要包含Primitives属性和Index属性。Primitives属性包含物体边界的顶点信息和法向量信息,它存储对应Accessor索引,以找到对应的信息。Index则是关于边界曲面的拓扑顺序,具体的顺序以Primitives中的Mode属性定义,能够定义的顺序包括:POINTS,LINES,TRIANGLES,TRIANGLES_STRIP,TRIANGLES_FAN。
Accessor:Accessor是BufferView中数据的访问器,一个BufferView能够同时存储多组同类数据,所以须要用不一样的访问器以得到不一样的数据。经过Accessor对BufferView的数据进行划分,以得到不一样的访问效果。
BufferView:BufferView能够比做数据视图,一个BufferView一般会对应一种数据,如浮点数,整数。这些数据从BufferView的角度来看是单纯的数组。
Buffer:Buffer是存储数据的数组,在这里,数据以二进制形式存储,经过Base64的编码形式编码。
如咱们在上一章讨论的,IFC是建筑行业的标准,包含了不少的非几何信息,而咱们导出的GLTF只包含几何信息,所以在转换时应关注几何信息。
IFC中全部的对象都组织在同一棵树中,这颗树的根是一个IfcProject对象,存储该模型的元信息。由根出发,IFC对象尤为是建筑构件由聚合关系或者包含等关系按照空间上的关系汇集在这棵树上,所以在装载成GLTF时也要注意保存这种组织顺序。在对象树中的IFC建筑构件,都拥有它对应的图元信息,这些图元信息将被咱们提取,转换成GLTF对象,一个建筑构件在IFC中是一个IfcProduct的子类(如IfcElement),而在GLTF中是一个Node结点。IfcProduct的成员中包含它的图元信息的连接,经过连接找到它对应的图元信息,对应的是多个IfcShape对象,而在GLTF中则是多个Mesh,一个IfcShape对应一个Mesh。所以,一个IfcProduct拥有多个IfcShape,在GLTF中则是一个Node的children属性指向多个Mesh(实际上是指向Node,可是这些node是叶子节点,只包含一个Mesh),在现实世界中,对应的概念则如一个椅子(IfcProduct)拥有多个构件,如凳腿,靠背,座板等。
在处理的时候,以递归的方式访问IFC对象树,而后对于每个访问的对象,建立一个Node节点,而且找到该对象对应的Shape,建立Mesh节点。下图中以队列的方式实现对IFC对象树的递归访问。