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
from blenderbim.bim.ifc import IfcStore
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
@@ -37,36 +38,15 @@ class EnableEditingGeoreferencing(bpy.types.Operator):
def execute(self, context):
self.file = IfcStore.get_file()
props = context.scene.BIMGeoreferenceProperties
self.props = props
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
if not props.is_map_unit_null:
props.map_unit_type = Data.projected_crs["MapUnit"]["type"]
if props.map_unit_type == "IfcSIUnit":
prefix = ifcopenshell.util.unit.get_prefix(Data.projected_crs["MapUnit"]["Prefix"]) or ""
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"]
blenderbim.bim.helper.import_attributes(
"IfcProjectedCRS",
props.projected_crs,
Data.projected_crs,
self.import_projected_crs_attributes)
props.map_conversion.clear()
blenderbim.bim.helper.import_attributes(
@@ -81,6 +61,20 @@ class EnableEditingGeoreferencing(bpy.types.Operator):
props.is_editing = True
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):
if name not in ["SourceCRS", "TargetCRS"]:
# 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])
return True
class DisableEditingGeoreferencing(bpy.types.Operator):
bl_idname = "bim.disable_editing_georeferencing"
bl_label = "Disable Editing Georeferencing"
@@ -111,20 +106,15 @@ class EditGeoreferencing(bpy.types.Operator):
self.file = IfcStore.get_file()
props = context.scene.BIMGeoreferenceProperties
projected_crs = blenderbim.bim.helper.export_attributes(props.projected_crs)
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)
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)
true_north = None
if props.has_true_north:
try:
true_north = [float(props.true_north_abscissa), float(props.true_north_ordinate)]
except:
pass
except ValueError:
self.report({"ERROR"}, "True North Abscissa and Ordinate expect a number")
ifcopenshell.api.run(
"georeference.edit_georeferencing",
@@ -132,20 +122,24 @@ class EditGeoreferencing(bpy.types.Operator):
**{
"map_conversion": map_conversion,
"projected_crs": projected_crs,
"map_unit": map_unit,
"true_north": true_north,
}
)
Data.load(IfcStore.get_file())
Data.load(self.file)
bpy.ops.bim.disable_editing_georeferencing()
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":
# We store our floats as string to prevent single precision data loss
attributes[prop.name] = float(prop.string_value)
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):
bl_idname = "bim.set_blender_grid_north"
@@ -36,22 +36,6 @@ class BIMGeoreferenceProperties(PropertyGroup):
is_editing: BoolProperty(name="Is Editing")
map_conversion: CollectionProperty(name="Map Conversion", 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_output: StringProperty(name="Coordinate Output", description="Formatted \"x,y,z\" (without quotes)")
has_blender_offset: BoolProperty(name="Has Blender Offset")
@@ -56,14 +56,6 @@ class BIM_PT_gis(Panel):
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.label(text="Map Conversion", icon="GRID")