From 7c662c96635c9521f74bba5b76998df060076c2f Mon Sep 17 00:00:00 2001
From: Paul Wolok
Date: Mon, 8 Sep 2025 16:29:31 +0200
Subject: [PATCH] =?UTF-8?q?test=20mit=20bl=C3=B6cken=20erstellen?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
lib/dxf2lib.py | 617 ++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 506 insertions(+), 111 deletions(-)
diff --git a/lib/dxf2lib.py b/lib/dxf2lib.py
index 4f74158..e0de2e5 100644
--- a/lib/dxf2lib.py
+++ b/lib/dxf2lib.py
@@ -1,6 +1,6 @@
import os
import ezdxf
-from ezdxf.math import Vec2, BoundingBox
+from ezdxf.math import Matrix44, Vec3, BoundingBox, Vec2
import math
import argparse
import sys
@@ -11,115 +11,120 @@ from pathlib import Path
import logging
-def get_bbox(entities):
- """
- Berechnet die Bounding Box für eine Liste von DXF-Entities.
+# def get_bbox(entities, transform_matrix=None):
+# """
+# Berechnet die Bounding Box für eine Liste von DXF-Entities.
- Args:
- entities: Liste von DXF-Entities (ezdxf entities)
+# Args:
+# entities: Liste von DXF-Entities (ezdxf entities)
- Returns:
- Vec2 or None: Zentrum der Bounding Box als Vec2-Objekt oder None,
- falls keine gültige Geometrie gefunden wurde
+# Returns:
+# Vec2 or None: Zentrum der Bounding Box als Vec2-Objekt oder None,
+# falls keine gültige Geometrie gefunden wurde
- Note:
- Unterstützt POLYLINE, LWPOLYLINE und andere Entity-Typen.
- Fehlerhafte Entities werden übersprungen und protokolliert.
- """
- min_x, min_y = float('inf'), float('inf')
- max_x, max_y = float('-inf'), float('-inf')
- for e in entities:
- try:
- if e.dxftype() == "POLYLINE":
- for vertex in e.vertices:
- if hasattr(vertex.dxf, 'location'):
- x, y = vertex.dxf.location.x, vertex.dxf.location.y
- min_x, min_y = min(min_x, x), min(min_y, y)
- max_x, max_y = max(max_x, x), max(max_y, y)
- elif e.dxftype() == "LWPOLYLINE":
- for x, y, *_ in e.get_points("xy"):
- min_x, min_y = min(min_x, x), min(min_y, y)
- max_x, max_y = max(max_x, x), max(max_y, y)
- elif e.dxftype() == "ARC":
- # Handle ARC entities: consider endpoints and cardinal extrema
- try:
- cx, cy = e.dxf.center.x, e.dxf.center.y
- except Exception:
- cx, cy = e.dxf.center
- r = float(e.dxf.radius)
- start_deg = float(e.dxf.start_angle)
- end_deg = float(e.dxf.end_angle)
- start = math.radians(start_deg % 360)
- end = math.radians(end_deg % 360)
+# Note:
+# Unterstützt POLYLINE, LWPOLYLINE und andere Entity-Typen.
+# Fehlerhafte Entities werden übersprungen und protokolliert.
+# """
+# min_x, min_y = float('inf'), float('inf')
+# max_x, max_y = float('-inf'), float('-inf')
+# for e in entities:
+# try:
+# if e.dxftype() == "POLYLINE":
+# for vertex in e.vertices:
+# if hasattr(vertex.dxf, 'location'):
+# x, y = vertex.dxf.location.x, vertex.dxf.location.y
+# min_x, min_y = min(min_x, x), min(min_y, y)
+# max_x, max_y = max(max_x, x), max(max_y, y)
+# elif e.dxftype() == "LWPOLYLINE":
+# for x, y, *_ in e.get_points("xy"):
+# min_x, min_y = min(min_x, x), min(min_y, y)
+# max_x, max_y = max(max_x, x), max(max_y, y)
+# elif e.dxftype() == "ARC":
+# # Handle ARC entities: consider endpoints and cardinal extrema
+# try:
+# cx, cy = e.dxf.center.x, e.dxf.center.y
+# except Exception:
+# cx, cy = e.dxf.center
+# r = float(e.dxf.radius)
+# start_deg = float(e.dxf.start_angle)
+# end_deg = float(e.dxf.end_angle)
+# start = math.radians(start_deg % 360)
+# end = math.radians(end_deg % 360)
- def in_sweep(a: float, s: float, e_: float) -> bool:
- # CCW sweep from s to e_ with wrap handling
- if e_ >= s:
- return s <= a <= e_
- return a >= s or a <= e_
+# def in_sweep(a: float, s: float, e_: float) -> bool:
+# # CCW sweep from s to e_ with wrap handling
+# if e_ >= s:
+# return s <= a <= e_
+# return a >= s or a <= e_
- candidates = []
- # Endpoints
- candidates.append((cx + r * math.cos(start), cy + r * math.sin(start)))
- candidates.append((cx + r * math.cos(end), cy + r * math.sin(end)))
- # Cardinal angles 0, 90, 180, 270 deg
- for ang in (0.0, math.pi/2, math.pi, 3*math.pi/2):
- if in_sweep(ang, start, end):
- candidates.append((cx + r * math.cos(ang), cy + r * math.sin(ang)))
- for px, py in candidates:
- min_x, min_y = min(min_x, px), min(min_y, py)
- max_x, max_y = max(max_x, px), max(max_y, py)
- elif e.dxftype() == "CIRCLE":
- # Handle CIRCLE entities via center and radius
- try:
- cx, cy = e.dsf.center.x, e.dsf.center.y
- except Exception:
- cx, cy = e.dxf.center
- r = float(e.dxf.radius)
- min_x, min_y = min(min_x, cx - r), min(min_y, cy - r)
- max_x, max_y = max(max_x, cx + r), max(max_y, cy + r)
- elif e.dxftype() == "LINE" or e.dxftype()== "Line":
- # Handle simple line entities by their start/end points
- try:
- sx, sy = e.dxf.start.x, e.dxf.start.y
- ex, ey = e.dxf.end.x, e.dxf.end.y
- except Exception:
- # Some ezdxf versions provide tuples
- (sx, sy), (ex, ey) = e.dxf.start, e.dxf.end
- min_x, min_y = min(min_x, sx, ex ), min(min_y, sy, ey)
- max_x, max_y = max(max_x, sx, ex), max(max_y, sy, ey)
- elif e.dxftype() == "SPLINE":
- # Approximate spline to compute bounding box
- points = []
- try:
- points = e.approximate(60)
- except Exception:
- try:
- points = list(e.flattening(1.0))
- except Exception:
- points = []
- if points:
- for pt in points:
- try:
- px, py = pt.x, pt.y
- except Exception:
- px, py = pt[0], pt[1]
- min_x, min_y = min(min_x, px), min(min_y, py)
- max_x, max_y = max(max_x, px), max(max_y, py)
- else:
- box = e.bbox()
- if box:
- (x1, y1), (x2, y2) = box.extmin, box.extmax
- min_x, min_y = min(min_x, x1), min(min_y, y1)
- max_x, max_y = max(max_x, x2), max(max_y, y2)
- except Exception as err:
- print(f" BBox Fehler für {e.dxftype()}: {err}")
- continue
+# candidates = []
+# # Endpoints
+# candidates.append((cx + r * math.cos(start), cy + r * math.sin(start)))
+# candidates.append((cx + r * math.cos(end), cy + r * math.sin(end)))
+# # Cardinal angles 0, 90, 180, 270 deg
+# for ang in (0.0, math.pi/2, math.pi, 3*math.pi/2):
+# if in_sweep(ang, start, end):
+# candidates.append((cx + r * math.cos(ang), cy + r * math.sin(ang)))
+# for px, py in candidates:
+# min_x, min_y = min(min_x, px), min(min_y, py)
+# max_x, max_y = max(max_x, px), max(max_y, py)
+# elif e.dxftype() == "CIRCLE":
+# # Handle CIRCLE entities via center and radius
+# try:
+# cx, cy = e.dsf.center.x, e.dsf.center.y
+# except Exception:
+# cx, cy = e.dxf.center
+# r = float(e.dxf.radius)
+# min_x, min_y = min(min_x, cx - r), min(min_y, cy - r)
+# max_x, max_y = max(max_x, cx + r), max(max_y, cy + r)
+# elif e.dxftype() == "LINE" or e.dxftype()== "Line":
+# # Handle simple line entities by their start/end points
+# try:
+# sx, sy = e.dxf.start.x, e.dxf.start.y
+# ex, ey = e.dxf.end.x, e.dxf.end.y
+# except Exception:
+# # Some ezdxf versions provide tuples
+# (sx, sy), (ex, ey) = e.dxf.start, e.dxf.end
+# min_x, min_y = min(min_x, sx, ex ), min(min_y, sy, ey)
+# max_x, max_y = max(max_x, sx, ex), max(max_y, sy, ey)
+# elif e.dxftype() == "SPLINE":
+# # Approximate spline to compute bounding box
+# points = []
+# try:
+# points = e.approximate(60)
+# except Exception:
+# try:
+# points = list(e.flattening(1.0))
+# except Exception:
+# points = []
+# if points:
+# for pt in points:
+# try:
+# px, py = pt.x, pt.y
+# except Exception:
+# px, py = pt[0], pt[1]
+# min_x, min_y = min(min_x, px), min(min_y, py)
+# max_x, max_y = max(max_x, px), max(max_y, py)
+# elif e.dxftype() == 'INSERT':
+# # INSERT: Block-Inhalt mit Transformation berücksichtigen
+# insert_bbox = calculate_insert_bounding_box(e, doc, transform_matrix)
+# if insert_bbox and insert_bbox.has_data:
+# bbox.extend(insert_bbox)
+# else:
+# box = e.bbox()
+# if box:
+# (x1, y1), (x2, y2) = box.extmin, box.extmax
+# min_x, min_y = min(min_x, x1), min(min_y, y1)
+# max_x, max_y = max(max_x, x2), max(max_y, y2)
+# except Exception as err:
+# print(f" BBox Fehler für {e.dxftype()}: {err}")
+# continue
- if min_x == float('inf'):
- return None, (0,0)
+# if min_x == float('inf'):
+# return None, (0,0)
- return Vec2((min_x + max_x) / 2, (min_y + max_y) / 2), (max_x -min_x, max_y -min_y)
+# return Vec2((min_x + max_x) / 2, (min_y + max_y) / 2), (max_x -min_x, max_y -min_y)
def create_block_library(input_dir, output_file, config, logger=None):
@@ -209,7 +214,8 @@ def create_block_library(input_dir, output_file, config, logger=None):
pass
- center, ausdehnung = get_bbox(entities)
+ # center, ausdehnung = get_bbox(entities)
+ center, ausdehnung = get_entity_bounding_box(entities, doc, transform_matrix=None)
if center is None:
error_msg = f"Keine gültige Geometrie in {filename}"
if logger:
@@ -224,13 +230,13 @@ def create_block_library(input_dir, output_file, config, logger=None):
blk = doc.blocks.new(name=name, base_point=(0,0))
- for e in entities:
- # Sicherstellen, dass referenzierte Blöcke für INSERT verfügbar sind
- if e.dxftype() == "INSERT":
- handle_insert_entities(doc, src_doc, e)
- cp = copy_entity(logger, error_files, filename, e, center)
- if cp:
- blk.add_entity(cp)
+ # for e in entities:
+ # # Sicherstellen, dass referenzierte Blöcke für INSERT verfügbar sind
+ # if e.dxftype() == "INSERT":
+ # handle_insert_entities(doc, src_doc, e)
+ cp = copy_entity(logger, error_files, filename, e, center)
+ if cp:
+ blk.add_entity(cp)
# Platzierung in Reihen und Spalten
# Attribut-Definition (ATTDEF) hinzufügen
blk.add_attdef(
@@ -394,6 +400,395 @@ def get_cfg_value(section, key, fallback):
return fallback
+
+
+def convert_dxf_to_block_with_inserts(input_filename, output_filename, block_name="CONVERTED_BLOCK"):
+ """
+ Konvertiert alle Entities einer DXF-Datei in einen neuen Block
+ INSERTs werden als Referenzen beibehalten (nicht explodiert)
+ """
+ try:
+ # Eingabe-DXF laden
+ input_doc = ezdxf.readfile(input_filename)
+ print(f"Lade DXF-Datei: {input_filename}")
+
+ # Neue Ausgabe-DXF erstellen
+ output_doc = ezdxf.new('R2010')
+ output_doc.header['$INSUNITS'] = 4 # Millimeter
+
+ # Zuerst alle Block-Definitionen kopieren
+ copied_blocks = copy_block_definitions(input_doc, output_doc)
+ print(f"Block-Definitionen kopiert: {len(copied_blocks)}")
+
+ # Neuen Hauptblock erstellen
+ new_block = output_doc.blocks.new(name=block_name)
+ print(f"Erstelle neuen Block: {block_name}")
+
+ # Alle Entities aus dem Modelspace kopieren
+ msp = input_doc.modelspace()
+ entity_count = 0
+ insert_count = 0
+
+ for entity in msp:
+ if entity.dxftype() == 'INSERT':
+ # INSERT direkt kopieren (nicht explodieren)
+ copy_entity_to_block(entity, new_block)
+ insert_count += 1
+ else:
+ # Normale Entity kopieren
+ copy_entity_to_block(entity, new_block)
+
+ entity_count += 1
+
+ # Bounding Box berechnen
+ bbox = calculate_block_bounding_box(new_block, output_doc)
+
+ # Block im Modelspace der neuen Datei platzieren
+ output_msp = output_doc.modelspace()
+ output_msp.add_blockref(block_name, insert=(0, 0))
+
+ # Bounding Box als Hilfslinien hinzufügen (optional)
+ if bbox.has_data:
+ add_bounding_box_to_modelspace(output_msp, bbox)
+
+ # Speichern
+ output_doc.saveas(output_filename)
+
+ print(f"Konvertierung abgeschlossen:")
+ print(f" - {entity_count} Entities übertragen")
+ print(f" - {insert_count} INSERTs als Referenzen beibehalten")
+ print(f" - Bounding Box: {format_bounding_box(bbox)}")
+ print(f" - Ausgabe: {output_filename}")
+
+ return bbox
+
+ except FileNotFoundError:
+ print(f"Fehler: Datei {input_filename} nicht gefunden")
+ return None
+ except ezdxf.DXFStructureError as e:
+ print(f"DXF-Strukturfehler: {e}")
+ return None
+ except Exception as e:
+ print(f"Unerwarteter Fehler: {e}")
+ return None
+
+
+def copy_block_definitions(source_doc, target_doc):
+ """
+ Kopiert alle Block-Definitionen vom Quell- zum Ziel-Dokument
+ """
+ copied_blocks = []
+
+ for block_name in source_doc.blocks:
+ # Standard-Blöcke (MODEL_SPACE, PAPER_SPACE) überspringen
+ if block_name.startswith('*'):
+ continue
+
+ source_block = source_doc.blocks[block_name]
+
+ # Prüfen ob Block bereits existiert
+ if block_name in target_doc.blocks:
+ print(f"Warnung: Block '{block_name}' existiert bereits, wird übersprungen")
+ continue
+
+ # Neuen Block in Ziel-Dokument erstellen
+ target_block = target_doc.blocks.new(name=block_name)
+
+ # Alle Entities des Quell-Blocks kopieren
+ for entity in source_block:
+ copy_entity_to_block(entity, target_block)
+
+ copied_blocks.append(block_name)
+
+ return copied_blocks
+
+
+def calculate_block_bounding_box(block, doc):
+ """
+ Berechnet die Bounding Box eines Blocks inklusive aller INSERTs
+ """
+ bbox = BoundingBox()
+
+ for entity in block:
+ entity_bbox = get_entity_bounding_box(entity, doc)
+ if entity_bbox and entity_bbox.has_data:
+ bbox.extend(entity_bbox)
+
+ return bbox
+
+
+def get_entity_bounding_box(entity, doc, transform_matrix=None):
+ """
+ Berechnet die Bounding Box einer einzelnen Entity
+ Berücksichtigt INSERTs mit ihren Block-Inhalten
+ """
+ bbox = BoundingBox()
+ for e in entity:
+ try:
+ if e.dxftype() == 'LINE':
+ start = Vec3(e.dxf.start)
+ end = Vec3(e.dxf.end)
+ if transform_matrix:
+ start = transform_matrix.transform(start)
+ end = transform_matrix.transform(end)
+ bbox.extend([start, end])
+
+ elif e.dxftype() == 'CIRCLE':
+ center = Vec3(e.dxf.center)
+ radius = e.dxf.radius
+ if transform_matrix:
+ center = transform_matrix.transform(center)
+ # Radius mit durchschnittlicher Skalierung anpassen
+ scale_factor = (transform_matrix.scale_x + transform_matrix.scale_y) / 2
+ radius *= abs(scale_factor)
+
+ bbox.extend([
+ Vec3(center.x - radius, center.y - radius, center.z),
+ Vec3(center.x + radius, center.y + radius, center.z)
+ ])
+
+ elif e.dxftype() == 'ARC':
+ # Vereinfachung: Bounding Box des vollständigen Kreises
+ center = Vec3(e.dxf.center)
+ radius = e.dxf.radius
+ if transform_matrix:
+ center = transform_matrix.transform(center)
+ scale_factor = (transform_matrix.scale_x + transform_matrix.scale_y) / 2
+ radius *= abs(scale_factor)
+
+ bbox.extend([
+ Vec3(center.x - radius, center.y - radius, center.z),
+ Vec3(center.x + radius, center.y + radius, center.z)
+ ])
+
+ elif e.dxftype() == 'LWPOLYLINE':
+ points = []
+ for point in e.get_points():
+ pt = Vec3(point[0], point[1], 0)
+ if transform_matrix:
+ pt = transform_matrix.transform(pt)
+ points.append(pt)
+ if points:
+ bbox.extend(points)
+
+ elif e.dxftype() == 'POLYLINE':
+ points = []
+ for vertex in e.vertices:
+ pt = Vec3(vertex.dxf.location)
+ if transform_matrix:
+ pt = transform_matrix.transform(pt)
+ points.append(pt)
+ if points:
+ bbox.extend(points)
+
+ elif e.dxftype() == 'TEXT':
+ # Vereinfachung: Nur Insert-Point berücksichtigen
+ insert_point = Vec3(e.dxf.insert)
+ if transform_matrix:
+ insert_point = transform_matrix.transform(insert_point)
+ bbox.extend([insert_point])
+
+ elif e.dxftype() == 'INSERT':
+ # INSERT: Block-Inhalt mit Transformation berücksichtigen
+ insert_bbox = calculate_insert_bounding_box(e, doc, transform_matrix)
+ if insert_bbox and insert_bbox.has_data:
+ bbox.extend(insert_bbox)
+
+ except Exception as e:
+ print(f"Fehler bei Bounding Box Berechnung für {entity.dxftype()}: {e}")
+
+ return bbox,( bbox.extmax.x - bbox.extmin.x,bbox.extmax.y -bbox.extmin.y)
+
+
+def calculate_insert_bounding_box(insert_entity, doc, parent_transform=None):
+ """
+ Berechnet die Bounding Box eines INSERTs inklusive Block-Inhalt
+ """
+ try:
+ # Block-Definition finden
+ block_name = insert_entity.dxf.name
+ if block_name not in doc.blocks:
+ print(f"Warnung: Block '{block_name}' nicht gefunden")
+ return BoundingBox()
+
+ block_def = doc.blocks[block_name]
+
+ # Transformation der INSERT-Entity berechnen
+ insert_transform = get_insert_transform_matrix(insert_entity)
+
+ # Mit übergeordneter Transformation kombinieren
+ if parent_transform:
+ combined_transform = parent_transform * insert_transform
+ else:
+ combined_transform = insert_transform
+
+ # Bounding Box aller Entities im Block berechnen
+ block_bbox = BoundingBox()
+
+ for block_entity in block_def:
+ entity_bbox = get_entity_bounding_box(block_entity, doc, combined_transform)
+ if entity_bbox and entity_bbox.has_data:
+ block_bbox.extend(entity_bbox)
+
+ return block_bbox
+
+ except Exception as e:
+ print(f"Fehler bei INSERT Bounding Box: {e}")
+ return BoundingBox()
+
+
+def get_insert_transform_matrix(insert_entity):
+ """
+ Berechnet die Transformationsmatrix für einen INSERT
+ """
+ # Position
+ insert_point = Vec3(insert_entity.dxf.insert)
+
+ # Skalierung
+ xscale = getattr(insert_entity.dxf, 'xscale', 1.0)
+ yscale = getattr(insert_entity.dxf, 'yscale', 1.0)
+ zscale = getattr(insert_entity.dxf, 'zscale', 1.0)
+
+ # Rotation (in Radiant umwandeln)
+ rotation = math.radians(getattr(insert_entity.dxf, 'rotation', 0.0))
+
+ # Transformationsmatrix erstellen
+ matrix = Matrix44.chain(
+ Matrix44.scale(xscale, yscale, zscale),
+ Matrix44.z_rotate(rotation),
+ Matrix44.translate(insert_point.x, insert_point.y, insert_point.z)
+ )
+
+ return matrix
+
+
+def copy_entity_to_block(entity, target_block):
+ """
+ Kopiert eine Entity in einen Zielblock
+ """
+ try:
+ # Entity kopieren und zum Block hinzufügen
+ entity_copy = entity.copy()
+ target_block.add_entity(entity_copy)
+
+ except Exception as e:
+ print(f"Fehler beim Kopieren von {entity.dxftype()}: {e}")
+
+
+def add_bounding_box_to_modelspace(msp, bbox):
+ """
+ Fügt die Bounding Box als Hilfslinien zum Modelspace hinzu
+ """
+ if not bbox.has_data:
+ return
+
+ # Bounding Box Rechteck zeichnen
+ min_pt = bbox.extmin
+ max_pt = bbox.extmax
+
+ # Rechteck als LWPOLYLINE
+ bbox_points = [
+ (min_pt.x, min_pt.y),
+ (max_pt.x, min_pt.y),
+ (max_pt.x, max_pt.y),
+ (min_pt.x, max_pt.y),
+ (min_pt.x, min_pt.y)
+ ]
+
+ bbox_poly = msp.add_lwpolyline(bbox_points)
+ bbox_poly.dxf.layer = "BOUNDING_BOX"
+ bbox_poly.dxf.color = 1 # Rot
+
+ # Bemaßungen hinzufügen
+ width = max_pt.x - min_pt.x
+ height = max_pt.y - min_pt.y
+
+ # Text mit Abmessungen
+ text_pos = Vec3(min_pt.x, max_pt.y + 5, 0)
+ msp.add_text(f"Breite: {width:.2f} mm", height=3,
+ dxfattribs={'insert': text_pos, 'layer': "BOUNDING_BOX", 'color': 1})
+
+ text_pos2 = Vec3(min_pt.x, max_pt.y + 10, 0)
+ msp.add_text(f"Höhe: {height:.2f} mm", height=3,
+ dxfattribs={'insert': text_pos2, 'layer': "BOUNDING_BOX", 'color': 1})
+
+
+def format_bounding_box(bbox):
+ """
+ Formatiert Bounding Box Information für Ausgabe
+ """
+ if not bbox.has_data:
+ return "Keine gültigen Geometriedaten gefunden"
+
+ min_pt = bbox.extmin
+ max_pt = bbox.extmax
+ width = max_pt.x - min_pt.x
+ height = max_pt.y - min_pt.y
+ depth = max_pt.z - min_pt.z
+
+ return (f"Min: ({min_pt.x:.2f}, {min_pt.y:.2f}, {min_pt.z:.2f}) "
+ f"Max: ({max_pt.x:.2f}, {max_pt.y:.2f}, {max_pt.z:.2f}) "
+ f"Größe: {width:.2f} × {height:.2f} × {depth:.2f} mm")
+
+
+def analyze_source_dxf_with_blocks(filename):
+ """
+ Analysiert die Quell-DXF inklusive Block-Definitionen
+ """
+ try:
+ doc = ezdxf.readfile(filename)
+ msp = doc.modelspace()
+
+ entity_types = {}
+ layer_count = {}
+ insert_blocks = {}
+ block_definitions = {}
+
+ # Modelspace analysieren
+ for entity in msp:
+ entity_type = entity.dxftype()
+ entity_types[entity_type] = entity_types.get(entity_type, 0) + 1
+
+ layer = getattr(entity.dxf, 'layer', '0')
+ layer_count[layer] = layer_count.get(layer, 0) + 1
+
+ if entity_type == 'INSERT':
+ block_name = entity.dxf.name
+ insert_blocks[block_name] = insert_blocks.get(block_name, 0) + 1
+
+ # Block-Definitionen analysieren
+ for block_name in doc.blocks:
+ if not block_name.startswith('*'): # Keine Standard-Blöcke
+ block_def = doc.blocks[block_name]
+ entity_count = len(list(block_def))
+ block_definitions[block_name] = entity_count
+
+ print(f"\nAnalyse von {filename}:")
+ print("=" * 50)
+ print("Entity-Typen im Modelspace:")
+ for etype, count in sorted(entity_types.items()):
+ print(f" {etype}: {count}")
+
+ print(f"\nLayer ({len(layer_count)}):")
+ for layer, count in sorted(layer_count.items()):
+ print(f" {layer}: {count} entities")
+
+ if insert_blocks:
+ print(f"\nINSERT-Verwendungen ({sum(insert_blocks.values())} total):")
+ for block, count in sorted(insert_blocks.items()):
+ print(f" {block}: {count}× verwendet")
+
+ if block_definitions:
+ print(f"\nBlock-Definitionen ({len(block_definitions)}):")
+ for block, count in sorted(block_definitions.items()):
+ print(f" {block}: {count} entities")
+
+ return entity_types, layer_count, insert_blocks, block_definitions
+
+ except Exception as e:
+ print(f"Fehler bei der Analyse: {e}")
+ return {}, {}, {}, {}
+
if __name__ == "__main__":
# Argumentparser für Kommandozeilenoptionen
parser = argparse.ArgumentParser(description="SVG/XML zu DXF Konverter")