news 2026/10/9 14:40:21

text-to-cad 实战:从文本解析到 STEP/STL/GLB 导出全链路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
text-to-cad 实战:从文本解析到 STEP/STL/GLB 导出全链路

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

第一次听到 "text-to-cad" 这个词,很多人脑子里浮现的画面大概是:对着电脑敲一句"给我画一个法兰盘",然后屏幕上就自动长出一个三维模型。这个想象不算离谱,但真正落地的时候,它解决的问题比"自动画图"要具体得多,也琐碎得多。

我接触这个方向是从一个很实际的需求开始的:手头有一批标准件,规格参数都躺在 Excel 表格里,但每次要出模型都得手动在 CAD 里拉伸、打孔、倒角,一个两个还好,上百个就是纯体力活。后来我想,既然参数是结构化的文本,模型是结构化的几何,那中间这段"翻译"工作为什么不能自动化?这就是 text-to-cad 的核心命题——把自然语言或结构化文本描述,转换成可用的 CAD 几何文件。

它输出的东西通常不是某个私有格式,而是几种通用交换格式:STEP(保留精确边界表示 B-rep,适合后续在专业 CAD 里继续编辑)、STL(三角网格,3D 打印和快速预览的通用语言)、GLB(带材质和层级信息的二进制 glTF,适合网页端和可视化场景)。这三种格式基本覆盖了从"要精度"到"要好看"到"要能打印"的全部需求。

适合看这篇内容的人,我大致分三类。第一类是做参数化建模的工程师,手里有大量重复性建模任务,想用脚本或 AI 提效;第二类是做 3D 打印和创客的玩家,想用一句话生成一个能打印的模型,省去学建模软件的时间;第三类是做工具链集成的开发者,想把 text-to-cad 能力嵌进自己的产品里,比如在线定制、电商预览、教育演示。这三类人的关注点不一样,但底层要打通的链路是同一套。

需要先泼一盆冷水:text-to-cad 目前不是"许愿机"。你输入"一个好看的杯子",它给不了你惊喜;但你输入"外径 80mm、内径 70mm、高 100mm、底部封闭的圆柱壳",它能给你一个精确的实体。所以理解它的能力边界,比盲目期待它"懂设计"要重要得多。下面我会把这条链路从文本解析、几何生成、格式导出到实际踩坑,一层层拆开讲。

2. 文本描述怎么变成几何参数:解析层的关键设计

2.1 为什么不能直接让大模型"画"出几何

很多人第一反应是:现在大模型这么强,直接让它输出 CAD 文件不就行了?我试过,结论是能出,但不能用。原因在于大模型生成的是 token 序列,它对"这个面是不是真的闭合""这两个实体有没有干涉""这个圆角半径是不是超过了壁厚"没有几何层面的校验能力。它可能给你一段看起来很像 STEP 的文本,但里面实体拓扑是错的,导入 CAD 直接报错。

所以正确的架构是两段式:第一段用语言模型做"语义到参数"的抽取,第二段用确定性的几何内核做"参数到实体"的构建。语言模型负责理解"外径 80、壁厚 5"这种表达,几何内核负责保证结果在数学上成立。这个分工是整个 text-to-cad 系统能不能稳定跑起来的分水岭。

2.2 参数抽取的三种输入形态

实际项目里,输入文本的规整程度差别很大,我一般按三种形态分别处理:

  • 完全结构化:像{"type":"cylinder","od":80,"id":70,"h":100}这种 JSON 或键值对。这种最好办,直接映射到几何内核的 API,几乎不需要语言模型介入,稳定性最高。
  • 半结构化:像"圆柱壳,外径80,内径70,高100,单位毫米"。这种需要做实体识别和单位归一,用规则加小模型就能搞定,准确率能到 95% 以上。
  • 自由自然语言:像"帮我做一个大概巴掌大的圆筒,壁别太厚"。这种最考验解析层,需要模型推断尺寸范围、默认壁厚、甚至补全缺失的约束。

我的经验是,不要指望解析层一步到位。更稳的做法是解析出一个"参数草案",然后回显给用户确认或微调。比如系统解析出"外径 80mm、壁厚 5mm",先展示出来让用户改,改完再生成。这一步交互能挡掉大量因为歧义导致的错误模型。

2.3 单位与坐标系:最容易被忽略的隐形坑

单位问题我在项目里栽过不止一次。文本里写"直径 80",到底是毫米还是厘米?如果解析层默认毫米,用户其实想的是厘米,出来的模型就小了十倍,3D 打印出来是个指甲盖大小的东西。强制单位归一是必须的:所有输入统一转成毫米,内部计算全程毫米,导出时再按目标格式决定是否转换。

坐标系同样关键。STEP 和 STL 对原点的约定不同,STL 很多切片软件默认模型要落在正 Z 半轴且底面贴 Z=0,而 STEP 里原点可以随便放。如果生成时不管坐标系,导出的 STL 可能在切片软件里"飘"在平台下方,用户还得手动挪。我的做法是在几何构建阶段就把模型底面归到 Z=0,几何中心对齐 X/Y 原点,这样导出的 STL 直接能打印,STEP 导入后位置也符合直觉。

2.4 约束求解:让参数"自洽"的那一步

参数抽出来不代表能直接建模。举个真实例子:用户说"外径 80、内径 85",这明显矛盾,内径比外径还大。如果直接丢给几何内核,要么报错,要么生成一个负壁厚的诡异实体。所以在参数和几何之间,需要一层约束校验:

校验项规则处理方式
尺寸正负所有长度参数 > 0报错并要求修正
内外关系内径 < 外径自动交换或提示
壁厚下限壁厚 ≥ 最小可制造厚度警告并建议值
圆角半径半径 < 相邻壁厚自动裁剪到安全值
孔位干涉孔不超出实体边界提示并高亮冲突

这层校验看起来不起眼,但它是"生成能用模型"和"生成报错模型"之间的那道闸门。我建议把校验规则做成可配置的,因为不同工艺(3D 打印、CNC、钣金)对最小壁厚、最小孔径的要求完全不同。

3. 几何内核选型:OpenCASCADE、CGAL 还是自研

3.1 为什么几何内核是 text-to-cad 的心脏

解析层把文本变成了参数,接下来要把参数变成真正的几何体。这一步靠的是几何建模内核,它负责布尔运算、倒角、抽壳、曲面求交这些底层操作。内核选得好,后面省一半力气;选得不好,光是布尔运算的稳定性问题就能拖垮整个项目。

目前开源圈子里主流的选择是OpenCASCADE(OCCT),它支持精确 B-rep 表示,能直接导出 STEP,布尔运算和倒角能力在开源里算最成熟的。另一个是CGAL,它在计算几何、网格处理上很强,但做实体建模和 STEP 导出不如 OCCT 顺手。还有一类是纯网格路线,用trimesh或Open3D直接操作三角网格,优点是轻量、快,缺点是精度和 STEP 导出能力弱。

3.2 三种路线的实测对比

我把三条路线都跑过一遍,结论如下表:

路线代表库STEP 导出布尔稳定性上手难度适用场景
精确 B-repOpenCASCADE原生支持高中高工程件、需后续编辑
计算几何CGAL需转换中高复杂曲面、网格优化
纯网格trimesh/Open3D不支持低低3D 打印、可视化预览

如果你的目标是"生成能进专业 CAD 继续改的模型",OCCT 基本是唯一解。如果只是"生成一个能打印的网格",trimesh 足够,而且开发速度快得多。我自己的项目是双轨:简单件走 trimesh 快速出 STL,复杂件走 OCCT 出 STEP。

3.3 OCCT 的 Python 绑定:pythonocc 的坑与技巧

OCCT 原生是 C++,Python 侧一般用pythonocc-core。装它是个坎,conda 装最省事:

conda install -c conda-forge pythonocc-core

pip 装经常因为编译依赖失败,我踩过好几次,最后老老实实回到 conda。装好之后,构建一个圆柱壳的代码大概长这样:

from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeCylinder from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Cut from OCC.Core.gp import gp_Ax2, gp_Pnt, gp_Dir # 外圆柱 outer = BRepPrimAPI_MakeCylinder(40, 100).Shape() # 半径40,高100 # 内圆柱,用于挖空 inner = BRepPrimAPI_MakeCylinder(35, 100).Shape() # 布尔差 shell = BRepAlgoAPI_Cut(outer, inner).Shape()

这段代码看着简单,但有几个坑:布尔运算前两个实体必须有明确的位置关系,否则可能得到空结果;半径参数是半径不是直径,从文本解析来的"外径80"要除以2;布尔运算后要检查IsDone(),失败时得回退或调整容差。

3.4 容差设置:布尔运算失败的元凶

OCCT 的布尔运算偶尔会失败,尤其是两个面几乎相切或者间隙极小时。默认容差是 1e-7 米级别,对于毫米单位的模型,这个容差有时候太严。我的做法是在布尔运算前统一把模型缩放到米制(OCCT 内部习惯用米),运算完再缩回来,这样容差和几何尺度匹配,成功率明显提升。这个技巧在官方文档里不显眼,但实战里非常管用。

4. 三种导出格式的取舍:STEP、STL、GLB 各管什么

4.1 STEP:要精度、要可编辑就选它

STEP(.step/.stp)是工程界的通用交换格式,它保存的是精确的边界表示,圆弧就是圆弧,平面就是平面,不是用三角面片逼近的。这意味着导入 SolidWorks、中望 CAD、Fusion 360 之后,你还能继续拉伸、打孔、改尺寸。如果你的 text-to-cad 产物要进正规设计流程,STEP 是首选。

导出 STEP 用 OCCT 的STEPControl_Writer:

from OCC.Core.STEPControl import STEPControl_Writer, STEPControl_AsIs writer = STEPControl_Writer() writer.Transfer(shell, STEPControl_AsIs) writer.Write("output.step")

注意STEPControl_AsIs这个模式,它保留原始几何不做额外处理,适合精确件。如果模型有大量小面片,导出文件会很大,这时候可以考虑先做形状简化再导出。

4.2 STL:3D 打印和快速预览的通用语

STL 只存三角网格,没有单位、没有材质、没有层级,就是一堆三角形。它的好处是几乎所有切片软件、3D 打印工具、网格处理软件都认。缺点是精度靠网格密度控制,密度低了圆变多边形,密度高了文件巨大。

导出 STL 的关键参数是线性偏差(linear deflection)和角度偏差(angular deflection)。线性偏差控制弦高误差,角度偏差控制相邻面片夹角。我的经验值:一般件线性偏差 0.1mm、角度偏差 0.5 弧度,出来的网格既光滑又不至于太大。精密件可以调到 0.01mm,但文件可能翻好几倍。

from OCC.Core.StlAPI import StlAPI_Writer from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh # 先网格化 BRepMesh_IncrementalMesh(shell, 0.1, False, 0.5, True) writer = StlAPI_Writer() writer.Write(shell, "output.stl")

4.3 GLB:网页展示和带材质场景的答案

GLB 是 glTF 的二进制版,天生为实时渲染设计。它支持材质、颜色、层级、动画,文件小、加载快,网页端 three.js、Babylon.js 直接能读。如果你做的是在线定制、产品预览、教育演示,GLB 是最合适的输出。

从 OCCT 的 B-rep 转 GLB 一般要经过网格化,再写 glTF。Python 侧可以用trimesh中转:

import trimesh mesh = trimesh.load("output.stl") mesh.export("output.glb")

这条路简单,但会丢掉精确几何,只剩网格。如果对材质有要求,可以在 trimesh 里给 mesh 赋颜色和材质再导出。

4.4 格式选择的决策表

需求首选格式理由
后续在 CAD 里继续编辑STEP保留精确 B-rep
3D 打印STL切片软件通用
网页/APP 实时预览GLB轻量、带材质
跨软件交换且要精度STEP工程标准
快速看形状STL/GLB生成快

我一般让系统同时导出三种格式,用户按需下载。存储成本不高,但省去了"我要的格式没有"的尴尬。

5. 从零跑通一个最小可用版本:完整实操链路

5.1 环境准备与依赖清单

先把环境搭起来。我推荐 Python 3.10 加 conda,依赖如下:

conda create -n text2cad python=3.10 conda activate text2cad conda install -c conda-forge pythonocc-core trimesh numpy pip install openai # 如果要用语言模型做解析

pythonocc-core负责几何,trimesh负责网格和 GLB 中转,numpy做数值处理。语言模型部分按你的方案选,本地模型或 API 都行。

5.2 解析层:把一句话拆成参数字典

假设输入是"外径80毫米、内径70毫米、高100毫米的圆柱壳",解析层要输出:

{ "type": "cylinder_shell", "outer_diameter": 80.0, "inner_diameter": 70.0, "height": 100.0, "unit": "mm" }

如果用规则解析,正则匹配"外径(\d+)"这类模式就够。如果用语言模型,给它一个明确的 JSON schema,让它按格式输出,再校验字段完整性。校验这一步不能省,模型偶尔会漏字段或给字符串,直接进几何层就崩。

5.3 几何层:参数到实体的构建函数

def build_cylinder_shell(od, id_, h): outer_r = od / 2 / 1000.0 # 转米 inner_r = id_ / 2 / 1000.0 h_m = h / 1000.0 outer = BRepPrimAPI_MakeCylinder(outer_r, h_m).Shape() inner = BRepPrimAPI_MakeCylinder(inner_r, h_m).Shape() result = BRepAlgoAPI_Cut(outer, inner).Shape() if result.IsNull(): raise ValueError("布尔运算失败,请检查参数") return result

注意这里先转米再建模,就是为了配合 OCCT 的容差习惯。导出前再转回毫米或按格式要求处理。

5.4 导出层:一次生成三种格式

def export_all(shape, basename): # STEP from OCC.Core.STEPControl import STEPControl_Writer, STEPControl_AsIs w = STEPControl_Writer() w.Transfer(shape, STEPControl_AsIs) w.Write(f"{basename}.step") # STL from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh from OCC.Core.StlAPI import StlAPI_Writer BRepMesh_IncrementalMesh(shape, 0.1, False, 0.5, True) StlAPI_Writer().Write(shape, f"{basename}.stl") # GLB import trimesh mesh = trimesh.load(f"{basename}.stl") mesh.export(f"{basename}.glb")

跑完这段,你会得到三个文件。STEP 拿去 CAD 改,STL 拿去打印,GLB 拿去网页展示。

5.5 实测中的意外情况

第一次跑通不代表稳定。我实测遇到过的意外包括:布尔运算偶发失败(缩放法解决)、STL 网格出现破面(调小线性偏差)、GLB 材质丢失(trimesh 导出时手动赋材质)、STEP 导入某些软件后单位错乱(导出时显式写单位)。这些问题在 demo 里不出现,一上量就冒出来,所以批量生成前一定要做小样本验证。

6. 踩坑实录:那些让模型"看起来对但用不了"的细节

6.1 壁厚为零的"纸片实体"

有次用户输入"外径80、内径80",解析层没拦住,几何层布尔差出来一个空壳,导出的 STL 是一层零厚度的面片,切片软件直接报错。根因是约束校验缺失。修复方案是在参数层加"内径必须小于外径至少 0.5mm"的硬规则,不满足就拒绝生成并提示。

6.2 STL 在切片软件里"飘"在平台下方

前面提过坐标系问题。OCCT 默认以原点为中心建圆柱,底面在 Z=-h/2。切片软件期望底面在 Z=0,结果模型一半在平台下。修复是建模后整体平移,把最小 Z 归零:

from OCC.Core.Bnd import Bnd_Box from OCC.Core.BRepBndLib import brepbndlib box = Bnd_Box() brepbndlib.Add(shape, box) xmin, ymin, zmin, xmax, ymax, zmax = box.Get() # 平移使 zmin=0,xy 居中

这个平移步骤我建议做成导出前的标准动作,别指望用户手动挪。

6.3 圆角半径大于壁厚导致的失败

用户说"边缘倒个 R5 的圆角",但壁厚只有 3mm。OCCT 倒角会失败或产生自交。修复是在参数层做圆角半径与相邻壁厚的比较,超过就自动裁剪到壁厚的 80% 并提示用户。这个"自动裁剪加提示"的策略比直接报错体验好得多。

6.4 批量生成时的内存泄漏

用 OCCT 批量生成几百个模型时,内存会持续上涨。原因是 OCCT 的 C++ 对象需要显式释放,Python 的 GC 管不到。解决是每生成一批后手动清理,或者用子进程隔离,跑完就退出。这个坑很隐蔽,单次生成看不出来,一上量就 OOM。

6.5 中文参数描述的解析歧义

"直径80"和"半径80"差一倍,"高100"和"厚度100"在不同语境下含义不同。我的处理是在解析层维护一个同义词表,把"直径/外径/OD"归一到 outer_diameter,把"半径/R"归一到 radius,并且优先要求用户用明确词汇。自由文本解析的准确率永远做不到 100%,所以回显确认这一步是刚需。

7. 把 text-to-cad 接进真实工作流的几种姿势

7.1 批量标准件生成

这是最直接的落地场景。把 Excel 里的规格表读进来,每行生成一个模型,批量导出 STEP 和 STL。我做过一个项目,300 多个法兰、垫片、套筒,原来手动建模要两天,脚本跑完不到十分钟。关键是参数表要规范,列名和解析层的字段对齐,否则还得写映射。

7.2 在线定制与即时预览

电商或定制类产品,用户填几个尺寸,后台生成 GLB 推到前端 three.js 预览,确认后生成 STEP 下单生产。这条链路里GLB 的生成速度是关键,因为用户等不了太久。我的优化是 GLB 走轻量网格路线,STEP 异步生成,用户确认后再出。

7.3 教育演示与参数化教学

教 CAD 的时候,让学生用一句话描述模型,系统实时生成,直观展示"参数怎么影响形状"。这种场景对精度要求不高,但对响应速度和可视化要求高,GLB 加网页渲染是最佳组合。

7.4 与现有 CAD 工具的衔接

生成的 STEP 可以直接拖进 SolidWorks、中望 CAD、Fusion 360。如果要做二次开发,很多 CAD 提供 API,可以把 text-to-cad 的解析层嵌进去,做成插件。这块要注意不同 CAD 对 STEP 版本的支持差异,导出时选兼容性好的版本(如 AP214)。

8. 关于精度、性能与扩展性的一些个人经验

8.1 精度不是越高越好

新手容易陷入"精度越高越好"的误区,把 STL 的线性偏差调到 0.001mm,结果文件几百 MB,切片软件打开就卡死。精度要匹配用途:3D 打印 FDM 层高 0.2mm,网格精度 0.1mm 足够;光固化可以到 0.05mm;网页预览 0.5mm 都行。按需设置,别一刀切。

8.2 生成速度的瓶颈在哪

实测下来,瓶颈通常在布尔运算和网格化,不在解析。一个中等复杂度的件,解析几十毫秒,布尔运算可能几百毫秒,网格化又是几百毫秒。优化方向是缓存常用几何、并行生成、按需网格化(预览用粗网格,导出用细网格)。

8.3 扩展性:从圆柱壳到任意形状

最小版本只支持圆柱壳,但架构要留扩展口。我的做法是把几何构建做成注册表,每种 type 对应一个构建函数,新增形状只需注册新函数,解析层和导出层不用动。这样从圆柱壳扩展到法兰、齿轮、支架,改动量很小。

8.4 一个容易被忽视的点:错误信息的可读性

用户输入错了,系统报"BRepAlgoAPI_Cut failed"没人看得懂。要把错误翻译成人话,比如"内径不能大于外径,请检查尺寸"。错误信息的质量直接决定用户能不能自己修好问题,这块投入产出比很高。

8.5 版本与依赖管理

OCCT、pythonocc、trimesh 的版本兼容性偶尔会出问题,尤其是跨大版本升级时 API 会变。我的经验是锁定版本,用 conda 环境文件固定,别用 latest。生产环境里,一次意外的依赖升级可能让整套流程崩掉。

最后分享一个我常用的调试技巧:把中间产物都落盘。解析出的参数字典存 JSON,布尔运算后的实体存 BREP,网格化后的存 STL,每一步都能单独检查。出问题时能快速定位是哪一层的事,比在黑盒里猜高效得多。这套链路我从最初的手动建模,到脚本化,再到文本驱动,前后迭代了挺多版,最大的体会是:text-to-cad 的价值不在于"AI 帮你画图"这个噱头,而在于把重复的、参数化的建模工作变成可批量、可复现、可集成的流程。把解析、几何、导出这三层解耦好,剩下的就是按需扩展形状库和优化性能了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 14:35:30

纯Java零依赖手写TopoJSON生成器:从GeoJSON到拓扑压缩

最近我在整理一批地图数据时发现了一个老问题&#xff1a;GeoJSON 格式虽然解析简单、生态成熟&#xff0c;但相邻多边形的公共边界会被重复存储两遍&#xff0c;数据量一上来体积就非常难看。每次做数据下发或者 Web 可视化&#xff0c;光地理数据就要吃掉大量带宽。痛定思痛&…

作者头像 李华
网站建设 2026/10/9 14:35:29

JSP教务管理系统源码还原实战:从.class反编译到可运行工程

简介&#xff1a;这份JSP源码实现了一套完整的教务管理系统&#xff0c;面向Java Web初学者、课程设计学生及需要练手项目的开发者&#xff0c;帮助理解JSP、Servlet与MySQL如何协同构建真实Web应用。压缩包共530个文件&#xff0c;约9.32MB&#xff0c;以412个gif与32个jpg页面…

作者头像 李华
网站建设 2026/10/9 14:35:27

若依微服务多数据源实战:MySQL与达梦数据库双源配置指南

最近在做一个国产化适配的项目&#xff0c;正好踩到了“若依微服务 MySQL 达梦双数据源”这个组合。需求其实很常见&#xff1a;老系统数据还在 MySQL&#xff0c;新系统要求兼容国产数据库&#xff0c;于是要在若依微服务框架里同时连 MySQL 和 DM 数据库&#xff0c;做一套…

作者头像 李华
网站建设 2026/10/9 14:35:02

Stata实现PLS-SEM完整教程:从模型设定到商业洞察

做定量研究的人&#xff0c;应该都听过PLS-SEM这个名字。但坦白说&#xff0c;真正能把PLS-SEM跑出来、再把结果讲清楚的人&#xff0c;比想象中少得多。Stata从17版本开始就内置了plssem命令&#xff0c;不再是只能依赖外部软件的局面&#xff0c;但很多人打开结果窗口后还是不…

作者头像 李华
网站建设 2026/10/9 14:33:54

CnOpenData中国地震震相表解析:从数据清洗到地震定位

先说说我为什么会对这份数据上心。做地震学研究的人都知道&#xff0c;震相表是绕不开的基础数据之一。大到地震定位、走时层析成像&#xff0c;小到一次课程设计里的震相到时拾取&#xff0c;都要和“某个台站在某时某刻记录到了某个震相”这种记录打交道。但现实是&#xff0…

作者头像 李华
网站建设 2026/10/9 14:33:40

编译原理教学手稿的PDF到可执行代码转化实践

简介&#xff1a;本资源是太原理工大学《编译原理》课程配套的实验报告PDF&#xff0c;面向计算机专业本科生及软件开发初学者&#xff0c;聚焦词法分析核心能力训练&#xff0c;解决高级语言编译前端基础实践薄弱问题。报告以“无符号数的词法分析程序”为具体任务&#xff0c…

作者头像 李华