[FIX] Omniflo TEF einfügen entlang Gerade funktioniert wieder; Omniflo Gerade ist aus dem Menü entfernt worden, da entweder über das Menü Fahrstrecke oder nur als Linie gezeichnet wird
This commit is contained in:
1 parent
afc5dce13a
commit
98106a6af4
17 files changed
+59
-548
No files matched your search
+3
-4
@@ -338,7 +338,7 @@ tests/
|
||||
testdata/
|
||||
kreisel_tests.json # Testfall-Definitionen fuer Kreisel
|
||||
omniflo_tests.json # Testfall-Definitionen fuer Omniflo
|
||||
omniflo_strecke_tests.json # Streckenzug: 4 Geraden + 2 Boegen + 1 Weiche (7 Elemente)
|
||||
omniflo_strecke_tests.json # Streckenzug: 2 Boegen + 1 Weiche (3 Elemente)
|
||||
hm_recformat.json # Aufzeichnung: rohes Journal der 5 Ketten
|
||||
hundm05.json # daraus abgeleitete Spec (wird erweitert)
|
||||
foerderer_tests.json / mubea.json / ...
|
||||
@@ -707,14 +707,13 @@ def <modul>_ref_dxf():
|
||||
|
||||
### test_omniflo_strecke.py
|
||||
|
||||
Streckenzug **4 Geraden -> 180-Grad-Kurve (4x 45-Grad-Bogen) -> 4 Geraden**.
|
||||
Streckenzug aus **2 Boegen + 1 Weiche**.
|
||||
Die Geometrie wird ohne BricsCAD direkt aus `omniflo_strecke_tests.json` geprueft.
|
||||
|
||||
| Klasse | Prueft |
|
||||
|---|---|
|
||||
| `TestStreckeStruktur` | 4+4+4 = 12 Elemente, Reihenfolge der Gruppen, Typen |
|
||||
| `TestStreckeStruktur` | 3 Elemente, Gruppenverteilung, Typen |
|
||||
| `TestStreckeKatalog` | Bogen-SivasNummern existieren in `omniflo_boegen.json` (Radius/Winkel) |
|
||||
| `TestStreckeGeometrie` | Lueckenlose Verkettung, Kurvensumme 180 Grad, gemeinsamer Bogen-Mittelpunkt |
|
||||
| `TestStreckeResults` | omniflo_strecke_results.json aus BricsCAD: Elemente vollstaendig, Status OK |
|
||||
|
||||
## Umgebungsvariablen
|
||||
|
||||
@@ -3,20 +3,12 @@
|
||||
;;
|
||||
;; Baut aus tests/testdata/omniflo_strecke_tests.json einen verketteten
|
||||
;; Streckenzug auf:
|
||||
;; 4 Geraden -> 180-Grad-Kurve (4x 45-Grad-Bogen) -> 4 Geraden
|
||||
;; 2 Boegen + 1 Weiche
|
||||
;;
|
||||
;; Jedes Element traegt bereits seine absolute Platzierung (x, y, drehung)
|
||||
;; sowie Endpunkt (x_ende, y_ende). Die Elemente sind lueckenlos verkettet
|
||||
;; (Ende[i] = Anfang[i+1]), sodass eine durchgehende U-foermige Strecke
|
||||
;; entsteht.
|
||||
;; Jedes Element traegt bereits seine absolute Platzierung (x, y, drehung).
|
||||
;;
|
||||
;; - Boegen (type "bogen"): DXF aus DXFM_OMNIFLO an (x,y) mit Drehung
|
||||
;; einfuegen (wie test_omniflo.lsp).
|
||||
;; - Geraden (type "gerade"): echter Aluprofil-Block ueber den skript-
|
||||
;; faehigen Kern omni:make-gerade (aus OmniModulInsert.lsp). Fehlt die
|
||||
;; Quell-.dwg (kein AP110.dwg im Blockpfad), werden Ersatz-Attribute
|
||||
;; verwendet, sodass dennoch ein Compound-Block (Linie + ATTDEFs) statt
|
||||
;; einer nackten Linie entsteht.
|
||||
;; - Boegen/Weichen (type "bogen"): DXF aus DXFM_OMNIFLO an (x,y) mit
|
||||
;; Drehung einfuegen (wie test_omniflo.lsp).
|
||||
;;
|
||||
;; Ergebnisse -> tests/output/omniflo_strecke_results.json
|
||||
;; (via omniflo_strecke:export-results, aufgerufen von SSG_RUN_ALL_TESTS
|
||||
@@ -90,54 +82,6 @@
|
||||
)
|
||||
|
||||
|
||||
;; --- Gerade non-interaktiv als echten Aluprofil-Block erzeugen ---
|
||||
;; Nutzt den skriptfaehigen Kern omni:make-gerade aus OmniModulInsert.lsp.
|
||||
;; profil = Profiltyp (z.B. "AP110")
|
||||
;; pt-anf = Anfangspunkt, pt-end = Endpunkt (bestimmen Laenge + Drehung)
|
||||
;; hoehe-str / drehung-str = Attributwerte HOEHE/DREHUNG
|
||||
;; Rueckgabe: Block-Entity oder nil.
|
||||
(defun omnistr:build-gerade (profil pt-anf pt-end hoehe-str drehung-str /
|
||||
srcAttribs textHeight textGap blockEnt)
|
||||
(dbgf "omnistr:build-gerade")
|
||||
(dbgmsg (strcat "profil=" (if profil profil "nil")
|
||||
" hoehe=" (if hoehe-str hoehe-str "nil")
|
||||
" drehung=" (if drehung-str drehung-str "nil")))
|
||||
(dbgreturn
|
||||
(if (null (car (atoms-family 1 '("OMNI:MAKE-GERADE"))))
|
||||
(progn
|
||||
;; Precondition-Fehler (Modul nicht geladen): bleibt im Fenster sichtbar
|
||||
(princ "\n[TEST_OMNIFLO_STRECKE] FEHLER: omni:make-gerade nicht geladen (OmniModulInsert.lsp)!")
|
||||
nil
|
||||
)
|
||||
(progn
|
||||
(setq textHeight (ssg-cfg-or "omniflo" "text_height" 100.0))
|
||||
(setq textGap (ssg-cfg-or "omniflo" "text_gap" 20.0))
|
||||
;; Quell-Attribute lesen; falls keine .dwg vorhanden, Ersatz erzeugen
|
||||
(setq srcAttribs (omni:read-src-attribs profil))
|
||||
(if (null srcAttribs)
|
||||
(progn
|
||||
(dbgmsg (strcat "keine Quell-.dwg fuer " profil " - Ersatz-Attribute"))
|
||||
(setq srcAttribs (list (cons "PROFILTYP" profil)
|
||||
(cons "HOEHE" (if hoehe-str hoehe-str "2000"))
|
||||
(cons "ID" "")))
|
||||
)
|
||||
)
|
||||
(setvar "ATTREQ" 0)
|
||||
(setvar "ATTDIA" 0)
|
||||
(setq blockEnt (omni:make-gerade profil pt-anf pt-end
|
||||
srcAttribs textHeight textGap nil))
|
||||
(if (and blockEnt (= (cdr (assoc 0 (entget blockEnt))) "INSERT"))
|
||||
(ssg-attrib-set-on blockEnt
|
||||
(list (cons "HOEHE" (if hoehe-str hoehe-str "2000"))
|
||||
(cons "DREHUNG" (if drehung-str drehung-str "0"))))
|
||||
)
|
||||
blockEnt
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
;; --- Ergebnis eines Streckenelements als JSON-String erzeugen ---
|
||||
(defun omnistr:test-result-json (test-id seq typ description status / )
|
||||
(strcat " {\n"
|
||||
@@ -184,9 +128,9 @@
|
||||
;; Liest omniflo_strecke_tests.json und baut den Streckenzug auf.
|
||||
;; ============================================================
|
||||
(defun c:TEST_OMNIFLO_STRECKE (/ tests-json-pfad elemente
|
||||
idx eintrag typ sivasnr profil hoehe-str drehung-str
|
||||
description x-val y-val xe-val ye-val seq
|
||||
insert-pt pt-end anzahl-ok anzahl-fehler
|
||||
idx eintrag typ sivasnr hoehe-str drehung-str
|
||||
description x-val y-val seq
|
||||
insert-pt anzahl-ok anzahl-fehler
|
||||
results-list ergebnis)
|
||||
|
||||
(ssg-start "TEST_OMNIFLO_STRECKE"
|
||||
@@ -245,22 +189,15 @@
|
||||
(if (null drehung-str) (setq drehung-str "0"))
|
||||
(if (numberp drehung-str) (setq drehung-str (rtos drehung-str 2 4)))
|
||||
|
||||
;; Anfangs- und Endpunkt lesen
|
||||
(setq x-val (ssg-val eintrag "x")
|
||||
y-val (ssg-val eintrag "y")
|
||||
xe-val (ssg-val eintrag "x_ende")
|
||||
ye-val (ssg-val eintrag "y_ende"))
|
||||
(if (null x-val) (setq x-val 0.0))
|
||||
(if (null y-val) (setq y-val 0.0))
|
||||
(if (null xe-val) (setq xe-val x-val))
|
||||
(if (null ye-val) (setq ye-val y-val))
|
||||
(if (not (numberp x-val)) (setq x-val (atof x-val)))
|
||||
(if (not (numberp y-val)) (setq y-val (atof y-val)))
|
||||
(if (not (numberp xe-val)) (setq xe-val (atof xe-val)))
|
||||
(if (not (numberp ye-val)) (setq ye-val (atof ye-val)))
|
||||
;; Einfuegepunkt lesen
|
||||
(setq x-val (ssg-val eintrag "x")
|
||||
y-val (ssg-val eintrag "y"))
|
||||
(if (null x-val) (setq x-val 0.0))
|
||||
(if (null y-val) (setq y-val 0.0))
|
||||
(if (not (numberp x-val)) (setq x-val (atof x-val)))
|
||||
(if (not (numberp y-val)) (setq y-val (atof y-val)))
|
||||
|
||||
(setq insert-pt (list x-val y-val (atof hoehe-str)))
|
||||
(setq pt-end (list xe-val ye-val (atof hoehe-str)))
|
||||
|
||||
(dbgmsg (strcat (itoa seq) ". " (if typ typ "?") ": "
|
||||
(if description description "")
|
||||
@@ -273,10 +210,6 @@
|
||||
((= typ "bogen")
|
||||
(setq sivasnr (ssg-val eintrag "sivasnr"))
|
||||
(omnistr:insert-bogen sivasnr insert-pt hoehe-str drehung-str))
|
||||
((= typ "gerade")
|
||||
(setq profil (ssg-val eintrag "profil"))
|
||||
(if (null profil) (setq profil "AP110"))
|
||||
(omnistr:build-gerade profil insert-pt pt-end hoehe-str drehung-str))
|
||||
(T
|
||||
(dbgmsg (strcat "WARNUNG: unbekannter Typ '"
|
||||
(if typ typ "nil") "'"))
|
||||
|
||||
@@ -4,28 +4,25 @@
|
||||
test_omniflo_strecke.py - Validiert den Omniflo-Streckenzug.
|
||||
|
||||
Testfall (tests/testdata/omniflo_strecke_tests.json), aktuelles Datenmodell:
|
||||
7 Elemente: 2x gerade_unten (Fahrtrichtung 0 Grad), 2x gerade_oben
|
||||
(Fahrtrichtung 180 Grad), 2x bogen (echte Omniflo-Boegen), 1x weiche.
|
||||
3 Elemente: 2x bogen (echte Omniflo-Boegen), 1x weiche.
|
||||
|
||||
Prueft (ohne BricsCAD):
|
||||
1. Struktur: 7 Elemente in der richtigen Gruppen-/Typ-Verteilung, seq lueckenlos
|
||||
1. Struktur: 3 Elemente in der richtigen Gruppen-/Typ-Verteilung, seq lueckenlos
|
||||
2. Katalog: die Bogen-SivasNummern (gruppe "bogen") existieren in
|
||||
data/json/omniflo_boegen.json mit passendem Radius/Kurvenwinkel; die
|
||||
Weichen-SivasNummer in data/json/omniflo_weichen.json
|
||||
3. Geometrie: die Geraden haben eine zur Laenge passende Distanz Anfang->Ende
|
||||
und behalten ihre Fahrtrichtung (drehung).
|
||||
|
||||
Hinweis: Boegen/Weichen tragen im aktuellen Testdaten-Modell KEINE Endpunkte
|
||||
(x_ende/y_ende = null) und keine Mittelpunkte - die frueheren Halbkreis-/
|
||||
Verkettungs-Tests (drehung_ende, x_mitte, kurve_180, 12 Elemente) bezogen sich
|
||||
auf ein anderes, nicht mehr vorhandenes Modell und wurden entfernt.
|
||||
auf ein anderes, nicht mehr vorhandenes Modell und wurden entfernt. Die
|
||||
Aluprofil-Geraden (AP60/AP110/APG110) wurden samt Menue und Befehlen entfernt.
|
||||
|
||||
Optional (nach BricsCAD-Lauf c:TEST_OMNIFLO_STRECKE):
|
||||
4. Integrationstest gegen tests/output/omniflo_strecke_results.json
|
||||
3. Integrationstest gegen tests/output/omniflo_strecke_results.json
|
||||
"""
|
||||
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
|
||||
import pytest
|
||||
@@ -103,8 +100,8 @@ def weichen_lookup():
|
||||
class TestStreckeStruktur:
|
||||
|
||||
def test_gesamtzahl(self, strecke):
|
||||
"""4 Geraden + 2 Boegen + 1 Weiche = 7 Elemente."""
|
||||
assert len(strecke) == 7, f"Erwartet 7 Elemente, erhalten {len(strecke)}"
|
||||
"""2 Boegen + 1 Weiche = 3 Elemente."""
|
||||
assert len(strecke) == 3, f"Erwartet 3 Elemente, erhalten {len(strecke)}"
|
||||
|
||||
def test_seq_lueckenlos(self, strecke):
|
||||
"""seq muss lueckenlos bei 1 beginnend aufsteigen."""
|
||||
@@ -112,33 +109,18 @@ class TestStreckeStruktur:
|
||||
assert el["seq"] == i + 1, f"Element {i}: seq={el['seq']}, erwartet {i + 1}"
|
||||
|
||||
def test_gruppen_verteilung(self, strecke):
|
||||
"""Erwartete Gruppen-Verteilung: 2x gerade_unten, 2x gerade_oben,
|
||||
2x bogen, 1x weiche."""
|
||||
"""Erwartete Gruppen-Verteilung: 2x bogen, 1x weiche."""
|
||||
from collections import Counter
|
||||
ist = Counter(el["gruppe"] for el in strecke)
|
||||
erwartet = {"gerade_unten": 2, "gerade_oben": 2, "bogen": 2, "weiche": 1}
|
||||
assert dict(ist) == erwartet, f"Gruppen-Verteilung abweichend:\n Ist: {dict(ist)}\n Soll: {erwartet}"
|
||||
erwartet = {"bogen": 2, "weiche": 1}
|
||||
assert dict(ist) == erwartet, (
|
||||
f"Gruppen-Verteilung abweichend: Ist {dict(ist)}, Soll {erwartet}")
|
||||
|
||||
def test_typen(self, strecke):
|
||||
"""gerade_* -> type 'gerade', bogen/weiche -> type 'bogen'."""
|
||||
"""bogen/weiche -> type 'bogen'."""
|
||||
for el in strecke:
|
||||
erwartet = "gerade" if el["gruppe"].startswith("gerade") else "bogen"
|
||||
assert el["type"] == erwartet, (
|
||||
f"seq {el['seq']}: type={el['type']}, erwartet {erwartet}")
|
||||
|
||||
def test_vier_geraden(self, strecke):
|
||||
"""Vier Geraden gesamt (2 unten + 2 oben)."""
|
||||
assert sum(1 for el in strecke if el["type"] == "gerade") == 4
|
||||
|
||||
def test_geraden_richtungen(self, strecke):
|
||||
"""gerade_unten faehrt 0 Grad, gerade_oben 180 Grad (Gegenrichtung)."""
|
||||
for el in strecke:
|
||||
if el["gruppe"] == "gerade_unten":
|
||||
assert el["drehung"] == pytest.approx(0.0, abs=_TOL), (
|
||||
f"seq {el['seq']}: gerade_unten drehung={el['drehung']}, erwartet 0")
|
||||
elif el["gruppe"] == "gerade_oben":
|
||||
assert el["drehung"] == pytest.approx(180.0, abs=_TOL), (
|
||||
f"seq {el['seq']}: gerade_oben drehung={el['drehung']}, erwartet 180")
|
||||
assert el["type"] == "bogen", (
|
||||
f"seq {el['seq']}: type={el['type']}, erwartet bogen")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -174,31 +156,7 @@ class TestStreckeKatalog:
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 3. Geometrie der Geraden
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestStreckeGeometrie:
|
||||
|
||||
def test_geraden_laenge(self, strecke):
|
||||
"""Die euklidische Distanz Anfang->Ende entspricht der Laenge."""
|
||||
for el in strecke:
|
||||
if el["type"] != "gerade":
|
||||
continue
|
||||
dist = math.hypot(el["x_ende"] - el["x"], el["y_ende"] - el["y"])
|
||||
assert dist == pytest.approx(el["laenge"], abs=0.5), (
|
||||
f"seq {el['seq']}: Distanz {dist:.2f} != Laenge {el['laenge']}")
|
||||
|
||||
def test_geraden_haben_endpunkt(self, strecke):
|
||||
"""Geraden tragen einen Endpunkt (x_ende/y_ende gesetzt)."""
|
||||
for el in strecke:
|
||||
if el["type"] != "gerade":
|
||||
continue
|
||||
assert el.get("x_ende") is not None and el.get("y_ende") is not None, (
|
||||
f"seq {el['seq']}: Gerade ohne Endpunkt")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 4. Integrationstest gegen BricsCAD-Ergebnis (optional)
|
||||
# 3. Integrationstest gegen BricsCAD-Ergebnis (optional)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestStreckeResults:
|
||||
|
||||
+2
-62
@@ -1,66 +1,6 @@
|
||||
[
|
||||
{
|
||||
"seq": 1,
|
||||
"gruppe": "gerade_unten",
|
||||
"type": "gerade",
|
||||
"profil": "AP110",
|
||||
"laenge": 1000.0,
|
||||
"x": 2000.0,
|
||||
"y": 0.0,
|
||||
"drehung": 0.0,
|
||||
"x_ende": 3000.0,
|
||||
"y_ende": 0.0,
|
||||
"hoehe": 2000,
|
||||
"id": "0003",
|
||||
"description": "Gerade AP110 L=1000"
|
||||
},
|
||||
{
|
||||
"seq": 2,
|
||||
"gruppe": "gerade_unten",
|
||||
"type": "gerade",
|
||||
"profil": "AP110",
|
||||
"laenge": 1000.0,
|
||||
"x": 3000.0,
|
||||
"y": 0.0,
|
||||
"drehung": 0.0,
|
||||
"x_ende": 4000.0,
|
||||
"y_ende": 0.0,
|
||||
"hoehe": 2000,
|
||||
"id": "0004",
|
||||
"description": "Gerade AP110 L=1000"
|
||||
},
|
||||
{
|
||||
"seq": 3,
|
||||
"gruppe": "gerade_oben",
|
||||
"type": "gerade",
|
||||
"profil": "AP110",
|
||||
"laenge": 1000.0,
|
||||
"x": 4000.0,
|
||||
"y": 990.34,
|
||||
"drehung": 180.0,
|
||||
"x_ende": 3000.0,
|
||||
"y_ende": 990.34,
|
||||
"hoehe": 2000,
|
||||
"id": "0005",
|
||||
"description": "Gerade AP110 L=1000"
|
||||
},
|
||||
{
|
||||
"seq": 4,
|
||||
"gruppe": "gerade_oben",
|
||||
"type": "gerade",
|
||||
"profil": "AP110",
|
||||
"laenge": 1000.0,
|
||||
"x": 3000.0,
|
||||
"y": 990.34,
|
||||
"drehung": 180.0,
|
||||
"x_ende": 2000.0,
|
||||
"y_ende": 990.34,
|
||||
"hoehe": 2000,
|
||||
"id": "0006",
|
||||
"description": "Gerade AP110 L=1000"
|
||||
},
|
||||
{
|
||||
"seq": 5,
|
||||
"gruppe": "bogen",
|
||||
"type": "bogen",
|
||||
"sivasnr": "821104022",
|
||||
@@ -74,7 +14,7 @@
|
||||
"description": "APB 110 R 400/90 - 500/500"
|
||||
},
|
||||
{
|
||||
"seq": 6,
|
||||
"seq": 2,
|
||||
"gruppe": "bogen",
|
||||
"type": "bogen",
|
||||
"sivasnr": "821104022",
|
||||
@@ -88,7 +28,7 @@
|
||||
"description": "APB 110 R 400/90 - 500/500"
|
||||
},
|
||||
{
|
||||
"seq": 7,
|
||||
"seq": 3,
|
||||
"gruppe": "weiche",
|
||||
"type": "bogen",
|
||||
"sivasnr": "834372100",
|
||||
|
||||
Reference in new issue
Block a user