diff --git a/bin/setenv.bat b/bin/setenv.bat index ca21b64..535fdc9 100644 --- a/bin/setenv.bat +++ b/bin/setenv.bat @@ -4,7 +4,7 @@ REM ================================================================ REM TEST - Umgebungsvariablen Setup REM ================================================================ -echo Setting up environment variables for TEST ... +echo Setting up environment variables for DXFMAKROS ... REM Basis-Projektpfad (aktueller Ordner) set "DXFMAKRO=%~dp0.." @@ -44,16 +44,7 @@ if not exist "%DXFM_RESULTS%" mkdir "%DXFM_RESULTS%" REM Umgebungsvariablen anzeigen echo. echo ================================================================ -echo TEST ENVIRONMENT SETUP COMPLETE -echo ================================================================ echo DXFMAKRO = %DXFMAKRO% -echo DXFM_BIN = %DXFM_BIN% -echo DXFM_CFG = %DXFM_CFG% -echo DXFM_LIB = %DXFM_LIB% -echo DXFM_DATA = %DXFM_DATA% -echo DXFM_BLOCKS = %DXFM_BLOCKS% -echo DXFM_LISP = %DXFM_LISP% -echo DXFM_RESULTS = %DXFM_RESULTS% echo PYTHONPATH = %PYTHONPATH% echo ================================================================ echo. diff --git a/lib/set_einfuegepkt.py b/lib/set_einfuegepkt.py index 359cac9..6830692 100644 --- a/lib/set_einfuegepkt.py +++ b/lib/set_einfuegepkt.py @@ -33,6 +33,7 @@ import ezdxf from utils import ( ROW_GROUPS, TEXT_HEIGHT, TEXT_MARGIN, CROSS_SIZE, ROW_LABEL_WIDTH, + SWITCH_FILTERS, build_row_layout, import_element_as_block, draw_cross, ) @@ -225,59 +226,23 @@ def horizontal_midpoint_insertion(doc): # --------------------------------------------------------------------------- # Schalter-Definitionen: (Label, JSON-Datei, Filter, Einfuegepunkt-Funktion) +# Filter kommen aus SWITCH_FILTERS in utils.py. # --------------------------------------------------------------------------- +_INSERTION_FUNCS = { + "boegen": boegen_insertion_point, + "weichen45": weichen_insertion_point, + "weichen90": weichen_insertion_point, + "weichenkoerper": weichenkoerper_insertion_point, + "weichen_parallel": weichenkoerper_insertion_point, + "sternweiche": horizontal_midpoint_insertion, + "delta": horizontal_midpoint_insertion, + "dreifachweiche": horizontal_midpoint_insertion, +} + SWITCH_DEFS = { - "boegen": ( - "Boegen", - "omniflo_boegen.json", - lambda item: True, - boegen_insertion_point, - ), - "weichen45": ( - "Weichen 45 Grad", - "omniflo_weichen.json", - lambda item: item["KurvenWinkel"] == 45 - and item["WeichenTyp"] not in ("Dreifachweiche", "Deltaweiche"), - weichen_insertion_point, - ), - "weichen90": ( - "Weichen 90 Grad", - "omniflo_weichen.json", - lambda item: item["KurvenWinkel"] == 90 - and item["WeichenTyp"] not in ("Dreifachweiche", "Deltaweiche"), - weichen_insertion_point, - ), - "weichenkoerper": ( - "Weichenkoerper", - "omniflo_weichen.json", - lambda item: item["KurvenWinkel"] == 22.5, - weichenkoerper_insertion_point, - ), - "weichen_parallel": ( - "Weichen Parallel", - "omniflo_weichen.json", - lambda item: item["KurvenWinkel"] == 0 and item["WeichenTyp"] != "Sternweiche", - weichenkoerper_insertion_point, - ), - "sternweiche": ( - "Sternweiche", - "omniflo_weichen.json", - lambda item: item["WeichenTyp"] == "Sternweiche", - horizontal_midpoint_insertion, - ), - "delta": ( - "Deltaweichen", - "omniflo_weichen.json", - lambda item: item["WeichenTyp"] == "Deltaweiche", - horizontal_midpoint_insertion, - ), - "dreifachweiche": ( - "Dreifachweichen", - "omniflo_weichen.json", - lambda item: item["WeichenTyp"] == "Dreifachweiche", - horizontal_midpoint_insertion, - ), + key: (*SWITCH_FILTERS[key], _INSERTION_FUNCS[key]) + for key in SWITCH_FILTERS } diff --git a/lib/set_koords.py b/lib/set_koords.py index 5ba932f..1c88e62 100644 --- a/lib/set_koords.py +++ b/lib/set_koords.py @@ -11,7 +11,11 @@ Schalter: Boegen: Beginn der obersten horizontalen Linie, x rechts, y oben, z aus Zeichenebene. Weichen: Beginn der untersten vertikalen Linie, - x oben, y rechts, z aus Zeichenebene. + x oben, y links, z aus Zeichenebene. + --k2set K2 an alle Boegen und Weichen setzen. + Boegen: anderes Kettenende, x tangential, + y senkrecht, z wie K1. + Weichen: noch nicht implementiert (Dummy). --show-omniflo Uebersichts-DXF mit K-Positionen als farbige Kreuze. --test Erzeugt Testdatei mit 4 KOS und verifiziert diese. --number SIVA Nur diese eine 9-stellige Sivasnr verarbeiten. @@ -28,6 +32,7 @@ from ezdxf.math import Matrix44 from utils import ( ROW_GROUPS, TEXT_HEIGHT, TEXT_MARGIN, CROSS_SIZE, ROW_LABEL_WIDTH, + SWITCH_FILTERS, load_omniflo_data, build_row_layout, import_element_as_block, draw_cross, is_bogen, ) @@ -251,6 +256,150 @@ def k1_point_weiche(doc): return (x, bottom_y, 0), 0, 0, 90 +# --------------------------------------------------------------------------- +# K2-Positionsbestimmung (nur Boegen) +# --------------------------------------------------------------------------- + +def k2_point_bogen(doc): + """K2-Position fuer Boegen: anderes Ende der Kette (Gerade-Bogen-Gerade). + + Sucht den Bogen, bestimmt welches Ende zur K1-Seite (oberste H-Linie) + gehoert, findet die laengste Linie am anderen Bogenende und setzt K2 + an deren aeusseres Ende. + + x-Achse tangential zur Linie (Richtung weg vom Bogen), + y senkrecht dazu, z aus Zeichenebene (wie K1). + Sonderfall 180-Grad-Bogen: x nach rechts (rz=0). + """ + msp = doc.modelspace() + + # Bogen finden + arc = None + for e in msp: + if e.dxftype() == "ARC": + arc = e + break + if arc is None: + return None + + cx, cy = arc.dxf.center[0], arc.dxf.center[1] + r = arc.dxf.radius + sa, ea = arc.dxf.start_angle, arc.dxf.end_angle + + arc_start = (cx + r * math.cos(math.radians(sa)), + cy + r * math.sin(math.radians(sa))) + arc_end = (cx + r * math.cos(math.radians(ea)), + cy + r * math.sin(math.radians(ea))) + + # K1-Seite = oberste horizontale Linie + hline = find_topmost_horizontal_line(doc) + if hline is None: + return None + h_y = hline.dxf.start[1] + + # Welches Bogenende liegt an der K1-H-Linie? + tol = 1.0 + if abs(arc_end[1] - h_y) < tol: + k2_junction = arc_start + else: + k2_junction = arc_end + + # Laengste Linie am K2-Bogenende suchen + best_line_len = 0 + k2_pos = None + junc_pt = None + for e in msp: + if e.dxftype() != "LINE": + continue + s = (e.dxf.start[0], e.dxf.start[1]) + end = (e.dxf.end[0], e.dxf.end[1]) + ds = ((s[0] - k2_junction[0])**2 + (s[1] - k2_junction[1])**2) ** 0.5 + de = ((end[0] - k2_junction[0])**2 + (end[1] - k2_junction[1])**2) ** 0.5 + if ds > tol and de > tol: + continue + ln = ((end[0] - s[0])**2 + (end[1] - s[1])**2) ** 0.5 + if ln > best_line_len: + best_line_len = ln + if ds < tol: + k2_pos = end + junc_pt = s + else: + k2_pos = s + junc_pt = end + + if k2_pos is None: + return None + + # Bogenspanne berechnen + span = (ea - sa) % 360 + + # Tangenten-Richtung: von K2 zur Junction (zur Bogenmitte) + dx = junc_pt[0] - k2_pos[0] + dy = junc_pt[1] - k2_pos[1] + rz = math.degrees(math.atan2(dy, dx)) + + # 180-Grad-Sonderfall: x nach rechts, wie K1 + if abs(span - 180) < 1: + rz = 0 + + return (k2_pos[0], k2_pos[1], 0), 0, 0, rz + + +# --------------------------------------------------------------------------- +# K2-Positionsbestimmung Weichen (Dummy-Funktionen) +# --------------------------------------------------------------------------- + +def k2_point_weichen45(doc): + """K2 fuer Weichen 45 Grad – noch nicht implementiert.""" + return None + + +def k2_point_weichen90(doc): + """K2 fuer Weichen 90 Grad – noch nicht implementiert.""" + return None + + +def k2_point_weichenkoerper(doc): + """K2 fuer Weichenkoerper – noch nicht implementiert.""" + return None + + +def k2_point_weichen_parallel(doc): + """K2 fuer Weichen Parallel – noch nicht implementiert.""" + return None + + +def k2_point_sternweiche(doc): + """K2 fuer Sternweiche – noch nicht implementiert.""" + return None + + +def k2_point_delta(doc): + """K2 fuer Deltaweichen – noch nicht implementiert.""" + return None + + +def k2_point_dreifachweiche(doc): + """K2 fuer Dreifachweichen – noch nicht implementiert.""" + return None + + +# --------------------------------------------------------------------------- +# K2 Schalter-Zuordnung: SWITCH_FILTERS-Key -> K2-Funktion +# --------------------------------------------------------------------------- + +K2_FUNCS = { + "boegen": k2_point_bogen, + "weichen45": k2_point_weichen45, + "weichen90": k2_point_weichen90, + "weichenkoerper": k2_point_weichenkoerper, + "weichen_parallel": k2_point_weichen_parallel, + "sternweiche": k2_point_sternweiche, + "delta": k2_point_delta, + "dreifachweiche": k2_point_dreifachweiche, +} + + # --------------------------------------------------------------------------- # --k1set # --------------------------------------------------------------------------- @@ -310,6 +459,63 @@ def process_k1set(data_dir, results_dir, number=None): print(f"\nErgebnisse in: {results_dir}") +# --------------------------------------------------------------------------- +# --k2set +# --------------------------------------------------------------------------- + +def process_k2set(data_dir, results_dir, number=None): + """Setzt K2-Block an alle Boegen und Weichen (ueber SWITCH_FILTERS).""" + omniflo_dir = os.path.join(data_dir, "omniflo") + + for key, k2_func in K2_FUNCS.items(): + label, json_file, filter_func = SWITCH_FILTERS[key] + + json_path = os.path.join(data_dir, "json", json_file) + if not os.path.exists(json_path): + continue + with open(json_path, "r", encoding="utf-8") as f: + all_items = json.load(f) + + filtered = [item for item in all_items if filter_func(item)] + if number: + filtered = [item for item in filtered if str(item["Sivasnr"]) == str(number)] + if not filtered: + continue + + print(f"=== K2 setzen: {label} ===") + for item in filtered: + sivasnr = str(item["Sivasnr"]) + dxf_path = os.path.join(results_dir, f"{sivasnr}.dxf") + if not os.path.exists(dxf_path): + dxf_path = os.path.join(omniflo_dir, f"{sivasnr}.dxf") + if not os.path.exists(dxf_path): + continue + + doc = ezdxf.readfile(dxf_path) + msp = doc.modelspace() + + # Bestehende K2-Referenzen entfernen + for entity in list(msp): + if entity.dxftype() == "INSERT" and entity.dxf.name == "K2": + msp.delete_entity(entity) + + result = k2_func(doc) + + if result is None: + print(f" {sivasnr}: K2 nicht bestimmbar (Dummy), ueberspringe.") + continue + + point, rx, ry, rz = result + insert_ks(msp, "K2", point, rx, ry, rz) + + out_path = os.path.join(results_dir, f"{sivasnr}.dxf") + doc.saveas(out_path) + print(f" {sivasnr}: K2 at ({point[0]:.2f},{point[1]:.2f},{point[2]:.2f}) " + f"rx={rx} ry={ry} rz={rz:.1f} [{item['ProfilTyp']}]") + + print(f"\nErgebnisse in: {results_dir}") + + # --------------------------------------------------------------------------- # --show-omniflo # --------------------------------------------------------------------------- @@ -412,6 +618,8 @@ def main(): ) parser.add_argument("--k1set", action="store_true", help="K1-Block an alle Boegen und Weichen setzen") + parser.add_argument("--k2set", action="store_true", + help="K2-Block an alle Boegen setzen (anderes Kettenende)") parser.add_argument("--show-omniflo", action="store_true", help="Uebersichts-DXF mit K-Positionen erzeugen") parser.add_argument("--test", action="store_true", @@ -424,7 +632,7 @@ def main(): print("FEHLER: --number muss eine 9-stellige Ganzzahl sein.") sys.exit(1) - if not args.k1set and not args.show_omniflo and not args.test: + if not args.k1set and not args.k2set and not args.show_omniflo and not args.test: parser.print_help() sys.exit(1) @@ -448,6 +656,9 @@ def main(): if args.k1set: process_k1set(data_dir, results_dir, args.number) + if args.k2set: + process_k2set(data_dir, results_dir, args.number) + if args.show_omniflo: print("=== Koordinaten Uebersicht ===") show_omniflo(data_dir, results_dir) diff --git a/lib/utils.py b/lib/utils.py index 49dbd11..695dd34 100644 --- a/lib/utils.py +++ b/lib/utils.py @@ -60,6 +60,57 @@ ROW_GROUPS = [ lambda w: w["WeichenTyp"] == "Sternweiche"), ] +# --------------------------------------------------------------------------- +# Schalter-Filter: (Label, JSON-Datei, Filter-Funktion) +# Gemeinsam genutzt von set_einfuegepkt.py und set_koords.py. +# --------------------------------------------------------------------------- + +SWITCH_FILTERS = { + "boegen": ( + "Boegen", + "omniflo_boegen.json", + lambda item: True, + ), + "weichen45": ( + "Weichen 45 Grad", + "omniflo_weichen.json", + lambda item: item["KurvenWinkel"] == 45 + and item["WeichenTyp"] not in ("Dreifachweiche", "Deltaweiche"), + ), + "weichen90": ( + "Weichen 90 Grad", + "omniflo_weichen.json", + lambda item: item["KurvenWinkel"] == 90 + and item["WeichenTyp"] not in ("Dreifachweiche", "Deltaweiche"), + ), + "weichenkoerper": ( + "Weichenkoerper", + "omniflo_weichen.json", + lambda item: item["KurvenWinkel"] == 22.5, + ), + "weichen_parallel": ( + "Weichen Parallel", + "omniflo_weichen.json", + lambda item: item["KurvenWinkel"] == 0 and item["WeichenTyp"] != "Sternweiche", + ), + "sternweiche": ( + "Sternweiche", + "omniflo_weichen.json", + lambda item: item["WeichenTyp"] == "Sternweiche", + ), + "delta": ( + "Deltaweichen", + "omniflo_weichen.json", + lambda item: item["WeichenTyp"] == "Deltaweiche", + ), + "dreifachweiche": ( + "Dreifachweichen", + "omniflo_weichen.json", + lambda item: item["WeichenTyp"] == "Dreifachweiche", + ), +} + + PADDING_X = 200 PADDING_Y = 400 TEXT_HEIGHT = 30