File size: 3,381 Bytes
4f55301
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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",
    )