ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

text-to-cad 实战:从自然语言到 STEP/STL/GLB 的完整链路

text-to-cad 实战:从自然语言到 STEP/STL/GLB 的完整链路

1. 从一段文字到三维模型:text-to-cad 到底在解决什么问题

第一次听到 “text-to-cad” 这个词,我脑子里蹦出来的画面是:对着电脑敲一句“给我画一个长宽高 100×60×30 的带圆角法兰盘”,然后屏幕上直接出现一个可以旋转、可以导出、可以丢进切片软件或者丢进装配体的三维实体。这个场景放在五年前,做机械设计的朋友大概率会回你一句“想得美”;但放到今天,它已经是一条能跑通的技术链路,只不过链路中间有很多细节需要人去兜底。

先把概念说清楚。text-to-cad 指的是用自然语言描述作为输入,自动或半自动地生成 CAD 模型数据的一类方法。这里的 CAD 不是单指某个软件,而是指计算机辅助设计所产出的几何数据;最终产物通常是一个可以被下游工具消费的文件,比如STEP、GLB、STL。这三个格式在热搜词里反复出现,不是偶然,它们分别代表了三条不同的下游路径:STEP 走的是精确 B-rep 实体路线,GLB 走的是可视化与轻量化路线,STL 走的是网格与 3D 打印路线。

为什么这件事值得单独拿出来讲?因为传统 CAD 的工作流是“人 → 草图 → 约束 → 特征 → 装配”,门槛集中在两个地方:一是你得熟悉软件的操作逻辑,二是你得把脑子里的形状翻译成参数和约束。text-to-cad 想干的事情,就是把第二道翻译工作尽量交给机器,让人只负责“说清楚要什么”。它解决的不是“替代设计师”,而是“把重复性建模、参数化改型、批量出图这类脏活累活压缩掉”。

适合看这篇内容的人,我大致分三类。第一类是做机械、钣金、工装夹具的工程师,手里有大量相似件,想用脚本或者 AI 辅助批量生成;第二类是做 3D 打印、手办、文创的玩家,想从一句描述快速拿到 STL 去切片;第三类是做前端可视化、数字孪生、AR 展示的开发者,需要把文字描述转成 GLB 塞进网页或者引擎里。这三类人的诉求不一样,但底层都绕不开“文本 → 几何 → 格式转换 → 校验”这条主线。

我自己的判断是:text-to-cad 目前最成熟的落点不是“一句话生成复杂装配体”,而是“一句话生成参数化零件 + 人工微调”。谁要是跟你说它能直接生成一台减速箱的全部零件并自动装配,那基本是在讲故事。但你要说它能根据“M8 螺栓、长度 40、全螺纹、头部带法兰”生成一个可用的 STEP,这个已经能做到,而且做得不差。

2. 核心思路拆解:文本怎么变成几何

2.1 三条主流技术路线与选型逻辑

把文本变成 CAD,市面上能跑通的路线大致有三条,我按“可控性”从高到低排一下。

第一条是模板 + 参数抽取。你先准备好一批参数化模板,比如法兰、轴、支架、齿轮、钣金折弯件,每个模板用脚本或者特征树定义好可变参数。文本输入进来之后,用一个解析器把“直径 50、厚度 10、四个 M6 孔均布”这类信息抽成结构化字段,再灌进模板里生成模型。这条路线的优点是结果稳定、尺寸精确、可复现,缺点是覆盖面受模板库限制,遇到没见过的形状就歇菜。

第二条是代码生成路线。让模型输出一段建模脚本,比如 OpenSCAD、CadQuery、build123d 或者 FreeCAD 的 Python 脚本,然后执行脚本得到几何。这条路线的妙处在于:文本到代码是语言问题,代码到几何是确定性问题。语言模型擅长前者,CAD 内核擅长后者,分工明确。热搜词里出现的 “python批量对cad修改” 其实就是这条路线的手工版,只不过现在把“写脚本”这一步也交给模型了。

第三条是直接生成网格或隐式场。比如用扩散模型直接吐出一个三角网格,或者生成一个 SDF(符号距离场)再 marching cubes 提取等值面。这条路线的优点是形状自由度高,能做出传统特征建模很难描述的有机形状;缺点是尺寸精度差、拓扑不干净、很难转成 STEP。所以它更适合走 GLB 和 STL,不适合走精确制造。

我个人的选型建议是这样的:

路线适合场景输出格式精度可控性
模板 + 参数抽取标准件、系列件、批量改型STEP高高
代码生成中等复杂度零件、可参数化结构STEP / STL高中高
直接生成网格有机形状、概念展示、手办GLB / STL低低

如果你是要拿去加工、装配、出工程图,前两条路线是唯一选择;如果你只是要一个能看、能打印、能放进网页里转一转的模型,第三条路线也能凑合。

2.2 为什么 STEP、GLB、STL 要分开对待

很多人一开始会问:既然都是三维文件,为什么不能一个格式走天下?答案是这三个格式描述几何的方式根本不一样。

STEP用的是 B-rep(边界表示),它记录的是精确的曲面方程、边、顶点拓扑关系。一个圆柱面在 STEP 里就是一个数学意义上的圆柱面,直径 50 就是 50,不会因为网格密度而变成 49.98。所以 STEP 是 CAD 之间交换数据的通用语言,SolidWorks、UG、Creo、中望 CAD、FreeCAD 都能读。热搜里 “sw中stl转stp” 之所以被反复搜,就是因为 STL 转 STEP 本质上是从近似网格反推精确曲面,这个过程叫逆向建模,很难做到完全无损。

STL是三角网格,它只记录三角形面片,没有曲面概念。一个圆柱在 STL 里是几百上千个三角形拼出来的近似体。它的优点是简单、通用、切片软件都认;缺点是精度受网格密度影响,而且没有单位、没有特征、没有装配关系。热搜里 “3dsmax2012修复stl模型的uv” 和 “qopengl 加载stl” 说明 STL 的使用场景非常分散,从渲染到可视化都有。

GLB是 glTF 的二进制版本,主打的是轻量化和 Web 友好。它支持材质、贴图、动画、层级节点,文件体积通常比 STL 小很多,浏览器里用 three.js 或者 Babylon.js 可以直接加载。热搜里 “cad快速看” 这类需求,如果做成网页版,GLB 基本是首选格式。

所以 text-to-cad 的输出格式选择,本质上是在问:你下游要干什么。要加工,走 STEP;要打印,走 STL;要展示,走 GLB。三条路线的后处理逻辑完全不同,不能混着来。

2.3 文本描述的结构化拆解

自然语言最大的问题是模糊。人说“一个圆角矩形板”,机器听到的是六个字,但实际需要的是:长、宽、厚、圆角半径、是否有孔、孔的位置和直径、材料、单位。所以 text-to-cad 的第一步不是生成几何,而是把模糊描述拆成结构化参数。

我一般会把描述拆成四层:

  • 几何类型层:这是板、轴、法兰、支架、齿轮还是壳体。
  • 尺寸参数层:长宽高、直径、厚度、半径、角度。
  • 特征层:孔、槽、倒角、圆角、螺纹、阵列。
  • 约束与关系层:孔均布、同心、对称、平行、垂直。

这四层里,第一层决定用哪个模板或哪段代码,第二层和第三层决定参数值,第四层决定特征之间的拓扑关系。实际测试下来,模型对第一层和第三层的识别准确率最高,对第四层的理解最容易出问题。比如“四个孔均布在直径 80 的圆上”,模型经常会把“均布”理解成“随便放四个”,这时候就需要在提示词里明确写“90 度等间隔阵列”。

提示:写 text-to-cad 提示词的时候,尽量用工程语言而不是生活语言。“一个扁扁的圆盘子”不如“直径 120、厚度 8 的圆板”来得可靠。

3. 实操落地:从一句话到可用的 STEP 文件

3.1 环境准备与工具链选择

要跑通一条 text-to-cad 的链路,你至少需要三样东西:一个能理解文本的模型、一个能生成几何的 CAD 内核、一个能做格式转换的后处理器。

CAD 内核这块,我推荐几个实际用过的:

  • CadQuery:基于 OpenCASCADE,Python 写参数化模型非常顺手,输出 STEP 和 STL 都是一行代码。社区活跃,文档够用。
  • build123d:CadQuery 的“兄弟项目”,语法更接近 Python 上下文管理器,写复杂特征树更清晰。
  • OpenSCAD:脚本化建模的老牌选手,语法简单,但曲面能力弱,适合做规则几何。
  • FreeCAD:自带 Python 控制台,可以脚本化操作,也能读 STEP 做二次处理。

格式转换这块,OpenCASCADE 的 Python 绑定(pythonocc-core)是绕不开的,STEP 读写、网格化、布尔运算都能干。如果只是 STL 转 STEP 这种逆向操作,可以看看 FreeCAD 的 Part 工作台,或者用 MeshLab 先做网格清理再转。

文本理解这块,如果你是在本地跑,可以用开源模型做意图识别和参数抽取;如果是在线服务,直接调 API 也行。关键是要把输出约束成 JSON,字段固定,后面才好接。

3.2 一个完整的法兰盘生成示例

我拿一个最常见的法兰盘来演示整条链路。输入描述是:

生成一个法兰盘,外径 120,内径 50,厚度 15,法兰上均布 6 个直径 10 的通孔,孔中心圆直径 90,边缘倒角 2。

第一步,参数抽取。把这段话拆成 JSON:

{ "type": "flange", "outer_diameter": 120, "inner_diameter": 50, "thickness": 15, "hole_count": 6, "hole_diameter": 10, "hole_circle_diameter": 90, "chamfer": 2, "unit": "mm" }

第二步,用 CadQuery 写生成脚本:

import cadquery as cq import math params = { "outer_diameter": 120, "inner_diameter": 50, "thickness": 15, "hole_count": 6, "hole_diameter": 10, "hole_circle_diameter": 90, "chamfer": 2 } result = ( cq.Workplane("XY") .circle(params["outer_diameter"] / 2) .circle(params["inner_diameter"] / 2) .extrude(params["thickness"]) ) hole_radius = params["hole_diameter"] / 2 hole_circle_radius = params["hole_circle_diameter"] / 2 angle_step = 360 / params["hole_count"] for i in range(params["hole_count"]): angle = math.radians(i * angle_step) x = hole_circle_radius * math.cos(angle) y = hole_circle_radius * math.sin(angle) result = ( result.faces(">Z").workplane() .center(x, y) .hole(params["hole_diameter"]) ) result = result.edges("|Z").chamfer(params["chamfer"]) cq.exporters.export(result, "flange.step") cq.exporters.export(result, "flange.stl")

这段脚本跑完,你会得到一个 STEP 和一个 STL。STEP 可以丢进 SolidWorks 或者中望 CAD 继续改,STL 可以直接丢进切片软件。

第三步,校验。这一步很多人会跳过,但我建议一定要做。校验至少看三件事:尺寸对不对、拓扑干不干净、单位是不是毫米。尺寸可以用 CadQuery 的 bounding box 查,拓扑可以用 FreeCAD 的 Part 检查工具看有没有自交面,单位在导出 STEP 的时候要确认是 MM 而不是 M。

3.3 参数计算与常见取值经验

法兰这个例子里有几个参数是有工程惯例的,不是随便填的。

孔中心圆直径一般是外径的 0.75 到 0.8 倍。外径 120 的话,孔中心圆取 90 到 96 比较合理,取 90 偏保守,取 96 更省材料但边缘会薄一些。

孔直径和螺栓规格挂钩。M8 螺栓的通孔一般取 9 到 10,M10 取 11 到 12。取 10 对应的是 M8 或 M10 的间隙孔,具体看装配精度要求。

倒角一般取 1 到 2 毫米,太大影响密封面,太小起不到去毛刺的作用。2 毫米对于 15 厚的法兰是合适的。

厚度这块,15 毫米对于 120 外径的法兰偏薄,如果承压或者承扭,建议加到 20 以上。但如果是低压或者只是结构连接,15 也能用。

这些经验值不是死的,但如果你让模型自由发挥,它很可能给你生成一个孔中心圆等于外径、孔直径等于 20 的离谱结果。所以参数校验这一步必须有人工规则兜底,不能全信模型。

注意:text-to-cad 生成的第一版模型,我建议一律当成“草稿”,不要直接拿去加工。至少过一遍尺寸链和干涉检查。

4. 格式转换与下游对接的坑

4.1 STL 转 STEP 为什么这么难

热搜里 “sw中stl转stp” 是个高频问题,我专门说一下。STL 是三角网格,STEP 是精确曲面,从 STL 到 STEP 本质上是一个曲面重建问题。你要从一堆离散三角形里猜出原始曲面是什么,这个过程没有唯一解。

实际操作中,SolidWorks 打开 STL 会走 ScanTo3D 或者曲面向导,FreeCAD 可以用 Part 工作台的“从网格创建形状”再转成实体。但转出来的 STEP 通常有两个问题:一是曲面被拆成很多小面片,不再是单个圆柱面;二是边线不干净,倒角和圆角会变成一堆碎边。

我的经验是:如果原始设计还在,永远优先拿原始 STEP,不要从 STL 反推。只有当你手里只有 STL、又必须做精确修改的时候,才走逆向这条路。逆向的时候,先用 MeshLab 做网格清理(去重、补洞、平滑),再进 CAD 做曲面拟合,成功率会高很多。

4.2 GLB 的轻量化处理

GLB 走的是可视化路线,所以重点不是精度而是体积和加载速度。一个 50MB 的 STL 转成 GLB 可能只有 2MB,但如果网格不优化,GLB 也可能很大。

我一般会做三步处理。第一步是减面,用 Blender 的 Decimate 修改器或者 meshoptimizer 把三角面数降到原来的 20% 到 30%,视觉上几乎看不出差别。第二步是合并材质,把多个材质合并成一个,减少 draw call。第三步是压缩,用 Draco 或者 Meshopt 压缩几何数据,GLB 体积能再降一半。

热搜里 “qopengl 加载stl” 和 “qt5.15.2 读取 stl 模拟六轴机械臂” 说明很多人在做桌面端的可视化。如果你的场景是桌面端,STL 直接加载也能接受;但如果是 Web 端,GLB 几乎是必选项。

4.3 批量处理与自动化

“python批量对cad修改” 这个热搜词背后是一个很真实的需求:手里有几百个相似的 CAD 文件,每个都要改几个参数,手动改到崩溃。text-to-cad 的思路在这里可以反过来用:先用脚本批量生成,再用脚本批量修改。

我做过一个夹具的项目,200 多个板件,每个板件的孔位和尺寸都不一样。做法是把所有参数整理成 CSV,然后用 CadQuery 写一个通用模板,循环读 CSV 生成 STEP。整个过程不到 10 分钟,比手动建模快了两个数量级。

批量处理的时候有几个坑要注意。一是文件命名,一定要用参数组合来命名,不然生成完你分不清哪个是哪个。二是异常捕获,某个参数组合可能导致布尔运算失败,脚本要能跳过并记录,不能整个中断。三是单位统一,CSV 里如果混了英寸和毫米,生成出来的模型会差 25.4 倍。

问题现象排查方向解决方式
布尔运算失败孔没打穿或实体消失检查孔径是否大于壁厚调整参数或改用切削顺序
导出 STEP 报错文件生成但打不开检查是否有自交面用 FreeCAD 做几何检查
单位错误模型大 25.4 倍检查输入单位统一转成毫米再生成
网格太粗STL 表面有棱角检查网格容差调小 linear deflection
GLB 太大网页加载慢检查面数和贴图减面 + Draco 压缩

5. 常见问题与排查技巧实录

5.1 模型生成失败或几何异常

最常见的问题是布尔运算失败。比如在一个薄壁上打一个直径接近壁厚的孔,OpenCASCADE 有时候会算出一个破碎的实体。排查方法是先把孔直径调小一点试试,如果能成功,说明是临界尺寸问题。解决方式有两种:一是调整参数避开临界值,二是改变操作顺序,先打孔再抽壳。

第二个问题是倒角失败。倒角对边线的连续性很敏感,如果边线有微小断点,倒角就会报错。我一般会先做clean()清理几何,再做倒角;如果还不行,就把倒角半径调小,或者改用圆角。

第三个问题是导出文件打不开。STEP 导出的时候如果实体不是闭合的,有些软件会拒绝加载。用 FreeCAD 的Part.CheckGeometry可以查出来哪里有问题,常见的是微小面或者重复顶点。

5.2 文本理解偏差怎么修

模型把“均布”理解成“随便放”是高频问题。我的做法是在提示词里显式写出阵列规则,比如“6 个孔,绕中心 360 度等间隔分布,间隔 60 度”。另外,给出参照系也很重要,比如“孔中心位于以原点为圆心、直径 90 的圆上”,比“孔在法兰上”明确得多。

如果模型反复理解错,可以考虑换一种表达方式。比如“沉头孔”不如“孔口倒 90 度锥角、锥面最大直径 18、通孔直径 10”来得准确。工程语言虽然啰嗦,但歧义少。

还有一个技巧是分步生成。先让模型生成外形,确认无误后再让它加特征。一次性生成复杂零件,出错概率远高于分步生成。

5.3 性能与精度平衡

STL 的网格密度直接决定文件大小和后续处理速度。CadQuery 导出 STL 的时候有两个参数:tolerance和angularTolerance。tolerance控制弦高误差,默认 0.001;angularTolerance控制角度误差,默认 0.1。调小这两个值,网格更细,文件更大。

我的经验值是:3D 打印用 tolerance 0.01 到 0.05 就够了,再细切片软件也体现不出来;可视化展示用 0.1 到 0.5,肉眼几乎看不出差别,但文件能小一个数量级。

STEP 没有网格密度问题,但文件体积和曲面复杂度正相关。如果一个零件有几千个面,STEP 可能几十 MB。这时候可以考虑简化特征,或者导出的时候做曲面合并。

提示:批量生成的时候,建议先用低精度跑一遍全流程,确认逻辑没问题,再用高精度重新生成最终文件。这样能省很多等待时间。

5.4 与现有 CAD 软件的对接

生成的 STEP 要能进 SolidWorks、UG、Creo、中望 CAD,关键是版本和协议。STEP 有 AP203、AP214、AP242 几个版本,AP242 支持颜色和 PMI,但老软件可能读不了。我一般导出 AP214,兼容性最好。

如果下游是钣金加工,注意 STEP 里的折弯特征不一定能被识别。热搜里 “金林钣金cad版” 和 “cad切地形” 说明国内钣金和地形场景很特殊,通用 STEP 不一定适配。这种时候可能需要针对特定软件做二次开发,或者导出中间格式再转换。

如果下游是 3D 打印,STL 的法线方向很重要。法线反了,切片软件会认为模型是空心的。CadQuery 导出的 STL 法线一般是对的,但如果经过其他工具处理,建议用 MeshLab 检查一下。

6. 我对 text-to-cad 的实际使用体会

我拿 text-to-cad 跑过几类零件:法兰、支架、齿轮毛坯、钣金折弯件、简单的壳体。感受最深的几点,跟一开始的预期不太一样。

第一,它最擅长的不是“从零生成”,而是“参数化改型”。你给它一个模板,让它改尺寸、改孔数、改阵列方式,它做得又快又准。但你让它凭空设计一个从没见过的结构,它给出的东西往往尺寸不合理、特征冗余、加工性差。

第二,提示词的质量直接决定输出质量。我试过用一句话描述一个支架,生成出来的东西完全不能用;后来把描述拆成“底板 100×60×8、立板高 50、厚 6、底板四角 M6 通孔、立板顶部一个直径 20 的轴孔、立板与底板之间加两个三角加强筋”,生成出来的模型基本可以直接用。差别就在于信息密度。

第三,格式转换是整条链路里最容易被低估的环节。很多人以为生成完 STEP 就结束了,实际上从 STEP 到 STL 到 GLB,每一步都有坑。网格精度、法线方向、材质丢失、单位错误,这些问题在批量处理的时候会集中爆发。

第四,人工校验不能省。我现在的流程是:模型生成 → 脚本校验尺寸 → 人工看一遍拓扑 → 导出下游格式。四步里任何一步跳过,后面都可能返工。尤其是尺寸校验,写几行代码就能自动比对,比人眼靠谱得多。

最后分享一个我常用的小技巧:把常用的参数化模板整理成一个库,每个模板配一份参数说明和默认值。text-to-cad 生成的时候,先匹配模板,再填参数,最后生成。这样比每次从零生成稳定得多,也更容易做批量。模板库不需要很大,二三十个覆盖常见零件类型就够了,关键是每个模板都要经过实际验证,确保参数合理、几何干净、导出正常。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进