📌

IFCのAttribute、PropertySet、Materialを一式書き出す

2024/01/21に公開

IfcOpenShellのIfcCSVでは、Attributeしか書き出せないので、PropertySetやMaterialなども一式書き出すには別手法を取る必要がある。
プログラムでは、Excelで書き出せるので、Power BI等のデータ可視化ツールに取り込むことも出来る。
ifc_file_pathに格納される値を好きなIFCファイル名に変更すれば動く。

data extraction
import ifcopenshell
import pandas as pd
import os

# エンティティ同士の親子構造を取得する
def get_hierarchy(ifc_file, entity, level=0):
    hierarchy.append((level, entity))
    if entity.is_a('IfcObjectDefinition'):
        for rel in entity.IsDecomposedBy:
            for related_object in rel.RelatedObjects:
                get_hierarchy(ifc_file, related_object, level + 1)
    if entity.is_a('IfcSpatialStructureElement'):
        for rel in entity.ContainsElements:
            for related_object in rel.RelatedElements:
                get_hierarchy(ifc_file, related_object, level + 1)

ifc_file_path = 'sample_ishou.ifc'

# IFCファイルを開く
ifc_file = ifcopenshell.open(ifc_file_path)

# Excelファイル名を生成(IFCファイル名 + "output")
base_name = os.path.splitext(os.path.basename(ifc_file_path))[0]
excel_file_name = f"{base_name}_output.xlsx"

# データと階層を格納するリストを初期化
hierarchy = []
attributes_data = []
properties_data = []
materials_data = []

# 階層を取得
for project in ifc_file.by_type('IfcProject'):
    get_hierarchy(ifc_file, project)

# 階層に従ってデータを抽出
for level, entity in hierarchy:
    # エンティティの属性を取得
    for attribute in entity.get_info():
        attributes_data.append([level, entity.is_a(), attribute, entity.get_info()[attribute]])

    # プロパティセットを取得
    for definition in entity.IsDefinedBy:
        if definition.is_a('IfcRelDefinesByProperties'):
            property_set = definition.RelatingPropertyDefinition
            if property_set.is_a('IfcPropertySet'):
                for property in property_set.HasProperties:
                    if property.is_a('IfcPropertySingleValue'):
                        value = property.NominalValue.wrappedValue if property.NominalValue else None
                        properties_data.append([level, entity.is_a(), property_set.Name, property.Name, value])

    # 材料情報を取得
    if entity.HasAssociations:
        for association in entity.HasAssociations:
            if association.is_a('IfcRelAssociatesMaterial'):
                material = association.RelatingMaterial
                material_name = material.Name if material.is_a('IfcMaterial') else 'Complex Material'
                materials_data.append([level, entity.is_a(), material_name])

# データをDataFrameに変換
attributes_df = pd.DataFrame(attributes_data, columns=["Level", "Entity", "Attribute", "Value"])
properties_df = pd.DataFrame(properties_data, columns=["Level", "Entity", "PropertySet", "Property", "Value"])
materials_df = pd.DataFrame(materials_data, columns=["Level", "Entity", "Material"])

# Excelファイルに書き出し
with pd.ExcelWriter(excel_file_name, engine='openpyxl') as writer:
    attributes_df.to_excel(writer, sheet_name='Attribute', index=False)
    properties_df.to_excel(writer, sheet_name='Property', index=False)
    materials_df.to_excel(writer, sheet_name='Material', index=False)

Discussion