From e3494530ea58d2ca29244cc3b52c7801b30f7cd3 Mon Sep 17 00:00:00 2001
From: Paul Wolok
Date: Wed, 10 Sep 2025 15:32:06 +0200
Subject: [PATCH] Inserts richtig in die Bounding box reingetan
---
lib/dxf2lib.py | 260 +++++++++++++++----------------------------------
1 file changed, 80 insertions(+), 180 deletions(-)
diff --git a/lib/dxf2lib.py b/lib/dxf2lib.py
index 46d05c8..f70717b 100644
--- a/lib/dxf2lib.py
+++ b/lib/dxf2lib.py
@@ -161,6 +161,8 @@ def create_block_library(input_dir, output_file, config, logger=None):
max_blockspacing_y = 0
for filename in os.listdir(input_dir):
+ if filename =='821104043.dxf':
+ test = 2
if not filename.lower().endswith(".dxf"):
continue
@@ -213,8 +215,7 @@ def create_block_library(input_dir, output_file, config, logger=None):
except Exception:
pass
- if filename == "0_BG090090_834372101_0_BG090090.dxf":
- filetest =3
+
# center, ausdehnung = get_bbox(entities)
boundingbox, ausdehnung, center = calculate_block_bounding_box(filtered_entities, doc,src_doc, filename)
if center is None:
@@ -238,8 +239,8 @@ def create_block_library(input_dir, output_file, config, logger=None):
for e in entities:
cp = copy_entity(logger, error_files, filename, e, center)
if cp:
- copy_entity_to_block(cp,blk)
- # blk.add_entity(cp)
+ blk.add_entity(cp)
+ add_bounding_box_to_modelspace(blk, boundingbox, centered=True)
# Platzierung in Reihen und Spalten
# Attribut-Definition (ATTDEF) hinzufügen
blk.add_attdef(
@@ -518,7 +519,8 @@ def calculate_block_bounding_box(block, doc, src_doc, filename):
if entity_bbox and entity_bbox.has_data:
bbox.extend(entity_bbox)
- return bbox, (bbox.extmax.x -bbox.extmin.x, bbox.extmax.y -bbox.extmin.y),Vec2(((bbox.extmax.x + bbox.extmin.x) / 2, (bbox.extmax.y + bbox.extmin.y) /2))
+
+ return bbox, (bbox.extmax.x -bbox.extmin.x, bbox.extmax.y -bbox.extmin.y),bbox.center
def get_entity_bounding_box(e, doc,src_doc,filename, transform_matrix=None,):
@@ -527,10 +529,7 @@ def get_entity_bounding_box(e, doc,src_doc,filename, transform_matrix=None,):
Berücksichtigt INSERTs mit ihren Block-Inhalten
"""
- bbox = BoundingBox()
-
-
-
+ bbox = BoundingBox()
try:
if e.dxftype() == 'LINE':
start = Vec3(e.dxf.start)
@@ -538,24 +537,24 @@ def get_entity_bounding_box(e, doc,src_doc,filename, transform_matrix=None,):
if transform_matrix:
start = transform_matrix.transform(start)
end = transform_matrix.transform(end)
- bbox.extend([start, end])
+ bbox.extend([start])
+ bbox.extend([end])
elif e.dxftype() == 'CIRCLE':
# Kreis durch Punktabtastung (robust bei Transformationen)
center = Vec3(e.dxf.center)
radius = float(e.dxf.radius)
- num = 72
- sampled = []
- for i in range(num):
- ang = 2 * math.pi * (i / num)
+ angles = (0.0, math.pi / 2, math.pi, 3 * math.pi / 2)
+ points = []
+ for ang in angles:
px = center.x + radius * math.cos(ang)
py = center.y + radius * math.sin(ang)
p = Vec3(px, py, center.z)
if transform_matrix:
p = transform_matrix.transform(p)
- sampled.append(p)
- if sampled:
- bbox.extend(sampled)
+ points.append(p)
+ if points:
+ bbox.extend(points)
elif e.dxftype() == 'ARC':
# Bogen durch Punktabtastung zwischen Start- und Endwinkel
@@ -565,34 +564,28 @@ def get_entity_bounding_box(e, doc,src_doc,filename, transform_matrix=None,):
end_deg = float(e.dxf.end_angle)
start = math.radians(start_deg % 360)
end = math.radians(end_deg % 360)
- # Schritte abhängig vom Sweep
- def sweep_steps(s, e_):
+
+ def in_sweep(a: float, s: float, e_: float) -> bool:
+ # CCW sweep von s nach e_ mit Wrap-Handling
if e_ >= s:
- span = e_ - s
- else:
- span = (2 * math.pi - s) + e_
- return max(12, int(72 * span / (2 * math.pi)))
- steps = sweep_steps(start, end)
- sampled = []
- # CCW Sweeping
- if end >= start:
- angles = [start + (end - start) * (i / steps) for i in range(steps + 1)]
- else:
- angles = []
- span1 = 2 * math.pi - start
- for i in range(int(steps * span1 / (2 * math.pi)) + 1):
- angles.append(start + span1 * (i / max(1, int(steps * span1 / (2 * math.pi)))))
- for i in range(1, steps - len(angles) + 2):
- angles.append(0.0 + end * (i / (steps - len(angles) + 1)))
+ return s <= a <= e_
+ return a >= s or a <= e_
+
+ angles = [start, end]
+ for ang in (0.0, math.pi / 2, math.pi, 3 * math.pi / 2):
+ if in_sweep(ang, start, end):
+ angles.append(ang)
+
+ points = []
for ang in angles:
px = center.x + radius * math.cos(ang)
py = center.y + radius * math.sin(ang)
p = Vec3(px, py, center.z)
if transform_matrix:
p = transform_matrix.transform(p)
- sampled.append(p)
- if sampled:
- bbox.extend(sampled)
+ points.append(p)
+ if points:
+ bbox.extend(points)
elif e.dxftype() == 'LWPOLYLINE':
# Nutze virtuelle Entities (Linien/Bögen), inkl. Bulge-Unterstützung
@@ -653,142 +646,30 @@ def extract_scaling(matrix):
sx = math.sqrt(matrix[0, 0]**2 + matrix[0, 1]**2 + matrix[0, 2]**2)
sy = math.sqrt(matrix[1, 0]**2 + matrix[1, 1]**2 + matrix[1, 2]**2)
return sx, sy,
-def get_entity_bounding_box_2(entity, doc,src_doc,filename, transform_matrix=None):
- """
- Berechnet die Bounding Box einer einzelnen Entity
- Berücksichtigt INSERTs mit ihren Block-Inhalten
- """
- bbox = BoundingBox()
-
-
- try:
- if entity.dxftype() == 'LINE':
- start = Vec3(entity.dxf.start)
- end = Vec3(entity.dxf.end)
- if transform_matrix:
- start = transform_matrix.transform(start)
- end = transform_matrix.transform(end)
- bbox.extend([start, end])
-
- elif entity.dxftype() == 'CIRCLE':
- center = Vec3(entity.dxf.center)
- radius = float(entity.dxf.radius)
- num = 72
- sampled = []
- for i in range(num):
- ang = 2 * math.pi * (i / num)
- px = center.x + radius * math.cos(ang)
- py = center.y + radius * math.sin(ang)
- p = Vec3(px, py, center.z)
- if transform_matrix:
- p = transform_matrix.transform(p)
- sampled.append(p)
- if sampled:
- bbox.extend(sampled)
-
- elif entity.dxftype() == 'ARC':
- center = Vec3(entity.dxf.center)
- radius = float(entity.dxf.radius)
- start_deg = float(entity.dxf.start_angle)
- end_deg = float(entity.dxf.end_angle)
- start = math.radians(start_deg % 360)
- end = math.radians(end_deg % 360)
- def sweep_steps(s, e_):
- if e_ >= s:
- span = e_ - s
- else:
- span = (2 * math.pi - s) + e_
- return max(12, int(72 * span / (2 * math.pi)))
- steps = sweep_steps(start, end)
- sampled = []
- if end >= start:
- angles = [start + (end - start) * (i / steps) for i in range(steps + 1)]
- else:
- angles = []
- span1 = 2 * math.pi - start
- for i in range(int(steps * span1 / (2 * math.pi)) + 1):
- angles.append(start + span1 * (i / max(1, int(steps * span1 / (2 * math.pi)))))
- for i in range(1, steps - len(angles) + 2):
- angles.append(0.0 + end * (i / (steps - len(angles) + 1)))
- for ang in angles:
- px = center.x + radius * math.cos(ang)
- py = center.y + radius * math.sin(ang)
- p = Vec3(px, py, center.z)
- if transform_matrix:
- p = transform_matrix.transform(p)
- sampled.append(p)
- if sampled:
- bbox.extend(sampled)
-
- elif entity.dxftype() == 'LWPOLYLINE':
- for ve in entity.virtual_entities():
- ve_bbox = get_entity_bounding_box_2(ve, doc, src_doc, filename, transform_matrix)[0]
- if ve_bbox and ve_bbox.has_data:
- bbox.extend(ve_bbox)
-
- elif entity.dxftype() == 'POLYLINE':
- for ve in entity.virtual_entities():
- ve_bbox = get_entity_bounding_box_2(ve, doc, src_doc, filename, transform_matrix)[0]
- if ve_bbox and ve_bbox.has_data:
- bbox.extend(ve_bbox)
-
- elif entity.dxftype() == 'SPLINE':
- try:
- pts = list(entity.approximate(60))
- except Exception:
- try:
- pts = list(entity.flattening(1.0))
- except Exception:
- pts = []
- sampled = []
- for pt in pts:
- try:
- vx, vy = pt.x, pt.y
- except Exception:
- vx, vy = pt[0], pt[1]
- v = Vec3(vx, vy, 0)
- if transform_matrix:
- v = transform_matrix.transform(v)
- sampled.append(v)
- if sampled:
- bbox.extend(sampled)
-
- elif entity.dxftype() == 'TEXT':
- insert_point = Vec3(entity.dxf.insert)
- if transform_matrix:
- insert_point = transform_matrix.transform(insert_point)
- bbox.extend([insert_point])
-
- elif entity.dxftype() == 'INSERT':
- insert_bbox = calculate_insert_bounding_box(entity, doc,src_doc,filename, 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},{filename}")
-
- return bbox,
def calculate_insert_bounding_box(insert_entity, doc,src_doc,filename,parent_transform=None):
"""
Berechnet die Bounding Box eines INSERTs inklusive Block-Inhalt
"""
try:
- if filename == "0_BG071090_834372404.dxf":
- filetest = 3
- # Block-Definition finden
+ # Block-Definition finden
block_name = insert_entity.dxf.name
src_blk = src_doc.blocks[block_name]
-
+ if block_name == "ccLab_2025312125317867_51":
+ print(filename)
if block_name in doc.blocks:
- return BoundingBox()
+ dst_blk = doc.blocks[block_name]
+
+ new_insert = False
+
else:
dst_blk = doc.blocks.new(name=block_name)
-
+ new_insert = True
if block_name not in src_doc.blocks:
print(f"Warnung: Block '{block_name}' ")
return BoundingBox()
+
block_def = src_blk
@@ -806,10 +687,12 @@ def calculate_insert_bounding_box(insert_entity, doc,src_doc,filename,parent_tra
for block_entity in block_def:
- entity_bbox,= get_entity_bounding_box_2(block_entity, doc,src_doc,filename, combined_transform)
+ entity_bbox= get_entity_bounding_box(block_entity, doc,src_doc,filename, combined_transform)
if entity_bbox and entity_bbox.has_data:
- dst_blk.add_entity(block_entity.copy())
+ if new_insert:
+ dst_blk.add_entity(block_entity.copy())
block_bbox.extend(entity_bbox)
+
return block_bbox
except Exception as e:
@@ -855,9 +738,11 @@ def copy_entity_to_block(entity, target_block):
print(f"Fehler beim Kopieren von {entity.dxftype()}: {e}")
-def add_bounding_box_to_modelspace(msp, bbox):
+def add_bounding_box_to_modelspace(msp, bbox, centered=False):
"""
- Fügt die Bounding Box als Hilfslinien zum Modelspace hinzu
+ Fügt die Bounding Box als Hilfslinien zum Modelspace hinzu.
+ Wenn centered=True, wird das Rechteck um den Ursprung (0,0) zentriert und
+ ein roter Punkt in die Mitte gesetzt.
"""
if not bbox.has_data:
return
@@ -865,32 +750,47 @@ def add_bounding_box_to_modelspace(msp, bbox):
# Bounding Box Rechteck zeichnen
min_pt = bbox.extmin
max_pt = bbox.extmax
+ width = max_pt.x - min_pt.x
+ height = max_pt.y - min_pt.y
- # 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)
- ]
+ if centered:
+ # Rechteck um (0,0) zentriert
+ left = -width / 2.0
+ right = width / 2.0
+ bottom = -height / 2.0
+ top = height / 2.0
+ bbox_points = [
+ (left, bottom),
+ (right, bottom),
+ (right, top),
+ (left, top),
+ (left, bottom)
+ ]
+ # Roter Punkt in der Mitte
+ msp.add_circle(center=(0.0, 0.0), radius=max(0.5, min(width, height) * 0.01),
+ dxfattribs={"layer": "BOUNDING_BOX", "color": 1})
+ else:
+ # Ursprüngliche, nicht-zentrierte Bounding Box
+ 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_pos = Vec3(bbox_points[0][0], (bbox_points[2][1] if centered else 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)
+ text_pos2 = Vec3(bbox_points[0][0], (bbox_points[2][1] if centered else 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})
+ dxfattribs={'insert': text_pos2, 'layer': "BOUNDING_BOX", 'color': 1})
def format_bounding_box(bbox):