From 778a885e6e88900c7314d2893a4d590815e519a5 Mon Sep 17 00:00:00 2001 From: Paul Wolok Date: Wed, 15 Oct 2025 11:52:04 +0200 Subject: [PATCH] =?UTF-8?q?erster=20protype=20einer=20f=C3=B6rderers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cfg/shapes.cfg | 9 +- lib/plant2dxf.py | 254 +++++++++++++++++++++++++++++++---------------- 2 files changed, 175 insertions(+), 88 deletions(-) diff --git a/cfg/shapes.cfg b/cfg/shapes.cfg index c70a338..c0dc8a9 100644 --- a/cfg/shapes.cfg +++ b/cfg/shapes.cfg @@ -13,4 +13,11 @@ rot_symb1 = 0.0 rot_symb2 = 0.0 asoffset = 537.90 esoffset = 479.95 -additionaloffset = 59.48 + + +[ILS 2.0 Variofoerderer] +Vario_Bogen_auf_39_Delta_SP_0 = 489.1281, 0, 25.6341 +Vario_Bogen_auf_39_Delta_SP_1 = 358.3992, 0, 260.3923 +Vario_Bogen_ab_39_Delta_SP_0 = 335.7703, 0, 243.9534 +Vario_Bogen_ab_39_Delta_SP_1 =461.1878, 0, 24.1747 + diff --git a/lib/plant2dxf.py b/lib/plant2dxf.py index 5c8ab47..7e11079 100644 --- a/lib/plant2dxf.py +++ b/lib/plant2dxf.py @@ -13,11 +13,15 @@ import configparser import ezdxf from ezdxf import units from ezdxf.entities import Line -from ezdxf.math import Matrix44 +from ezdxf.math import Matrix44, X_AXIS,Y_AXIS,Z_AXIS +from ezdxf.math import UCS +from ezdxf import transform +from ezdxf.addons.importer import Importer from pathlib import Path import math from utils import check_environment_var, setup_logger + # --------------------------------------------------------- CFG-Leser für shapes.cfg def get_shape_cfg(teileart, cfg_path, logger=None): parser = configparser.ConfigParser() @@ -80,19 +84,23 @@ def parse_merkmale(merkmale_str: str) -> dict: except json.JSONDecodeError: return {} -def import_block(block_name: str, from_doc, to_doc) -> None: +def import_block(block_name: str, from_doc, to_doc, winkel = None) -> None: """Importiert Blockdefinition block_name von from_doc nach to_doc. - Kopiert alle Entities des Blocks - Stellt sicher, dass benutzte Layer im Ziel existieren (mit Eigenschaften) - Übernimmt Basis­punkt und Block-Layer, falls vorhanden """ - if block_name in to_doc.blocks: - return + if block_name == '200000291_Staustrecke_SP_steigend__6': + test = 3 + + if (block_name in to_doc.blocks): + return if block_name not in from_doc.blocks: raise ValueError(f"Block '{block_name}' nicht in Bibliothek gefunden.") src = from_doc.blocks[block_name] # Sicherstellen, dass alle verwendeten Layer existieren + try: used_layer_names = {e.dxf.layer for e in src if hasattr(e.dxf, "layer")} for layer_name in used_layer_names: @@ -110,7 +118,6 @@ def import_block(block_name: str, from_doc, to_doc) -> None: to_doc.layers.add(name=layer_name) except Exception: pass - tgt = to_doc.blocks.new(name=block_name) # Basis­punkt/Layer des Blocks übernehmen, wenn vorhanden try: @@ -123,8 +130,13 @@ def import_block(block_name: str, from_doc, to_doc) -> None: pass for ent in src: + if winkel != None: + + rotation_matrix = Matrix44.axis_rotate(Y_AXIS, winkel) + ent.transform(rotation_matrix) + if ent.dxftype() == "INSERT": - import_block(ent.dxf.name,from_doc, to_doc) + import_block(ent.dxf.name,from_doc, to_doc,None) tgt.add_entity(ent.copy()) @@ -160,7 +172,7 @@ def transform_coords(x: float, y: float, height: float) -> tuple[float, float]: """Transformiert Bildschirmkoordinaten (0,0 oben links) ins DXF-KoSy (0,0 unten links).""" return x, y -def handle_ils_2_0_kreisel(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols,gefaellestrecken_nachbarn,config): +def handle_ils_2_0_kreisel(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols,strecken_nachbarn,config): abstand_m = merkmale.get( "Abstand (Kreiselachse A - Kreiselachse) in Meter", "20" ).replace(",", ".") @@ -281,10 +293,12 @@ def handle_standard(msp, blocknames, teileid, x, y, lib_doc, doc, verbose): f"({x:.1f}, {y:.1f})") -def handle_ils_2_0_gefaellestrecke(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols, gefaellestrecken_nachbarn,config): +def handle_ils_2_0_gefaellestrecke(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols, strecken_nachbarn,config): #Vorbereitung der attributen + + if "6-SP" not in doc.layers: - doc.layers.add(name="6-SP", color=3) + doc.layers.add(name="6-SP", color=7) verbunden_am_einen = False am_kreisel = 0 @@ -295,7 +309,7 @@ def handle_ils_2_0_gefaellestrecke(msp, teileid, merkmale, x, y, doc, lib_doc, v upper_hoehe_gefaehlle= float(merkmale.get("Höhe oben")) *1000 lower_hoehe_gefaehlle = float(merkmale.get("Höhe unten")) * 1000 hoehe_gefaehlle = (upper_hoehe_gefaehlle + lower_hoehe_gefaehlle)/2 - for nachbarn in gefaellestrecken_nachbarn: + for nachbarn in strecken_nachbarn: if teileid == nachbarn.get("Id"): gefaellestrecke_nachbarn = nachbarn break @@ -833,6 +847,137 @@ def handle_ils_2_0_gefaellestrecke(msp, teileid, merkmale, x, y, doc, lib_doc, v line = msp.add_line(start,ende) line.dxf.layer = "6-SP" + +def handle_ils_2_0_variofoerderer(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols, strecken_nachbarn,config): + if "VARIO" not in doc.layers: + doc.layers.add(name="VARIO", color=3) + verbunden_am_einen = False + + + am_kreisel = 0 + richtung2 ="DEFAULT" + unterschiedlich = False + asoffset = float(config.get("ILS 2.0 Gefällestrecke", "asoffset")) + esoffset = float(config.get("ILS 2.0 Gefällestrecke", "esoffset")) + Vario_Bogen_auf_39_Delta_SP_0 = tuple(float(x)for x in (config.get("ILS 2.0 Variofoerderer","Vario_Bogen_auf_39_Delta_SP_0")).split(",")) + Vario_Bogen_auf_39_Delta_SP_1 = tuple(float(x) for x in (config.get("ILS 2.0 Variofoerderer","Vario_Bogen_auf_39_Delta_SP_1")).split(",")) + Vario_Bogen_ab_39_Delta_SP_0 = tuple(float(x) for x in(config.get("ILS 2.0 Variofoerderer","Vario_Bogen_ab_39_Delta_SP_0")).split(",")) + Vario_Bogen_ab_39_Delta_SP_1 = tuple(float(x) for x in(config.get("ILS 2.0 Variofoerderer","Vario_Bogen_ab_39_Delta_SP_1")).split(",")) + block_Vario_Umlenkstation_500mm ="Vario_Umlenkstation_500mm" + block_Vario_Bogen_auf_39 = "Vario_Bogen_auf_39°" + block_Vario_Bogen_ab_39 = "Vario_Bogen_ab_39°" + block_Vario_Motorstation_500mm = "Vario_Motorstation_500mm" + upper_hoehe_vario= float(merkmale.get("Höhe Anfang")) *1000 + lower_hoehe_vario = float(merkmale.get("Höhe Ende")) *1000 + hoehe_vario= (upper_hoehe_vario + lower_hoehe_vario)/2 + for nachbarn in strecken_nachbarn: + if teileid == nachbarn.get("Id"): + gefaellestrecke_vario = nachbarn + break + block = doc.blocks.new(name="test", base_point=(0,0,0)) + import_block(block_Vario_Umlenkstation_500mm, lib_doc, doc,math.radians(3)) + import_block(block_Vario_Bogen_auf_39, lib_doc, doc,math.radians(3)) + import_block(block_Vario_Bogen_ab_39, lib_doc, doc,math.radians(-36)) + import_block( block_Vario_Motorstation_500mm, lib_doc, doc,math.radians(3)) + laenge = float(merkmale.get("Länge in Meter")) *1000 + halbe_laenge = laenge/2 + dx = halbe_laenge * math.cos(0) + if upper_hoehe_vario< lower_hoehe_vario: + hight = upper_hoehe_vario + upper_hoehe_vario = lower_hoehe_vario + lower_hoehe_vario = hight + start = (x+ dx,y, upper_hoehe_vario) + ende = (x -dx,y, lower_hoehe_vario) + # msp.add_line(start, ende) + + block.add_blockref(block_Vario_Umlenkstation_500mm,(ende[0] + 249.6574 -x,ende[1] -y ,ende[2] - hoehe_vario -13.0840 )) + ende = (ende[0] + 499.3148,ende[1],ende[2] -26.1680) + # msp.add_line(ende, (0, y , ende[2])) + block.add_blockref(block_Vario_Bogen_auf_39,(ende[0] -x +Vario_Bogen_auf_39_Delta_SP_0[0],ende[1] -y ,ende[2] - Vario_Bogen_auf_39_Delta_SP_0[2]- hoehe_vario )) + ende = (ende[0] +Vario_Bogen_auf_39_Delta_SP_1[0] + Vario_Bogen_auf_39_Delta_SP_0[0] ,ende[1] ,ende[2] + Vario_Bogen_auf_39_Delta_SP_1[2] - Vario_Bogen_auf_39_Delta_SP_0[2]) + + block.add_blockref(block_Vario_Motorstation_500mm, (start[0]-x - 249.6574, start[1] -y ,start[2] - hoehe_vario +13.0840)) + start = start[0] - 499.3148, start[1],start[2] +26.1680 + block.add_blockref(block_Vario_Bogen_ab_39 ,(start[0]-x - Vario_Bogen_ab_39_Delta_SP_1[0],start[1] -y ,start[2] - hoehe_vario+Vario_Bogen_ab_39_Delta_SP_1[2])) + start = start[0] - Vario_Bogen_ab_39_Delta_SP_0[0] - Vario_Bogen_ab_39_Delta_SP_1[0],start[1],start[2] -Vario_Bogen_ab_39_Delta_SP_0[2] + Vario_Bogen_ab_39_Delta_SP_1[2] + line = Line.new(dxfattribs={"start": start, "end": ende}) + + copy= line.copy() + + copy.translate(-x,-y,-hoehe_vario) + block.add_entity(copy) + bref =msp.add_blockref("test",(x,y,hoehe_vario)) + # msp.add_blockref(block_Vario_Bogen_ab_39,(x,y,0 )) + # msp.add_line((x,y+250,0 ),(x,y-250,0)) + # msp.add_line((x+250,y,0 ),(x-250,y,0)) + + + + + +def handle_omniflo(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols, strecken_nachbarn,config): + """ + 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")) + except Exception: + winkel = 0.0 + + winkel_rad = math.radians(winkel) + halbe_laenge = laenge / 2 + # Man muss bei sin -1 machen wegen des links koordinaten system + dx = halbe_laenge * math.sin(winkel_rad * -1) + dy = halbe_laenge * math.cos(winkel_rad) + start = (x + dx, y + dy, float(merkmale.get("Höhe oben")) ) + ende = (x - dx, y - dy, float(merkmale.get("Höhe unten"))) + if "A-2" not in doc.layers: + doc.layers.add(name="A-2", color=2) + linie=msp.add_line(start, ende) + linie.dxf.layer = "A-2" + + + 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) + blockref_layer = get_layer(doc, lib_doc, blockname) + drehung = merkmale.get("Drehung") + + bref = msp.add_blockref(blockname, (x, y,float(merkmale.get("Höhe"))), dxfattribs={"xscale": 1.0, "yscale":1.0,"rotation": drehung, "layer": blockref_layer}) + + a =bref.add_attrib( + tag= "NAME", + text= merkmale.get("bezeichner"), + insert = (x,y) + + + ) + a.is_invisible = True + bref.add_auto_attribs({ATTR_TAG: teileid}) + if verbose: + print(f"[INFO] Block '{blockname}' (Omniflo) → {teileid} ({x:.1f}, {y:.1f})") + + + def erstellung_gefaelle_block_verbunenden_am_einen(x, y, doc, lib_doc, asoffset, esoffset, upper_hoehe_gefaehlle, lower_hoehe_gefaehlle, hoehe_gefaehlle, drehung0, laenge, hight, blockname): if blockname not in doc.blocks and hight == "higher" and drehung0 == "GUZS": block = doc.blocks.new(name=blockname, base_point=(0,0,0)) @@ -1165,71 +1310,6 @@ def gefaellegerade_erstellung(x, y, doc, lib_doc, asoffset, esoffset, upper_hoeh block.add_blockref(block_as,(start[0]-x ,start[1]+asoffset -y,start[2] - hoehe_gefaehlle),dxfattribs={"rotation": 180}) block.add_blockref(block_es, (ende[0]-x ,ende[1]-esoffset -y,ende[2] - hoehe_gefaehlle)) - -def handle_omniflo(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols, gefaellestrecken_nachbarn,config): - """ - 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")) - except Exception: - winkel = 0.0 - - winkel_rad = math.radians(winkel) - halbe_laenge = laenge / 2 - # Man muss bei sin -1 machen wegen des links koordinaten system - dx = halbe_laenge * math.sin(winkel_rad * -1) - dy = halbe_laenge * math.cos(winkel_rad) - start = (x + dx, y + dy, float(merkmale.get("Höhe oben")) ) - ende = (x - dx, y - dy, float(merkmale.get("Höhe unten"))) - if "A-2" not in doc.layers: - doc.layers.add(name="A-2", color=2) - linie=msp.add_line(start, ende) - linie.dxf.layer = "A-2" - - - 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) - blockref_layer = get_layer(doc, lib_doc, blockname) - drehung = merkmale.get("Drehung") - - bref = msp.add_blockref(blockname, (x, y,float(merkmale.get("Höhe"))), dxfattribs={"xscale": 1.0, "yscale":1.0,"rotation": drehung, "layer": blockref_layer}) - - a =bref.add_attrib( - tag= "NAME", - text= merkmale.get("bezeichner"), - insert = (x,y) - - - ) - a.is_invisible = True - bref.add_auto_attribs({ATTR_TAG: teileid}) - if verbose: - print(f"[INFO] Block '{blockname}' (Omniflo) → {teileid} ({x:.1f}, {y:.1f})") - - - - def get_layer(doc, lib_doc, blockname): if blockname in lib_doc.blocks: src = lib_doc.blocks[blockname] @@ -1287,21 +1367,21 @@ def get_libfile_cfg(teileart, cfg_path): return None -def get_rotations_of_gefaellestrecke(csv_path:Path) -> dict: - gefaehlleStrecken = [] +def get_rotations_of_strecken(csv_path:Path) -> dict: + geraden = [] kreisel =[] - gefaellestrecken_nachbarn = [] + strecken_nachbarn = [] anweisungen = 0 """Gib für jede gefällestrecke zurück welche Drehrichtung die benachbarten Kreisel haben """ with csv_path.open(newline="", encoding="utf-8") as fh: reader = csv.DictReader(fh, delimiter=';') for row in reader: bezeichner = row["TeileArt"].strip() - if bezeichner == "ILS 2.0 Gefällestrecke": + if bezeichner == "ILS 2.0 Gefällestrecke" or bezeichner =="ILS 2.0 VarioFoerderer": Id = row["TeileId"].strip() NachbarIds = row["NachbarIds"].strip() - gefaehlleStrecken.append({"Id": Id, "NachbarIds": NachbarIds}) + geraden.append({"Id": Id, "NachbarIds": NachbarIds}) if bezeichner == "ILS 2.0 Kreisel": Id = row["TeileId"].strip() planquadrat = row["Planquadrat"] @@ -1316,11 +1396,11 @@ def get_rotations_of_gefaellestrecke(csv_path:Path) -> dict: kreisel.append({"Id":Id, "drehung":drehung, "höhe":hight,"x": x, "y": y, "rotation": rotation,"abstand":abstand_m}) - for gefaelle in gefaehlleStrecken: + for gerade in geraden: anweisungen = 0 - eintrag = {"Id": gefaelle["Id"]} + eintrag = {"Id": gerade["Id"]} for kreis in kreisel: - if kreis["Id"] in gefaelle["NachbarIds"]: + if kreis["Id"] in gerade["NachbarIds"]: if anweisungen == 0: eintrag["Drehung0"] = kreis.get("drehung") eintrag["Hoehe0"] = kreis.get("höhe") @@ -1337,9 +1417,9 @@ def get_rotations_of_gefaellestrecke(csv_path:Path) -> dict: eintrag["rotation1"] = kreis.get("rotation") eintrag["abstand1"] = kreis.get("abstand") break - gefaellestrecken_nachbarn.append(eintrag) + strecken_nachbarn.append(eintrag) - return gefaellestrecken_nachbarn + return strecken_nachbarn @@ -1377,7 +1457,7 @@ def main(csv_path: Path, lib_path: Path, cfg_path: Path, blocklib_dir = data_dir / "block_libraries" lib_docs = dict() - gefaellestrecken_nachbarn = get_rotations_of_gefaellestrecke(csv_path) + strecken_nachbarn = get_rotations_of_strecken(csv_path) # gibt zu jeder ShapeId einer Gefällestrecke zurück, ob sich der jeweilige Kreisel im UZ oder GUZ dreht # rot_of_gf["shape_3ae53a7b-efb8-f66b-eadc-20b99f949ef1"] = ('UZ', 'GUZ') @@ -1434,7 +1514,7 @@ def main(csv_path: Path, lib_path: Path, cfg_path: Path, if func_name.startswith('handle_omniflo'): handler = globals().get('handle_omniflo') if handler: - handler(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols, gefaellestrecken_nachbarn, config) + handler(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols, strecken_nachbarn, config) else: msg = f"[WARN] Keine Routine für TeileArt '{teileart}'. Überspringe '{teileid}'." if logger: