Converting to project units inside QtoCalculator.guess_quantity

Also added some error message if `calculate_quantity` failed to calculate a quantity
This commit is contained in:
Andrej730
2023-04-20 11:00:01 +05:00
parent f160516772
commit 648eb8fdd1
3 changed files with 50 additions and 46 deletions
@@ -381,11 +381,19 @@ class CalculateQuantity(bpy.types.Operator):
self.qto_calculator = QtoCalculator()
obj = context.active_object
prop = obj.PsetProperties.properties.get(self.prop)
prop.metadata.float_value = self.calculate_quantity(obj, context)
quantity = self.calculate_quantity(obj, context)
if quantity is None:
self.report({"ERROR"}, "Could not calculate quantity")
return {"CANCELLED"}
prop.metadata.float_value = quantity
return {"FINISHED"}
def calculate_quantity(self, obj, context):
quantity = self.qto_calculator.calculate_quantity(obj.PsetProperties.active_pset_name, self.prop, obj)
if quantity is None:
return
return round(quantity, 3)
@@ -404,35 +412,7 @@ class GuessQuantity(bpy.types.Operator):
def guess_quantity(self, obj, context):
quantity = self.qto_calculator.guess_quantity(self.prop, [p.name for p in obj.PsetProperties.properties], obj)
if "area" in self.prop.lower():
if context.scene.BIMProperties.area_unit:
prefix, name = self.get_prefix_name(context.scene.BIMProperties.area_unit)
quantity = ifcopenshell.util.unit.convert(quantity, None, "SQUARE_METRE", prefix, name)
elif "volume" in self.prop.lower():
if context.scene.BIMProperties.volume_unit:
prefix, name = self.get_prefix_name(context.scene.BIMProperties.volume_unit)
quantity = ifcopenshell.util.unit.convert(quantity, None, "CUBIC_METRE", prefix, name)
else:
prefix, name = self.get_blender_prefix_name(context)
quantity = ifcopenshell.util.unit.convert(quantity, None, "METRE", prefix, name)
return round(quantity, 3)
def get_prefix_name(self, value):
if "/" in value:
return value.split("/")
return None, value
def get_blender_prefix_name(self, context):
unit_settings = context.scene.unit_settings
if unit_settings.system == "IMPERIAL":
if unit_settings.length_unit == "INCHES":
return None, "inch"
elif unit_settings.length_unit == "FEET":
return None, "foot"
elif unit_settings.system == "METRIC":
if unit_settings.length_unit == "METERS":
return None, "METRE"
return unit_settings.length_unit[0 : -len("METERS")], "METRE"
return round(quantity, 3) if quantity is not None else None
class CopyPropertyToSelection(bpy.types.Operator, Operator):
@@ -59,30 +59,48 @@ class QtoCalculator:
return tool.Qto.convert_to_project_units(value, qto_name, quantity_name) or value
def guess_quantity(self, prop_name, alternative_prop_names, obj):
"""guess the value of the quantity by name, returns the value in the project units"""
prop_name = prop_name.lower()
alternative_prop_names = [p.lower() for p in alternative_prop_names]
value = None
if "length" in prop_name and "width" not in alternative_prop_names and "height" not in alternative_prop_names:
return self.get_linear_length(obj)
value = self.get_linear_length(obj)
elif "length" in prop_name:
return self.get_length(obj)
value = self.get_length(obj)
elif "width" in prop_name and "length" not in alternative_prop_names:
return self.get_length(obj)
value = self.get_length(obj)
elif "width" in prop_name:
return self.get_width(obj)
value = self.get_width(obj)
elif "height" in prop_name or "depth" in prop_name:
return self.get_height(obj)
value = self.get_height(obj)
elif "perimeter" in prop_name:
return self.get_net_perimeter(obj)
value = self.get_net_perimeter(obj)
elif "area" in prop_name and ("footprint" in prop_name or "section" in prop_name or "floor" in prop_name):
return self.get_net_footprint_area(obj)
value = self.get_net_footprint_area(obj)
elif "area" in prop_name and "side" in prop_name:
return self.get_side_area(obj)
value = self.get_side_area(obj)
elif "area" in prop_name:
return self.get_gross_surface_area(obj)
value = self.get_gross_surface_area(obj)
elif "volume" in prop_name and "gross" in prop_name:
return self.get_gross_volume(obj)
value = self.get_gross_volume(obj)
elif "volume" in prop_name:
return self.get_net_volume(obj)
value = self.get_net_volume(obj)
if value is None:
return
unit_type_keywords = {
"length": "Q_LENGTH",
"width": "Q_LENGTH",
"height": "Q_LENGTH",
"depth": "Q_LENGTH",
"perimeter": "Q_LENGTH",
"area": "Q_AREA",
"volume": "Q_VOLUME",
}
unit_type = next(unit_type_keywords[k] for k in unit_type_keywords if k in prop_name)
return tool.Qto.convert_to_project_units(value, quantity_type=unit_type) or value
def get_units(self, o, vg_index):
return len([v for v in o.data.vertices if vg_index in [g.group for g in v.groups]])
+11 -5
View File
@@ -90,7 +90,8 @@ class Qto(blenderbim.core.tool.Qto):
return {
quantity_name: cls.get_rounded_value(calculator.calculate_quantity(qto_name, quantity_name, obj))
for quantity_name in cls.get_applicable_quantity_names(qto_name) or []
if cls.has_calculator(qto_name, quantity_name) and calculator.calculate_quantity(qto_name, quantity_name, obj) is not None
if cls.has_calculator(qto_name, quantity_name)
and calculator.calculate_quantity(qto_name, quantity_name, obj) is not None
}
@classmethod
@@ -98,16 +99,22 @@ class Qto(blenderbim.core.tool.Qto):
return bool(mapper.get(qto_name, {}).get(quantity_name, None))
@classmethod
def convert_to_project_units(cls, value, qto_name, quantity_name):
def convert_to_project_units(cls, value, qto_name=None, quantity_name=None, quantity_type=None):
"""You can either specify `quantity_type` or provide `qto_name/quantity_name`
to let method figure the `quantity_type` from the templates
`quantity_type` values are `Q_LENGTH`, `Q_AREA`, `Q_VOLUME`
"""
ifc_file = tool.Ifc.get()
quantity_to_unit_types = {
"Q_LENGTH": ("LENGTHUNIT", "METRE"),
"Q_AREA": ("AREAUNIT", "SQUARE_METRE"),
"Q_VOLUME": ("VOLUMEUNIT", "CUBIC_METRE"),
}
if not quantity_type:
qt = blenderbim.bim.schema.ifc.psetqto.get_by_name(qto_name)
quantity_type = next(q.TemplateType for q in qt.HasPropertyTemplates if q.Name == quantity_name)
qt = blenderbim.bim.schema.ifc.psetqto.get_by_name(qto_name)
quantity_type = next(q.TemplateType for q in qt.HasPropertyTemplates if q.Name == quantity_name)
unit_type = quantity_to_unit_types.get(quantity_type, None)
if not unit_type:
return
@@ -125,7 +132,6 @@ class Qto(blenderbim.core.tool.Qto):
)
return value
@classmethod
def get_guessed_quantities(cls, obj, pset_qto_properties):
calculated_quantities = {}