From 5aec0718f42341a177c19b729b497032f5da4055 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sat, 15 May 2021 18:05:15 +1000 Subject: [PATCH] IFC drawings are now roundtrip and are imported as Blender camera objects. See #1153. --- src/blenderbim/blenderbim/bim/import_ifc.py | 59 ++++++++++++++++++++- src/blenderbim/blenderbim/bim/operator.py | 2 +- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 6ec10e5145..f9572b9ad9 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -18,6 +18,7 @@ import multiprocessing import zipfile import tempfile import numpy as np +import blenderbim.bim.prop from pathlib import Path from itertools import cycle from datetime import datetime @@ -702,11 +703,15 @@ class IfcImporter: checkpoint = time.time() shape = iterator.get() if shape: + product = self.file.by_id(shape.guid) if shape.context != "Body" and shape.guid in IfcStore.guid_map: # We only load a single context, and we prioritise the Body context. See #1290. pass + elif product.is_a("IfcAnnotation") and product.ObjectType == "DRAWING": + # We have already processed this during the create_annotation step + pass else: - self.create_product(self.file.by_id(shape.guid), shape) + self.create_product(product, shape) if not iterator.next(): break print("Done creating geometry") @@ -784,6 +789,8 @@ class IfcImporter: if mesh: pass + elif element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING": + mesh = self.create_camera(element, shape) elif shape: mesh_name = self.get_mesh_name(shape.geometry) mesh = self.meshes.get(mesh_name) @@ -1206,6 +1213,14 @@ class IfcImporter: self.structural_member_collection.objects.link(obj) elif element.is_a("IfcStructuralConnection"): self.structural_connection_collection.objects.link(obj) + elif element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING": + view_collection = bpy.data.collections.get("Views") + if not view_collection: + view_collection = bpy.data.collections.new("Views") + bpy.context.scene.collection.children.link(view_collection) + drawing_collection = bpy.data.collections.new(obj.name) + view_collection.children.link(drawing_collection) + drawing_collection.objects.link(obj) else: self.ifc_import_settings.logger.warning("Warning: this object is outside the spatial hierarchy %s", element) bpy.context.scene.collection.objects.link(obj) @@ -1294,6 +1309,48 @@ class IfcImporter: context_id = representation.ContextOfItems.id() if hasattr(representation, "ContextOfItems") else 0 return "{}/{}".format(context_id, representation_id) + def create_camera(self, element, shape): + if hasattr(shape, "geometry"): + geometry = shape.geometry + else: + geometry = shape + + v = geometry.verts + x = [v[i] for i in range(0, len(v), 3)] + y = [v[i + 1] for i in range(0, len(v), 3)] + z = [v[i + 2] for i in range(0, len(v), 3)] + width = max(x) - min(x) + height = max(y) - min(y) + depth = max(z) - min(z) + + camera = bpy.data.cameras.new(self.get_mesh_name(geometry)) + camera.type = "ORTHO" + camera.ortho_scale = width if width > height else height + camera.clip_end = depth + + if width > height: + camera.BIMCameraProperties.raster_x = 1000 + camera.BIMCameraProperties.raster_y = round(1000 * (height / width)) + else: + camera.BIMCameraProperties.raster_x = round(1000 * (width / height)) + camera.BIMCameraProperties.raster_y = 1000 + + psets = ifcopenshell.util.element.get_psets(element) + pset = psets.get("EPset_Drawing") + if pset: + if "TargetView" in pset: + camera.BIMCameraProperties.target_view = pset["TargetView"] + if "Scale" in pset: + valid_scales = [ + i[0] for i in blenderbim.bim.prop.getDiagramScales(None, None) if pset["Scale"] == i[0].split("|")[-1] + ] + if valid_scales: + camera.BIMCameraProperties.diagram_scale = valid_scales[0] + else: + camera.BIMCameraProperties.diagram_scale = "CUSTOM" + camera.BIMCameraProperties.custom_diagram_scale = pset["Scale"] + return camera + def create_mesh(self, element, shape): try: if hasattr(shape, "geometry"): diff --git a/src/blenderbim/blenderbim/bim/operator.py b/src/blenderbim/blenderbim/bim/operator.py index dbdea5c904..0e37e19ec5 100644 --- a/src/blenderbim/blenderbim/bim/operator.py +++ b/src/blenderbim/blenderbim/bim/operator.py @@ -1552,7 +1552,7 @@ class RefreshDrawingList(bpy.types.Operator): for obj in bpy.context.scene.objects: if not isinstance(obj.data, bpy.types.Camera): continue - if "IfcGroup/" in obj.name and obj.users_collection[0].name == obj.name: + if "IfcAnnotation/" in obj.name and obj.users_collection[0].name == obj.name: new = bpy.context.scene.DocProperties.drawings.add() new.name = obj.name.split("/")[1] new.camera = obj