From 49efce7ecab984126092a34a43ee19dc07f30e0b Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 8 Nov 2019 17:24:15 +1100 Subject: [PATCH] New option to ignore site, to import incorrectly geolocated IFCs This behaviour occurs extensively in IFC files coming from Revit --- .../io_export_ifc/import_ifc.py | 66 ++++++++++--------- .../io_export_ifc/operator.py | 1 + src/ifcblenderexport/io_export_ifc/ui.py | 3 + 3 files changed, 38 insertions(+), 32 deletions(-) diff --git a/src/ifcblenderexport/io_export_ifc/import_ifc.py b/src/ifcblenderexport/io_export_ifc/import_ifc.py index 6c05b2d53c..c4b7895d0a 100644 --- a/src/ifcblenderexport/io_export_ifc/import_ifc.py +++ b/src/ifcblenderexport/io_export_ifc/import_ifc.py @@ -16,35 +16,6 @@ class IfcSchema(): ifc_schema = IfcSchema() -# Helper functions, to be refactored - -def a2p(o,z,x): - y = z.cross(x) - r = mathutils.Matrix((x, y, z, o)) - r.resize_4x4() - r.transpose() - return r - -def get_axis2placement(plc): - z = mathutils.Vector(plc.Axis.DirectionRatios if plc.Axis else (0,0,1)) - x = mathutils.Vector(plc.RefDirection.DirectionRatios if plc.RefDirection else (1,0,0)) - o = plc.Location.Coordinates - return a2p(o,z,x) - -def get_cartesiantransformationoperator(plc): - #z = mathutils.Vector(plc.Axis3.DirectionRatios if plc.Axis3 else (0,0,1)) - x = mathutils.Vector(plc.Axis1.DirectionRatios if plc.Axis1 else (1,0,0)) - z = x.cross(mathutils.Vector(plc.Axis2.DirectionRatios if plc.Axis2 else (0,1,0))) - o = plc.LocalOrigin.Coordinates - return a2p(o,z,x) - -def get_local_placement(plc): - if plc.PlacementRelTo is None: - parent = mathutils.Matrix() - else: - parent = get_local_placement(plc.PlacementRelTo) - return parent @ get_axis2placement(plc.RelativePlacement) - class MaterialCreator(): def __init__(self): self.mesh = None @@ -202,7 +173,7 @@ class IfcImporter(): object = bpy.data.objects.new(self.get_name(element), mesh) - element_matrix = get_local_placement(element.ObjectPlacement) + element_matrix = self.get_local_placement(element.ObjectPlacement) # Blender supports reusing a mesh with a different transformation # applied at the object level. In contrast, IFC supports reusing a mesh @@ -217,7 +188,7 @@ class IfcImporter(): shared_shape_transformation = self.get_representation_cartesian_transformation( self.file.by_id(self.mesh_shapes[mesh_name].product.id())) if shared_shape_transformation: - shared_transform = get_cartesiantransformationoperator(shared_shape_transformation) + shared_transform = self.get_cartesiantransformationoperator(shared_shape_transformation) shared_transform.invert() element_matrix = element_matrix @ shared_transform @@ -225,7 +196,7 @@ class IfcImporter(): # transformation to our current element's object transformation transformation = self.get_representation_cartesian_transformation(element) if transformation: - element_matrix = get_cartesiantransformationoperator(transformation) @ element_matrix + element_matrix = self.get_cartesiantransformationoperator(transformation) @ element_matrix element_matrix[0][3] *= self.unit_scale element_matrix[1][3] *= self.unit_scale @@ -298,8 +269,39 @@ class IfcImporter(): print('Could not create mesh for {}: {}/{}'.format( element.GlobalId, self.get_name(element))) + def a2p(self, o, z, x): + y = z.cross(x) + r = mathutils.Matrix((x, y, z, o)) + r.resize_4x4() + r.transpose() + return r + + def get_axis2placement(self, plc): + z = mathutils.Vector(plc.Axis.DirectionRatios if plc.Axis else (0,0,1)) + x = mathutils.Vector(plc.RefDirection.DirectionRatios if plc.RefDirection else (1,0,0)) + o = plc.Location.Coordinates + return self.a2p(o,z,x) + + def get_cartesiantransformationoperator(self, plc): + #z = mathutils.Vector(plc.Axis3.DirectionRatios if plc.Axis3 else (0,0,1)) + x = mathutils.Vector(plc.Axis1.DirectionRatios if plc.Axis1 else (1,0,0)) + z = x.cross(mathutils.Vector(plc.Axis2.DirectionRatios if plc.Axis2 else (0,1,0))) + o = plc.LocalOrigin.Coordinates + return self.a2p(o,z,x) + + def get_local_placement(self, plc): + if plc.PlacementRelTo is None: + parent = mathutils.Matrix() + else: + parent = self.get_local_placement(plc.PlacementRelTo) + if self.ifc_import_settings.should_ignore_site_coordinates \ + and 'IfcSite' in [o.is_a() for o in plc.PlacesObject]: + return parent + return parent @ self.get_axis2placement(plc.RelativePlacement) + class IfcImportSettings: def __init__(self): self.logger = None self.input_file = None + self.should_ignore_site_coordinates = False self.should_import_curves = False diff --git a/src/ifcblenderexport/io_export_ifc/operator.py b/src/ifcblenderexport/io_export_ifc/operator.py index d175fe89e5..1fa1edfa70 100644 --- a/src/ifcblenderexport/io_export_ifc/operator.py +++ b/src/ifcblenderexport/io_export_ifc/operator.py @@ -58,6 +58,7 @@ class ImportIFC(bpy.types.Operator, ImportHelper): ifc_import_settings.logger = logging.getLogger('ImportIFC') ifc_import_settings.logger.info('Starting import') ifc_import_settings.input_file = self.filepath + ifc_import_settings.should_ignore_site_coordinates = bpy.context.scene.BIMProperties.import_should_ignore_site_coordinates ifc_import_settings.should_import_curves = bpy.context.scene.BIMProperties.import_should_import_curves ifc_importer = import_ifc.IfcImporter(ifc_import_settings) ifc_importer.execute() diff --git a/src/ifcblenderexport/io_export_ifc/ui.py b/src/ifcblenderexport/io_export_ifc/ui.py index 7441d36aab..751e41a71a 100644 --- a/src/ifcblenderexport/io_export_ifc/ui.py +++ b/src/ifcblenderexport/io_export_ifc/ui.py @@ -63,6 +63,7 @@ class BIMProperties(bpy.types.PropertyGroup): export_has_representations: bpy.props.BoolProperty(name="Export Representations", default=True) export_should_export_all_materials_as_styled_items: bpy.props.BoolProperty(name="Export All Materials as Styled Items", default=False) export_should_use_presentation_style_assignment: bpy.props.BoolProperty(name="Export with Presentation Style Assignment", default=False) + import_should_ignore_site_coordinates: bpy.props.BoolProperty(name="Import Ignoring Site Coordinates", default=False) import_should_import_curves: bpy.props.BoolProperty(name="Import Curves", default=False) qa_reject_element_reason: bpy.props.StringProperty(name="Element Rejection Reason") pset_name: bpy.props.EnumProperty(items=getPsetNames, name="Pset Name") @@ -452,5 +453,7 @@ class MVDPanel(bpy.types.Panel): row = layout.row() row.prop(bim_properties, "export_should_use_presentation_style_assignment") + row = layout.row() + row.prop(bim_properties, "import_should_ignore_site_coordinates") row = layout.row() row.prop(bim_properties, "import_should_import_curves")