Python 生成螺旋线圈图
創建於:2025年1月18日
創建於:2025年1月18日
用python生成一个svg格式的线圈图形。线宽10mil,间距10mil,至少7匝,圆角矩形,长80mm 宽30mm,线圈间距需要保证严格一致,且只有一条螺旋形走线
下面的示例 Python 脚本会生成一个带有单条螺旋线(矩形螺旋,带圆角)的 SVG 文件,满足如下要求:
脚本思路简要说明:
单位转换
螺旋生成逻辑
圆角实现
A rx,ry 0 0 1 x_end,y_end
命令(或者更常见的 a
命令)来画 90° 的圆角弧。输出
coil.svg
文件,可用浏览器或矢量图软件查看。下面给出一个可运行的完整示例代码,使用纯字符串方式写入 <path>
命令(也可以使用诸如 svgwrite
的库来构造),供参考和按需修改:
python#!/usr/bin/env python3 # -*- coding: utf-8 -*- import math def mil_to_mm(mil): return mil * 0.0254 def generate_spiral_coil_svg( filename="coil.svg", outer_length_mm=80.0, # 外框总长 (mm) outer_width_mm=30.0, # 外框总宽 (mm) line_width_mil=10.0, # 线宽 (mil) spacing_mil=10.0, # 线与线的间距 (mil) turns=7 # 匝数(至少 7 匝) ): """ 生成一个矩形螺旋(带圆角)的 SVG 文件。 线宽和间距都以 mil 为单位给出,外框尺寸以 mm 为单位给出。 """ # 1. 基本参数换算 line_width = mil_to_mm(line_width_mil) # 线宽 (mm) spacing = mil_to_mm(spacing_mil) # 净距 (mm) offset = line_width + spacing # 每匝向内收缩的总距离 (mm) # 圆角半径(可根据需求微调,这里设为线宽的一半) corner_radius = line_width * 0.5 # 2. 初始化外圈矩形范围 x_min, y_min = 0.0, 0.0 x_max, y_max = outer_length_mm, outer_width_mm # 3. 准备 SVG 的头部 # 注意:width/height 只是最终渲染视口;真正坐标范围用 viewBox 控制方便。 svg_header = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{outer_length_mm}mm" height="{outer_width_mm}mm" viewBox="0 0 {outer_length_mm} {outer_width_mm}" version="1.1"> ''' svg_footer = "</svg>" # 4. 我们用一个 <path> 元素来承载整条螺旋 # 先用列表收集命令,最后拼成一个完整的 d="..." 字符串 path_cmds = [] # 当前的“笔”位置,从外框左上角(带一点圆角偏移)开始 # 先移动到 (x_min + corner_radius, y_min) 作为起点 cx = x_min + corner_radius cy = y_min path_cmds.append(f"M {cx:.4f},{cy:.4f}") # MoveTo # 一共需要走 turns 匝,每匝有 4 条边(含 4 个圆角) # 总共 = turns * 4 边 total_sides = turns * 4 for i in range(total_sides): # 判断当前要走的是第几个边:0=向右,1=向下,2=向左,3=向上 (循环) direction = i % 4 # 计算本边可走的“有效长度” (扣除 2 * corner_radius) if direction in (0, 2): # 水平边 length = (x_max - x_min) - 2.0 * corner_radius else: # 垂直边 length = (y_max - y_min) - 2.0 * corner_radius # 根据方向,计算终点坐标 if direction == 0: # 向右 nx = cx + length ny = cy # 边的末端 path_cmds.append(f"L {nx:.4f},{ny:.4f}") # 下一个圆角的终点 # 这里走的是“右上角”向“右下角”的那段 90° 弧 # 圆心在 (nx, ny + corner_radius),我们只需指定终点(nx, ny + corner_radius) # 在 SVG path 中,画弧命令 A 的语法: # A rx,ry x-axis-rotation large-arc-flag sweep-flag x,y # 这里 rx=ry=corner_radius, 其余标志可根据方向确定,这里用 0 0 1 (顺时针小弧) nx2 = nx ny2 = ny + corner_radius path_cmds.append(f"A {corner_radius:.4f},{corner_radius:.4f} 0 0 1 {nx2:.4f},{ny2:.4f}") elif direction == 1: # 向下 nx = cx ny = cy + length path_cmds.append(f"L {nx:.4f},{ny:.4f}") # 右下角→左下角 那段圆角 (顺时针) nx2 = nx - corner_radius ny2 = ny path_cmds.append(f"A {corner_radius:.4f},{corner_radius:.4f} 0 0 1 {nx2:.4f},{ny2:.4f}") elif direction == 2: # 向左 nx = cx - length ny = cy path_cmds.append(f"L {nx:.4f},{ny:.4f}") # 左下角→左上角 圆角 nx2 = nx ny2 = ny - corner_radius path_cmds.append(f"A {corner_radius:.4f},{corner_radius:.4f} 0 0 1 {nx2:.4f},{ny2:.4f}") else: # direction == 3,向上 nx = cx ny = cy - length path_cmds.append(f"L {nx:.4f},{ny:.4f}") # 左上角→右上角 圆角 nx2 = nx + corner_radius ny2 = ny path_cmds.append(f"A {corner_radius:.4f},{corner_radius:.4f} 0 0 1 {nx2:.4f},{ny2:.4f}") # 更新“笔”坐标到画完圆角之后 cx, cy = nx2, ny2 # 每走完 4 条边,说明完成一匝,需要缩小边界,进入下一匝 if (i + 1) % 4 == 0: x_min += offset y_min += offset x_max -= offset y_max -= offset # 把所有路径命令合并成字符串 spiral_path = " ".join(path_cmds) # 5. 组装完整 SVG,注意设置 stroke-width 为线宽 # fill="none" 只画线条不填充 svg_content = ( svg_header + f' <path d="{spiral_path}" ' f'stroke="black" ' f'stroke-width="{line_width:.4f}" ' f'fill="none" />\n' + svg_footer ) # 6. 输出到文件 with open(filename, "w", encoding="utf-8") as f: f.write(svg_content) print(f"已生成 SVG 文件: {filename}") if __name__ == "__main__": generate_spiral_coil_svg( filename="coil.svg", # 输出文件名 outer_length_mm=80.0, # 整体长度 80 mm outer_width_mm=30.0, # 整体宽度 30 mm line_width_mil=10.0, # 线宽 10 mil spacing_mil=10.0, # 线距 10 mil turns=7 # 匝数(至少 7 匝) )
螺旋路径的核心在于:
<path>
中“转角 → 缩小边界 → 再转角”,形成单条连续的螺旋。x_min, y_min, x_max, y_max
向内缩(offset = 线宽 + 间距
),开始下一匝。圆角的绘制
A rx ry 0 0 1 end_x end_y
命令(大写 A
表示绝对坐标)。large-arc-flag
和 sweep-flag
配合来控制画圆弧的大小及方向。0 0 1
。如果希望逆时针,可改为 0 0 0
,可根据需求微调。线宽(line_width) 和视口(viewBox)
stroke-width
设置为转换后(0.254 mm)的数值。width="80mm" height="30mm"
并 viewBox="0 0 80 30"
可以让该 SVG 文件在不同软件中都按 80×30 mm 的物理尺寸比例呈现(若支持查看实际毫米尺寸时)。运行后,会在同目录下生成 coil.svg
,即可用浏览器或矢量图软件(如 Inkscape、Illustrator 等)打开查看。根据需要可自行调整参数(例如改圆角半径、匝数、线宽等)。这样就可以得到一个严格保持线间距、线宽、具有圆角拐角、单条螺旋线的矩形线圈图形。
这个不对,线圈只有右边和下边两部分,且不是圆角矩形
下面给出一段改进后的 Python 示例代码,能够生成单一连续路径的「圆角矩形螺旋线圈」(spiral coil),并且保证:
关键改动:通过显式地按「上边 + 右上圆角 → 右边 + 右下圆角 → 下边 + 左下圆角 → 左边 + 左上圆角」的顺序画一圈,然后向内偏移,依次画若干圈,且不使用
Z
或closepath
,从而形成一条连续的螺旋路径。
每个圆角都使用了A rx ry 0 0 1 x_end y_end
形式的绝对弧指令,并且根据顺时针方向(Clockwise)指定sweep-flag=1
。这样四个角都是顺时针 90° 的圆角弧。
请将下面的脚本保存为 spiral_coil.py
(或其他你喜欢的名字),然后执行:
python#!/usr/bin/env python3 # -*- coding: utf-8 -*- def mil_to_mm(mil): """1 mil = 0.0254 mm""" return mil * 0.0254 def generate_spiral_coil_svg( filename="coil.svg", outer_length_mm=80.0, # 外框总长 (mm) outer_width_mm=30.0, # 外框总宽 (mm) line_width_mil=10.0, # 线宽 (mil) spacing_mil=10.0, # 线间净距 (mil) turns=7 # 需要的匝数 ): """ 生成一个矩形螺旋(带圆角)的 SVG 文件。 线宽和间距以 mil 为单位;外框尺寸以 mm 为单位。 """ import math # 1. 单位换算 line_width_mm = mil_to_mm(line_width_mil) # 线宽 (mm) spacing_mm = mil_to_mm(spacing_mil) # 两条线中心线之间的“净距” (mm) offset = line_width_mm + spacing_mm # 每匝向内偏移的距离 (mm) # 2. 圆角半径 # 可以根据需求微调,这里可设为线宽/2 或线宽本身等 corner_radius = line_width_mm * 0.5 # 3. 准备 SVG 的头/尾 # 注意: width/height 用于显示大小,viewBox 控制实际坐标空间 svg_header = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{outer_length_mm}mm" height="{outer_width_mm}mm" viewBox="0 0 {outer_length_mm} {outer_width_mm}" version="1.1"> ''' svg_footer = "</svg>" # 4. 外框初始边界 x_min, y_min = 0.0, 0.0 x_max, y_max = outer_length_mm, outer_width_mm # 5. 准备收集 path 命令的列表 path_cmds = [] # 先把“笔”移动到第一个圈的起点:外框左上角处的 (x_min+corner_radius, y_min) cx = x_min + corner_radius cy = y_min path_cmds.append(f"M {cx:.4f},{cy:.4f}") # 做 turns 圈,每圈包含顺时针 4 边 + 4 个圆角 for ring_index in range(turns): # 每一圈包含 4 个 segment: # # Segment 0: 上边 + 右上圆角 # line: (x_min+corner_radius, y_min) → (x_max-corner_radius, y_min) # arc : → (x_max, y_min+corner_radius) # # Segment 1: 右边 + 右下圆角 # line: (x_max, y_min+corner_radius) → (x_max, y_max-corner_radius) # arc : → (x_max-corner_radius, y_max) # # Segment 2: 下边 + 左下圆角 # line: (x_max-corner_radius, y_max) → (x_min+corner_radius, y_max) # arc : → (x_min, y_max-corner_radius) # # Segment 3: 左边 + 左上圆角 # line: (x_min, y_max-corner_radius) → (x_min, y_min+corner_radius) # arc : → (x_min+corner_radius, y_min) # # 最后落点又回到 (x_min+corner_radius, y_min),然后进行下一圈向内偏移。 # # 注意这里我们“并不关闭路径”,而是直接在下一个圈继续画,从而形成一个连续的螺旋。 # 为了避免在剩余空间不足时画错,可判断当前 x_min < x_max、y_min < y_max 等 # 若确实空间不够,可 break。但本示例默认用户给的尺寸足够容纳设定匝数。 # --- Segment 0: 上边 + 右上角 --- # line 到 (x_max - corner_radius, y_min) x_line_end = x_max - corner_radius y_line_end = y_min path_cmds.append(f"L {x_line_end:.4f},{y_line_end:.4f}") # arc 到 (x_max, y_min + corner_radius) arc_end_x = x_max arc_end_y = y_min + corner_radius # A rx ry x-axis-rot large-arc-flag sweep-flag x y # large-arc-flag=0 (小弧), sweep-flag=1 (顺时针) path_cmds.append(f"A {corner_radius:.4f},{corner_radius:.4f} 0 0 1 {arc_end_x:.4f},{arc_end_y:.4f}") # 更新 (cx, cy) cx, cy = arc_end_x, arc_end_y # --- Segment 1: 右边 + 右下角 --- # line 到 (x_max, y_max - corner_radius) x_line_end = x_max y_line_end = y_max - corner_radius path_cmds.append(f"L {x_line_end:.4f},{y_line_end:.4f}") # arc 到 (x_max - corner_radius, y_max) arc_end_x = x_max - corner_radius arc_end_y = y_max path_cmds.append(f"A {corner_radius:.4f},{corner_radius:.4f} 0 0 1 {arc_end_x:.4f},{arc_end_y:.4f}") cx, cy = arc_end_x, arc_end_y # --- Segment 2: 下边 + 左下角 --- x_line_end = x_min + corner_radius y_line_end = y_max path_cmds.append(f"L {x_line_end:.4f},{y_line_end:.4f}") # arc 到 (x_min, y_max - corner_radius) arc_end_x = x_min arc_end_y = y_max - corner_radius path_cmds.append(f"A {corner_radius:.4f},{corner_radius:.4f} 0 0 1 {arc_end_x:.4f},{arc_end_y:.4f}") cx, cy = arc_end_x, arc_end_y # --- Segment 3: 左边 + 左上角 --- x_line_end = x_min y_line_end = y_min + corner_radius path_cmds.append(f"L {x_line_end:.4f},{y_line_end:.4f}") # arc 到 (x_min+corner_radius, y_min) arc_end_x = x_min + corner_radius arc_end_y = y_min path_cmds.append(f"A {corner_radius:.4f},{corner_radius:.4f} 0 0 1 {arc_end_x:.4f},{arc_end_y:.4f}") cx, cy = arc_end_x, arc_end_y # 至此,一圈完成,最终点又回到 (x_min + corner_radius, y_min) # 6. 向内偏移进入下一圈 x_min += offset y_min += offset x_max -= offset y_max -= offset # 移动“笔”坐标到下一圈的起始位置(新的 x_min+corner_radius, y_min), # 以保证连续性 (不 ClosePath!) # 注意:我们已经在上一步的 arc 把笔带回了 (x_min+corner_radius, y_min) 的“旧位置”。 # 但 x_min 刚刚变了,所以需要显式再移动一下。 new_cx = x_min + corner_radius new_cy = y_min path_cmds.append(f"M {new_cx:.4f},{new_cy:.4f}") # 把命令合并 spiral_path = " ".join(path_cmds) # 7. 整理出最终 SVG 内容 # - stroke-width 用实际 mm 大小 # - fill="none" 只画线,不填充 svg_content = ( svg_header + f' <path d="{spiral_path}" ' + f'stroke="black" stroke-width="{line_width_mm:.4f}" fill="none" />\n' + svg_footer ) # 8. 写入文件 with open(filename, "w", encoding="utf-8") as f: f.write(svg_content) print(f"已生成 SVG 文件: {filename}") if __name__ == "__main__": generate_spiral_coil_svg( filename="coil.svg", outer_length_mm=80.0, # 外框长度 80 mm outer_width_mm=30.0, # 外框宽度 30 mm line_width_mil=10.0, # 线宽 10 mil spacing_mil=10.0, # 线间距 10 mil turns=7 # 匝数至少 7 匝 )
螺旋实现思路
closepath (Z)
将这圈封闭,而是在最后一个圆角后,直接把“笔”移动到下一圈起始坐标,然后缩小 x_min,y_min,x_max,y_max
再画下一圈,从而形成单一螺旋。圆角方向
A r,r 0 0 1 end_x,end_y
,表示顺时针(sweep-flag=1
)的小弧(90°)。sweep-flag
改为 0
;但一般常见的矩形转角是顺着外沿的顺时针/逆时针。只要四个角一致即可。线宽与间距
offset = line_width_mm + spacing_mm
,表示连续匝之间的中心线间距 = 线宽 + 净间隙。offset
必须至少是 line_width_mm + spacing_mm
,否则会出现匝间重叠或不满足最小净距要求。拐角半径 (corner_radius)
corner_radius = line_width_mm * 0.5
。若出现最后几圈无法再画出完整矩形
检查实际生成的图
coil.svg
后,用浏览器或 Inkscape / Illustrator 等矢量软件打开。<svg width="..." height="..." viewBox="...">
中的宽高以便看清细节。这样即可得到一个真正的矩形螺旋线(单条路径、带圆角、间距固定),满足「线宽 10mil、净距 10mil、匝数不少于 7」的需求。