Skip to content

Commit

Permalink
Added unit scaling functions in units.py
Browse files Browse the repository at this point in the history
  • Loading branch information
JR-Morgan committed Sep 6, 2023
1 parent 9723394 commit 2b583fd
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 2 deletions.
37 changes: 35 additions & 2 deletions src/specklepy/objects/units.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Units(Enum):
Units.none: ["none", "null"],
}


UNITS_ENCODINGS = {
Units.none: 0,
None: 0,
Expand All @@ -49,6 +50,20 @@ class Units(Enum):
}


UNIT_SCALE = {
Units.none: 1,
Units.mm: 0.001,
Units.cm: 0.01,
Units.m: 1.0,
Units.km: 1000.0,
Units.inches: 0.0254,
Units.feet: 0.3048,
Units.yards: 0.9144,
Units.miles: 1609.340,
}
"""Unit scaling factor to meters"""


def get_units_from_string(unit: str) -> Units:
if not isinstance(unit, str):
raise SpeckleInvalidUnitException(unit)
Expand All @@ -59,10 +74,10 @@ def get_units_from_string(unit: str) -> Units:
raise SpeckleInvalidUnitException(unit)


def get_units_from_encoding(unit: int):
def get_units_from_encoding(unit: int) -> Units:
for name, encoding in UNITS_ENCODINGS.items():
if unit == encoding:
return name
return name or Units.none

raise SpeckleException(
message=(
Expand All @@ -87,3 +102,21 @@ def get_encoding_from_units(unit: Union[Units, str, None]):
f"Please enter a valid unit to encode (eg {UNITS_ENCODINGS})."
)
) from e


def get_scale_factor_from_string(fromUnits: str, toUnits: str) -> float:
"""Returns a scalar to convert distance values from one unit system to another"""
return get_scale_factor(get_units_from_string(fromUnits), get_units_from_string(toUnits))


def get_scale_factor(fromUnits: Units, toUnits: Units) -> float:
"""Returns a scalar to convert distance values from one unit system to another"""
return get_scale_factor_to_meters(fromUnits) / get_scale_factor_to_meters(toUnits)


def get_scale_factor_to_meters(fromUnits: Units) -> float:
"""Returns a scalar to convert distance values from one unit system to meters"""
if fromUnits not in UNIT_SCALE:
raise ValueError(f"Invalid units provided: {fromUnits}")

return UNIT_SCALE[fromUnits]
56 changes: 56 additions & 0 deletions tests/unit/test_unit_scaling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@


import pytest

from specklepy.objects.units import Units, get_scale_factor


@pytest.mark.parametrize(
"fromUnits, toUnits, inValue, expectedOutValue",
[
#To self
(Units.km, Units.km, 1.5, 1.5),
(Units.km, Units.km, 0, 0),
(Units.m, Units.m, 1.5, 1.5),
(Units.m, Units.m, 0, 0),
(Units.cm, Units.cm, 1.5, 1.5),
(Units.cm, Units.cm, 0, 0),
(Units.mm, Units.mm, 1.5, 1.5),
(Units.mm, Units.mm, 0, 0),
(Units.miles, Units.miles, 1.5, 1.5),
(Units.miles, Units.miles, 0, 0),
(Units.yards, Units.yards, 1.5, 1.5),
(Units.yards, Units.yards, 0, 0),
(Units.feet, Units.feet, 1.5, 1.5),
(Units.feet, Units.feet, 0, 0),
#To Meters
(Units.km, Units.m, 987654.321, 987654321),
(Units.m, Units.m, 987654.321, 987654.321),
(Units.mm, Units.m, 98765432.1, 98765.4321),
(Units.cm, Units.m, 9876543.21, 98765.4321),
#To negative meters
(Units.km, Units.m, -987654.321, -987654321),
(Units.m, Units.m,- 987654.321, -987654.321),
(Units.mm, Units.m, -98765432.1, -98765.4321),
(Units.cm, Units.m, -9876543.21, -98765.4321),
(Units.m, Units.km, 987654.321, 987.654321),
(Units.m, Units.cm, 987654.321, 98765432.1),
(Units.m, Units.mm, 987654.321, 987654321),
#Imperial
(Units.miles, Units.m, 123.45, 198673.517),
(Units.miles, Units.inches, 123.45, 7821792),
(Units.yards, Units.m, 123.45, 112.88268),
(Units.yards, Units.inches, 123.45, 4444.2),
(Units.feet, Units.m, 123.45, 37.62756),
(Units.feet, Units.inches, 123.45, 1481.4),
(Units.inches, Units.m, 123.45, 3.13563),
],
)
def test_get_scale_factor_between_units(fromUnits: Units, toUnits: Units, inValue: float, expectedOutValue: float):
Tolerance = 1e-10
actual = inValue * get_scale_factor(fromUnits, toUnits)
assert(actual - expectedOutValue < Tolerance)

0 comments on commit 2b583fd

Please sign in to comment.