mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
Support appending IfcGroup assets via project.append_asset (#8162)
append_asset could not import an IfcGroup from a project library: IfcGroup was absent from APPENDABLE_ASSET, so execute() fell through every branch and returned None, appending nothing. Add IfcGroup to APPENDABLE_ASSET and an append_group() routine that mirrors append_product(): it whitelists the group's IsGroupedBy inverse so the members reached through IfcRelAssignsToGroup are copied via the regular element-append path (bringing their materials, properties and representations), and the relationship is recreated in the destination linking the copied group to the copied members. Idempotency comes from the existing GUID-based reuse, so re-appending the same group does not duplicate it. Verified headless: appending a group of three walls yields group=1, walls=3, IfcRelAssignsToGroup=1 with RelatingGroup and RelatedObjects correctly wired; re-appending is a no-op; appending a plain IfcProduct still works unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,7 @@ APPENDABLE_ASSET = Literal[
|
||||
"IfcCostSchedule",
|
||||
"IfcProfileDef",
|
||||
"IfcPresentationStyle",
|
||||
"IfcGroup",
|
||||
]
|
||||
APPENDABLE_ASSET_TYPES: tuple[APPENDABLE_ASSET, ...] = get_args(APPENDABLE_ASSET)
|
||||
MATERIAL_SETS = ("IfcMaterialLayerSet", "IfcMaterialConstituentSet", "IfcMaterialProfileSet")
|
||||
@@ -68,8 +69,8 @@ def append_asset(
|
||||
|
||||
:param library: The file object containing the asset.
|
||||
:param element: An element in the library file of the asset. It may be
|
||||
an IfcTypeProduct, IfcProduct, IfcMaterial, IfcCostSchedule, or
|
||||
IfcProfileDef.
|
||||
an IfcTypeProduct, IfcProduct, IfcMaterial, IfcCostSchedule,
|
||||
IfcProfileDef, or IfcGroup.
|
||||
:param reuse_identities: Optional dictionary of mapped entities' identities to the
|
||||
already created elements. It will be used to avoid creating
|
||||
duplicated inverse elements during multiple `project.append_asset` calls. If you want
|
||||
@@ -236,6 +237,9 @@ class Usecase:
|
||||
elif self.settings["element"].is_a("IfcPresentationStyle"):
|
||||
self.target_class = "IfcPresentationStyle"
|
||||
return self.append_presentation_style()
|
||||
elif self.settings["element"].is_a("IfcGroup"):
|
||||
self.target_class = "IfcGroup"
|
||||
return self.append_group()
|
||||
|
||||
def by_guid(self, guid: str) -> Union[ifcopenshell.entity_instance, None]:
|
||||
try:
|
||||
@@ -393,6 +397,33 @@ class Usecase:
|
||||
self.reuse_existing_contexts()
|
||||
return element
|
||||
|
||||
def append_group(self):
|
||||
# A group (IfcGroup and subtypes like IfcSystem, IfcZone) is appended
|
||||
# together with its members. Members are reached through the group's
|
||||
# ``IsGroupedBy`` inverse (the IfcRelAssignsToGroup relationship), whose
|
||||
# ``RelatedObjects`` are copied via the regular element-append path, so
|
||||
# they bring their own materials, properties, and representations. The
|
||||
# relationship itself is recreated in the destination linking the copied
|
||||
# group to the copied members.
|
||||
self.whitelisted_inverse_attributes = {
|
||||
"IfcObjectDefinition": ["HasAssociations"],
|
||||
"IfcObject": ["IsDefinedBy.IfcRelDefinesByProperties"],
|
||||
"IfcGroup": ["IsGroupedBy"],
|
||||
"IfcElement": ["HasOpenings"],
|
||||
self.base_material_class: ["HasExternalReferences", "HasProperties", "HasRepresentation"],
|
||||
"IfcRepresentationItem": [
|
||||
"StyledByItem",
|
||||
"LayerAssignments" if self.file.schema == "IFC2X3" else "LayerAssignment",
|
||||
],
|
||||
"IfcRepresentation": ["LayerAssignments"],
|
||||
"IfcProductDefinitionShape": ["HasShapeAspects"],
|
||||
"IfcRepresentationMap": ["HasShapeAspects"],
|
||||
}
|
||||
self.existing_contexts = self.file.by_type("IfcGeometricRepresentationContext")
|
||||
element = self.add_element(self.settings["element"])
|
||||
self.reuse_existing_contexts()
|
||||
return element
|
||||
|
||||
def append_product(self):
|
||||
self.whitelisted_inverse_attributes = {
|
||||
"IfcObjectDefinition": ["HasAssociations"],
|
||||
|
||||
Reference in New Issue
Block a user