From e6d4274525a236949e6ac87a0dbef68250c01199 Mon Sep 17 00:00:00 2001 From: Tia Lechner Date: Tue, 27 Oct 2026 12:13:33 +0100 Subject: [PATCH] sixth commit: test added --- src/matrixmania/__init__.py | 2 +- src/matrixmania/compute.py | 20 ++++++++ .../test_project_perspective.py | 48 +++++++++++++++++++ test/test_matrixmania/test_projection.py | 21 ++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 test/test_matrixmania/test_project_perspective.py create mode 100644 test/test_matrixmania/test_projection.py diff --git a/src/matrixmania/__init__.py b/src/matrixmania/__init__.py index c812c86..bcee88e 100644 --- a/src/matrixmania/__init__.py +++ b/src/matrixmania/__init__.py @@ -1 +1 @@ -from .compute import matmul, transpose, rot_2D, rot_3D \ No newline at end of file +from .compute import matmul, transpose, rot_2D, rot_3D, project_ortho, project_perspective \ No newline at end of file diff --git a/src/matrixmania/compute.py b/src/matrixmania/compute.py index 55d9c96..c65fca6 100644 --- a/src/matrixmania/compute.py +++ b/src/matrixmania/compute.py @@ -142,6 +142,26 @@ def rot_3D(angle: float, axis: str) -> list[list[float]]: [0, 0, 1], ] +def project_ortho(point: tuple[float, float, float], scale: float = 1) -> tuple[float, float]: + """Project a 3D point onto a 2D plane using orthogonal projection.""" + x, y, _z = point + return (x * scale, y * scale) + + +def project_perspective(point: tuple[float, float, float], + focal_length: float = 1.0, + scale: float = 1.0, + camera_distance: float = 4.0) -> tuple[float, float]: + """Project a 3D point onto a 2D plane using perspective projection.""" + x, y ,z = point + factor = focal_length / (z+camera_distance) + x_2d = x * factor * scale + y_2d = y * factor * scale + return (x_2d, y_2d) + + + + if __name__ == "__main__": diff --git a/test/test_matrixmania/test_project_perspective.py b/test/test_matrixmania/test_project_perspective.py new file mode 100644 index 0000000..bc6ecfe --- /dev/null +++ b/test/test_matrixmania/test_project_perspective.py @@ -0,0 +1,48 @@ +import math +import pytest + +from matrixmania import project_perspective + + +def approx_equal(a: float, b: float, rel_tol: float = 1e-9) -> bool: + """Utility to compare two floats with a relative tolerance.""" + return math.isclose(a, b, rel_tol=rel_tol) + + +@pytest.mark.parametrize( + "point,focal_length,scale,expected", + [ + # Case 1 – no scaling, unit focal length + ( + (1.0, 2.0, 3.0), + 1.0, # focal_length + 1.0, # scale + ( + 1.0 / (4.0 + 3.0), # x projected + 2.0 / (4.0 + 3.0), # y projected + ), + ), + # Case 2 – scale 100, focal length 2 + ( + (1.0, 2.0, 3.0), + 2.0, # focal_length + 100.0, # scale + ( + 2.0 * 100.0 / (4.0 + 3.0), # x projected + 2.0 * 100.0 * 2.0 / (4.0 + 3.0), # y projected + ), + ), + ], +) +def test_project_perspective(point, focal_length, scale, expected): + """Test that project_perspective returns the correct 2‑D projection.""" + # Call the function under test + result = project_perspective(point, focal_length=focal_length, scale=scale) + + # Basic sanity checks + assert isinstance(result, tuple), "Result should be a tuple" + assert len(result) == 2, "Result should contain two coordinates" + + # Confirm values are close to expected (within tiny tolerance) + assert approx_equal(result[0], expected[0]), f"X coordinate mismatch: {result[0]} != {expected[0]}" + assert approx_equal(result[1], expected[1]), f"Y coordinate mismatch: {result[1]} != {expected[1]}" \ No newline at end of file diff --git a/test/test_matrixmania/test_projection.py b/test/test_matrixmania/test_projection.py new file mode 100644 index 0000000..3a8c7e9 --- /dev/null +++ b/test/test_matrixmania/test_projection.py @@ -0,0 +1,21 @@ +from matrixmania import project_ortho + + +def test_projection_point(): + #Arrange + point = (1.0, 2.0, 3.0) + expected_value = (1.0, 2.0) + + #Act + result = project_ortho(point) + + #Assert + assert result == expected_value + +def test_projection_scale(): + point = (1.0, 2.0, 3.0) + scale = 100 + expected_value = (100.0, 200.0) + + result = project_ortho(point, scale) + assert result == expected_value