1. 从一段文字到三维实体:text-to-cad 到底在解决什么问题
第一次听到 "text-to-cad" 这个词,很多人会下意识地把它理解成"用嘴画图"——说一句话,软件自动帮你生成一张工程图纸。这个理解只对了一半。真正的 text-to-cad,核心链路是把一段自然语言描述,转换成可被 CAD 软件识别、可被下游制造流程消费的三维几何数据,最终落地成 STEP、GLB、STL 这类标准格式文件。它解决的不是"画图快不快"的问题,而是"从想法到可制造模型之间那道鸿沟"的问题。
我接触这个方向,最初是因为一个很具体的场景:手头有一批非标零件,客户只给了一段文字描述和几张手绘草图,要求快速出三维模型用于报价和打样。传统做法是打开 CAD 软件,一个特征一个特征地拉伸、旋转、倒角,一个中等复杂度的零件从理解需求到出图,熟练工也要一两个小时。如果需求方改一次尺寸,整个模型可能要重做。这种重复劳动逼着我去研究:能不能让机器理解"一个直径 50mm、高 80mm 的圆柱,顶部开一个深 20mm、宽 10mm 的槽"这种描述,直接吐出几何体?
这就是 text-to-cad 的起点。它适合几类人:做快速原型的产品经理和工业设计师、需要批量生成参数化零件的工程师、做 AI 辅助设计工具的开发者和研究者,以及想把设计流程自动化的制造从业者。哪怕你只是偶尔需要把一段描述变成 STL 去 3D 打印,这套思路也能帮你省下大量手动建模时间。
需要先明确一个边界:text-to-cad 目前不是一个"说完就完美"的魔法。它更像一个"高起点草稿生成器"——把 60% 到 80% 的基础几何自动搭出来,剩下的精度修正、装配约束、工程标注,仍然需要人来把关。理解这个定位,后面的所有技术选型和实操才不会跑偏。
2. 拆解 text-to-cad 的技术链路:文字是怎么变成几何体的
2.1 自然语言理解层:把口语翻译成结构化参数
文字描述最大的问题是模糊。"一个差不多拳头大的方块"这种话,人听了能脑补,机器不行。所以链路的第一环,是把自然语言解析成结构化的几何参数。这一步通常靠大语言模型来完成,因为它擅长从非结构化文本里抽取实体、尺寸、关系和约束。
举个实际处理的例子,输入是"一个长 100mm、宽 60mm、厚 10mm 的底板,四角各有一个直径 6mm 的圆孔,孔中心距边缘 8mm"。模型需要抽取出:基础形状是长方体,三个维度尺寸分别是 100、60、10,特征操作是"打孔",孔的数量是 4,直径 6,位置约束是"距边缘 8mm"。这些信息会被组织成一份 JSON 或类似的结构化描述,作为下一阶段的输入。
这里有个容易被忽略的细节:单位。自然语言里经常省略单位,或者混用"毫米""厘米""寸"。我的做法是在解析层强制统一到毫米,并在提示词里明确要求模型输出带单位标注的数值。如果输入里出现"寸"这种歧义词,宁可让模型反问,也不要猜——猜错一次,后面整个模型都是废的。
2.2 几何生成层:从参数到实体模型
拿到结构化参数后,就要真正生成几何体了。这一层有两条主流路线,选哪条直接决定了你后续能走多远。
第一条是参数化建模路线,代表工具是 OpenCASCADE(简称 OCCT)这类几何内核。它的逻辑是:把每个特征翻译成内核的 API 调用,比如创建一个长方体、在指定位置打一个圆柱孔、做布尔减运算。这条路线的最大优势是生成的模型是"真"的 B-Rep(边界表示)实体,精度高、可编辑、能导出 STEP 这种工程级格式。缺点是每一步都要精确指定参数,容错性差,一个坐标算错整个特征就废了。
第二条是网格生成路线,代表是各类基于深度学习的三维生成模型,直接输出三角网格。它的优势是能处理复杂、有机的形状,比如"一个流线型的外壳",参数化路线很难描述这种形状。缺点是生成的网格精度有限,表面是三角面片拼出来的,不适合做精密工程,导出 STEP 时还需要做逆向转换,会丢失特征信息。
我的经验是:规则零件走参数化,自由曲面走网格生成。一个带孔带槽的机械件,用 OCCT 生成,尺寸精确到微米级;一个艺术造型的摆件,用网格生成,然后导出 STL 直接打印。两者不是替代关系,而是互补。
2.3 格式转换层:STEP、GLB、STL 各自的分工
生成完几何体,最后一步是导出成下游能用的格式。这三种格式经常被混用,但它们的定位完全不同,选错了会带来一堆麻烦。
| 格式 | 本质 | 精度 | 典型用途 | 是否保留特征 |
|---|---|---|---|---|
| STEP | B-Rep 实体 | 精确 | 工程制造、CNC 加工、装配 | 是 |
| GLB | 三角网格 + 材质 | 中等 | 网页展示、AR/VR、渲染 | 否 |
| STL | 三角网格 | 中等 | 3D 打印、快速原型 | 否 |
STEP 是工程界的通用语言,几乎所有主流 CAD 软件都能读写,它保留的是数学精确的曲面和实体信息,所以适合拿去加工。GLB 是给展示和交互用的,带材质和贴图,适合放到网页或 AR 场景里。STL 是 3D 打印的事实标准,只描述表面三角面片,简单粗暴但通用。
提示:如果你的下游是 CNC 加工或者需要二次编辑,务必导出 STEP。STL 转 STEP 是一个"逆向重建"过程,会丢失圆角、孔位等特征信息,转出来的模型往往没法直接用。
3. 动手搭一条最小可用的 text-to-cad 流水线
3.1 环境准备:几何内核和运行时的选择
要自己跑通一条流水线,第一步是把几何内核装起来。OCCT 是最成熟的开源选择,Python 侧可以用pythonocc-core这个绑定库,它把 OCCT 的能力封装成了 Python 接口,写起来比 C++ 友好太多。
安装方式我推荐用 conda,因为 OCCT 依赖一堆底层库,pip 装经常缺依赖:
conda install -c conda-forge pythonocc-core装完之后验证一下:
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox box = BRepPrimAPI_MakeBox(100, 60, 10).Shape() print("几何内核工作正常")如果这行能跑通,说明内核没问题。这里有个坑:pythonocc-core的版本要和 OCCT 主版本对应,装错版本会出现各种诡异的段错误。我一般锁定 conda-forge 上的稳定版本,不追最新。
自然语言解析这一层,可以用任意一个支持结构化输出的语言模型 API。关键不是用哪个模型,而是提示词的设计——必须强制模型输出严格的 JSON,字段名固定,数值带单位。我通常会在提示词里给两三个示例,让模型照着格式填。
3.2 把一句话翻译成建模指令
假设输入是"一个 80×40×5mm 的矩形板,中心有一个直径 20mm 的通孔"。解析层要输出这样的结构:
{ "base": {"type": "box", "length": 80, "width": 40, "height": 5}, "features": [ {"type": "hole", "diameter": 20, "position": [40, 20], "through": true} ], "unit": "mm" }拿到这份结构,几何生成层就可以按部就班地执行:先建一个 80×40×5 的长方体,再在 (40, 20) 位置建一个直径 20 的圆柱,做布尔减运算,最后导出。
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeCylinder from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Cut from OCC.Core.gp import gp_Pnt, gp_Ax2, gp_Dir # 建底板 base = BRepPrimAPI_MakeBox(80, 40, 5).Shape() # 建圆柱(通孔,高度给大一点保证穿透) axis = gp_Ax2(gp_Pnt(40, 20, -1), gp_Dir(0, 0, 1)) cyl = BRepPrimAPI_MakeCylinder(axis, 10, 7).Shape() # 布尔减 result = BRepAlgoAPI_Cut(base, cyl).Shape()这段代码里,圆柱的半径是 10(直径 20),高度给 7 而不是 5,是为了保证布尔运算时圆柱完全穿透底板,避免出现零厚度的残留面。这是实操中非常容易踩的坑——如果圆柱高度刚好等于板厚,布尔运算可能因为浮点误差留下一个极薄的壳,导出的模型在切片软件里会报错。
3.3 导出 STEP 与 STL 的实操细节
几何体建好后,导出这一步看似简单,其实细节不少。导出 STEP 用STEPControl_Writer:
from OCC.Core.STEPControl import STEPControl_Writer, STEPControl_AsIs from OCC.Core.Interface import Interface_Static_SetCVal writer = STEPControl_Writer() Interface_Static_SetCVal("write.step.unit", "MM") writer.Transfer(result, STEPControl_AsIs) writer.Write("part.step")注意write.step.unit这一行,如果不显式设置单位,有些下游软件读进去会按英寸解释,尺寸直接差 25.4 倍。这个坑我在一个项目里踩过,客户拿到模型说"怎么大了这么多",排查了半天才发现是单位问题。
导出 STL 用StlAPI_Writer,关键参数是网格精度:
from OCC.Core.StlAPI import StlAPI_Writer from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh # 先做网格化,精度决定三角面片的密度 BRepMesh_IncrementalMesh(result, 0.1) stl_writer = StlAPI_Writer() stl_writer.Write(result, "part.stl")BRepMesh_IncrementalMesh的第二个参数是线性偏差,值越小网格越密、文件越大、表面越光滑。0.1mm 对于大多数 3D 打印够用了,如果做精细手办可以调到 0.02。但别一味调小,网格太密会让切片软件卡死,我见过一个模型因为精度设成 0.001,STL 文件直接飙到 200MB。
4. 实测中那些文档不会告诉你的坑
4.1 布尔运算失败:最常见也最头疼
布尔运算失败是参数化建模里出现频率最高的问题。表现是运算后模型出现破面、丢失特征,或者干脆返回空结果。根本原因通常是两个实体在边界处"擦边"——比如两个面刚好重合、两个顶点刚好重合,浮点精度一抖动,内核就判断不出到底该保留哪部分。
我的应对策略有三条。第一,让相交的实体充分重叠,就像前面圆柱高度给 7 而不是 5 那样,宁可多切一点也不要刚好贴着。第二,避免共面,如果两个特征的面恰好在一个平面上,稍微偏移 0.01mm 就能绕开。第三,分步做布尔运算,不要一次性把五个特征全减掉,一个一个来,出问题好定位。
排查的时候,可以先把中间结果导出 STL 看一眼,确认每一步的几何体是不是符合预期。很多时候问题不在布尔运算本身,而是前一步的实体就没建对。
4.2 自然语言里的"隐含约束"最容易被漏掉
语言模型解析文字时,最容易漏的是那些"没说出口但默认成立"的约束。比如"四角各有一个孔",人一看就知道是四个角对称分布,但模型可能只理解成"有四个孔",位置随便放。再比如"中心孔",模型可能把"中心"理解成几何中心,也可能理解成某个基准点。
解决办法是在提示词里把这些隐含约束显式化。我会在解析规则里加一条:凡是涉及"对称""均布""中心""边缘"这类位置词,必须输出明确的计算公式或坐标。比如"四角孔"要展开成"孔中心坐标分别为 (8,8)、(72,8)、(8,32)、(72,32)",而不是留给下游去猜。
这一步多花的功夫,能省掉后面反复返工的时间。我现在的习惯是,解析结果出来后先人工扫一眼坐标,确认位置逻辑对得上,再进几何生成。
4.3 单位、坐标系和朝向的连锁错误
单位问题前面提过,这里补充坐标系和朝向。CAD 里默认的坐标系是右手系,Z 轴朝上,但不同软件、不同导出格式对"上"的定义可能不一样。STL 导出时如果朝向反了,打印出来的模型是倒的,虽然切片软件能自动摆正,但如果是装配体,朝向错了整个装配关系就乱了。
我的做法是在流水线里固定一套内部坐标系约定:Z 轴朝上,模型底面在 Z=0 平面。所有生成的特征都按这个约定来,导出前再做一次朝向检查。对于需要特定朝向的场景,在导出参数里显式指定,不依赖下游软件的自动纠正。
5. 从能跑到好用:让 text-to-cad 真正进工作流
5.1 参数化模板:把重复需求沉淀下来
跑通单次生成只是第一步,真正提升效率的是把高频需求做成模板。比如我经常要生成各种规格的法兰盘,就把"外径、内径、螺栓孔数量、螺栓孔分布圆直径、厚度"这几个参数抽出来,做成一个模板函数。下次只要填参数,不用重新描述。
def make_flange(outer_d, inner_d, bolt_count, bolt_circle_d, thickness): # 建外圆盘 # 挖内孔 # 按分布圆均布螺栓孔 # 返回实体 ...模板化的好处不只是快,更重要的是一致性。同一类零件用同一个模板生成,尺寸逻辑、倒角习惯、孔位规则都统一,下游装配不会出现莫名其妙的干涉。这在批量出图的场景里价值极大。
5.2 批量生成与命名规范
当需求变成"生成 50 个不同规格的支架"时,单次调用就不够了,需要批量处理。我的做法是把需求整理成一张 CSV 表,每行一个零件的参数,然后循环调用生成函数,按规范命名输出文件。
命名规范这件事看着小,实际影响很大。我用的格式是{零件类型}_{关键尺寸}_{版本}.step,比如bracket_100x60x5_v2.step。这样在文件夹里一眼就能找到想要的,不用一个个打开看。批量生成时如果命名混乱,几百个文件堆在一起,找起来能让人崩溃。
批量生成还要注意异常处理。某个零件因为参数不合理导致布尔运算失败时,不能让整个批处理中断。我会用 try-except 包住单个生成逻辑,失败的记录到日志里,继续处理下一个,最后统一看哪些失败了、为什么失败。
5.3 和现有 CAD 工具的衔接
生成的模型最终要进到实际工作流里,和现有工具的衔接很关键。STEP 文件可以直接被主流 CAD 软件打开做二次编辑,这是最通用的方式。如果下游是 3D 打印,STL 直接丢进切片软件。如果要做网页展示,GLB 配合 three.js 这类库就能在浏览器里渲染。
有个细节值得注意:从 text-to-cad 生成的 STEP 导入到某些 CAD 软件后,特征树是"哑"的——它是一堆曲面和实体的集合,没有参数化的特征历史。这意味着下游想改一个孔的直径,不能像原生建模那样双击改参数,而要重新做布尔运算。如果下游需要频繁改参数,更好的做法是把参数化模板也一起交付,让对方在源头改。
6. 这套东西的边界在哪里,以及我踩过的真实教训
text-to-cad 不是万能的,认清它的边界比学会用它更重要。它擅长的是规则明确、参数可枚举的零件——板、轴、法兰、支架、简单的壳体。这些零件的几何逻辑清晰,文字描述能覆盖绝大部分信息。它不擅长的是高度依赖工程判断和隐性知识的设计,比如一个需要考虑散热、应力、装配公差链的复杂结构,这些信息文字里根本写不全,模型也无从生成。
我踩过最深的一个坑,是早期太信任自动生成的结果,没有做几何校验就直接把 STEP 发给加工厂。结果一个零件的孔位因为解析时把"距边缘 8mm"理解成了"距中心 8mm",整批零件孔位全错,报废了一批材料。从那以后,我在流水线里加了一道自动校验:生成后检查关键尺寸是否在合理范围内、孔位是否落在实体内部、壁厚是否大于最小加工厚度。这些检查用简单的几何计算就能做,但能拦住大部分低级错误。
另一个教训是关于精度预期。自然语言描述天然是粗粒度的,"直径 50mm"可能实际是 50.0 也可能是 50.5,文字里没写。如果下游对精度要求高,必须在输入阶段就把公差明确写出来,或者生成后人工标注。指望从一句模糊描述里得到精密工程模型,是不现实的。
我现在的工作流是这样的:文字描述进,模型出,然后人工在 CAD 里过一遍,确认关键特征和尺寸,再导出正式文件。这套流程下来,一个中等复杂度的零件从描述到可用模型,大概十分钟,比纯手工建模快了三到五倍。省下来的时间,花在真正需要工程判断的地方,这才是 text-to-cad 的正确用法。
如果你刚开始尝试,我的建议是先从一个最简单的零件跑通全链路——建一个带孔的板,导出 STEP 和 STL,用 CAD 软件和切片软件分别验证一遍。链路通了,再逐步加复杂度。别一上来就挑战复杂装配体,那样只会在布尔运算的坑里反复挣扎,最后怀疑整个方向。