diff --git a/src/blenderbim/test/bim/feature/geometry.feature b/src/blenderbim/test/bim/feature/geometry.feature index f72c5e4597..a59f91a831 100644 --- a/src/blenderbim/test/bim/feature/geometry.feature +++ b/src/blenderbim/test/bim/feature/geometry.feature @@ -42,6 +42,27 @@ Scenario: Add representation - add a new representation to a typed instance Then the object "IfcWall/Instance" data is a "Annotation2D" representation of "Plan/Annotation/PLAN_VIEW" And the object "IfcWall/Instance.001" data is a "Annotation2D" representation of "Plan/Annotation/PLAN_VIEW" +Scenario: Add representation - add a representation with a scale factor applied + Given an empty IFC project + And I add a cube + And the object "Cube" is selected + When the object "Cube" is scaled to "2" + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + Then the object "IfcWall/Cube" has no scale + And the object "IfcWall/Cube" dimensions are "4,4,4" + +Scenario: Add representation - add a representation with a scale factor removed due to multiple users + Given an empty IFC project + And I add a cube + And I press "object.duplicate_move_linked" + And the object "Cube" is selected + When the object "Cube" is scaled to "2" + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + Then the object "IfcWall/Cube" has no scale + And the object "IfcWall/Cube" dimensions are "2,2,2" + Scenario: Switch representation Given an empty IFC project And I add a cube diff --git a/src/blenderbim/test/bim/test_feature.py b/src/blenderbim/test/bim/test_feature.py index b5844574f2..60c1360a83 100644 --- a/src/blenderbim/test/bim/test_feature.py +++ b/src/blenderbim/test/bim/test_feature.py @@ -86,7 +86,7 @@ def i_add_an_empty(): @given("I add a sun") @when("I add an sun") -def i_add_an_empty(): +def i_add_a_sun(): bpy.ops.object.light_add(type="SUN") @@ -143,10 +143,16 @@ def the_object_name_is_selected(name): @given(parsers.parse('the object "{name}" is moved to "{location}"')) @when(parsers.parse('the object "{name}" is moved to "{location}"')) -def the_object_name_is_selected(name, location): +def the_object_name_is_moved_to_location(name, location): the_object_name_exists(name).location += Vector([float(co) for co in location.split(",")]) +@given(parsers.parse('the object "{name}" is scaled to "{scale}"')) +@when(parsers.parse('the object "{name}" is scaled to "{scale}"')) +def the_object_name_is_scaled_to_scale(name, scale): + the_object_name_exists(name).scale *= float(scale) + + @given(parsers.parse('the object "{name}" is placed in the collection "{collection}"')) @when(parsers.parse('the object "{name}" is placed in the collection "{collection}"')) def the_object_name_is_placed_in_the_collection_collection(name, collection): @@ -449,6 +455,22 @@ def the_object_name_is_at_location(name, location): ).length < 0.1, f"Object is at {obj_location}" +@then(parsers.parse('the object "{name}" has no scale')) +def the_object_name_has_no_scale(name): + assert the_object_name_exists(name).scale == Vector( + ( + 1.0, + 1.0, + 1.0, + ) + ) + + +@then(parsers.parse('the object "{name}" dimensions are "{dimensions}"')) +def the_object_name_dimensions_are_dimensions(name, dimensions): + assert list(the_object_name_exists(name).dimensions) == [float(co) for co in dimensions.split(",")] + + @then(parsers.parse('the object "{name}" bottom left corner is at "{location}"')) def the_object_name_is_at_location(name, location): obj_corner = Vector(the_object_name_exists(name).bound_box[0]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_representation.py index 906a06e610..ae2ed7cd82 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_representation.py @@ -66,6 +66,15 @@ class Usecase: return any([abs((tM @ v.co).z) > threshold for v in face.verts]) def evaluate_geometry(self): + if self.settings["blender_object"].scale != Vector((1., 1., 1.)): + if self.settings["blender_object"].data.users == 1: + context_override = {} + context_override["object"] = context_override["active_object"] = self.settings["blender_object"] + context_override["selected_objects"] = context_override["selected_editable_objects"] = [self.settings["blender_object"]] + bpy.ops.object.transform_apply(context_override, location=False, rotation=False, scale=True) + else: + self.settings["blender_object"].scale = Vector((1., 1., 1.)) + for modifier in self.settings["blender_object"].modifiers: if modifier.type == "BOOLEAN": modifier.show_viewport = False diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/unassign_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/unassign_representation.py index 185fda0a01..dd2a28d2c8 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/unassign_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/unassign_representation.py @@ -34,9 +34,8 @@ class Usecase: self.settings["product"].RepresentationMaps = self.settings["product"].RepresentationMaps or None def remove_representation_map_only(self, representation_map): - dummy_representation = self.file.createIfcShapeRepresentation() - representation_map.MappedRepresentation = dummy_representation - ifcopenshell.util.element.remove_deep(self.file, representation_map) + representation_map.MappedRepresentation = self.file.createIfcShapeRepresentation() + ifcopenshell.util.element.remove_deep2(self.file, representation_map) self.file.remove(representation_map) def unassign_products_using_mapped_representation(self, representation_map):