diff --git a/cfg/create_tests.json b/cfg/create_tests.json index 8b7ddfe..444c5a0 100644 --- a/cfg/create_tests.json +++ b/cfg/create_tests.json @@ -37,10 +37,10 @@ "kennzeichnung": "A01+UH00", "layer_name": "ILS_MOTOR", "direction": "LEFT_RIGHT", - "x": 1400, - "y": 1100, + "x": 700, + "y": 800, "width": 3600, - "height": 580, + "height": 450, "use_polyline": false }, { diff --git a/lib/create_example.py b/lib/create_example.py index eef6e9d..9bf2996 100644 --- a/lib/create_example.py +++ b/lib/create_example.py @@ -721,7 +721,8 @@ class TestDataGenerator: block_insert_y = top_right_y - text_d_y_offset blockref = self.msp.add_blockref( 'io', - insert=(block_insert_x, block_insert_y), +# insert=(block_insert_x, block_insert_y), + insert=(x, y), dxfattribs={'layer': 'ILS_MOTOR'} ) # Erzeuge Attribut-Instanzen aus ATTDEFs mit Werten @@ -752,7 +753,8 @@ class TestDataGenerator: block_insert_y = left_bottom_y - text_d_y_offset blockref = self.msp.add_blockref( 'io', - insert=(block_insert_x, block_insert_y), + #insert=(block_insert_x, block_insert_y), + insert=(left_bottom_x, left_bottom_y), dxfattribs={'layer': 'ILS_MOTOR'} ) blockref.add_auto_attribs({ @@ -787,7 +789,8 @@ class TestDataGenerator: block_insert_y = y - text_d_y_offset blockref = self.msp.add_blockref( 'io', - insert=(block_insert_x, block_insert_y), + #insert=(block_insert_x, block_insert_y), + insert=(x, y), dxfattribs={'layer': 'ILS_MOTOR'} ) blockref.add_auto_attribs({ diff --git a/lib/create_numbers.py b/lib/create_numbers.py index 3960923..a449595 100644 --- a/lib/create_numbers.py +++ b/lib/create_numbers.py @@ -446,15 +446,13 @@ def validate_direction_with_geometry(direction, is_rectangle): return True, f"Unbekannte DIRECTION '{direction}' - Verarbeitung wird fortgesetzt" -def process_renamer_blocks(doc, msp, renamer_layers, error_collector): +def collect_and_group_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. + Erster Pass: Sammelt und gruppiert alle Renamer-Blöcke nach Konfiguration. + + Returns: + Dictionary mit {config_key: [(insert, boundary, attributes, is_rectangle), ...]} """ - all_renamed = [] - - # Erste Pass: Sammle und gruppiere alle Renamer-Blöcke renamer_groups = {} # {config_key: [(insert, boundary, attributes, is_rectangle), ...]} for layer in renamer_layers: @@ -511,7 +509,18 @@ def process_renamer_blocks(doc, msp, renamer_layers, error_collector): renamer_groups[config_key] = [] renamer_groups[config_key].append((insert, boundary, attributes, is_rectangle)) - # Zweite Pass: Verarbeite jede Gruppe + return renamer_groups + +def process_renamer_groups(doc, msp, renamer_layers, renamer_groups, error_collector): + """ + Zweiter Pass: Verarbeitet jede Renamer-Block-Gruppe. + Sammelt Symbole, sortiert sie und nummeriert sie. + + Returns: + Liste aller umbenannten Symbole + """ + all_renamed = [] + for config_key, group_blocks in renamer_groups.items(): if not group_blocks: continue @@ -540,21 +549,42 @@ def process_renamer_blocks(doc, msp, renamer_layers, error_collector): seen_entities[entity_id] = (symbol, [renamer_pos]) all_symbols.append(symbol) else: - # Symbol wurde bereits in einem anderen Bereich gefunden - Warnung + # Symbol wurde bereits in einem anderen Bereich gefunden - Fehler existing_symbol, existing_positions = seen_entities[entity_id] existing_positions.append(renamer_pos) symbol_pos = symbol['position'] - warning_msg = ( + io_value = symbol['attributes'].get('IO', 'N/A') + error_msg = ( f"Symbol an Position ({symbol_pos[0]:.1f}, {symbol_pos[1]:.1f}) " - f"liegt in mehreren Renamer-Bereichen der Gruppe '{block_name}'. " + f"mit IO='{io_value}' liegt in mehreren Renamer-Bereichen der Gruppe '{block_name}'. " f"Gefunden in Renamer-Blöcken an Positionen: " f"{', '.join([f'({p[0]:.1f}, {p[1]:.1f})' for p in existing_positions])}" ) - error_collector.add_warnings({"symbol_in_multiple_boundaries": warning_msg}) + print(f" FEHLER: {error_msg}") + error_collector.add_errors({"symbol_in_multiple_boundaries": error_msg}) print(f" Gesamt {len(all_symbols)} eindeutige Template-Symbole aus {len(group_blocks)} Blöcken") if not all_symbols: + # Fehlermeldung: Keine Symbole gefunden + layer_names = [] + for i in range(1, 4): + layer_key = f"LAYER_NAME{i}" + if layer_key in reference_attributes and reference_attributes[layer_key]: + layer_names.append(reference_attributes[layer_key]) + if "LAYER_NAME" in reference_attributes and reference_attributes["LAYER_NAME"]: + layer_names.append(reference_attributes["LAYER_NAME"]) + + renamer_positions = [f"({insert.dxf.insert[0]:.1f}, {insert.dxf.insert[1]:.1f})" + for insert, _, _, _ in group_blocks] + error_msg = ( + f"Renamer-Block-Gruppe '{block_name}' (DIRECTION: {direction}) " + f"hat keine passenden Symbole gefunden. " + f"Gesucht auf Layer: {', '.join(layer_names) if layer_names else 'N/A'}. " + f"Renamer-Blöcke an Positionen: {', '.join(renamer_positions)}" + ) + print(f" FEHLER: {error_msg}") + error_collector.add_errors({"no_symbols_found": error_msg}) continue # Sortiere alle Symbole zusammen nach Richtung @@ -568,6 +598,96 @@ def process_renamer_blocks(doc, msp, renamer_layers, error_collector): return all_renamed +def check_symbols_in_boundaries(doc, msp, renamer_groups, error_collector): + """ + Dritter Pass: Prüft ob alle Symbole mit "@" im IO in einem Renamer-Bereich liegen. + """ + print("\n" + "="*60) + print("Prüfe ob alle Symbole mit '@' im IO in einem Renamer-Bereich liegen") + print("="*60) + + # Sammle alle Renamer-Boundaries + all_boundaries = [] + for group_blocks in renamer_groups.values(): + for insert, boundary, attributes, is_rectangle in group_blocks: + all_boundaries.append((boundary, attributes)) + + # Finde alle Symbole mit "@" im IO-Attribut + symbols_with_at = [] + for entity in msp.query('INSERT'): + symbol_attribs = extract_block_attributes(doc, entity) + if not symbol_attribs: + continue + + # Prüfe ob IO-Attribut "@" enthält + io_value = symbol_attribs.get('IO', '') + if '@' in str(io_value): + pos = entity.dxf.insert + point = (pos[0], pos[1]) + symbols_with_at.append({ + 'entity': entity, + 'position': point, + 'attributes': symbol_attribs, + 'layer': entity.dxf.layer, + 'io': io_value + }) + + # Prüfe für jedes Symbol, ob es in mindestens einem Renamer-Bereich liegt + symbols_not_in_any_boundary = [] + for symbol in symbols_with_at: + in_any_boundary = False + for boundary, attributes in all_boundaries: + # Prüfe ob Symbol auf dem richtigen Layer ist + search_layers = [] + for i in range(1, 4): + layer_key = f"LAYER_NAME{i}" + if layer_key in attributes and attributes[layer_key]: + search_layers.append(attributes[layer_key]) + if "LAYER_NAME" in attributes and attributes["LAYER_NAME"]: + search_layers.append(attributes["LAYER_NAME"]) + + if symbol['layer'] not in search_layers: + continue + + # Prüfe ob Symbol innerhalb des Bereichs liegt + if point_in_polygon(symbol['position'], boundary): + in_any_boundary = True + break + + if not in_any_boundary: + symbols_not_in_any_boundary.append(symbol) + + # Melde Fehler für Symbole, die in keinem Bereich liegen + if symbols_not_in_any_boundary: + for symbol in symbols_not_in_any_boundary: + error_msg = ( + f"Symbol an Position ({symbol['position'][0]:.1f}, {symbol['position'][1]:.1f}) " + f"mit IO='{symbol['io']}' auf Layer '{symbol['layer']}' " + f"enthält '@' im IO-Attribut, liegt aber in keinem Renamer-Bereich." + ) + print(f" FEHLER: {error_msg}") + error_collector.add_errors({"symbol_with_at_not_in_boundary": error_msg}) + else: + print(f" Alle {len(symbols_with_at)} Symbole mit '@' im IO liegen in einem Renamer-Bereich.") + + +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. + """ + # 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 + if __name__ == '__main__': parser = argparse.ArgumentParser(description='Nummeriert Symbole in DXF-Dateien basierend auf Renamer-Blöcken', prog='create_numbers')