diff --git a/src/blenderbim/blenderbim/bim/export_ifc.py b/src/blenderbim/blenderbim/bim/export_ifc.py index 5dfae0a135..6a2d345bb4 100644 --- a/src/blenderbim/blenderbim/bim/export_ifc.py +++ b/src/blenderbim/blenderbim/bim/export_ifc.py @@ -119,6 +119,8 @@ class IfcExporter: def sync_object_placement(self, obj): blender_matrix = np.array(obj.matrix_world) element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) + if element.is_a("IfcGridAxis"): + return self.sync_grid_axis_object_placement(obj, element) if not hasattr(element, "ObjectPlacement"): return ifc_matrix = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement) @@ -139,6 +141,14 @@ class IfcExporter: if not np.allclose(ifc_matrix, blender_matrix, atol=0.0001): blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Surveyor, obj=obj) + def sync_grid_axis_object_placement(self, obj, element): + grid = (element.PartOfU or element.PartOfV or element.PartOfW)[0] + grid_obj = tool.Ifc.get_object(grid) + if grid_obj: + self.sync_object_placement(grid_obj) + if grid_obj.matrix_world != obj.matrix_world: + bpy.ops.bim.update_representation(obj=obj.name) + def sync_object_container(self, guid, obj): element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) element_collection = bpy.data.collections.get(obj.name) diff --git a/src/blenderbim/test/bim/feature/project.feature b/src/blenderbim/test/bim/feature/project.feature index 1b40fe3f3d..f3327f77f2 100644 --- a/src/blenderbim/test/bim/feature/project.feature +++ b/src/blenderbim/test/bim/feature/project.feature @@ -320,3 +320,20 @@ Scenario: Export IFC - with basic contents And I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc')" When I press "export_ifc.bim(filepath='{cwd}/test/files/export.ifc')" Then nothing happens + +Scenario: Export IFC - with moved object location synchronised + Given an empty IFC project + When the object "IfcBuildingStorey/My Storey" is moved to "0,0,1" + And I press "export_ifc.bim(filepath='{cwd}/test/files/export.ifc')" + And an empty Blender session + And I press "bim.load_project(filepath='{cwd}/test/files/export.ifc')" + Then the object "IfcBuildingStorey/My Storey" is at "0,0,1" + +Scenario: Export IFC - with moved grid axis location synchronised + Given an empty IFC project + And I press "mesh.add_grid" + When the object "IfcGridAxis/01" is moved to "1,0,0" + And I press "export_ifc.bim(filepath='{cwd}/test/files/export.ifc')" + And an empty Blender session + And I press "bim.load_project(filepath='{cwd}/test/files/export.ifc')" + Then the object "IfcGridAxis/01" bottom left corner is at "1,-2,0" diff --git a/src/blenderbim/test/bim/test_feature.py b/src/blenderbim/test/bim/test_feature.py index 64701d779f..d42ac7d34e 100644 --- a/src/blenderbim/test/bim/test_feature.py +++ b/src/blenderbim/test/bim/test_feature.py @@ -41,6 +41,7 @@ def replace_variables(value): @given("an empty Blender session") +@when("an empty Blender session") def an_empty_ifc_project(): IfcStore.purge() bpy.ops.wm.read_homefile(app_template="") @@ -140,6 +141,12 @@ def the_object_name_is_selected(name): additionally_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): + the_object_name_exists(name).location += Vector([float(co) for co in location.split(",")]) + + @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): @@ -428,6 +435,14 @@ def the_object_name_is_at_location(name, location): ).length < 0.1, f"Object is at {obj_location}" +@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]) + assert ( + obj_corner - Vector([float(co) for co in location.split(",")]) + ).length < 0.1, f"Object has corner {obj_corner}" + + @then(parsers.parse('the object "{name}" is contained in "{container_name}"')) def the_object_name_is_contained_in_container_name(name, container_name): ifc = an_ifc_file_exists()