import numpy as np from leonida.classify import CLASSES from leonida.vectors import centerlines, land_polygons, mask_polygons, road_polygons def test_square_becomes_one_polygon_with_right_area(): mask = np.zeros((100, 100), dtype=bool) mask[20:60, 30:80] = True # 40 x 50 Pixel = 2000 m² polys = mask_polygons(mask, min_area=10, simplify=1.0) assert len(polys) == 1 assert abs(polys[0].area - 2000) < 60 # Vereinfachung darf etwas abweichen def test_island_keeps_its_lagoon(): labels = np.full((80, 80), CLASSES["wasser"], dtype=np.uint8) labels[10:70, 10:70] = CLASSES["land"] labels[30:50, 30:50] = CLASSES["wasser"] # Lagune polys = land_polygons(labels) assert len(polys) == 1 assert len(polys[0].interiors) == 1 def test_road_over_water_is_flagged_as_bridge(): labels = np.full((60, 60), CLASSES["wasser"], dtype=np.uint8) labels[0:10, :] = CLASSES["land"] labels[25:31, :] = CLASSES["strasse"] # Damm quer durchs Wasser roads = road_polygons(labels) assert len(roads) == 1 assert roads[0][1] is True def test_crossing_roads_form_a_single_polygon(): labels = np.full((60, 60), CLASSES["land"], dtype=np.uint8) labels[28:32, :] = CLASSES["strasse"] labels[:, 28:32] = CLASSES["strasse"] roads = road_polygons(labels) assert len(roads) == 1 # Kreuzung, kein Zerfall in vier Arme def test_centerline_runs_once_along_a_straight_road(): labels = np.full((60, 300), CLASSES["land"], dtype=np.uint8) labels[28:38, 50:250] = CLASSES["strasse"] # 200 lang, 10 breit lines = centerlines(labels) assert len(lines) == 1 assert 180 <= lines[0].length <= 215 # einmal entlang, nicht hin und zurück def test_crossing_roads_yield_separate_centerlines(): labels = np.full((120, 120), CLASSES["land"], dtype=np.uint8) labels[55:65, :] = CLASSES["strasse"] labels[:, 55:65] = CLASSES["strasse"] assert len(centerlines(labels)) >= 3 # Arme werden an der Kreuzung getrennt def test_wide_road_area_on_land_is_not_a_bridge(): """Eine breite Kreuzungsfläche ohne Wasser in der Nähe ist nie eine Brücke. Ihre Mitte liegt weiter als LAND_REACH_PX von straßenfreiem Land entfernt, weil dort nur Straße ist — das allein darf sie nicht zur Brücke machen. """ labels = np.full((120, 120), CLASSES["land"], dtype=np.uint8) labels[30:90, 30:90] = CLASSES["strasse"] # 60x60 Straßenfläche, kein Wasser pieces = road_polygons(labels) assert pieces assert not any(bridge for _, bridge in pieces)