mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-10-02 13:04:49 +00:00
Refactor parse_distance_string into tool classmethod and add tests including e9eca5e behaviour
This commit is contained in:
@@ -157,7 +157,6 @@ from mathutils.kdtree import KDTree
|
|||||||
|
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
from bonsai.bim.module.drawing.shaders import ExtrusionGuidesShader
|
from bonsai.bim.module.drawing.shaders import ExtrusionGuidesShader
|
||||||
from bonsai.tool.unit import parse_distance_string
|
|
||||||
|
|
||||||
SNAP_POINT_SIZE = 10.0
|
SNAP_POINT_SIZE = 10.0
|
||||||
SNAP_POINT_COLOR = (1.0, 0.5, 0.0, 1.0)
|
SNAP_POINT_COLOR = (1.0, 0.5, 0.0, 1.0)
|
||||||
@@ -1028,7 +1027,7 @@ class NumericInputState:
|
|||||||
return
|
return
|
||||||
|
|
||||||
input_str = self.get_input_string()
|
input_str = self.get_input_string()
|
||||||
is_valid, value = parse_distance_string(input_str)
|
is_valid, value = tool.Unit.parse_distance_string(input_str)
|
||||||
|
|
||||||
if is_valid:
|
if is_valid:
|
||||||
self.parsed_value = value
|
self.parsed_value = value
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import bonsai.core.geometry
|
|||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
from bonsai.bim.module.spatial.data import SpatialDecompositionData
|
from bonsai.bim.module.spatial.data import SpatialDecompositionData
|
||||||
from bonsai.bim.prop import ObjProperty
|
from bonsai.bim.prop import ObjProperty
|
||||||
from bonsai.tool.unit import parse_distance_string
|
|
||||||
|
|
||||||
|
|
||||||
def get_subelement_class(
|
def get_subelement_class(
|
||||||
@@ -52,7 +51,7 @@ def get_subelement_class(
|
|||||||
|
|
||||||
def update_elevation(self: "BIMContainer", context: bpy.types.Context) -> None:
|
def update_elevation(self: "BIMContainer", context: bpy.types.Context) -> None:
|
||||||
# Try to parse the input string with unit support first
|
# Try to parse the input string with unit support first
|
||||||
is_valid, parsed_elevation = parse_distance_string(self.elevation, use_project_unit=True)
|
is_valid, parsed_elevation = tool.Unit.parse_distance_string(self.elevation, use_project_unit=True)
|
||||||
|
|
||||||
if is_valid:
|
if is_valid:
|
||||||
elevation = parsed_elevation
|
elevation = parsed_elevation
|
||||||
|
|||||||
@@ -1132,7 +1132,6 @@ class Unit:
|
|||||||
def set_active_unit(cls, unit): pass
|
def set_active_unit(cls, unit): pass
|
||||||
def get_project_currency_unit(cls): pass
|
def get_project_currency_unit(cls): pass
|
||||||
def get_currency_name(cls): pass
|
def get_currency_name(cls): pass
|
||||||
def add_mass_and_time_units(cls): pass
|
|
||||||
|
|
||||||
@interface
|
@interface
|
||||||
class Voider:
|
class Voider:
|
||||||
|
|||||||
@@ -34,7 +34,35 @@ if TYPE_CHECKING:
|
|||||||
from bonsai.bim.module.unit.prop import BIMUnitProperties
|
from bonsai.bim.module.unit.prop import BIMUnitProperties
|
||||||
|
|
||||||
|
|
||||||
def parse_distance_string(input_string: str, use_project_unit: bool = True) -> tuple[bool, float]:
|
class Unit(bonsai.core.tool.Unit):
|
||||||
|
UNIT_TYPE = Literal["LENGTHUNIT", "AREAUNIT", "VOLUMEUNIT", "MASSUNIT", "TIMEUNIT"]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def format_distance(meters: float, use_imperial: bool = None, **kwargs) -> str:
|
||||||
|
"""
|
||||||
|
Format a distance value in meters to a string in the project's unit system.
|
||||||
|
|
||||||
|
:param meters: The distance value in meters
|
||||||
|
:param use_imperial: If True, format as imperial; if False, format as metric; if None, auto-detect from scene
|
||||||
|
:param kwargs: Additional arguments to pass to the underlying format_distance function
|
||||||
|
(hide_units, precision, decimal_places, etc.)
|
||||||
|
:return: Formatted string with units
|
||||||
|
"""
|
||||||
|
# Import the comprehensive format_distance from the helper module
|
||||||
|
from bonsai.bim.module.drawing import helper
|
||||||
|
|
||||||
|
# The comprehensive function expects value in scene units, not meters
|
||||||
|
# So we pass meters directly since it handles unit conversion internally
|
||||||
|
return helper.format_distance(
|
||||||
|
meters,
|
||||||
|
hide_units=kwargs.get("hide_units", False),
|
||||||
|
precision=kwargs.get("precision"),
|
||||||
|
decimal_places=kwargs.get("decimal_places"),
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse_distance_string(cls, input_string: str, use_project_unit: bool = True) -> tuple[bool, float]:
|
||||||
"""
|
"""
|
||||||
Parse a distance string with optional unit suffixes and convert to meters.
|
Parse a distance string with optional unit suffixes and convert to meters.
|
||||||
|
|
||||||
@@ -272,34 +300,6 @@ def parse_distance_string(input_string: str, use_project_unit: bool = True) -> t
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return False, 0.0
|
return False, 0.0
|
||||||
|
|
||||||
|
|
||||||
class Unit(bonsai.core.tool.Unit):
|
|
||||||
UNIT_TYPE = Literal["LENGTHUNIT", "AREAUNIT", "VOLUMEUNIT", "MASSUNIT", "TIMEUNIT"]
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def format_distance(meters: float, use_imperial: bool = None, **kwargs) -> str:
|
|
||||||
"""
|
|
||||||
Format a distance value in meters to a string in the project's unit system.
|
|
||||||
|
|
||||||
:param meters: The distance value in meters
|
|
||||||
:param use_imperial: If True, format as imperial; if False, format as metric; if None, auto-detect from scene
|
|
||||||
:param kwargs: Additional arguments to pass to the underlying format_distance function
|
|
||||||
(hide_units, precision, decimal_places, etc.)
|
|
||||||
:return: Formatted string with units
|
|
||||||
"""
|
|
||||||
# Import the comprehensive format_distance from the helper module
|
|
||||||
from bonsai.bim.module.drawing import helper
|
|
||||||
|
|
||||||
# The comprehensive function expects value in scene units, not meters
|
|
||||||
# So we pass meters directly since it handles unit conversion internally
|
|
||||||
return helper.format_distance(
|
|
||||||
meters,
|
|
||||||
hide_units=kwargs.get("hide_units", False),
|
|
||||||
precision=kwargs.get("precision"),
|
|
||||||
decimal_places=kwargs.get("decimal_places"),
|
|
||||||
**kwargs,
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_unit_props(cls) -> BIMUnitProperties:
|
def get_unit_props(cls) -> BIMUnitProperties:
|
||||||
return bpy.context.scene.BIMUnitProperties
|
return bpy.context.scene.BIMUnitProperties
|
||||||
|
|||||||
@@ -33,6 +33,17 @@ class TestImplementsTool(NewFile):
|
|||||||
assert isinstance(subject(), bonsai.core.tool.Unit)
|
assert isinstance(subject(), bonsai.core.tool.Unit)
|
||||||
|
|
||||||
|
|
||||||
|
class TestParseDistanceString(NewFile):
|
||||||
|
def test_run(self):
|
||||||
|
assert subject.parse_distance_string("5m") == (True, 5.0)
|
||||||
|
assert subject.parse_distance_string("30cm") == (True, 0.3)
|
||||||
|
assert subject.parse_distance_string("10ft") == (True, 3.048)
|
||||||
|
assert subject.parse_distance_string("12in") == (True, 0.3048)
|
||||||
|
assert subject.parse_distance_string("5'6\"") == (True, 1.6764)
|
||||||
|
assert subject.parse_distance_string("-5'6\"") == (True, -1.6764)
|
||||||
|
assert subject.parse_distance_string("invalid") == (False, 0.0)
|
||||||
|
|
||||||
|
|
||||||
class TestClearActiveUnit(NewFile):
|
class TestClearActiveUnit(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
props = tool.Unit.get_unit_props()
|
props = tool.Unit.get_unit_props()
|
||||||
|
|||||||
Reference in New Issue
Block a user