关于 parametric-3d-printing
这是一个基于 CadQuery 的技能,用于创建参数化 3D 打印模型并导出 STL。它涵盖需求收集、尺寸调研、分阶段预览与反馈,以及打印建议。
主要功能
- 01使用 CadQuery 参数化建模
- 02导出 STL 并渲染预览
- 03分阶段设计并收集反馈
- 04尺寸调研与可打印性检查
适用场景
- 01按实测尺寸设计组件外壳
- 02最终导出前迭代模型
- 03准备 FDM 打印模型
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ flowful-ai/ cad-skill --skill parametric-3d-printing安装后在 Claude Code 中输入/parametric-3d-printing确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.mdoutline_from_scan.pydesign-review.mdpreview.pyLICENSE.gitignoremesh_io.pygridfinity.pystl_to_3mf.pyrequirements.txtrun_cadquery_model.pyexamples/gridfinity_d110_bin.pymx_master3_bin_3x3.pytests/conftest.pytest_mesh_io.pytest_run_wrapper.pytest_stl_to_3mf.pytest_gridfinity.py详细介绍
使用 CadQuery 进行参数化 3D 打印
概述
此技能使用 CadQuery(Python)生成参数化 3D 模型,并将其导出为可直接切片的 STL 文件。CadQuery 是首选方案,因为它可通过 pip 安装,拥有符合 Python 风格的 API,并且处理复杂几何体(圆角、倒角、布尔运算、装配体)的能力优于其他方案。
设置
# CadQuery requires Python 3.10-3.12 (OCC kernel lacks 3.13+ wheels)
python3.12 -m venv .venv && source .venv/bin/activate
# Install CadQuery and preview dependencies
pip install cadquery trimesh pyrender Pillow numpy lxml
CadQuery 底层使用 OpenCASCADE 内核。trimesh、pyrender、Pillow 和 numpy 用于预览、分析和迭代流程;3MF writer(stl_to_3mf.py)依赖 lxml。无需显示服务器;所有内容都通过 pyrender 的离屏后端进行渲染。
如果 CadQuery 安装失败(OCC 内核构建错误),请尝试:
# Option 1: Use conda (CadQuery's officially recommended method)
conda install -c cadquery -c conda-forge cadquery
# Option 2: Use the pre-built wheels
pip install cadquery --find-links https://github.com/CadQuery/CadQuery/releases
现实世界尺寸调研
设计需要与真实产品(手机、充电器、PCB、连接器等)配合使用的物体时,请先通过网页搜索查找准确尺寸,再编写任何几何代码。不要猜测或使用近似值。即使相差 1-2mm,也可能导致部件无法使用。
需要调研的内容:
- 连接器/端口尺寸(USB-C:开口尺寸为 8.4 x 2.6mm,Lightning、桶形插孔)
- 设备尺寸(手机宽度/厚度、PCB 封装尺寸、充电器圆盘直径)
- 安装孔位图和螺丝尺寸(M2.5、M3 等)
- 标准组件规格(MagSafe 圆盘:直径 56mm、厚度 5.6mm)
- 电缆弯曲半径和应力消除要求
使用方法:
- 搜索“[product] dimensions mm”或“[component] datasheet”
- 对精度要求较高的尺寸,至少交叉核对 2 个来源
- 将查到的尺寸作为注释添加到 PARAMETERS 部分:
# MagSafe puck dimensions (source: Apple spec + iFixit teardown) puck_diameter = 56.0 # mm puck_thickness = 5.6 # mm - 如有疑问,给外部尺寸增加 0.3-0.5mm 的间隙
以下情况尤其需要注意:手机壳/支架、充电器支架、PCB 外壳、电缆管理、适配器接头,以及任何需要夹在现有产品上或包裹现有产品的物件。
核心工作流程
- 收集需求(见下文“需求收集”)
- 调研涉及的任何真实产品尺寸(见上文)
- 阶段 1:基础形状:构建外壳、预览并征求用户反馈
- 阶段 2:功能特征:添加功能细节、预览并征求用户反馈
- 阶段 3:最终交付:添加圆角、清理模型、最终预览 + STL + 打印建议
- 交付后提供参数调整选项
这是一个协作式、逐步展示的流程。不要离开一段时间后直接带着完成的模型回来。请在每个阶段向用户展示进展,并在继续之前采纳他们的反馈。
需求收集
在编写任何代码之前,先与用户通过对话逐项讨论以下主题。不要一次性抛出所有问题。先问最重要的问题,再根据回答追问。用户未指定时,采用合理的默认值。
这是什么? 对象类型、用途,以及它容纳/保护什么或连接到什么。首先要对对象形成清晰的整体认识。
关键尺寸 必须匹配的尺寸,例如 PCB 的大小、手机宽度、螺丝间距、它要环绕的物体直径等。这些尺寸不可妥协,并决定了其他所有设计。
安装与连接 它如何连接到其他物体?用螺丝(多大尺寸?)、卡扣、胶带、磁铁,还是独立放在桌面上?这会影响壁厚、螺丝柱位置和整体结构。
打印机与材料 用户使用什么打印机?(Bambu、Prusa、Ender 等)喷嘴尺寸是多少?使用什么材料(PLA、PETG、TPU)?这会直接影响公差、最小特征尺寸和设计限制。默认值:0.4mm 喷嘴、PLA、0.2mm 层高。
功能需求 通风/气流、防水性、布线、检修面板、可视窗口、堆叠、重量限制。只询问与对象相关的内容。
美观偏好 边缘要圆润还是锐利,偏简约还是工业风,以及颜色方面的考虑(会影响层纹的可见度)。简单询问即可。大多数用户更看重功能而非外观。
先询问前两项(是什么 + 尺寸),然后在相关时再询问安装方式和材料。只有在用户似乎在意美观,或美观会影响结构选择时,才询问外观偏好。
渐进式预览工作流
分阶段构建模型。每个阶段都要导出 STL、渲染预览、自行检查,然后向用户展示并征求反馈,再继续下一阶段。这样可以及早发现问题,并让用户参与其中。
预览流程(每个阶段都使用)
一步完成(运行脚本 + 渲染 + 将结果解析为 JSON):
python3 run_cadquery_model.py model.py --preview --strict
此流程会执行 model.py,找到它写入的 STL,渲染多视图预览,并输出包含 success、stdout、stderr、stl、preview 和 watertight 的 JSON 结果。使用 --strict 时,非水密网格会导致硬性失败。默认使用此流程:如果 success 为 false,读取 stderr 字段以修复 CadQuery 脚本,然后重新运行。
仅渲染(STL 已存在时):
python3 preview.py model.stl preview.png --views multi
然后查看预览图像,根据 design-review.md 中的清单自行检查,并在向用户展示之前修复发现的任何问题。
第 1 阶段:基本形状
构建基本外形:整体尺寸、外壳/壁面、底板。暂不添加开孔、圆角或细节。
- 编写包含参数和基本几何体的脚本
- 导出 STL 并渲染预览
- 自行检查:形状和尺寸看起来是否正确?底面是否平整,适合打印?
- 向用户展示预览:“这是基本形状。在我添加细节之前,这样看起来合适吗?”并附上关键尺寸。
- 等待反馈。如果用户希望修改,先在此阶段迭代,再继续下一阶段。
第 2 阶段:特征
添加功能细节:孔、开口、安装凸台、线缆槽、通风结构、卡扣、内部结构。
- 在脚本中添加特征
- 导出 STL 并渲染预览
- 自行检查:所有特征是否清晰可见?布尔运算结果是否干净?孔的位置是否正确?
- 向用户展示预览:“我已添加[特征列表]。最终定稿前还需要修改什么吗?”
- 等待反馈。按需迭代。
第 3 阶段:最终交付
进行收尾处理:圆角、倒角、清理边缘。全面检查模型是否适合打印。
- 添加圆角/倒角(先处理最大半径,在外壳完成后应用)
- 导出最终 STL 并渲染预览图
- 使用
design-review.md中的完整检查清单进行全面自检:目视检查、尺寸验证、可打印性分析 - 修复发现的任何问题,必要时重新导出
- 交付给用户:最终 STL + 预览图 + 打印建议(方向、支撑、填充率、材料说明)
**重要:**除非模型非常简单(例如带两个孔的平面支架),否则请勿跳过或合并阶段。对于带有封闭几何体、多个特征或严格公差的模型,请遵循全部三个阶段。
请阅读 design-review.md,了解完整的目视检查清单、尺寸验证代码和可打印性分析辅助工具。
打印建议(最终交付)
交付最终 STL 时,务必附上一行切片器配方和简短说明。Bambu Studio、PrusaSlicer 和 OrcaSlicer 已根据耗材和工艺预设设置了合理的默认值,因此无需重述每项切片器选项。只需告知用户与此模型相关的重要事项:材料、层高、壁数、填充率、支撑和摆放方向。除非模型有需要,否则请沿用以下基准设置。
基准配方(0.4mm 喷嘴,常见 FDM):
PLA,0.2mm 层高,2 层壁,15% 陀螺形填充,无支撑,摆放方向:平面朝下置于热床。
何时偏离基准设置:
- 承重支架/挂钩/铰链:将填充率提高到 25-40%,设置 3-4 层壁;考虑使用韧性优于 PLA 的 PETG。
- 薄装饰壁或花瓶:0 填充率,使用花瓶模式或 1 层壁。
- 高而窄的部件:添加裙边以增强热床附着力。
- 柔性部件(垫圈、握把):使用 TPU 95A,0.2mm 层高,降低速度,无支撑。
- 几何形状无法避免的功能性悬垂:使用树状支撑,或明确指出,让用户知晓。
- 户外/高温环境:使用 PETG 或 ASA,而非 PLA。
- 食品/皮肤接触:指出 FDM 部件不适用于食品接触,并建议使用食品级涂层。
交付时的格式:
Print settings: PLA, 0.2mm layer, 2 walls, 15% gyroid infill, no supports.
Orientation: place flat back side on the bed (front face up).
Why: the case has no overhangs above 45°, and 15% infill is plenty for a
TPU-adjacent protective shell.
控制在约 3 行。切勿罗列所有切片器设置;切片器已经知道这些信息。
脚本模板
脚本始终按以下结构编写:
import cadquery as cq
# ============================================================
# PARAMETERS - Edit these to customize the model
# ============================================================
# Overall dimensions
width = 60.0 # mm - outer width
depth = 40.0 # mm - outer depth
height = 25.0 # mm - outer height
# Wall and structural
wall = 2.0 # mm - wall thickness (min 1.2 for FDM)
corner_r = 2.0 # mm - corner fillet radius
# Tolerances
fit_clearance = 0.3 # mm - clearance for press-fit (adjust per printer)
# ============================================================
# MODEL
# ============================================================
result = (
cq.Workplane("XY")
.box(width, depth, height, centered=(True, True, False))
# ... build geometry using parameters above (bottom at Z=0)
)
# ============================================================
# EXPORT
# ============================================================
# Use tolerance=0.01, angularTolerance=0.1 for consistent tessellation
# across models. Defaults give coarser, wildly variable STL sizes.
cq.exporters.export(result, "output.stl",
tolerance=0.01, angularTolerance=0.1)
print(f"Exported: {width}x{depth}x{height}mm")
关键规则
参数优先
- 所有尺寸都放在顶部的 PARAMETERS 部分
- 使用描述性名称:
screw_hole_d,而不是d1 - 在注释中注明单位(始终使用 mm)
- 按关联参数分组,各组之间留空行并添加分节注释
适合打印的默认值
FDM 设计的关键默认值:
| 属性 | 最小值 | 推荐值 |
|---|---|---|
| 壁厚 | 1.2mm | 2.0mm |
| 层高 | 0.08mm | 0.2mm |
| 孔隙间隙 | 0.2mm | 0.3mm |
| 压配过盈量 | 0.1mm | 0.15mm |
| 最小特征尺寸 | 0.4mm(喷嘴) | 0.8mm |
| 圆角半径(底部) | 0.5mm | 1.0mm |
| 桥接跨度 | - | 无支撑时 < 20mm |
| 悬垂角度 | - | 相对垂直方向 < 45 度 |
**材料特定调整:**TPU 柔性较大,需要更大的间隙(约 0.5mm)。PETG 更容易粘连,因此配合间隙增加 +0.1mm。ABS 收缩约 0.5-0.7%,因此应略微增大关键尺寸。不确定时,请先打印一个小型测试件。
方向意识
- 设计时考虑打印方向
- 平坦的底面最适合打印
- 尽可能通过设计避开悬垂,减少支撑
- 底部边缘使用倒角而非圆角(圆角需要支撑)
- 在脚本中注明预期的打印方向
CadQuery 常用模式
需要了解的常用模式:
中空外壳(布尔减法,优先使用):
outer = (
cq.Workplane("XY")
.box(width, depth, height, centered=(True, True, False))
.edges("|Z").fillet(corner_r)
)
inner = (
cq.Workplane("XY")
.workplane(offset=floor_t)
.box(width - 2*wall, depth - 2*wall, height, centered=(True, True, False))
.edges("|Z").fillet(max(0.1, corner_r - wall))
)
result = outer.cut(inner)
螺钉凸台:
.pushPoints([(x, y)])
.circle(boss_od / 2).extrude(boss_h)
.pushPoints([(x, y)])
.hole(screw_d + fit_clearance)
卡扣:
# Cantilever beam with overhang hook
.workplane(offset=wall)
.moveTo(x, y).rect(clip_w, clip_l).extrude(clip_h)
# Add hook at tip with a small overhang (< 45 deg)
通风栅格:
.pushPoints(vent_positions)
.slot2D(slot_l, slot_w).cutThruAll()
其他模式:安装支架、走线槽、文本/标签(.text())、带定位销的多部件装配。
常见问题
- 挖空:优先使用布尔减法,而不是
.shell()。.shell()很脆弱,在带锥度的实体、放样形状、多个基本体的并集,以及带有许多圆角的形状上都会失败。可靠的模式是:
只有当实体是单个简单基本体(一个outer = cq.Workplane("XY").box(w, d, h, centered=(True, True, False)).edges("|Z").fillet(corner_r) inner = ( cq.Workplane("XY") .workplane(offset=floor_t) .box(w - 2*wall, d - 2*wall, h, centered=(True, True, False)) .edges("|Z").fillet(max(0.1, corner_r - wall)) ) result = outer.cut(inner).box()或.cylinder()),且所有侧面的壁厚均匀时,才考虑使用.shell()。如有疑问,请使用布尔减法。 - 构建顺序:先倒圆角,再切割,而不是先切割,再倒圆角。几何体仍为干净的基本体时就应用圆角。对实体切出孔、槽或凹腔后,再对产生的边倒圆角往往会失败,或产生糟糕的几何形状。倒角也遵循同样的规则。
- 圆角失败:按半径从大到小的顺序应用圆角。不要将圆角操作包在
try/except中,以便悄悄缩小半径。 圆角失败意味着几何形状或半径有误;请找出根本原因(半径过大、壁厚小于半径,或相邻面会因倒圆角而退化)并修复。 - 零厚度几何体:确保布尔运算不会产生无限薄的壁。在切割刚好穿过表面的实体时,加入一个小的 epsilon(0.01mm)。
- 坐标系:CadQuery 默认将几何体置于原点。对
.box()使用centered=(True, True, False),将底部放在 Z=0,这样.faces("<Z")始终是打印平台面。 - 孔的方向:默认情况下,
.hole()会贯穿整个零件。若要加工沉孔或沉头孔,请使用.cboreHole()或.cskHole()。 - 锥度方向:在
.extrude(taper=angle)中,正锥度角会使形状变窄(向内拔模),负锥度角会使形状向外扩张。这与许多人的预期相反。 - 放样不稳定:
.loft()在许多截面组合上都会失败。如果要在某个形状与其缩放版本之间过渡,请优先使用.extrude(taper=angle)。只有在需要在真正不同的轮廓之间过渡时(例如从圆形过渡到矩形),才使用.loft()。 - 导出错误/STL 不闭合:如果导出失败,或预览报告网格不闭合,则几何体无效(通常是布尔运算导致自相交,或存在零厚度面)。请修复原因,不要掩盖问题。运行
python3 preview.py model.stl --strict,以便在输出不闭合时明确报错。
导出
# STL (for slicing) - always set tolerance + angularTolerance for
# consistent tessellation. Defaults produce variable file sizes and
# over-tessellated glyphs on text features.
cq.exporters.export(result, "model.stl",
tolerance=0.01, angularTolerance=0.1)
# STEP (for further CAD editing)
cq.exporters.export(result, "model.step")
打印时始终导出 STL。如果用户可能想在 Fusion 360 或类似软件中编辑,也可以选择导出 STEP。
多零件模型
对于包含多个零件的模型(例如外壳 + 盖子):
# Export each part separately
cq.exporters.export(body, "enclosure_body.stl")
cq.exporters.export(lid, "enclosure_lid.stl")
文件名应描述清晰,让用户知道每个文件对应哪个零件。
Gridfinity 收纳盒
对于任何 Gridfinity 请求(适用于 42 mm 模块化网格系统的收纳盒、内衬、托架),请使用随附的 gridfinity.py 模块;切勿手动重建底座轮廓。该模块经过测试,符合规格(底座轮廓、堆叠凸缘、6×2 mm 磁铁孔、位于 26 mm 方形上的 M3 螺丝孔),并会针对参数提供有实际指导意义的错误信息。
工作流:
- 将此技能目录中的
gridfinity.py复制到模型脚本旁边(这是一个随附的模块;生成的脚本必须能够独立运行)。 - 使用
GridfinityBinAPI 构建:
import cadquery as cq
from gridfinity import GridfinityBin
bin = GridfinityBin(grid_x=3, grid_y=2, height_units=3,
stacking_lip=True, magnets=False)
bin.add_pocket(length=88.6, width=72.6, corner_r=(12.0, 1.0)) # cradle
# or: bin.add_compartments(cols=3, rows=2, scoop_r=6, label_tab=True)
# or: bin.add_polygon_pocket(points, depth=15, clearance=0.3)
# or: bin.add_cylinder_pocket(diameter=22, center=(42, 27), # finger well; overlapping pockets merge
# tilt=35, tilt_dir=(-1, 0), round_bottom=True) # smooth angled thumb scoop
# or: bin.add_finger_notch(side="+Y", width=20, offset=40) # offset slides it along the wall
result = bin.build()
cq.exporters.export(result, "my_bin.stl", tolerance=0.01, angularTolerance=0.1)
print(bin.summary())
速查表:
- 规格常量:网格间距为 42 mm,高度单位为 7 mm。所有派生数值(占地尺寸、凸缘高度、底面 Z 坐标、可用内腔深度)都可通过构建器获取:
bin.outer_w、bin.outer_d、bin.total_h、bin.floor_z、bin.max_depth,而bin.summary()会打印全部数值。请读取这些值,不要重新计算。 - 为物品设计收纳槽尺寸:每侧增加 0.3 mm 的配合间隙;如果物品需要轻松放入和取出,则每侧再增加约 1 mm。
- 让收纳槽贴合实际物品的形状:
outline_from_scan.py可从物品的 STL 扫描模型中提取最大截面轮廓(对齐、缩放至规格尺寸、切片、合并),可直接用于add_polygon_pocket。 - 高度选择:只需能容纳物品;物品可以高出边缘(参见
examples/gridfinity_d110_bin.py)。 magnets=True需要配合磁性底板使用;抽屉收纳盒请跳过此设置。
如果收纳槽过大、侧壁过薄或底面太浅而无法容纳螺丝,构建器会抛出带有具体错误信息的 GridfinityError(部分检查在 add_* 调用中触发,其余检查在 build() 中触发)。请修正参数;不要绕过验证。
如果用户需要模块不支持的设计(如底板、特殊凸缘),则改用自定义几何,但仍须以 gridfinity.py 中的规格常量为准。交付正式版本时,请将 gridfinity.py 与模型脚本一并提供。
提供参数调整选项
交付最终模型后,始终以汇总表的形式列出关键参数,并主动提出调整选项。这样用户无需重新说明整个设计,就能微调参数。
示例:
Here's your final model! Current parameters:
| Parameter | Value |
|----------------|--------|
| Width | 90 mm |
| Depth | 65 mm |
| Height | 30 mm |
| Wall thickness | 4 mm |
| Cable slot | 18 mm |
| Corner radius | 3 mm |
| Fit clearance | 0.3 mm |
Want me to adjust anything? Just say e.g. "make it 5mm taller" or "wider cable slot."
只列出用户可能希望更改的参数。跳过 eps 或 nozzle_d 等内部常量。按逻辑分组(先列尺寸,再列结构参数,最后列公差)。
输出检查清单
交付模型前,请确认:
- 所有尺寸均已参数化(几何代码中没有魔法数字)
- 壁厚 >= 1.2 mm
- 设计便于打印(尽量减少悬垂和支撑)
- 在注释中注明打印方向
- 已导出 STL,且文件大小合理(不为 0 字节)
- 参数名称清晰,并标明单位
- 脚本可无错误运行
- 已生成多视图预览并进行目视检查
- 预览中显示的形状、特征和比例均正确
- 边界框尺寸符合要求
- 已向用户交付 STL 和预览 PNG