From e4564be24c73e4d7a4f4422bcb9dbd76fef39f1d Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Thu, 11 Jun 2026 11:15:13 +0200 Subject: [PATCH] =?UTF-8?q?Omniflo=20Eintr=C3=A4ge=20von=20Verbindern=20un?= =?UTF-8?q?d=20B=C3=B6gen=20f=C3=BCr=20Weichen=20Erg=C3=A4nzt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lisp/OmniModulInsert.lsp | 132 +++++++++++++++++++++++++++++++++++++++ cfg/attradd.cfg | 29 +++++++-- lib/attradd.py | 85 ++++++++++++++++++++++--- menu/SSG_LIB.mnu | 34 ++++++++++ 4 files changed, 268 insertions(+), 12 deletions(-) diff --git a/Lisp/OmniModulInsert.lsp b/Lisp/OmniModulInsert.lsp index ef03d95..0873960 100644 --- a/Lisp/OmniModulInsert.lsp +++ b/Lisp/OmniModulInsert.lsp @@ -1338,3 +1338,135 @@ (princ "\n[DUMMY] KettenFoerderer") (princ) ) + +;; --- Omniflo / Verbinder --- +(defun c:OMNI_TV_W_W () + (princ "\n[DUMMY] TV W-W kpl") + (princ) +) +(defun c:OMNI_TV_W_AP110 () + (princ "\n[DUMMY] TV W-AP110 kpl") + (princ) +) +(defun c:OMNI_TV_W_AP60 () + (princ "\n[DUMMY] TV W-AP60 oben kpl.") + (princ) +) +(defun c:OMNI_TV_W_AP110_W () + (princ "\n[DUMMY] TV W-AP110-W kpl") + (princ) +) +(defun c:OMNI_TV_W_AP () + (princ "\n[DUMMY] TV W-AP oben kpl") + (princ) +) +(defun c:OMNI_TV_80 () + (princ "\n[DUMMY] TV 80") + (princ) +) +(defun c:OMNI_TV_50 () + (princ "\n[DUMMY] TV 50") + (princ) +) +(defun c:OMNI_TV_ENDPLATTE () + (princ "\n[DUMMY] Endplatte Al-Profil AP schraubbar") + (princ) +) +(defun c:OMNI_TV_ANSCHLAG () + (princ "\n[DUMMY] Anschlag AP-Ende fuer Spulenzug") + (princ) +) +(defun c:OMNI_TV_A_AP110_AP60 () + (princ "\n[DUMMY] TV-A fuer AP110/AP60 kpl") + (princ) +) +(defun c:OMNI_TV_A_AP60_ST () + (princ "\n[DUMMY] TV-A fuer AP60/ST") + (princ) +) +(defun c:OMNI_TV_A_AP110_ST () + (princ "\n[DUMMY] TV-A fuer AP110/ST kpl") + (princ) +) +(defun c:OMNI_TV_SW_II_SW_SW () + (princ "\n[DUMMY] TV-SW II fuer SW-SW") + (princ) +) +(defun c:OMNI_TV_SW_III_AP110_SW () + (princ "\n[DUMMY] TV-SW III fuer SW-AP110-SW") + (princ) +) +(defun c:OMNI_TV_SW_III_AP110 () + (princ "\n[DUMMY] TV-SW III fuer SW-AP110") + (princ) +) +(defun c:OMNI_TV_SW_IV_AP60 () + (princ "\n[DUMMY] TV-SW IV fuer Anschluss SW-AP60") + (princ) +) +(defun c:OMNI_TV_SW_IV_ST () + (princ "\n[DUMMY] TV-SW IV fuer SW-ST") + (princ) +) +(defun c:OMNI_TV_MUFFE () + (princ "\n[DUMMY] Muffe") + (princ) +) + +;; --- Omniflo / Boegen fuer Weichen --- +(defun c:OMNI_APBW_R400_45_140 () + (princ "\n[DUMMY] APB 110 R400/45 140 nur fuer Delta") + (princ) +) +(defun c:OMNI_APBW_R550_45_194 () + (princ "\n[DUMMY] APB 110 R550/45 194 nur fuer Delta") + (princ) +) +(defun c:OMNI_APBW_R550_225_360 () + (princ "\n[DUMMY] APBW 110 R550/22,5 360x248,5") + (princ) +) +(defun c:OMNI_APBW_R550_225_410A () + (princ "\n[DUMMY] APBW 110 R550/22,5 410x298,5") + (princ) +) +(defun c:OMNI_APBW_R550_225_410B () + (princ "\n[DUMMY] APBW 110 R550/22,5 410x78,5") + (princ) +) +(defun c:OMNI_APBW_R550_225_410C () + (princ "\n[DUMMY] APBW 110 R550/22,5 410x98,5") + (princ) +) +(defun c:OMNI_APBW_R550_675_360 () + (princ "\n[DUMMY] APBW 110 R550/67,5 360x598,5") + (princ) +) +(defun c:OMNI_APBW_R400_675_260 () + (princ "\n[DUMMY] APBW 110 R400/67,5 260x398,5") + (princ) +) +(defun c:OMNI_APBW_R550_45_77 () + (princ "\n[DUMMY] APBW 110 R550/45 77x160") + (princ) +) +(defun c:OMNI_APBW_R550_675_125 () + (princ "\n[DUMMY] APBW 110 R550/67,5 125x83,5") + (princ) +) +(defun c:OMNI_APBW_R750_90_200 () + (princ "\n[DUMMY] APBW 110 R750/90 200x290") + (princ) +) +(defun c:OMNI_APBW_R650_90_300 () + (princ "\n[DUMMY] APBW 110 R650/90 300x190") + (princ) +) +(defun c:OMNI_APBW_R550_675_208 () + (princ "\n[DUMMY] APBW 110 R550/67,5 208x347") + (princ) +) +(defun c:OMNI_APBW_R550_675_58 () + (princ "\n[DUMMY] APBW 110 R550/67,5 58x497") + (princ) +) diff --git a/cfg/attradd.cfg b/cfg/attradd.cfg index 6dc1efc..6bae22d 100644 --- a/cfg/attradd.cfg +++ b/cfg/attradd.cfg @@ -2,7 +2,7 @@ # attradd.cfg - Attribut-Konfiguration fuer Omniflo DXF-Elemente # # Format: -# [ABSCHNITT] Elementtyp (bogen / weiche) +# [ABSCHNITT] Elementtyp (bogen / weiche / layer) # TAG = QUELLE QUELLE ist entweder: # - ein JSON-Feldname (wird aus omniflo_*.json gelesen) # - ein fester Wert in Anfuehrungszeichen: "fester Text" @@ -10,18 +10,38 @@ # # Verfuegbare Platzhalter: # {sivasnr} SivasNr des Elements (= DXF-Dateiname) -# {layer} Ziel-Layer (aus dieser Config) +# {layer} Ziel-Layer (aus [layer] Abschnitt) # {profiltyp} ProfilTyp aus JSON # # Hinweis: # Zeilen mit # sind Kommentare. Leerzeilen werden ignoriert. # ============================================================ +# ------------------------------------------------------------ +# Layer-Zuordnung nach Elementkategorie +# attradd.py bestimmt die Kategorie anhand KurvenWinkel und +# WeichenTyp aus den JSON-Daten und setzt LAYER entsprechend. +# ------------------------------------------------------------ +[layer] +# Boegen (alle Winkel) +bogen = "A-2" +# Weichen 90 Grad (Einzelweiche/Doppelweiche/Dreiwegeweiche, KurvenWinkel=90) +weiche_90 = "A-2" +# Weichen 45 Grad (Einzelweiche/Doppelweiche/Dreiwegeweiche, KurvenWinkel=45) +weiche_45 = "A-2" +# Weichenbatterien / Parallel (KurvenWinkel=0) +weichenbatterie = "A-2" +# Weichenkombinationen (Deltaweiche, Sternweiche, Dreifachweiche) +weichenkombination = "L-2" +# Weichenkoerper (KurvenWinkel=22.5) +weichenkoerper = "L-2" + [bogen] BESCHR = ProfilTyp ARTINR = Sivasnr TEILEART = "Omniflo Kurve" -LAYER = "A-OF-Bogen" +# LAYER wird aus [layer] bestimmt (Kategorie: bogen) +# LAYER = "A-OF-Bogen" RADIUS = Radius WINKEL = KurvenWinkel SIVASNR_TEF = SivasnrTEF @@ -32,7 +52,8 @@ DREHUNG = "0" BESCHR = ProfilTyp ARTINR = Sivasnr TEILEART = "Omniflo Weiche" -LAYER = "A-OF-Weiche" +# LAYER wird aus [layer] bestimmt (Kategorie abhaengig von KurvenWinkel/WeichenTyp) +# LAYER = "A-OF-Weiche" WEICHENTYP = WeichenTyp WINKEL = KurvenWinkel RADIUS = Breite diff --git a/lib/attradd.py b/lib/attradd.py index 640ccb2..bdb523e 100644 --- a/lib/attradd.py +++ b/lib/attradd.py @@ -36,6 +36,7 @@ def load_config(cfg_path): { "bogen": [("BESCHR", "ProfilTyp"), ("ARTINR", "Sivasnr"), ...], "weiche": [("BESCHR", "ProfilTyp"), ...], + "layer": {"bogen": "OF Boegen A-2", "weiche_90": "Weiche 90 Grad A-2", ...}, } """ config = configparser.ConfigParser() @@ -44,14 +45,65 @@ def load_config(cfg_path): result = {} for section in config.sections(): - attrs = [] - for tag, source in config.items(section): - attrs.append((tag, source.strip())) - result[section] = attrs + if section == "layer": + # Layer-Sektion als einfaches Dict speichern + layer_map = {} + for key, val in config.items(section): + val = val.strip() + if val.startswith('"') and val.endswith('"'): + val = val[1:-1] + layer_map[key] = val + result["layer"] = layer_map + else: + attrs = [] + for tag, source in config.items(section): + attrs.append((tag, source.strip())) + result[section] = attrs return result +KOMBI_TYPEN = {"Deltaweiche", "Sternweiche", "Dreifachweiche"} + + +def get_layer_for_entry(typ, json_entry, layer_map): + """ + Bestimmt den Layer-Namen anhand von Elementtyp und JSON-Daten. + Gibt den Layer-String zurueck oder "" wenn kein Mapping vorhanden. + """ + if not layer_map: + return "" + + if typ == "bogen": + return layer_map.get("bogen", "") + + # Weiche: Kategorie anhand KurvenWinkel und WeichenTyp bestimmen + winkel = json_entry.get("KurvenWinkel", 0) + weichentyp = json_entry.get("WeichenTyp", "") + + # Weichenkombinationen (Deltaweiche, Sternweiche, Dreifachweiche) + if weichentyp in KOMBI_TYPEN: + return layer_map.get("weichenkombination", "") + + # Weichenkoerper (KurvenWinkel = 22.5) + if winkel == 22.5: + return layer_map.get("weichenkoerper", "") + + # Weiche 90 Grad + if winkel == 90: + return layer_map.get("weiche_90", "") + + # Weiche 45 Grad + if winkel == 45: + return layer_map.get("weiche_45", "") + + # Weichenbatterien / Parallel (KurvenWinkel = 0) + if winkel == 0: + return layer_map.get("weichenbatterie", "") + + return "" + + def resolve_value(source, json_entry, sivasnr): """ Loest einen Quell-Ausdruck aus der Config auf: @@ -105,13 +157,15 @@ ATTDEF_HEIGHT = 5.0 ATTDEF_LAYER = "ATTRIB" -def add_attdefs_to_dxf(dxf_path, output_path, attr_defs, json_entry, sivasnr): +def add_attdefs_to_dxf(dxf_path, output_path, attr_defs, json_entry, sivasnr, + layer_value=""): """ Oeffnet eine DXF-Datei, fuegt ATTDEF-Entities in den Modelspace ein und speichert das Ergebnis. attr_defs: Liste von (TAG, source_expression) aus der Config json_entry: Dict mit den JSON-Daten fuer dieses Element + layer_value: Layer-Name aus [layer]-Sektion (wird als LAYER-ATTDEF gesetzt) """ doc = ezdxf.readfile(dxf_path) msp = doc.modelspace() @@ -125,9 +179,15 @@ def add_attdefs_to_dxf(dxf_path, output_path, attr_defs, json_entry, sivasnr): for e in existing: msp.delete_entity(e) + # Alle ATTDEFs sammeln: Config-Attribute + LAYER aus [layer]-Sektion + all_defs = list(attr_defs) + if layer_value: + all_defs.append(("LAYER", f'"{layer_value}"')) + # ATTDEFs hinzufuegen y_pos = ATTDEF_START_Y - for tag, source in attr_defs: + count = 0 + for tag, source in all_defs: default_value = resolve_value(source, json_entry, sivasnr) prompt = tag @@ -143,9 +203,10 @@ def add_attdefs_to_dxf(dxf_path, output_path, attr_defs, json_entry, sivasnr): }, ) y_pos += ATTDEF_SPACING + count += 1 doc.saveas(output_path) - return len(attr_defs) + return count # --------------------------------------------------------------------------- @@ -157,7 +218,11 @@ def process_all(data_dir, cfg_path, results_dir, single_nr=None, dry_run=False): # Config laden attr_config = load_config(cfg_path) + layer_map = attr_config.pop("layer", {}) print(f"[attradd] Config geladen: {list(attr_config.keys())}") + if layer_map: + print(f" [layer] {len(layer_map)} Zuordnungen: " + f"{', '.join(f'{k}={v}' for k, v in layer_map.items())}") for section, attrs in attr_config.items(): tags = [a[0] for a in attrs] print(f" [{section}] Attribute: {', '.join(tags)}") @@ -197,18 +262,22 @@ def process_all(data_dir, cfg_path, results_dir, single_nr=None, dry_run=False): continue attr_defs = attr_config[typ] + layer_value = get_layer_for_entry(typ, entry, layer_map) output_path = os.path.join(out_dir, dxf_name) if dry_run: values = {tag: resolve_value(src, entry, sivasnr) for tag, src in attr_defs} + if layer_value: + values["LAYER"] = layer_value print(f" [DRY] {sivasnr} ({typ}): {values}") processed += 1 continue try: count = add_attdefs_to_dxf(dxf_path, output_path, attr_defs, - entry, sivasnr) + entry, sivasnr, + layer_value=layer_value) processed += 1 print(f" OK: {sivasnr} ({typ}) -> {count} Attribute -> {output_path}") except Exception as e: diff --git a/menu/SSG_LIB.mnu b/menu/SSG_LIB.mnu index 2da5f58..11df845 100644 --- a/menu/SSG_LIB.mnu +++ b/menu/SSG_LIB.mnu @@ -76,6 +76,40 @@ [Antriebst. rechts fuer TEF rechts]^C^COMNI_TEF_AntriebR [<-TEF Gerade]^C^COMNI_TEF_Gerade [KettenFoerderer]^C^COMNI_KettenFoerderer +[->Verbinder] +[TV W-W kpl]^C^COMNI_TV_W_W +[TV W-AP110 kpl]^C^COMNI_TV_W_AP110 +[TV W-AP60 oben kpl.]^C^COMNI_TV_W_AP60 +[TV W-AP110-W kpl]^C^COMNI_TV_W_AP110_W +[TV W-AP oben kpl]^C^COMNI_TV_W_AP +[TV 80]^C^COMNI_TV_80 +[TV 50]^C^COMNI_TV_50 +[Endplatte Al-Profil AP schraubbar]^C^COMNI_TV_ENDPLATTE +[Anschlag AP-Ende fuer Spulenzug]^C^COMNI_TV_ANSCHLAG +[TV-A fuer AP110/AP60 kpl]^C^COMNI_TV_A_AP110_AP60 +[TV-A fuer AP60/ST]^C^COMNI_TV_A_AP60_ST +[TV-A fuer AP110/ST kpl]^C^COMNI_TV_A_AP110_ST +[TV-SW II fuer SW-SW]^C^COMNI_TV_SW_II_SW_SW +[TV-SW III fuer SW-AP110-SW]^C^COMNI_TV_SW_III_AP110_SW +[TV-SW III fuer SW-AP110]^C^COMNI_TV_SW_III_AP110 +[TV-SW IV fuer Anschluss SW-AP60]^C^COMNI_TV_SW_IV_AP60 +[TV-SW IV fuer SW-ST]^C^COMNI_TV_SW_IV_ST +[<-Muffe]^C^COMNI_TV_MUFFE +[->Boegen fuer Weichen] +[APB 110 R400/45 140 nur fuer Delta]^C^COMNI_APBW_R400_45_140 +[APB 110 R550/45 194 nur fuer Delta]^C^COMNI_APBW_R550_45_194 +[APBW 110 R550/22,5 360x248,5]^C^COMNI_APBW_R550_225_360 +[APBW 110 R550/22,5 410x298,5]^C^COMNI_APBW_R550_225_410A +[APBW 110 R550/22,5 410x78,5]^C^COMNI_APBW_R550_225_410B +[APBW 110 R550/22,5 410x98,5]^C^COMNI_APBW_R550_225_410C +[APBW 110 R550/67,5 360x598,5]^C^COMNI_APBW_R550_675_360 +[APBW 110 R400/67,5 260x398,5]^C^COMNI_APBW_R400_675_260 +[APBW 110 R550/45 77x160]^C^COMNI_APBW_R550_45_77 +[APBW 110 R550/67,5 125x83,5]^C^COMNI_APBW_R550_675_125 +[APBW 110 R750/90 200x290]^C^COMNI_APBW_R750_90_200 +[APBW 110 R650/90 300x190]^C^COMNI_APBW_R650_90_300 +[APBW 110 R550/67,5 208x347]^C^COMNI_APBW_R550_675_208 +[<-APBW 110 R550/67,5 58x497]^C^COMNI_APBW_R550_675_58 [<-Element bearbeiten]^C^COMNI_EDIT [->External] [Call Python]^C^CCALLPYTHON