Circle und arch logic bishen verbessert (funktieoniert noch nicht ganz), libary zum testen

This commit is contained in:
2025-09-09 15:32:30 +02:00
parent 3c4a149aa6
commit ca2c06c8f9
2 changed files with 71831 additions and 124152 deletions
+152 -81
View File
@@ -541,54 +541,94 @@ def get_entity_bounding_box(e, doc,src_doc,filename, transform_matrix=None,):
bbox.extend([start, end])
elif e.dxftype() == 'CIRCLE':
# Kreis durch Punktabtastung (robust bei Transformationen)
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)
])
radius = float(e.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 e.dxftype() == 'ARC':
# Vereinfachung: Bounding Box des vollständigen Kreises
# Bogen durch Punktabtastung zwischen Start- und Endwinkel
center = Vec3(e.dxf.center)
radius = e.dxf.radius
if transform_matrix:
center = transform_matrix.transform(center)
x,y =extract_scaling(transform_matrix)
x,y =extract_scaling(transform_matrix)
scale_factor = (x+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)
])
radius = 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)
# Schritte abhängig vom Sweep
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 = []
# 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)))
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 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)
# Nutze virtuelle Entities (Linien/Bögen), inkl. Bulge-Unterstützung
for ve in e.virtual_entities():
ve_bbox = get_entity_bounding_box(ve, doc, src_doc, filename, transform_matrix)
if ve_bbox and ve_bbox.has_data:
bbox.extend(ve_bbox)
elif e.dxftype() == 'POLYLINE':
points = []
for vertex in e.vertices:
pt = Vec3(vertex.dxf.location)
# 2D/3D Polylines ebenfalls über virtuelle Entities
for ve in e.virtual_entities():
ve_bbox = get_entity_bounding_box(ve, doc, src_doc, filename, transform_matrix)
if ve_bbox and ve_bbox.has_data:
bbox.extend(ve_bbox)
elif e.dxftype() == 'SPLINE':
# Approximation der Spline-Kurve
try:
pts = list(e.approximate(60))
except Exception:
try:
pts = list(e.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:
pt = transform_matrix.transform(pt)
points.append(pt)
if points:
bbox.extend(points)
v = transform_matrix.transform(v)
sampled.append(v)
if sampled:
bbox.extend(sampled)
elif e.dxftype() == 'TEXT':
# Vereinfachung: Nur Insert-Point berücksichtigen
@@ -633,63 +673,94 @@ def get_entity_bounding_box_2(entity, doc,src_doc,filename, transform_matrix=Non
elif entity.dxftype() == 'CIRCLE':
center = Vec3(entity.dxf.center)
radius = entity.dxf.radius
if transform_matrix:
center = transform_matrix.transform(center)
# Radius mit durchschnittlicher Skalierung anpassen
x,y =extract_scaling(transform_matrix)
scale_factor = (x+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)
])
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':
# Vereinfachung: Bounding Box des vollständigen Kreises
center = Vec3(entity.dxf.center)
radius = entity.dxf.radius
if transform_matrix:
center = transform_matrix.transform(center)
x,y =extract_scaling(transform_matrix)
scale_factor = (x+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)
])
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':
points = []
for point in entity.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)
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':
points = []
for vertex in entity.vertices:
pt = Vec3(vertex.dxf.location)
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:
pt = transform_matrix.transform(pt)
points.append(pt)
if points:
bbox.extend(points)
v = transform_matrix.transform(v)
sampled.append(v)
if sampled:
bbox.extend(sampled)
elif entity.dxftype() == 'TEXT':
# Vereinfachung: Nur Insert-Point berücksichtigen
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: Block-Inhalt mit Transformation berücksichtigen
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)
@@ -734,7 +805,7 @@ def calculate_insert_bounding_box(insert_entity, doc,src_doc,filename,parent_tra
block_bbox = BoundingBox()
for block_entity in block_def:
if block_entity is not "ATTDEF":
entity_bbox,= get_entity_bounding_box_2(block_entity, doc,src_doc,filename, combined_transform)
if entity_bbox and entity_bbox.has_data:
dst_blk.add_entity(block_entity.copy())