Schalter --show_symbol_frames dazugemacht.
This commit is contained in:
+89
-29
@@ -14,9 +14,11 @@ import json
|
||||
from pathlib import Path
|
||||
import ezdxf
|
||||
|
||||
from symbol_frames import draw_symbol_frames
|
||||
|
||||
# Umgebungsvariablen
|
||||
PROJECT = os.getenv('PROJECT', Path(__file__).parent.parent.absolute())
|
||||
PROJECT_TEST = os.getenv('PROJECT_TEST', os.path.join(PROJECT, 'testdata'))
|
||||
PROJECT_WORK = os.getenv('PROJECT_WORK', os.path.join(PROJECT, 'work'))
|
||||
PROJECT_CFG = os.getenv('PROJECT_CFG', os.path.join(PROJECT, 'cfg'))
|
||||
|
||||
|
||||
@@ -284,13 +286,38 @@ class TestDataGenerator:
|
||||
def save(self, output_dir=None):
|
||||
"""Speichert das DXF-Dokument"""
|
||||
if output_dir is None:
|
||||
output_dir = PROJECT_TEST
|
||||
output_dir = PROJECT_WORK
|
||||
|
||||
output_path = os.path.join(output_dir, self.filename)
|
||||
self.doc.saveas(output_path)
|
||||
print(f"Test-DXF erstellt: {output_path}")
|
||||
return output_path
|
||||
|
||||
def draw_frames_for_generated_symbols(self):
|
||||
"""
|
||||
Zeichnet Rahmen um alle generierten Symbole zur Visualisierung.
|
||||
Konvertiert das interne Format in das von draw_symbol_frames erwartete Format.
|
||||
"""
|
||||
if not self.generated_symbols:
|
||||
print("Keine generierten Symbole zum Zeichnen von Rahmen gefunden")
|
||||
return 0
|
||||
|
||||
# Konvertiere das interne Format in das erwartete Format
|
||||
symbols_for_frames = []
|
||||
for sym in self.generated_symbols:
|
||||
# generated_symbols enthält 'x', 'y' (Einfügepunkt = linke untere Ecke bei left_bottom_corner)
|
||||
# draw_symbol_frames erwartet Position = linke untere Ecke des Symbols
|
||||
# Wir können die gespeicherten Koordinaten direkt verwenden
|
||||
|
||||
symbols_for_frames.append({
|
||||
'position': (sym['x'], sym['y']), # Position = linke untere Ecke
|
||||
'attributes': {'IO': sym['io']}, # IO-Wert für Breitenberechnung
|
||||
'layer': sym.get('layer', 'ILS_MOTOR')
|
||||
})
|
||||
|
||||
# Zeichne die Rahmen
|
||||
return draw_symbol_frames(self.doc, self.msp, symbols_for_frames)
|
||||
|
||||
def load_block_from_file(self, source_file, block_name):
|
||||
"""
|
||||
Lädt einen Block aus einer anderen DXF-Datei
|
||||
@@ -608,15 +635,15 @@ class TestDataGenerator:
|
||||
|
||||
return offset_map.get(insert_point, (0, 0)) # Default: left_top_corner
|
||||
|
||||
def _generate_ma_group(self, group, ma_defaults, width_per_char, fixed_height, spacing_factor, y_offsets_list, insert_point='left_top_corner'):
|
||||
def _generate_ma_group(self, group, ma_defaults, symbol_width, symbol_height, spacing_factor, y_offsets_list, insert_point='left_top_corner'):
|
||||
"""
|
||||
Generiert eine Gruppe von MA-Symbolen
|
||||
|
||||
Args:
|
||||
group: Dict mit Gruppen-Config (name, count, layout_type, base_x, base_y, spacing)
|
||||
ma_defaults: Dict mit MA-Default-Attributen
|
||||
width_per_char: Breite pro Zeichen
|
||||
fixed_height: Fixe Symbol-Höhe
|
||||
symbol_width: Feste Breite des Symbols
|
||||
symbol_height: Feste Höhe des Symbols
|
||||
spacing_factor: Spacing-Faktor zwischen Symbolen
|
||||
y_offsets_list: Liste von Y-Offsets für horizontal_offset Layout
|
||||
insert_point: Einfügepunkt des Blocks (z.B. "left_top_corner", "center")
|
||||
@@ -630,9 +657,6 @@ class TestDataGenerator:
|
||||
# Extrahiere IO-Pattern aus Name (z.B. "MA-1@@_top" -> "MA-1@@")
|
||||
io_pattern = name.split('_')[0]
|
||||
|
||||
# Berechne Symbol-Ausdehnung
|
||||
symbol_width = len(io_pattern) * width_per_char
|
||||
|
||||
# Berechne Spacing
|
||||
if layout_type in ['horizontal', 'horizontal_offset']:
|
||||
actual_spacing = symbol_width * spacing_factor
|
||||
@@ -644,7 +668,7 @@ class TestDataGenerator:
|
||||
layer = ma_defaults.get('layer', 'ILS_MOTOR')
|
||||
|
||||
# Berechne Offset basierend auf Einfügepunkt
|
||||
offset_x, offset_y = self._calculate_insert_offset(insert_point, symbol_width, fixed_height)
|
||||
offset_x, offset_y = self._calculate_insert_offset(insert_point, symbol_width, symbol_height)
|
||||
|
||||
# Generiere Symbole basierend auf Layout-Typ
|
||||
for i in range(count):
|
||||
@@ -669,7 +693,7 @@ class TestDataGenerator:
|
||||
# (da der io-Block bei (0,0) startet und nach oben geht)
|
||||
blockref = self.msp.add_blockref(
|
||||
'io',
|
||||
insert=(left_top_x, left_top_y - fixed_height),
|
||||
insert=(left_top_x, left_top_y - symbol_height),
|
||||
dxfattribs={'layer': layer}
|
||||
)
|
||||
|
||||
@@ -681,10 +705,12 @@ class TestDataGenerator:
|
||||
blockref.add_auto_attribs(attrib_values)
|
||||
|
||||
# Speichere Symbol-Position für spätere Validierung
|
||||
# Speichere immer die linke obere Ecke
|
||||
# Speichere den tatsächlichen Einfügepunkt (linke untere Ecke bei left_bottom_corner)
|
||||
actual_insert_x = left_top_x
|
||||
actual_insert_y = left_top_y - symbol_height
|
||||
self.generated_symbols.append({
|
||||
'x': left_top_x,
|
||||
'y': left_top_y,
|
||||
'x': actual_insert_x,
|
||||
'y': actual_insert_y,
|
||||
'io': io_pattern,
|
||||
'group_name': name,
|
||||
'layer': layer
|
||||
@@ -701,10 +727,10 @@ class TestDataGenerator:
|
||||
ma_defaults = self.config.get('ma_defaults', {})
|
||||
general = self.config.get('general', {})
|
||||
|
||||
# Hole Dimensions aus Config
|
||||
# Hole Dimensions aus Config (feste Werte)
|
||||
dimensions = ma_defaults.get('dimensions', {})
|
||||
width_per_char = dimensions.get('width_per_char', 201.49)
|
||||
fixed_height = dimensions.get('fixed_height', 380.94)
|
||||
symbol_width = dimensions.get('width', 1210)
|
||||
symbol_height = dimensions.get('height', 381)
|
||||
|
||||
# Hole Layout-Einstellungen
|
||||
layout = general.get('layout', {})
|
||||
@@ -717,7 +743,7 @@ class TestDataGenerator:
|
||||
|
||||
# Generiere MA-Gruppen aus Config
|
||||
for group in scene.get('ma_groups', []):
|
||||
self._generate_ma_group(group, ma_defaults, width_per_char, fixed_height, spacing_factor, y_offsets_list, insert_point)
|
||||
self._generate_ma_group(group, ma_defaults, symbol_width, symbol_height, spacing_factor, y_offsets_list, insert_point)
|
||||
|
||||
# Generiere Renamer-Rahmen aus Config
|
||||
for frame_config in scene.get('renaming_frames', []):
|
||||
@@ -916,10 +942,15 @@ class TestDataGenerator:
|
||||
print("Prüfe ob alle generierten Symbole in Renamer-Frames liegen")
|
||||
print("="*60)
|
||||
|
||||
# Hole Symbol-Dimensionen aus Config
|
||||
# Hole Symbol-Dimensionen aus Config (feste Werte)
|
||||
dimensions = self.config.get('ma_defaults', {}).get('dimensions', {})
|
||||
width_per_char = dimensions.get('width_per_char', 201.49)
|
||||
fixed_height = dimensions.get('fixed_height', 380.94)
|
||||
ma_symbol_width = dimensions.get('width', 1210)
|
||||
ma_symbol_height = dimensions.get('height', 381)
|
||||
|
||||
# Hole Multi-Frame Dimensionen
|
||||
multi_dimensions = self.config.get('general', {}).get('multi_frame', {}).get('dimensions', {})
|
||||
multi_symbol_width = multi_dimensions.get('width', 1410)
|
||||
multi_symbol_height = multi_dimensions.get('height', 381)
|
||||
|
||||
# Sammle alle Frame-Boundaries
|
||||
frame_boundaries = []
|
||||
@@ -969,15 +1000,20 @@ class TestDataGenerator:
|
||||
# Prüfe jedes generierte Symbol
|
||||
symbols_outside = []
|
||||
for symbol in self.generated_symbols:
|
||||
# Berechne Symbol-Dimensionen
|
||||
# Berechne Symbol-Dimensionen basierend auf IO-Text Länge
|
||||
io_text = symbol['io']
|
||||
symbol_width = len(io_text) * width_per_char
|
||||
symbol_height = fixed_height
|
||||
char_count = len(io_text)
|
||||
if char_count >= 7:
|
||||
symbol_width = multi_symbol_width # Multi-Frame (BG/MB/POT)
|
||||
symbol_height = multi_symbol_height
|
||||
else:
|
||||
symbol_width = ma_symbol_width # MA-Frame
|
||||
symbol_height = ma_symbol_height
|
||||
|
||||
# Berechne Mittelpunkt des Symbols
|
||||
# symbol['x'], symbol['y'] ist die linke obere Ecke
|
||||
# symbol['x'], symbol['y'] ist die linke untere Ecke
|
||||
symbol_center_x = symbol['x'] + symbol_width / 2
|
||||
symbol_center_y = symbol['y'] - symbol_height / 2
|
||||
symbol_center_y = symbol['y'] + symbol_height / 2
|
||||
symbol_point = (symbol_center_x, symbol_center_y)
|
||||
|
||||
# Radius für Kreis-Test
|
||||
@@ -1041,7 +1077,8 @@ class TestDataGenerator:
|
||||
symbol_with_type['symbol_radius'] = symbol_radius
|
||||
symbol_with_type['shift_x'] = best_shift[0]
|
||||
symbol_with_type['shift_y'] = best_shift[1]
|
||||
symbol_with_type['closest_frame'] = closest_frame.get('name', 'UNKNOWN') if closest_frame else 'UNKNOWN'
|
||||
symbol_with_type['closest_frame_name'] = closest_frame.get('name', 'UNKNOWN') if closest_frame else 'UNKNOWN'
|
||||
symbol_with_type['closest_frame_dict'] = closest_frame # Speichere das gesamte Dictionary
|
||||
symbols_outside.append(symbol_with_type)
|
||||
|
||||
# Gib Warnungen aus und zeichne Fehlerkreise
|
||||
@@ -1059,18 +1096,31 @@ class TestDataGenerator:
|
||||
else:
|
||||
shift_x = symbol.get('shift_x', 0)
|
||||
shift_y = symbol.get('shift_y', 0)
|
||||
closest_frame = symbol.get('closest_frame', 'UNKNOWN')
|
||||
closest_frame_name = symbol.get('closest_frame_name', 'UNKNOWN')
|
||||
|
||||
if shift_x != 0 or shift_y != 0:
|
||||
print(f"{base_msg}: "
|
||||
f"Symbol liegt nicht innerhalb des Renamer-Rahmens '{closest_frame}'. "
|
||||
f"Symbol liegt nicht innerhalb des Renamer-Rahmens '{closest_frame_name}'. "
|
||||
f"Verschieben Sie um dx={shift_x:.1f}, dy={shift_y:.1f}")
|
||||
else:
|
||||
print(f"{base_msg}: "
|
||||
f"Symbol liegt nicht innerhalb des Renamer-Rahmens")
|
||||
|
||||
# Zeichne Fehlerkreis um das Symbol
|
||||
self._draw_error_circle(symbol['x'], symbol['y'], symbol['symbol_radius'])
|
||||
# Berechne Symbol-Zentrum (symbol['x'], symbol['y'] = linke untere Ecke)
|
||||
io_text = symbol['io']
|
||||
char_count = len(io_text)
|
||||
if char_count >= 7:
|
||||
sym_width = multi_symbol_width
|
||||
sym_height = multi_symbol_height
|
||||
else:
|
||||
sym_width = ma_symbol_width
|
||||
sym_height = ma_symbol_height
|
||||
|
||||
symbol_center_x = symbol['x'] + sym_width / 2
|
||||
symbol_center_y = symbol['y'] + sym_height / 2
|
||||
|
||||
self._draw_error_circle(symbol_center_x, symbol_center_y, symbol['symbol_radius'])
|
||||
else:
|
||||
print(f"\nOK: Alle {len(self.generated_symbols)} generierten Symbole erfüllen die Frame-Kriterien")
|
||||
|
||||
@@ -1186,6 +1236,12 @@ def main():
|
||||
help=f'JSON-Konfigurationsdatei (Standard: {default_config})'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--show_symbol_frames',
|
||||
action='store_true',
|
||||
help='Zeichne Rahmen um jedes Symbol, um die Grenze des Symbols zu visualisieren'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Bestimme Filename: entweder angegeben oder aus scene ableiten
|
||||
@@ -1202,6 +1258,10 @@ def main():
|
||||
generator = TestDataGenerator(filename, args.scene, config_file=args.config)
|
||||
|
||||
if generator.generate():
|
||||
# Zeichne Symbol-Rahmen wenn gewünscht
|
||||
if args.show_symbol_frames:
|
||||
generator.draw_frames_for_generated_symbols()
|
||||
|
||||
generator.save(args.output_dir)
|
||||
return 0
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user