From f9558bf8b56c35fec8e22e427ddb0dad81c542ec Mon Sep 17 00:00:00 2001
From: Paul Wolok
Date: Mon, 26 Jan 2026 11:04:53 +0100
Subject: [PATCH] =?UTF-8?q?refactoren=20einf=C3=BCgen=20von=20scanner=20un?=
=?UTF-8?q?d=20separtor=20zu=20Omniflogerade?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
doc/plant2dxf_dokumentation.md | 36 ++++++++++++++++++++++++++++++++++
lib/Elemente/Omniflo.py | 32 +++++++++++++++++++++++-------
lib/Elemente/VarioFoerderer.py | 6 +++++-
lib/as_es_methoden.py | 14 ++++++++++++-
lib/plant2dxf.py | 29 +++++++++++++++------------
5 files changed, 96 insertions(+), 21 deletions(-)
diff --git a/doc/plant2dxf_dokumentation.md b/doc/plant2dxf_dokumentation.md
index e0b3623..c95a628 100644
--- a/doc/plant2dxf_dokumentation.md
+++ b/doc/plant2dxf_dokumentation.md
@@ -1,5 +1,41 @@
# plant2dxf - Dokumentation
+## ⚠️ Wichtiger Hinweis
+
+**Zukünftige Anpassungen erforderlich:**
+
+Aufgrund möglicher Änderungen im CSV-Dateiformat von RuleDesigner müssen in Zukunft möglicherweise folgende Berechnungen und Logiken angepasst werden:
+
+### AS/ES-Element-Berechnungen
+
+Die Logik zur Bestimmung und Platzierung von AS- und ES-Elementen bei Gefällestrecken und Vario-Förderern basiert auf dem aktuellen CSV-Format. Bei Änderungen der Datenstruktur oder der verfügbaren Informationen müssen folgende Methoden in `as_es_methoden.py` überprüft und angepasst werden:
+
+- `erstellung_gefaelle_block_verbunenden_am_einen()`: Erstellt AS/ES-Elemente für Gefällestrecken, die mit einem Kreisel verbunden sind
+- `gefaellegerade_erstellung()`: Erstellt AS/ES-Elemente für Gefällestrecken, die mit zwei Kreiseln verbunden sind
+- `am_kreisel_direct_verbunden()`: Prüft, ob eine Gefällestrecke/Vario-Förderer direkt mit einem Kreisel verbunden ist (ohne Stahlband)
+
+### Höhenvergleiche für Kreisel-Logik
+
+Die Höhenvergleiche zur Bestimmung der Verbindungsart zwischen Gefällestrecken/Vario-Förderern und Kreiseln (z.B. ob die Gefällestrecke mit dem höheren oder niedrigeren Teil des Kreisels verbunden ist) basieren auf den aktuellen CSV-Datenfeldern. Änderungen in der Struktur der Höheninformationen erfordern Anpassungen in:
+
+**Handler-Funktionen (`lib/plant2dxf.py`):**
+
+- `handle_ils_2_0_gefaellestrecke()`: Haupt-Handler für Gefällestrecken
+- `handle_ils_2_0_variofoerderer()`: Haupt-Handler für Vario-Förderer
+
+**Gefällestrecke-Methoden (`lib/Elemente/Gefaehllestrecke.py`):**
+
+- `rotation_mit_zwei_verbunden()`: Berechnet Rotation bei Verbindung mit zwei Kreiseln (verwendet Höhenvergleiche)
+
+**Vario-Förderer-Methoden (`lib/Elemente/VarioFoerderer.py`):**
+- `vario_verbuden_am_kreisel()`: Erstellt Gefällestrecken-Komponenten bei direkter Kreisel-Verbindung (verwendet Höhenvergleiche mit Kreiseln)
+
+**Betroffene Dateien:**
+- `lib/as_es_methoden.py`: AS/ES-Element-Berechnungen
+- `lib/plant2dxf.py`: Handler-Funktionen für Gefällestrecken und Vario-Förderer
+- `lib/Elemente/Gefaehllestrecke.py`: Höhenvergleiche und Verbindungslogik
+- `lib/Elemente/VarioFoerderer.py`: Höhenvergleiche und Verbindungslogik
+
## Übersicht
`plant2dxf` ist ein Python-Skript, das aus einer RuleDesigner-CSV-Datei DXF-Elemente erzeugt. Das Skript liest eine CSV-Datei mit Angaben über alle in einer Anlage enthaltenen Elemente und generiert daraus eine DXF-Datei der kompletten Anlage.
diff --git a/lib/Elemente/Omniflo.py b/lib/Elemente/Omniflo.py
index 4a04fa7..45e230d 100644
--- a/lib/Elemente/Omniflo.py
+++ b/lib/Elemente/Omniflo.py
@@ -9,14 +9,18 @@ class Omniflo(BaseModel):
teileid:str
x:float
y:float
-
sivasnummer:str
laenge: Optional [float]
drehung: float
hoehe : Optional[float]
h0: Optional[float] = Field(default = 0.0,description="Höhe unten im CSV")
h1: Optional[float] = Field(default = 0.0, description="Höhe Oben im CSV")
+ anzahl_scanner: Optional [int] = Field(default=0, description="Anzahl der Scanner")
+ anzahl_separatoren: Optional [int] = Field(default=0, description="Anzahl der Separatoren")
+ @property
+ def hight_zwischen(self):
+ return ((self.h0 + self.h1) /2)
@classmethod
def from_merkmale(cls, teileid,x,y, merkmale):
sivasnummer = merkmale.get("SivasNummer")
@@ -40,6 +44,14 @@ class Omniflo(BaseModel):
h1 = float(merkmale.get("Höhe oben"))
except Exception:
h1 = 0.0
+ try:
+ anzahl_scanner = int(merkmale.get("Anzahl der Scanner", "0").replace(",", ".")) * 1000 # Meter → mm
+ except Exception:
+ anzahl_scanner = 0
+ try:
+ anzahl_separatoren = float(merkmale.get("Anzahl der Separatoren", "0").replace(",", ".")) * 1000 # Meter → mm
+ except Exception:
+ anzahl_separatoren = 0
return cls(
teileid= teileid,
x=x,
@@ -49,13 +61,17 @@ class Omniflo(BaseModel):
drehung = winkel,
hoehe = hoehe,
h0 = h0,
- h1 = h1
+ h1 = h1,
+ anzahl_scanner = anzahl_scanner,
+ anzahl_separatoren = anzahl_separatoren
)
- def Omniflo_geraden_erstellung(msp, x, y, doc, tefsivas, omniflo_objekt):
+ def Omniflo_geraden_erstellung(msp, doc, tefsivas, omniflo_objekt):
"""Erstellung der Tef gerade und Omniflo gerade"""
winkel_rad = math.radians(omniflo_objekt.drehung)
halbe_laenge = omniflo_objekt.laenge / 2
- # Man muss bei sin -1 machen wegen des links koordinaten system
+ x = omniflo_objekt.x
+ y = omniflo_objekt.y
+ # 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, omniflo_objekt.h1 )
@@ -69,15 +85,17 @@ class Omniflo(BaseModel):
linie.dxf.layer = "F-1"
else:
linie.dxf.layer = "A-2"
- def omniflo_foerdererstellung(msp, x, y, doc, lib_doc, omniflo_objekt, rotation):
+ def omniflo_foerdererstellung(msp, doc, lib_doc, omniflo_objekt):
""""Erstellung des Kettenförderers aktuell nur grundriss"""
block_methoden.import_block("bogen1",lib_doc,doc)
block_methoden.import_block("bogen2",lib_doc,doc)
-
+ x = omniflo_objekt.x
+ y = omniflo_objekt.y
+ rotation = omniflo_objekt.drehung
laenge = omniflo_objekt.laenge
h0 = omniflo_objekt.h0
h1 = omniflo_objekt.h1
- h_zwischen = (h0 + h1)/2
+ h_zwischen = omniflo_objekt.hight_zwischen
blockname = (f"OF_Förderer_{laenge}_{h_zwischen}")
winkel_rad = math.radians(rotation)
halbe_laenge = laenge / 2
diff --git a/lib/Elemente/VarioFoerderer.py b/lib/Elemente/VarioFoerderer.py
index ec6a539..8da439c 100644
--- a/lib/Elemente/VarioFoerderer.py
+++ b/lib/Elemente/VarioFoerderer.py
@@ -307,8 +307,12 @@ class VarioFoerderer(BaseModel):
return winkel_VP_offset_vorne,winkel_VP_offset_hinten
- def horizontale_ausrichtung(x, y, voerder_richtung, rotation, x0_kreisel, y0_kreisel):
+ def horizontale_ausrichtung(foerderer, x0_kreisel, y0_kreisel):
"""Schaut was für eine Ausrichtung der Horizontale Förder hat"""
+ voerder_richtung = foerderer.foerderer_richtung
+ rotation = foerderer.drehung
+ x = foerderer.x
+ y = foerderer.y
# mit_horizontal_verbunden None als String für einen späteren vergleich
mit_horizontal_verbunden = "None"
if voerder_richtung == "Horizontal":
diff --git a/lib/as_es_methoden.py b/lib/as_es_methoden.py
index beb1134..6b0e9a2 100644
--- a/lib/as_es_methoden.py
+++ b/lib/as_es_methoden.py
@@ -111,8 +111,20 @@ def erstellung_gefaelle_block_verbunenden_am_einen(msp,x, y, doc, lib_doc, upper
msp.add_blockref(block_es,(ende[0],ende[1]+esoffset_y,lower_hoehe_gefaehlle),dxfattribs={"rotation": as_es_rotation,"layer":layer,"color":color})
return True
-def gefaellegerade_erstellung(x, y, doc, lib_doc, upper_hoehe_gefaehlle, lower_hoehe_gefaehlle, hoehe_gefaehlle,richtung2, drehung0, drehung1, laenge, hight_position, blockname,config, block_vario = None,voerder_richtung = None, am_kreisel = None, erster_kreisel_höher = None,y1=None,z1 =None):
+def gefaellegerade_erstellung(objekt,doc, lib_doc,richtung2, drehung0, drehung1,hight_position, blockname,config, block_vario = None, am_kreisel = None, erster_kreisel_höher = None,y1=None,z1 =None):
"""erstellung des blockes falls die gefaelle strecke mit einem kreisel verbunden ist, mehrere variation von selben weil diese nötig sind sobald man die richtigen inserts bekommen"""
+ if hasattr(objekt,"foerderer_richtung"):
+ voerder_richtung = objekt.foerderer_richtung
+ else:
+ voerder_richtung = None
+
+ laenge =objekt.laenge
+ upper_hoehe_gefaehlle = objekt.h1
+ lower_hoehe_gefaehlle = objekt.h0
+ x = objekt.x
+ y = objekt.y
+ hoehe_gefaehlle = objekt.hight_zwischen
+
asoffset = float(config.get("ILS 2.0 Gefällestrecke", "asoffset"))
esoffset = float(config.get("ILS 2.0 Gefällestrecke", "esoffset"))
winkel_as = float(config.get("Ils 2.0 core winkel", "winkel_as"))
diff --git a/lib/plant2dxf.py b/lib/plant2dxf.py
index 54dc5b7..1b48acf 100644
--- a/lib/plant2dxf.py
+++ b/lib/plant2dxf.py
@@ -97,10 +97,9 @@ def handle_ils_2_0_gefaellestrecke(msp, teileid, merkmale, x, y, doc, lib_doc, v
doc.layers.add(name="6-SP", color=7)
gefaelle_layer = "6-SP"
verbunden_am_einen = False
-
richtung2 ="DEFAULT"
unterschiedlich = False
- anzahl_seperatoren_oder_scan(msp, x, y, doc, lib_doc, gefaelle_objekt, hoehe_gefaehlle, rotation)
+ anzahl_seperatoren_oder_scan(msp, doc, lib_doc, gefaelle_objekt)
for nachbarn in strecken_nachbarn:
if teileid == nachbarn.get("Id"):
gefaellestrecke_nachbarn = nachbarn
@@ -264,7 +263,7 @@ def handle_ils_2_0_gefaellestrecke(msp, teileid, merkmale, x, y, doc, lib_doc, v
blockname = f"Ils_2.0_Gefaellestrecke_{laenge}_{hoehe_gefaehlle}_{drehung0}_{drehung1}_{hight_position}_{verbunden_am_einen}"
else:
blockname = f"Ils_2.0_Gefaellestrecke_{laenge}_{hoehe_gefaehlle}_{drehung0}_{drehung1}_{hight_position}_{unterschiedlich}_{richtung2}_{verbunden_am_einen}"
- as_es_methoden.gefaellegerade_erstellung(x, y, doc, lib_doc, upper_hoehe_gefaehlle, lower_hoehe_gefaehlle, hoehe_gefaehlle,richtung2,drehung0, drehung1, laenge, hight_position,blockname,config)
+ as_es_methoden.gefaellegerade_erstellung(gefaelle_objekt, doc, lib_doc,richtung2,drehung0, drehung1, hight_position,blockname,config)
bref =msp.add_blockref(blockname,(x,y,hoehe_gefaehlle),dxfattribs={"rotation": rotation, "layer": gefaelle_layer})
a = bref.add_attrib(
tag= "NAME",
@@ -337,7 +336,7 @@ def handle_ils_2_0_variofoerderer(msp, teileid, merkmale, x, y, doc, lib_doc, ve
upper_hoehe_vario= foerderer.h1
lower_hoehe_vario = foerderer.h0
hoehe_vario= foerderer.hight_zwischen
- anzahl_seperatoren_oder_scan(msp, x, y, doc, lib_doc, foerderer, hoehe_vario, rotation)
+ anzahl_seperatoren_oder_scan(msp, doc, lib_doc, foerderer)
as_es_methoden.vertausch_der_höhe(foerderer)
upper_hoehe_vario = foerderer.h1
lower_hoehe_vario = foerderer.h0
@@ -364,7 +363,7 @@ def handle_ils_2_0_variofoerderer(msp, teileid, merkmale, x, y, doc, lib_doc, ve
ein_kreisel_höher = True
else:
ein_kreisel_höher = False
- mit_horizontal_verbunden = VarioFoerderer.VarioFoerderer.horizontale_ausrichtung(x, y, voerder_richtung, rotation, x0_eckrad, y0_eckrad)
+ mit_horizontal_verbunden = VarioFoerderer.VarioFoerderer.horizontale_ausrichtung(foerderer, x0_eckrad, y0_eckrad)
blockname = (f"Vario_Foerderer_{winkel}_{voerder_richtung}_{laenge}_{hoehe_vario}_rechts_{ein_kreisel_höher}_{motor_vorhanden}_{umlenk_vorhanden}_{gefaelle}_{gefahellewinkel}_{mit_horizontal_verbunden}")
block_name_links = (f"Vario_Foerderer_{winkel}_{voerder_richtung}_{laenge}_{hoehe_vario}_links_{ein_kreisel_höher}_{motor_vorhanden}_{umlenk_vorhanden}_{gefaelle}_{gefahellewinkel}_{mit_horizontal_verbunden}")
if blockname not in doc.blocks:
@@ -418,7 +417,7 @@ def handle_ils_2_0_variofoerderer(msp, teileid, merkmale, x, y, doc, lib_doc, ve
richtung0 = float(gefaellestrecke_vario.get("rotation0"))
richtung_rad0= math.radians(richtung0)
- mit_horizontal_verbunden = VarioFoerderer.VarioFoerderer.horizontale_ausrichtung(x, y, voerder_richtung, rotation, x0_kreisel, y0_kreisel)
+ mit_horizontal_verbunden = VarioFoerderer.VarioFoerderer.horizontale_ausrichtung(foerderer, x0_kreisel, y0_kreisel)
am_kreisel,kreseil_verbunden =as_es_methoden.am_kreisel_direct_verbunden(x, y, upper_hoehe_vario, lower_hoehe_vario, x0_kreisel, y0_kreisel, richtung_rad0, abstand0, dx, dy, None, None, None, None )
if am_kreisel == 1:
# Erstellung der blockname für wenn die Motorstation rechts und links
@@ -565,7 +564,7 @@ def handle_ils_2_0_variofoerderer(msp, teileid, merkmale, x, y, doc, lib_doc, ve
# Schauen welche es oder as element man braucht man braucht und diese in den block einfügen
# Entnehmen von start und end Werte für spätere vario erstellung
- start, ende = as_es_methoden.gefaellegerade_erstellung(x, y, doc, lib_doc, upper_hoehe_vario, lower_hoehe_vario, hoehe_vario,richtung2, drehung0, drehung1, laenge, None, blockname,config,block_vario,voerder_richtung, am_kreisel,erster_kreisel_höher,y1,z1)
+ start, ende = as_es_methoden.gefaellegerade_erstellung(foerderer, doc, lib_doc,richtung2, drehung0, drehung1, None, blockname,config,block_vario, am_kreisel,erster_kreisel_höher,y1,z1)
# Erstellung der Vario gefälle selber
VarioFoerderer.VarioFoerderer.vario_erstellung(foerderer, doc, lib_doc, config, block_vario,block_name_links, start, ende,voerder_richtung ,winkel_VP_offset_vorne,winkel_VP_offset_hinten)
# Reintuen des endblockes in den Modelspace
@@ -593,7 +592,7 @@ def handle_ils_2_0_variofoerderer(msp, teileid, merkmale, x, y, doc, lib_doc, ve
# Schauen welche es oder as element man braucht man braucht und diese in den block einfügen
# Entnehmen von start und end Werte für spätere vario erstellung
- start, ende = as_es_methoden.gefaellegerade_erstellung(x, y, doc, lib_doc, upper_hoehe_vario, lower_hoehe_vario, hoehe_vario,richtung2, drehung0, drehung1, laenge, None, blockname,config,block_vario,voerder_richtung)
+ start, ende = as_es_methoden.gefaellegerade_erstellung(foerderer, doc, lib_doc,richtung2, drehung0, drehung1, None, blockname,config,block_vario)
# Erstellung des Vario selber
VarioFoerderer.VarioFoerderer.vario_erstellung(foerderer, doc, lib_doc, config, block_vario,block_name_links, start, ende,voerder_richtung,winkel_VP_offset_vorne,winkel_VP_offset_hinten )
# Reintuen des endblockes in den Modelspace
@@ -689,10 +688,12 @@ def handle_omniflo(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols,
omniflo_objekt = Omniflo.Omniflo.from_merkmale(teileid,x,y,merkmale)
rotation = omniflo_objekt.drehung
if omniflo_objekt.sivasnummer == omnisivas or omniflo_objekt.sivasnummer == tefsivas:
- Omniflo.Omniflo.Omniflo_geraden_erstellung(msp, x, y, doc, tefsivas, omniflo_objekt)
-
+ Omniflo.Omniflo.Omniflo_geraden_erstellung(msp, doc, tefsivas, omniflo_objekt)
+ if omniflo_objekt.sivasnummer == omnisivas:
+ anzahl_seperatoren_oder_scan(msp, doc, lib_doc, omniflo_objekt)
elif omniflo_objekt.sivasnummer == foerderer:
- Omniflo.Omniflo.omniflo_foerdererstellung(msp, x, y, doc, lib_doc, omniflo_objekt, rotation)
+ Omniflo.Omniflo.omniflo_foerdererstellung(msp, doc, lib_doc, omniflo_objekt)
+ return
# Sonst wie gehabt: Block mit SivasNummer
else:
if not lib_doc:
@@ -710,10 +711,14 @@ def handle_omniflo(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols,
layer, color = block_methoden.get_insert_color_layer(lib_doc, omniflo_objekt.sivasnummer)
msp.add_blockref(blockname, (x, y,omniflo_objekt.hoehe), dxfattribs={"rotation": rotation,"layer": layer, "color": color})
-def anzahl_seperatoren_oder_scan(msp, x, y, doc, lib_doc, klassen_objekt, hoehe, rotation):
+def anzahl_seperatoren_oder_scan(msp, doc, lib_doc, klassen_objekt):
"""Importiert alle seperatoren und/oder scanner für das nötige objekt"""
separatoren = klassen_objekt.anzahl_separatoren
scanner = klassen_objekt.anzahl_scanner
+ x = klassen_objekt.x
+ y = klassen_objekt.y
+ hoehe =klassen_objekt.hight_zwischen
+ rotation = klassen_objekt.drehung
# Schauen welche Ausrichtung das Objekt hat, damit man die Separtoren unbd Scanner nicht in das Objekt tut
if rotation == 0 or rotation == -180:
ausrichtung = "V"