Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions cad_core/units.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from __future__ import annotations

from decimal import ROUND_HALF_UP, Decimal

MM_PER_INCH = 25.4

# Global default tolerance for geometric comparisons
EPS: float = 1e-9


def mm_to_inch(mm: float) -> float:
return mm / MM_PER_INCH


def inch_to_mm(inch: float) -> float:
return inch * MM_PER_INCH


def almost_equal(a: float, b: float, tol: float = EPS) -> bool:
return abs(a - b) <= tol


def clamp(x: float, lo: float, hi: float) -> float:
if lo > hi:
lo, hi = hi, lo
return hi if x > hi else lo if x < lo else x


def sgn(x: float, tol: float = EPS) -> int:
if x > tol:
return 1
if x < -tol:
return -1
return 0


def round_tol(value: float, tol: float = 1e-6) -> float:
if tol <= 0:
return value
# Try decimal quantization for decimal-friendly tolerances to avoid FP drift
try:
dval = Decimal(str(value))
dtol = Decimal(str(tol))
q = (dval / dtol).to_integral_value(rounding=ROUND_HALF_UP)
return float(q * dtol)
except Exception:
return round(value / tol) * tol
17 changes: 17 additions & 0 deletions tasks/chore-cad-core-units-tolerances-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Task: cad_core – Units tolerances tests

Scope
- Add focused tests for `cad_core/units.py`: `EPS`, `almost_equal`, `clamp`, `sgn`, `round_tol`.

Details
- New file: `tests/cad_core/test_units_tolerances.py` with small, isolated cases.
- Ensure no dependency on UI or other modules; pure functions only.
- Keep tolerance behavior consistent across core geometry.

Acceptance
- `pytest -q` passes; new tests cover edge cases (negative, swapped bounds, zero tol).
- `ruff` and `black --check` pass.

Branch
- `chore/cad-core-units-tolerances-tests`

29 changes: 29 additions & 0 deletions tasks/pr/chore-cad-core-units-tolerances-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Title: chore(cad_core): add units tolerances tests

Summary
- Adds focused tests for `cad_core/units.py` covering `EPS`, `almost_equal`, `clamp`, `sgn`, and `round_tol`.
- Introduces `cad_core/units.py` helpers with improved `round_tol` using Decimal to avoid FP drift.

Changes
- New: `tests/cad_core/test_units_tolerances.py`
- New: `cad_core/units.py`
- Task: `tasks/chore-cad-core-units-tolerances-tests.md`

Rationale
- Establish consistent tolerance behavior used across core geometry.
- Provide small, pure tests to keep regressions visible and fast.

Test Plan (agents pulling this)
- From repo root:
- `python -m pip install -e .` (or set `PYTHONPATH` to repo root)
- `ruff check cad_core tests/cad_core/test_units_tolerances.py`
- `black --check cad_core tests/cad_core/test_units_tolerances.py`
- `pytest -q tests/cad_core/test_units_tolerances.py`

Notes
- No UI impact; pure functions only.
- Keep `EPS` and helpers as the single source of tolerance logic across CAD core.

Refs
- Issue: N/A (please update if applicable)

37 changes: 37 additions & 0 deletions tests/cad_core/test_units_tolerances.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from cad_core.units import EPS, almost_equal, clamp, round_tol, sgn


def test_eps_value_and_usage():
assert isinstance(EPS, float)
assert EPS == 1e-9
# Values within EPS are considered equal
assert almost_equal(1.0, 1.0 + EPS * 0.5)


def test_almost_equal_with_custom_tol():
assert almost_equal(0.0, 1e-6, tol=1e-5)
assert not almost_equal(0.0, 2e-5, tol=1e-5)


def test_clamp_basic_and_swapped_bounds():
assert clamp(5.0, 0.0, 10.0) == 5.0
assert clamp(-1.0, 0.0, 10.0) == 0.0
assert clamp(11.0, 0.0, 10.0) == 10.0
# Swapped bounds should be handled
assert clamp(5.0, 10.0, 0.0) == 5.0


def test_sgn_with_tolerance():
assert sgn(1.0) == 1
assert sgn(-1.0) == -1
assert sgn(EPS * 0.5) == 0
assert sgn(-EPS * 0.5) == 0


def test_round_tol_behaviour():
assert round_tol(1.2345, 0.01) == 1.23
assert round_tol(-1.234, 0.1) == -1.2
# Non-positive tolerance returns the input as-is
x = 3.14159
assert round_tol(x, 0.0) == x
assert round_tol(x, -0.1) == x
Loading