diff --git a/src/bonsai/bonsai/bim/module/geometry/operator.py b/src/bonsai/bonsai/bim/module/geometry/operator.py index cb50494ee0..18bd2b7beb 100644 --- a/src/bonsai/bonsai/bim/module/geometry/operator.py +++ b/src/bonsai/bonsai/bim/module/geometry/operator.py @@ -3073,14 +3073,10 @@ class AddHalfSpaceSolidItem(bpy.types.Operator, tool.Ifc.Operator): obj.matrix_world = matrix tool.Geometry.record_object_position(obj) - ifc_file = tool.Ifc.get() - unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file) - local_z = ifc_file.createIfcDirection((0.0, 0.0, 1.0)) - local_x = ifc_file.createIfcDirection((1.0, 0.0, 0.0)) - point = ifc_file.createIfcCartesianPoint((np.array(local_matrix.translation) / unit_scale).tolist()) - placement = ifc_file.createIfcAxis2Placement3D(point, local_z, local_x) - plane = ifc_file.createIfcPlane(placement) - item = ifc_file.createIfcHalfSpaceSolid(plane, AgreementFlag=False) + unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) + builder = ifcopenshell.util.shape_builder.ShapeBuilder(tool.Ifc.get()) + location = np.array(local_matrix.translation) / unit_scale + item = builder.half_space_solid(builder.plane(location=location)) props.add_item_object(obj, item) representation = tool.Geometry.get_active_representation(props.representation_obj) diff --git a/src/bonsai/bonsai/tool/geometry.py b/src/bonsai/bonsai/tool/geometry.py index a07e4b203c..133189b184 100644 --- a/src/bonsai/bonsai/tool/geometry.py +++ b/src/bonsai/bonsai/tool/geometry.py @@ -1636,11 +1636,11 @@ class Geometry(bonsai.core.tool.Geometry): if not (obj := item_obj.obj) or not tool.Ifc.is_moved(obj): continue item = tool.Ifc.get().by_id(obj.data.BIMMeshProperties.ifc_definition_id) - if is_swept_area := item.is_a("IfcSweptAreaSolid"): + if item.is_a("IfcSweptAreaSolid"): has_changed = True old_position = item.Position - if is_swept_area and np.allclose(np.array(rep_matrix), np.array(obj.matrix_world), atol=1e-4): + if np.allclose(np.array(rep_matrix), np.array(obj.matrix_world), atol=1e-4): if old_position: item.Position = None ifcopenshell.util.element.remove_deep2(tool.Ifc.get(), old_position) @@ -1651,7 +1651,7 @@ class Geometry(bonsai.core.tool.Geometry): item.Position = builder.create_axis2_placement_3d_from_matrix(position) if old_position: ifcopenshell.util.element.remove_deep2(tool.Ifc.get(), old_position) - if item.is_a("IfcHalfSpaceSolid"): + elif item.is_a("IfcHalfSpaceSolid"): has_changed = True surface = item.BaseSurface if surface.is_a("IfcPlane"): diff --git a/src/ifcopenshell-python/ifcopenshell/util/shape_builder.py b/src/ifcopenshell-python/ifcopenshell/util/shape_builder.py index 02295462d7..5b336d8e1e 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/shape_builder.py +++ b/src/ifcopenshell-python/ifcopenshell/util/shape_builder.py @@ -912,6 +912,16 @@ class ShapeBuilder: """ return self.file.createIfcBlock(self.create_axis2_placement_3d(position), x_length, y_length, z_length) + def half_space_solid( + self, plane: ifcopenshell.entity_instance, agreement_flag: bool = False + ) -> ifcopenshell.entity_instance: + """ + :param plane: The IfcPlane representing the half space. + :param agreement_flag: False if +Z represents the void + :return: IfcHalfSpaceSolid + """ + return self.file.createIfcHalfSpaceSolid(plane, AgreementFlag=agreement_flag) + def extrude( self, profile_or_curve: ifcopenshell.entity_instance,