File size: 5,305 Bytes
51982d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
"""Gradio UI for running wall compliance checks on uploaded IFC files."""

import argparse
import sys
from pathlib import Path

import gradio as gr


ROOT_DIR = Path(__file__).resolve().parent.parent
WALLS_DIR = ROOT_DIR / "walls_check"
if str(WALLS_DIR) not in sys.path:
    sys.path.insert(0, str(WALLS_DIR))

from Walls import run_wall_checks
import rules


def analyze_ifc_walls(
    ifc_file,
    min_mm,
    min_height_mm,
    min_service_height_mm,
    use_space_aware_height,
    max_u,
    climate_zone,
    include_summary,
):
    if ifc_file is None:
        return "", "Please upload an IFC file first."

    ifc_path = ifc_file if isinstance(ifc_file, str) else ifc_file.name
    normalized_zone = None if climate_zone == "Custom (use max U-value)" else climate_zone

    try:
        report_lines = run_wall_checks(
            ifc_path,
            min_mm=float(min_mm),
            min_height_mm=float(min_height_mm),
            min_service_height_mm=float(min_service_height_mm),
            use_space_aware_height=bool(use_space_aware_height),
            max_u=float(max_u),
            climate_zone=normalized_zone,
            include_summary=bool(include_summary),
        )
        report_text = "\n".join(report_lines)
        fail_count = sum(1 for line in report_lines if line.startswith("[FAIL] IfcWall "))
        if normalized_zone:
            u_info = f"U-limit mode: climate zone {normalized_zone} (U_lim={rules.CLIMATE_ZONE_U_LIMITS[normalized_zone]:.2f})"
        else:
            u_info = f"U-limit mode: custom max U={float(max_u):.3f}"
        if use_space_aware_height:
            h_info = f"Height mode: room-aware ({float(min_height_mm):.0f}/{float(min_service_height_mm):.0f}mm)"
        else:
            h_info = f"Height mode: fixed ({float(min_height_mm):.0f}mm)"
        status = f"Analyzed: {Path(ifc_path).name} | Failed checks: {fail_count} | {u_info} | {h_info}"
        return report_text, status
    except Exception as exc:
        return "", f"Error analyzing {Path(ifc_path).name}: {exc}"


def build_app():
    with gr.Blocks(title="IFC Wall Compliance Checker") as app:
        gr.Markdown(
            """
# IFC Wall Compliance Checker
Upload an IFC model and run wall compliance checks.
`U-value` (thermal transmittance) is in W/m2K: lower is better insulation.
If room-aware height is enabled: 2.50m general, 2.20m for kitchen/bath/corridor (based on IfcSpace links).
"""
        )

        with gr.Row():
            with gr.Column(scale=1):
                ifc_input = gr.File(
                    label="Upload IFC file",
                    file_types=[".ifc"],
                    type="filepath",
                )
                min_mm = gr.Number(label="Minimum wall thickness (mm)", value=100, precision=0)
                min_height_mm = gr.Number(label="General minimum wall height (mm)", value=2500, precision=0)
                min_service_height_mm = gr.Number(
                    label="Service-space minimum height (mm)",
                    value=2200,
                    precision=0,
                )
                use_space_aware_height = gr.Checkbox(
                    label="Use room-aware height (kitchen/bath/corridor)",
                    value=True,
                )
                max_u = gr.Number(label="Maximum U-value", value=0.8, precision=3)
                climate_zone = gr.Dropdown(
                    label="Climate zone (CTE external-wall U limit)",
                    choices=["Custom (use max U-value)", "A", "B", "C", "D", "E"],
                    value="Custom (use max U-value)",
                )
                include_summary = gr.Checkbox(label="Include summary section", value=True)
                analyze_btn = gr.Button("Run wall checks", variant="primary")
                clear_btn = gr.Button("Clear")

            with gr.Column(scale=2):
                status = gr.Markdown("Upload a file and click **Run wall checks**.")
                output = gr.Textbox(
                    label="Compliance report",
                    lines=24,
                    max_lines=40,
                )

        analyze_btn.click(
            fn=analyze_ifc_walls,
            inputs=[
                ifc_input,
                min_mm,
                min_height_mm,
                min_service_height_mm,
                use_space_aware_height,
                max_u,
                climate_zone,
                include_summary,
            ],
            outputs=[output, status],
        )

        clear_btn.click(
            fn=lambda: ("", "Upload a file and click **Run wall checks**."),
            inputs=[],
            outputs=[output, status],
        )

    return app


def parse_args():
    parser = argparse.ArgumentParser(description="Run the wall compliance Gradio app.")
    parser.add_argument("--host", default="127.0.0.1", help="Host interface for Gradio server.")
    parser.add_argument("--port", type=int, default=7860, help="Port for Gradio server.")
    parser.add_argument(
        "--share",
        action="store_true",
        help="Create a temporary public Gradio link.",
    )
    return parser.parse_args()


if __name__ == "__main__":
    args = parse_args()
    build_app().launch(server_name=args.host, server_port=args.port, share=args.share)