neue Python Funktion zum setzen des Einfügepunktes an die korrekte Stelle für Oflo Bögen und Weichen 45/90 Grad
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
"""
|
||||
Setzt den Einfuegepunkt ($INSBASE) von Omniflo DXF-Dateien.
|
||||
|
||||
Mit --boegen: Einfuegepunkt auf den Schnittpunkt der Tangenten
|
||||
am Anfangs- und Endpunkt der Bogenkurve.
|
||||
|
||||
Mit --weichen45 / --weichen90: Einfuegepunkt auf den Schnittpunkt
|
||||
der laengsten vertikalen Linie und des Endpunktes der Bogenkurve.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
import sys
|
||||
|
||||
import ezdxf
|
||||
|
||||
|
||||
def find_arc(doc):
|
||||
"""Findet die erste ARC-Entity im Modelspace."""
|
||||
msp = doc.modelspace()
|
||||
for entity in msp:
|
||||
if entity.dxftype() == "ARC":
|
||||
return entity
|
||||
return None
|
||||
|
||||
|
||||
def tangent_intersection(arc):
|
||||
"""Berechnet den Schnittpunkt der Tangenten am Start- und Endpunkt des Bogens.
|
||||
Bei 180-Grad-Boegen wird der Mittelpunkt zwischen Start und Ende verwendet.
|
||||
"""
|
||||
cx, cy, _ = arc.dxf.center
|
||||
r = arc.dxf.radius
|
||||
a_start = math.radians(arc.dxf.start_angle)
|
||||
a_end = math.radians(arc.dxf.end_angle)
|
||||
|
||||
# Start- und Endpunkt
|
||||
p1x = cx + r * math.cos(a_start)
|
||||
p1y = cy + r * math.sin(a_start)
|
||||
p2x = cx + r * math.cos(a_end)
|
||||
p2y = cy + r * math.sin(a_end)
|
||||
|
||||
# Tangentenrichtungen (senkrecht zum Radius)
|
||||
d1x = -math.sin(a_start)
|
||||
d1y = math.cos(a_start)
|
||||
d2x = -math.sin(a_end)
|
||||
d2y = math.cos(a_end)
|
||||
|
||||
# Determinante
|
||||
det = d1x * (-d2y) - (-d2x) * d1y
|
||||
|
||||
if abs(det) < 1e-9:
|
||||
# Tangenten parallel (z.B. 180-Grad-Bogen) -> Mittelpunkt
|
||||
return (p1x + p2x) / 2, (p1y + p2y) / 2
|
||||
|
||||
dx = p2x - p1x
|
||||
dy = p2y - p1y
|
||||
t = (-dx * d2y + dy * d2x) / det
|
||||
|
||||
ix = p1x + t * d1x
|
||||
iy = p1y + t * d1y
|
||||
return ix, iy
|
||||
|
||||
|
||||
def find_longest_vertical_line(doc):
|
||||
"""Findet die laengste vertikale Linie im Modelspace und gibt deren x-Koordinate zurueck."""
|
||||
msp = doc.modelspace()
|
||||
longest = None
|
||||
longest_len = 0
|
||||
for entity in msp:
|
||||
if entity.dxftype() != "LINE":
|
||||
continue
|
||||
start = entity.dxf.start
|
||||
end = entity.dxf.end
|
||||
dx = abs(end[0] - start[0])
|
||||
if dx > 0.01:
|
||||
continue
|
||||
length = abs(end[1] - start[1])
|
||||
if length > longest_len:
|
||||
longest_len = length
|
||||
longest = entity
|
||||
return longest
|
||||
|
||||
|
||||
def arc_endpoint(arc):
|
||||
"""Gibt den Endpunkt (end_angle) des Bogens zurueck."""
|
||||
cx, cy, _ = arc.dxf.center
|
||||
r = arc.dxf.radius
|
||||
a_end = math.radians(arc.dxf.end_angle)
|
||||
return cx + r * math.cos(a_end), cy + r * math.sin(a_end)
|
||||
|
||||
|
||||
def weichen_insertion_point(doc):
|
||||
"""Berechnet den Einfuegepunkt fuer eine Weiche:
|
||||
Schnittpunkt der laengsten vertikalen Linie mit einer Horizontalen
|
||||
durch den Endpunkt der Bogenkurve.
|
||||
"""
|
||||
vline = find_longest_vertical_line(doc)
|
||||
if vline is None:
|
||||
return None
|
||||
arc = find_arc(doc)
|
||||
if arc is None:
|
||||
return None
|
||||
vx = vline.dxf.start[0]
|
||||
_, ey = arc_endpoint(arc)
|
||||
return vx, ey
|
||||
|
||||
|
||||
def process_weichen(data_dir, json_path, results_dir, kurven_winkel):
|
||||
"""Verarbeitet Weichen-DXF-Dateien fuer den angegebenen KurvenWinkel."""
|
||||
with open(json_path, "r", encoding="utf-8") as f:
|
||||
weichen = json.load(f)
|
||||
|
||||
omniflo_dir = os.path.join(data_dir, "omniflo")
|
||||
filtered = [w for w in weichen if w["KurvenWinkel"] == kurven_winkel]
|
||||
|
||||
if not filtered:
|
||||
print(f"Keine Weichen mit KurvenWinkel={kurven_winkel} gefunden.")
|
||||
return
|
||||
|
||||
for weiche in filtered:
|
||||
sivasnr = str(weiche["Sivasnr"])
|
||||
dxf_path = os.path.join(omniflo_dir, f"{sivasnr}.dxf")
|
||||
|
||||
if not os.path.exists(dxf_path):
|
||||
print(f"WARNUNG: {dxf_path} nicht gefunden, ueberspringe.")
|
||||
continue
|
||||
|
||||
doc = ezdxf.readfile(dxf_path)
|
||||
result = weichen_insertion_point(doc)
|
||||
|
||||
if result is None:
|
||||
print(f"WARNUNG: Kein ARC oder keine vertikale Linie in {sivasnr}.dxf, ueberspringe.")
|
||||
continue
|
||||
|
||||
ix, iy = result
|
||||
old_base = doc.header.get("$INSBASE", (0, 0, 0))
|
||||
doc.header["$INSBASE"] = (ix, iy, 0)
|
||||
|
||||
out_path = os.path.join(results_dir, f"{sivasnr}.dxf")
|
||||
doc.saveas(out_path)
|
||||
|
||||
print(
|
||||
f"{sivasnr}: INSBASE ({old_base[0]:.2f}, {old_base[1]:.2f}) "
|
||||
f"-> ({ix:.2f}, {iy:.2f}) [{weiche['ProfilTyp']}]"
|
||||
)
|
||||
|
||||
print(f"\nErgebnisse in: {results_dir}")
|
||||
|
||||
|
||||
def process_boegen(data_dir, json_path, results_dir):
|
||||
"""Verarbeitet alle Boegen-DXF-Dateien."""
|
||||
with open(json_path, "r", encoding="utf-8") as f:
|
||||
boegen = json.load(f)
|
||||
|
||||
omniflo_dir = os.path.join(data_dir, "omniflo")
|
||||
|
||||
for bogen in boegen:
|
||||
sivasnr = str(bogen["Sivasnr"])
|
||||
dxf_path = os.path.join(omniflo_dir, f"{sivasnr}.dxf")
|
||||
|
||||
if not os.path.exists(dxf_path):
|
||||
print(f"WARNUNG: {dxf_path} nicht gefunden, ueberspringe.")
|
||||
continue
|
||||
|
||||
doc = ezdxf.readfile(dxf_path)
|
||||
arc = find_arc(doc)
|
||||
|
||||
if arc is None:
|
||||
print(f"WARNUNG: Kein ARC in {sivasnr}.dxf gefunden, ueberspringe.")
|
||||
continue
|
||||
|
||||
ix, iy = tangent_intersection(arc)
|
||||
|
||||
old_base = doc.header.get("$INSBASE", (0, 0, 0))
|
||||
doc.header["$INSBASE"] = (ix, iy, 0)
|
||||
|
||||
out_path = os.path.join(results_dir, f"{sivasnr}.dxf")
|
||||
doc.saveas(out_path)
|
||||
|
||||
print(
|
||||
f"{sivasnr}: INSBASE ({old_base[0]:.2f}, {old_base[1]:.2f}) "
|
||||
f"-> ({ix:.2f}, {iy:.2f}) [{bogen['ProfilTyp']}]"
|
||||
)
|
||||
|
||||
print(f"\nErgebnisse in: {results_dir}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Setzt Einfuegepunkte fuer Omniflo DXF-Dateien"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--boegen",
|
||||
action="store_true",
|
||||
help="Einfuegepunkt auf Tangentenschnittpunkt der Bogenkurve setzen",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--weichen45",
|
||||
action="store_true",
|
||||
help="Einfuegepunkt fuer 45-Grad-Weichen setzen",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--weichen90",
|
||||
action="store_true",
|
||||
help="Einfuegepunkt fuer 90-Grad-Weichen setzen",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.boegen and not args.weichen45 and not args.weichen90:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
data_dir = os.environ.get("DXFM_DATA")
|
||||
results_dir = os.environ.get("DXFM_RESULTS")
|
||||
|
||||
if not data_dir or not results_dir:
|
||||
print("FEHLER: Umgebungsvariablen DXFM_DATA und DXFM_RESULTS muessen gesetzt sein.")
|
||||
print("Bitte zuerst setenv.bat ausfuehren.")
|
||||
sys.exit(1)
|
||||
|
||||
os.makedirs(results_dir, exist_ok=True)
|
||||
|
||||
if args.boegen:
|
||||
json_path = os.path.join(data_dir, "json", "omniflo_boegen.json")
|
||||
if not os.path.exists(json_path):
|
||||
print(f"FEHLER: {json_path} nicht gefunden.")
|
||||
sys.exit(1)
|
||||
process_boegen(data_dir, json_path, results_dir)
|
||||
|
||||
if args.weichen45 or args.weichen90:
|
||||
json_path = os.path.join(data_dir, "json", "omniflo_weichen.json")
|
||||
if not os.path.exists(json_path):
|
||||
print(f"FEHLER: {json_path} nicht gefunden.")
|
||||
sys.exit(1)
|
||||
if args.weichen45:
|
||||
print("=== Weichen 45 Grad ===")
|
||||
process_weichen(data_dir, json_path, results_dir, 45)
|
||||
if args.weichen90:
|
||||
print("=== Weichen 90 Grad ===")
|
||||
process_weichen(data_dir, json_path, results_dir, 90)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user