Schalter --show_symbol_frames dazugemacht.

This commit is contained in:
2026-01-29 16:45:48 +01:00
parent c4ef6e28f4
commit ae82736960
3 changed files with 442 additions and 34 deletions
+295
View File
@@ -0,0 +1,295 @@
import ezdxf
from ezdxf import colors
from ezdxf.enums import TextEntityAlignment
import math
def create_grounding_symbol(filename="erdung.dxf"):
"""Erstellt ein Schutzerde-Symbol nach DIN EN 60617"""
doc = ezdxf.new('R2010')
msp = doc.modelspace()
# Block erstellen
block = doc.blocks.new(name='ERDUNG')
# Mittelpunkt (relativ zum Block)
cx, cy = 0, 0
# Vertikale Linie (Erdungsleiter)
block.add_line((cx, cy + 60), (cx, cy - 20))
# Drei horizontale Linien (Erdsymbol)
# Obere Linie (längste)
block.add_line((cx - 40, cy - 20), (cx + 40, cy - 20))
# Mittlere Linie
block.add_line((cx - 25, cy - 35), (cx + 25, cy - 35))
# Untere Linie (kürzeste)
block.add_line((cx - 15, cy - 50), (cx + 15, cy - 50))
# Beschriftung PE
block.add_text("PE", dxfattribs={
'height': 12,
'insert': (cx, cy + 70),
'halign': TextEntityAlignment.CENTER
})
# Attribute definieren
block.add_attdef(tag='REALE_POSITION', insert=(cx, cy - 70), dxfattribs={
'height': 8,
'prompt': 'Reale Position:',
'default': 'x',
'halign': TextEntityAlignment.CENTER,
'invisible': 1 # Unsichtbar, nur für Daten
})
block.add_attdef(tag='NAME', insert=(cx, cy - 85), dxfattribs={
'height': 10,
'prompt': 'Name:',
'default': '',
'halign': TextEntityAlignment.CENTER
})
block.add_attdef(tag='KENNZEICHNUNG', insert=(cx, cy - 100), dxfattribs={
'height': 8,
'prompt': 'Kennzeichnung:',
'default': '=A01+UH00-X01',
'halign': TextEntityAlignment.CENTER,
'invisible': 1 # Unsichtbar, nur für Daten
})
# Block-Instanz einfügen
msp.add_blockref('ERDUNG', (125, 125))
doc.saveas(filename)
print(f"{filename} erstellt")
def create_switchboard_symbol(filename="schaltschrank.dxf"):
"""Erstellt ein schematisches Schaltschrank-Symbol für Lagepläne"""
doc = ezdxf.new('R2010')
msp = doc.modelspace()
# Block erstellen
block = doc.blocks.new(name='SCHALTSCHRANK')
# Mittelpunkt (relativ zum Block)
cx, cy = 0, 0
# Rechteck für Schaltschrank (60x80mm)
width, height = 60, 80
x1, y1 = cx - width/2, cy - height/2
x2, y2 = cx + width/2, cy + height/2
# Außenrahmen
block.add_lwpolyline([
(x1, y1), (x2, y1), (x2, y2), (x1, y2), (x1, y1)
], dxfattribs={'closed': True})
# Innere Unterteilung (Fächer)
block.add_line((x1, cy - 15), (x2, cy - 15))
block.add_line((x1, cy + 15), (x2, cy + 15))
# Türgriff-Symbol (vertikale Linie links)
block.add_line((x1 + 5, cy - 25), (x1 + 5, cy + 25))
# Beschriftung
block.add_text("Schaltschrank", dxfattribs={
'height': 10,
'insert': (cx, y2 + 15),
'halign': TextEntityAlignment.CENTER
})
# Attribute definieren
block.add_attdef(tag='REALE_POSITION', insert=(cx, y1 - 15), dxfattribs={
'height': 8,
'prompt': 'Reale Position:',
'default': 'x',
'halign': TextEntityAlignment.CENTER,
'invisible': 1
})
block.add_attdef(tag='NAME', insert=(cx, y1 - 30), dxfattribs={
'height': 10,
'prompt': 'Name:',
'default': '',
'halign': TextEntityAlignment.CENTER
})
block.add_attdef(tag='KENNZEICHNUNG', insert=(cx, y1 - 45), dxfattribs={
'height': 8,
'prompt': 'Kennzeichnung:',
'default': '=A01+UH00-X01',
'halign': TextEntityAlignment.CENTER,
'invisible': 1
})
# Block-Instanz einfügen
msp.add_blockref('SCHALTSCHRANK', (125, 125))
doc.saveas(filename)
print(f"{filename} erstellt")
def create_subdistribution_symbol(filename="unterverteiler.dxf"):
"""Erstellt ein Unterverteiler-Symbol (ähnlich Schaltschrank, kleiner)"""
doc = ezdxf.new('R2010')
msp = doc.modelspace()
# Block erstellen
block = doc.blocks.new(name='UNTERVERTEILER')
# Mittelpunkt (relativ zum Block)
cx, cy = 0, 0
# Rechteck für Unterverteiler (45x60mm - kleiner als Schaltschrank)
width, height = 45, 60
x1, y1 = cx - width/2, cy - height/2
x2, y2 = cx + width/2, cy + height/2
# Außenrahmen
block.add_lwpolyline([
(x1, y1), (x2, y1), (x2, y2), (x1, y2), (x1, y1)
], dxfattribs={'closed': True})
# Innere Unterteilung (weniger Fächer)
block.add_line((x1, cy), (x2, cy))
# Türgriff-Symbol
block.add_line((x1 + 4, cy - 15), (x1 + 4, cy + 15))
# Beschriftung UV (Unterverteiler)
block.add_text("UV", dxfattribs={
'height': 12,
'insert': (cx, cy),
'halign': TextEntityAlignment.CENTER,
'valign': TextEntityAlignment.MIDDLE
})
# Zusätzliche Beschriftung
block.add_text("Unterverteiler", dxfattribs={
'height': 10,
'insert': (cx, y2 + 15),
'halign': TextEntityAlignment.CENTER
})
# Attribute definieren
block.add_attdef(tag='REALE_POSITION', insert=(cx, y1 - 15), dxfattribs={
'height': 8,
'prompt': 'Reale Position:',
'default': 'x',
'halign': TextEntityAlignment.CENTER,
'invisible': 1
})
block.add_attdef(tag='NAME', insert=(cx, y1 - 30), dxfattribs={
'height': 10,
'prompt': 'Name:',
'default': '',
'halign': TextEntityAlignment.CENTER
})
block.add_attdef(tag='KENNZEICHNUNG', insert=(cx, y1 - 45), dxfattribs={
'height': 8,
'prompt': 'Kennzeichnung:',
'default': '=A01+UH00-X01',
'halign': TextEntityAlignment.CENTER,
'invisible': 1
})
# Block-Instanz einfügen
msp.add_blockref('UNTERVERTEILER', (125, 125))
doc.saveas(filename)
print(f"{filename} erstellt")
def create_motor_symbol(filename="motor.dxf"):
"""Erstellt ein allgemeines Motor-Symbol (M im Kreis) nach DIN EN 60617"""
doc = ezdxf.new('R2010')
msp = doc.modelspace()
# Block erstellen
block = doc.blocks.new(name='MOTOR')
# Mittelpunkt (relativ zum Block)
cx, cy = 0, 0
radius = 30
# Kreis
block.add_circle((cx, cy), radius)
# Buchstabe "M" in der Mitte
block.add_text("M", dxfattribs={
'height': 25,
'insert': (cx, cy),
'halign': TextEntityAlignment.CENTER,
'valign': TextEntityAlignment.MIDDLE
})
# Anschlussklemmen (drei Linien für Drehstrom - optional)
# Oben
block.add_line((cx, cy + radius), (cx, cy + radius + 20))
# Links unten
angle1 = math.radians(210)
x1 = cx + radius * math.cos(angle1)
y1 = cy + radius * math.sin(angle1)
block.add_line((x1, y1), (x1 - 15, y1 - 10))
# Rechts unten
angle2 = math.radians(330)
x2 = cx + radius * math.cos(angle2)
y2 = cy + radius * math.sin(angle2)
block.add_line((x2, y2), (x2 + 15, y2 - 10))
# Beschriftung
block.add_text("Motor", dxfattribs={
'height': 10,
'insert': (cx, cy - radius - 25),
'halign': TextEntityAlignment.CENTER
})
# Attribute definieren
block.add_attdef(tag='REALE_POSITION', insert=(cx, cy - radius - 40), dxfattribs={
'height': 8,
'prompt': 'Reale Position:',
'default': 'x',
'halign': TextEntityAlignment.CENTER,
'invisible': 1
})
block.add_attdef(tag='NAME', insert=(cx, cy - radius - 55), dxfattribs={
'height': 10,
'prompt': 'Name:',
'default': '',
'halign': TextEntityAlignment.CENTER
})
block.add_attdef(tag='KENNZEICHNUNG', insert=(cx, cy - radius - 70), dxfattribs={
'height': 8,
'prompt': 'Kennzeichnung:',
'default': '=A01+UH00-X01',
'halign': TextEntityAlignment.CENTER,
'invisible': 1
})
# Block-Instanz einfügen
msp.add_blockref('MOTOR', (125, 125))
doc.saveas(filename)
print(f"{filename} erstellt")
# Hauptprogramm
if __name__ == "__main__":
print("Erstelle DXF Elektrosymbole nach DIN EN 60617 mit Attributen...\n")
create_grounding_symbol()
create_switchboard_symbol()
create_subdistribution_symbol()
create_motor_symbol()
print("\n✓ Alle Symbole wurden erfolgreich erstellt!")
print("\nDateien:")
print(" - erdung.dxf")
print(" - schaltschrank.dxf")
print(" - unterverteiler.dxf")
print(" - motor.dxf")
print("\nJedes Symbol ist als Block mit folgenden Attributen definiert:")
print(" - REALE_POSITION (Standard: 'x', unsichtbar)")
print(" - NAME (Standard: leer, sichtbar unter dem Symbol)")
print(" - KENNZEICHNUNG (Standard: '=A01+UH00-X01', unsichtbar)")
print("\nDie Attribute können in CAD-Programmen bearbeitet werden.")
+89 -29
View File
@@ -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:
+58 -5
View File
@@ -4,6 +4,7 @@ from pathlib import Path
from error_collector import ErrorCollector, write_json_file
from utils import check_environment_var, check_file_in_work, dxf_is_binary, get_dxf_file
from symbol_frames import draw_symbol_frames
"""
@@ -491,6 +492,7 @@ def collect_and_group_renamer_blocks(doc, msp, renamer_layers, error_collector):
continue
print(f" Boundary gefunden mit {len(boundary)} Punkten (Rechteck: {is_rectangle})")
print(f" Eckpunkte: {', '.join([f'({p[0]:.2f}, {p[1]:.2f})' for p in boundary])}")
# Validiere DIRECTION gegen Geometrie
direction = attributes.get("DIRECTION", "LEFT_RIGHT")
@@ -679,17 +681,59 @@ def process_renamer_blocks(doc, msp, renamer_layers, error_collector):
Verarbeitet alle Renamer-Blöcke auf den angegebenen Layern.
Gruppiert Blöcke mit identischer Konfiguration und nummeriert alle Symbole
aus allen Blöcken einer Gruppe gemeinsam.
Returns:
Tuple (all_renamed, renamer_groups):
- all_renamed: Liste der umbenannten Symbole
- renamer_groups: Dictionary der gruppierten Renamer-Blöcke
"""
# Erster Pass: Sammle und gruppiere alle Renamer-Blöcke
renamer_groups = collect_and_group_renamer_blocks(doc, msp, renamer_layers, error_collector)
# Zweiter Pass: Verarbeite jede Gruppe
all_renamed = process_renamer_groups(doc, msp, renamer_layers, renamer_groups, error_collector)
# Dritter Pass: Prüfe ob alle Symbole mit "@" im IO in einem Renamer-Bereich liegen
check_symbols_in_boundaries(doc, msp, renamer_groups, error_collector)
return all_renamed
return all_renamed, renamer_groups
def collect_all_symbols_from_groups(doc, msp, renamer_groups, renamer_layers, error_collector):
"""
Sammelt alle Symbole aus allen Renamer-Gruppen für Visualisierungszwecke.
Args:
doc: DXF-Dokument
msp: Modelspace
renamer_groups: Dictionary mit gruppierten Renamer-Blöcken
renamer_layers: Liste der Layer mit Renamer-Blöcken
error_collector: ErrorCollector für Fehlerbehandlung
Returns:
Liste aller gefundenen Symbole mit 'entity', 'position', 'attributes', 'layer'
"""
all_symbols = []
seen_entities = set() # Verhindere Duplikate
for config_key, group_blocks in renamer_groups.items():
if not group_blocks:
continue
reference_attributes = group_blocks[0][2]
for insert, boundary, attributes, is_rectangle in group_blocks:
# Finde Symbole innerhalb dieses Bereichs
symbols = find_symbols_in_boundary(doc, msp, boundary, renamer_layers, attributes, error_collector)
# Füge Symbole hinzu, aber nur wenn das Entity noch nicht gesehen wurde
for symbol in symbols:
entity_id = id(symbol['entity'])
if entity_id not in seen_entities:
seen_entities.add(entity_id)
all_symbols.append(symbol)
return all_symbols
if __name__ == '__main__':
@@ -726,6 +770,7 @@ if __name__ == '__main__':
parser.add_argument('-e', '--errorfile', action='store', required=False, help='JSON-Datei für Fehler und Warnungen', metavar='errors.json')
parser.add_argument('-w', '--write', action='store', help='Schreibe Ergebnisse der Nummerierung in eine JSON-Datei')
parser.add_argument('-d', '--dryrun', action='store_true', help='Symbole nicht in der DXF-Datei überschreiben, nur Ausgabe auf Konsole')
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()
@@ -770,7 +815,7 @@ if __name__ == '__main__':
print("Starte Verarbeitung der Renamer-Blöcke")
print("="*60 + "\n")
renamed_symbols = process_renamer_blocks(doc, msp, renamer_layers, error_collector)
renamed_symbols, renamer_groups = process_renamer_blocks(doc, msp, renamer_layers, error_collector)
print("\n" + "="*60)
print(f"Verarbeitung abgeschlossen: {len(renamed_symbols)} Symbole nummeriert")
@@ -782,6 +827,14 @@ if __name__ == '__main__':
for item in renamed_symbols:
print(f" {item['old_value']} -> {item['new_value']} (Layer: {item['layer']}, Pos: {item['position']})")
# Zeichne Symbol-Rahmen wenn gewünscht
if args.show_symbol_frames:
all_symbols = collect_all_symbols_from_groups(doc, msp, renamer_groups, renamer_layers, error_collector)
if all_symbols:
draw_symbol_frames(doc, msp, all_symbols)
else:
print("\nKeine Symbole für Rahmen-Zeichnung gefunden")
# Speichere DXF-Datei wenn nicht dry-run
if not args.dryrun:
output_path = dxf_path.parent / f"{dxf_path.stem}_numbered{dxf_path.suffix}"