From fedd12d6e23aaf530af84539027877c3c983489e Mon Sep 17 00:00:00 2001 From: lertlmaier Date: Wed, 30 Jul 2025 11:39:55 +0200 Subject: [PATCH] =?UTF-8?q?Erweiterung=20der=20allgemeinen=20Konfiguration?= =?UTF-8?q?sdatei=20zur=20Zuweisung=20von=20Block-Bibliotheken=20f=C3=BCr?= =?UTF-8?q?=20ILS=20und=20Omniflo.=20Implementierung=20der=20Funktion=20`h?= =?UTF-8?q?andle=5Fomniflo`=20zur=20Verarbeitung=20von=20Omniflo-Typen=20i?= =?UTF-8?q?n=20`plant2dxf.py`.=20Anpassung=20der=20Hauptfunktion=20zur=20U?= =?UTF-8?q?nterst=C3=BCtzung=20von=20Bibliotheksdateien=20basierend=20auf?= =?UTF-8?q?=20der=20Teileart.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cfg/allgemein.cfg | 11 ++++- lib/plant2dxf.py | 109 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 99 insertions(+), 21 deletions(-) diff --git a/cfg/allgemein.cfg b/cfg/allgemein.cfg index 7003541..4e4784e 100644 --- a/cfg/allgemein.cfg +++ b/cfg/allgemein.cfg @@ -1,2 +1,9 @@ -# Allgemeine Konfigurationsdatei, welche die einzulesenden Layer, sowie geometrische Abhängigkeiten steuert. -# General Config-File, that controls the Layers being read while processing a certain dxf file +# Allgemeine Konfigurationsdatei, welche die Zuweisung von Block-Bibliotheken zu bestimmten Bauteil-Familien steuert +# General Config-File, that controls the assignment of block libraries to certain component families + +[ILS] +libfile = ils_lib.dxf + +[Omniflo] +libfile = omniflo_lib.dxf + diff --git a/lib/plant2dxf.py b/lib/plant2dxf.py index 163dbc0..1adae2b 100644 --- a/lib/plant2dxf.py +++ b/lib/plant2dxf.py @@ -263,6 +263,48 @@ def handle_ils_2_0_gefaellestrecke(msp, teileid, merkmale, x, y, doc, lib_doc, v elif lib_doc is None: print("[WARN] lib_doc nicht verfügbar, Blöcke werden nicht eingefügt.") +def handle_omniflo(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols): + """ + Für Omniflo Gerade: zeichnet eine Linie (Mitte = Koordinate, Länge und Winkel aus Merkmale). + Für alle anderen Omniflo-Typen: Block mit SivasNummer an den Koordinaten. + """ + # Prüfen, ob es sich um eine Gerade handelt + if merkmale.get("Länge in Meter") is not None and merkmale.get("Winkel") is not None: + try: + laenge = float(merkmale.get("Länge in Meter", "0").replace(",", ".")) * 1000 # Meter → mm + except Exception: + laenge = 0 + try: + winkel = float(merkmale.get("Drehung", 0)) + except Exception: + winkel = 0.0 + winkel_rad = math.radians(winkel) + halbe_laenge = laenge / 2 + dx = halbe_laenge * math.cos(winkel_rad) + dy = halbe_laenge * math.sin(winkel_rad) + start = (x - dx, y - dy) + ende = (x + dx, y + dy) + msp.add_line(start, ende) + if verbose: + print(f"[INFO] Omniflo Gerade → {teileid} Linie von ({start[0]:.1f}, {start[1]:.1f}) nach ({ende[0]:.1f}, {ende[1]:.1f})") + return + # Sonst wie gehabt: Block mit SivasNummer + if not lib_doc: + print("[WARN] lib_doc nicht verfügbar, Block wird nicht eingefügt.") + return + blockname = merkmale.get("SivasNummer") + if not blockname: + print(f"[WARN] Keine SivasNummer für {teileid}, überspringe.") + return + if blockname not in lib_doc.blocks: + print(f"[WARN] Omniflo-Block '{blockname}' nicht in Bibliothek {lib_doc.filename}. Überspringe {teileid}.") + return + import_block(blockname, lib_doc, doc) + bref = msp.add_blockref(blockname, (x, y)) + bref.add_auto_attribs({ATTR_TAG: teileid}) + if verbose: + print(f"[INFO] Block '{blockname}' (Omniflo) → {teileid} ({x:.1f}, {y:.1f})") + def normalize_func_name(name): return ( name.replace('ä', 'ae') @@ -274,28 +316,31 @@ def normalize_func_name(name): .lower() ) +def get_libfile_cfg(teileart, cfg_path): + """Liest den Bibliotheksdateinamen für eine TeileArt aus der allgemein.cfg.""" + parser = configparser.ConfigParser() + with open(cfg_path, encoding='utf-8') as f: + parser.read_file(f) + # Teileart kann z.B. "ILS 2.0 Kreisel" sein, wir nehmen den ersten Teil vor erstem Leerzeichen oder Punkt + # oder suchen iterativ nach Sektionen, die im Teileart-Namen vorkommen + for section in parser.sections(): + if section in teileart: + return parser.get(section, "libfile", fallback=None) + return None + # --------------------------------------------------------- Hauptfunktion -def main(csv_path: Path, lib_path: Path, cfg_path: Path, - output_path: Path, verbose=False): +def main(csv_path: Path, default_lib_path: Path, shapes_cfg_path: Path, output_path: Path, verbose=False): - # Bibliothek nur laden, wenn Datei existiert - lib_doc = None - if lib_path.exists(): - try: - lib_doc = ezdxf.readfile(lib_path) - if verbose: - print(f"[INFO] Bibliothek geladen: {lib_path}") - except Exception as e: - sys.exit(f"Fehler beim Lesen der Bibliothek '{lib_path}': {e}") - else: - print(f"[INFO] Keine Bibliothek gefunden unter {lib_path}. " - "Komplexe Formen werden übersprungen.") + # Bibliotheks-Cache + lib_docs = {} + # Verzeichnisse + data_dir = check_environment_var("PROJECT_DATA") + blocklib_dir = Path(data_dir) / "block_libaries" - # Neue Ziel­zeichnung (DXF R2018) + # Neue Zielzeichnung (DXF R2018) doc = ezdxf.new(dxfversion="R2018") msp = doc.modelspace() - # CSV einlesen # Höhe bestimmen für Koordinaten-Transformation height = berechne_hoehe(csv_path) @@ -315,10 +360,35 @@ def main(csv_path: Path, lib_path: Path, cfg_path: Path, print(f"[WARN] {teileid}: {e}") continue + # Bibliotheksdatei bestimmen + libfile = get_libfile_cfg(teileart, allgemein_cfg_path) + if libfile: + lib_path = blocklib_dir / libfile + else: + lib_path = default_lib_path + + # Bibliothek laden (mit Cache) + lib_doc = None + if lib_path in lib_docs: + lib_doc = lib_docs[lib_path] + elif lib_path.exists(): + try: + lib_doc = ezdxf.readfile(lib_path) + lib_docs[lib_path] = lib_doc + if verbose: + print(f"[INFO] Bibliothek geladen: {lib_path}") + except Exception as e: + print(f"[WARN] Fehler beim Lesen der Bibliothek '{lib_path}': {e}") + else: + print(f"[INFO] Keine Bibliothek gefunden unter {lib_path}. Komplexe Formen werden übersprungen.") + # Funktions-Dispatch: handle_ (mit _ statt Leerzeichen und Punkten, alles klein) func_name = f'handle_{normalize_func_name(teileart)}' handler = globals().get(func_name) - symbols = get_shape_cfg(teileart, cfg_path) + symbols = get_shape_cfg(teileart, shapes_cfg_path) + # Mapping für Omniflo-Typen + if func_name.startswith('handle_omniflo'): + handler = globals().get('handle_omniflo') if handler: handler(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols) else: @@ -351,7 +421,8 @@ if __name__ == "__main__": csv_path = Path(args.file) cfg_path = Path(args.config) if args.config else config_dir / "shapes.cfg" - lib_path = Path(args.lib) if args.lib else data_dir / "blocks.dxf" + allgemein_cfg_path = config_dir / "allgemein.cfg" + default_lib_path = Path(args.lib) if args.lib else data_dir / "blocks.dxf" output_path = Path(args.output) if args.output else (work_dir / f"{csv_path.stem}.dxf") - main(csv_path, lib_path, cfg_path, output_path, verbose=args.verbose) + main(csv_path, default_lib_path, cfg_path, output_path, verbose=args.verbose)