False origin is always in terms of map coordinates, not as an offset.

Previously, the false origin would be in terms of local coordinates. This means that the same false origin would give two different results on files with different map conversions. Now, false origin is ... well, a true map coordinate and works equally for both IFCs with and without a map conversion.
This commit is contained in:
Dion Moult
2024-06-16 22:28:48 +10:00
parent 99f329c13d
commit 743a197542
4 changed files with 38 additions and 28 deletions
+4 -4
View File
@@ -539,7 +539,7 @@ class IfcImporter:
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()
return tool.Loader.set_manual_blender_offset(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:
@@ -569,9 +569,9 @@ class IfcImporter:
obj.BIMObjectProperties.blender_offset_type = "OBJECT_PLACEMENT"
matrix = ifcopenshell.util.geolocation.global2local(
matrix,
float(props.blender_eastings) * self.unit_scale,
float(props.blender_northings) * self.unit_scale,
float(props.blender_orthogonal_height) * self.unit_scale,
float(props.blender_offset_x) * self.unit_scale,
float(props.blender_offset_y) * self.unit_scale,
float(props.blender_offset_z) * self.unit_scale,
float(props.blender_x_axis_abscissa),
float(props.blender_x_axis_ordinate),
)
@@ -17,7 +17,7 @@
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
from blenderbim.bim.prop import StrProperty, Attribute
from blenderbim.bim.prop import Attribute
from bpy.types import PropertyGroup
from bpy.props import (
PointerProperty,
@@ -49,6 +49,9 @@ class BIMGeoreferenceProperties(PropertyGroup):
blender_orthogonal_height: StringProperty(name="Blender Orthogonal Height", default="0")
blender_x_axis_abscissa: StringProperty(name="Blender X Axis Abscissa", default="1")
blender_x_axis_ordinate: StringProperty(name="Blender X Axis Ordinate", default="0")
blender_offset_x: StringProperty(name="Blender Offset X", default="0")
blender_offset_y: StringProperty(name="Blender Offset Y", default="0")
blender_offset_z: StringProperty(name="Blender Offset Z", default="0")
has_true_north: BoolProperty(name="Has True North", default=True)
true_north_abscissa: StringProperty(name="True North Abscissa")
true_north_ordinate: StringProperty(name="True North Ordinate")
@@ -90,7 +90,7 @@ class BIM_PT_gis(Panel):
if props.has_blender_offset:
row = self.layout.row()
row.label(text="Blender Offset", icon="TRACKING_REFINE_FORWARDS")
row.label(text="Blender Session Origin", icon="TRACKING_REFINE_FORWARDS")
row = self.layout.row(align=True)
row.label(text="Eastings")
+29 -22
View File
@@ -555,24 +555,33 @@ class Loader(blenderbim.core.tool.Loader):
return results
@classmethod
def set_manual_blender_offset(cls) -> None:
props = bpy.context.scene.BIMGeoreferenceProperties
props.blender_eastings = str(cls.settings.false_origin[0])
props.blender_northings = str(cls.settings.false_origin[1])
props.blender_orthogonal_height = str(cls.settings.false_origin[2])
props.has_blender_offset = True
def set_manual_blender_offset(cls, ifc_file: ifcopenshell.file) -> None:
model_origin = np.array(ifcopenshell.util.geolocation.auto_xyz2enh(ifc_file, 0, 0, 0))
false_origin = np.array(cls.settings.false_origin)
model_offset = false_origin - model_origin
zero_origin = np.array((0, 0, 0))
has_model_offset = not np.allclose(model_offset, zero_origin)
if has_model_offset:
props = bpy.context.scene.BIMGeoreferenceProperties
props.blender_offset_x = str(model_offset[0])
props.blender_offset_y = str(model_offset[1])
props.blender_offset_z = str(model_offset[2])
props.blender_eastings = str(false_origin[0])
props.blender_northings = str(false_origin[1])
props.blender_orthogonal_height = str(false_origin[2])
props.has_blender_offset = True
@classmethod
def guess_false_origin_and_project_north(cls, element: ifcopenshell.entity_instance) -> None:
def guess_false_origin_and_project_north(cls, ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) -> None:
if not element.ObjectPlacement or not element.ObjectPlacement.is_a("IfcLocalPlacement"):
return
placement = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement)
offset_point = [placement[0][3], placement[1][3], placement[2][3]]
cls.settings.false_origin = ifcopenshell.util.geolocation.auto_xyz2enh(ifc_file, *offset_point)
cls.set_manual_blender_offset(ifc_file)
props = bpy.context.scene.BIMGeoreferenceProperties
props.blender_eastings = str(placement[0][3])
props.blender_northings = str(placement[1][3])
props.blender_orthogonal_height = str(placement[2][3])
x_axis = mathutils.Vector(placement[:, 0][0:3])
default_x_axis = mathutils.Vector((1, 0, 0))
x_axis = Vector(placement[:, 0][0:3])
default_x_axis = Vector((1, 0, 0))
if (default_x_axis - x_axis).length > 0.01:
props.blender_x_axis_abscissa = str(placement[0][0])
props.blender_x_axis_ordinate = str(placement[1][0])
@@ -622,9 +631,10 @@ class Loader(blenderbim.core.tool.Loader):
elements_checked += 1
mat = ifcopenshell.util.shape.get_shape_matrix(shape)
point = mat @ np.array((shape.geometry.verts[0], shape.geometry.verts[1], shape.geometry.verts[2], 1.0))
point = point / cls.unit_scale
if cls.is_point_far_away(point, is_meters=False):
return point
if cls.is_point_far_away(point, is_meters=True):
# Arbitrary origins should be to the nearest millimeter.
# Anything more precise is just ridiculous from a practical surveying perspective.
return [round(float(p), 3) / cls.unit_scale for p in point[:3]]
@classmethod
def guess_false_origin_from_elements(cls, ifc_file: ifcopenshell.file) -> None:
@@ -635,11 +645,8 @@ class Loader(blenderbim.core.tool.Loader):
offset_point = cls.get_offset_point(ifc_file)
if offset_point is None:
return
props = bpy.context.scene.BIMGeoreferenceProperties
props.blender_eastings = str(offset_point[0])
props.blender_northings = str(offset_point[1])
props.blender_orthogonal_height = str(offset_point[2])
props.has_blender_offset = True
cls.settings.false_origin = ifcopenshell.util.geolocation.auto_xyz2enh(ifc_file, *offset_point)
cls.set_manual_blender_offset(ifc_file)
@classmethod
def guess_false_origin(cls, ifc_file: ifcopenshell.file) -> None:
@@ -649,8 +656,8 @@ class Loader(blenderbim.core.tool.Loader):
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)
return cls.guess_false_origin_and_project_north(ifc_file, 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_and_project_north(ifc_file, building)
return cls.guess_false_origin_from_elements(ifc_file)