Spaces:
Sleeping
Sleeping
| """ | |
| Shared IFC utility functions used by team adapters. | |
| """ | |
| import ifcopenshell | |
| import ifcopenshell.util.element | |
| # ββ Property extraction ββββββββββββββββββββββββββββββββββββββ | |
| def get_pset_value(element, pset_name: str, prop_name: str): | |
| """Return a property value from a named property set, or None.""" | |
| try: | |
| psets = ifcopenshell.util.element.get_psets(element) | |
| if pset_name in psets and prop_name in psets[pset_name]: | |
| v = psets[pset_name][prop_name] | |
| if v is not None and v != "": | |
| return v | |
| except Exception: | |
| pass | |
| return None | |
| def search_psets(element, prop_name: str): | |
| """Search ALL property sets for a property by name. Returns first numeric match.""" | |
| try: | |
| psets = ifcopenshell.util.element.get_psets(element) | |
| for _pset_name, props in psets.items(): | |
| if isinstance(props, dict) and prop_name in props: | |
| v = props[prop_name] | |
| if v is not None and v != "" and isinstance(v, (int, float)): | |
| return v | |
| except Exception: | |
| pass | |
| return None | |
| # ββ Unit helpers βββββββββββββββββββββββββββββββββββββββββββββ | |
| def to_mm(value_m): | |
| """Convert a value (assumed metres) to millimetres. | |
| Heuristic: if value > 100 it's probably already in mm. | |
| """ | |
| if value_m is None: | |
| return None | |
| if value_m > 100: | |
| return round(value_m) | |
| return round(value_m * 1000) | |
| def safe_float(x): | |
| """Try to convert x to float, return None on failure.""" | |
| try: | |
| return float(x) if x is not None else None | |
| except (ValueError, TypeError): | |
| return None | |
| # ββ Material helpers βββββββββββββββββββββββββββββββββββββββββ | |
| def get_material_total_thickness(element): | |
| """Sum the thicknesses of all material layers (in model units), or None.""" | |
| try: | |
| for rel in getattr(element, "HasAssociations", []): | |
| if rel.is_a("IfcRelAssociatesMaterial"): | |
| mat = rel.RelatingMaterial | |
| layers = None | |
| if mat.is_a("IfcMaterialLayerSetUsage"): | |
| layers = mat.ForLayerSet.MaterialLayers | |
| elif mat.is_a("IfcMaterialLayerSet"): | |
| layers = mat.MaterialLayers | |
| if layers: | |
| total = sum(l.LayerThickness for l in layers) | |
| if total > 0: | |
| return total | |
| except Exception: | |
| pass | |
| return None | |
| # ββ Element label ββββββββββββββββββββββββββββββββββββββββββββ | |
| def label(element) -> str: | |
| """Return a readable label for an IFC element.""" | |
| name = element.Name or element.GlobalId | |
| return f"{element.is_a()} '{name}'" | |