2020-05-17 18:32:56 +10:00
|
|
|
from math import pi
|
|
|
|
|
|
2020-11-01 20:08:27 +07:00
|
|
|
prefixes = {
|
|
|
|
|
"EXA": 1e18,
|
|
|
|
|
"PETA": 1e15,
|
|
|
|
|
"TERA": 1e12,
|
|
|
|
|
"GIGA": 1e9,
|
|
|
|
|
"MEGA": 1e6,
|
|
|
|
|
"KILO": 1e3,
|
|
|
|
|
"HECTO": 1e2,
|
|
|
|
|
"DECA": 1e1,
|
|
|
|
|
"DECI": 1e-1,
|
|
|
|
|
"CENTI": 1e-2,
|
|
|
|
|
"MILLI": 1e-3,
|
|
|
|
|
"MICRO": 1e-6,
|
|
|
|
|
"NANO": 1e-9,
|
|
|
|
|
"PICO": 1e-12,
|
|
|
|
|
"FEMTO": 1e-15,
|
|
|
|
|
"ATTO": 1e-18,
|
|
|
|
|
}
|
2020-05-17 18:32:56 +10:00
|
|
|
|
2020-11-01 20:08:27 +07:00
|
|
|
unit_names = [
|
|
|
|
|
"AMPERE",
|
|
|
|
|
"BECQUEREL",
|
|
|
|
|
"CANDELA",
|
|
|
|
|
"COULOMB",
|
|
|
|
|
"CUBIC_METRE",
|
|
|
|
|
"DEGREE CELSIUS",
|
|
|
|
|
"FARAD",
|
|
|
|
|
"GRAM",
|
|
|
|
|
"GRAY",
|
|
|
|
|
"HENRY",
|
|
|
|
|
"HERTZ",
|
|
|
|
|
"JOULE",
|
|
|
|
|
"KELVIN",
|
|
|
|
|
"LUMEN",
|
|
|
|
|
"LUX",
|
|
|
|
|
"MOLE",
|
|
|
|
|
"NEWTON",
|
|
|
|
|
"OHM",
|
|
|
|
|
"PASCAL",
|
|
|
|
|
"RADIAN",
|
|
|
|
|
"SECOND",
|
|
|
|
|
"SIEMENS",
|
|
|
|
|
"SIEVERT",
|
|
|
|
|
"SQUARE METRE",
|
|
|
|
|
"METRE",
|
|
|
|
|
"STERADIAN",
|
|
|
|
|
"TESLA",
|
|
|
|
|
"VOLT",
|
|
|
|
|
"WATT",
|
|
|
|
|
"WEBER",
|
|
|
|
|
]
|
2020-05-17 18:32:56 +10:00
|
|
|
|
2021-08-06 12:38:34 +10:00
|
|
|
si_dimensions = {
|
|
|
|
|
"METRE": (1, 0, 0, 0, 0, 0, 0),
|
|
|
|
|
"SQUARE_METRE": (2, 0, 0, 0, 0, 0, 0),
|
|
|
|
|
"CUBIC_METRE": (3, 0, 0, 0, 0, 0, 0),
|
|
|
|
|
"GRAM": (0, 1, 0, 0, 0, 0, 0),
|
|
|
|
|
"SECOND": (0, 0, 1, 0, 0, 0, 0),
|
|
|
|
|
"AMPERE": (0, 0, 0, 1, 0, 0, 0),
|
|
|
|
|
"KELVIN": (0, 0, 0, 0, 1, 0, 0),
|
|
|
|
|
"MOLE": (0, 0, 0, 0, 0, 1, 0),
|
|
|
|
|
"CANDELA": (0, 0, 0, 0, 0, 0, 1),
|
|
|
|
|
"RADIAN": (0, 0, 0, 0, 0, 0, 0),
|
|
|
|
|
"STERADIAN": (0, 0, 0, 0, 0, 0, 0),
|
|
|
|
|
"HERTZ": (0, 0, -1, 0, 0, 0, 0),
|
|
|
|
|
"NEWTON": (1, 1, -2, 0, 0, 0, 0),
|
|
|
|
|
"PASCAL": (-1, 1, -2, 0, 0, 0, 0),
|
|
|
|
|
"JOULE": (2, 1, -2, 0, 0, 0, 0),
|
|
|
|
|
"WATT": (2, 1, -3, 0, 0, 0, 0),
|
|
|
|
|
"COULOMB": (0, 0, 1, 1, 0, 0, 0),
|
|
|
|
|
"VOLT": (2, 1, -3, -1, 0, 0, 0),
|
|
|
|
|
"FARAD": (-2, -1, 4, 2, 0, 0, 0),
|
|
|
|
|
"OHM": (2, 1, -3, -2, 0, 0, 0),
|
|
|
|
|
"SIEMENS": (-2, -1, 3, 2, 0, 0, 0),
|
|
|
|
|
"WEBER": (2, 1, -2, -1, 0, 0, 0),
|
|
|
|
|
"TESLA": (0, 1, -2, -1, 0, 0, 0),
|
|
|
|
|
"HENRY": (2, 1, -2, -2, 0, 0, 0),
|
|
|
|
|
"DEGREE_CELSIUS": (0, 0, 0, 0, 1, 0, 0),
|
|
|
|
|
"LUMEN": (0, 0, 0, 0, 0, 0, 1),
|
|
|
|
|
"LUX": (-2, 0, 0, 0, 0, 0, 1),
|
|
|
|
|
"BECQUEREL": (0, 0, -1, 0, 0, 0, 0),
|
|
|
|
|
"GRAY": (2, 0, -2, 0, 0, 0, 0),
|
|
|
|
|
"SIEVERT": (2, 0, -2, 0, 0, 0, 0),
|
|
|
|
|
"OTHERWISE": (0, 0, 0, 0, 0, 0, 0)
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-17 18:32:56 +10:00
|
|
|
si_conversions = {
|
2020-11-01 20:08:27 +07:00
|
|
|
"inch": 0.0254,
|
|
|
|
|
"foot": 0.3048,
|
|
|
|
|
"yard": 0.914,
|
|
|
|
|
"mile": 1609,
|
|
|
|
|
"square inch": 0.0006452,
|
|
|
|
|
"square foot": 0.09290304,
|
|
|
|
|
"square yard": 0.83612736,
|
|
|
|
|
"acre": 4046.86,
|
|
|
|
|
"square mile": 2588881,
|
|
|
|
|
"cubic inch": 0.00001639,
|
|
|
|
|
"cubic foot": 0.02831684671168849,
|
|
|
|
|
"cubic yard": 0.7636,
|
|
|
|
|
"litre": 0.001,
|
|
|
|
|
"fluid ounce UK": 0.0000284130625,
|
|
|
|
|
"fluid ounce US": 0.00002957353,
|
|
|
|
|
"pint UK": 0.000568,
|
|
|
|
|
"pint US": 0.000473,
|
|
|
|
|
"gallon UK": 0.004546,
|
|
|
|
|
"gallon US": 0.003785,
|
|
|
|
|
"degree": pi / 180,
|
|
|
|
|
"ounce": 0.02835,
|
|
|
|
|
"pound": 0.454,
|
|
|
|
|
"ton UK": 1016.0469088,
|
|
|
|
|
"ton US": 907.18474,
|
|
|
|
|
"lbf": 4.4482216153,
|
|
|
|
|
"kip": 4448.2216153,
|
|
|
|
|
"psi": 6894.7572932,
|
|
|
|
|
"ksi": 6894757.2932,
|
|
|
|
|
"minute": 60,
|
|
|
|
|
"hour": 3600,
|
|
|
|
|
"day": 86400,
|
|
|
|
|
"btu": 1055.056,
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-17 18:32:56 +10:00
|
|
|
|
|
|
|
|
def get_prefix(text):
|
2021-01-19 11:18:26 +11:00
|
|
|
if text:
|
|
|
|
|
for prefix in prefixes.keys():
|
|
|
|
|
if prefix in text.upper():
|
|
|
|
|
return prefix
|
2020-05-17 18:32:56 +10:00
|
|
|
|
2020-11-01 20:08:27 +07:00
|
|
|
|
2020-05-17 18:32:56 +10:00
|
|
|
def get_prefix_multiplier(text):
|
|
|
|
|
if not text:
|
|
|
|
|
return 1
|
|
|
|
|
prefix = get_prefix(text)
|
|
|
|
|
if prefix:
|
|
|
|
|
return prefixes[prefix]
|
|
|
|
|
return 1
|
|
|
|
|
|
2020-11-01 20:08:27 +07:00
|
|
|
|
2020-05-17 18:32:56 +10:00
|
|
|
def get_unit_name(text):
|
|
|
|
|
for name in unit_names:
|
2020-11-01 20:08:27 +07:00
|
|
|
if name in text.upper().replace("METER", "METRE"):
|
2020-05-17 18:32:56 +10:00
|
|
|
return name
|
2020-08-08 16:31:27 +10:00
|
|
|
|
2020-11-01 20:08:27 +07:00
|
|
|
|
2021-08-06 12:38:34 +10:00
|
|
|
def get_si_dimensions(name):
|
|
|
|
|
return si_dimensions.get(name, si_dimensions["OTHERWISE"])
|
|
|
|
|
|
|
|
|
|
|
2020-08-08 16:31:27 +10:00
|
|
|
def convert(value, from_prefix, from_unit, to_prefix, to_unit):
|
|
|
|
|
"""Converts between length, area, and volume units
|
|
|
|
|
|
|
|
|
|
:param value: The numeric value you want to convert
|
|
|
|
|
:type value: float
|
|
|
|
|
:param from_prefix: A prefix from IfcSIPrefix. Can be None.
|
|
|
|
|
:type from_prefix: string
|
|
|
|
|
:param from_unit: IfcSIUnitName or IfcConversionBasedUnit.Name
|
|
|
|
|
:type from_unit: string
|
|
|
|
|
:param to_prefix: A prefix from IfcSIPrefix. Can be None.
|
|
|
|
|
:type to_prefix: string
|
|
|
|
|
:param to_unit: IfcSIUnitName or IfcConversionBasedUnit.Name
|
|
|
|
|
:type to_unit: string
|
|
|
|
|
"""
|
|
|
|
|
if from_unit in si_conversions:
|
|
|
|
|
value *= si_conversions[from_unit]
|
|
|
|
|
elif from_prefix:
|
|
|
|
|
value *= get_prefix_multiplier(from_prefix)
|
2020-11-01 20:08:27 +07:00
|
|
|
if "SQUARE" in from_unit:
|
2020-08-08 16:31:27 +10:00
|
|
|
value *= get_prefix_multiplier(from_prefix)
|
2020-11-01 20:08:27 +07:00
|
|
|
elif "CUBIC" in from_unit:
|
2020-08-08 16:31:27 +10:00
|
|
|
value *= get_prefix_multiplier(from_prefix)
|
|
|
|
|
value *= get_prefix_multiplier(from_prefix)
|
|
|
|
|
if to_unit in si_conversions:
|
|
|
|
|
return value * (1 / si_conversions[to_unit])
|
|
|
|
|
elif to_prefix:
|
2020-11-01 20:08:27 +07:00
|
|
|
value *= 1 / get_prefix_multiplier(to_prefix)
|
|
|
|
|
if "SQUARE" in from_unit:
|
|
|
|
|
value *= 1 / get_prefix_multiplier(to_prefix)
|
|
|
|
|
elif "CUBIC" in from_unit:
|
|
|
|
|
value *= 1 / get_prefix_multiplier(to_prefix)
|
|
|
|
|
value *= 1 / get_prefix_multiplier(to_prefix)
|
2020-08-08 16:31:27 +10:00
|
|
|
return value
|
2021-01-02 19:33:32 +11:00
|
|
|
|
|
|
|
|
|
2021-07-06 12:20:22 +10:00
|
|
|
"""Returns a unit scale factor to convert to and from IFC project length units and SI meters
|
|
|
|
|
|
|
|
|
|
Example::
|
|
|
|
|
|
|
|
|
|
ifc_project_length * unit_scale = si_meters
|
|
|
|
|
si_meters / unit_scale = ifc_project_length
|
|
|
|
|
|
|
|
|
|
:returns: The scale factor
|
|
|
|
|
:rtype: float
|
|
|
|
|
"""
|
2021-01-02 19:33:32 +11:00
|
|
|
def calculate_unit_scale(file):
|
|
|
|
|
units = file.by_type("IfcUnitAssignment")[0]
|
|
|
|
|
unit_scale = 1
|
|
|
|
|
for unit in units.Units:
|
|
|
|
|
if not hasattr(unit, "UnitType") or unit.UnitType != "LENGTHUNIT":
|
|
|
|
|
continue
|
|
|
|
|
while unit.is_a("IfcConversionBasedUnit"):
|
|
|
|
|
unit_scale *= unit.ConversionFactor.ValueComponent.wrappedValue
|
|
|
|
|
unit = unit.ConversionFactor.UnitComponent
|
|
|
|
|
if unit.is_a("IfcSIUnit"):
|
|
|
|
|
unit_scale *= get_prefix_multiplier(unit.Prefix)
|
|
|
|
|
return unit_scale
|