mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-27 18:57:17 +00:00
Georeference UI now lets you edit either a decimal degrees angle or an abscissa ordinate and calculates on the fly
Seriously no normal person uses abscissa and ordinate
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
import ifcopenshell.util.geolocation
|
||||||
from blenderbim.bim.prop import Attribute
|
from blenderbim.bim.prop import Attribute
|
||||||
from bpy.types import PropertyGroup
|
from bpy.types import PropertyGroup
|
||||||
from bpy.props import (
|
from bpy.props import (
|
||||||
@@ -38,10 +39,65 @@ def get_coordinate_operation_class(self, context):
|
|||||||
return GeoreferenceData.data["coordinate_operation_class"]
|
return GeoreferenceData.data["coordinate_operation_class"]
|
||||||
|
|
||||||
|
|
||||||
|
def update_true_north_angle(self, context):
|
||||||
|
if self.is_changing_angle:
|
||||||
|
return
|
||||||
|
self.is_changing_angle = True
|
||||||
|
try:
|
||||||
|
x, y = ifcopenshell.util.geolocation.angle2yaxis(float(self.true_north_angle))
|
||||||
|
self.true_north_abscissa = str(x)
|
||||||
|
self.true_north_ordinate = str(y)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
self.is_changing_angle = False
|
||||||
|
|
||||||
|
|
||||||
|
def update_true_north_vector(self, context):
|
||||||
|
if self.is_changing_angle:
|
||||||
|
return
|
||||||
|
self.is_changing_angle = True
|
||||||
|
try:
|
||||||
|
x = float(self.true_north_abscissa)
|
||||||
|
y = float(self.true_north_ordinate)
|
||||||
|
self.true_north_angle = str(round(ifcopenshell.util.geolocation.yaxis2angle(x, y), 7))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
self.is_changing_angle = False
|
||||||
|
|
||||||
|
|
||||||
|
def update_grid_north_angle(self, context):
|
||||||
|
if self.is_changing_angle:
|
||||||
|
return
|
||||||
|
self.is_changing_angle = True
|
||||||
|
try:
|
||||||
|
x, y = ifcopenshell.util.geolocation.angle2xaxis(float(self.grid_north_angle))
|
||||||
|
self.x_axis_abscissa = str(x)
|
||||||
|
self.x_axis_ordinate = str(y)
|
||||||
|
self.x_axis_is_null = False
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
self.is_changing_angle = False
|
||||||
|
|
||||||
|
|
||||||
|
def update_grid_north_vector(self, context):
|
||||||
|
if self.is_changing_angle:
|
||||||
|
return
|
||||||
|
self.is_changing_angle = True
|
||||||
|
try:
|
||||||
|
x = float(self.x_axis_abscissa)
|
||||||
|
y = float(self.x_axis_ordinate)
|
||||||
|
self.grid_north_angle = str(round(ifcopenshell.util.geolocation.xaxis2angle(x, y), 7))
|
||||||
|
self.x_axis_is_null = False
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
self.is_changing_angle = False
|
||||||
|
|
||||||
|
|
||||||
class BIMGeoreferenceProperties(PropertyGroup):
|
class BIMGeoreferenceProperties(PropertyGroup):
|
||||||
coordinate_operation_class: bpy.props.EnumProperty(
|
coordinate_operation_class: bpy.props.EnumProperty(
|
||||||
items=get_coordinate_operation_class, name="Coordinate Operation Class"
|
items=get_coordinate_operation_class, name="Coordinate Operation Class"
|
||||||
)
|
)
|
||||||
|
is_changing_angle: BoolProperty(name="Is Changing Angle", default=False)
|
||||||
is_editing: BoolProperty(name="Is Editing")
|
is_editing: BoolProperty(name="Is Editing")
|
||||||
is_editing_wcs: BoolProperty(name="Is Editing WCS")
|
is_editing_wcs: BoolProperty(name="Is Editing WCS")
|
||||||
is_editing_true_north: BoolProperty(name="Is Editing True North")
|
is_editing_true_north: BoolProperty(name="Is Editing True North")
|
||||||
@@ -53,24 +109,10 @@ class BIMGeoreferenceProperties(PropertyGroup):
|
|||||||
map_coordinates: StringProperty(
|
map_coordinates: StringProperty(
|
||||||
name="Map Coordinates", description='Formatted "x,y,z" (without quotes)', default="0,0,0"
|
name="Map Coordinates", description='Formatted "x,y,z" (without quotes)', default="0,0,0"
|
||||||
)
|
)
|
||||||
angle_degree_input_x: FloatProperty(name="Angle Degree Input", description="Angle (in degrees) rel to Easting")
|
grid_north_angle: StringProperty(name="Grid North Angle", update=update_grid_north_angle)
|
||||||
angle_degree_input_y: FloatProperty(name="Angle Degree Input", description="Angle (in degrees) rel to +Y")
|
x_axis_abscissa: StringProperty(name="X Axis Abscissa", update=update_grid_north_vector)
|
||||||
x_axis_abscissa_output: StringProperty(
|
x_axis_ordinate: StringProperty(name="X Axis Ordinate", update=update_grid_north_vector)
|
||||||
name="X Axis Abscissa Ordinate Output",
|
x_axis_is_null: BoolProperty(name="X Axis Is Null")
|
||||||
description="X axis abscissa and ordinate",
|
|
||||||
)
|
|
||||||
x_axis_ordinate_output: StringProperty(
|
|
||||||
name="X Axis Abscissa Ordinate Output",
|
|
||||||
description="X axis abscissa and ordinate",
|
|
||||||
)
|
|
||||||
y_axis_abscissa_output: StringProperty(
|
|
||||||
name="Y Axis Abscissa Ordinate Output",
|
|
||||||
description="Y axis abscissa and ordinate",
|
|
||||||
)
|
|
||||||
y_axis_ordinate_output: StringProperty(
|
|
||||||
name="Y Axis Abscissa Ordinate Output",
|
|
||||||
description="Y axis abscissa and ordinate",
|
|
||||||
)
|
|
||||||
host_model_origin: StringProperty(name="Host Model Origin")
|
host_model_origin: StringProperty(name="Host Model Origin")
|
||||||
model_origin: StringProperty(name="Model Origin")
|
model_origin: StringProperty(name="Model Origin")
|
||||||
has_blender_offset: BoolProperty(name="Has Blender Offset")
|
has_blender_offset: BoolProperty(name="Has Blender Offset")
|
||||||
@@ -82,8 +124,9 @@ class BIMGeoreferenceProperties(PropertyGroup):
|
|||||||
blender_offset_x: StringProperty(name="Blender Offset X", default="0")
|
blender_offset_x: StringProperty(name="Blender Offset X", default="0")
|
||||||
blender_offset_y: StringProperty(name="Blender Offset Y", default="0")
|
blender_offset_y: StringProperty(name="Blender Offset Y", default="0")
|
||||||
blender_offset_z: StringProperty(name="Blender Offset Z", default="0")
|
blender_offset_z: StringProperty(name="Blender Offset Z", default="0")
|
||||||
true_north_abscissa: StringProperty(name="True North Abscissa")
|
true_north_angle: StringProperty(name="True North Angle", update=update_true_north_angle)
|
||||||
true_north_ordinate: StringProperty(name="True North Ordinate")
|
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)
|
||||||
wcs_x: StringProperty(name="WCS X", default="0")
|
wcs_x: StringProperty(name="WCS X", default="0")
|
||||||
wcs_y: StringProperty(name="WCS Y", default="0")
|
wcs_y: StringProperty(name="WCS Y", default="0")
|
||||||
wcs_z: StringProperty(name="WCS Z", default="0")
|
wcs_z: StringProperty(name="WCS Z", default="0")
|
||||||
|
|||||||
@@ -57,11 +57,23 @@ class BIM_PT_gis(Panel):
|
|||||||
row.label(text="Coordinate Operation", icon="GRID")
|
row.label(text="Coordinate Operation", icon="GRID")
|
||||||
|
|
||||||
for attribute in props.coordinate_operation:
|
for attribute in props.coordinate_operation:
|
||||||
if attribute.name == "Scale" and hasattr(context.scene, "sun_pos_properties"):
|
if attribute.name == "XAxisAbscissa":
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.operator("bim.set_ifc_grid_north", text="Set IFC North")
|
row.prop(props, "grid_north_angle", text="Angle")
|
||||||
row.operator("bim.set_blender_grid_north", text="Set Blender North")
|
row.prop(props, "x_axis_is_null", icon="RADIOBUT_OFF" if props.x_axis_is_null else "RADIOBUT_ON", text="")
|
||||||
draw_attribute(attribute, self.layout.row())
|
row = self.layout.row(align=True)
|
||||||
|
row.prop(props, "x_axis_abscissa", text="XAxis Abscissa")
|
||||||
|
row.prop(props, "x_axis_is_null", icon="RADIOBUT_OFF" if props.x_axis_is_null else "RADIOBUT_ON", text="")
|
||||||
|
elif attribute.name == "XAxisOrdinate":
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.prop(props, "x_axis_ordinate", text="XAxis Ordinate")
|
||||||
|
row.prop(props, "x_axis_is_null", icon="RADIOBUT_OFF" if props.x_axis_is_null else "RADIOBUT_ON", text="")
|
||||||
|
if hasattr(context.scene, "sun_pos_properties"):
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.operator("bim.set_ifc_grid_north", text="Set IFC North")
|
||||||
|
row.operator("bim.set_blender_grid_north", text="Set Blender North")
|
||||||
|
else:
|
||||||
|
draw_attribute(attribute, self.layout.row())
|
||||||
|
|
||||||
def draw_ui(self, context):
|
def draw_ui(self, context):
|
||||||
props = context.scene.BIMGeoreferenceProperties
|
props = context.scene.BIMGeoreferenceProperties
|
||||||
@@ -158,9 +170,11 @@ class BIM_PT_gis_true_north(Panel):
|
|||||||
|
|
||||||
def draw_editable_ui(self, context):
|
def draw_editable_ui(self, context):
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
row.prop(self.props, "true_north_abscissa")
|
row.prop(self.props, "true_north_angle", text="Angle")
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
row.prop(self.props, "true_north_ordinate")
|
row.prop(self.props, "true_north_abscissa", text="Abscissa")
|
||||||
|
row = self.layout.row()
|
||||||
|
row.prop(self.props, "true_north_ordinate", text="Ordinate")
|
||||||
if hasattr(context.scene, "sun_pos_properties"):
|
if hasattr(context.scene, "sun_pos_properties"):
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.operator("bim.set_ifc_true_north", text="Set IFC North")
|
row.operator("bim.set_ifc_true_north", text="Set IFC North")
|
||||||
@@ -173,8 +187,11 @@ class BIM_PT_gis_true_north(Panel):
|
|||||||
def draw_ui(self):
|
def draw_ui(self):
|
||||||
if GeoreferenceData.data["true_north"]:
|
if GeoreferenceData.data["true_north"]:
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.label(text="Vector")
|
row.label(text="Abscissa")
|
||||||
row.label(text=str(GeoreferenceData.data["true_north"][0:2])[1:-1])
|
row.label(text=str(GeoreferenceData.data["true_north"][0]))
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.label(text="Ordinate")
|
||||||
|
row.label(text=str(GeoreferenceData.data["true_north"][1]))
|
||||||
row.operator("bim.enable_editing_true_north", icon="GREASEPENCIL", text="")
|
row.operator("bim.enable_editing_true_north", icon="GREASEPENCIL", text="")
|
||||||
row.operator("bim.remove_true_north", icon="X", text="")
|
row.operator("bim.remove_true_north", icon="X", text="")
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
|
|||||||
@@ -88,6 +88,23 @@ class Georeference(blenderbim.core.tool.Georeference):
|
|||||||
prop.data_type = "string"
|
prop.data_type = "string"
|
||||||
prop.string_value = "" if prop.is_null else str(data[name].wrappedValue)
|
prop.string_value = "" if prop.is_null else str(data[name].wrappedValue)
|
||||||
return True
|
return True
|
||||||
|
elif name == "XAxisAbscissa":
|
||||||
|
props = bpy.context.scene.BIMGeoreferenceProperties
|
||||||
|
props.is_changing_angle = True
|
||||||
|
if data["XAxisAbscissa"] is None or data["XAxisOrdinate"]:
|
||||||
|
props.x_axis_is_null = True
|
||||||
|
else:
|
||||||
|
props.grid_north_angle = str(
|
||||||
|
round(
|
||||||
|
ifcopenshell.util.geolocation.xaxis2angle(data["XAxisAbscissa"], data["XAxisOrdinate"]), 7
|
||||||
|
)
|
||||||
|
)
|
||||||
|
props.x_axis_abscissa = str(data["XAxisAbscissa"])
|
||||||
|
props.x_axis_ordinate = str(data["XAxisOrdinate"])
|
||||||
|
props.is_changing_angle = False
|
||||||
|
return True
|
||||||
|
elif name == "XAxisOrdinate":
|
||||||
|
return True
|
||||||
elif name not in ("SourceCRS", "TargetCRS"):
|
elif name not in ("SourceCRS", "TargetCRS"):
|
||||||
# Enforce a string data type to prevent data loss in single-precision Blender props
|
# Enforce a string data type to prevent data loss in single-precision Blender props
|
||||||
prop.data_type = "string"
|
prop.data_type = "string"
|
||||||
@@ -114,11 +131,20 @@ class Georeference(blenderbim.core.tool.Georeference):
|
|||||||
return
|
return
|
||||||
|
|
||||||
props = bpy.context.scene.BIMGeoreferenceProperties
|
props = bpy.context.scene.BIMGeoreferenceProperties
|
||||||
|
props.is_changing_angle = True
|
||||||
|
props.true_north_abscissa = "0"
|
||||||
|
props.true_north_ordinate = "1"
|
||||||
|
props.true_north_angle = "0"
|
||||||
|
props.is_changing_angle = False
|
||||||
|
|
||||||
for context in tool.Ifc.get().by_type("IfcGeometricRepresentationContext", include_subtypes=False):
|
for context in tool.Ifc.get().by_type("IfcGeometricRepresentationContext", include_subtypes=False):
|
||||||
if context.TrueNorth:
|
if context.TrueNorth:
|
||||||
true_north = context.TrueNorth.DirectionRatios
|
true_north = context.TrueNorth.DirectionRatios
|
||||||
|
props.is_changing_angle = True
|
||||||
props.true_north_abscissa = str(true_north[0])
|
props.true_north_abscissa = str(true_north[0])
|
||||||
props.true_north_ordinate = str(true_north[1])
|
props.true_north_ordinate = str(true_north[1])
|
||||||
|
props.true_north_angle = str(round(ifcopenshell.util.geolocation.yaxis2angle(*true_north[:2]), 7))
|
||||||
|
props.is_changing_angle = False
|
||||||
return
|
return
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -143,6 +169,17 @@ class Georeference(blenderbim.core.tool.Georeference):
|
|||||||
elif prop.name in ("FirstCoordinate", "SecondCoordinate"):
|
elif prop.name in ("FirstCoordinate", "SecondCoordinate"):
|
||||||
attributes[prop.name] = tool.Ifc.get().create_entity(measure_type, float(prop.string_value))
|
attributes[prop.name] = tool.Ifc.get().create_entity(measure_type, float(prop.string_value))
|
||||||
return True
|
return True
|
||||||
|
elif prop.name == "XAxisAbscissa":
|
||||||
|
props = bpy.context.scene.BIMGeoreferenceProperties
|
||||||
|
if props.x_axis_is_null:
|
||||||
|
attributes["XAxisAbscissa"] = None
|
||||||
|
attributes["XAxisOrdinate"] = None
|
||||||
|
else:
|
||||||
|
attributes["XAxisAbscissa"] = float(props.x_axis_abscissa)
|
||||||
|
attributes["XAxisOrdinate"] = float(props.x_axis_ordinate)
|
||||||
|
return True
|
||||||
|
elif prop.name == "XAxisOrdinate":
|
||||||
|
return True
|
||||||
elif not prop.is_null and prop.data_type == "string":
|
elif not prop.is_null and prop.data_type == "string":
|
||||||
# We store our floats as string to prevent single precision data loss
|
# We store our floats as string to prevent single precision data loss
|
||||||
attributes[prop.name] = float(prop.string_value)
|
attributes[prop.name] = float(prop.string_value)
|
||||||
@@ -183,7 +220,6 @@ class Georeference(blenderbim.core.tool.Georeference):
|
|||||||
def disable_editing_true_north(cls):
|
def disable_editing_true_north(cls):
|
||||||
bpy.context.scene.BIMGeoreferenceProperties.is_editing_true_north = False
|
bpy.context.scene.BIMGeoreferenceProperties.is_editing_true_north = False
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_coordinates(cls, io, coordinates):
|
def set_coordinates(cls, io, coordinates):
|
||||||
if io == "local":
|
if io == "local":
|
||||||
@@ -345,7 +381,7 @@ class Georeference(blenderbim.core.tool.Georeference):
|
|||||||
if np.allclose(placement, np.eye(4)):
|
if np.allclose(placement, np.eye(4)):
|
||||||
props.wcs_x = props.wcs_y = props.wcs_z = props.wcs_rotation = "0"
|
props.wcs_x = props.wcs_y = props.wcs_z = props.wcs_rotation = "0"
|
||||||
else:
|
else:
|
||||||
props.wcs_rotation = str(round(ifcopenshell.util.geolocation.yaxis2angle(*placement[:, 1][:2]), 3))
|
props.wcs_rotation = str(round(ifcopenshell.util.geolocation.yaxis2angle(*placement[:, 1][:2]), 7))
|
||||||
props.wcs_x, props.wcs_y, props.wcs_z = map(str, placement[:, 3][:3])
|
props.wcs_x, props.wcs_y, props.wcs_z = map(str, placement[:, 3][:3])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
Reference in New Issue
Block a user