You can now specify custom project norths when loading in models in absolute terms

This commit is contained in:
Dion Moult
2024-07-06 15:43:16 +10:00
parent accb1890dc
commit 95f71a2e2f
10 changed files with 55 additions and 34 deletions
@@ -1498,6 +1498,7 @@ class IfcImportSettings:
self.distance_limit = 1000
self.false_origin_mode = "AUTOMATIC"
self.false_origin = None
self.project_north = None
self.element_offset = 0
self.element_limit = 30000
self.has_filter = None
@@ -1533,6 +1534,10 @@ class IfcImportSettings:
settings.false_origin = [float(o) for o in props.false_origin.split(",")[:3]]
except:
settings.false_origin = [0, 0, 0]
try:
settings.project_north = float(props.project_north)
except:
settings.project_north = 0
settings.element_offset = props.element_offset
settings.element_limit = props.element_limit
return settings
@@ -35,7 +35,6 @@ class GeoreferenceData:
@classmethod
def load(cls):
cls.data["coordinate_operation_class"] = cls.coordinate_operation_class()
cls.data["blender_derived_angle"] = cls.blender_derived_angle()
cls.data["coordinate_operation"] = cls.coordinate_operation()
cls.data["map_derived_angle"] = cls.map_derived_angle()
cls.data["projected_crs"] = cls.projected_crs()
@@ -56,19 +55,6 @@ class GeoreferenceData:
version = tool.Ifc.get_schema()
return [(c, c, get_entity_doc(version, c).get("description", "")) for c in sorted(names)]
@classmethod
def blender_derived_angle(cls):
props = bpy.context.scene.BIMGeoreferenceProperties
if props.has_blender_offset:
return str(
round(
ifcopenshell.util.geolocation.xaxis2angle(
float(props.blender_x_axis_abscissa), float(props.blender_x_axis_ordinate)
),
3,
)
)
@classmethod
def coordinate_operation(cls):
if tool.Ifc.get_schema() == "IFC2X3":
@@ -119,11 +119,12 @@ class BIMGeoreferenceProperties(PropertyGroup):
blender_eastings: StringProperty(name="Blender Eastings", default="0")
blender_northings: StringProperty(name="Blender Northings", default="0")
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_project_north: StringProperty(name="Blender Angle to Grid North", 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")
blender_x_axis_abscissa: StringProperty(name="Blender X Axis Abscissa", default="1")
blender_x_axis_ordinate: StringProperty(name="Blender X Axis Ordinate", default="0")
true_north_angle: StringProperty(name="True North Angle", update=update_true_north_angle)
true_north_abscissa: StringProperty(name="True North Abscissa", update=update_true_north_vector)
true_north_ordinate: StringProperty(name="True North Ordinate", update=update_true_north_vector)
@@ -92,7 +92,7 @@ class BIM_PT_gis(Panel):
if props.has_blender_offset:
row = self.layout.row()
row.label(text="Blender Session Origin", icon="TRACKING_REFINE_FORWARDS")
row.label(text="Blender Session Coordinates", icon="TRACKING_REFINE_FORWARDS")
row = self.layout.row(align=True)
row.label(text=f"Eastings ({GeoreferenceData.data['local_unit_symbol']})")
@@ -104,14 +104,8 @@ class BIM_PT_gis(Panel):
row.label(text=f"OrthogonalHeight ({GeoreferenceData.data['local_unit_symbol']})")
row.label(text=props.blender_orthogonal_height)
row = self.layout.row(align=True)
row.label(text="XAxisAbscissa")
row.label(text=props.blender_x_axis_abscissa)
row = self.layout.row(align=True)
row.label(text="XAxisOrdinate")
row.label(text=props.blender_x_axis_ordinate)
row = self.layout.row(align=True)
row.label(text="Derived Grid North")
row.label(text=GeoreferenceData.data["blender_derived_angle"])
row.label(text="Angle to Grid North")
row.label(text=props.blender_project_north)
if GeoreferenceData.data["projected_crs"]:
row = self.layout.row(align=True)
@@ -144,7 +138,7 @@ class BIM_PT_gis(Panel):
row.label(text=str(value))
if key == "XAxisOrdinate":
row = self.layout.row(align=True)
row.label(text="Derived Angle")
row.label(text="*Angle to Grid North")
row.label(text=GeoreferenceData.data["map_derived_angle"])
@@ -195,7 +189,7 @@ class BIM_PT_gis_true_north(Panel):
row.operator("bim.enable_editing_true_north", icon="GREASEPENCIL", text="")
row.operator("bim.remove_true_north", icon="X", text="")
row = self.layout.row(align=True)
row.label(text="Derived Angle")
row.label(text="*Angle to True North")
row.label(text=GeoreferenceData.data["true_derived_angle"])
else:
row = self.layout.row(align=True)
@@ -918,6 +918,8 @@ class LinkIfc(bpy.types.Operator):
if pprops.false_origin_mode == "MANUAL":
row = self.layout.row()
row.prop(pprops, "false_origin")
row = self.layout.row()
row.prop(pprops, "project_north")
def execute(self, context):
start = time.time()
@@ -1071,6 +1073,7 @@ def run():
pprops.distance_limit = {pprops.distance_limit}
pprops.false_origin_mode = "{pprops.false_origin_mode}"
pprops.false_origin = "{pprops.false_origin}"
pprops.project_north = "{pprops.project_north}"
bpy.ops.bim.load_linked_project(filepath="{self.filepath}")
bpy.ops.wm.save_as_mainfile(filepath="{blend_filepath}")
@@ -1413,6 +1416,7 @@ class LoadLinkedProject(bpy.types.Operator):
"distance_limit": pprops.distance_limit,
"false_origin_mode": pprops.false_origin_mode,
"false_origin": pprops.false_origin,
"project_north": pprops.project_north,
}
with open(self.json_filepath, "w") as f:
json.dump(data, f)
@@ -171,6 +171,11 @@ class BIMProjectProperties(PropertyGroup):
description="False origin in project units that the Blender origin will correlate to",
default="0,0,0",
)
project_north: StringProperty(
name="Angle to Grid North",
description="The angle (postive is anticlockwise) pointing to grid north relative to project north",
default="0",
)
element_offset: IntProperty(name="Element Offset", default=0)
element_limit: IntProperty(name="Element Offset", default=30000)
should_disable_undo_on_save: BoolProperty(
@@ -175,6 +175,8 @@ class BIM_PT_project(Panel):
if pprops.false_origin_mode == "MANUAL":
row = self.layout.row()
row.prop(pprops, "false_origin")
row = self.layout.row()
row.prop(pprops, "project_north")
row = self.layout.row()
row.label(text="Element Range")
@@ -91,7 +91,7 @@ class Georeference(blenderbim.core.tool.Georeference):
elif name == "XAxisAbscissa":
props = bpy.context.scene.BIMGeoreferenceProperties
props.is_changing_angle = True
if data["XAxisAbscissa"] is None or data["XAxisOrdinate"]:
if data["XAxisAbscissa"] is None or data["XAxisOrdinate"] is None:
props.x_axis_is_null = True
else:
props.grid_north_angle = str(
+26 -5
View File
@@ -568,15 +568,36 @@ class Loader(blenderbim.core.tool.Loader):
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:
has_offset = not np.allclose(model_offset, zero_origin)
parameters = ifcopenshell.util.geolocation.get_helmert_transformation_parameters(ifc_file)
model_north = ifcopenshell.util.geolocation.xaxis2angle(parameters.xaa, parameters.xao)
project_north = cls.settings.project_north
model_rotation = project_north - model_north
if model_rotation > 180:
model_rotation = (360 - model_rotation) * -1
elif model_rotation < -180:
model_rotation = (model_rotation * -1) - 360
has_rotation = not np.isclose(model_north, project_north)
if not has_offset:
model_offset = false_origin = (0, 0, 0)
if not has_rotation:
project_north = 0
if has_offset or has_rotation:
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.blender_project_north = str(project_north)
props.blender_offset_x = str(model_offset[0])
props.blender_offset_y = str(model_offset[1])
props.blender_offset_z = str(model_offset[2])
xaa, xao = ifcopenshell.util.geolocation.angle2xaxis(model_rotation)
props.blender_x_axis_abscissa = str(xaa)
props.blender_x_axis_ordinate = str(xao)
props.has_blender_offset = True
@classmethod
@@ -543,7 +543,9 @@ def xaxis2angle(x: float, y: float) -> float:
the page?". See the diagram on the IfcGeometricRepresentationContext
documentation for clarification.
The angle indicates "how do I rotate grid east to get to project east?".
The angle indicates "how do I rotate project east to get to grid east?".
Alternatively: "how do I rotate project north to get to grid north?".
Positive angles are anticlockwise.
:param x: The X axis abscissa
:param y: The X axis ordinate
@@ -562,6 +564,7 @@ def yaxis2angle(x: float, y: float) -> float:
documentation for clarification.
The angle indicates "how do I rotate project north to get to true north?".
Positive angles are anticlockwise.
:param x: The Y axis abscissa
:param y: The Y axis ordinate