New option to ignore site, to import incorrectly geolocated IFCs

This behaviour occurs extensively in IFC files coming from Revit
This commit is contained in:
Dion Moult
2019-11-08 17:24:15 +11:00
parent c425b44ca9
commit 49efce7eca
3 changed files with 38 additions and 32 deletions
@@ -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
@@ -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()
+3
View File
@@ -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")