Inserts richtig in die Bounding box reingetan

This commit is contained in:
2025-09-10 15:32:06 +02:00
parent ca2c06c8f9
commit e3494530ea
+80 -180
View File
@@ -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):