WIP port unit assignment to partial editing. See #1222.

This commit is contained in:
Dion Moult
2021-01-05 21:13:44 +11:00
parent d74b344a95
commit f76d792a25
7 changed files with 154 additions and 0 deletions
@@ -14,6 +14,7 @@ if bpy is not None:
import blenderbim.bim.module.geometry as module_geometry
import blenderbim.bim.module.model as module_model
import blenderbim.bim.module.spatial as module_spatial
import blenderbim.bim.module.unit as module_unit
from . import ui, prop, operator
classes = [
@@ -320,6 +321,7 @@ if bpy is not None:
classes.extend(module_geometry.classes)
classes.extend(module_model.classes)
classes.extend(module_spatial.classes)
classes.extend(module_unit.classes)
def menu_func_export(self, context):
self.layout.operator(operator.ExportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcjson)")
@@ -360,6 +362,7 @@ if bpy is not None:
module_geometry.register()
module_model.register()
module_spatial.register()
module_unit.register()
bpy.app.handlers.depsgraph_update_pre.append(operator.depsgraph_update_pre_handler)
def unregister():
@@ -380,6 +383,7 @@ if bpy is not None:
del bpy.types.Camera.BIMCameraProperties
del bpy.types.TextCurve.BIMTextProperties
bpy.types.SCENE_PT_unit.remove(ui.ifc_units)
module_unit.unregister()
module_spatial.unregister()
module_model.unregister()
module_geometry.unregister()
@@ -1,6 +1,7 @@
from bpy.types import Panel
from blenderbim.bim.module.context.data import Data
class BIM_PT_context(Panel):
bl_label = "IFC Geometric Representation Contexts"
bl_idname = "BIM_PT_context"
@@ -0,0 +1,14 @@
import bpy
from . import ui, operator
classes = (
operator.AssignUnit,
)
def register():
pass
def unregister():
pass
@@ -0,0 +1,76 @@
import ifcopenshell.util.unit
class Usecase():
def __init__(self, file, settings=None):
self.file = file
self.settings = {
"length": {
"is_metric": True,
"raw": "MILLIMETERS"
},
"area": {
"is_metric": True,
"raw": "METERS"
},
"volume": {
"is_metric": True,
"raw": "METERS"
},
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
for unit_type, data in self.settings.items():
if data["is_metric"]:
data["ifc"] = self.create_metric_unit(unit_type, data)
else:
data["ifc"] = self.create_imperial_unit(unit_type, data)
unit_assignment = self.file.by_type("IfcUnitAssignment")
if unit_assignment:
unit_assignment = unit_assignment[0]
# TODO: handle unit rewriting, which is complicated
else:
unit_assignment = self.file.createIfcUnitAssignment([u["ifc"] for u in self.settings.values()])
self.file.by_type("IfcProject")[0].UnitsInContext = unit_assignment
return unit_assignment
def create_metric_unit(self, unit_type, data):
type_prefix = ""
if unit_type == "area":
type_prefix = "SQUARE_"
elif unit_type == "volume":
type_prefix = "CUBIC_"
return self.file.createIfcSIUnit(
None,
"{}UNIT".format(unit_type.upper()),
ifcopenshell.util.unit.get_prefix(data["raw"]),
type_prefix + ifcopenshell.util.unit.get_unit_name(data["raw"]),
)
def create_imperial_unit(self, unit_type, data):
if unit_type == "length":
dimensional_exponents = self.file.createIfcDimensionalExponents(1, 0, 0, 0, 0, 0, 0)
name_prefix = ""
elif unit_type == "area":
dimensional_exponents = self.file.createIfcDimensionalExponents(2, 0, 0, 0, 0, 0, 0)
name_prefix = "square"
elif unit_type == "volume":
dimensional_exponents = self.file.createIfcDimensionalExponents(3, 0, 0, 0, 0, 0, 0)
name_prefix = "cubic"
si_unit = self.file.createIfcSIUnit(
None,
"{}UNIT".format(unit_type.upper()),
None,
"{}METRE".format(name_prefix.upper() + "_" if name_prefix else ""),
)
if data["raw"] == "INCHES":
name = "{}inch".format(name_prefix + " " if name_prefix else "")
elif data["raw"] == "FEET":
name = "{}foot".format(name_prefix + " " if name_prefix else "")
value_component = self.file.create_entity("IfcReal", **{"wrappedValue": ifcopenshell.util.unit.si_conversions[name]})
conversion_factor = self.file.createIfcMeasureWithUnit(value_component, si_unit)
return self.file.createIfcConversionBasedUnit(
dimensional_exponents, "{}UNIT".format(unit_type.upper()), name, conversion_factor
)
@@ -0,0 +1,19 @@
from blenderbim.bim.ifc import IfcStore
class Data:
is_loaded = False
units = {}
@classmethod
def load(cls):
file = IfcStore.get_file()
if not file:
return
unit_assignment = file.by_type("IfcUnitAssignment")
if not unit_assignment:
return
for unit in unit_assignment[0].Units:
pass
# TODO: implement along with UI
cls.is_loaded = True
@@ -0,0 +1,40 @@
import bpy
import blenderbim.bim.module.unit.assign_unit as assign_unit
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.module.unit.data import Data
class AssignUnit(bpy.types.Operator):
bl_idname = "bim.assign_unit"
bl_label = "Assign Unit"
def execute(self, context):
assign_unit.Usecase(IfcStore.get_file(), self.get_units()).execute()
Data.load()
return {"FINISHED"}
def get_units(self):
units = {
"length": {
"ifc": None,
"is_metric": bpy.context.scene.unit_settings.system != "IMPERIAL",
"raw": bpy.context.scene.unit_settings.length_unit,
},
"area": {
"ifc": None,
"is_metric": bpy.context.scene.unit_settings.system != "IMPERIAL",
"raw": bpy.context.scene.unit_settings.length_unit,
},
"volume": {
"ifc": None,
"is_metric": bpy.context.scene.unit_settings.system != "IMPERIAL",
"raw": bpy.context.scene.unit_settings.length_unit,
},
}
for data in units.values():
if data["raw"] == "ADAPTIVE":
if data["is_metric"]:
data["raw"] = "METERS"
else:
data["raw"] = "FEET"
return units