Spaces:
Sleeping
Sleeping
| """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) | |