在python中使用IfcOpenShell提取元素数量

在python中使用IfcOpenShell提取元素数量,python,ifc,Python,Ifc,我正在尝试使用Python中的IfcOpenShell读取ifc文件中对象的最深层数量。到目前为止,我已经: import ifcopenshell path = r'D:\ifcos_1\slab.ifc' ifc_file = ifcopenshell.open(path) geometries = ifc_file.by_type("IfcProduct") for geometry in geometries: if geometry.is_a("IfcSlab"):

我正在尝试使用Python中的
IfcOpenShell
读取
ifc
文件中对象的最深层数量。到目前为止,我已经:

import ifcopenshell

path = r'D:\ifcos_1\slab.ifc'
ifc_file = ifcopenshell.open(path)

geometries = ifc_file.by_type("IfcProduct")

for geometry in geometries:
    if geometry.is_a("IfcSlab"):
        print geometry
        test = geometry.IfcPhysicalQuantity()
        print test
我研究过这个问题

无论我尝试为
test=geometry.X()
放置哪种类型的函数,我都会得到一个错误:

不知道如何解决这个问题,希望得到帮助

编辑:

获得板和进一步参考的进一步工作:

for geometry in geometries:
    if geometry.is_a("IfcSlab"):
        print geometry
        definedBy = geometry.IsDefinedBy

        print definedBy[0]

        for each in definedBy:
            test = each.is_a()
            print test
到目前为止,障碍是与IFC4的兼容性,我将尝试使用来自的指令重新编译它

编辑2:

进一步的工作目前使用IFC 2x3标准,使用一个包含数量信息的文件(通过原始数据验证)。以下是相关代码:

for geometry in geometries:
    if geometry.is_a("IfcSlab"):
        definedBy = geometry.IsDefinedBy

        for line in definedBy:
        test = line.is_a()
        # print test
        if line.is_a() == 'IfcRelDefinesByProperties' or line.is_a() == 'IfcRelDefinesByType':
            step1 = line.RelatingPropertyDefinition
            step2 = step1.is_a()
            print step2
无论我在
step1=line之后放置什么,都会出现错误。
,以下任何一项都不会给出结果:

line.IfcPropertySet
line.IfcElementQuantity
line.RelatingPropertyDefiniton
然而,该代码的输出为:

IfcPropertySet
IfcPropertySet
IfcPropertySet
IfcPropertySet
IfcPropertySet
IfcPropertySet
IfcPropertySet
IfcPropertySet
IfcPropertySet
IfcPropertySet
IfcElementQuantity
IfcElementQuantity

这意味着我可以访问
IfcElementQuantity
,但所有属性都不起作用。我已经看过了,但找不到正确的版本。

在实现此功能时,您应该注意导入库使用的IFC版本-由IfcOpenShell网站发布的版本与IFC2X3一起使用。对于IFC4,您可能需要自己编译一个版本。(您可以使用ifcopenshell.schema\u标识符检查IFC版本)

我正在建立buildingSMART IFC 4定义的链接,即使我在谈论IFC2X3。与IFC2X3的差异在buildingSMART网页上以红色标记。IFC4的定义更易于阅读(IMO)

数量不像属性那样直接附加。它们作为属性集写入,然后与元素或元素类型相关。因此,首先应确保IFC文件包含数量,否则将找不到任何数量。通常从特定的产品开始--
ifc\u文件。按类型('IfcSlab')
。可以通过反向属性访问特性集-这些属性通常由IFC库设置,它们不会直接作为属性显示在文件中

我将示例文件缩短到大约三分之一(因此它仍然是一个有效的IFC2X3文件):

这是附着了面积测量的楼板。它应该有一个反向属性
IsDefinedBy
。在IFC2X3中,这指向一个实体和属性的列表。使用IFC4时,IfcRelDefinesByType将被放入反向属性
IsTypedBy

每个IFCreldFinesByProperty都指向其属性
RelatingPropertyDefinition
中的属性集。有多种特性集类型,在搜索物理量时,您希望它的类型为。在迭代属性关系列表时,必须在运行时检查当前持有的类型

数量集在属性
数量中附加了一个数量列表。这些可以是简单量或复杂量,它们由多个简单量组成。对于简单数量,有面积、计数或重量的特定子类型。同样,您必须在运行时检查具体类型

面积数量本身有一个名称和描述,以提供进一步的上下文(不是我们的,但可能在现实世界中)。value属性以数量类型命名,因此IfcQuantityArea有一个属性
AreaValue
。同样令人感兴趣的是属性
Unit
,它是对值的单位的引用。如果未设置(如我们的示例中所示),则需要在IfcProject实体中查找指定的单位

不幸的是,这可能不是全部。如果对象(这里是我们的IfcSlab)具有指定的对象类型,则该类型还可以附加属性集(我将示例文件修改为这种情况)。您的类型实体没有反向属性,而是直接属性,
HasProperties
。如果已设置,则可以通过它发现附加的属性

总之,您可能需要多个循环:

  • 对于每个对象,获取属性集
  • 对于每个特性集,测试它是否为数量集
  • 对于每个数量集,检查数量
  • 如果对象具有用户定义的类型,则可能重复此搜索

    下面的代码应该正好做到这一点(使用python 3.5.4在我的机器上编写,使用IFC2X3模式在ifcopenshell上编写):

  • 从文件中获取所有板(只有一个)
  • 检查反向属性中的所有实体
    是由
    定义的-这些实体可以是
    ifcreldefinesbyproperty
    ifcreldefinesbype
  • 从实体获取属性集
  • 检查给定的属性集是否为
    IfcElementQuantity
    ,如果为,则继续打印数量
  • 导入ifcopenshell
    def打印数量(属性定义):
    如果“IfcElementQuantity”==属性\u定义。是\u a():
    对于属性_definition.Quantities中的数量:
    如果“IfcQuantityArea”==数量,则为a()
    打印('面积值:'+str(数量.面积值))
    如果“IfcQuantityVolume”==数量,则为a()
    打印('体积值:'+str(数量.体积值))
    如果“IfcQuantityLength”==数量,则为a()
    打印('长度值:'+str(数量.长度值))
    ifc_file=ifcopenshell.open('slab.ifc')
    products=ifc\u文件。按类型('IfcSlab')
    对于产品中的产品:
    如果product.IsDefinedBy:
    定义=product.IsDefinedBy
    对于定义中的定义:
    #在IFC2X3中,这可能是属性或类型
    #在IFC4中,类型处于反向属性IsTypedBy中
    如果“IfcRelDefinesByProperties”==definition.is_a():
    property_definition=definition.RelatingPropertyDefinition
    打印数量(属性定义)
    如果“IfcRelDefinesByType”==definition.is_a():
    type=definition.RelatingType
    如果type.HasPropertySets:
    对于type.HasPropertySets中的属性定义:
    
    IfcPropertySet
    IfcPropertySet
    IfcPropertySet
    IfcPropertySet
    IfcPropertySet
    IfcPropertySet
    IfcPropertySet
    IfcPropertySet
    IfcPropertySet
    IfcPropertySet
    IfcElementQuantity
    IfcElementQuantity
    
    ISO-10303-21;
    HEADER;FILE_DESCRIPTION(('ViewDefinition [Custom, QuantityTakeOffAddOnView, SpaceBoundary2ndLevelAddOnView]','Option [Drawing Scale: 100.000000]','Option [Global Unique Identifiers (GUID): Keep existing]','Option [Elements to export: Visible elements (on all stories)]','Option [Partial Structure Display: Entire Model]','Option [IFC Domain: All]','Option [Structural Function: All Elements]','Option [Convert Grid elements: On]','Option [Convert IFC Annotations and ARCHICAD 2D elements: Off]','Option [Convert 2D symbols of Doors and Windows: Off]','Option [Explode Composite and Complex Profile elements into parts: On]','Option [Export geometries that Participates in Collision Detection only: Off]','Option [Elements in Solid Element Operations: Extruded/revolved]','Option [Elements with junctions: Extruded/revolved without junctions]','Option [Slabs with slanted edge(s): Extruded]','Option [Use legacy geometric methods as in Coordination View 1.0: Off]','Option [IFC Site Geometry: As boundary representation (BRep)]','Option [IFC Site Location: At Project Origin]','Option [Curtain Wall export mode: Container Element]','Option [Railing export mode: Single Element]','Option [Stair export mode: Container Element]','Option [Properties To Export: All properties]','Option [Space containment: On]','Option [IFC Domain For Space Containment: All]','Option [Bounding Box: Off]','Option [Geometry to type objects: Off]','Option [Element Properties: All]','Option [Property Type Element Parameter: On]','Option [Quantity Type Element Parameter: On]','Option [IFC Base Quantities: On]','Option [Window Door Lining and Panel Parameters: On]','Option [IFC Space boundaries: On]','Option [ARCHICAD Zone Categories as IFC Space classification data: On]','Option [Element Classifications: On]'),'2;1');
    FILE_NAME('D:\\Side Projects\\Paragraph3\\The database\\IFC Files\\Local tests\\ifcos_1\\slab.ifc','2018-06-13T18:28:40',('Architect'),('Building Designer Office'),'The EXPRESS Data Manager Version 5.02.0100.09 : 26 Sep 2013','IFC file generated by GRAPHISOFT ARCHICAD-64 21.0.0 INT FULL Windows version (IFC2x3 add-on version: 3005 INT FULL).','The authorising person');
    FILE_SCHEMA(('IFC2X3'));
    ENDSEC;
    DATA;
    #1= IFCPERSON($,'Undefined',$,$,$,$,$,$);
    #7= IFCPERSONANDORGANIZATION(#1,#10,$);
    #10= IFCORGANIZATION('GS','GRAPHISOFT','GRAPHISOFT',$,$);
    #11= IFCAPPLICATION(#10,'21.0.0','ARCHICAD-64','IFC2x3 add-on version: 3005 INT FULL');
    #12= IFCOWNERHISTORY(#7,#11,$,.ADDED.,$,$,$,1528907320);
    #13= IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.);
    #14= IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
    #16= IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
    #17= IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.0174532925199),#16);
    #18= IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
    #19= IFCCONVERSIONBASEDUNIT(#18,.PLANEANGLEUNIT.,'DEGREE',#17);
    #29= IFCUNITASSIGNMENT((#13,#14,#19));
    #31= IFCDIRECTION((1.,0.,0.));
    #35= IFCDIRECTION((0.,0.,1.));
    #37= IFCCARTESIANPOINT((0.,0.,0.));
    #39= IFCAXIS2PLACEMENT3D(#37,#35,#31);
    #40= IFCDIRECTION((0.,1.));
    #42= IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.00000000000E-5,#39,#40);
    #45= IFCPROJECT('344O7vICcwH8qAEnwJDjSU',#12,'Project',$,$,$,$,(#42),#29);
    #59= IFCLOCALPLACEMENT($,#39);
    #62= IFCSITE('20FpTZCqJy2vhVJYtjuIce',#12,'Site',$,$,#59,$,$,.ELEMENT.,(47,33,34,948800),(19,3,17,204400),0.,$,$);
    #68= IFCRELAGGREGATES('0Du7$nzQXCktKlPUTLFSAT',#12,$,$,#45,(#62));
    #74= IFCQUANTITYLENGTH('GrossPerimeter',$,$,0.);
    #76= IFCQUANTITYAREA('GrossArea',$,$,0.);
    #77= IFCELEMENTQUANTITY('2GNZepdf73fvGc$0W6rozj',#12,'BaseQuantities',$,'ARCHICAD BIM Base Quantities',(#74,#76));
    #82= IFCRELDEFINESBYPROPERTIES('2Hm9JvZjohDNSD2kdxZI3b',#12,$,$,(#62),#77);
    #93= IFCLOCALPLACEMENT(#59,#39);
    #95= IFCBUILDING('00tMo7QcxqWdIGvc4sMN2A',#12,'Building',$,$,#93,$,$,.ELEMENT.,$,$,$);
    #97= IFCRELAGGREGATES('2b_h_mYcGArd6glJG2Fmbt',#12,$,$,#62,(#95));
    #101= IFCQUANTITYAREA('GrossFloorArea',$,$,0.);
    #102= IFCELEMENTQUANTITY('1kQMlmT0rD35a9E43iKTas',#12,'BaseQuantities',$,'ARCHICAD BIM Base Quantities',(#101));
    #104= IFCRELDEFINESBYPROPERTIES('0L87OdSD3DqSTjSRlAciZL',#12,$,$,(#95),#102);
    #115= IFCLOCALPLACEMENT(#93,#39);
    #117= IFCBUILDINGSTOREY('1oZ0wPs_PE8ANCPg3bIs4j',#12,'Ground Floor',$,$,#115,$,$,.ELEMENT.,0.);
    #119= IFCRELAGGREGATES('118jwqMnuwK1xuf97w7fU5',#12,$,$,#95,(#117));
    #180= IFCSLAB('3W29Drc$H6CxK3FGIxjJNl',#12,'SLA - 001',$,$,$,$,'E0089375-9BF4-4633-B503-3D04BBB535EF',.FLOOR.);
    #195= IFCRELCONTAINEDINSPATIALSTRUCTURE('04ldtj6cp2dME6CiP80Bzh',#12,$,$,(#180),#117);
    #326= IFCPROPERTYSINGLEVALUE('Fragility rating',$,IFCLABEL('0'),$);
    #327= IFCPROPERTYSINGLEVALUE('Tile dimensions',$,IFCLABEL('Undefined'),$);
    #328= IFCPROPERTYSINGLEVALUE('Anti-static Surface',$,IFCBOOLEAN(.F.),$);
    #329= IFCPROPERTYSINGLEVALUE('Non-skid Surface',$,IFCBOOLEAN(.F.),$);
    #330= IFCPROPERTYSET('0LYX8AqOOS9ft8M4aJYEYa',#12,'FLOORINGS',$,(#326,#327,#328,#329));
    #332= IFCRELDEFINESBYPROPERTIES('1G6WWCSQGg0PdTnW7hwMrM',#12,$,$,(#180),#330);
    #335= IFCPROPERTYSINGLEVALUE('Renovation Status',$,IFCLABEL('Existing'),$);
    #336= IFCPROPERTYSET('0cR6wsk2QWcLKPchA8mF3u',#12,'AC_Pset_RenovationAndPhasing',$,(#335));
    #338= IFCRELDEFINESBYPROPERTIES('3nYD8KGPhoBw5okmj1JjsA',#12,$,$,(#180),#336);
    #341= IFCQUANTITYLENGTH('Width',$,$,300.);
    #342= IFCQUANTITYLENGTH('Perimeter',$,$,22000.);
    #343= IFCQUANTITYAREA('GrossArea',$,$,28.);
    #344= IFCQUANTITYAREA('NetArea',$,$,28.);
    #345= IFCQUANTITYVOLUME('GrossVolume',$,$,8.4);
    #346= IFCQUANTITYVOLUME('NetVolume',$,$,8.4);
    #347= IFCELEMENTQUANTITY('1RfXJewSc7OCIaD$L2ZoXT',#12,'BaseQuantities',$,'ARCHICAD BIM Base Quantities',(#341,#342,#343,#344,#345,#346));
    #349= IFCRELDEFINESBYPROPERTIES('085uLttAQRllG3nL_YikZ8',#12,$,$,(#180),#347);
    #375= IFCQUANTITYVOLUME('Gross Volume of the Slab',$,$,8.4);
    #376= IFCQUANTITYVOLUME('Gross Volume of the Slab with Holes',$,$,8.4);
    #377= IFCQUANTITYLENGTH('Holes Perimeter',$,$,0.);
    #378= IFCQUANTITYAREA('Holes Surface Area',$,$,0.);
    #379= IFCQUANTITYLENGTH('Perimeter',$,$,22000.);
    #381= IFCQUANTITYAREA('Top Surface Area',$,$,28.);
    #382= IFCELEMENTQUANTITY('0DuZ12CVtssgcIQPaQ$1sp',#12,'ArchiCADQuantities',$,'ARCHICAD BIM Quantities',(#375,#376,#377,#378,#379,#381));
    #384= IFCRELDEFINESBYPROPERTIES('0KgGv0Y8Fc2jg8BCPhxnM5',#12,$,$,(#180),#382);
    #393= IFCSLABTYPE('0K1otpnkQcEpOBXPxnZ3dB',#12,'Timber - Floor 300',$,$,(#396),$,'14072DF3-C6E6-A63B-360B-859EF18C39CB',$,.FLOOR.);
    #395= IFCRELDEFINESBYTYPE('353egCMRpZtJd$CDCoSsCb',#12,$,$,(#180),#393);
    #352= IFCQUANTITYAREA('Area',$,$,28.);
    #353= IFCQUANTITYLENGTH('Height',$,$,300.);
    #354= IFCQUANTITYVOLUME('Net Volume',$,$,8.4);
    #396= IFCELEMENTQUANTITY('1Zyxf4r7NogSp4V7ORMpET',#12,'ArchiCADQuantities',$,'ARCHICAD BIM Quantities',(#352,#353,#354));
    ENDSEC;
    END-ISO-10303-21;
    
    Length value: 300.0
    Length value: 22000.0
    Area value: 28.0
    Area value: 28.0
    Volume value: 8.4
    Volume value: 8.4
    Volume value: 8.4
    Volume value: 8.4
    Length value: 0.0
    Area value: 0.0
    Length value: 22000.0
    Area value: 28.0
    Area value: 28.0
    Length value: 300.0
    Volume value: 8.4
    
    def get_related_quantities(ifc_instance):
    """
    Returns a list of IfcElementQuantity for given IFC ID
    argument: ifc_instance
    return: list of property sets
    """
    quantities_list =[]
    for x in ifc_instance.IsDefinedBy:
        if x.is_a("IfcRelDefinesByProperties"):
            if x.RelatingPropertyDefinition.is_a("IfcElementQuantity"):
                quantities_list.append(x.RelatingPropertyDefinition)
    return quantities_list  
    
    def get_quantity_single_value(x):
    """
    Returns a dict of dicts of IfcElementQuantity single values.
    Returning a dictionary of dictionaries
    is used, because it is easy to transform to pandas.DataFrame 
    argument: IFC Element as contained in list from get_related_property_sets()
    return: dict of property single values like {"IfcName":"xx", "IfcGlobalId": "klkhlkh", ......}
    """
    quantities_dicts = {}
    for y in x.Quantities:
        if y.is_a('IfcQuantityArea'):
            quantities_dicts.update({y.Name:y.AreaValue})
        if y.is_a('IfcQuantityLength'):
            quantities_dicts.update({y.Name:y.LengthValue})
        if y.is_a('IfcQuantityVolume'):
            quantities_dicts.update({y.Name:y.VolumeValue})
        if y.is_a('IfcQuantityCount'):
            quantities_dicts.update({y.Name:y.CountValue})
        if y.is_a('IfcQuantityWeight'):
            quantities_dicts.update({y.Name:y.WeightValue})
    
    return quantities_dicts