From 348ef4023fe1cced2ecd2303acddbb1080fbe194 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 16 Jun 2024 14:50:33 +1000 Subject: [PATCH] False origins can now be explicitly auto, manual, or disabled --- src/blenderbim/blenderbim/bim/import_ifc.py | 31 ++++++------------- .../blenderbim/bim/module/project/prop.py | 19 +++++++++--- .../blenderbim/bim/module/project/ui.py | 5 ++- src/blenderbim/blenderbim/tool/loader.py | 14 +++++++++ 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 9289c94816..6e955cfaef 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -17,16 +17,12 @@ # along with BlenderBIM Add-on. If not, see . from __future__ import annotations -import os -import re import bpy import time import json -import bmesh import logging import mathutils import numpy as np -import numpy.typing as npt import multiprocessing import ifcopenshell import ifcopenshell.geom @@ -37,8 +33,6 @@ import ifcopenshell.util.placement import ifcopenshell.util.representation import ifcopenshell.util.shape import blenderbim.tool as tool -import blenderbim.core.spatial -import ifcopenshell.ifcopenshell_wrapper as ifcopenshell_wrapper from itertools import chain, accumulate from blenderbim.bim.ifc import IfcStore, IFC_CONNECTED_TYPE from blenderbim.tool.loader import OBJECT_DATA_TYPE @@ -542,19 +536,11 @@ class IfcImporter: props = bpy.context.scene.BIMGeoreferenceProperties if props.has_blender_offset: return - if self.ifc_import_settings.false_origin: + elif self.ifc_import_settings.false_origin_mode == "DISABLED": + return + elif self.ifc_import_settings.false_origin_mode == "MANUAL": return tool.Loader.set_manual_blender_offset() - if self.file.schema == "IFC2X3": - project = self.file.by_type("IfcProject")[0] - else: - project = self.file.by_type("IfcContext")[0] - site = tool.Loader.find_decomposed_ifc_class(project, "IfcSite") - if site and tool.Loader.is_element_far_away(site): - return tool.Loader.guess_false_origin_and_project_north(site) - building = tool.Loader.find_decomposed_ifc_class(project, "IfcBuilding") - if building and tool.Loader.is_element_far_away(building): - return tool.Loader.guess_false_origin_and_project_north(building) - return tool.Loader.guess_false_origin_from_elements(self.file) + return tool.Loader.guess_false_origin(self.file) def apply_blender_offset_to_matrix_world(self, obj: bpy.types.Object, matrix: np.ndarray) -> mathutils.Matrix: props = bpy.context.scene.BIMGeoreferenceProperties @@ -1560,6 +1546,7 @@ class IfcImportSettings: # Locations greater than 1km are not considered "small sites" according to the georeferencing guide # Users can configure this if they have to handle larger sites but beware of surveying precision self.distance_limit = 1000 + self.false_origin_mode = "AUTOMATIC" self.false_origin = None self.element_offset = 0 self.element_limit = 30000 @@ -1591,9 +1578,11 @@ class IfcImportSettings: settings.angular_tolerance = props.angular_tolerance settings.void_limit = props.void_limit settings.distance_limit = props.distance_limit - settings.false_origin = [float(o) for o in props.false_origin.split(",")] if props.false_origin else None - if settings.false_origin == [0, 0, 0]: - settings.false_origin = None + settings.false_origin_mode = props.false_origin_mode + try: + settings.false_origin = [float(o) for o in props.false_origin.split(",")[:3]] + except: + settings.false_origin = [0, 0, 0] settings.element_offset = props.element_offset settings.element_limit = props.element_limit return settings diff --git a/src/blenderbim/blenderbim/bim/module/project/prop.py b/src/blenderbim/blenderbim/bim/module/project/prop.py index a971878c59..4669c9426f 100644 --- a/src/blenderbim/blenderbim/bim/module/project/prop.py +++ b/src/blenderbim/blenderbim/bim/module/project/prop.py @@ -153,13 +153,22 @@ class BIMProjectProperties(PropertyGroup): angular_tolerance: FloatProperty(name="Angular Tolerance", default=0.5) void_limit: IntProperty(name="Void Limit", default=30) distance_limit: FloatProperty(name="Distance Limit", default=1000, subtype="DISTANCE") + false_origin_mode: bpy.props.EnumProperty( + items=[ + ( + "AUTOMATIC", + "Automatic", + "An automatic false origin will be detected from geometry with large coordinates", + ), + ("MANUAL", "Manual", "You can specify the false origin coordinates"), + ("DISABLED", "Disabled", "The model in original local coordinates will be shown as is"), + ], + name="False Origin Mode", + default="AUTOMATIC", + ) false_origin: StringProperty( name="False Origin", - description=( - "False origin that will be used to offset the entire model.\n" - "(0,0,0) value is interpreted as an unset false origin - false origin will be guessed based on Distance Limit.\n" - "False origin is defined in project units" - ), + description="False origin in project units that the Blender origin will correlate to", default="0,0,0", ) element_offset: IntProperty(name="Element Offset", default=0) diff --git a/src/blenderbim/blenderbim/bim/module/project/ui.py b/src/blenderbim/blenderbim/bim/module/project/ui.py index 4c56ea92a5..27855b8984 100644 --- a/src/blenderbim/blenderbim/bim/module/project/ui.py +++ b/src/blenderbim/blenderbim/bim/module/project/ui.py @@ -145,7 +145,10 @@ class BIM_PT_project(Panel): row = self.layout.row() row.prop(pprops, "distance_limit") row = self.layout.row() - row.prop(pprops, "false_origin") + row.prop(pprops, "false_origin_mode") + if pprops.false_origin_mode == "MANUAL": + row = self.layout.row() + row.prop(pprops, "false_origin") row = self.layout.row() row.label(text="Element Range") diff --git a/src/blenderbim/blenderbim/tool/loader.py b/src/blenderbim/blenderbim/tool/loader.py index 8dc80c5150..584e300dc3 100644 --- a/src/blenderbim/blenderbim/tool/loader.py +++ b/src/blenderbim/blenderbim/tool/loader.py @@ -665,3 +665,17 @@ class Loader(blenderbim.core.tool.Loader): props.blender_northings = str(offset_point[1]) props.blender_orthogonal_height = str(offset_point[2]) props.has_blender_offset = True + + @classmethod + def guess_false_origin(cls, ifc_file: ifcopenshell.file) -> None: + if ifc_file.schema == "IFC2X3": + project = ifc_file.by_type("IfcProject")[0] + else: + project = ifc_file.by_type("IfcContext")[0] + site = cls.find_decomposed_ifc_class(project, "IfcSite") + if site and cls.is_element_far_away(site): + return cls.guess_false_origin_and_project_north(site) + building = cls.find_decomposed_ifc_class(project, "IfcBuilding") + if building and cls.is_element_far_away(building): + return cls.guess_false_origin_and_project_north(building) + return cls.guess_false_origin_from_elements(ifc_file)