"""Tests for lines, emphasizing exact intersection. Oracles hand-derived from ``geometry/planar/Line.java``. """ from __future__ import annotations from freeroute.geometry import IntPoint, Line, RationalPoint, Side def test_side_of_point(): # Line.side_of reports where the *line* is relative to the point # (point.side_of(line).negate() in the source): a point above a +x line has # the line on its right. line = Line.from_coords(0, 0, 2, 0) # along +x assert line.side_of(IntPoint(1, 1)) == Side.ON_THE_RIGHT assert line.side_of(IntPoint(1, -1)) == Side.ON_THE_LEFT assert line.side_of(IntPoint(5, 0)) == Side.COLLINEAR def test_integral_intersection_fast_paths(): # vertical x horizontal v = Line.from_coords(3, 0, 3, 9) h = Line.from_coords(0, 4, 9, 4) assert v.intersection(h) == IntPoint(3, 4) # horizontal x right-diagonal (y=x): y=4 -> (4,4) diag = Line.from_coords(0, 0, 5, 5) assert h.intersection(diag) == IntPoint(4, 4) def test_general_integral_intersection(): # y = x/2 and y = 1 -> x = 2 a = Line.from_coords(0, 0, 2, 1) b = Line.from_coords(0, 1, 4, 1) assert a.intersection(b) == IntPoint(2, 1) def test_rational_intersection_exact(): # y = 2x/3 and y = 1 -> x = 1.5 -> RationalPoint (3,2,2) a = Line.from_coords(0, 0, 3, 2) b = Line.from_coords(0, 1, 5, 1) result = a.intersection(b) assert isinstance(result, RationalPoint) assert result == RationalPoint(3, 2, 2) assert not result.is_infinite() # float approximation agrees fp = result.to_float() assert abs(fp.x - 1.5) < 1e-9 and abs(fp.y - 1.0) < 1e-9 def test_parallel_intersection_is_infinite(): a = Line.from_coords(0, 0, 1, 0) b = Line.from_coords(0, 5, 1, 5) result = a.intersection(b) assert result.is_infinite() assert a.is_parallel(b) def test_intersection_exact_beyond_double_precision(): # Two nearly-parallel steep lines crossing at a non-integer point far out. # Coordinates chosen so a double determinant would lose bits; int stays exact. a = Line.from_coords(0, 0, 1000000, 999999) b = Line.from_coords(0, 1, 1000000, 1000000) result = a.intersection(b) assert isinstance(result, RationalPoint) # Verify exactness: the intersection lies on both lines (exact side test). assert a.side_of(result) == Side.COLLINEAR assert b.side_of(result) == Side.COLLINEAR def test_intersection_approx_matches_exact(): a = Line.from_coords(0, 0, 3, 2) b = Line.from_coords(0, 1, 5, 1) approx = a.intersection_approx(b) assert abs(approx.x - 1.5) < 1e-9 assert abs(approx.y - 1.0) < 1e-9 def test_translate_and_opposite(): line = Line.from_coords(0, 0, 4, 0) assert line.opposite().direction().equals(line.direction()) is False from freeroute.geometry import IntVector moved = line.translate_by(IntVector(0, 5)) assert moved.side_of(IntPoint(2, 5)) == Side.COLLINEAR def test_perpendicular_and_parallel_predicates(): horizontal = Line.from_coords(0, 0, 1, 0) vertical = Line.from_coords(0, 0, 0, 1) assert horizontal.is_perpendicular(vertical) assert not horizontal.is_parallel(vertical) assert horizontal.is_parallel(Line.from_coords(3, 7, 10, 7)) def test_line_equality_same_set_same_direction(): a = Line.from_coords(0, 0, 2, 0) b = Line.from_coords(-5, 0, 9, 0) # same line, same direction c = Line.from_coords(9, 0, -5, 0) # same set, opposite direction assert a == b assert a != c assert a.is_equal_or_opposite(c)