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:
2026-05-11 15:56:20 +02:00
parent 241d24c1d2
commit c677f7482e
2 changed files with 254 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
@echo off
REM ================================================================
REM Setzt Einfuegepunkte fuer Omniflo DXF-Dateien
REM ================================================================
call "%~dp0setenv.bat"
python "%DXFM_LIB%\set_einfuegepkt.py" %*
+246
View File
@@ -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()