diff --git a/src/ifcblenderexport/blenderbim/bim/export_ifc.py b/src/ifcblenderexport/blenderbim/bim/export_ifc.py index b043b77d0f..efabfcbdeb 100644 --- a/src/ifcblenderexport/blenderbim/bim/export_ifc.py +++ b/src/ifcblenderexport/blenderbim/bim/export_ifc.py @@ -1,10 +1,12 @@ import os import bpy import json +import numpy as np import datetime import zipfile import tempfile import ifcopenshell +import ifcopenshell.util.placement from blenderbim.bim.ifc import IfcStore import addon_utils @@ -16,6 +18,8 @@ class IfcExporter: def export(self): self.file = IfcStore.get_file() self.set_header() + if bpy.context.scene.BIMProjectProperties.is_authoring: + self.sync_object_placements() extension = self.ifc_export_settings.output_file.split(".")[-1] if extension == "ifczip": with tempfile.TemporaryDirectory() as unzipped_path: @@ -68,6 +72,36 @@ class IfcExporter: # else: # self.file.wrapped_data.header.file_name.authorization = "Nobody" + def sync_object_placements(self): + self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file) + for obj in bpy.data.objects: + try: + self.sync_object_placement(obj) + except: + pass + + def sync_object_placement(self, obj): + blender_matrix = np.matrix(obj.matrix_world) + ifc_matrix = ifcopenshell.util.placement.get_local_placement( + self.file.by_id(obj.BIMObjectProperties.ifc_definition_id).ObjectPlacement + ) + ifc_matrix[0][3] *= self.unit_scale + ifc_matrix[1][3] *= self.unit_scale + ifc_matrix[2][3] *= self.unit_scale + + props = bpy.context.scene.BIMGeoreferenceProperties + if props.has_blender_offset and props.blender_offset_type == "OBJECT_PLACEMENT": + ifc_matrix = ifcopenshell.util.geolocation.global2local( + ifc_matrix, + float(props.blender_eastings) * self.unit_scale, + float(props.blender_northings) * self.unit_scale, + float(props.blender_orthogonal_height) * self.unit_scale, + float(props.blender_x_axis_abscissa), + float(props.blender_x_axis_ordinate), + ) + if not np.allclose(ifc_matrix, blender_matrix, atol=0.0001): + bpy.ops.bim.edit_object_placement(obj=obj.name) + def get_application_name(self): return "BlenderBIM" diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/operator.py b/src/ifcblenderexport/blenderbim/bim/module/geometry/operator.py index a3d8c69149..8fec09a106 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/module/geometry/operator.py @@ -1,6 +1,7 @@ import bpy import numpy as np import ifcopenshell +import ifcopenshell.util.unit import ifcopenshell.util.element import logging import blenderbim.bim.module.geometry.edit_object_placement as edit_object_placement @@ -37,19 +38,19 @@ class EditObjectPlacement(bpy.types.Operator): self.file = IfcStore.get_file() # TODO: determine how to deal with this module dependency props = bpy.context.scene.BIMGeoreferenceProperties + unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file) for obj in objs: if not obj.BIMObjectProperties.ifc_definition_id: continue matrix = np.array(obj.matrix_world) if props.has_blender_offset and props.blender_offset_type == "OBJECT_PLACEMENT": - self.calculate_unit_scale() # TODO: np.array? Why not matrix? matrix = np.array( ifcopenshell.util.geolocation.local2global( np.matrix(obj.matrix_world), - float(props.blender_eastings) * self.unit_scale, - float(props.blender_northings) * self.unit_scale, - float(props.blender_orthogonal_height) * self.unit_scale, + float(props.blender_eastings) * unit_scale, + float(props.blender_northings) * unit_scale, + float(props.blender_orthogonal_height) * unit_scale, float(props.blender_x_axis_abscissa), float(props.blender_x_axis_ordinate), ) @@ -63,18 +64,6 @@ class EditObjectPlacement(bpy.types.Operator): ).execute() return {"FINISHED"} - def calculate_unit_scale(self): - self.unit_scale = 1 - units = self.file.by_type("IfcUnitAssignment")[0] - for unit in units.Units: - if not hasattr(unit, "UnitType") or unit.UnitType != "LENGTHUNIT": - continue - while unit.is_a("IfcConversionBasedUnit"): - self.unit_scale *= unit.ConversionFactor.ValueComponent.wrappedValue - unit = unit.ConversionFactor.UnitComponent - if unit.is_a("IfcSIUnit"): - self.unit_scale *= ifcopenshell.util.unit.get_prefix_multiplier(unit.Prefix) - class AddRepresentation(bpy.types.Operator): bl_idname = "bim.add_representation" diff --git a/src/ifcblenderexport/blenderbim/bim/module/project/prop.py b/src/ifcblenderexport/blenderbim/bim/module/project/prop.py index 6e40d13122..d90ceea623 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/project/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/module/project/prop.py @@ -13,4 +13,4 @@ from bpy.props import ( class BIMProjectProperties(PropertyGroup): - is_authoring: BoolProperty(name="Enable Authoring Mode") + is_authoring: BoolProperty(name="Enable Authoring Mode", default=True)