Display project units instead of hardcoded ones (#1699)

* Display project units instead of hardcoded ones

* Treat MapUnit as a regular attribute

* Remove left over attributes

* Refactor operator for MapUnit change

* Fix unit fetch failing because of wrong id type
This commit is contained in:
Gorgious56
2021-08-27 10:07:51 +02:00
committed by GitHub
parent dd0a3d0421
commit 8d5970f002
3 changed files with 33 additions and 63 deletions
@@ -26,6 +26,7 @@ import ifcopenshell.api
import blenderbim.bim.helper import blenderbim.bim.helper
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.georeference.data import Data from ifcopenshell.api.georeference.data import Data
from ifcopenshell.api.unit.data import Data as UnitData
from math import radians, degrees, atan, tan, cos, sin from math import radians, degrees, atan, tan, cos, sin
@@ -37,36 +38,15 @@ class EnableEditingGeoreferencing(bpy.types.Operator):
def execute(self, context): def execute(self, context):
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
props = context.scene.BIMGeoreferenceProperties props = context.scene.BIMGeoreferenceProperties
self.props = props
props.projected_crs.clear() props.projected_crs.clear()
for attribute in IfcStore.get_schema().declaration_by_name("IfcProjectedCRS").all_attributes():
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
if data_type == "entity":
continue
new = props.projected_crs.add()
new.name = attribute.name()
new.is_null = Data.projected_crs[attribute.name()] is None
new.is_optional = attribute.optional()
new.data_type = data_type
if data_type == "string":
new.string_value = "" if new.is_null else Data.projected_crs[attribute.name()]
elif data_type == "float":
new.float_value = 0.0 if new.is_null else Data.projected_crs[attribute.name()]
elif data_type == "integer":
new.int_value = 0 if new.is_null else Data.projected_crs[attribute.name()]
elif data_type == "boolean":
new.bool_value = False if new.is_null else Data.projected_crs[attribute.name()]
props.is_map_unit_null = Data.projected_crs["MapUnit"] is None blenderbim.bim.helper.import_attributes(
if not props.is_map_unit_null: "IfcProjectedCRS",
props.map_unit_type = Data.projected_crs["MapUnit"]["type"] props.projected_crs,
if props.map_unit_type == "IfcSIUnit": Data.projected_crs,
prefix = ifcopenshell.util.unit.get_prefix(Data.projected_crs["MapUnit"]["Prefix"]) or "" self.import_projected_crs_attributes)
name = ifcopenshell.util.unit.get_unit_name(Data.projected_crs["MapUnit"]["Name"])
props.map_unit_si = prefix + name
elif props.map_unit_type == "IfcConversionBasedUnit":
props.map_unit_imperial = Data.projected_crs["MapUnit"]["Name"]
props.map_conversion.clear() props.map_conversion.clear()
blenderbim.bim.helper.import_attributes( blenderbim.bim.helper.import_attributes(
@@ -81,6 +61,20 @@ class EnableEditingGeoreferencing(bpy.types.Operator):
props.is_editing = True props.is_editing = True
return {"FINISHED"} return {"FINISHED"}
def import_projected_crs_attributes(self, name, prop, data):
if name == "MapUnit":
new = self.props.projected_crs.add()
new.name = name
new.data_type = "enum"
new.is_null = data[name] is None
new.is_optional = True
new.enum_items = json.dumps({
u["id"]: u["Name"]
for u in UnitData.units.values()
if u["UnitType"] == "LENGTHUNIT"
})
return True
def import_map_conversion_attributes(self, name, prop, data): def import_map_conversion_attributes(self, name, prop, data):
if name not in ["SourceCRS", "TargetCRS"]: if 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
@@ -88,6 +82,7 @@ class EnableEditingGeoreferencing(bpy.types.Operator):
prop.string_value = "" if prop.is_null else str(data[name]) prop.string_value = "" if prop.is_null else str(data[name])
return True return True
class DisableEditingGeoreferencing(bpy.types.Operator): class DisableEditingGeoreferencing(bpy.types.Operator):
bl_idname = "bim.disable_editing_georeferencing" bl_idname = "bim.disable_editing_georeferencing"
bl_label = "Disable Editing Georeferencing" bl_label = "Disable Editing Georeferencing"
@@ -111,20 +106,15 @@ class EditGeoreferencing(bpy.types.Operator):
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
props = context.scene.BIMGeoreferenceProperties props = context.scene.BIMGeoreferenceProperties
projected_crs = blenderbim.bim.helper.export_attributes(props.projected_crs) projected_crs = blenderbim.bim.helper.export_attributes(props.projected_crs, self.export_crs_attributes)
map_conversion = blenderbim.bim.helper.export_attributes(props.map_conversion, self.export_map_attributes)
map_unit = ""
if not props.is_map_unit_null:
map_unit = props.map_unit_si if props.map_unit_type == "IfcSIUnit" else props.map_unit_imperial
map_conversion = blenderbim.bim.helper.export_attributes(props.map_conversion, self.export_attributes)
true_north = None true_north = None
if props.has_true_north: if props.has_true_north:
try: try:
true_north = [float(props.true_north_abscissa), float(props.true_north_ordinate)] true_north = [float(props.true_north_abscissa), float(props.true_north_ordinate)]
except: except ValueError:
pass self.report({"ERROR"}, "True North Abscissa and Ordinate expect a number")
ifcopenshell.api.run( ifcopenshell.api.run(
"georeference.edit_georeferencing", "georeference.edit_georeferencing",
@@ -132,20 +122,24 @@ class EditGeoreferencing(bpy.types.Operator):
**{ **{
"map_conversion": map_conversion, "map_conversion": map_conversion,
"projected_crs": projected_crs, "projected_crs": projected_crs,
"map_unit": map_unit,
"true_north": true_north, "true_north": true_north,
} }
) )
Data.load(IfcStore.get_file()) Data.load(self.file)
bpy.ops.bim.disable_editing_georeferencing() bpy.ops.bim.disable_editing_georeferencing()
return {"FINISHED"} return {"FINISHED"}
def export_attributes(self, attributes, prop): def export_map_attributes(self, attributes, prop):
if not prop.is_null and prop.data_type == "string": if 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)
return True return True
def export_crs_attributes(self, attributes, prop):
if not prop.is_null and prop.name == "MapUnit":
attributes[prop.name] = self.file.by_id(int(prop.enum_value))
return True
class SetBlenderGridNorth(bpy.types.Operator): class SetBlenderGridNorth(bpy.types.Operator):
bl_idname = "bim.set_blender_grid_north" bl_idname = "bim.set_blender_grid_north"
@@ -36,22 +36,6 @@ class BIMGeoreferenceProperties(PropertyGroup):
is_editing: BoolProperty(name="Is Editing") is_editing: BoolProperty(name="Is Editing")
map_conversion: CollectionProperty(name="Map Conversion", type=Attribute) map_conversion: CollectionProperty(name="Map Conversion", type=Attribute)
projected_crs: CollectionProperty(name="Projected CRS", type=Attribute) projected_crs: CollectionProperty(name="Projected CRS", type=Attribute)
map_unit_type: EnumProperty(
items=[(n, n, "") for n in ["IfcSIUnit", "IfcConversionBasedUnit"]],
name="Map Unit Type",
default="IfcSIUnit",
)
map_unit_si: EnumProperty(
items=[(n, n.lower().capitalize(), "") for n in ["MILLIMETRE", "CENTIMETRE", "METRE", "KILOMETRE"]],
name="Map Unit SI",
default="METRE",
)
map_unit_imperial: EnumProperty(
items=[(n, n.lower().capitalize(), "") for n in ["inch", "foot", "yard", "mile"]],
name="Map Unit SI",
default="foot",
)
is_map_unit_null: BoolProperty(name="Is Map Unit Null")
coordinate_input: StringProperty(name="Coordinate Input", description="Formatted \"x,y,z\" (without quotes)") coordinate_input: StringProperty(name="Coordinate Input", description="Formatted \"x,y,z\" (without quotes)")
coordinate_output: StringProperty(name="Coordinate Output", description="Formatted \"x,y,z\" (without quotes)") coordinate_output: StringProperty(name="Coordinate Output", description="Formatted \"x,y,z\" (without quotes)")
has_blender_offset: BoolProperty(name="Has Blender Offset") has_blender_offset: BoolProperty(name="Has Blender Offset")
@@ -56,14 +56,6 @@ class BIM_PT_gis(Panel):
draw_attributes(props.projected_crs, self.layout) draw_attributes(props.projected_crs, self.layout)
row = self.layout.row(align=True)
row.prop(props, "map_unit_type", text="MapUnit")
if props.map_unit_type == "IfcSIUnit":
row.prop(props, "map_unit_si", text="")
elif props.map_unit_type == "IfcConversionBasedUnit":
row.prop(props, "map_unit_imperial", text="")
row.prop(props, "is_map_unit_null", icon="RADIOBUT_OFF" if props.is_map_unit_null else "RADIOBUT_ON", text="")
row = self.layout.row() row = self.layout.row()
row.label(text="Map Conversion", icon="GRID") row.label(text="Map Conversion", icon="GRID")