ifcSpace Update
build and deploy Speckle functions / publish-automate-function-version (push) Has been cancelled

This commit is contained in:
NLSA
2026-03-13 14:43:27 +01:00
parent 112f031608
commit f9193ee3a0
2 changed files with 105 additions and 3 deletions
+10 -3
View File
@@ -14,7 +14,7 @@ from utils.type_manager import TypeManager
SPATIAL_STRUCTURE_TYPES = {
"IfcBuilding", "IfcBuildingStorey",
"IfcSpace", "IfcExternalSpatialElement", "IfcSpatialZone",
"IfcExternalSpatialElement", "IfcSpatialZone",
"IfcGrid", "IfcAnnotation",
}
@@ -110,7 +110,12 @@ def automate_function(
skipped_spatial += 1
continue
name = build_element_name(obj)
# IfcSpace uses the Speckle object name (e.g. "Rooms - Live/Work Unit 507")
# instead of Family:Type (which is "none:none" for Revit rooms)
if ifc_class == "IfcSpace":
name = getattr(obj, "name", None) or build_element_name(obj)
else:
name = build_element_name(obj)
storey = storey_manager.get_or_create(level_name)
# ------------------------------------------------------------------ #
@@ -250,8 +255,10 @@ def _create_element(ifc, ifc_class, name, rep, placement, storey,
element.ObjectPlacement = _make_placement(ifc, 0.0, 0.0, 0.0)
# Queue spatial assignment (batched flush at end for performance)
# IfcSpace is a spatial structure element — must be decomposed (aggregated)
# under its IfcBuildingStorey, not spatially contained.
if storey_manager:
if ifc_class == "IfcSite":
if ifc_class in ("IfcSite", "IfcSpace"):
storey_manager.queue_aggregate(storey, element)
else:
storey_manager.queue_contain(storey, element)
+95
View File
@@ -424,9 +424,104 @@ def write_common_pset(ifc, element, obj: Base, ifc_class: str, category_name: st
except Exception:
pass
# IfcSpace-specific: set Name, LongName, Category, and BaseQuantities
if ifc_class == "IfcSpace":
_write_space_properties(ifc, element, obj, ifc_props)
_write_pset(ifc, element, pset_name, ifc_props)
def _write_space_properties(ifc, element, obj: Base, ifc_props: list):
"""
Set IfcSpace attributes and BaseQuantities from Revit Room parameters.
Uses internalDefinitionName to find values:
ROOM_NUMBER → IfcSpace.Name + Pset_SpaceCommon.Reference
ROOM_NAME → IfcSpace.LongName
Occupant → Pset_SpaceCommon.Category
ROOM_AREA → Qto_SpaceBaseQuantities.NetFloorArea
ROOM_VOLUME → Qto_SpaceBaseQuantities.NetVolume
"""
props = _get_props_dict(obj)
params = _safe_get(props, "Parameters", {})
inst_params = _safe_get(params, "Instance Parameters", {})
# --- Room Number → IfcSpace.Name + Pset_SpaceCommon.Reference ---
room_number = _param_value(inst_params, "ROOM_NUMBER")
if room_number:
room_number = str(room_number).strip()
element.Name = room_number
# Replace any existing Reference in ifc_props
ifc_props[:] = [p for p in ifc_props if p.Name != "Reference"]
p = _make_prop(ifc, "Reference", "IfcIdentifier", room_number)
if p:
ifc_props.append(p)
# Also add as explicit RoomNumber in the pset
p = _make_prop(ifc, "RoomNumber", "IfcLabel", room_number)
if p:
ifc_props.append(p)
# --- Room Name → IfcSpace.LongName + Pset_SpaceCommon.RoomName ---
room_name = _param_value(inst_params, "ROOM_NAME")
if not room_name:
# Fallback to the Speckle object's own name
room_name = getattr(obj, "name", None)
if room_name:
room_name = str(room_name).strip()
try:
element.LongName = room_name
except AttributeError:
pass
p = _make_prop(ifc, "RoomName", "IfcLabel", room_name)
if p:
ifc_props.append(p)
# --- Occupant → Pset_SpaceCommon.Category ---
occupant = _param_value(inst_params, "Occupant")
if occupant:
p = _make_prop(ifc, "Category", "IfcLabel", str(occupant).strip())
if p:
ifc_props.append(p)
# --- Area & Volume → Qto_SpaceBaseQuantities ---
quantities = []
area_val = _param_value(inst_params, "ROOM_AREA")
if area_val is not None:
try:
q = ifc.create_entity(
"IfcQuantityArea",
Name="NetFloorArea",
AreaValue=float(area_val),
)
quantities.append(q)
except Exception:
pass
volume_val = _param_value(inst_params, "ROOM_VOLUME")
if volume_val is not None:
try:
q = ifc.create_entity(
"IfcQuantityVolume",
Name="NetVolume",
VolumeValue=float(volume_val),
)
quantities.append(q)
except Exception:
pass
if quantities:
try:
qto = ifcopenshell.api.run(
"pset.add_qto", ifc,
product=element,
name="Qto_SpaceBaseQuantities",
)
qto.Quantities = quantities
except Exception as e:
print(f" ⚠️ Qto_SpaceBaseQuantities: {e}")
# ---------------------------------------------------------------------------
# Pset_EnvironmentalImpactIndicators (always written, Reference = TypeName)
# ---------------------------------------------------------------------------