diff --git a/src/bonsai/bonsai/bim/module/geometry/operator.py b/src/bonsai/bonsai/bim/module/geometry/operator.py index 9bc0566532..7d6e60d2f6 100644 --- a/src/bonsai/bonsai/bim/module/geometry/operator.py +++ b/src/bonsai/bonsai/bim/module/geometry/operator.py @@ -2683,6 +2683,19 @@ class OverrideModeSetObject(bpy.types.Operator, tool.Ifc.Operator): self.enable_edit_mode(bpy.context) return + if item.is_a("IfcGeometricCurveSet"): + # The set itself is the edited representation item (e.g. a dimension + # annotation). Keep the same set entity and just swap out its nested + # curve Elements, rather than replacing the set with a bare curve. + old_elements = list(item.Elements) + item.Elements = tuple(new) + for old_element in old_elements: + ifcopenshell.util.element.remove_deep2(tool.Ifc.get(), old_element) + tool.Ifc.link(item, obj.data) + tool.Geometry.import_item(obj) + tool.Geometry.reload_representation(props.representation_obj) + return + additional_curves = [] if len(new) > 1: additional_curves = new[1:] @@ -2886,12 +2899,27 @@ class DirectProfileEdit(bpy.types.Operator, tool.Ifc.Operator): ProfileDecorator.install(context) return {"CANCELLED"} + ifc_file = tool.Ifc.get() + + if item.is_a("IfcGeometricCurveSet"): + # The set itself is the edited representation item (e.g. a dimension + # annotation). Keep the same set entity and just swap out its nested + # curve Elements, rather than replacing the set with a bare curve. + old_elements = list(item.Elements) + item.Elements = tuple(new) + for old_element in old_elements: + ifcopenshell.util.element.remove_deep2(ifc_file, old_element) + tool.Ifc.link(item, obj.data) + tool.Geometry.import_item(obj) + tool.Geometry.reload_representation(props.representation_obj) + tool.Geometry.disable_item_mode() + return {"FINISHED"} + additional_curves = [] if len(new) > 1: additional_curves = new[1:] new = new[0] - ifc_file = tool.Ifc.get() for inverse in ifc_file.get_inverse(item): ifcopenshell.util.element.replace_attribute(inverse, item, new) ifcopenshell.util.element.remove_deep2(ifc_file, item) diff --git a/src/bonsai/bonsai/tool/geometry.py b/src/bonsai/bonsai/tool/geometry.py index c4b7cd0ef6..48da9d2437 100644 --- a/src/bonsai/bonsai/tool/geometry.py +++ b/src/bonsai/bonsai/tool/geometry.py @@ -1348,6 +1348,7 @@ class Geometry(bonsai.core.tool.Geometry): or item.is_a("IfcCompositeCurve") or item.is_a("IfcIndexedPolyCurve") or item.is_a("IfcCircle") + or item.is_a("IfcGeometricCurveSet") ) @classmethod diff --git a/src/bonsai/bonsai/tool/model.py b/src/bonsai/bonsai/tool/model.py index f54633c3cc..cc651a6ee8 100644 --- a/src/bonsai/bonsai/tool/model.py +++ b/src/bonsai/bonsai/tool/model.py @@ -625,6 +625,12 @@ class Model(bonsai.core.tool.Model): for segment in curve.Segments: cls.convert_curve_to_mesh(obj, position, segment.ParentCurve) + elif curve.is_a("IfcGeometricCurveSet"): + # A set of independent curves (e.g. dimension annotations). Each element is + # imported as its own disconnected edge loop within the same mesh. + for sub_curve in curve.Elements: + cls.convert_curve_to_mesh(obj, position, sub_curve, x_angle=x_angle) + elif curve.is_a("IfcIndexedPolyCurve"): for local_point in curve.Points.CoordList: global_point = position @ Vector(cls.convert_unit_to_si(local_point)).to_3d()