669 lines
22 KiB
Python
669 lines
22 KiB
Python
"""
|
||
Setzt Koordinatensystem-Bloecke (K1, K2, ...) in Omniflo DXF-Dateien.
|
||
|
||
Jeder Block enthaelt drei Linien vom Ursprung:
|
||
- rot(1) X-Achse, Laenge 1
|
||
- gruen(3) Y-Achse, Laenge 2
|
||
- blau(5) Z-Achse, Laenge 3
|
||
|
||
Schalter:
|
||
--k1set K1 an alle Boegen und Weichen setzen.
|
||
Boegen: Beginn der obersten horizontalen Linie,
|
||
x rechts, y oben, z aus Zeichenebene.
|
||
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).
|
||
--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.
|
||
"""
|
||
|
||
import argparse
|
||
import json
|
||
import math
|
||
import os
|
||
import sys
|
||
|
||
import ezdxf
|
||
from ezdxf.math import Matrix44
|
||
|
||
from utils import (
|
||
ROW_GROUPS, TEXT_HEIGHT, TEXT_MARGIN, CROSS_SIZE, ROW_LABEL_WIDTH,
|
||
SWITCH_FILTERS,
|
||
load_omniflo_data, build_row_layout, import_element_as_block,
|
||
draw_cross, is_bogen,
|
||
)
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Block-Definition
|
||
# ---------------------------------------------------------------------------
|
||
|
||
KS_LINES = [
|
||
(1, 1.0, 0.0, 0.0), # rot, X-Achse, Laenge 1
|
||
(3, 0.0, 2.0, 0.0), # gruen, Y-Achse, Laenge 2
|
||
(5, 0.0, 0.0, 3.0), # blau, Z-Achse, Laenge 3
|
||
]
|
||
|
||
|
||
def _ensure_block(doc, block_name):
|
||
"""Erzeugt den Block falls er noch nicht existiert."""
|
||
if block_name not in doc.blocks:
|
||
blk = doc.blocks.new(name=block_name)
|
||
for color, dx, dy, dz in KS_LINES:
|
||
blk.add_line(
|
||
start=(0, 0, 0),
|
||
end=(dx, dy, dz),
|
||
dxfattribs={"color": color},
|
||
)
|
||
return block_name
|
||
|
||
|
||
def _ensure_layer(doc, layer_name="_KOORDINATENSYSTEME"):
|
||
"""Stellt sicher, dass der Layer existiert."""
|
||
if layer_name not in doc.layers:
|
||
doc.layers.add(layer_name)
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# insert / read / verify
|
||
# ---------------------------------------------------------------------------
|
||
|
||
def insert_ks(msp, name, point, rx=0, ry=0, rz=0):
|
||
"""
|
||
Erzeugt ein benanntes Koordinatensystem als Block-Referenz.
|
||
|
||
Args:
|
||
msp: Modelspace oder Block des Ziel-Dokuments.
|
||
name: Block-Name (z.B. "K1", "K2", "K3", "K4").
|
||
point: Einfuegepunkt als (x, y, z) Tupel.
|
||
rx: Rotation um X-Achse in Grad.
|
||
ry: Rotation um Y-Achse in Grad.
|
||
rz: Rotation um Z-Achse in Grad.
|
||
|
||
Returns:
|
||
Das erzeugte INSERT-Entity.
|
||
"""
|
||
doc = msp.doc
|
||
_ensure_layer(doc)
|
||
_ensure_block(doc, name)
|
||
|
||
insert = msp.add_blockref(
|
||
name,
|
||
insert=point,
|
||
dxfattribs={"layer": "_KOORDINATENSYSTEME"},
|
||
)
|
||
|
||
m = Matrix44.chain(
|
||
Matrix44.translate(-point[0], -point[1], -point[2]),
|
||
Matrix44.x_rotate(math.radians(rx)),
|
||
Matrix44.y_rotate(math.radians(ry)),
|
||
Matrix44.z_rotate(math.radians(rz)),
|
||
Matrix44.translate(point[0], point[1], point[2]),
|
||
)
|
||
insert.transform(m)
|
||
|
||
return insert
|
||
|
||
|
||
def read_ks(doc, name):
|
||
"""
|
||
Liest ein Koordinatensystem aus einer DXF-Datei zurueck.
|
||
|
||
Returns:
|
||
Dict mit 'name', 'point', 'rx', 'ry', 'rz' oder None.
|
||
"""
|
||
msp = doc.modelspace()
|
||
for entity in msp:
|
||
if entity.dxftype() == "INSERT" and entity.dxf.name == name:
|
||
lines = [e for e in entity.virtual_entities() if e.dxftype() == "LINE"]
|
||
if len(lines) != 3:
|
||
return None
|
||
|
||
point = (lines[0].dxf.start[0], lines[0].dxf.start[1], lines[0].dxf.start[2])
|
||
|
||
axes = {}
|
||
for line in lines:
|
||
end = line.dxf.end
|
||
dx = end[0] - point[0]
|
||
dy = end[1] - point[1]
|
||
dz = end[2] - point[2]
|
||
length = (dx**2 + dy**2 + dz**2) ** 0.5
|
||
axes[line.dxf.color] = (dx / length, dy / length, dz / length)
|
||
|
||
x_axis = axes.get(1, (1, 0, 0))
|
||
y_axis = axes.get(3, (0, 1, 0))
|
||
z_axis = axes.get(5, (0, 0, 1))
|
||
|
||
ry = math.asin(max(-1, min(1, -x_axis[2])))
|
||
cos_ry = math.cos(ry)
|
||
|
||
if abs(cos_ry) > 1e-6:
|
||
rx = math.atan2(y_axis[2] / cos_ry, z_axis[2] / cos_ry)
|
||
rz = math.atan2(x_axis[1] / cos_ry, x_axis[0] / cos_ry)
|
||
else:
|
||
rz = 0
|
||
rx = math.atan2(-z_axis[0], y_axis[0])
|
||
|
||
return {
|
||
"name": name,
|
||
"point": point,
|
||
"rx": math.degrees(rx),
|
||
"ry": math.degrees(ry),
|
||
"rz": math.degrees(rz),
|
||
}
|
||
return None
|
||
|
||
|
||
def verify_ks(dxf_path, expected):
|
||
"""Liest KS-Bloecke und vergleicht mit Erwartungswerten (Toleranz 0.01)."""
|
||
doc = ezdxf.readfile(dxf_path)
|
||
all_ok = True
|
||
tol = 0.01
|
||
|
||
for exp in expected:
|
||
result = read_ks(doc, exp["name"])
|
||
if result is None:
|
||
print(f"FEHLER: Block '{exp['name']}' nicht gefunden")
|
||
all_ok = False
|
||
continue
|
||
|
||
errors = []
|
||
for i, axis in enumerate(("x", "y", "z")):
|
||
if abs(result["point"][i] - exp["point"][i]) > tol:
|
||
errors.append(f"{axis}={result['point'][i]:.3f} (erwartet {exp['point'][i]:.3f})")
|
||
|
||
for angle in ("rx", "ry", "rz"):
|
||
diff = abs(result[angle] - exp[angle])
|
||
if diff > 360 - tol:
|
||
diff = abs(diff - 360)
|
||
if diff > tol:
|
||
errors.append(f"{angle}={result[angle]:.2f} (erwartet {exp[angle]:.2f})")
|
||
|
||
if errors:
|
||
print(f"FEHLER {exp['name']}: {', '.join(errors)}")
|
||
all_ok = False
|
||
else:
|
||
print(f"OK {exp['name']}: point=({result['point'][0]:.2f},{result['point'][1]:.2f},{result['point'][2]:.2f}) "
|
||
f"rx={result['rx']:.2f} ry={result['ry']:.2f} rz={result['rz']:.2f}")
|
||
|
||
return all_ok
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# K1-Positionsbestimmung
|
||
# ---------------------------------------------------------------------------
|
||
|
||
def find_topmost_horizontal_line(doc):
|
||
"""Findet die am weitesten oben liegende horizontale Linie."""
|
||
best = None
|
||
best_y = -float('inf')
|
||
for entity in doc.modelspace():
|
||
if entity.dxftype() != "LINE":
|
||
continue
|
||
s, e = entity.dxf.start, entity.dxf.end
|
||
if abs(e[1] - s[1]) > 0.01:
|
||
continue
|
||
if s[1] > best_y:
|
||
best_y = s[1]
|
||
best = entity
|
||
return best
|
||
|
||
|
||
def find_bottommost_vertical_line(doc):
|
||
"""Findet die am weitesten unten liegende rein vertikale Linie."""
|
||
best = None
|
||
best_min_y = float('inf')
|
||
for entity in doc.modelspace():
|
||
if entity.dxftype() != "LINE":
|
||
continue
|
||
s, e = entity.dxf.start, entity.dxf.end
|
||
if abs(e[0] - s[0]) > 0.01:
|
||
continue
|
||
min_y = min(s[1], e[1])
|
||
if min_y < best_min_y:
|
||
best_min_y = min_y
|
||
best = entity
|
||
return best
|
||
|
||
|
||
def k1_point_bogen(doc):
|
||
"""K1-Position fuer Boegen: Beginn der obersten horizontalen Linie.
|
||
Rotation: x rechts, y oben, z aus Zeichenebene (Standard, rz=0).
|
||
"""
|
||
hline = find_topmost_horizontal_line(doc)
|
||
if hline is None:
|
||
return None
|
||
s, e = hline.dxf.start, hline.dxf.end
|
||
left_x = min(s[0], e[0])
|
||
y = s[1]
|
||
return (left_x, y, 0), 0, 0, 0
|
||
|
||
|
||
def k1_point_weiche(doc):
|
||
"""K1-Position fuer Weichen: Beginn der untersten vertikalen Linie.
|
||
Rotation: 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]
|
||
bottom_y = min(s[1], e[1])
|
||
return (x, bottom_y, 0), 0, 0, 90
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# K2-Positionsbestimmung (nur Boegen)
|
||
# ---------------------------------------------------------------------------
|
||
|
||
def k2_point_bogen(doc):
|
||
"""K2-Position fuer Boegen: anderes Ende der Kette (Gerade-Bogen-Gerade).
|
||
|
||
Sucht den Bogen, bestimmt welches Ende zur K1-Seite (oberste H-Linie)
|
||
gehoert, findet die laengste Linie am anderen Bogenende und setzt K2
|
||
an deren aeusseres Ende.
|
||
|
||
x-Achse tangential zur Linie (Richtung weg vom Bogen),
|
||
y senkrecht dazu, z aus Zeichenebene (wie K1).
|
||
Sonderfall 180-Grad-Bogen: x nach rechts (rz=0).
|
||
"""
|
||
msp = doc.modelspace()
|
||
|
||
# Bogen finden
|
||
arc = None
|
||
for e in msp:
|
||
if e.dxftype() == "ARC":
|
||
arc = e
|
||
break
|
||
if arc is None:
|
||
return None
|
||
|
||
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 = oberste horizontale Linie
|
||
hline = find_topmost_horizontal_line(doc)
|
||
if hline is None:
|
||
return None
|
||
h_y = hline.dxf.start[1]
|
||
|
||
# Welches Bogenende liegt an der K1-H-Linie?
|
||
tol = 1.0
|
||
if abs(arc_end[1] - h_y) < tol:
|
||
k2_junction = arc_start
|
||
else:
|
||
k2_junction = arc_end
|
||
|
||
# Laengste Linie am K2-Bogenende suchen
|
||
best_line_len = 0
|
||
k2_pos = None
|
||
junc_pt = None
|
||
for e in msp:
|
||
if e.dxftype() != "LINE":
|
||
continue
|
||
s = (e.dxf.start[0], e.dxf.start[1])
|
||
end = (e.dxf.end[0], e.dxf.end[1])
|
||
ds = ((s[0] - k2_junction[0])**2 + (s[1] - k2_junction[1])**2) ** 0.5
|
||
de = ((end[0] - k2_junction[0])**2 + (end[1] - k2_junction[1])**2) ** 0.5
|
||
if ds > tol and de > tol:
|
||
continue
|
||
ln = ((end[0] - s[0])**2 + (end[1] - s[1])**2) ** 0.5
|
||
if ln > best_line_len:
|
||
best_line_len = ln
|
||
if ds < tol:
|
||
k2_pos = end
|
||
junc_pt = s
|
||
else:
|
||
k2_pos = s
|
||
junc_pt = end
|
||
|
||
if k2_pos is None:
|
||
return None
|
||
|
||
# Bogenspanne berechnen
|
||
span = (ea - sa) % 360
|
||
|
||
# Tangenten-Richtung: von K2 zur Junction (zur Bogenmitte)
|
||
dx = junc_pt[0] - k2_pos[0]
|
||
dy = junc_pt[1] - k2_pos[1]
|
||
rz = math.degrees(math.atan2(dy, dx))
|
||
|
||
# 180-Grad-Sonderfall: x nach rechts, wie K1
|
||
if abs(span - 180) < 1:
|
||
rz = 0
|
||
|
||
return (k2_pos[0], k2_pos[1], 0), 0, 0, rz
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# K2-Positionsbestimmung Weichen (Dummy-Funktionen)
|
||
# ---------------------------------------------------------------------------
|
||
|
||
def k2_point_weichen45(doc):
|
||
"""K2 fuer Weichen 45 Grad – noch nicht implementiert."""
|
||
return None
|
||
|
||
|
||
def k2_point_weichen90(doc):
|
||
"""K2 fuer Weichen 90 Grad – noch nicht implementiert."""
|
||
return None
|
||
|
||
|
||
def k2_point_weichenkoerper(doc):
|
||
"""K2 fuer Weichenkoerper – noch nicht implementiert."""
|
||
return None
|
||
|
||
|
||
def k2_point_weichen_parallel(doc):
|
||
"""K2 fuer Weichen Parallel – noch nicht implementiert."""
|
||
return None
|
||
|
||
|
||
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
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# K2 Schalter-Zuordnung: SWITCH_FILTERS-Key -> K2-Funktion
|
||
# ---------------------------------------------------------------------------
|
||
|
||
K2_FUNCS = {
|
||
"boegen": k2_point_bogen,
|
||
"weichen45": k2_point_weichen45,
|
||
"weichen90": k2_point_weichen90,
|
||
"weichenkoerper": k2_point_weichenkoerper,
|
||
"weichen_parallel": k2_point_weichen_parallel,
|
||
"sternweiche": k2_point_sternweiche,
|
||
"delta": k2_point_delta,
|
||
"dreifachweiche": k2_point_dreifachweiche,
|
||
}
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# --k1set
|
||
# ---------------------------------------------------------------------------
|
||
|
||
def process_k1set(data_dir, results_dir, number=None):
|
||
"""Setzt K1-Block an alle Boegen und Weichen."""
|
||
sources = load_omniflo_data(data_dir)
|
||
omniflo_dir = os.path.join(data_dir, "omniflo")
|
||
|
||
all_items = []
|
||
for b in sources["boegen"]:
|
||
all_items.append((str(b["Sivasnr"]), b["ProfilTyp"], True))
|
||
for w in sources["weichen"]:
|
||
all_items.append((str(w["Sivasnr"]), w["ProfilTyp"], False))
|
||
|
||
if number:
|
||
all_items = [(s, p, ib) for s, p, ib in all_items if s == str(number)]
|
||
|
||
if not all_items:
|
||
print("Keine Elemente gefunden.")
|
||
return
|
||
|
||
print("=== K1 setzen ===")
|
||
for sivasnr, profil, is_bog in all_items:
|
||
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)
|
||
|
||
# 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 is_bog:
|
||
result = k1_point_bogen(doc)
|
||
else:
|
||
result = k1_point_weiche(doc)
|
||
|
||
if result is None:
|
||
print(f"WARNUNG: K1 in {sivasnr}.dxf nicht bestimmbar, ueberspringe.")
|
||
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}) "
|
||
f"rx={rx} ry={ry} rz={rz} [{profil}]")
|
||
|
||
print(f"\nErgebnisse in: {results_dir}")
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# --k2set
|
||
# ---------------------------------------------------------------------------
|
||
|
||
def process_k2set(data_dir, results_dir, number=None):
|
||
"""Setzt K2-Block an alle Boegen und Weichen (ueber SWITCH_FILTERS)."""
|
||
omniflo_dir = os.path.join(data_dir, "omniflo")
|
||
|
||
for key, k2_func in K2_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)
|
||
|
||
filtered = [item for item in all_items if filter_func(item)]
|
||
if number:
|
||
filtered = [item for item in filtered if str(item["Sivasnr"]) == str(number)]
|
||
if not filtered:
|
||
continue
|
||
|
||
print(f"=== K2 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()
|
||
|
||
# Bestehende K2-Referenzen entfernen
|
||
for entity in list(msp):
|
||
if entity.dxftype() == "INSERT" and entity.dxf.name == "K2":
|
||
msp.delete_entity(entity)
|
||
|
||
result = k2_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)
|
||
|
||
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}) "
|
||
f"rx={rx} ry={ry} rz={rz:.1f} [{item['ProfilTyp']}]")
|
||
|
||
print(f"\nErgebnisse in: {results_dir}")
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# --show-omniflo
|
||
# ---------------------------------------------------------------------------
|
||
|
||
# Farben: K1=rot(1), K2=orange(30), K3=gelb(2), K4=gruen(3)
|
||
K_COLORS = {"K1": 1, "K2": 30, "K3": 2, "K4": 3}
|
||
|
||
|
||
def show_omniflo(data_dir, results_dir):
|
||
"""Uebersichts-DXF mit K-Positionen als farbige Kreuze."""
|
||
sources, rows = build_row_layout(data_dir, results_dir)
|
||
|
||
target = ezdxf.new(dxfversion='R2010')
|
||
target_msp = target.modelspace()
|
||
target.layers.add('ANNOTATION', color=7)
|
||
target.layers.add('K_POINTS', color=1)
|
||
target.layers.add('ROW_LABEL', color=3)
|
||
|
||
block_counter = 0
|
||
|
||
for row in rows:
|
||
label_y = row['cursor_y'] + row['max_height'] / 2
|
||
target_msp.add_mtext(
|
||
row['label'],
|
||
dxfattribs={
|
||
'layer': 'ROW_LABEL',
|
||
'char_height': TEXT_HEIGHT * 1.2,
|
||
}
|
||
).set_location(insert=(-ROW_LABEL_WIDTH, label_y))
|
||
|
||
for elem in row['elements']:
|
||
block_name = f"BLK_{block_counter}"
|
||
block_counter += 1
|
||
|
||
import_element_as_block(elem['source'], target, block_name)
|
||
target_msp.add_blockref(block_name,
|
||
insert=(elem['offset_x'], elem['offset_y']))
|
||
|
||
# K-Positionen aus dem Quell-DXF auslesen und anzeigen
|
||
for k_name, k_color in K_COLORS.items():
|
||
k_data = read_ks(elem['source'], k_name)
|
||
if k_data is None:
|
||
continue
|
||
kx = k_data['point'][0] + elem['offset_x']
|
||
ky = k_data['point'][1] + elem['offset_y']
|
||
draw_cross(target_msp, kx, ky, CROSS_SIZE, k_color, 'K_POINTS')
|
||
|
||
text_x = elem['offset_x'] + elem['extmin'][0]
|
||
text_y = row['cursor_y'] + elem['height'] + TEXT_MARGIN
|
||
target_msp.add_mtext(
|
||
elem['sivasnr'],
|
||
dxfattribs={
|
||
'layer': 'ANNOTATION',
|
||
'char_height': TEXT_HEIGHT,
|
||
}
|
||
).set_location(insert=(text_x, text_y))
|
||
|
||
out_path = os.path.join(results_dir, "koords_uebersicht.dxf")
|
||
target.saveas(out_path)
|
||
print(f"Uebersicht gespeichert: {out_path}")
|
||
print(f" {block_counter} Elemente in {len(rows)} Reihen")
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# --test
|
||
# ---------------------------------------------------------------------------
|
||
|
||
def run_test(results_dir):
|
||
"""Erzeugt Testdatei mit 4 KOS und verifiziert Ruecklesen."""
|
||
doc = ezdxf.new(dxfversion="R2010")
|
||
msp = doc.modelspace()
|
||
|
||
test_cases = [
|
||
{"name": "K1", "point": (0, 0, 0), "rx": 0, "ry": 0, "rz": 0},
|
||
{"name": "K2", "point": (10, 0, 0), "rx": 0, "ry": 0, "rz": 90},
|
||
{"name": "K3", "point": (20, 0, 0), "rx": 0, "ry": 45, "rz": 0},
|
||
{"name": "K4", "point": (30, 0, 0), "rx": 30, "ry": 45, "rz": 60},
|
||
]
|
||
|
||
for tc in test_cases:
|
||
insert_ks(msp, tc["name"], tc["point"], tc["rx"], tc["ry"], tc["rz"])
|
||
|
||
out_path = os.path.join(results_dir, "ks_test.dxf")
|
||
doc.saveas(out_path)
|
||
print(f"Testdatei gespeichert: {out_path}\n")
|
||
|
||
print("Verifikation:")
|
||
ok = verify_ks(out_path, test_cases)
|
||
print(f"\nErgebnis: {'ALLE OK' if ok else 'FEHLER GEFUNDEN'}")
|
||
return ok
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# main
|
||
# ---------------------------------------------------------------------------
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser(
|
||
description="Setzt Koordinatensystem-Bloecke in Omniflo DXF-Dateien"
|
||
)
|
||
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)")
|
||
parser.add_argument("--show-omniflo", action="store_true",
|
||
help="Uebersichts-DXF mit K-Positionen erzeugen")
|
||
parser.add_argument("--test", action="store_true",
|
||
help="Testdatei mit 4 KOS erzeugen und verifizieren")
|
||
parser.add_argument("--number", type=int,
|
||
help="Nur diese 9-stellige Sivasnr verarbeiten")
|
||
args = parser.parse_args()
|
||
|
||
if args.number and len(str(args.number)) != 9:
|
||
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:
|
||
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:
|
||
if args.test:
|
||
results_dir = results_dir or "results"
|
||
os.makedirs(results_dir, exist_ok=True)
|
||
run_test(results_dir)
|
||
return
|
||
print("FEHLER: Umgebungsvariablen DXFM_DATA und DXFM_RESULTS muessen gesetzt sein.")
|
||
sys.exit(1)
|
||
|
||
os.makedirs(results_dir, exist_ok=True)
|
||
|
||
if args.test:
|
||
run_test(results_dir)
|
||
|
||
if args.k1set:
|
||
process_k1set(data_dir, results_dir, args.number)
|
||
|
||
if args.k2set:
|
||
process_k2set(data_dir, results_dir, args.number)
|
||
|
||
if args.show_omniflo:
|
||
print("=== Koordinaten Uebersicht ===")
|
||
show_omniflo(data_dir, results_dir)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|