diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index 76299f4500..b868a7feb1 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -158,6 +158,7 @@ if bpy is not None: operator.RemoveIfcFile, operator.SelectDocIfcFile, operator.AddAnnotation, + operator.GenerateReferences, operator.ResizeText, operator.AddVariable, operator.RemoveVariable, diff --git a/src/ifcblenderexport/blenderbim/bim/annotation.py b/src/ifcblenderexport/blenderbim/bim/annotation.py index 45f1c0b659..afeec657d3 100644 --- a/src/ifcblenderexport/blenderbim/bim/annotation.py +++ b/src/ifcblenderexport/blenderbim/bim/annotation.py @@ -56,8 +56,11 @@ class Annotator: text_obj.data.size = font_size @staticmethod - def add_line_to_annotation(obj): - co1, co2 = Annotator.get_placeholder_coords() + def add_line_to_annotation(obj, co1=None, co2=None): + if co1 is None: + co1, co2 = Annotator.get_placeholder_coords() + co1 = obj.matrix_world.inverted() @ co1 + co2 = obj.matrix_world.inverted() @ co2 if isinstance(obj.data, bpy.types.Mesh): obj.data.vertices.add(2) obj.data.vertices[-2].co = co1 diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index 960200ac9d..80ac851be8 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -22,7 +22,7 @@ from . import annotation from . import helper from bpy_extras.io_utils import ImportHelper from itertools import cycle -from mathutils import Vector, Matrix, Euler +from mathutils import Vector, Matrix, Euler, geometry from math import radians, atan, tan, cos, sin, atan2 from pathlib import Path from bpy.app.handlers import persistent @@ -3088,6 +3088,71 @@ class AddAnnotation(bpy.types.Operator): return {'FINISHED'} +class GenerateReferences(bpy.types.Operator): + bl_idname = 'bim.generate_references' + bl_label = 'Generate References' + + def execute(self, context): + self.camera = bpy.context.scene.camera + self.filter_potential_references() + if self.camera.data.BIMCameraProperties.target_view == 'PLAN_VIEW': + self.generate_grids() + if self.camera.data.BIMCameraProperties.target_view == 'ELEVATION_VIEW': + self.generate_grids() + self.generate_levels() + if self.camera.data.BIMCameraProperties.target_view == 'SECTION_VIEW': + self.generate_grids() + self.generate_levels() + return {'FINISHED'} + + def filter_potential_references(self): + for name in ['grids', 'levels']: + setattr(self, name, []) + for obj in bpy.data.objects: + if 'IfcGridAxis/' in obj.name: + self.grids.append(obj) + if 'IfcBuildingStorey/' in obj.name: + self.levels.append(obj) + + def generate_grids(self): + # TODO + pass + + def generate_levels(self): + if self.camera.data.BIMCameraProperties.raster_x > self.camera.data.BIMCameraProperties.raster_y: + width = self.camera.data.ortho_scale + height = width / self.camera.data.BIMCameraProperties.raster_x * self.camera.data.BIMCameraProperties.raster_y + else: + height = self.camera.data.ortho_scale + width = height / self.camera.data.BIMCameraProperties.raster_y * self.camera.data.BIMCameraProperties.raster_x + level_obj = annotation.Annotator.get_annotation_obj('Section Level', 'curve') + + width_in_mm = width * 1000 + if self.camera.data.BIMCameraProperties.diagram_scale == 'CUSTOM': + human_scale, fraction = self.camera.data.BIMCameraProperties.custom_diagram_scale.split('|') + else: + human_scale, fraction = self.camera.data.BIMCameraProperties.diagram_scale.split('|') + numerator, denominator = fraction.split('/') + scale = float(numerator) / float(denominator) + real_world_width_in_mm = width_in_mm * scale + offset_in_mm = 20 + offset_percentage = offset_in_mm / real_world_width_in_mm + + for obj in self.levels: + projection = self.project_point_onto_camera(obj.location) + co1 = self.camera.matrix_world @ Vector((width/2-(offset_percentage * width), projection[1], -1)) + co2 = self.camera.matrix_world @ Vector((-(width/2), projection[1], -1)) + annotation.Annotator.add_line_to_annotation(level_obj, co1, co2) + + def project_point_onto_camera(self, point): + projection = self.camera.matrix_world.to_quaternion() @ Vector((0, 0, -1)) + return self.camera.matrix_world.inverted() @ geometry.intersect_line_plane( + point.xyz, + point.xyz-projection, + self.camera.location, + projection) + + class ResizeText(bpy.types.Operator): bl_idname = 'bim.resize_text' bl_label = 'Resize Text' diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 39f03651a9..301652607f 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -865,6 +865,8 @@ class BIM_PT_camera(Panel): row = layout.row() row.prop(props, 'is_nts') + row = layout.row() + row.operator('bim.generate_references') row = layout.row() row.operator('bim.resize_text')