ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

text-to-cad 全链路解析:从文本意图到 STEP/GLB/STL 参数化建模

text-to-cad 全链路解析:从文本意图到 STEP/GLB/STL 参数化建模

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

第一次听到 "text-to-cad" 这个词,很多人会下意识觉得它是个噱头——输入一句话就能生成 CAD 模型?这听起来像是把设计师十几年的经验压缩成一次回车键。但真正在机械设计、工业建模或者 3D 打印这条线上摸爬滚打过的人会明白,这个方向要解决的根本不是"替代设计师",而是把重复性建模劳动从人手里拿走。

传统 CAD 工作流是这样的:打开软件,新建零件,选基准面,画草图,标注尺寸,拉伸/旋转/扫掠,倒角,打孔,导出。一个简单的法兰盘,熟手也要五到十分钟;如果是参数化程度高的标准件,比如齿轮、轴承座、型材连接件,一天下来可能有一半时间花在"改尺寸—重建—再改尺寸"的循环里。text-to-cad 想做的事情,就是让你用自然语言描述几何意图,由系统解析成可执行的建模指令,最终输出 STEP、GLB 或 STL 这类通用格式。

这里必须先把一个概念说清楚:text-to-cad 不是"文字直接变网格"。市面上有些工具确实能根据文字生成一个看起来像那么回事的 3D 模型,但那种模型是三角面片堆出来的,没有特征树、没有参数、没有尺寸约束,拿去 3D 打印勉强能用,拿去改一个孔位就彻底废了。真正有价值的 text-to-cad 管线,中间一定要经过参数化几何内核这一层,最终产出的 STEP 文件里带着 B-Rep(边界表示)信息,能被 SolidWorks、中望 CAD、FreeCAD 这类软件正常打开并继续编辑。

所以这篇文章适合谁看?如果你是机械工程师、产品结构设计师、3D 打印玩家,或者正在做 AI+工业软件方向的产品经理,这篇内容会帮你把 text-to-cad 的完整链路拆开:从文本解析、几何参数映射、内核调用,到 STEP/GLB/STL 三种格式的取舍,再到实际落地时那些文档里不会写的坑。我不会只给你一个"调用某个 API 就完事"的假教程,而是把每一步为什么这么做讲透。

关键词里出现的 CAD、STEP、GLB、STL,正好对应了这条链路的四个关键节点:CAD 是目标场景,STEP 是工程交付格式,GLB 是可视化与 Web 展示格式,STL 是 3D 打印格式。搞懂这四个词之间的关系,text-to-cad 的骨架就立起来了。

2. 文本到几何的中间层:为什么不能跳过参数化内核

2.1 大模型直接输出网格的致命缺陷

现在很多演示视频里,输入"一个带六个孔的圆盘",几秒钟就出来一个模型,转起来还挺好看。但你把那个模型下载下来,用 MeshLab 或者 Blender 打开,会发现它就是一个高密度的三角网格,几万个面片,没有任何语义信息。你想把孔径从 5mm 改成 6mm,对不起,只能重新生成,而且重新生成的结果和上一次可能完全不一样——因为大模型的输出带有随机性。

这在工程场景里是灾难性的。工程设计的核心诉求是可追溯、可修改、可装配。一个零件改了尺寸,装配体里的配合关系要能自动更新;一张图纸改了标注,BOM 表要能联动。三角网格做不到这些,它只是一堆顶点的集合,没有"孔"这个概念,更没有"这个孔的中心在圆盘中心"这种约束关系。

2.2 参数化内核扮演的角色

参数化内核(比如 OpenCASCADE、Parasolid、ACIS)做的事情,是把几何体表示成特征操作的序列加上约束系统。一个圆盘不是"一堆三角形",而是"一个圆柱体,减去六个圆柱形孔,孔沿圆周均布,孔径 d,分布圆直径 D"。这种表示方式下,改一个参数,整个模型按规则重建,结果确定且可预测。

text-to-cad 的正确架构应该是三段式:

  1. 文本理解层:把自然语言解析成结构化的建模意图,比如{shape: "disk", holes: 6, hole_diameter: 5, pitch_circle: 40, thickness: 8}
  2. 几何映射层:把结构化意图翻译成内核能执行的 API 调用序列
  3. 内核执行层:调用 OpenCASCADE 等内核生成 B-Rep,再导出为目标格式

大模型只负责第一层,第二层和第三层是确定性的代码。这样既利用了语言模型的语义理解能力,又保证了几何输出的稳定性和可编辑性。

2.3 一个最小可用的意图结构设计

我在实际项目里用过的一套意图 JSON 结构大概长这样,你可以直接参考:

{ "primitive": "cylinder", "parameters": { "radius": 25, "height": 8 }, "operations": [ { "type": "hole_pattern", "hole_radius": 2.5, "count": 6, "pattern": "circular", "pitch_radius": 20, "axis": "z" } ], "units": "mm" }

这个结构的好处是:每个字段都能直接映射到 OpenCASCADE 的BRepPrimAPI_MakeCylinder和BRepAlgoAPI_Cut调用,不需要做复杂的几何推理。大模型的任务只是把"帮我画一个直径 50、厚 8 毫米的圆盘,上面打六个直径 5 毫米的孔,孔均匀分布在一个直径 40 的圆上"这段话,转成上面这个 JSON。

注意:单位一定要显式声明。我见过太多因为英寸和毫米混淆导致模型放大 25.4 倍的案例,尤其是在对接海外需求或者老图纸时。

2.4 为什么 STEP 是工程交付的底线

STEP(ISO 10303)是工程领域的事实标准交换格式。它用 B-Rep 描述几何,保留了面、边、顶点的拓扑关系,几乎所有主流 CAD 软件都能读写。text-to-cad 如果最终输出的是 STEP,意味着这个模型可以进入正规的设计流程:导入装配体、做干涉检查、出工程图、加工编程。

相比之下,STL 只包含三角面片,没有拓扑,没有单位(虽然文件头可以写,但很多软件忽略),没有颜色和材质。GLB 虽然包含材质和层级,但同样是网格格式,适合展示不适合制造。所以一个负责任的 text-to-cad 工具,应该至少支持 STEP 导出,GLB 和 STL 作为附加选项。

3. 三种输出格式的取舍:STEP、GLB、STL 各自的主场

3.1 STEP:参数化交付的唯一正解

STEP 文件的核心价值在于它是有"结构"的。你用文本编辑器打开一个 STEP 文件,能看到CARTESIAN_POINT、CIRCLE、CYLINDRICAL_SURFACE这些实体定义,而不是一堆坐标数字。这意味着下游软件能识别出"这是一个圆柱面",从而支持选中、修改半径、添加配合。

在 text-to-cad 管线里,STEP 导出通常由内核直接完成。以 OpenCASCADE 为例,导出 STEP 的代码大致是:

STEPControl_Writer writer; writer.Transfer(shape, STEPControl_AsIs); writer.Write("output.step");

看起来简单,但实际踩坑点很多。最常见的是单位问题:OpenCASCADE 内部默认单位是毫米,但 STEP 文件头需要显式写入单位上下文。如果没写对,导入 SolidWorks 后模型可能变成英寸。另一个坑是精度设置,Interface_Static::SetCVal("write.step.unit", "MM")这类参数要提前设好,否则不同软件读出来的结果不一致。

3.2 GLB:Web 展示和快速预览的最优解

GLB 是 glTF 的二进制版本,特点是文件小、加载快、支持 PBR 材质,浏览器原生支持。如果你做的 text-to-cad 工具需要在线预览,GLB 几乎是唯一选择。Three.js、Babylon.js、model-viewer 这些库都能直接加载。

从 B-Rep 转 GLB 需要先做网格化(Tessellation)。这一步的关键参数是线性偏差和角度偏差:

# 伪代码示意 mesh = tessellate(shape, linear_deflection=0.1, angular_deflection=0.5) export_glb(mesh, "output.glb")

linear_deflection控制弦高误差,值越小网格越密、文件越大。0.1mm 对于大多数零件够用,但如果是大尺寸曲面(比如汽车覆盖件),可能需要 0.01 甚至更小。angular_deflection控制相邻面片的最大夹角,0.5 弧度是常用值。

实操心得:GLB 预览时如果发现曲面有棱角感,先别急着怀疑模型,八成是网格化参数太粗。把 linear_deflection 调到 0.05 试试,文件大小会涨但视觉效果明显改善。

3.3 STL:3D 打印的通用语言,但别拿它做设计

STL 是最古老的 3D 打印格式,本质上就是一堆三角形。它的优点是几乎所有切片软件都支持,缺点是没有单位、没有拓扑、没有颜色。你导出一个 STL,切片软件默认按毫米处理,但如果原始模型是英寸,打出来就是错的。

text-to-cad 输出 STL 时,我建议做两件事:一是在文件名里标注单位,比如bracket_mm.stl;二是控制面片数量,太密会导致切片软件卡顿,太疏会导致打印表面粗糙。一般来说,一个手掌大小的零件,5 万到 20 万面片是比较合理的范围。

格式是否保留参数是否含材质典型用途推荐导出场景
STEP是否工程交付、装配、加工需要后续修改的设计
GLB否是Web 预览、AR/VR在线展示、快速查看
STL否否3D 打印、快速成型直接打印、临时验证

3.4 格式转换中的"信息丢失"链条

这里有个很多人忽略的事实:STEP → GLB → STL 是单向不可逆的。你从 STEP 转成 GLB,参数信息就没了;从 GLB 转成 STL,材质和层级也没了。所以 text-to-cad 系统里,STEP 应该作为主存储格式,GLB 和 STL 都是按需生成的派生文件。

我见过一个团队为了省存储,只存 GLB,结果客户要改一个孔位,他们只能让用户重新输入文字生成,体验极差。正确的做法是:原始意图 JSON + STEP 文件一起存,前者用于重新生成,后者用于直接交付。

4. 搭建一条可用的 text-to-cad 管线:从环境到跑通

4.1 内核选型:OpenCASCADE 是开源场景下的默认答案

如果你要做自己的 text-to-cad 工具,几何内核的选择基本决定了技术栈。商业内核 Parasolid 和 ACIS 授权费高、集成复杂,个人开发者和小团队基本不用考虑。开源方案里,OpenCASCADE(简称 OCCT)是唯一成熟且功能完整的选项。

OCCT 提供 C++ 库,也有 Python 绑定(pythonocc-core)。Python 绑定的好处是开发快,适合做原型;缺点是性能不如原生 C++,而且某些高级功能绑定不全。我的建议是:原型阶段用 pythonocc,产品化阶段用 C++ 重写核心链路。

安装 pythonocc-core 最省事的方式是 conda:

conda install -c conda-forge pythonocc-core

装完之后可以跑一个最小验证:

from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeCylinder from OCC.Core.STEPControl import STEPControl_Writer, STEPControl_AsIs cylinder = BRepPrimAPI_MakeCylinder(25, 8).Shape() writer = STEPControl_Writer() writer.Transfer(cylinder, STEPControl_AsIs) writer.Write("test_cylinder.step")

这段代码生成一个半径 25、高 8 的圆柱并导出 STEP。跑通它,说明环境没问题。

4.2 文本解析层:大模型输出结构化 JSON 的提示词设计

大模型在这里的角色是"翻译官",不是"设计师"。提示词要明确约束输出格式,避免它自由发挥。我常用的一段系统提示词是这样的:

你是一个 CAD 建模意图解析器。用户会用自然语言描述一个零件。 你需要输出一个 JSON,包含 primitive(基本体类型)、parameters(尺寸参数)、 operations(后续操作)三个字段。所有尺寸单位默认为毫米。 不要输出任何解释文字,只输出 JSON。

然后用户输入"画一个 50x30x10 的长方体,四个角倒 R3 的圆角",模型应该输出:

{ "primitive": "box", "parameters": {"length": 50, "width": 30, "height": 10}, "operations": [ {"type": "fillet", "radius": 3, "edges": "vertical"} ], "units": "mm" }

这里的关键是约束输出空间。如果你不限制,大模型可能给你输出一段 Python 代码,或者一个它自己编的格式,后续解析会非常痛苦。

4.3 几何映射层:把 JSON 翻译成内核调用

这一层是纯确定性代码,不需要 AI。核心是一个分发器,根据primitive字段调用对应的内核 API,然后按顺序执行operations。

def build_shape(intent): p = intent["parameters"] if intent["primitive"] == "box": shape = BRepPrimAPI_MakeBox(p["length"], p["width"], p["height"]).Shape() elif intent["primitive"] == "cylinder": shape = BRepPrimAPI_MakeCylinder(p["radius"], p["height"]).Shape() # ... 其他基本体 for op in intent.get("operations", []): if op["type"] == "fillet": shape = apply_fillet(shape, op["radius"]) elif op["type"] == "hole_pattern": shape = apply_hole_pattern(shape, op) return shape

倒角和打孔的实现要复杂一些,需要先找到对应的边或面。OCCT 里用TopExp_Explorer遍历拓扑元素,再根据几何属性(比如边的方向、面的法向)筛选。这部分代码量不小,但逻辑是固定的,写一次就能复用。

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

模型建好后,导出三种格式的代码可以并行执行:

def export_all(shape, basename): # STEP step_writer = STEPControl_Writer() step_writer.Transfer(shape, STEPControl_AsIs) step_writer.Write(f"{basename}.step") # STL stl_writer = StlAPI_Writer() stl_writer.Write(shape, f"{basename}.stl") # GLB 需要先网格化再走 glTF 导出库 mesh = tessellate(shape) export_glb(mesh, f"{basename}.glb")

STL 导出有个细节:StlAPI_Writer默认使用较粗的网格,如果发现导出的 STL 表面有棱角,需要设置SetDeflection参数。这个值建议设为零件最大尺寸的 0.1% 左右,比如 100mm 的零件用 0.1mm。

4.5 一个完整的端到端示例

假设用户输入:"一个外径 60、内径 40、高 20 的圆环,侧面打四个直径 6 的孔,均布。"

解析后的 JSON:

{ "primitive": "tube", "parameters": {"outer_radius": 30, "inner_radius": 20, "height": 20}, "operations": [ {"type": "hole_pattern", "hole_radius": 3, "count": 4, "pattern": "circular", "pitch_radius": 25, "axis": "radial"} ], "units": "mm" }

构建流程:先用两个圆柱做布尔差得到圆环,再在侧面按径向方向打四个孔。导出后得到ring.step、ring.glb、ring.stl三个文件。整个过程如果内核调用优化得当,可以在 1 到 2 秒内完成。

5. 实际落地时那些文档不会告诉你的坑

5.1 布尔运算失败:text-to-cad 最常见的崩溃点

OCCT 的布尔运算(BRepAlgoAPI_Cut、BRepAlgoAPI_Fuse)在几何复杂或者参数极端时经常失败,返回一个空 shape 或者报错。原因通常是面与面几乎相切、公差设置不当、或者输入 shape 本身有微小缺陷。

我的处理经验是三层防御:

  1. 参数校验:在调用内核前检查参数合理性。比如孔径不能大于分布圆半径,否则孔会打到外面去。
  2. 公差调整:OCCT 默认公差是 1e-7,对于大尺寸模型可能太严。可以适当放宽到 1e-5,但不要超过 1e-3,否则模型精度会出问题。
  3. 失败重试:布尔失败时,尝试对输入 shape 做一次ShapeFix_Shape修复,再重试。如果还失败,降级为返回未打孔的模型并给出警告。

踩坑记录:我曾经做一个带 200 个散热孔的模型,布尔运算跑了 40 秒还失败。后来发现是孔间距太小导致面片重叠。把孔间距从 0.5mm 调到 1mm,问题消失。所以参数校验不是可选项,是必选项。

5.2 单位与坐标系的隐形陷阱

前面提过单位问题,这里再强调坐标系。OCCT 默认 Z 轴向上,但有些 CAD 软件(比如某些版本的 3ds Max)是 Y 轴向上。text-to-cad 生成的模型如果直接导入这些软件,可能会躺倒。

解决方案是在导出时提供坐标系选项,或者在意图 JSON 里加一个up_axis字段。默认用 Z-up,需要时转成 Y-up。转换本身很简单,就是绕 X 轴旋转 -90 度,但如果不做,用户会以为模型生成错了。

5.3 大模型"幻觉"导致的几何错误

大模型有时候会"脑补"用户没说的参数。比如用户说"画一个圆盘",模型可能自作主张加上"直径 100、厚 10"。这在某些场景下是便利,在工程场景下是隐患。

我的做法是:必填参数缺失时,不猜,直接追问。在提示词里明确要求,如果用户没有提供关键尺寸,输出一个need_clarification字段,列出缺失的参数。这样虽然多一轮交互,但避免了生成错误模型浪费更多时间。

5.4 性能优化:从 10 秒到 1 秒的关键改动

text-to-cad 的响应速度直接影响体验。我做过一轮优化,把平均生成时间从 10 秒压到 1.5 秒,主要改动有三个:

  • 缓存内核对象:OCCT 的某些初始化操作(比如加载单位系统)只做一次,不要每次生成都重复。
  • 并行导出:STEP、GLB、STL 三个导出任务互相独立,用线程池并行执行。
  • 按需网格化:如果用户只要 STEP,就不做网格化,省掉最耗时的一步。
优化项优化前耗时优化后耗时说明
内核初始化2.0s0.1s改为全局单例
几何构建3.0s0.8s减少不必要的布尔运算
网格化3.5s0.4s按需执行 + 参数调优
文件导出1.5s0.2s并行导出

5.5 与现有 CAD 软件的对接现实

很多人关心 text-to-cad 生成的 STEP 能不能直接在中望 CAD、SolidWorks 里用。答案是能,但有条件。STEP 是标准格式,导入没问题,但特征树不会保留——你看到的是一个"哑实体",没有拉伸、打孔这些历史特征。这是 STEP 格式本身的限制,不是工具的问题。

如果用户需要可编辑的特征树,那 text-to-cad 的输出应该考虑生成CAD 软件的脚本,比如 SolidWorks 的 VBA 宏、FreeCAD 的 Python 脚本。这样导入后能重放建模过程,得到完整的特征树。这是进阶玩法,实现成本高,但对专业用户价值很大。

6. 这条链路还能怎么延伸

text-to-cad 目前最成熟的场景是标准件和简单结构件的快速生成。但它的潜力不止于此。我最近在尝试的一个方向是批量参数化生成:给一个 CSV 文件,每行是一组参数,系统自动生成对应的 STEP 文件并打包。这在做系列化产品设计时非常有用,比如不同规格的法兰、不同长度的型材连接件。

另一个方向是与 3D 打印切片软件联动。生成的 STL 直接推送到切片队列,用户只需要确认打印参数。这个链路打通后,从"描述需求"到"开始打印"可能只需要几分钟。

还有一个值得关注的点是逆向结合:用户上传一张手绘草图或者一张照片,系统识别出几何意图,再走 text-to-cad 的管线生成参数化模型。这比纯文字输入更直观,也更接近设计师的工作习惯。

我在实际项目里最大的体会是:text-to-cad 的价值不在于"全自动",而在于"减少重复劳动"。它不会让设计师失业,但会让设计师把时间花在真正需要创造力的地方。那些标准件、那些改尺寸的重复劳动,交给管线去跑,人去做更值得做的事情。这个定位想清楚了,工具的设计方向就不会跑偏。

返回列表