ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

text-to-cad实战:从自然语言到STEP/GLB/STL的几何生成全链路

text-to-cad实战:从自然语言到STEP/GLB/STL的几何生成全链路 1. 从一段文字到三维实体text-to-cad 到底在解决什么问题第一次听到 text-to-cad 这个词很多人会下意识觉得它是个噱头——用一句话生成一个能直接开模的零件听起来像是把工业设计当成了聊天。但真正在机械、建筑、工业设计一线待过的人会明白这个方向瞄准的痛点非常具体从设计意图到可制造几何体之间的那道鸿沟长期依赖人工建模来填。一个熟练的 CAD 工程师画一个带倒角、螺纹孔、加强筋的支架快则半小时慢则半天而其中大量时间花在重复性的草图约束、拉伸、打孔、阵列上。text-to-cad 想做的就是把这部分重复劳动压缩成一段自然语言描述让程序直接吐出 STEP、GLB 或 STL 这类标准几何文件。它的核心价值不在于替代设计师而在于把描述变成可编辑的几何中间态。你输入一个 80mm × 60mm × 5mm 的底板四角各一个直径 6mm 的沉头孔中心有一个高 20mm 的圆柱凸台系统输出的不应该是一张图片而是一个带参数化特征的实体模型能导出成 STEP 拿去 CAM 加工或者转成 STL 直接丢进切片软件。这背后涉及三个关键环节自然语言到结构化参数的解析、参数到几何特征的映射、几何特征到标准格式的序列化。任何一个环节掉链子出来的东西就是看着像但没法用。适合关注这个方向的人其实比想象中广。做机械设计的想知道能不能用它快速出概念方案做 3D 打印的想用它批量生成可打印模型做建筑和室内设计的想用它把文字需求转成体块模型甚至做游戏和 AR 的也想用它快速产出低模资产。关键词里出现的 STEP、GLB、STL 正好对应了三条主流出口STEP 面向精密制造GLB 面向实时渲染和 Web 展示STL 面向增材制造。理解这三者的差异是理解 text-to-cad 整个技术栈的起点。我在这篇文章里不会给你画大饼而是把这条链路拆开讲清楚每一步实际怎么做、用什么工具、参数怎么定、坑在哪里。你会看到从文本解析到几何生成的具体思路也会看到导出不同格式时那些文档里不会写的细节。如果你手上正好有 Python 环境很多代码可以直接跑起来验证。2. 文本如何变成几何参数解析层的真实工作方式2.1 为什么不能直接让大模型输出 CAD 命令很多人第一反应是既然有大语言模型直接让它输出 AutoCAD 的 LISP 脚本或者 FreeCAD 的 Python 脚本不就行了我试过这条路结论是能跑通但极不稳定。原因在于大模型对空间关系的理解是概率性的它可能把孔在凸台左侧理解成完全相反的方向也可能在尺寸链上自相矛盾——前面说底板厚 5mm后面倒角却写了 R8。更致命的是CAD 脚本对语法和坐标精度极其敏感一个括号错位或者单位混淆整个模型就废了。所以实际可用的方案是两段式解析先用语言模型把自然语言抽成结构化的 JSON 参数再用确定性的几何内核去消费这些参数。JSON 里只放尺寸、位置、特征类型这些离散信息几何内核负责把它们变成实体。这样做的好处是语言模型只做它擅长的语义理解几何计算交给专门的库误差不会累积。一个典型的中间结构大概长这样{ base: {type: box, length: 80, width: 60, height: 5}, features: [ {type: hole, subtype: counterbore, diameter: 6, countersink_d: 11, depth: 3, positions: [[10,10],[70,10],[10,50],[70,50]]}, {type: boss, diameter: 20, height: 20, position: [40,30]} ], units: mm }这个结构里每个字段都是可校验的。比如positions必须在底板范围内countersink_d必须大于diameter这些约束可以在解析后立刻检查不合法就报错让用户改描述而不是等到生成几何时崩溃。2.2 尺寸和单位的歧义处理自然语言里最容易被忽略的是单位。做一个 80 的板子这个 80 是毫米还是厘米在机械语境下默认毫米在建筑语境下可能是厘米甚至米。我的做法是在解析层强制要求单位归一化如果用户没写单位根据关键词判断场景——出现螺纹沉头倒角就按毫米出现房间墙体层高就按毫米但数值放大到建筑尺度出现英寸inch就按 25.4 换算。这个判断逻辑不复杂但能避免大量低级错误。另一个坑是尺寸链的闭合。用户说底板 80 宽两边各留 10中间放一个 60 的凸台这里 10601080 刚好闭合。但如果用户说底板 80 宽两边各留 15中间放一个 60 的凸台15601590 就超了。解析层必须做这种算术校验发现矛盾时给出明确提示而不是默默把凸台缩小或者让孔跑到板子外面去。2.3 特征顺序对几何结果的影响同样一组特征建模顺序不同结果可能完全不同。先打孔再拉伸凸台和先拉伸凸台再打孔如果孔的位置和凸台重叠前者会在凸台上留下孔后者可能孔被凸台覆盖。text-to-cad 的解析层需要推断一个合理的特征顺序通常的规则是基础实体优先减材料特征孔、槽在后加材料特征凸台、筋在减材料之前。但这个规则不是绝对的如果用户明确说在凸台上打一个通孔那孔就必须在凸台之后。我在实际项目里采用的是一个简单的优先级队列基础体 → 加材料 → 减材料 → 倒角/圆角 → 阵列。这个顺序覆盖了大多数机械零件的建模习惯遇到特殊情况再让用户用先…再…的句式显式指定顺序。别小看这个顺序问题它直接决定了生成的 STEP 文件在后续 CAM 编程时好不好选面。3. 几何内核选型为什么我最终选了 CadQuery 而不是直接调 OpenCASCADE3.1 几种主流路线的对比要把参数变成实体绕不开几何内核。市面上的选择大概有这么几类直接调 OpenCASCADE 的 C 接口、用 FreeCAD 的 Python API、用 CadQuery 或 build123d 这类高层封装、以及用 trimesh 这类面向网格的库。我前后试过其中三种最后落在 CadQuery 上原因不是它最强而是它在开发效率和几何精度之间取得了最好的平衡。方案几何精度开发效率参数化能力适合场景OpenCASCADE 原生最高低强大型商业软件内核FreeCAD API高中强桌面端脚本化CadQuery高高强服务端批量生成trimesh中网格高弱3D 打印、渲染OpenCASCADE 是工业级内核STEP 导出质量最好但它的 API 是 C 风格Python 绑定用起来很啰嗦画一个带孔板子要写几十行。FreeCAD 的 API 友好一些但它依赖整个 FreeCAD 运行环境部署到服务器上比较重。trimesh 处理 STL 很顺手但它本质是网格操作做不了真正的参数化实体倒角、螺纹这些特征很难精确表达。CadQuery 的好处是它基于 OpenCASCADE但用 Python 的链式调用把常用操作封装得很干净。画一个带四个沉头孔的底板核心代码不到十行import cadquery as cq result ( cq.Workplane(XY) .box(80, 60, 5) .faces(Z) .workplane() .rect(60, 40, forConstructionTrue) .vertices() .cboreHole(6, 11, 3) .faces(Z) .workplane() .circle(10) .extrude(20) ) cq.exporters.export(result, bracket.step)这段代码生成的实体是真正的 B-rep 实体导出 STEP 后每个面都是精确的解析曲面不是三角面片近似。这一点对后续加工至关重要。3.2 安装 CadQuery 时最容易卡住的地方CadQuery 的安装是新手第一个坎。它依赖 OpenCASCADE 的 Python 绑定在 Windows 上直接用 pip 装经常报编译错误。我的建议是用 conda 装命令是conda install -c conda-forge cadquery它会自动拉取预编译好的二进制包。如果非要用 pip至少确保 Python 版本在 3.9 到 3.11 之间3.12 以上有些依赖还没跟上。另一个常见问题是中文字体路径。CadQuery 导出某些格式时需要字体支持如果系统字体路径有中文偶尔会报编码错误。解决办法是在代码开头显式设置os.environ[CADQUERY_FONT_PATH]指向一个纯英文路径的字体文件。这个坑很隐蔽报错信息也不直接我第一次遇到时排查了两个小时。3.3 从参数到实体的映射逻辑解析层给出的 JSON 需要一套映射规则变成 CadQuery 调用。我的做法是写一个分发器根据type字段调用对应的构建函数。基础体直接调box或cylinder孔特征根据subtype调hole、cboreHole或cskHole凸台用circle加extrude。位置信息统一用工作平面的坐标变换来处理避免在全局坐标里硬算。这里有个经验所有特征都相对于当前工作平面定位而不是全局坐标。因为一旦基础体旋转了全局坐标就全乱了。CadQuery 的workplane()和faces()选择器能让你始终在正确的局部坐标系里操作这是它比裸 OpenCASCADE 好用的核心原因。4. 导出 STEP、GLB、STL三种格式的脾气完全不同4.1 STEP 是给制造用的精度不能妥协STEP 是 text-to-cad 输出里最重的格式它保留完整的 B-rep 边界表示每个圆柱面是真正的圆柱面每个平面是真正的平面。CAM 软件读 STEP 后能直接识别孔的中心轴、面的法向编程时选面选边都很准。导出 STEP 时唯一需要注意的是单位CadQuery 默认导出毫米如果你的模型是按厘米建的导出前要乘 10否则到了加工端尺寸差十倍。cq.exporters.export(result, part.step, cq.exporters.ExportTypes.STEP)STEP 的缺点是文件大、加载慢一个中等复杂度的零件可能几 MB网页端展示不友好。所以它适合做最终交付不适合做预览。4.2 GLB 是给眼睛看的面数要控制GLB 是 glTF 的二进制版本本质是三角网格加材质适合在浏览器和移动端实时渲染。从 CadQuery 的实体转 GLB需要先做网格化tessellation把解析曲面离散成三角面片。这里的关键参数是线性偏差和角度偏差偏差越小网格越密、文件越大。我的经验值是线性偏差 0.1mm、角度偏差 0.3 弧度这个精度下肉眼看不出棱角文件大小也可控。cq.exporters.export(result, part.glb, cq.exporters.ExportTypes.GLB, tolerance0.1, angularTolerance0.3)注意 GLB 导出后就没有参数化信息了它只是一个壳。如果你想让用户在网页上旋转查看GLB 是最佳选择但如果用户想下载后继续编辑必须给 STEP。4.3 STL 是给打印机用的法向一致性是命门STL 只存三角面片和法向不存颜色和材质是 3D 打印切片软件的通用输入。从实体转 STL 和转 GLB 类似但有一个额外要求法向必须一致朝外。如果法向乱了切片软件会分不清内外可能把实体当成空腔。CadQuery 导出的 STL 默认法向是正确的但如果你中间经过了布尔运算或者网格修复就要用 trimesh 检查一遍import trimesh mesh trimesh.load(part.stl) trimesh.repair.fix_normals(mesh) mesh.export(part_fixed.stl)还有一个坑是STL 的单位。STL 文件本身不记录单位切片软件默认按毫米读。如果你的模型是英寸建的导出 STL 前必须换算成毫米否则打印出来尺寸完全不对。这个错误在 3D 打印社区里非常常见我见过有人打出来的零件小了 25.4 倍还以为是打印机故障。4.4 三种格式的转换链路实际项目里经常需要从一种格式转到另一种。比如用户上传了一个 STL想转成 STEP 继续编辑。这里要泼一盆冷水STL 转 STEP 不是格式转换而是逆向工程。STL 只有三角面片没有曲面信息转成 STEP 需要先做面片拟合把平面、圆柱面、锥面识别出来再重建 B-rep。这个过程的精度损失很大一个原本光滑的圆柱面可能被拟合成几十个小平面。所以如果源头能拿到 STEP千万不要用 STL 中转。反过来STEP 转 STL 或 GLB 是降维操作信息有损但可控是常规做法。我的建议是始终保留 STEP 作为主格式STL 和 GLB 按需生成不要反过来。5. 实测中那些文档不会告诉你的坑5.1 布尔运算失败几何内核的经典难题做 text-to-cad 绕不开布尔运算——打孔是减运算加凸台是加运算。OpenCASCADE 的布尔运算在大多数情况下可靠但遇到相切面、共面、极小间隙时经常失败报错信息通常是Boolean operation failed或者直接返回空结果。我遇到过最诡异的一次是一个孔的位置刚好在底板边缘上孔壁和底板侧面共面布尔减运算直接崩了。解决办法有两个一是在解析层做几何预检如果孔的位置距离边缘小于孔径的一半就提示用户调整位置或者自动把孔改成缺口二是在布尔运算前做微小偏移把相切变成明确相交或明确分离比如把孔的中心往外挪 0.01mm。第二种方法有点脏但在批量生成场景下很有效。5.2 倒角和圆角的顺序陷阱倒角和圆角是提升零件质感的关键但它们对顺序极其敏感。如果你先给底板所有边倒了 R2 的角再在底板上打一个靠近边缘的孔孔可能会切掉一部分倒角产生一个奇怪的曲面。正确的顺序通常是先做所有减材料特征再统一倒角。但如果是铸造件拔模斜度和圆角又有另一套规则。我的做法是在 JSON 里把倒角/圆角单独列为一个阶段等所有实体特征都完成后统一应用。如果用户明确要求某个特征在倒角之后再用显式顺序覆盖。这个策略覆盖了 90% 的机械零件场景。5.3 批量生成时的内存泄漏如果你要做的是服务端批量生成比如一次处理几百个描述会发现 CadQuery 跑着跑着内存就上去了。原因是 OpenCASCADE 的对象在 Python 里不会自动回收需要显式清理。我的做法是每个模型生成完就重启一个子进程用multiprocessing池来管理。虽然启动开销大一点但稳定性好得多。另一个办法是在循环里手动调gc.collect()但效果不如进程隔离彻底。5.4 中文描述的分词和同义词中文用户描述零件时用词很随意打个洞开个孔钻个眼都是一个意思倒个角修个边做圆角也可能指同一件事。解析层需要维护一个同义词表把这些口语化表达映射到标准特征名。这个表不需要很大覆盖几十个常用词就能显著提升解析成功率。另外中文里尺寸经常和特征连在一起写比如四个M6的孔需要把M6识别为螺纹规格而不是直径 6mm 的普通孔。6. 把 text-to-cad 接进实际工作流的几种姿势6.1 作为设计前端的快速概念工具最轻量的用法是把它当成一个草图加速器。设计师在早期概念阶段用文字快速生成几个体块方案导出 GLB 丢进渲染器看比例确定方向后再用传统 CAD 精细建模。这个场景下不需要 STEP 精度GLB 足够生成速度比手画快很多。我自己的习惯是先用 text-to-cad 出三四个变体截图对比选定一个后再手动细化。6.2 作为参数化零件库的生成引擎如果你有一批结构相似、尺寸不同的零件比如不同规格的法兰、支架、连接件text-to-cad 可以配合模板批量生成。做法是把模板里的可变尺寸抽成参数用一段描述或者一个 CSV 表格驱动一次性生成几十个 STEP 文件。这比在 CAD 里一个个改参数快得多而且不容易出错。关键词里提到的python批量对cad修改其实就是这个思路的另一种实现。6.3 作为 3D 打印的按需建模入口3D 打印用户经常需要一些简单的功能性零件比如手机支架、线缆夹、抽屉分隔件。这些零件结构简单但每个人需要的尺寸不同。text-to-cad 可以让用户用一句话描述需求直接生成可打印的 STL。这个场景对精度要求不高但对可打印性要求高——壁厚不能太薄、悬垂角度不能太大、底面要平整。解析层需要内置这些打印约束生成时自动检查并提示。6.4 和现有 CAD 软件的配合text-to-cad 生成的 STEP 可以导入 SolidWorks、中望 CAD、Fusion 360 等软件继续编辑。导入后通常是一个哑实体没有特征树但尺寸和几何是准确的。如果需要修改可以在导入的实体上继续做特征或者回到 text-to-cad 改描述重新生成。我的建议是把 text-to-cad 当成上游的概念生成器把传统 CAD 当成下游的精细编辑器两者不是替代关系。7. 几个我踩过之后才明白的实操心得第一个心得关于描述的具体程度。刚开始用的时候我总想一句话说清楚整个零件结果解析出来经常缺胳膊少腿。后来发现把描述拆成基础形状 特征列表 尺寸三段式解析成功率会高很多。比如不说做一个带四个孔和中间凸台的板而是说基础是一个 80×60×5 的板四个角各一个 M6 沉头孔中心一个直径 20 高 20 的凸台。结构化的描述让解析层少做很多猜测。第二个心得关于验证环节不能省。生成的 STEP 不要直接拿去加工一定要先做几何检查体积是否合理、包围盒尺寸是否和描述一致、有没有非流形边。CadQuery 自带val().Volume()和val().BoundingBox()几行代码就能做基本校验。我吃过一次亏一个孔的布尔运算静默失败了模型看起来正常但孔没打穿如果直接加工就是一批废件。第三个心得关于版本锁定。CadQuery 和 OpenCASCADE 的版本更新有时会改变几何算法的行为同一个脚本在不同版本下生成的模型可能有细微差异。生产环境一定要锁定版本号并且在升级前用一组标准测试用例回归验证。这个习惯是从一次线上事故后养成的——升级后某个倒角算法变了导致一批零件的边缘尺寸超差。第四个心得关于别追求全自动。text-to-cad 目前的能力边界很清楚简单零件、规则结构、明确描述它能做得很好复杂曲面、自由造型、模糊需求它力不从心。与其硬撑全自动不如设计成人机协作——机器出初稿人做审核和微调。这个定位反而让它在实际工作流里更容易落地因为用户对它的预期是合理的。最后说一个关于格式选择的小技巧。如果你的模型最终要进 Unity 或 Unreal 做交互展示GLB 导出时记得勾选嵌入材质否则模型到了引擎里是灰的。如果要做 AR 展示GLB 的面数控制在 5 万三角面以内否则手机端会卡。这些细节看起来小但直接影响最终交付效果。
返回列表