При реализации этого вы должны позаботиться о том, с какой версией IFC работает ваша библиотека импорта - версия, распространяемая веб-сайтом IfcOpenShell, работает с IFC2X3. Для IFC4 вам, вероятно, потребуется скомпилировать версию самостоятельно. (вы можете проверить свою версию IFC с помощью ifcopenshell.schema_identifier
)
Я размещаю ссылки на определение BuildingSMART IFC 4, даже если я говорю об IFC2X3. Отличия от 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 это указывает на список объектов IfcRelDefinesByProperties и IfcRelDefinesByType. В IFC4 IfcRelDefinesByType будет помещен в обратный атрибут IsTypedBy
.
Каждый IfcRelDefinesByProperties указывает на набор свойств в их атрибуте RelatingPropertyDefinition
. Существуют различные типы наборов свойств, вы хотите, чтобы они были типа IfcElementQuantity при поиске физических величин. Вам нужно будет проверить во время выполнения, какой тип вы в настоящее время имеете при повторении списка отношений свойств.
Набор количества содержит список IfcPhysicalQuantities. прикреплен в атрибуте Quantities
. Это могут быть простые величины или сложные величины, состоящие из нескольких простых величин. Для простых величин существуют специальные подтипы для площади, количества или веса. Опять же, вам придется проверять конкретный тип во время выполнения.
Сама величина площади имеет имя и описание для дополнительного контекста (не нашего, но, возможно, реального мира). Атрибут значения назван в честь типа количества, поэтому IfcQuantityArea имеет атрибут AreaValue
. Также представляет интерес атрибут Unit
, который является ссылкой на единицу измерения значения. Если он не установлен (как в нашем примере), вам нужно будет искать назначенные единицы в объекте IfcProject.
К сожалению, это может быть не все. Если объект (здесь наш IfcSlab) имеет назначенный тип объекта, этот тип также может иметь прикрепленные наборы свойств (я изменил пример файла для этого случая). Сущность вашего типа имеет не обратный атрибут, а прямой, HasProperties
. Если он установлен, через него можно обнаружить прикрепленные свойства.
Подводя итог, вам, вероятно, понадобится несколько циклов:
- Для каждого объекта получить наборы свойств
- Для каждого набора свойств проверьте, является ли он набором количества
- Для каждого набора количества просмотрите количество
И потенциально повторить этот поиск, если объект имеет тип, определенный пользователем.
Следующий код должен делать именно это (написан на моей машине с python 3.5.4 и ifcopenshell со схемой IFC2X3)):
- Получить все slabs из файла (есть только один)
- Пройдитесь по всем сущностям в обратном атрибуте
IsDefinedBy
— это могут быть IfcRelDefinesByProperties
или IFcRelDefinesByType
.
- Получить наборы свойств от сущности
- Проверьте, является ли заданный набор свойств
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
person
Loebl
schedule
24.05.2018