#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ test_dxf_scan_gf.py - Gefaellestrecken aus Staustrecken-Linien (gf_eintraege_aus_linien in lib/dxf_scan_components.py). Laeuft ohne BricsCAD und ohne DXF: die Linien und Ausschleuselemente sind die gemessenen Werte aus Dematic_arvato_reduced.dxf, von Hand nachgestellt. 1. Fallende Linie mit AS am oberen Ende -> GF, AS wird verbraucht. 2. Der Nachbar-AS der Linie daneben (800 mm Raster, auf der anderen Seite naeher dran) wird NICHT gegriffen - die Seite aus dem Blocknamen entscheidet, nicht der kleinste Abstand. 3. Rueckwaerts gezeichnete GF (tiefes Ende zuerst) -> Start bleibt oben. 4. AS am UNTEREN Ende -> Steigfoerderer, keine GF, AS bleibt unverbraucht. 5. Waagrechte Linie -> keine GF. 6. Anschluss an die Kreisel: Start/Ende werden auf die Ketten geschoben, deltaL reicht von Kette zu Kette; Hoehen kommen von den Kreiseln. 7. Separator auf der Achse wird verbraucht, einer daneben nicht. 8. hoehen_entfernen laesst nur Anwender-Hoehen stehen. """ import os import sys import pytest sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "lib")) import dxf_scan_components as dsc # noqa: E402 AS_LINKS = "Ausschleuselement links 200000217 Draufsicht" def _as(x, y, z=3191.63, block=AS_LINKS): return {"familie": "schleuselement", "block": block, "x": x, "y": y, "z": z, "rot": 270.0} def _linie(a, b, layer="6-SP"): return {"layer": layer, "a": list(a), "b": list(b)} @pytest.fixture(autouse=True) def _projekt(monkeypatch): monkeypatch.setattr(dsc, "PROJEKT", "Test") # Die beiden Kreisel am GF-Feld (Radmitten AN8 -> SP8, r = 400), wie # baue_eintraege sie als kreisel_geo anlegt. Ketten: oben y = 12919.72, # unten y = 24478.8. def _kreisel_oben(z=2437.0): return {"id": "K_oben", "a": (35460.37, 12519.72), "u": (-1.0, 0.0), "laenge": 33044.28, "r": 400.0, "z_anwender": z} def _kreisel_unten(z=1826.0): return {"id": "K_unten", "a": (36261.24, 24878.8), "u": (-1.0, 0.0), "laenge": 33470.18, "r": 400.0, "z_anwender": z} def test_gf_mit_as_am_oberen_ende(): linie = _linie((5833.56, 13348.38, 3191.63), (5833.44, 24002.54, 2821.63)) as_eigen = _as(5367.10, 14505.61) eintraege, belegt, hinweise = dsc.gf_eintraege_aus_linien([linie], [as_eigen]) assert len(eintraege) == 1 gf = eintraege[0] assert gf["test_id"] == "GF_Test_01" assert gf["modus"] == 1 # ohne Kreisel: Linienende bleibt stehen, Hoehe unbekannt -> Platzhalter assert gf["start_mm"] == [5833.56, 13348.38, 0.0] assert gf["deltaL_mm"] == pytest.approx(10654.16, abs=0.01) assert gf["hz_grad"] == 90.0 assert gf["winkel_grad"] == 3.0 assert gf["hoehe_unbekannt"] is True assert (gf["as_seite"], gf["as_winkel"]) == ("links", "90") assert belegt == {id(as_eigen)} assert len(hinweise) == 2 and all("kein Kreisel" in h for h in hinweise) def test_anschluss_an_beide_kreisel_mit_hoehen(): linie = _linie((5833.56, 13348.38, 3191.63), (5833.44, 24002.54, 2821.63)) eintraege, _, hinweise = dsc.gf_eintraege_aus_linien( [linie], [_as(5367.10, 14505.61)], [_kreisel_oben(), _kreisel_unten()]) gf = eintraege[0] assert gf["start_mm"][1] == pytest.approx(12919.72, abs=0.01) assert gf["start_mm"][2] == 2437.0 assert gf["hoehe_ende_mm"] == 1826.0 assert gf["hoehe_quelle"] == "Anwender" assert "winkel_grad" not in gf # rechnet der LISP-Treiber assert gf["deltaL_mm"] == pytest.approx(24478.8 - 12919.72, abs=0.05) assert (gf["kreisel_start"], gf["kreisel_ende"]) == ("K_oben", "K_unten") assert hinweise == [] def test_kreisel_ohne_hoehe_gibt_platzhalter(): linie = _linie((5833.56, 13348.38, 3191.63), (5833.44, 24002.54, 2821.63)) eintraege, _, _ = dsc.gf_eintraege_aus_linien( [linie], [], [_kreisel_oben(z=None), _kreisel_unten()]) assert eintraege[0]["kreisel_start"] == "K_oben" assert "hoehe_ende_mm" not in eintraege[0] assert eintraege[0]["winkel_grad"] == 3.0 def test_separator_auf_achse_wird_verbraucht(): linie = _linie((5833.56, 13348.38, 3191.63), (5833.44, 24002.54, 2821.63)) sep_achse = {"familie": "sensor", "block": "S-SP", "x": 5834.0, "y": 23810.0} sep_daneben = {"familie": "sensor", "block": "S-SP", "x": 6734.0, "y": 23810.0} scanner = {"familie": "sensor", "block": "Scanner", "x": 5834.0, "y": 20000.0} _, belegt, _ = dsc.gf_eintraege_aus_linien( [linie], [], [_kreisel_oben(), _kreisel_unten()], [sep_achse, sep_daneben, scanner]) assert belegt == {id(sep_achse)} def test_hoehen_entfernen_laesst_anwender_hoehen_stehen(): eintraege = [ {"id": "K1", "x": 0, "y": 0, "z": 2437.0, "hoehe_quelle": "Anwender"}, {"block": "S-SP", "x": 0, "y": 0, "z": 2821.63, "comment": ""}, {"test_id": "G", "typ": "gerade", "startpunkt": [0, 0, 5.0], "endpunkt": [1, 0, 5.0]}, ] assert dsc.hoehen_entfernen(eintraege) == 2 assert eintraege[0]["z"] == 2437.0 assert eintraege[1]["z"] == 0.0 and eintraege[1]["hoehe_unbekannt"] is True assert eintraege[2]["startpunkt"][2] == 0.0 and eintraege[2]["endpunkt"][2] == 0.0 def test_nachbar_as_auf_falscher_seite_wird_nicht_gegriffen(): # Linie bei x=5834; ihr AS 467 mm links, der AS der Nachbarlinie # (x=6734) 433 mm RECHTS - also naeher, aber auf der falschen Seite. linie = _linie((5833.56, 13348.38, 3191.63), (5833.44, 24002.54, 2821.63)) as_eigen = _as(5367.10, 14505.61) as_nachbar = _as(6267.10, 14505.61) _, belegt, _ = dsc.gf_eintraege_aus_linien([linie], [as_nachbar, as_eigen]) assert belegt == {id(as_eigen)} def test_rueckwaerts_gezeichnete_gf_startet_oben(): linie = _linie((5833.44, 24002.54, 2821.63), (5833.56, 13348.38, 3191.63)) eintraege, _, _ = dsc.gf_eintraege_aus_linien([linie], [_as(5367.10, 14505.61)]) assert eintraege[0]["start_mm"][:2] == [5833.56, 13348.38] assert eintraege[0]["hz_grad"] == 90.0 def test_as_am_unteren_ende_ist_steigfoerderer(): # Gemessen: Linie x=2801 von 2822 hinauf auf 3192, AS am tiefen Ende. linie = _linie((2801.42, 24043.0, 2821.63), (2801.42, 13389.0, 3191.63)) as_unten = _as(3267.48, 22892.92, z=2821.63) eintraege, belegt, hinweise = dsc.gf_eintraege_aus_linien([linie], [as_unten]) assert eintraege == [] assert belegt == set() assert len(hinweise) == 1 and "Steigfoerderer" in hinweise[0] def test_waagrechte_linie_ist_keine_gf(): linie = _linie((36661.0, 10279.0, 2821.63), (36661.0, 24879.0, 2821.63)) eintraege, belegt, hinweise = dsc.gf_eintraege_aus_linien([linie], []) assert eintraege == [] assert belegt == set() assert any("waagrechte" in h for h in hinweise) def test_ohne_as_defaults_und_hinweis(): linie = _linie((0.0, 0.0, 1000.0), (5000.0, 0.0, 800.0)) eintraege, _, hinweise = dsc.gf_eintraege_aus_linien([linie], []) assert eintraege[0]["hz_grad"] == 0.0 assert eintraege[0]["as_seite"] == dsc.DEFAULT_SEITE assert any("ohne Ausschleuselement" in h for h in hinweise)