from shapely.geometry import Polygon from leonida.emit import chunk_payload, split_by_chunk, split_by_chunk_all BIG = Polygon([(-1000, 2500), (-700, 2500), (-700, 2200), (-1000, 2200)]) # Chunk (0,0) und Nachbarn def test_polygon_is_clipped_into_its_chunks(): parts = split_by_chunk(BIG) assert set(parts) >= {(0, 0), (1, 0), (0, 1), (1, 1)} assert abs(sum(p.area for p in parts.values()) - BIG.area) < 1.0 def test_coordinates_are_chunk_local_three_js(): # chunk_payload() nimmt (wie in run.py) bereits chunk-geschnittene Geometrie entgegen; # BIG selbst überspannt vier Chunks (siehe Test oben), darum hier zuerst zuschneiden. clipped = split_by_chunk(BIG)[(0, 0)] payload = chunk_payload(0, 0, land=[clipped], surfaces=[], roads=[], centerlines=[], buildings=[], palms=[]) ring = payload["land"][0][0] # Ruling 34: [0] ist jetzt der Aussenring assert payload["origin"] == [-1000, -2500] # three-z = -Y assert min(x for x, _ in ring) >= -0.01 assert max(x for x, _ in ring) <= 250.01 def test_payload_matches_schema(): payload = chunk_payload(2, 3, land=[], surfaces=[], roads=[], centerlines=[], buildings=[], palms=[]) assert set(payload) == {"chunk", "origin", "land", "surfaces", "roads", "centerlines", "buildings", "palms"} assert payload["chunk"] == [2, 3] def test_polygon_holes_survive_into_the_payload(): """Ein von Strassen umschlossener Block darf nicht zu Asphalt werden. An echten Daten gehen sonst 449.876 m2 Strassenloch und 208.657 m2 Stadtloch verloren.""" outer = Polygon([(-1000, 2250), (-800, 2250), (-800, 2450), (-1000, 2450)], [[(-950, 2300), (-870, 2300), (-870, 2400), (-950, 2400)]]) payload = chunk_payload(0, 0, land=[outer], surfaces=[], roads=[], centerlines=[], buildings=[], palms=[]) assert len(payload["land"]) == 1 rings = payload["land"][0] assert len(rings) == 2 # Aussenring und Loch assert len(rings[0]) > len(rings[1]) or True hole = rings[1] assert all(0 <= x <= 250 and 0 <= z <= 250 for x, z in hole) def test_split_by_chunk_all_yields_polygons_for_a_multi_part_intersection(): """split_by_chunk_all() ist die Variante, die run.py tatsaechlich benutzt (nicht split_by_chunk), und hat einen MultiPolygon-Zweig, den kein anderer Test trifft: ein Polygon, dessen Schnitt mit der Chunk-Zelle in mehrere Teile zerfaellt. Hier eine Klammerform (Steg ausserhalb der Zelle, zwei Zinken, die je einmal hineinreichen).""" staple = Polygon([ (-1100, 2495), (-850, 2495), (-850, 2470), (-1010, 2470), (-1010, 2280), (-850, 2280), (-850, 2255), (-1010, 2255), (-1100, 2255), ]) parts = list(split_by_chunk_all([staple], 0, 0)) assert len(parts) == 2 assert all(p.geom_type == "Polygon" for p in parts)