From 1ac1b289c150c7fdb35780904a214c5466d82b37 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sat, 27 Jul 2024 19:53:45 +1000 Subject: [PATCH] Map coords always visualise using map units, visualise IFC local origin, and don't show blender coords if no blender offset --- .../bim/module/georeference/data.py | 16 +++- .../bim/module/georeference/decorator.py | 77 +++++++++++++++---- 2 files changed, 79 insertions(+), 14 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/georeference/data.py b/src/blenderbim/blenderbim/bim/module/georeference/data.py index ed9ba7102f..0ca923ea9c 100644 --- a/src/blenderbim/blenderbim/bim/module/georeference/data.py +++ b/src/blenderbim/blenderbim/bim/module/georeference/data.py @@ -44,6 +44,7 @@ class GeoreferenceData: cls.data["local_unit_symbol"] = cls.local_unit_symbol() cls.data["map_unit_symbol"] = cls.map_unit_symbol() cls.data["world_coordinate_system"] = cls.world_coordinate_system() + cls.data["local_origin"] = cls.local_origin() cls.is_loaded = True @classmethod @@ -165,7 +166,7 @@ class GeoreferenceData: props = bpy.context.scene.BIMGeoreferenceProperties if props.has_blender_offset: - blender_xyz = ifcopenshell.util.geolocation.xyz2enh( + blender_xyz = ifcopenshell.util.geolocation.enh2xyz( result["x"], result["y"], result["z"], @@ -186,3 +187,16 @@ class GeoreferenceData: wcs[2][3] *= unit_scale result["matrix"] = Matrix(wcs) return result + + @classmethod + def local_origin(cls): + props = bpy.context.scene.BIMGeoreferenceProperties + if not props.has_blender_offset: + return + unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) + x = float(props.blender_offset_x) * -1 + y = float(props.blender_offset_y) * -1 + z = float(props.blender_offset_z) * -1 + enh = ifcopenshell.util.geolocation.auto_xyz2enh(tool.Ifc.get(), 0, 0, 0) + xyz_si = Vector([x * unit_scale, y * unit_scale, z * unit_scale]) + return {"x": x, "y": y, "z": z, "enh": enh, "location": xyz_si} diff --git a/src/blenderbim/blenderbim/bim/module/georeference/decorator.py b/src/blenderbim/blenderbim/bim/module/georeference/decorator.py index 716812edf2..77950e0885 100644 --- a/src/blenderbim/blenderbim/bim/module/georeference/decorator.py +++ b/src/blenderbim/blenderbim/bim/module/georeference/decorator.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with BlenderBIM Add-on. If not, see . +import bpy import blf import gpu import bmesh @@ -61,6 +62,10 @@ class GeoreferenceDecorator: self.calculate_angles(context) props = context.scene.BIMGeoreferenceProperties e, n, h = [round(float(o), 7) for o in props.model_origin.split(",")] + if (operation := GeoreferenceData.data["coordinate_operation"]) and (scale := operation.get("Scale", None)): + e *= scale + n *= scale + h *= scale self.addon_prefs = tool.Blender.get_addon_preferences() @@ -71,10 +76,14 @@ class GeoreferenceDecorator: blf.enable(self.font_id, blf.SHADOW) blf.shadow(self.font_id, 6, 0, 0, 0, 1) - text = f"Blender Coordinates ({GeoreferenceData.data['local_unit_symbol']}) X: 0, Y: 0, Z: 0" + if props.has_blender_offset: + text = "Blender Origin" + text += f"\nBlender Coordinates ({GeoreferenceData.data['local_unit_symbol']}) X: 0, Y: 0, Z: 0" + else: + text = "IFC Local Origin" text += f"\nLocal Coordinates ({GeoreferenceData.data['local_unit_symbol']}) X: {props.blender_offset_x}, Y: {props.blender_offset_y}, Z: {props.blender_offset_z}" if GeoreferenceData.data["projected_crs"]: - text += f"\nMap Coordinates ({GeoreferenceData.data['local_unit_symbol']}) E: {e}, N: {n}, H: {h}" + text += f"\nMap Coordinates ({GeoreferenceData.data['map_unit_symbol']}) E: {e}, N: {n}, H: {h}" self.draw_text_at_position(context, text, Vector((0, -0.1, 0))) angle = Matrix.Rotation(radians(self.pn_angle), 4, "Z") @@ -109,7 +118,8 @@ class GeoreferenceDecorator: if (wcs := GeoreferenceData.data["world_coordinate_system"]) and ["has_transformation"]: text = "WCS" - text += f"\nBlender Coordinates ({GeoreferenceData.data['local_unit_symbol']}) X: {wcs['blender_x']}, Y: {wcs['blender_y']}, Z: {wcs['blender_z']}" + if props.has_blender_offset: + text += f"\nBlender Coordinates ({GeoreferenceData.data['local_unit_symbol']}) X: {wcs['blender_x']}, Y: {wcs['blender_y']}, Z: {wcs['blender_z']}" text += f"\nLocal Coordinates ({GeoreferenceData.data['local_unit_symbol']}) X: {wcs['x']}, Y: {wcs['y']}, Z: {wcs['z']}" if operation := GeoreferenceData.data["coordinate_operation"]: e = operation.get("Eastings") @@ -126,6 +136,22 @@ class GeoreferenceDecorator: self.draw_text_at_position(context, text, position) + if props.has_blender_offset: + text = "IFC Local Origin" + x = GeoreferenceData.data["local_origin"]["x"] + y = GeoreferenceData.data["local_origin"]["y"] + z = GeoreferenceData.data["local_origin"]["z"] + location = GeoreferenceData.data["local_origin"]["location"] + text += f"\nBlender Coordinates ({GeoreferenceData.data['local_unit_symbol']}) X: {x}, Y: {y}, Z: {z}" + text += f"\nLocal Coordinates ({GeoreferenceData.data['local_unit_symbol']}) X: 0, Y: 0, Z: 0" + if GeoreferenceData.data["projected_crs"]: + e, n, h = GeoreferenceData.data["local_origin"]["enh"] + text += f"\nMap Coordinates ({GeoreferenceData.data['map_unit_symbol']}) E: {e}, N: {n}, H: {h}" + if location.length > 1000: + location = location.normalized() * 3 + text += "\n(Warning: Actual XYZ Not Shown)" + self.draw_text_at_position(context, text, location) + def draw_text_at_position(self, context, text, position): coords_2d = location_3d_to_region_2d(context.region, context.region_data, position) if not coords_2d: @@ -256,24 +282,49 @@ class GeoreferenceDecorator: self.draw_batch("LINES", verts, decorator_color_special, edges) if (wcs := GeoreferenceData.data["world_coordinate_system"]) and ["has_transformation"]: - if wcs["blender_location"].length < 1000: verts = [Vector((0, 0, 0)), wcs["blender_location"]] edges = [[0, 1]] self.draw_batch("LINES", verts, decorator_color_special, edges) self.draw_batch("POINTS", verts[1:], decorator_color_special) else: + location = wcs["blender_location"].normalized() edges = [[0, 1]] - verts = [Vector((0, 0, 0)), wcs["blender_location"].normalized() * 3] + verts = [Vector((0, 0, 0)), location * 3] self.draw_batch("LINES", verts, decorator_color_special, edges) - verts = [wcs["blender_location"].normalized() * 3, wcs["blender_location"].normalized() * 3.1] - self.draw_batch("LINES", verts, decorator_color_error, edges) - verts = [wcs["blender_location"].normalized() * 3.12, wcs["blender_location"].normalized() * 3.2] - self.draw_batch("LINES", verts, decorator_color_error, edges) - verts = [wcs["blender_location"].normalized() * 3.22, wcs["blender_location"].normalized() * 3.3] - self.draw_batch("LINES", verts, decorator_color_error, edges) - verts = [wcs["blender_location"].normalized() * 3.32, wcs["blender_location"].normalized() * 3.4] - self.draw_batch("LINES", verts, decorator_color_error, edges) + self.draw_dashed_line(location * 3, location * 6, decorator_color_error) + + props = context.scene.BIMGeoreferenceProperties + if props.has_blender_offset: + location = GeoreferenceData.data["local_origin"]["location"] + if location.length < 1000: + verts = [Vector((0, 0, 0)), location] + edges = [[0, 1]] + self.draw_batch("LINES", verts, decorator_color_special, edges) + self.draw_batch("POINTS", verts[1:], decorator_color_special) + else: + location = location.normalized() + edges = [[0, 1]] + verts = [Vector((0, 0, 0)), location * 3] + self.draw_batch("LINES", verts, decorator_color_special, edges) + self.draw_dashed_line(location * 3, location * 6, decorator_color_error) + + def draw_dashed_line(self, start, end, colour): + direction = (end - start).normalized() + distance = (end - start).length + current_distance = Vector((0, 0, 0)) + gap = 0.05 * direction + dash = 0.1 * direction + points = [start] + while current_distance.length < distance: + points.append(start + current_distance + dash) + points.append(start + current_distance + dash + gap) + current_distance += gap + dash + points.pop() + + edges = [[i, i + 1] for i in range(0, len(points), 2)] + verts = points + self.draw_batch("LINES", verts, colour, edges) def calculate_angles(self, context): self.pn_angle = 0.0