mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 10:57:49 +00:00
328 lines
14 KiB
Python
328 lines
14 KiB
Python
# Bonsai - OpenBIM Blender Add-on
|
|
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
|
#
|
|
# This file is part of Bonsai.
|
|
#
|
|
# Bonsai is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# Bonsai is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import bpy
|
|
import ifcopenshell
|
|
import ifcopenshell.api.project
|
|
import ifcopenshell.api.root
|
|
import ifcopenshell.api.unit
|
|
import bonsai.core.tool
|
|
import bonsai.tool as tool
|
|
from test.bim.bootstrap import NewFile
|
|
from bonsai.tool.unit import Unit as subject
|
|
|
|
|
|
class TestImplementsTool(NewFile):
|
|
def test_run(self):
|
|
assert isinstance(subject(), bonsai.core.tool.Unit)
|
|
|
|
|
|
class TestClearActiveUnit(NewFile):
|
|
def test_run(self):
|
|
props = tool.Unit.get_unit_props()
|
|
props.active_unit_id = 1
|
|
subject.clear_active_unit()
|
|
assert props.active_unit_id == 0
|
|
|
|
|
|
class TestDisableEditingUnits(NewFile):
|
|
def test_run(self):
|
|
props = tool.Unit.get_unit_props()
|
|
props.is_editing = True
|
|
subject.disable_editing_units()
|
|
assert props.is_editing == False
|
|
|
|
|
|
class TestEnableEditingUnits(NewFile):
|
|
def test_run(self):
|
|
props = tool.Unit.get_unit_props()
|
|
props.is_editing = False
|
|
subject.enable_editing_units()
|
|
assert props.is_editing == True
|
|
|
|
|
|
class TestExportUnitAttributes(NewFile):
|
|
def test_exporting_derived_units(self):
|
|
TestImportUnitAttributes().test_importing_derived_units()
|
|
assert subject.export_unit_attributes() == {
|
|
"UnitType": "ANGULARVELOCITYUNIT",
|
|
"UserDefinedType": "UserDefinedType",
|
|
}
|
|
|
|
def test_exporting_monetary_units(self):
|
|
TestImportUnitAttributes().test_importing_monetary_units()
|
|
assert subject.export_unit_attributes() == {"Currency": "Currency"}
|
|
|
|
def test_exporting_monetary_units_ifc2x3(self):
|
|
TestImportUnitAttributes().test_importing_monetary_units_ifc2x3()
|
|
assert subject.export_unit_attributes() == {"Currency": "USD"}
|
|
|
|
def test_exporting_context_dependent_units(self):
|
|
TestImportUnitAttributes().test_importing_context_dependent_units()
|
|
assert subject.export_unit_attributes() == {
|
|
"UnitType": "ABSORBEDDOSEUNIT",
|
|
"Name": "Name",
|
|
"Dimensions": [1, 2, 3, 4, 5, 6, 7],
|
|
}
|
|
|
|
def test_exporting_conversion_based_units(self):
|
|
TestImportUnitAttributes().test_importing_conversion_based_units()
|
|
assert subject.export_unit_attributes() == {
|
|
"UnitType": "ABSORBEDDOSEUNIT",
|
|
"Name": "Name",
|
|
"Dimensions": [1, 2, 3, 4, 5, 6, 7],
|
|
}
|
|
|
|
def test_exporting_conversion_based_with_offset_units(self):
|
|
TestImportUnitAttributes().test_importing_conversion_based_with_offset_units()
|
|
assert subject.export_unit_attributes() == {
|
|
"UnitType": "ABSORBEDDOSEUNIT",
|
|
"Name": "Name",
|
|
"Dimensions": [1, 2, 3, 4, 5, 6, 7],
|
|
"ConversionOffset": 1,
|
|
}
|
|
|
|
def test_exporting_si_units(self):
|
|
TestImportUnitAttributes().test_importing_si_units()
|
|
assert subject.export_unit_attributes() == {"UnitType": "ABSORBEDDOSEUNIT", "Prefix": "EXA", "Name": "AMPERE"}
|
|
|
|
|
|
class TestGetSceneUnitName(NewFile):
|
|
def test_getting_an_imperial_name(self):
|
|
assert bpy.context.scene
|
|
props = tool.Blender.get_bim_props()
|
|
bpy.context.scene.unit_settings.system = "IMPERIAL"
|
|
bpy.context.scene.unit_settings.length_unit = "MILES"
|
|
props.area_unit = "square foot"
|
|
props.volume_unit = "cubic inch"
|
|
assert subject.get_scene_unit_name("LENGTHUNIT") == "mile"
|
|
assert subject.get_scene_unit_name("AREAUNIT") == "square foot"
|
|
assert subject.get_scene_unit_name("VOLUMEUNIT") == "cubic inch"
|
|
bpy.context.scene.unit_settings.length_unit = "FEET"
|
|
assert subject.get_scene_unit_name("LENGTHUNIT") == "foot"
|
|
assert subject.get_scene_unit_name("AREAUNIT") == "square foot"
|
|
assert subject.get_scene_unit_name("VOLUMEUNIT") == "cubic inch"
|
|
bpy.context.scene.unit_settings.length_unit = "INCHES"
|
|
assert subject.get_scene_unit_name("LENGTHUNIT") == "inch"
|
|
assert subject.get_scene_unit_name("AREAUNIT") == "square foot"
|
|
assert subject.get_scene_unit_name("VOLUMEUNIT") == "cubic inch"
|
|
bpy.context.scene.unit_settings.length_unit = "THOU"
|
|
assert subject.get_scene_unit_name("LENGTHUNIT") == "thou"
|
|
assert subject.get_scene_unit_name("AREAUNIT") == "square foot"
|
|
assert subject.get_scene_unit_name("VOLUMEUNIT") == "cubic inch"
|
|
bpy.context.scene.unit_settings.length_unit = "ADAPTIVE"
|
|
assert subject.get_scene_unit_name("LENGTHUNIT") == "foot"
|
|
assert subject.get_scene_unit_name("AREAUNIT") == "square foot"
|
|
assert subject.get_scene_unit_name("VOLUMEUNIT") == "cubic inch"
|
|
|
|
def test_getting_a_name_with_no_unit_system(self):
|
|
assert bpy.context.scene
|
|
bpy.context.scene.unit_settings.system = "NONE"
|
|
assert subject.get_scene_unit_name("LENGTHUNIT") == "foot"
|
|
|
|
|
|
class TestGetSceneUnitSIPrefix:
|
|
def test_run(self):
|
|
assert bpy.context.scene
|
|
bpy.context.scene.unit_settings.system = "METRIC"
|
|
bpy.context.scene.unit_settings.length_unit = "METERS"
|
|
assert subject.get_scene_unit_si_prefix("LENGTHUNIT") is None
|
|
bpy.context.scene.unit_settings.length_unit = "MICROMETERS"
|
|
assert subject.get_scene_unit_si_prefix("LENGTHUNIT") == "MICRO"
|
|
bpy.context.scene.unit_settings.length_unit = "MILLIMETERS"
|
|
assert subject.get_scene_unit_si_prefix("LENGTHUNIT") == "MILLI"
|
|
bpy.context.scene.unit_settings.length_unit = "CENTIMETERS"
|
|
assert subject.get_scene_unit_si_prefix("LENGTHUNIT") == "CENTI"
|
|
bpy.context.scene.unit_settings.length_unit = "KILOMETERS"
|
|
assert subject.get_scene_unit_si_prefix("LENGTHUNIT") == "KILO"
|
|
bpy.context.scene.unit_settings.length_unit = "ADAPTIVE"
|
|
assert subject.get_scene_unit_si_prefix("LENGTHUNIT") is None
|
|
props = tool.Blender.get_bim_props()
|
|
props.area_unit = "SQUARE_METRE"
|
|
assert subject.get_scene_unit_si_prefix("AREAUNIT") is None
|
|
props.area_unit = "MILLI/SQUARE_METRE"
|
|
assert subject.get_scene_unit_si_prefix("AREAUNIT") == "MILLI"
|
|
props.volume_unit = "CUBIC_METRE"
|
|
assert subject.get_scene_unit_si_prefix("VOLUMEUNIT") is None
|
|
props.volume_unit = "MILLI/CUBIC_METRE"
|
|
assert subject.get_scene_unit_si_prefix("VOLUMEUNIT") == "MILLI"
|
|
|
|
|
|
class TestImportUnitAttributes(NewFile):
|
|
def test_importing_derived_units(self):
|
|
tool.Ifc.set(ifc := ifcopenshell.file())
|
|
unit = ifc.createIfcDerivedUnit()
|
|
unit.UnitType = "ANGULARVELOCITYUNIT"
|
|
unit.UserDefinedType = "UserDefinedType"
|
|
subject.import_unit_attributes(unit)
|
|
props = tool.Unit.get_unit_props()
|
|
assert props.unit_attributes["UnitType"].enum_value == "ANGULARVELOCITYUNIT"
|
|
assert props.unit_attributes["UserDefinedType"].string_value == "UserDefinedType"
|
|
|
|
def test_importing_monetary_units(self):
|
|
tool.Ifc.set(ifc := ifcopenshell.file())
|
|
unit = ifc.createIfcMonetaryUnit()
|
|
unit.Currency = "Currency"
|
|
subject.import_unit_attributes(unit)
|
|
props = tool.Unit.get_unit_props()
|
|
assert props.unit_attributes["Currency"].string_value == "Currency"
|
|
|
|
def test_importing_monetary_units_ifc2x3(self):
|
|
tool.Ifc.set(ifc := ifcopenshell.file(schema="IFC2X3"))
|
|
unit = ifc.createIfcMonetaryUnit()
|
|
unit.Currency = "USD"
|
|
subject.import_unit_attributes(unit)
|
|
props = tool.Unit.get_unit_props()
|
|
assert props.unit_attributes["Currency"].enum_value == "USD"
|
|
|
|
def test_importing_context_dependent_units(self):
|
|
ifc = ifcopenshell.file()
|
|
tool.Ifc.set(ifc)
|
|
unit = ifc.createIfcContextDependentUnit()
|
|
unit.UnitType = "ABSORBEDDOSEUNIT"
|
|
unit.Name = "Name"
|
|
unit.Dimensions = ifc.createIfcDimensionalExponents(1, 2, 3, 4, 5, 6, 7)
|
|
subject.import_unit_attributes(unit)
|
|
props = tool.Unit.get_unit_props()
|
|
assert props.unit_attributes["UnitType"].enum_value == "ABSORBEDDOSEUNIT"
|
|
assert props.unit_attributes["Name"].string_value == "Name"
|
|
assert props.unit_attributes["Dimensions"].string_value == "[1, 2, 3, 4, 5, 6, 7]"
|
|
|
|
def test_importing_conversion_based_units(self):
|
|
ifc = ifcopenshell.file()
|
|
tool.Ifc.set(ifc)
|
|
unit = ifc.createIfcConversionBasedUnit()
|
|
unit.UnitType = "ABSORBEDDOSEUNIT"
|
|
unit.Name = "Name"
|
|
unit.Dimensions = ifc.createIfcDimensionalExponents(1, 2, 3, 4, 5, 6, 7)
|
|
subject.import_unit_attributes(unit)
|
|
props = tool.Unit.get_unit_props()
|
|
assert props.unit_attributes["UnitType"].enum_value == "ABSORBEDDOSEUNIT"
|
|
assert props.unit_attributes["Name"].string_value == "Name"
|
|
assert props.unit_attributes["Dimensions"].string_value == "[1, 2, 3, 4, 5, 6, 7]"
|
|
|
|
def test_importing_conversion_based_with_offset_units(self):
|
|
ifc = ifcopenshell.file()
|
|
tool.Ifc.set(ifc)
|
|
unit = ifc.createIfcConversionBasedUnitWithOffset()
|
|
unit.UnitType = "ABSORBEDDOSEUNIT"
|
|
unit.Name = "Name"
|
|
unit.Dimensions = ifc.createIfcDimensionalExponents(1, 2, 3, 4, 5, 6, 7)
|
|
unit.ConversionOffset = 1
|
|
subject.import_unit_attributes(unit)
|
|
props = tool.Unit.get_unit_props()
|
|
assert props.unit_attributes["UnitType"].enum_value == "ABSORBEDDOSEUNIT"
|
|
assert props.unit_attributes["Name"].string_value == "Name"
|
|
assert props.unit_attributes["Dimensions"].string_value == "[1, 2, 3, 4, 5, 6, 7]"
|
|
assert props.unit_attributes["ConversionOffset"].float_value == 1
|
|
|
|
def test_importing_si_units(self):
|
|
ifc = ifcopenshell.file()
|
|
tool.Ifc.set(ifc)
|
|
unit = ifc.createIfcSIUnit()
|
|
unit.UnitType = "ABSORBEDDOSEUNIT"
|
|
unit.Prefix = "EXA"
|
|
unit.Name = "AMPERE"
|
|
subject.import_unit_attributes(unit)
|
|
props = tool.Unit.get_unit_props()
|
|
assert props.unit_attributes["UnitType"].enum_value == "ABSORBEDDOSEUNIT"
|
|
assert props.unit_attributes["Prefix"].enum_value == "EXA"
|
|
assert props.unit_attributes["Name"].enum_value == "AMPERE"
|
|
assert "Dimensions" not in props.unit_attributes
|
|
|
|
|
|
class TestImportUnits(NewFile):
|
|
def test_importing_multiple_units(self):
|
|
ifc = ifcopenshell.api.project.create_file()
|
|
tool.Ifc.set(ifc)
|
|
unit1 = ifc.createIfcDerivedUnit(UnitType="ANGULARVELOCITYUNIT")
|
|
unit2 = ifc.createIfcMonetaryUnit(Currency="Currency")
|
|
unit3 = ifc.createIfcContextDependentUnit(Name="Name", UnitType="ABSORBEDDOSEUNIT")
|
|
unit4 = ifc.createIfcConversionBasedUnit(Name="Name", UnitType="ABSORBEDDOSEUNIT")
|
|
unit5 = ifc.createIfcSIUnit(Name="AMPERE", Prefix="MILLI", UnitType="ABSORBEDDOSEUNIT")
|
|
unit6 = ifc.createIfcSIUnit(Name="CUBIC_METRE", Prefix="CENTI", UnitType="ABSORBEDDOSEUNIT")
|
|
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
|
|
ifcopenshell.api.unit.assign_unit(ifc, units=[unit2])
|
|
subject.import_units()
|
|
props = tool.Unit.get_unit_props()
|
|
assert len(props.units) == 6
|
|
|
|
assert props.units[0].ifc_definition_id == unit1.id()
|
|
assert props.units[0].name == ""
|
|
assert props.units[0].is_assigned is False
|
|
assert props.units[0].unit_type == unit1.UnitType
|
|
assert props.units[0].ifc_class == unit1.is_a()
|
|
|
|
assert props.units[1].ifc_definition_id == unit2.id()
|
|
assert props.units[1].name == "Currency"
|
|
assert props.units[1].is_assigned is True
|
|
assert props.units[1].unit_type == "CURRENCY"
|
|
assert props.units[1].ifc_class == unit2.is_a()
|
|
|
|
assert props.units[2].ifc_definition_id == unit3.id()
|
|
assert props.units[2].name == "Name"
|
|
assert props.units[2].is_assigned is False
|
|
assert props.units[2].unit_type == unit3.UnitType
|
|
assert props.units[2].ifc_class == unit3.is_a()
|
|
|
|
assert props.units[3].ifc_definition_id == unit4.id()
|
|
assert props.units[3].name == "Name"
|
|
assert props.units[3].is_assigned is False
|
|
assert props.units[3].unit_type == unit4.UnitType
|
|
assert props.units[3].ifc_class == unit4.is_a()
|
|
|
|
assert props.units[4].ifc_definition_id == unit5.id()
|
|
assert props.units[4].name == "MILLIAMPERE"
|
|
assert props.units[4].is_assigned is False
|
|
assert props.units[4].unit_type == unit5.UnitType
|
|
assert props.units[4].ifc_class == unit5.is_a()
|
|
|
|
assert props.units[5].ifc_definition_id == unit6.id()
|
|
assert props.units[5].name == "CUBIC CENTIMETRE"
|
|
assert props.units[5].is_assigned is False
|
|
assert props.units[5].unit_type == unit6.UnitType
|
|
assert props.units[5].ifc_class == unit6.is_a()
|
|
|
|
|
|
class TestIsSceneUnitMetric(NewFile):
|
|
def test_run(self):
|
|
assert bpy.context.scene
|
|
props = bpy.context.scene.unit_settings
|
|
props.system = "METRIC"
|
|
assert subject.is_scene_unit_metric() is True
|
|
props.system = "IMPERIAL"
|
|
assert subject.is_scene_unit_metric() is False
|
|
props.system = "NONE"
|
|
assert subject.is_scene_unit_metric() is True
|
|
|
|
|
|
class TestIsUnitClass:
|
|
def test_run(self):
|
|
ifc = ifcopenshell.file()
|
|
assert subject.is_unit_class(ifc.createIfcSIUnit(), "IfcNamedUnit") is True
|
|
assert subject.is_unit_class(ifc.createIfcSIUnit(), "IfcMonetaryUnit") is False
|
|
|
|
|
|
class TestSetActiveUnit(NewFile):
|
|
def test_run(self):
|
|
ifc = ifcopenshell.file()
|
|
unit = ifc.createIfcSIUnit()
|
|
subject.set_active_unit(unit)
|
|
props = tool.Unit.get_unit_props()
|
|
assert props.active_unit_id == unit.id()
|