
CAD 这行当有个特别拧巴的地方脑子里想清楚一个零件只要几秒钟把它变成能加工、能渲染、能进仿真管线的三维实体却可能要花上半小时甚至更久。拉伸、倒角、打孔、装配约束每一步都在消耗耐心。text-to-cad 这个方向之所以最近被反复提起本质上就是冲着这个落差去的——用一段自然语言描述直接吐出可用的 CAD 几何文件。我前后折腾了几个月从纯文本生成网格到参数化脚本再到能导出 STEP 的实体建模踩的坑比想象中多得多。这篇就把我摸出来的完整路径摊开讲包括为什么有些方案看着美好实际没法用、STEP 和 STL 到底该在什么环节切换、以及那些没人写在文档里的参数细节。1. 先把 text-to-cad 这件事的边界划清楚很多人第一次听到 text-to-cad脑子里浮现的是我说一句画个法兰盘软件就给我一个能直接上机床的模型。这个预期不能说错但如果不先把边界划清楚后面选型一定会走弯路。我见过太多人一上来就追求一句话出成品结果卡在几何有效性上连文件都打不开。1.1 它到底在解决哪一段的问题text-to-cad 真正能帮上忙的是从意图到初始几何这一段。也就是说你描述一个外径 80、内径 40、厚度 10 的圆环边缘倒角 2 毫米它能给你一个大致符合的实体。但这个圆环要能承受 5 吨轴向载荷、材料选 45 号钢、表面粗糙度 Ra1.6这类工程约束它管不了也不该指望它管。我把整个链路拆成四段来看text-to-cad 的定位就清楚了阶段传统做法text-to-cad 能介入的程度需求理解人读图纸/需求文档强自然语言直接映射初始几何构建手动草图特征强这是主战场工程校验仿真/干涉检查弱基本靠后续工具加工准备出图/工艺规划几乎不涉及所以正确的用法是把它当成一个高速草稿机而不是替代整个设计流程。它帮你把最枯燥的从零到有个形状这一步压缩掉剩下的精修和校验还是得人来。1.2 为什么文本这个输入方式比想象中难自然语言描述几何最大的麻烦是歧义和不完备。你说一个带孔的板孔在哪、几个、多大、通孔还是盲孔全是空白。人类工程师靠经验和上下文能脑补机器不行。我实测下来能稳定生成的前提是描述里必须包含这几类信息基本体类型长方体、圆柱、圆环、拉伸体、旋转体关键尺寸长宽高、直径、半径、厚度最好带单位位置关系同心、共面、居中、偏移多少特征操作打孔、倒角、圆角、抽壳以及对应的数值缺了任何一类生成结果就会飘。比如只说一个圆柱它可能给你半径 1 也可能给你半径 100完全看模型心情。所以写 prompt 的时候宁可啰嗦不要省略。1.3 三类主流技术路线的真实差异目前能跑通 text-to-cad 的路线大致三条我每条都试过体感差别很大第一条是代码生成路线。让大模型输出 OpenSCAD 或 CadQuery 这类脚本语言的代码再由脚本引擎执行出几何。优点是几何精确、参数可控、天然支持 STEP 导出缺点是模型得懂这些 DSL 的语法写错了直接报错。第二条是网格生成路线。模型直接输出顶点和面片数据或者生成 STL/OBJ。优点是视觉上很快出效果缺点是网格是死的没有参数历史改一个尺寸等于重做而且经常出现非流形边、法线翻转这类问题。第三条是参数化模板填充路线。预先做好一批参数化模板模型只负责从文本里抽取参数填进去。优点是稳定、可控缺点是覆盖面窄超出模板范围就歇菜。我的结论是要工程可用走第一条要快速看效果走第二条要批量标准化零件走第三条。下面几节会分别展开。2. 代码生成路线为什么它才是能落地的方案如果你只想要一个能旋转看看的模型网格路线够用。但只要你需要这个模型进入后续的装配、仿真、出图流程代码生成路线几乎是唯一选择。原因很简单STEP 是边界表示B-rep实体而 STL 是三角网格两者在工程语义上不是一个层级的东西。2.1 OpenSCAD 和 CadQuery 该怎么选这两个是我用得最多的。它们都能从代码生成实体但设计哲学完全不同。OpenSCAD 是**函数式、CSG构造实体几何**的思路。你写的是先有个立方体减去一个圆柱再和另一个立方体求并集。它的语法极简模型很容易学会生成速度快。缺点是它内部其实还是网格化的导出的 STEP 质量一般复杂曲面基本没戏。CadQuery 是基于 OCCT 内核的输出的是真正的 B-rep 实体。它用 Python 写支持选择器selector语法能精确操作某条边、某个面。比如选中所有 Z 方向高度为 10 的边给它们倒角 2 毫米这种操作在 OpenSCAD 里几乎没法表达。我的一般原则简单机械件、快速验证、教学演示 → OpenSCAD需要精确倒角/圆角、需要 STEP 进下游、需要复杂选择逻辑 → CadQuery举个实际例子生成一个带四个安装孔的法兰盘CadQuery 的写法大概是这样import cadquery as cq result ( cq.Workplane(XY) .circle(40) # 外径 80 .circle(20) # 内径 40 .extrude(10) # 厚度 10 .faces(Z) # 选顶面 .workplane() .rect(60, 60, forConstructionTrue) .vertices() # 取矩形四角 .hole(6) # 打直径 6 的通孔 .edges(|Z) # 选所有竖直边 .fillet(2) # 倒角 2 ) cq.exporters.export(result, flange.step)这段代码里每个选择器都有明确意图改尺寸只要改数字几何会自动重建。这就是参数化的价值。2.2 让大模型写脚本时最容易翻车的地方直接让模型生成 CadQuery 代码成功率其实不高。我统计过自己早期的尝试十次里能一次跑通的不到三次。翻车点集中在几个地方第一是 API 记错。CadQuery 的版本迭代比较快模型训练数据里的写法可能对应旧版本。比如.hole()在某些版本里参数含义不同.fillet()对选择器的要求也变过。解决办法是在 prompt 里明确指定版本比如使用 CadQuery 2.4 的 API。第二是选择器逻辑错误。.edges(|Z)表示平行于 Z 轴的边.faces(Z)表示 Z 方向最靠上的面。这些符号模型经常搞混写出.edges(Z)这种不存在的表达。我现在的做法是让模型先输出选择器的自然语言解释确认无误再让它写代码。第三是单位混乱。CadQuery 默认单位是毫米但模型有时候会按米来思考生成circle(0.04)这种。这个必须在 prompt 里钉死。第四是忘记导出。代码逻辑都对就是没写export那行跑完啥也没有。这个属于低级错误但很常见。提示让模型生成脚本时要求它同时输出这段代码预期生成什么形状、关键尺寸是多少的说明。这样你一眼就能看出它理解得对不对不用等跑完才发现方向错了。2.3 从脚本到 STEP 的完整验证链路生成脚本只是第一步真正要确认的是导出的 STEP 文件是否有效。我固定用这套流程验证脚本执行无报错先确保 Python 能跑通几何能构建出来。体积和包围盒检查用 CadQuery 的.val().Volume()和.val().BoundingBox()打印出来和预期值对比。一个外径 80、内径 40、厚 10 的圆环理论体积是 π×(40²−20²)×10 ≈ 37699 立方毫米如果差太多说明几何错了。STEP 重新导入把导出的 STEP 再读回来确认能正常解析。有些几何在内存里没问题写出去就坏了。面数和边数合理性一个简单法兰盘的面数应该在几十这个量级如果上千说明倒角或布尔运算出了问题。这套检查看起来繁琐但能挡掉八成以上的隐性错误。我吃过亏——有次生成的模型在 CadQuery 里看着好好的导出 STEP 后导入到别的软件里直接报无效实体原因是一个倒角半径超过了相邻边的长度产生了自相交。这种问题只有重新导入才能发现。3. 网格路线STL 和 GLB 在什么场景下才值得用说完代码路线得给网格路线一个公道。STL 和 GLB 不是低级格式它们只是用途不同。理解这个区别能帮你少走很多弯路。3.1 STL、GLB、STEP 三者的本质区别我用一个类比来说明STEP 像是带完整施工图的建筑每面墙、每根梁都有精确的数学定义STL 像是用无数小三角片拼出来的建筑模型远看一样近看全是锯齿GLB 则是在 STL 基础上加了材质、颜色、光照信息更适合展示。格式几何表示是否参数化典型用途文件特点STEPB-rep 实体是工程制造、装配、仿真精确、体积小、可编辑STL三角网格否3D 打印、快速预览只有面片、无单位、无颜色GLB三角网格材质否网页展示、AR/VR含材质光照、适合渲染关键点在于STL 没有单位。一个 STL 文件里的1到底是 1 毫米还是 1 米文件本身不告诉你全靠导入时约定。这就是为什么很多人把 STL 导进软件后发现模型要么小得看不见要么大得离谱。3.2 什么时候网格格式反而更合适有三种情况我会主动选网格格式一是 3D 打印。切片软件吃的就是 STL你给它 STEP 它还得自己转。而且打印对几何精度的要求没那么高网格足够。二是网页或移动端展示。GLB 在浏览器里加载快、渲染好适合做产品展示页。STEP 在网页里基本没法直接渲染。三是快速概念验证。当你只想看看这个形状大概长啥样网格生成的速度优势就体现出来了不用等实体内核慢慢算布尔运算。但反过来只要涉及尺寸精度、装配配合、后续修改就必须回到 STEP。我见过有人拿 STL 去做公差分析这从根上就是错的——网格的顶点位置本身就有离散误差。3.3 网格转实体的那些坑有时候你手上只有 STL但需要 STEP就得做网格转实体。这个操作在 SolidWorks、Fusion 360 里都有对应功能但成功率堪忧。核心难点是网格是离散的实体是连续的。转换工具要做的其实是逆向拟合把一堆三角片重新拟合成光滑曲面。如果原始网格质量差面片大小不均、有孔洞、有自相交拟合就会失败或者生成一堆碎面。我总结的几条经验转换前先用网格修复工具如 MeshLab清理补洞、去重顶点、统一法线方向尽量用平面拟合模式处理规则几何用曲面拟合处理自由曲面转换后一定要检查实体有效性看有没有薄壁自相交零面积面复杂模型不要指望一次成功分块转换再合并往往更靠谱注意网格转实体本质上是有损的。一个圆柱面用网格表示时是几十个平面拼的转回实体后可能变成几十个小平面而不是一个光滑圆柱。如果下游需要光滑曲面最好从源头就用实体建模。4. 把 text-to-cad 接进实际工作流的几个关键决策技术路线选好了接下来是工程化的问题。这部分很少有人讲但恰恰是决定这套东西能不能真正用起来的关键。4.1 参数抽取环节怎么做才稳从自然语言里抽参数是整个链路的第一道关。我的做法是分两步走先让模型输出结构化的 JSON再从这个 JSON 生成几何。比如输入一个 100×60×20 的盒子顶面中心有个直径 10、深 5 的盲孔先转成{ type: box, dimensions: {length: 100, width: 60, height: 20}, features: [ { type: hole, face: top, position: center, diameter: 10, depth: 5, through: false } ] }这样做的好处是JSON 结构固定容易校验参数和几何生成解耦改几何引擎不影响抽取逻辑出问题时能快速定位是抽取错了还是生成错了。我一开始图省事直接让模型输出代码结果调试起来极其痛苦——分不清是它理解错了需求还是代码写错了。加了 JSON 中间层之后排查效率提升明显。4.2 单位、坐标系、朝向的统一约定这三个东西不统一后面全是灾难。我给自己定的规矩是单位一律毫米prompt 里明确写所有尺寸单位为毫米坐标系右手系Z 轴向上和大多数 CAD 软件默认一致模型默认放在第一象限即所有坐标为正方便后续定位朝向约定主视图看向 -Y 方向这样和工程图习惯对齐这些约定看起来是小事但不统一的话生成十个模型有八个位置是乱的装配的时候光对齐就要命。4.3 批量生成时的命名和版本管理当你开始批量生成零件文件管理就成了问题。我的做法是文件名包含语义关键尺寸时间戳如flange_d80_t10_20240115.step每个零件配一个同名 JSON记录生成时的参数和 prompt用 Git 管理脚本和参数文件几何文件不进版本库太大关键版本打 tag方便回溯这套下来任何一个零件都能追溯到它是怎么来的、用的什么参数。别小看这个等你三个月后想改一个零件却发现不知道当初怎么生成的时候就知道值了。5. 实测中那些文档不会告诉你的坑前面讲的都是应该怎么做这一节讲实际会怎么坏。这些是我踩过的真实坑按出现频率排序。5.1 几何有效性最隐蔽的杀手几何有效性问题是 text-to-cad 最烦人的地方因为它经常不报错。模型能生成、能显示、能导出但导出的文件在别的软件里打不开或者打开后是个空壳。常见的不有效几何包括自相交倒角半径大于相邻边长度曲面自己穿过自己零厚度壁抽壳厚度等于或大于实体尺寸产生零厚度面非流形边一条边被三个以上的面共享实体内核无法处理微小面布尔运算产生的极小面片累积误差导致后续操作失败我的应对策略是在每个环节后做有效性检查。CadQuery 里可以用.val().isValid()OCCT 有专门的检查工具。发现问题就回退到上一步调整参数重来不要带着坏几何往下走。5.2 布尔运算失败顺序比参数更重要布尔运算并、交、差失败是另一个高频问题。同样的两个实体先并后差能成功先差后并就失败这种事经常发生。原因是布尔运算对几何退化很敏感。当两个面几乎共面、两条边几乎重合时内核的容差判断就会出问题。我的经验是先做加法并集再做减法差集通常更稳避免共面操作需要贴合时让一个实体稍微嵌入另一个比如多伸 0.01 毫米分步做不要一次性把五六个布尔运算串起来中间结果检查一下调整容差OCCT 允许设置 fuzzy 值适当放宽容差能救回一些失败案例5.3 倒角和圆角的顺序陷阱倒角和圆角看着简单其实很讲究顺序。一个立方体你要在一条边上同时做倒角和圆角先做哪个结果完全不同。更麻烦的是倒角半径和相邻特征冲突。比如一个 10 毫米厚的板你要在边上倒 6 毫米的角倒角面就会和板面相交产生退化。这种情况要么减小半径要么改变倒角类型。我现在的习惯是所有倒角圆角放在最后做且半径从小到大试。先做小半径确认几何没问题再逐步加大到目标值。这样能快速定位是哪个半径超限了。5.4 导出格式的隐藏参数导出 STEP 和 STL 时有几个参数直接影响结果质量但默认值往往不是最优STEP 导出协议版本AP203 兼容性好AP214 支持颜色AP242 支持 PMI产品制造信息单位确认导出为毫米有些库默认是米精度一般用默认即可但复杂曲面可以调高STL 导出弦高chord tolerance控制曲面离散精度越小越精细但文件越大角度容差控制相邻面片的最大夹角二进制 vs ASCII二进制文件小很多除非要人工查看否则用二进制我吃过一次亏导出的 STL 弦高设太大圆柱面变成了明显的多边形3D 打印出来一圈棱。后来把弦高从默认的 0.1 调到 0.01问题解决代价是文件大了十倍。6. 从单件生成到参数化零件库的演进思路单次生成能跑通之后自然会想把它做成可复用的东西。这一步的跨越比想象中大核心是从生成一个模型变成生成一类模型。6.1 什么样的零件适合做成模板不是所有零件都值得模板化。我判断的标准是结构固定、尺寸可变比如法兰、支架、齿轮、标准件复用频率高经常需要生成同类零件参数维度有限参数太多超过十个模板会变得难以维护反过来那些每次结构都不一样的零件硬做模板反而累赘不如每次重新生成。6.2 模板的参数设计原则设计模板参数时我遵循几条原则参数要正交。也就是说改一个参数不影响其他参数的语义。比如孔径和孔位应该分开不要合成一个孔配置。提供合理默认值。模板要能零参数跑通给出一个合理的默认零件用户再按需覆盖。参数要有约束校验。比如内径必须小于外径这种约束要在生成前检查给出明确报错而不是让几何引擎抛一个看不懂的异常。暴露必要的、隐藏复杂的。用户只需要关心关键尺寸那些影响几何稳定性的内部容差、离散精度藏在模板内部就好。6.3 模板库的组织和维护当模板积累到几十个组织方式就重要了。我按功能类别分目录紧固件、传动件、结构件、外壳类每类下面再按具体类型分。每个模板是一个独立的 Python 模块暴露统一的接口def generate(params: dict) - cq.Workplane: 根据参数字典生成几何 ... def validate(params: dict) - list: 校验参数返回错误列表 ... def default_params() - dict: 返回默认参数 ...这样上层调用逻辑统一加新模板只要实现这三个函数就行。维护的时候也清楚改一个模板不影响其他。7. 我对这套东西的实际使用体会折腾到现在text-to-cad 在我工作流里的定位已经很清楚了它是一个高效的起点生成器不是终点。我现在的典型用法是接到一个新需求先用自然语言描述核心几何让系统生成一个初始模型导出 STEP。然后把这个 STEP 导入到常规 CAD 软件里在此基础上做精修——加工程特征、调整配合、做仿真。整个过程比从零手绘快很多尤其是那些结构规整、参数明确的零件。但也有它明显不擅长的地方。自由曲面、复杂有机形状、需要大量人工判断的拓扑优化结构这些还是得靠传统建模或者专门的生成式设计工具。硬要用文本描述去逼近投入产出比很低。一个我反复验证过的经验描述越具体结果越可控。与其说画个好看的支架不如说一个 L 形支架竖板 80×60×8横板 60×40×8竖板顶部两个直径 8 的通孔孔中心距竖板顶边 15水平间距 30。后者几乎每次都能一次成型前者十次有八次需要返工。还有一点值得说别指望一次生成就完美。把 text-to-cad 当成一个能快速迭代的草稿工具生成、检查、调整描述、再生成这个循环跑起来之后效率提升才真正体现出来。我现在的平均迭代次数是两到三次比一开始的七八次已经好很多靠的就是把描述写得更结构化、把校验做得更前置。最后分享一个我最近才想明白的点text-to-cad 的价值不只是省时间更是把设计意图显式化。当你被迫用文字把每个尺寸、每个特征说清楚的时候其实是在逼自己把需求想明白。很多时候生成失败根源不是工具不行而是我自己都没想清楚到底要什么。这个副产品可能比生成模型本身更有意义。