1. 从一句话到三维模型:text-to-cad 到底在解决什么问题
第一次听到 text-to-cad 这个词,我的反应是:这不就是把“用嘴画图”这件事给工程化了么。干了十几年机械设计和参数化建模,我太清楚传统 CAD 工作流的痛点在哪——脑子里有个结构想法,得先打开软件、选基准面、画草图、约束、拉伸、倒角,一套流程下来半小时起步,改一个尺寸还得回头找特征树。text-to-cad 想干的事情很直接:你用自然语言描述一个零件或装配体,系统直接吐出可用的三维模型文件,常见格式就是 STEP、GLB、STL 这几种。
它解决的核心问题不是“替代 CAD 工程师”,而是把从想法到第一版几何这段最耗时的路给压缩掉。适合谁来用?我梳理了三类人:一是做概念设计的产品经理和工业设计师,需要快速把脑暴变成可视化的三维形体;二是机械/结构工程师,想用脚本批量生成标准件、支架、法兰这类重复性结构;三是做 3D 打印、游戏资产、AR 展示的开发者,需要 STL 或 GLB 这种轻量格式直接进下游管线。
这里必须先厘清三种格式的分工,很多人一上来就搞混。STEP是精确的边界表示(B-rep)格式,带完整的曲面数学定义,是 CAD 之间交换的“普通话”,能保留圆角、螺纹、孔位这些工程特征,适合后续做 CAM 加工、装配干涉检查。STL是三角网格,只有表面三角形面片,没有单位、没有特征、没有拓扑关系,是 3D 打印和快速预览的通用格式,但精度靠网格密度控制。GLB是 glTF 的二进制封装,专为实时渲染和 Web 展示设计,带材质、贴图、层级,适合放进网页、游戏引擎或 AR 场景。
text-to-cad 这类工具的价值,就在于它能根据你的用途,把同一份几何意图输出成不同格式。你要拿去加工,就导出 STEP;你要丢进切片软件打印,就导出 STL;你要放到网页里给客户转着看,就导出 GLB。这个“一次描述、多格式落地”的能力,才是它区别于传统建模的真正意义。
2. 拆解 text-to-cad 的技术链路:从文字到几何到底发生了什么
2.1 自然语言理解层:把“一个带四个安装孔的方形法兰”翻译成结构化参数
text-to-cad 的第一步不是画图,是语义解析。你输入的那句话,系统得先判断出这是哪一类几何体、有哪些关键尺寸、有哪些特征操作。比如“一个 100x100x10 的方形底板,四角各有一个直径 8 的通孔,孔中心距边缘 15”,这句话里藏着的信息量其实很大:基体是长方体,尺寸三个维度都给了,特征是四个圆柱孔,孔的定位方式是相对边缘的偏置。
我实测过几款工具,发现它们对自然语言的处理策略分两派。一派是模板匹配派,内置大量常见零件模板(法兰、支架、齿轮毛坯、外壳),你描述的关键词命中模板后,再抽取数字填参数。这派的好处是稳定、可预测,坏处是超出模板就抓瞎。另一派是代码生成派,把自然语言转成 CadQuery、OpenSCAD 或 build123d 这类参数化建模脚本,再执行脚本生成几何。这派灵活度高,理论上能表达任意结构,但对语言模型的代码能力要求高,容易生成跑不通的脚本。
从工程实践角度看,代码生成派更值得关注,因为它把“描述”和“几何”之间的中间层暴露出来了。你能看到它生成的脚本,能改、能复用、能版本管理。这比黑盒直接吐模型要可控得多。下面是一段典型的 CadQuery 风格脚本,描述的就是上面那个法兰:
import cadquery as cq result = ( cq.Workplane("XY") .box(100, 100, 10) .faces(">Z").workplane() .rect(70, 70, forConstruction=True) .vertices() .hole(8) )这段代码的逻辑很清晰:先建 100x100x10 的盒子,选顶面作为工作平面,画一个 70x70 的构造矩形(因为孔中心距边缘 15,所以 100-2×15=70),取四个顶点打直径 8 的孔。你看,自然语言里的“孔中心距边缘 15”被翻译成了构造矩形的尺寸,这就是语义到参数的映射过程。
2.2 几何内核层:为什么 STEP 比 STL 难生成得多
很多人不理解为什么 text-to-cad 工具导出 STEP 往往比导出 STL 慢,甚至有些工具只支持 STL。原因在几何内核。STL 只需要把表面三角化,本质上是采样离散点连成三角形,任何网格都能表达,对内核要求低。STEP 要求的是精确的 B-rep 表示,每个面得是解析曲面(平面、圆柱面、球面、样条面),面与面之间要有精确的交线,还要维护拓扑关系(哪个面属于哪个实体、哪条边连接哪两个面)。
这就好比 STL 是拿乐高积木拼一个球,远看像球,近看全是棱角;STEP 是直接用数学公式定义一个真正的球面。前者谁都能拼,后者需要一套完整的几何引擎。主流的内核有 OpenCASCADE(开源,CadQuery、FreeCAD 都用它)、Parasolid(西门子,SolidWorks、NX 用)、ACIS(达索,部分产品用)。text-to-cad 工具如果底层接的是 OpenCASCADE,那 STEP 导出基本没问题;如果只是自己写了个网格生成器,那大概率只能出 STL。
这里有个实操经验:如果你拿到的 STEP 文件在别的 CAD 里打开后特征树是空的、只有一个死实体,说明它是从网格反向拟合出来的,不是原生 B-rep。这种 STEP 能看不能改,做装配还行,做参数化修改就废了。判断方法很简单,在 FreeCAD 里打开,看模型树里是不是只有一个“Solid”节点,没有 Pad、Pocket 这些特征。
2.3 格式转换层:STL 转 STEP 为什么是个坑
热搜词里有个“sw中stl转stp”,这其实是很多人的真实需求,也是 text-to-cad 工作流里绕不开的一环。STL 转 STEP 本质上是逆向工程:从三角网格拟合出解析曲面。这个过程分几步走——先做网格去噪和简化,再识别平面区域和曲面区域,然后对每个区域拟合出平面或样条面,最后缝合成分片的 B-rep。
问题在于,拟合出来的曲面和原始设计意图往往对不上。一个原本是圆柱面的孔,网格化之后变成一圈三角形,拟合回来可能变成一个 NURBS 曲面,虽然形状接近,但不再是标准的圆柱特征,你没法直接改它的直径参数。所以我的建议是:能用原生 text-to-cad 直接出 STEP 的,就别走 STL 转 STEP 这条路。转换只适合那种“只有 STL 但必须进 CAD 做装配”的救急场景。
如果非转不可,SolidWorks 的 ScanTo3D 插件、FreeCAD 的“从网格创建形状”功能、以及一些在线转换服务都能做。但转换后一定要做几何校验:测量关键尺寸是否和原始设计一致,检查有没有破面、自交、法线翻转。我踩过的坑是,一个带内螺纹的 STL 转成 STEP 后,螺纹全变成了光滑圆柱,因为网格精度根本不足以表达螺纹牙型。
3. 实操:用 text-to-cad 思路从零生成一个可打印的支架
3.1 需求拆解与描述撰写
假设我要做一个 L 形支架,用来把一个小电机固定在桌面上。这个需求用自然语言怎么描述?我总结了一个五要素描述法:基体形状、关键尺寸、特征操作、定位关系、用途约束。套进去就是:
“一个 L 形支架,底板 60x40x5,立板高 50、厚 5,底板和立板垂直。底板上开两个直径 4.5 的沉头孔,孔中心距底板左右边缘各 10,距后边缘 10。立板上开一个直径 22 的电机轴孔,孔中心距立板顶面 15,距立板左右居中。所有外角倒 R3 圆角。”
这段话里,基体是 L 形(两个长方体布尔并集),尺寸全给了,特征是沉头孔和通孔,定位用边缘偏置和居中描述,用途约束是“可打印”,意味着不能有悬垂超过 45 度的面、壁厚不能太薄。
3.2 生成脚本与参数计算
如果用 CadQuery 来实现,脚本大概长这样:
import cadquery as cq # 底板 base = cq.Workplane("XY").box(60, 40, 5) # 立板,沿 Y 轴后边缘立起 wall = ( cq.Workplane("XY") .box(60, 5, 50) .translate((0, -17.5, 25)) ) bracket = base.union(wall) # 底板沉头孔 bracket = ( bracket.faces("<Z").workplane() .pushPoints([(-20, 10), (20, 10)]) .cboreHole(4.5, 9, 2.5) ) # 立板电机孔 bracket = ( bracket.faces(">Y").workplane() .center(0, 10) .hole(22) ) # 倒圆角 bracket = bracket.edges("|Z").fillet(3) cq.exporters.export(bracket, "bracket.step") cq.exporters.export(bracket, "bracket.stl")这里有几个参数计算需要说明。立板的 Y 方向位置:底板 Y 范围是 -20 到 20,立板厚 5,要贴在底板后边缘,所以立板中心 Y = -20 + 2.5 = -17.5。立板 Z 方向:底板顶面在 Z=5,立板高 50,所以立板中心 Z = 5 + 25 = 30,但上面代码写的是 25,因为 box 的 translate 是相对原点的,实际应该按立板底面在 Z=5 算,中心在 Z=5+25=30。这种细节就是实操中容易翻车的地方,布尔运算的坐标系一定要在脑子里过一遍。
电机孔的位置:立板顶面在 Z=55,孔中心距顶面 15,所以孔中心 Z=40。立板 Y 方向中心是 -17.5,孔要打在立板面上,所以工作平面选>Y面,center 的偏移量按立板局部坐标算。
3.3 导出与下游验证
生成完 STEP 和 STL 后,别急着丢切片软件。我的验证流程是三步:
- STEP 回灌 CAD:把 STEP 拖进 FreeCAD 或 SolidWorks,检查实体是否有效(不是壳、没有自交),测量关键尺寸。
- STL 网格检查:用 Meshmixer 或 Netfabb 打开 STL,看有没有非流形边、翻转法线、孔洞。3D 打印最怕的就是模型不水密,切片出来全是洞。
- 切片预览:丢进 Cura 或 PrusaSlicer,看悬垂角度、支撑需求、打印时间。L 形支架的立板和底板交界处是内直角,打印时容易翘边,可以考虑在脚本里加一个 R3 的根部圆角。
这里补一句,GLB 导出在 CadQuery 里不是原生支持的,得先导出 STL 再用 Blender 或 trimesh 转 GLB。如果 text-to-cad 工具直接支持 GLB,那它内部多半是走了一遍网格化加材质打包。
4. 踩坑实录:text-to-cad 实操中最容易翻车的六个地方
4.1 单位问题:你的 10 到底是毫米还是英寸
这是最隐蔽的坑。自然语言里说“一个 10 的孔”,系统默认单位可能是毫米,也可能是英寸,还可能是无量纲的单位。STEP 文件本身带单位定义,但 STL 不带——STL 只有数值,没有单位。我见过有人生成的 STL 丢进切片软件,发现模型只有 0.4 毫米高,因为工具默认单位是英寸,10 英寸被当成 10 毫米处理了。
解决办法:在描述里显式带单位,比如“直径 10mm 的孔”“底板长 60mm”。如果工具支持配置,在设置里锁定单位为毫米。导出 STL 后,在切片软件里先看包围盒尺寸,和预期对不上就检查单位缩放。
4.2 布尔运算失败:为什么你的孔打不穿
text-to-cad 生成复杂结构时,布尔运算是重灾区。两个实体做差集,如果面与面恰好共面、或者交线退化成一个点,内核就可能报错或产生无效几何。比如你在底板边缘打一个孔,孔壁和底板侧面恰好相切,这种“临界接触”最容易出问题。
我的经验是留冗余:孔不要打在正好和边缘相切的位置,往里缩 0.5mm;两个实体做并集时,让它们有明确的重叠体积,不要只是面贴面。如果工具生成的脚本能改,就在布尔操作前加一个微小的偏移量。
4.3 圆角顺序:先倒角还是先打孔
这个顺序问题在传统 CAD 里是老生常谈,在 text-to-cad 里同样存在。如果你先给底板四角倒 R3 圆角,再在靠近角落的位置打孔,孔可能会切到圆角面,导致几何复杂化甚至失败。正确的顺序通常是:先做主体形状,再打孔和开槽,最后倒圆角。因为圆角是“收尾操作”,它需要处理的是已经确定的边。
但也不是绝对。有些圆角必须在打孔前做,比如孔口倒角,那是孔的特征的一部分。判断标准是:这个圆角属于哪个特征?属于主体的,主体做完就倒;属于孔的,打完孔再倒。
4.4 网格精度:STL 的弦高和角度公差怎么设
导出 STL 时,工具通常会让你设两个参数:线性偏差(弦高)和角度偏差。弦高控制曲面被三角化的精细程度,值越小三角形越多、模型越精细、文件越大。角度偏差控制相邻三角形法线的最大夹角。
对于 3D 打印,我的常用设置是弦高 0.01mm、角度偏差 1 度。对于只做预览的 GLB,弦高 0.1mm 就够了。设得太细,STL 文件几百兆,切片软件卡死;设得太粗,圆柱变成多边形,装配时孔轴配合直接卡住。有个快速判断方法:看圆柱面的三角形数量,直径 10mm 的孔,圆周至少要有 32 个分段才看起来圆。
4.5 特征树丢失:为什么改不了参数
前面提过,text-to-cad 如果输出的是“死实体”STEP,你在 CAD 里是改不了参数的。但即使是原生 B-rep,如果工具没有保留特征历史,你也只能改整体尺寸,改不了单个孔的直径。这是目前这类工具的通病——它们生成的是最终几何,不是参数化特征树。
如果你需要后续可编辑,有两条路:一是让工具输出建模脚本(CadQuery/OpenSCAD),你在脚本层面改参数重新生成;二是把 STEP 导入 CAD 后,用“特征识别”功能把孔、圆角、拉伸识别成特征。后者成功率看模型复杂度,简单零件还行,复杂装配基本没戏。
4.6 常见问题速查表
| 问题现象 | 可能原因 | 排查与解决 |
|---|---|---|
| 导出的 STL 尺寸不对 | 单位不一致 | 检查工具单位设置,描述中显式带 mm |
| STEP 在 CAD 里打开是空壳 | 只导出了曲面没导出实体 | 检查是否闭合实体,重新导出 |
| 孔打不穿或布尔失败 | 临界接触、共面 | 留 0.5mm 冗余,避免相切 |
| 圆角处破面 | 圆角半径大于相邻壁厚 | 减小圆角半径或加厚壁厚 |
| STL 切片后全是洞 | 网格不水密、法线翻转 | 用 Netfabb 修复,检查流形性 |
| GLB 在网页里显示全黑 | 法线或材质缺失 | 重新计算法线,补默认材质 |
| 模型能看不能改 | 特征树丢失 | 改用脚本输出,或做特征识别 |
| 生成速度极慢 | 网格精度设太高 | 降低弦高和角度偏差 |
5. 工具选型与工作流搭建:把 text-to-cad 接进现有管线
5.1 三类工具的定位差异
市面上的 text-to-cad 工具,我大致分成三类。第一类是对话式建模助手,你一句句描述,它一步步生成,适合概念探索,但精度和可复现性一般。第二类是脚本生成器,把自然语言转成 CadQuery/OpenSCAD 代码,适合工程师,可控性最强。第三类是专用零件生成器,针对齿轮、法兰、支架等特定品类,输入参数直接出模型,精度最高但适用范围窄。
选型逻辑很简单:要精度和可编辑性,选脚本生成器;要速度和易用性,选对话式;要批量做标准件,选专用生成器。我个人的主力工作流是脚本生成器加 CadQuery,因为生成的脚本能进 Git 做版本管理,改一个参数重新跑一遍,比在 GUI 里点来点去快得多。
5.2 与现有 CAD 的衔接
text-to-cad 生成的 STEP,最终多半要进 SolidWorks、Fusion 360、中望 CAD 这些软件做后续处理。衔接时注意两点:一是坐标系对齐,生成的模型原点最好在零件的某个基准角或中心,方便装配时定位;二是命名规范,导出的文件按“零件名_版本_日期”命名,别用默认的 output.step,不然十个文件放一起分不清。
如果要做装配,建议在 text-to-cad 里分别生成每个零件,导出 STEP 后在 CAD 里做配合。不要试图用一句话描述整个装配体,目前的工具对多体装配的支持还很弱,容易生成一堆位置错乱的实体。
5.3 批量生成的思路
text-to-cad 真正体现效率的地方是批量生成。比如你要做一系列不同长度的支架,长度从 50 到 200,每 10mm 一档。用脚本生成器,写一个循环,改一个参数,跑十六次,十六个 STEP 文件就出来了。这在传统 CAD 里得手动改尺寸、另存为,重复十六遍。
import cadquery as cq for length in range(50, 201, 10): bracket = ( cq.Workplane("XY") .box(length, 40, 5) .faces(">Z").workplane() .rect(length - 20, 20, forConstruction=True) .vertices() .hole(4.5) ) cq.exporters.export(bracket, f"bracket_{length}mm.step")这段代码跑完,你就有了十六个不同长度的支架 STEP 文件。这种批量能力,才是 text-to-cad 对工程师最大的价值——把重复劳动交给脚本,把精力留给真正的设计决策。
6. 我对 text-to-cad 的实际使用体会
用了大半年这类工具,我的真实感受是:它现在的能力边界很清晰——适合做第一版几何、适合做标准件批量生成、适合做概念可视化,但不适合做最终交付的精密工程图。你让它生成一个带公差配合、表面粗糙度标注、形位公差的零件,它做不到,这些还是得回传统 CAD。
但它在工作流前端的位置已经站稳了。我现在接到一个新需求,第一反应不是打开 SolidWorks,而是先写一段描述,让 text-to-cad 出个大概形状,看看比例和结构合不合理。确认方向对了,再导 STEP 进 CAD 精修。这个习惯帮我省掉了大量“打开软件-建草图-发现方向不对-删掉重来”的循环。
最后分享一个小技巧:描述零件时,先描述整体,再描述局部,最后描述修饰。整体是基体和主要尺寸,局部是孔、槽、凸台这些特征,修饰是圆角、倒角、拔模。这个顺序和大多数建模脚本的执行顺序一致,生成的几何也最稳定。反过来,如果你一上来就说“四个角倒 R3 圆角”,系统可能还没搞清楚主体是什么,圆角就无处可倒。