如何用Python的IfcOpenShell提取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"): print geometry test = geometry.IfcPhysicalQuantity() print test
但不管怎么调整geometry.X()里的方法,都会报这个错误:
AttributeError: entity instance of type 'IfcSlab' has no attribute 'IfcPhysicalQuantity'
我查了IFC定义文档,还是没找到正确的调用方式。
第一次编辑:获取关联信息
后来我写了能获取楼板及关联信息的代码:
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兼容性问题,我打算参考相关论坛说明重新编译IfcOpenShell。
第二次编辑:转向IFC2x3后的困境
我换成了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
输出结果里能看到IfcElementQuantity:
IfcPropertySet
IfcPropertySet
...
IfcElementQuantity
IfcElementQuantity
但不管我在step1 = line.后加什么属性(比如line.IfcPropertySet、line.IfcElementQuantity、line.RelatingPropertyDefinition)都会报错,找不到正确的属性访问方式。
解决方案
问题核心是你对IFC数据结构的访问逻辑有误:IfcPhysicalQuantity并不是IfcSlab的直接属性,它嵌套在IfcElementQuantity中,而IfcElementQuantity又通过IfcRelDefinesByProperties关联到IfcSlab。下面是正确的遍历流程:
正确代码示例(针对IFC2x3)
import ifcopenshell path = r'D:\ifcos_1\slab.ifc' ifc_file = ifcopenshell.open(path) slabs = ifc_file.by_type("IfcSlab") for slab in slabs: print(f"楼板ID: {slab.GlobalId}") # 遍历所有关联的定义关系 for rel in slab.IsDefinedBy: if rel.is_a("IfcRelDefinesByProperties"): prop_def = rel.RelatingPropertyDefinition # 筛选出存储工程量的容器 if prop_def.is_a("IfcElementQuantity"): print("找到工程量集合:") # 遍历具体的工程量条目 for quantity in prop_def.Quantities: quantity_type = quantity.is_a() quantity_name = quantity.Name # 根据工程量类型获取对应数值 if quantity_type == "IfcVolumeQuantity": value = quantity.VolumeValue print(f"- {quantity_name}: {value} 立方米") elif quantity_type == "IfcAreaQuantity": value = quantity.AreaValue print(f"- {quantity_name}: {value} 平方米") elif quantity_type == "IfcLengthQuantity": value = quantity.LengthValue print(f"- {quantity_name}: {value} 米") # 其他工程量类型可以按需扩展
关键知识点
- 不要直接调用类名作为属性:比如
geometry.IfcPhysicalQuantity()是错误的,IFC实体的属性都是成员变量(驼峰式或小写开头),不是类方法调用。 - 关系对象的筛选:
IsDefinedBy返回的关系可能有多种类型,要先筛选IfcRelDefinesByProperties,再通过它的RelatingPropertyDefinition拿到属性集合。 - 区分属性集合类型:
RelatingPropertyDefinition可能是IfcPropertySet(普通属性)或IfcElementQuantity(工程量),需要先判断类型再处理。 - 工程量的差异化获取:不同的
IfcPhysicalQuantity子类有不同的数值属性,比如体积用VolumeValue、面积用AreaValue,要根据类型匹配。
内容的提问来源于stack exchange,提问作者Yafim Simanovsky

