mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
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:
@@ -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]])
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
Reference in New Issue
Block a user