Spaces:
Sleeping
Sleeping
File size: 5,231 Bytes
9f084b2 bbbfba8 9f084b2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | """Tests for geometry/transforms.py — coordinate transformations."""
from __future__ import annotations
import pytest
from src.app.geometry import transforms
class TestRescaleBbox:
def test_upscale(self) -> None:
result = transforms.rescale_bbox((10, 20, 100, 50), 2.0)
assert result == (20, 40, 200, 100)
def test_downscale(self) -> None:
result = transforms.rescale_bbox((10, 20, 100, 50), 0.5)
assert result == (5, 10, 50, 25)
def test_identity(self) -> None:
b = (10, 20, 100, 50)
assert transforms.rescale_bbox(b, 1.0) == b
def test_zero_factor_rejected(self) -> None:
with pytest.raises(ValueError, match="must be > 0"):
transforms.rescale_bbox((0, 0, 10, 10), 0)
def test_negative_factor_rejected(self) -> None:
with pytest.raises(ValueError, match="must be > 0"):
transforms.rescale_bbox((0, 0, 10, 10), -1)
class TestRescalePolygon:
def test_upscale(self) -> None:
poly = [(10, 20), (30, 20), (30, 40), (10, 40)]
result = transforms.rescale_polygon(poly, 2.0)
assert result == [(20, 40), (60, 40), (60, 80), (20, 80)]
def test_zero_rejected(self) -> None:
with pytest.raises(ValueError):
transforms.rescale_polygon([(0, 0)], 0)
class TestClipBboxToPage:
def test_already_inside(self) -> None:
result = transforms.clip_bbox_to_page((10, 20, 50, 30), 100, 100)
assert result == (10, 20, 50, 30)
def test_overflow_right(self) -> None:
result = transforms.clip_bbox_to_page((80, 10, 50, 20), 100, 100)
# x=80, x2=130, clipped to x2=100, so w=20
assert result == (80, 10, 20, 20)
def test_overflow_bottom(self) -> None:
result = transforms.clip_bbox_to_page((10, 85, 20, 30), 100, 100)
assert result == (10, 85, 20, 15)
def test_negative_origin(self) -> None:
result = transforms.clip_bbox_to_page((-5, -10, 50, 50), 100, 100)
assert result[0] == 0
assert result[1] == 0
def test_min_dimension_1(self) -> None:
# bbox entirely outside right edge
result = transforms.clip_bbox_to_page((200, 50, 10, 10), 100, 100)
assert result[2] >= 1
assert result[3] >= 1
class TestClipPolygonToPage:
def test_clamp(self) -> None:
poly = [(-5, -10), (150, -10), (150, 120), (-5, 120)]
result = transforms.clip_polygon_to_page(poly, 100, 100)
assert result == [(0, 0), (100, 0), (100, 100), (0, 100)]
class TestRotateBbox90:
def test_once(self) -> None:
# Page 100x200, bbox at (10, 20, 30, 40)
# After 90° CW: new_x = 200 - 20 - 40 = 140, new_y = 10
# w and h swap: w=40, h=30
result = transforms.rotate_bbox_90((10, 20, 30, 40), 100, 200, times=1)
assert result == (140, 10, 40, 30)
def test_twice(self) -> None:
# 180°: (page_w - x - w, page_h - y - h, w, h)
result = transforms.rotate_bbox_90((10, 20, 30, 40), 100, 200, times=2)
assert result == (60, 140, 30, 40)
def test_four_times_identity(self) -> None:
b = (10, 20, 30, 40)
result = transforms.rotate_bbox_90(b, 100, 200, times=4)
assert result == pytest.approx(b)
def test_zero_times_identity(self) -> None:
b = (10, 20, 30, 40)
result = transforms.rotate_bbox_90(b, 100, 200, times=0)
assert result == b
class TestRescalePoint:
def test_upscale(self) -> None:
assert transforms.rescale_point((10, 20), 2.0) == (20, 40)
def test_zero_rejected(self) -> None:
with pytest.raises(ValueError, match="must be > 0"):
transforms.rescale_point((10, 20), 0)
class TestRotatePoint90:
def test_once(self) -> None:
# Page 100x200, point (10, 20) → (200 - 20, 10) = (180, 10)
assert transforms.rotate_point_90((10, 20), 100, 200, times=1) == (180, 10)
def test_four_times_identity(self) -> None:
p = (10, 20)
result = transforms.rotate_point_90(p, 100, 200, times=4)
assert result == pytest.approx(p)
def test_zero_times_identity(self) -> None:
p = (10, 20)
assert transforms.rotate_point_90(p, 100, 200, times=0) == p
class TestRotatePolygon90:
def test_rotates_all_points(self) -> None:
poly = [(0, 0), (10, 0), (10, 10), (0, 10)]
result = transforms.rotate_polygon_90(poly, 100, 200, times=1)
assert len(result) == 4
# Check first point: (0,0) → (200-0, 0) = (200, 0)
assert result[0] == (200, 0)
def test_four_times_identity(self) -> None:
poly = [(10, 20), (30, 20), (30, 40), (10, 40)]
result = transforms.rotate_polygon_90(poly, 100, 200, times=4)
for orig, rotated in zip(poly, result, strict=True):
assert rotated == pytest.approx(orig)
class TestTranslate:
def test_bbox(self) -> None:
result = transforms.translate_bbox((10, 20, 30, 40), 5, -10)
assert result == (15, 10, 30, 40)
def test_polygon(self) -> None:
poly = [(0, 0), (10, 0), (10, 10)]
result = transforms.translate_polygon(poly, 100, 200)
assert result == [(100, 200), (110, 200), (110, 210)]
|