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,8 @@
|
|||||||
|
@echo off
|
||||||
|
REM ================================================================
|
||||||
|
REM Setzt Einfuegepunkte fuer Omniflo DXF-Dateien
|
||||||
|
REM ================================================================
|
||||||
|
|
||||||
|
call "%~dp0setenv.bat"
|
||||||
|
|
||||||
|
python "%DXFM_LIB%\set_einfuegepkt.py" %*
|
||||||
@@ -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