File size: 4,232 Bytes
9f59d45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import gradio as gr
import ifcopenshell
import pandas as pd
from tempfile import NamedTemporaryFile
import os

def extract_properties(ifc_file_path, element_class):
    try:
        model = ifcopenshell.open(ifc_file_path)

        results = []
        elements = model.by_type("IfcElement")
        # Get unique type names
        element_types = sorted(list(set(elem.is_a() for elem in elements)))
        classes_to_check = [element_class] if element_class != "" else sorted(list(set(obj.is_a() for obj in element_types)))

        for class_name in classes_to_check:
            elements = model.by_type(class_name)
            for element in elements:
                # Get all properties
                properties = {}
                for definition in element.IsDefinedBy:
                    if definition.is_a("IfcRelDefinesByProperties"):
                        prop_set = definition.RelatingPropertyDefinition
                        if prop_set.is_a("IfcPropertySet"):
                            for prop in prop_set.HasProperties:
                                properties[f"{prop_set.Name}.{prop.Name}"] = prop.NominalValue.wrappedValue if prop.NominalValue else None

                row = {
                    "GlobalId": element.GlobalId,
                    "Type": element.is_a(),
                    "Name": element.Name,
                    **properties
                }
                results.append(row)

        if not results:
            return pd.DataFrame({"Message": [f"No {element_class if element_class != '' else ''} elements found"]}), None, None

        df = pd.DataFrame(results)
        # Create temporary files for downloads
        with NamedTemporaryFile(delete=False, suffix='.csv') as tmp_csv:
            df.to_csv(tmp_csv.name, index=False)
            csv_path = tmp_csv.name

        with NamedTemporaryFile(delete=False, suffix='.xlsx') as tmp_excel:
            df.to_excel(tmp_excel.name, index=False)
            excel_path = tmp_excel.name

        return df, csv_path, excel_path

    except Exception as e:
        return pd.DataFrame({"Error": [f"Processing failed: {str(e)}"]}), None, None

def extract_ifc_types(ifc_file):
    """Extract all IFC types from uploaded file"""
    if not ifc_file:
        return []
    try:
        ifc = ifcopenshell.open(ifc_file.name)
        # Get all elements that are IfcElement or its subtypes
        elements = ifc.by_type("IfcElement")
        # Get unique type names
        element_types = sorted(list(set(elem.is_a() for elem in elements)))
        return element_types
    except:
        return []

def update_dropdown(ifc_file):
    """Update dropdown options when file is uploaded"""
    choices = extract_ifc_types(ifc_file)
    return gr.Dropdown(choices=choices, value="", interactive=True)

# Gradio Interface
with gr.Blocks(title="IFC Property Extractor") as demo:
    gr.Markdown("## 🛠️ IFC Property Extractor")

    with gr.Row():
        ifc_input = gr.File(
            label="1. Upload IFC File",
            file_types=[".ifc"],
            type="filepath"
        )

    with gr.Row():
        with gr.Column():
            class_filter = gr.Dropdown(
                [""],
                value="",
                label="2. Filter by Class",
                interactive=False
            )
            extract_btn = gr.Button("Extract Properties", variant="primary")

        with gr.Column():
            csv_download = gr.File(label="Download CSV", visible=False)
            excel_download = gr.File(label="Download Excel", visible=False)

    output_table = gr.Dataframe(
        label="Extracted Properties",
        interactive=True,
        wrap=False,
    )

    # Update dropdown when file is uploaded
    ifc_input.change(
        fn=update_dropdown,
        inputs=ifc_input,
        outputs=[class_filter]
    )

    extract_btn.click(
        fn=extract_properties,
        inputs=[ifc_input, class_filter],
        outputs=[output_table, csv_download, excel_download]
    )

    # Show download buttons only when files are available
    extract_btn.click(
        lambda: [gr.File(visible=True), gr.File(visible=True)],
        outputs=[csv_download, excel_download]
    )

demo.launch()