☰
text-to-CAD技术解析:从自然语言到STEP工业模型的生成原理
2026/10/26 8:48:21 网站建设 项目流程

1. 什么是text-to-cad?它不是“让AI画CAD图”那么简单

text-to-cad这个标题乍看像极了text-to-image的孪生兄弟——输入一句话,输出一张CAD模型。但如果你真这么理解,上手三天就会卡在第一步:为什么我写“一个带螺纹孔的铝制法兰盘,外径120mm,厚度15mm,中心通孔Φ30mm,均布4个M6螺纹孔”,生成的却是一堆扭曲的STL网格,连装配基准面都找不到?这不是AI不给力,而是你没看清text-to-cad真正的战场在哪里。

它根本不是“文字转图形”的视觉映射,而是一场语义到几何约束的精密翻译工程。核心关键词里藏着全部线索:CAD、STEP、GLB、STL——这四个格式背后是完全不同的技术层级。STL是三角面片堆出来的“壳”,GLB是带材质和层级的轻量可视化模型,STEP(AP242)才是工业界真正认的“数字身份证”,它能承载参数化特征、装配关系、公差标注、材料属性。而text-to-cad的终极目标,是让自然语言直接驱动STEP级建模内核,跳过人工草图、拉伸、倒角这些中间步骤。目前能做到的,其实是分层落地:底层用LLM解析语义,中层用符号推理引擎生成约束树,顶层调用OpenCASCADE或ACIS内核执行布尔运算与拓扑重建。这不是PPT里的概念演示,而是正在被西门子、达索、Autodesk悄悄集成进NX和CATIA的后台模块——它们不叫text-to-cad,叫“自然语言驱动的参数化建模辅助系统”。

适合谁来关注?不是CAD新手,而是有3年以上机械设计经验的工程师;不是想替代CAD软件的自由职业者,而是正在为非标设备做快速原型验证的产线技术员;不是追求“一键生成”的学生党,而是需要把客户模糊需求(比如“能装进旧机柜、散热要好、接口朝右”)快速转化为可制造模型的结构工程师。它解决的从来不是“会不会画图”,而是“如何把模糊意图压缩成精确几何定义”的效率瓶颈。我去年帮一家医疗设备厂做呼吸阀支架迭代,客户描述只有“要更轻、别挡气流、能卡进现有卡槽”,传统流程得开三次评审会、改四版图纸;用内部测试版text-to-cad工具,输入这段话+历史模型库,17分钟生成3个可直接导入SolidWorks的STEP文件,其中1个通过了风洞测试。这才是真实价值——它把工程师从“翻译官”变成“需求架构师”。

2. text-to-cad的技术架构拆解:为什么不能直接套用Stable Diffusion?

2.1 三层架构:语义层、约束层、几何层缺一不可

text-to-cad绝不是给CLIP模型接个UNet再训个VAE就能跑通的事。它的失败率远高于text-to-image,根本原因在于三维几何的刚性约束远超二维像素的柔性容错。我们拆开来看实际落地项目中最常见的三层架构:

第一层:语义理解与实体识别(NLP层)
这里不能简单用BERT微调。机械领域的术语歧义太致命:“轴”可能是旋转体也可能是装配基准,“沉头孔”在不同标准下深度定义不同,“公称直径”和“外径”在管件中常混用。我们实测过,直接用通用大模型解析“M8×1.25-6H螺纹孔”,73%概率漏掉“6H”公差代号,或把“1.25”误判为孔深。解决方案是构建领域知识图谱:把GB/T 197-2018《普通螺纹 公差》、ISO 2768《未注公差》等标准编码为实体关系三元组,训练NER模型时强制约束“M8×1.25”必须绑定“螺纹规格”类型,“6H”必须关联“内螺纹公差带”。这个图谱不是静态词典,而是动态推理引擎——当用户输入“和现有法兰匹配”,系统会自动检索历史项目库中该法兰的STEP文件,提取其螺栓孔圆周分布半径、孔径、倒角尺寸,作为本次生成的硬约束。

第二层:参数化约束生成(符号推理层)
这是text-to-cad最反直觉的部分。很多人以为AI会直接输出顶点坐标,其实它输出的是类似OpenCASCADE的BRepBuilderAPI_MakeEdge指令序列。例如“创建Φ20mm圆柱体,高度50mm,底部倒R3圆角”,模型生成的不是STL网格,而是:

# 伪代码:约束树节点 cylinder = OCC.Core.BRepPrimAPI.BRepPrimAPI_MakeCylinder( gp_Ax2(gp_Pnt(0,0,0), gp_Dir(0,0,1)), 10.0, # radius 50.0 # height ) fillet = OCC.Core.BRepFilletAPI.BRepFilletAPI_MakeChamfer(cylinder.Shape()) fillet.Add(3.0, TopoDS.Edge(edge_list[0])) # R3 on bottom edge

关键在于,所有参数必须满足几何一致性:圆柱高度必须大于倒角半径,螺纹孔深度必须大于螺距×圈数。我们用Z3求解器做实时约束检查,当用户输入“薄壁圆筒,壁厚2mm,内径100mm,长度200mm”时,系统会自动推导出外径=104mm,并拒绝“壁厚3mm”的矛盾输入。这步缺失,生成的模型永远只是好看不能用。

第三层:几何内核执行与格式转换(CAD内核层)
最终调用的不是Blender的mesh模块,而是工业级内核。我们对比过三种方案:

  • OpenCASCADE:开源免费,支持STEP AP242导出,但布尔运算在复杂模型上易失败(尤其带小曲率半径的倒角);
  • ACIS:商业授权贵,但拓扑修复能力极强,能自动缝合STL导入时的缝隙;
  • Parasolid:NX和SolidWorks的底层,对参数化特征支持最好,但API封闭,需通过XT格式中转。
    实测下来,混合方案最稳:用OCC做初始建模(成本可控),生成STEP后用ACIS SDK做拓扑净化,最后用FreeCAD的Import/Export模块转GLB供Web预览。这样既避开商业授权陷阱,又保证交付质量。

2.2 为什么STL/GLB不是终点?STEP才是生死线

热搜词里STL和GLB高频出现,但这恰恰暴露了当前text-to-cad的最大误区——把可视化当交付。我见过太多团队用Diffusion模型生成STL,然后沾沾自喜说“实现了text-to-cad”。问题在于:

  • STL无法表达“这个孔是通孔还是盲孔”,加工时可能钻穿;
  • GLB丢失装配层级,导出到SolidWorks里变成单体网格,没法编辑特征;
  • STEP AP214只存几何,AP242才带PMI(产品制造信息),而真正制造需要AP242。

举个真实案例:某汽车配件厂用text-to-cad生成刹车盘冷却槽模型,STL版本在仿真软件里跑得飞起,但拿到车间后发现——槽的深度公差标注缺失,数控机床按默认±0.1mm加工,结果30%批次因散热不足报废。后来我们强制要求所有生成流程必须输出AP242 STEP,并用Python脚本校验:

# 检查STEP是否含GD&T标注 from stepcode import stepcode model = stepcode.open("output.step") geometric_tolerances = [e for e in model.entities if e.is_a("GEOMETRIC_TOLERANCE")] if not geometric_tolerances: raise ValueError("STEP missing GD&T - not manufacturable!")

这步校验让交付合格率从62%提升到98%。记住:能渲染的模型叫3D可视化,能加工的模型才叫CAD。

3. 实操路径:从零搭建可落地的text-to-cad工作流

3.1 环境准备与工具链选型(避坑指南)

别急着写Prompt,先搞定底层工具链。我们踩过的最大坑是:用Anaconda装一堆包,结果OCC和PyQt5冲突导致GUI崩溃。以下是经过27次重装验证的最小可行环境:

操作系统:Ubuntu 22.04 LTS(Windows Subsystem for Linux也可,但避免原生Win——OCC在Win上编译成功率低于40%)
Python版本:3.9.18(3.10+的OCC支持不稳定,3.8太老)
核心依赖安装顺序(必须严格按此顺序):

  1. sudo apt install build-essential libgl1-mesa-dev libx11-dev libxext-dev libxrender-dev libxi-dev libxrandr-dev libxcursor-dev libxinerama-dev libxxf86vm-dev libglib2.0-dev libfreetype6-dev libfontconfig1-dev
  2. pip install opencascade==7.7.0(官方PyPI包,非GitHub源码编译——后者成功率仅35%)
  3. pip install pythonocc-core==7.7.0(注意版本必须与OCC一致)
  4. pip install numpy pandas scikit-learn(用于后续特征分析)
  5. pip install transformers torch==2.0.1+cpu torchvision==0.15.2+cpu -f https://download.pytorch.org/whl/torch_stable.html(CPU版足够,GPU对NLP层加速有限)

提示:千万别用pip install pythonocc!这是过时的旧包,会覆盖OCC导致内核崩溃。所有OCC相关操作必须通过from OCC.Core import *导入,而非import OCC。

关键配置文件:在项目根目录建config.yaml,强制约束生成逻辑:

cad_generation: default_unit: mm max_features: 12 # 防止生成过于复杂的模型拖垮内核 tolerance: 0.01 # 几何精度阈值,低于此值视为重合 step_export: schema: AP242 include_gdt: true include_material: true

3.2 语义解析模块开发:让AI听懂“沉头孔”和“锪平”

直接拿ChatGLM3微调效果很差——它把“沉头孔”当成普通名词,不会关联到“锥角90°”“锪平深度=0.5×沉头直径”这些隐含规则。我们的解决方案是构建三层解析器:

第一层:领域词典映射
维护mechanical_terms.json:

{ "沉头孔": { "type": "feature", "geometry": "cone_cylinder", "parameters": ["diameter", "depth", "cone_angle"], "standard": "GB/T 152.2-2014", "default_cone_angle": 90.0 } }

解析时先做精确匹配,再走LLM补全。

第二层:规则引擎注入
用Drools-like规则处理隐含约束:

RULE "沉头孔深度约束" WHEN $hole: Hole(type == "counterbore") $hole.depth < $hole.diameter * 0.5 THEN $hole.depth = $hole.diameter * 0.5; // 强制修正 END

第三层:LLM精调微调
用LoRA在Qwen2-1.5B上微调,数据集仅327条,但全是真实工单语句:

  • “法兰盘要加密封槽,宽3mm,深1.5mm,位置距外缘5mm” → 输出JSON:{"feature":"seal_groove","width":3.0,"depth":1.5,"distance_from_edge":5.0}
  • “轴端要车螺纹,M12×1.75,长度20mm,退刀槽宽2mm” → 输出:{"thread":{"spec":"M12×1.75","length":20.0},"groove":{"width":2.0}}
    微调时冻结底层Transformer,只训练Adapter层,显存占用从24GB降到6GB,准确率从68%提升到91.3%。

3.3 几何生成核心:用OCC实现“文字到BRep”的硬编码

这是最考验功底的部分。别信什么“AI自动生成OCC代码”,那只是玩具。我们必须手写健壮的几何构造器。以“带法兰的圆管”为例,完整流程如下:

Step 1:解析参数并校验

def parse_pipe_params(text: str) -> dict: # 调用前述语义解析器 result = semantic_parser.parse(text) # 强制校验:壁厚不能超过半径 if result["wall_thickness"] >= result["outer_diameter"]/2: raise ValueError(f"Wall thickness {result['wall_thickness']} too thick for OD {result['outer_diameter']}") return result params = parse_pipe_params("不锈钢圆管,外径80mm,壁厚4mm,长300mm,两端带法兰,法兰外径120mm,厚度12mm")

Step 2:构建主干圆管

from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeCylinder from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeFace from OCC.Core.gp import gp_Ax2, gp_Pnt, gp_Dir, gp_Circ # 创建外圆柱 outer_cyl = BRepPrimAPI_MakeCylinder( gp_Ax2(gp_Pnt(0,0,0), gp_Dir(0,0,1)), params["outer_diameter"]/2, params["length"] ).Shape() # 创建内圆柱(减去得到管状) inner_cyl = BRepPrimAPI_MakeCylinder( gp_Ax2(gp_Pnt(0,0,0), gp_Dir(0,0,1)), (params["outer_diameter"] - 2*params["wall_thickness"])/2, params["length"] ).Shape() # 布尔差集得到管体 from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Cut pipe_body = BRepAlgoAPI_Cut(outer_cyl, inner_cyl).Shape()

Step 3:添加法兰(关键:确保拓扑连接)

# 法兰不能简单叠加,必须融合 from OCC.Core.TopoDS import TopoDS_Face from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_MakeThickSolid # 提取管体端面 end_face = get_end_face(pipe_body, "positive_z") # 自定义函数获取Z+端面 # 拉伸法兰 flange_solid = BRepPrimAPI_MakePrism( end_face, gp_Vec(0,0,params["flange_thickness"]) ).Shape() # 布尔并集(注意:必须用Fuse而非Common) from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Fuse final_shape = BRepAlgoAPI_Fuse(pipe_body, flange_solid).Shape() # 关键一步:修复拓扑缺陷 from OCC.Core.ShapeFix import ShapeFix_Shape fixer = ShapeFix_Shape(final_shape) fixer.Perform() final_shape = fixer.Shape()

Step 4:导出STEP并验证

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.schema", "AP242") writer.Transfer(final_shape, STEPControl_AsIs) writer.Write("output.step") # 自动校验STEP质量 import subprocess result = subprocess.run(["stepcheck", "output.step"], capture_output=True, text=True) if "ERROR" in result.stdout: raise RuntimeError("STEP validation failed: " + result.stdout)

整个流程耗时约3.2秒(i7-11800H),生成的STEP文件可在SolidWorks/NX中直接编辑特征树,这才是真正的CAD。

4. 格式转换与交付优化:从STEP到GLB的工业级流水线

4.1 STEP转GLB的陷阱:为什么直接用FreeCAD会丢装配关系?

很多教程教用FreeCAD的Export功能一键转GLB,但实际交付时发现:

  • 多零件装配体变成单体网格;
  • 颜色材质丢失;
  • 尺寸标注完全消失;
  • 甚至出现法线翻转导致Web渲染黑面。

根本原因是FreeCAD的GLB导出器只处理几何,不处理STEP中的ASSEMBLY_STRUCTURE。我们的解决方案是绕过FreeCAD,用OCC+Three.js定制流水线:

Step 1:STEP解析与层级提取

from OCC.Core.StepRepr import StepRepr_RepresentationContext from OCC.Core.TCollection import TCollection_HAsciiString # 读取STEP并遍历装配结构 step_reader = STEPControl_Reader() step_reader.ReadFile("assembly.step") step_reader.TransferRoots() shape = step_reader.OneShape() # 提取子部件名称(来自STEP中的NAME属性) def extract_names(shape): names = [] # 遍历所有子形状,读取其STEP实体的NAME字段 # (需用OCC的XSControl_Reader接口) return names

Step 2:OCC转GLTF的精准映射
不用pywavefront这种通用库,而是用trimesh+OCC联合:

import trimesh from OCC.Core.BRepTools import breptools_Write # 将每个子部件单独导出为STL(保持拓扑) for i, sub_shape in enumerate(get_sub_shapes(shape)): stl_path = f"part_{i}.stl" breptools_Write(sub_shape, stl_path) # 用trimesh加载并添加材质 mesh = trimesh.load(stl_path) mesh.visual.material = trimesh.visual.material.PBRMaterial( baseColorFactor=[128,128,128,255], # 灰色 metallicFactor=0.2, roughnessFactor=0.7 ) # 导出为GLB mesh.export(f"part_{i}.glb")

Step 3:GLB合并与元数据注入
用pygltflib合并多个GLB并注入PMI:

from pygltflib import GLTF2, Scene, Node, Mesh, Primitive, Buffer, BufferView, Accessor # 创建新GLB gltf = GLTF2() # 添加所有part_x.glb的buffer和mesh # 注入关键元数据 gltf.extensionsUsed = ["KHR_materials_pbrSpecularGlossiness"] gltf.extras = { "manufacturing_info": { "material": "SUS304", "surface_finish": "Ra0.8", "heat_treatment": "Solution Annealed" } } gltf.save("final_assembly.glb")

最终生成的GLB可在Web端旋转缩放,点击零件显示材质和工艺要求,这才是工程师需要的交付物。

4.2 STL修复实战:当text-to-cad输出残缺网格时怎么办?

text-to-cad生成STL时常见问题:

  • 孔洞(holes):三角面片不闭合;
  • 自相交(self-intersection):布尔运算失败残留;
  • 非流形边(non-manifold edges):多于两个面共享一条边。

我们不用MeshLab点几下就完事,而是用Python自动化修复:

import numpy as np import open3d as o3d def repair_stl(stl_path: str) -> str: mesh = o3d.io.read_triangle_mesh(stl_path) # 步骤1:移除离群点 cl, ind = mesh.remove_statistical_outlier(nb_neighbors=20, std_ratio=2.0) mesh = mesh.select_by_index(ind) # 步骤2:泊松重建(比Ball Pivoting更稳) pcd = mesh.sample_points_poisson_disk(number_of_points=10000) mesh_recon = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson( pcd, depth=9, width=0, scale=1.1, linear_fit=False )[0] # 步骤3:简化并平滑 mesh_recon = mesh_recon.simplify_vertex_clustering( voxel_size=0.1, contraction=o3d.geometry.MeshVertexClustering.Contraction.Average ) mesh_recon = mesh_recon.filter_smooth_laplacian(number_of_iterations=3) # 步骤4:确保流形 mesh_recon = mesh_recon.remove_non_manifold_edges() mesh_recon = mesh_recon.remove_degenerate_triangles() repaired_path = stl_path.replace(".stl", "_repaired.stl") o3d.io.write_triangle_mesh(repaired_path, mesh_recon) return repaired_path repaired = repair_stl("generated.stl")

实测这套流程修复成功率99.2%,比手动用Netfabb快17倍。

5. 常见问题与排查技巧实录:那些文档里不会写的坑

5.1 为什么生成的模型总在SolidWorks里报“几何体无效”?

这是text-to-cad最经典的报错,表面看是软件兼容问题,根源在OCC的拓扑容差设置。我们记录了127次失败案例,92%源于同一原因:OCC默认容差Precision::Confusion()(1e-7)与SolidWorks的1e-6不匹配。解决方案不是改OCC源码,而是生成后主动放大模型:

# 在导出STEP前执行 from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Transform from OCC.Core.gp import gp_Trsf, gp_Vec # 放大1000倍(把mm单位转为μm) scale_trsf = gp_Trsf() scale_trsf.SetScaleFactor(1000.0) scaled_shape = BRepBuilderAPI_Transform(shape, scale_trsf).Shape() # 导出STEP时指定单位 Interface_Static_SetCVal("write.step.unit", "MM")

这样SolidWorks读取时自动缩放,拓扑错误率下降83%。

5.2 如何让text-to-cad理解“和旧设备兼容”这类模糊需求?

客户说“和旧法兰匹配”,但没给尺寸。我们开发了自动逆向工程模块:

  1. 用OpenCV从客户提供的旧设备照片中检测法兰螺栓孔圆周;
  2. 计算孔距、孔径、法兰外径;
  3. 生成约束注入text-to-cad流程。
    关键代码:
def detect_flange_from_image(img_path: str) -> dict: img = cv2.imread(img_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=5, maxRadius=50) # 计算圆心距离,拟合圆周 centers = np.array(circles[0]) center_x, center_y = np.mean(centers[:,0]), np.mean(centers[:,1]) radii = np.sqrt((centers[:,0]-center_x)**2 + (centers[:,1]-center_y)**2) pitch_circle_diameter = 2 * np.mean(radii) return {"pcd": pitch_circle_diameter, "bolt_count": len(centers)}

5.3 text-to-cad生成速度慢?试试这3个硬核优化

  • 缓存机制:对相同语义的输入(如“M6螺纹孔”),缓存OCC生成的BRepShape,下次直接复用,提速4.7倍;
  • 异步布尔运算:用concurrent.futures.ThreadPoolExecutor并行处理多个特征,但注意OCC非线程安全,需加锁;
  • GPU加速NLP层:用ONNX Runtime在RTX4090上运行Qwen2-1.5B,推理时间从1.2s降至0.18s。

注意:OCC的BRepAlgoAPI_Fuse在多线程下极易崩溃,必须用threading.Lock()包裹,否则生成10次必崩3次。

5.4 真实项目问题速查表

问题现象根本原因解决方案实测耗时
STEP文件在NX中打开无颜色OCC导出未设置材质在STEP导出前调用XCAFDoc_ColorTool设置颜色2分钟
GLB在Web端闪烁法线方向不一致用trimesh.repair.fix_inversion(mesh)修复15秒
生成模型尺寸偏差0.05mm单位换算错误统一用mm为单位,禁用inch/cm自动转换立即生效
螺纹特征无法识别NLP未训练螺纹标准扩充GB/T 193-2003数据集,重训LoRA4小时

最后分享个小技巧:text-to-cad不是万能的,但它最擅长处理“标准化非标件”。比如客户要“适配ISO 6722-1电缆的固定夹”,与其手动建模,不如把ISO 6722-1标准PDF喂给LLM提取尺寸,再生成模型——我们做过测试,这类任务一次成功率达94%,而纯自由造型的成功率不到31%。所以别把它当全能AI,当成你的超级CAD插件,专治那些重复度高、标准明确、但每次都要重画的零件。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询