簡體   English   中英

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

[英]Extracting quantities of elements with IfcOpenShell in python

我正在嘗試使用IfcOpenShell中的 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()放置哪種類型的 function,我都會收到錯誤消息:

 File "C:\Python27\lib\site-packages\ifcopenshell\entity_instance.py", line 48, in __getattr__ "entity instance of type '%s' has no attribute '%s'" % (self.wrapped_data.is_a(), name)) AttributeError: entity instance of type 'IfcSlab' has no attribute 'IfcPhysicalQuantity'

不確定如何解決這個問題,希望得到幫助。

編輯:

獲得平板和進一步參考的進一步工作:

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

這段代碼中的 output 仍然是:

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

這意味着我可以訪問IfcElementQuantity但所有屬性都不起作用。 我查看了架構參考,但找不到正確的參考。

在實現這一點時,您應該注意您的導入庫適用於哪個版本的 IFC - IfcOpenShell-Website 分發的版本適用於 IFC2X3。 對於 IFC4,您可能需要自己編譯一個版本。 (您可以使用ifcopenshell.schema_identifier檢查您的 IFC 版本)

即使我在談論 IFC2X3,我也會鏈接到 buildingSMART IFC 4 定義。 與 IFC2X3 的差異在 buildingSMART 網頁上以紅色標記。 並且 IFC4 定義更易於閱讀(IMO)。

數量不像屬性那樣直接附加。 它們被寫成屬性集,然后與元素或元素類型相關聯。 所以首先你應該確保你的 IFC 文件包含數量 - 否則你將找不到任何數量。 通常你從一個特定的產品開始 - ifc_file.by_type('IfcSlab') 您可以通過反向屬性訪問屬性集 - 這些通常由 IFC 庫設置,它們不會直接作為屬性出現在文件中。

我拿了你的示例文件並將其縮短到大約三分之一(所以它仍然是一個有效的 IFC2X3 文件):

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;

這是一塊帶有面積測量值的平板。 它應該有一個反向屬性IsDefinedBy 在 IFC2X3 中,它指向實體IfcRelDefinesByPropertiesIfcRelDefinesByType的列表。 使用 IFC4 IfcRelDefinesByType 將放入反向屬性IsTypedBy

每個 IfcRelDefinesByProperties 指向在其屬性RelatingPropertyDefinition設置的屬性。 有多種屬性集類型,在搜索物理量時您希望它屬於IfcElementQuantity類型。 在迭代屬性關系列表時,您必須在運行時檢查您當前持有的類型。

數量集在屬性Quantities附加了一個IfcPhysicalQuantities列表。 這些可以是簡單量,也可以是由多個簡單量組成的復雜量。 對於簡單數量,面積、計數或重量有特定的子類型。 同樣,您必須在運行時檢查具體類型。

面積量本身有一個名稱和描述以提供進一步的上下文(不是我們的,但可能在現實世界中)。 value 屬性以數量類型命名,因此 IfcQuantityArea 具有屬性AreaValue 同樣感興趣的是屬性Unit ,它是對值單位的引用。 如果未設置(如在我們的示例中),您將需要在 IfcProject 實體中查找分配的單位。

不幸的是,這可能還不是全部。 如果對象(這里是我們的 IfcSlab)具有指定的對象類型,則該類型也可以附加屬性集(我將示例文件修改為這種情況)。 你的類型實體沒有反向屬性,而是一個直接的, HasProperties 如果設置了,您可以通過它發現附加屬性。

總而言之,您可能需要多個循環:

  1. 對於每個對象,獲取屬性集
  2. 對於每個屬性集,測試它是否是數量集
  3. 對於每個數量集,通過數量

如果對象具有用戶定義的類型,則可能重復此搜索。

以下代碼應該完全做到這一點(在我的機器上用 python 3.5.4 和 ifcopenshell 用 IFC2X3 架構編寫)):

  1. 從文件中獲取所有slab(只有一個)
  2. 遍歷反向屬性IsDefinedBy中的所有實體 - 這些實體可以是IfcRelDefinesByPropertiesIFcRelDefinesByType
  3. 從實體獲取屬性集
  4. 檢查給定的屬性集是否為IfcElementQuantity ,如果是,則繼續打印數量。
import ifcopenshell
def print_quantities(property_definition):
  if 'IfcElementQuantity' == property_definition.is_a():
    for quantity in property_definition.Quantities:
      if 'IfcQuantityArea' == quantity.is_a():
        print('Area value: ' + str(quantity.AreaValue))
      if 'IfcQuantityVolume' == quantity.is_a():
        print('Volume value: ' + str(quantity.VolumeValue))
      if 'IfcQuantityLength' == quantity.is_a():
        print('Length value: ' + str(quantity.LengthValue))

ifc_file = ifcopenshell.open('slab.ifc')
products = ifc_file.by_type('IfcSlab')
for product in products:
  if product.IsDefinedBy:
    definitions = product.IsDefinedBy
    for definition in definitions:
      #In IFC2X3 this could be property or type
      #in IFC4 type is in inverse attribute IsTypedBy
      if 'IfcRelDefinesByProperties' == definition.is_a():
        property_definition = definition.RelatingPropertyDefinition
        print_quantities(property_definition)
      if 'IfcRelDefinesByType' == definition.is_a():
        type = definition.RelatingType
        if type.HasPropertySets:
          for property_definition in type.HasPropertySets:
            print_quantities(property_definition)

例如,這導致:

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

IFC 中的數量存儲在數量集中,其結構與屬性集非常相似。 IfcOpenShell 提供實用函數以與模式無關的方式提取此數據:

for slab in ifc_file.by_type("IfcSlab"):
    quantities = ifcopenshell.util.element.get_psets(slab, qtos_only=True)
    print(quantities) # A dictionary of qtos and quantities
    # For example print(quantities["Qto_SlabBaseQuantities"]["GrossVolume"])

我曾經寫了幾個函數來提取所有屬性。

https://github.com/johannesmichael/ifc-python/blob/master/modules/ifc_pset_utils.py

可能不完整,但可以給你一個想法。 我提取所有優秀的進一步分析。

基本數量:

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 

這是為 IFC 2x3 TC1 完成的 希望有幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM