stardust-coder's picture
mod
4f55301
import math
import ezdxf
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, Arc
def render_dxf_layer_to_png(
doc: object,
layer_name: str,
output_path: str = "layer.png",
dpi: int = 300,
line_width: float = 1.0,
padding_ratio: float = 0.05,
):
msp = doc.modelspace()
fig, ax = plt.subplots()
xs = []
ys = []
def update_bounds(x, y):
xs.append(x)
ys.append(y)
for e in msp:
if e.dxf.layer != layer_name:
continue
etype = e.dxftype()
if etype == "LINE":
x1, y1 = e.dxf.start.x, e.dxf.start.y
x2, y2 = e.dxf.end.x, e.dxf.end.y
ax.plot([x1, x2], [y1, y2], linewidth=line_width)
update_bounds(x1, y1)
update_bounds(x2, y2)
elif etype == "LWPOLYLINE":
pts = [(p[0], p[1]) for p in e.get_points()]
if len(pts) >= 2:
x = [p[0] for p in pts]
y = [p[1] for p in pts]
if e.closed:
x.append(pts[0][0])
y.append(pts[0][1])
ax.plot(x, y, linewidth=line_width)
for px, py in pts:
update_bounds(px, py)
elif etype == "POLYLINE":
pts = [(v.dxf.location.x, v.dxf.location.y) for v in e.vertices]
if len(pts) >= 2:
x = [p[0] for p in pts]
y = [p[1] for p in pts]
if e.is_closed:
x.append(pts[0][0])
y.append(pts[0][1])
ax.plot(x, y, linewidth=line_width)
for px, py in pts:
update_bounds(px, py)
elif etype == "CIRCLE":
cx, cy = e.dxf.center.x, e.dxf.center.y
r = e.dxf.radius
patch = Circle((cx, cy), r, fill=False, linewidth=line_width)
ax.add_patch(patch)
update_bounds(cx - r, cy - r)
update_bounds(cx + r, cy + r)
elif etype == "ARC":
cx, cy = e.dxf.center.x, e.dxf.center.y
r = e.dxf.radius
start_angle = e.dxf.start_angle
end_angle = e.dxf.end_angle
patch = Arc(
(cx, cy),
width=2 * r,
height=2 * r,
angle=0,
theta1=start_angle,
theta2=end_angle,
linewidth=line_width,
)
ax.add_patch(patch)
# γƒγ‚¦γƒ³γƒ‡γ‚£γƒ³γ‚°ζ›΄ζ–°γ―η°‘ζ˜“ηš„γ«ε††ε…¨δ½“γ§ε–γ‚‹
update_bounds(cx - r, cy - r)
update_bounds(cx + r, cy + r)
if not xs or not ys:
raise ValueError(f"Layer '{layer_name}' γ«ζη”»ε―Ύθ±‘γŒγ‚γ‚ŠγΎγ›γ‚“")
min_x, max_x = min(xs), max(xs)
min_y, max_y = min(ys), max(ys)
dx = max_x - min_x
dy = max_y - min_y
pad_x = max(dx * padding_ratio, 1e-6)
pad_y = max(dy * padding_ratio, 1e-6)
ax.set_xlim(min_x - pad_x, max_x + pad_x)
ax.set_ylim(min_y - pad_y, max_y + pad_y)
ax.set_aspect("equal", adjustable="box")
ax.axis("off")
plt.savefig(output_path, dpi=dpi, bbox_inches="tight", pad_inches=0)
plt.close(fig)
if __name__ == "__main__":
render_dxf_layer_to_png(
dxf_path="input.dxf",
layer_name="MY_LAYER",
output_path="layer.png",
)