231 lines
7.7 KiB
Python
231 lines
7.7 KiB
Python
"""
|
|
Gemeinsame Hilfsfunktionen fuer DXF-Makros.
|
|
|
|
Enthaelt die Reihen-Gruppierung fuer Omniflo-Elemente und Layout-Funktionen
|
|
fuer die Uebersichts-DXF Erzeugung.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
|
|
import ezdxf
|
|
from ezdxf import bbox as ezdxf_bbox
|
|
from ezdxf.addons.importer import Importer
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Reihen-Gruppen: (Label, Quell-Key, Filter-Funktion)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
ROW_GROUPS = [
|
|
("Boegen 22.5", "boegen",
|
|
lambda b: b["KurvenWinkel"] == 22.5),
|
|
("Boegen 45", "boegen",
|
|
lambda b: b["KurvenWinkel"] == 45),
|
|
("Boegen 67.5", "boegen",
|
|
lambda b: b["KurvenWinkel"] == 67.5),
|
|
("Boegen 90", "boegen",
|
|
lambda b: b["KurvenWinkel"] == 90),
|
|
("Boegen 180", "boegen",
|
|
lambda b: b["KurvenWinkel"] == 180),
|
|
("Weichenkoerper Einzel", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Einzelweiche" and w["KurvenWinkel"] == 22.5),
|
|
("Weichenkoerper Doppel", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Doppelweiche" and w["KurvenWinkel"] == 22.5),
|
|
("Weichenkoerper Dreiwege", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Dreiwegeweiche" and w["KurvenWinkel"] == 22.5),
|
|
("Einzelweiche 45", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Einzelweiche" and w["KurvenWinkel"] == 45),
|
|
("Einzelweiche 90", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Einzelweiche" and w["KurvenWinkel"] == 90),
|
|
("Einzelweiche Parallel", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Einzelweiche" and w["KurvenWinkel"] == 0),
|
|
("Doppelweiche 45", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Doppelweiche" and w["KurvenWinkel"] == 45),
|
|
("Doppelweiche 90", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Doppelweiche" and w["KurvenWinkel"] == 90),
|
|
("Doppelweiche Parallel", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Doppelweiche" and w["KurvenWinkel"] == 0),
|
|
("Dreiwegeweiche 45", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Dreiwegeweiche" and w["KurvenWinkel"] == 45),
|
|
("Dreiwegeweiche 90", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Dreiwegeweiche" and w["KurvenWinkel"] == 90),
|
|
("Dreiwegeweiche Parallel", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Dreiwegeweiche" and w["KurvenWinkel"] == 0),
|
|
("Dreifachweiche", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Dreifachweiche"),
|
|
("Deltaweiche", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Deltaweiche"),
|
|
("Sternweiche", "weichen",
|
|
lambda w: w["WeichenTyp"] == "Sternweiche"),
|
|
]
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Schalter-Filter: (Label, JSON-Datei, Filter-Funktion)
|
|
# Gemeinsam genutzt von set_einfuegepkt.py und set_koords.py.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
SWITCH_FILTERS = {
|
|
"boegen": (
|
|
"Boegen",
|
|
"omniflo_boegen.json",
|
|
lambda item: True,
|
|
),
|
|
"weichen45": (
|
|
"Weichen 45 Grad",
|
|
"omniflo_weichen.json",
|
|
lambda item: item["KurvenWinkel"] == 45
|
|
and item["WeichenTyp"] not in ("Dreifachweiche", "Deltaweiche"),
|
|
),
|
|
"weichen90": (
|
|
"Weichen 90 Grad",
|
|
"omniflo_weichen.json",
|
|
lambda item: item["KurvenWinkel"] == 90
|
|
and item["WeichenTyp"] not in ("Dreifachweiche", "Deltaweiche"),
|
|
),
|
|
"weichenkoerper": (
|
|
"Weichenkoerper",
|
|
"omniflo_weichen.json",
|
|
lambda item: item["KurvenWinkel"] == 22.5,
|
|
),
|
|
"weichen_parallel": (
|
|
"Weichen Parallel",
|
|
"omniflo_weichen.json",
|
|
lambda item: item["KurvenWinkel"] == 0 and item["WeichenTyp"] != "Sternweiche",
|
|
),
|
|
"sternweiche": (
|
|
"Sternweiche",
|
|
"omniflo_weichen.json",
|
|
lambda item: item["WeichenTyp"] == "Sternweiche",
|
|
),
|
|
"delta": (
|
|
"Deltaweichen",
|
|
"omniflo_weichen.json",
|
|
lambda item: item["WeichenTyp"] == "Deltaweiche",
|
|
),
|
|
"dreifachweiche": (
|
|
"Dreifachweichen",
|
|
"omniflo_weichen.json",
|
|
lambda item: item["WeichenTyp"] == "Dreifachweiche",
|
|
),
|
|
}
|
|
|
|
|
|
PADDING_X = 200
|
|
PADDING_Y = 400
|
|
TEXT_HEIGHT = 30
|
|
CROSS_SIZE = 40
|
|
TEXT_MARGIN = 20
|
|
ROW_LABEL_WIDTH = 600
|
|
|
|
|
|
def load_omniflo_data(data_dir):
|
|
"""Laedt Boegen- und Weichen-JSON und gibt ein Dict {boegen, weichen} zurueck."""
|
|
boegen_path = os.path.join(data_dir, "json", "omniflo_boegen.json")
|
|
weichen_path = os.path.join(data_dir, "json", "omniflo_weichen.json")
|
|
|
|
with open(boegen_path, "r", encoding="utf-8") as f:
|
|
boegen_data = json.load(f)
|
|
with open(weichen_path, "r", encoding="utf-8") as f:
|
|
weichen_data = json.load(f)
|
|
|
|
return {"boegen": boegen_data, "weichen": weichen_data}
|
|
|
|
|
|
def is_bogen(sivasnr, sources):
|
|
"""Prueft ob eine Sivasnr ein Bogen ist."""
|
|
return any(str(b["Sivasnr"]) == str(sivasnr) for b in sources["boegen"])
|
|
|
|
|
|
def build_row_layout(data_dir, results_dir):
|
|
"""
|
|
Berechnet das Layout aller Omniflo-Elemente in Reihen.
|
|
|
|
Returns:
|
|
(sources, rows) wobei rows eine Liste von Dicts ist:
|
|
[{
|
|
'label': str,
|
|
'source_key': str,
|
|
'elements': [{'sivasnr', 'source', 'extmin', 'extmax',
|
|
'width', 'height', 'offset_x', 'offset_y'}],
|
|
'cursor_y': float,
|
|
'max_height': float,
|
|
}]
|
|
"""
|
|
sources = load_omniflo_data(data_dir)
|
|
omniflo_dir = os.path.join(data_dir, "omniflo")
|
|
|
|
rows = []
|
|
cursor_y = 0.0
|
|
|
|
for label, source_key, filter_func in ROW_GROUPS:
|
|
items = [item for item in sources[source_key] if filter_func(item)]
|
|
if not items:
|
|
continue
|
|
|
|
row_elements = []
|
|
for item in items:
|
|
sivasnr = str(item["Sivasnr"])
|
|
dxf_path_result = os.path.join(results_dir, f"{sivasnr}.dxf")
|
|
dxf_path_orig = os.path.join(omniflo_dir, f"{sivasnr}.dxf")
|
|
dxf_path = dxf_path_result if os.path.exists(dxf_path_result) else dxf_path_orig
|
|
|
|
if not os.path.exists(dxf_path):
|
|
continue
|
|
|
|
source_doc = ezdxf.readfile(dxf_path)
|
|
bb = ezdxf_bbox.extents(source_doc.modelspace())
|
|
if not bb.has_data:
|
|
continue
|
|
|
|
row_elements.append({
|
|
'sivasnr': sivasnr,
|
|
'source': source_doc,
|
|
'extmin': bb.extmin,
|
|
'extmax': bb.extmax,
|
|
'width': bb.extmax[0] - bb.extmin[0],
|
|
'height': bb.extmax[1] - bb.extmin[1],
|
|
})
|
|
|
|
if not row_elements:
|
|
continue
|
|
|
|
max_height = max(e['height'] for e in row_elements)
|
|
|
|
cursor_x = 0.0
|
|
for elem in row_elements:
|
|
elem['offset_x'] = cursor_x - elem['extmin'][0]
|
|
elem['offset_y'] = cursor_y - elem['extmin'][1]
|
|
cursor_x += elem['width'] + PADDING_X
|
|
|
|
rows.append({
|
|
'label': label,
|
|
'source_key': source_key,
|
|
'elements': row_elements,
|
|
'cursor_y': cursor_y,
|
|
'max_height': max_height,
|
|
})
|
|
|
|
cursor_y -= max_height + TEXT_HEIGHT + TEXT_MARGIN * 2 + PADDING_Y
|
|
|
|
return sources, rows
|
|
|
|
|
|
def import_element_as_block(source_doc, target_doc, block_name):
|
|
"""Importiert alle Modelspace-Entities eines Quell-Dokuments als Block."""
|
|
importer = Importer(source_doc, target_doc)
|
|
importer.import_tables()
|
|
blk = target_doc.blocks.new(name=block_name)
|
|
for entity in source_doc.modelspace():
|
|
importer.import_entity(entity, blk)
|
|
importer.finalize()
|
|
return block_name
|
|
|
|
|
|
def draw_cross(msp, x, y, size, color, layer):
|
|
"""Zeichnet ein Kreuz an (x, y)."""
|
|
msp.add_line((x - size, y), (x + size, y),
|
|
dxfattribs={'layer': layer, 'color': color})
|
|
msp.add_line((x, y - size), (x, y + size),
|
|
dxfattribs={'layer': layer, 'color': color})
|