Files
dxfmakros/tests/test_dxf_scan_gf.py
T

169 lines
7.0 KiB
Python

#!/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)