kleinere Korrektur für Dreifach, Delta und Sternweiche zur Bestimmung von K2 und K3. NEuer Algorithmus
This commit is contained in:
+443
-61
@@ -13,9 +13,32 @@ Schalter:
|
||||
Weichen: Beginn der untersten vertikalen Linie,
|
||||
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).
|
||||
Nutzt dieselben Schalter-Filter wie set_einfuegepkt.py
|
||||
(SWITCH_FILTERS aus utils.py).
|
||||
|
||||
Boegen:
|
||||
Position am anderen Ende der Kette (Gerade-Bogen-Gerade).
|
||||
x-Achse tangential zur Linie, zur Bogenmitte zeigend.
|
||||
y senkrecht dazu, z wie K1 (aus Zeichenebene).
|
||||
180-Grad-Sonderfall: x nach rechts (rz=0).
|
||||
|
||||
Weichen (weichen45, weichen90, weichen_parallel):
|
||||
Folgt dem Bogenzweig bis zum Ende.
|
||||
x tangential zur Linie, zur Kurve zeigend.
|
||||
Bei Doppelweichen: linker Zweig.
|
||||
y senkrecht dazu, z wie K1.
|
||||
|
||||
--k3set K3 an Weichen mit 2+ Boegen setzen (rechter Zweig).
|
||||
Gleiche Logik wie K2, aber rechter Ast (groesstes x).
|
||||
Nur bei: Doppelweichen, Dreiwegeweichen,
|
||||
Dreifachweiche, Delta, Stern, Weichenkoerper Doppel/Dreiwege.
|
||||
--k4set K4 an Weichen setzen (oberes Ende der K1-Linie).
|
||||
K4 liegt K1 gegenueber, am oberen Ende derselben V-Linie.
|
||||
Rotation wie K1: x oben, y links, z aus Zeichenebene.
|
||||
Kein K4 bei: Boegen, Doppelweiche, Dreifachweiche, Delta.
|
||||
--set-all Alle Koordinatensysteme (K1-K4) in einem Durchgang setzen.
|
||||
--force Bestehende Kx ueberschreiben (sonst skip wenn vorhanden).
|
||||
Duplikate werden immer bereinigt (letztes bleibt).
|
||||
--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.
|
||||
@@ -256,6 +279,25 @@ def k1_point_weiche(doc):
|
||||
return (x, bottom_y, 0), 0, 0, 90
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# K2-Positionsbestimmung (nur Boegen)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def k4_point_weiche(doc):
|
||||
"""K4-Position fuer Weichen: oberes Ende der K1-Vertikallinie.
|
||||
|
||||
K4 liegt K1 gegenueber, am oberen Ende derselben vertikalen Linie.
|
||||
Rotation wie K1: x oben, y links, z aus Zeichenebene (rz=90).
|
||||
"""
|
||||
vline = find_bottommost_vertical_line(doc)
|
||||
if vline is None:
|
||||
return None
|
||||
s, e = vline.dxf.start, vline.dxf.end
|
||||
x = s[0]
|
||||
top_y = max(s[1], e[1])
|
||||
return (x, top_y, 0), 0, 0, 90
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# K2-Positionsbestimmung (nur Boegen)
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -346,65 +388,329 @@ def k2_point_bogen(doc):
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# K2-Positionsbestimmung Weichen (Dummy-Funktionen)
|
||||
# K2-Positionsbestimmung Weichen
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def k2_point_weichen45(doc):
|
||||
"""K2 fuer Weichen 45 Grad – noch nicht implementiert."""
|
||||
return None
|
||||
def _find_weiche_arc_branches(doc):
|
||||
"""Findet alle Bogenzweig-Endpunkte einer Weiche.
|
||||
|
||||
Returns:
|
||||
Liste von (k2_pos, junc_pt) Tupeln, sortiert nach x (links zuerst),
|
||||
oder None falls keine Boegen gefunden.
|
||||
"""
|
||||
msp = doc.modelspace()
|
||||
|
||||
# K1-Position bestimmen (unterste vertikale Linie)
|
||||
vline = find_bottommost_vertical_line(doc)
|
||||
if vline is None:
|
||||
return None
|
||||
s, e = vline.dxf.start, vline.dxf.end
|
||||
k1_x = s[0]
|
||||
k1_y = min(s[1], e[1])
|
||||
|
||||
# Alle Boegen sammeln
|
||||
arcs = [e for e in msp if e.dxftype() == "ARC"]
|
||||
if not arcs:
|
||||
return None
|
||||
|
||||
tol = 1.0
|
||||
|
||||
# Fuer jeden Bogen: K2-seitiges Ende bestimmen und Endpunkt der Linie finden
|
||||
candidates = []
|
||||
for arc in arcs:
|
||||
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 = naeher an K1
|
||||
d_start = ((arc_start[0] - k1_x)**2 + (arc_start[1] - k1_y)**2) ** 0.5
|
||||
d_end = ((arc_end[0] - k1_x)**2 + (arc_end[1] - k1_y)**2) ** 0.5
|
||||
|
||||
if d_start < d_end:
|
||||
k2_junction = arc_end
|
||||
else:
|
||||
k2_junction = arc_start
|
||||
|
||||
# Laengste Linie am K2-Bogenende suchen
|
||||
best_len = 0
|
||||
k2_pos = None
|
||||
junc_pt = None
|
||||
for ent in msp:
|
||||
if ent.dxftype() != "LINE":
|
||||
continue
|
||||
ls = (ent.dxf.start[0], ent.dxf.start[1])
|
||||
le = (ent.dxf.end[0], ent.dxf.end[1])
|
||||
ds = ((ls[0] - k2_junction[0])**2 + (ls[1] - k2_junction[1])**2) ** 0.5
|
||||
de = ((le[0] - k2_junction[0])**2 + (le[1] - k2_junction[1])**2) ** 0.5
|
||||
if ds > tol and de > tol:
|
||||
continue
|
||||
ln = ((le[0] - ls[0])**2 + (le[1] - ls[1])**2) ** 0.5
|
||||
if ln > best_len:
|
||||
best_len = ln
|
||||
if ds < tol:
|
||||
k2_pos = le
|
||||
junc_pt = ls
|
||||
else:
|
||||
k2_pos = ls
|
||||
junc_pt = le
|
||||
|
||||
if k2_pos is not None:
|
||||
candidates.append((k2_pos, junc_pt))
|
||||
|
||||
if not candidates:
|
||||
return None
|
||||
|
||||
# Sortieren nach x: links (kleinstes x) zuerst, rechts (groesstes x) zuletzt
|
||||
candidates.sort(key=lambda c: c[0][0])
|
||||
return candidates
|
||||
|
||||
|
||||
def k2_point_weichen90(doc):
|
||||
"""K2 fuer Weichen 90 Grad – noch nicht implementiert."""
|
||||
return None
|
||||
def _pick_branch(candidates, branch):
|
||||
"""Waehlt linken oder rechten Zweig aus und berechnet rz."""
|
||||
if branch == "left":
|
||||
k2_pos, junc_pt = candidates[0]
|
||||
else:
|
||||
k2_pos, junc_pt = candidates[-1]
|
||||
|
||||
# x-Achse tangential zur Linie, zur Kurve zeigend
|
||||
dx = junc_pt[0] - k2_pos[0]
|
||||
dy = junc_pt[1] - k2_pos[1]
|
||||
rz = math.degrees(math.atan2(dy, dx))
|
||||
|
||||
return (k2_pos[0], k2_pos[1], 0), 0, 0, rz
|
||||
|
||||
|
||||
def k2_point_weiche_arc(doc):
|
||||
"""K2 fuer Weichen: Ende des linken Bogenzweigs."""
|
||||
candidates = _find_weiche_arc_branches(doc)
|
||||
if candidates is None:
|
||||
return None
|
||||
return _pick_branch(candidates, "left")
|
||||
|
||||
|
||||
def k3_point_weiche_arc(doc):
|
||||
"""K3 fuer Weichen: Ende des rechten Bogenzweigs.
|
||||
|
||||
Nur bei Weichen mit 2+ Boegen (Doppel-, Dreiwegeweichen etc.).
|
||||
Bei Einzelweichen (nur 1 Bogen) gibt es keinen rechten Zweig.
|
||||
"""
|
||||
candidates = _find_weiche_arc_branches(doc)
|
||||
if candidates is None or len(candidates) < 2:
|
||||
return None
|
||||
return _pick_branch(candidates, "right")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# K2/K3 fuer Weichenkoerper (keine ARCs, nur Diagonalen)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _find_weichenkoerper_diag_branches(doc):
|
||||
"""Findet die Enden der langen Diagonalen eines Weichenkoerpers.
|
||||
|
||||
Weichenkoerper haben keine Boegen, sondern Diagonalen die sich an einem
|
||||
Punkt nahe der K1-Vertikallinie treffen. K2/K3 liegen an den aeusseren
|
||||
Enden der langen Diagonalen (Laenge > 100).
|
||||
|
||||
Returns:
|
||||
Liste von (outer_pt, junction_pt) Tupeln, sortiert nach x (links zuerst),
|
||||
oder None falls keine langen Diagonalen gefunden.
|
||||
"""
|
||||
msp = doc.modelspace()
|
||||
|
||||
# K1-Position bestimmen (unterste vertikale Linie)
|
||||
vline = find_bottommost_vertical_line(doc)
|
||||
if vline is None:
|
||||
return None
|
||||
s, e = vline.dxf.start, vline.dxf.end
|
||||
k1_x = s[0]
|
||||
k1_y = min(s[1], e[1])
|
||||
|
||||
# Lange Diagonalen finden (nicht horizontal, nicht vertikal, Laenge > 100)
|
||||
candidates = []
|
||||
for ent in msp:
|
||||
if ent.dxftype() != "LINE":
|
||||
continue
|
||||
ls = (ent.dxf.start[0], ent.dxf.start[1])
|
||||
le = (ent.dxf.end[0], ent.dxf.end[1])
|
||||
dx = abs(le[0] - ls[0])
|
||||
dy = abs(le[1] - ls[1])
|
||||
if dx < 0.01 or dy < 0.01:
|
||||
continue
|
||||
ln = (dx**2 + dy**2) ** 0.5
|
||||
if ln < 100:
|
||||
continue
|
||||
|
||||
# Das Ende naeher an K1 ist die Junction, das andere ist der K2/K3-Punkt
|
||||
d_start = ((ls[0] - k1_x)**2 + (ls[1] - k1_y)**2) ** 0.5
|
||||
d_end = ((le[0] - k1_x)**2 + (le[1] - k1_y)**2) ** 0.5
|
||||
if d_start < d_end:
|
||||
candidates.append((le, ls))
|
||||
else:
|
||||
candidates.append((ls, le))
|
||||
|
||||
if not candidates:
|
||||
return None
|
||||
|
||||
# Sortieren nach x: links (kleinstes x) zuerst
|
||||
candidates.sort(key=lambda c: c[0][0])
|
||||
return candidates
|
||||
|
||||
|
||||
def k2_point_weichenkoerper(doc):
|
||||
"""K2 fuer Weichenkoerper – noch nicht implementiert."""
|
||||
return None
|
||||
"""K2 fuer Weichenkoerper: Ende der linken langen Diagonale."""
|
||||
candidates = _find_weichenkoerper_diag_branches(doc)
|
||||
if candidates is None:
|
||||
return None
|
||||
outer_pt, junc_pt = candidates[0]
|
||||
dx = junc_pt[0] - outer_pt[0]
|
||||
dy = junc_pt[1] - outer_pt[1]
|
||||
rz = math.degrees(math.atan2(dy, dx))
|
||||
return (outer_pt[0], outer_pt[1], 0), 0, 0, rz
|
||||
|
||||
|
||||
def k2_point_weichen_parallel(doc):
|
||||
"""K2 fuer Weichen Parallel – noch nicht implementiert."""
|
||||
return None
|
||||
def k3_point_weichenkoerper(doc):
|
||||
"""K3 fuer Weichenkoerper: Ende der rechten langen Diagonale.
|
||||
|
||||
|
||||
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
|
||||
Nur bei Doppel- und Dreiwegeweichenkoerpern (2+ Diagonalen).
|
||||
"""
|
||||
candidates = _find_weichenkoerper_diag_branches(doc)
|
||||
if candidates is None or len(candidates) < 2:
|
||||
return None
|
||||
outer_pt, junc_pt = candidates[-1]
|
||||
dx = junc_pt[0] - outer_pt[0]
|
||||
dy = junc_pt[1] - outer_pt[1]
|
||||
rz = math.degrees(math.atan2(dy, dx))
|
||||
return (outer_pt[0], outer_pt[1], 0), 0, 0, rz
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# K2 Schalter-Zuordnung: SWITCH_FILTERS-Key -> K2-Funktion
|
||||
# K2/K3 fuer Dreifach-, Delta-, Sternweiche (Enden der laengsten H-Linie)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _find_longest_hline(doc):
|
||||
"""Findet die laengste horizontale Linie im Modelspace."""
|
||||
best = None
|
||||
best_len = 0
|
||||
for e in doc.modelspace():
|
||||
if e.dxftype() != "LINE":
|
||||
continue
|
||||
s, end = e.dxf.start, e.dxf.end
|
||||
if abs(end[1] - s[1]) > 0.01:
|
||||
continue
|
||||
ln = abs(end[0] - s[0])
|
||||
if ln > best_len:
|
||||
best_len = ln
|
||||
best = e
|
||||
return best
|
||||
|
||||
|
||||
def k2_point_hline(doc):
|
||||
"""K2 am linken Ende der laengsten horizontalen Linie. x zeigt nach rechts."""
|
||||
hline = _find_longest_hline(doc)
|
||||
if hline is None:
|
||||
return None
|
||||
s, e = hline.dxf.start, hline.dxf.end
|
||||
lx = min(s[0], e[0])
|
||||
y = s[1]
|
||||
return (lx, y, 0), 0, 0, 0
|
||||
|
||||
|
||||
def k3_point_hline(doc):
|
||||
"""K3 am rechten Ende der laengsten horizontalen Linie. x zeigt nach links."""
|
||||
hline = _find_longest_hline(doc)
|
||||
if hline is None:
|
||||
return None
|
||||
s, e = hline.dxf.start, hline.dxf.end
|
||||
rx = max(s[0], e[0])
|
||||
y = s[1]
|
||||
return (rx, y, 0), 0, 0, 180
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# K2/K3 Schalter-Zuordnung: SWITCH_FILTERS-Key -> Funktion
|
||||
# K2 = linker Zweig, K3 = rechter Zweig (nur bei 2+ Boegen/Diagonalen)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
K2_FUNCS = {
|
||||
"boegen": k2_point_bogen,
|
||||
"weichen45": k2_point_weichen45,
|
||||
"weichen90": k2_point_weichen90,
|
||||
"weichen45": k2_point_weiche_arc,
|
||||
"weichen90": k2_point_weiche_arc,
|
||||
"weichenkoerper": k2_point_weichenkoerper,
|
||||
"weichen_parallel": k2_point_weichen_parallel,
|
||||
"sternweiche": k2_point_sternweiche,
|
||||
"delta": k2_point_delta,
|
||||
"dreifachweiche": k2_point_dreifachweiche,
|
||||
"weichen_parallel": k2_point_weiche_arc,
|
||||
"sternweiche": k2_point_hline,
|
||||
"delta": k2_point_hline,
|
||||
"dreifachweiche": k2_point_hline,
|
||||
}
|
||||
|
||||
K3_FUNCS = {
|
||||
"weichen45": k3_point_weiche_arc,
|
||||
"weichen90": k3_point_weiche_arc,
|
||||
"weichenkoerper": k3_point_weichenkoerper,
|
||||
"weichen_parallel": k3_point_weiche_arc,
|
||||
"sternweiche": k3_point_hline,
|
||||
"delta": k3_point_hline,
|
||||
"dreifachweiche": k3_point_hline,
|
||||
}
|
||||
|
||||
# K4: oberes Ende der K1-Linie. Kein K4 bei: Boegen, Doppelweiche,
|
||||
# Dreifachweiche, Deltaweiche (inkl. Weichenkoerper Doppel).
|
||||
K4_FUNCS = {
|
||||
"weichen45": k4_point_weiche,
|
||||
"weichen90": k4_point_weiche,
|
||||
"weichenkoerper": k4_point_weiche,
|
||||
"weichen_parallel": k4_point_weiche,
|
||||
"sternweiche": k4_point_weiche,
|
||||
}
|
||||
|
||||
_K4_EXCLUDE_TYPES = ("Doppelweiche", "Dreifachweiche", "Deltaweiche")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Existenz-Pruefung und Duplikat-Bereinigung
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _check_and_clean_ks(msp, k_name, sivasnr, force=False):
|
||||
"""Prueft ob ein Kx bereits existiert und bereinigt Duplikate.
|
||||
|
||||
- Mehrfach vorhandene Kx: alle bis auf das letzte entfernen (immer).
|
||||
- Genau ein Kx vorhanden und kein --force: skip (return False).
|
||||
- Genau ein Kx vorhanden und --force: entfernen (return True).
|
||||
- Kein Kx vorhanden: return True (neu erzeugen).
|
||||
|
||||
Returns:
|
||||
True = Kx soll (neu) erzeugt werden.
|
||||
False = Kx existiert bereits, skip.
|
||||
"""
|
||||
existing = [e for e in msp if e.dxftype() == "INSERT" and e.dxf.name == k_name]
|
||||
|
||||
if len(existing) > 1:
|
||||
# Duplikate: alle bis auf das letzte entfernen
|
||||
for e in existing[:-1]:
|
||||
msp.delete_entity(e)
|
||||
print(f" {sivasnr}: {len(existing)-1} Duplikat(e) von {k_name} entfernt.")
|
||||
existing = existing[-1:]
|
||||
|
||||
if len(existing) == 1:
|
||||
if force:
|
||||
msp.delete_entity(existing[0])
|
||||
return True
|
||||
else:
|
||||
print(f" {sivasnr}: skipping {k_name} (bereits vorhanden)")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# --k1set
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def process_k1set(data_dir, results_dir, number=None):
|
||||
def process_k1set(data_dir, results_dir, number=None, force=False):
|
||||
"""Setzt K1-Block an alle Boegen und Weichen."""
|
||||
sources = load_omniflo_data(data_dir)
|
||||
omniflo_dir = os.path.join(data_dir, "omniflo")
|
||||
@@ -431,12 +737,10 @@ def process_k1set(data_dir, results_dir, number=None):
|
||||
continue
|
||||
|
||||
doc = ezdxf.readfile(dxf_path)
|
||||
|
||||
# Bestehende K1-Referenzen entfernen
|
||||
msp = doc.modelspace()
|
||||
for entity in list(msp):
|
||||
if entity.dxftype() == "INSERT" and entity.dxf.name == "K1":
|
||||
msp.delete_entity(entity)
|
||||
|
||||
if not _check_and_clean_ks(msp, "K1", sivasnr, force):
|
||||
continue
|
||||
|
||||
if is_bog:
|
||||
result = k1_point_bogen(doc)
|
||||
@@ -448,26 +752,25 @@ def process_k1set(data_dir, results_dir, number=None):
|
||||
continue
|
||||
|
||||
point, rx, ry, rz = result
|
||||
msp = doc.modelspace()
|
||||
insert_ks(msp, "K1", point, rx, ry, rz)
|
||||
|
||||
out_path = os.path.join(results_dir, f"{sivasnr}.dxf")
|
||||
doc.saveas(out_path)
|
||||
print(f"{sivasnr}: K1 at ({point[0]:.2f},{point[1]:.2f},{point[2]:.2f}) "
|
||||
print(f" {sivasnr}: K1 at ({point[0]:.2f},{point[1]:.2f},{point[2]:.2f}) "
|
||||
f"rx={rx} ry={ry} rz={rz} [{profil}]")
|
||||
|
||||
print(f"\nErgebnisse in: {results_dir}")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# --k2set
|
||||
# --k2set / --k3set
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def process_k2set(data_dir, results_dir, number=None):
|
||||
"""Setzt K2-Block an alle Boegen und Weichen (ueber SWITCH_FILTERS)."""
|
||||
def _process_kset(k_name, funcs, data_dir, results_dir, number=None, force=False):
|
||||
"""Generische Verarbeitung fuer K2/K3: iteriert ueber SWITCH_FILTERS."""
|
||||
omniflo_dir = os.path.join(data_dir, "omniflo")
|
||||
|
||||
for key, k2_func in K2_FUNCS.items():
|
||||
for key, k_func in funcs.items():
|
||||
label, json_file, filter_func = SWITCH_FILTERS[key]
|
||||
|
||||
json_path = os.path.join(data_dir, "json", json_file)
|
||||
@@ -482,7 +785,7 @@ def process_k2set(data_dir, results_dir, number=None):
|
||||
if not filtered:
|
||||
continue
|
||||
|
||||
print(f"=== K2 setzen: {label} ===")
|
||||
print(f"=== {k_name} setzen: {label} ===")
|
||||
for item in filtered:
|
||||
sivasnr = str(item["Sivasnr"])
|
||||
dxf_path = os.path.join(results_dir, f"{sivasnr}.dxf")
|
||||
@@ -494,23 +797,82 @@ def process_k2set(data_dir, results_dir, number=None):
|
||||
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)
|
||||
if not _check_and_clean_ks(msp, k_name, sivasnr, force):
|
||||
continue
|
||||
|
||||
result = k2_func(doc)
|
||||
result = k_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)
|
||||
insert_ks(msp, k_name, 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}) "
|
||||
print(f" {sivasnr}: {k_name} 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}")
|
||||
|
||||
|
||||
def process_k2set(data_dir, results_dir, number=None, force=False):
|
||||
"""Setzt K2-Block (linker Bogenzweig) an alle Boegen und Weichen."""
|
||||
_process_kset("K2", K2_FUNCS, data_dir, results_dir, number, force)
|
||||
|
||||
|
||||
def process_k3set(data_dir, results_dir, number=None, force=False):
|
||||
"""Setzt K3-Block (rechter Bogenzweig) an Weichen mit 2+ Boegen."""
|
||||
_process_kset("K3", K3_FUNCS, data_dir, results_dir, number, force)
|
||||
|
||||
|
||||
def process_k4set(data_dir, results_dir, number=None, force=False):
|
||||
"""Setzt K4-Block (oberes K1-Linienende) an Weichen ohne Doppel/Dreifach/Delta."""
|
||||
omniflo_dir = os.path.join(data_dir, "omniflo")
|
||||
|
||||
for key, k4_func in K4_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)
|
||||
|
||||
# SWITCH_FILTERS-Filter + K4-Ausschluss (Doppelweiche etc.)
|
||||
filtered = [item for item in all_items
|
||||
if filter_func(item)
|
||||
and item.get("WeichenTyp", "") not in _K4_EXCLUDE_TYPES]
|
||||
if number:
|
||||
filtered = [item for item in filtered if str(item["Sivasnr"]) == str(number)]
|
||||
if not filtered:
|
||||
continue
|
||||
|
||||
print(f"=== K4 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()
|
||||
|
||||
if not _check_and_clean_ks(msp, "K4", sivasnr, force):
|
||||
continue
|
||||
|
||||
result = k4_func(doc)
|
||||
if result is None:
|
||||
continue
|
||||
|
||||
point, rx, ry, rz = result
|
||||
insert_ks(msp, "K4", point, rx, ry, rz)
|
||||
|
||||
out_path = os.path.join(results_dir, f"{sivasnr}.dxf")
|
||||
doc.saveas(out_path)
|
||||
print(f" {sivasnr}: K4 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}")
|
||||
@@ -619,7 +981,15 @@ 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)")
|
||||
help="K2-Block setzen (linker Bogenzweig)")
|
||||
parser.add_argument("--k3set", action="store_true",
|
||||
help="K3-Block setzen (rechter Bogenzweig, nur Doppel-/Dreiwegeweichen)")
|
||||
parser.add_argument("--k4set", action="store_true",
|
||||
help="K4-Block setzen (oberes K1-Linienende, nicht Doppel/Dreifach/Delta)")
|
||||
parser.add_argument("--set-all", action="store_true",
|
||||
help="Alle Koordinatensysteme (K1-K4) in einem Durchgang setzen")
|
||||
parser.add_argument("--force", action="store_true",
|
||||
help="Bestehende Kx ueberschreiben (sonst skip)")
|
||||
parser.add_argument("--show-omniflo", action="store_true",
|
||||
help="Uebersichts-DXF mit K-Positionen erzeugen")
|
||||
parser.add_argument("--test", action="store_true",
|
||||
@@ -632,7 +1002,7 @@ def main():
|
||||
print("FEHLER: --number muss eine 9-stellige Ganzzahl sein.")
|
||||
sys.exit(1)
|
||||
|
||||
if not args.k1set and not args.k2set and not args.show_omniflo and not args.test:
|
||||
if not args.k1set and not args.k2set and not args.k3set and not args.k4set and not args.set_all and not args.show_omniflo and not args.test:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
@@ -653,11 +1023,23 @@ def main():
|
||||
if args.test:
|
||||
run_test(results_dir)
|
||||
|
||||
if args.set_all:
|
||||
process_k1set(data_dir, results_dir, args.number, args.force)
|
||||
process_k2set(data_dir, results_dir, args.number, args.force)
|
||||
process_k3set(data_dir, results_dir, args.number, args.force)
|
||||
process_k4set(data_dir, results_dir, args.number, args.force)
|
||||
|
||||
if args.k1set:
|
||||
process_k1set(data_dir, results_dir, args.number)
|
||||
process_k1set(data_dir, results_dir, args.number, args.force)
|
||||
|
||||
if args.k2set:
|
||||
process_k2set(data_dir, results_dir, args.number)
|
||||
process_k2set(data_dir, results_dir, args.number, args.force)
|
||||
|
||||
if args.k3set:
|
||||
process_k3set(data_dir, results_dir, args.number, args.force)
|
||||
|
||||
if args.k4set:
|
||||
process_k4set(data_dir, results_dir, args.number, args.force)
|
||||
|
||||
if args.show_omniflo:
|
||||
print("=== Koordinaten Uebersicht ===")
|
||||
|
||||
Reference in New Issue
Block a user