FreeCAD 二次开发实战:用 20 行 Python 搭一条参数化建模流水线
【免费下载链接】FreeCADOfficial source code of FreeCAD, a free and opensource multiplatform 3D parametric modeler.项目地址: https://gitcode.com/GitHub_Trending/fr/FreeCAD
做机械结构的人应该都干过这种事:同一块安装板,按 6 孔、8 孔、10 孔各建一版,每版改完尺寸还要在模型里手工挪孔位,建到第三版就把孔径写错了,推倒重来。这种"参数变了、模型还得人肉跟着变"的活,恰恰最适合交给脚本。这篇带你用 FreeCAD 自带的 Part 模块 和属性系统,写一个能批量生成参数化安装板的小工具,全程不超过 20 行 Python。读完你能自己写一个挂在模型树里的参数化零件,改一个数字,整族零件自动重算。
环境怎么备,三分钟的事
装一个 FreeCAD 官方发行版就够了,Python 绑定随包附带,不用额外配置依赖。想读源码的话拉一份下来:
git clone https://gitcode.com/GitHub_Trending/fr/freecad写代码时用 FreeCAD 内置的 Python 控制台(View → Panels → Python console),import FreeCAD, Part之后就能直接交互。下面所有示例都在这条控制台上跑。
先搞懂 Part::FeaturePython 的代理套路
FreeCAD 模型树里的每个节点都是文档对象,而Part::FeaturePython是其中最特别的一种:它是个"空壳",允许你挂一个 Python 对象进去,由这个对象决定形状长什么样——就像宜家柜体里预留的卡槽,塞什么面板进去,柜子就变成什么样子。
被挂进去的 Python 对象叫proxy。proxy 的职责有三件:在__init__里用addProperty声明参数;实现execute(self, obj)生成几何;把结果赋给obj.Shape。文档重算时 FreeCAD 会回调execute,于是"参数变了、模型自动跟着变"就是这么发生的。
仓库里的渐开线齿轮 InvoluteGearFeature.py 就是这个套路的完整示范,它的execute只做了两件事:按属性值算出齿形轮廓,再赋给obj.Shape:
def execute(self, obj): w = fcgear.FCWireBuilder() generator_func = ( involute.CreateExternalGear if obj.ExternalGear else involute.CreateInternalGear ) generator_func(w, obj.Modules.Value, obj.NumberOfTeeth, obj.PressureAngle.Value, ...) gearw = Part.Wire([o.toShape() for o in w.wire]) obj.Shape = gearw属性声明则是在__init__里一行行addProperty,类型写App::PropertyLength,默认值给"2.5 mm"这样的字符串。看懂这两个位置,你就看懂了 PartDesign 里一半的 Python 功能对象,它们的 C++ 侧底座在 PartDesign 模块。
上面这张图是 PartDesign 工作台的界面:左侧特征树里每个节点对应一次建模操作,右下属性面板改数字、模型树即刻更新——你要做的就是用 Python 复刻这套"数字驱动几何"的体验。
动手做一块参数化安装板
按三步走,每步都能在控制台里立刻看到结果。
第一步:建空壳。输入:一个对象名;动作:
import FreeCAD, Part doc = FreeCAD.newDocument("MountPlate") obj = doc.addObject("Part::FeaturePython", "MountPlate")预期:模型树里多出一个MountPlate,3D 视区还是空的——形状还没生成,这很正常。
第二步:声明参数。输入:参数名、类型、默认值;动作:
obj.addProperty("App::PropertyLength", "BaseLength", "Dimensions") obj.addProperty("App::PropertyLength", "BaseWidth", "Dimensions") obj.addProperty("App::PropertyLength", "Height", "Dimensions") obj.addProperty("App::PropertyInteger", "HoleCount", "Features") obj.BaseLength = "150 mm" obj.BaseWidth = "100 mm" obj.Height = "30 mm" obj.HoleCount = 6预期:属性面板里能看到四个参数,单位换算、合法性检查都交给 FreeCAD,你不用自己写。
第三步:写 proxy 并触发重算。输入:一个生成几何的类;动作:
class MountPlate: def __init__(self, obj): obj.Proxy = self def execute(self, obj): box = Part.makeBox(obj.BaseLength.Value, obj.BaseWidth.Value, obj.Height.Value) y = obj.BaseWidth.Value / 2.0 for i in range(1, obj.HoleCount + 1): x = obj.BaseLength.Value * i / (obj.HoleCount + 1) box = box.cut(Part.makeCylinder(5, obj.Height.Value, FreeCAD.Vector(x, y, 0))) obj.Shape = box MountPlate(obj) doc.recompute()预期:一块 150×100×30、中间一排 6 个通孔的安装板出现在视区里。之后把参数包进函数,改参数就是调函数:
obj.HoleCount = 10 obj.BaseLength = "200 mm" obj.Proxy.execute(obj) # 脚本里改完参数要手动推一把预期:孔位间距自动重排,板长变成 200mm。这些板生成后可以直接丢进装配模块里做布局,效果类似仓库自带示例data/examples/AssemblyExample.FCStd的样子。
三个新手最容易踩的坑
坑一:单位对象直接当数字传。obj.BaseLength是个 Quantity,Part.makeBox只吃 float。makeBox(obj.BaseLength, ...)会抛出莫名其妙的类型错误,加上.Value就没事了——上文的代码里我处处带着它,不是啰嗦。
坑二:改完参数模型"纹丝不动"。和 C++ 特征不同,Part::FeaturePython不会在属性变化时自动重算。交互编辑面板里想实时预览,就在赋值后手动调obj.Proxy.execute(obj),齿轮的任务面板就是这么做的;而doc.recompute()是另一种更"正式"的触发方式,两者都认。
坑三:改过属性结构,老文件打不开。给对象改属性名、换分组,旧文档里存的对象会缺属性。FreeCAD 在加载时会自动回调 proxy 的onDocumentRestored,你在里面用hasattr补齐缺失属性即可,仓库里齿轮的实现 InvoluteGearFeature.py 就带了这种迁移钩子:
def onDocumentRestored(self, obj): if not hasattr(obj, "HoleCount"): obj.addProperty("App::PropertyInteger", "HoleCount", "Features")再补一句:脚本驱动的快速建模用 Part 模块最顺手;要给用户看"特征树"这种体验,再上 PartDesign 的 Body,两者不冲突。
手动建 10 版和跑一条脚本的差距
把同一个需求做两种做法对比一下就很直观:
- 手动:10 个规格的安装板,每版进草图改尺寸、挪孔位、重画,按每版 3 分钟算也要半小时,中途写错一个数就得推倒重来
- 脚本:
create_mount_plate("150,100,30,6")这样的调用循环一遍,整族零件秒级生成,尺寸零手输
def create_mount_plate(spec): l, w, h, n = (float(v) for v in spec.split(",")) o = doc.addObject("Part::FeaturePython", f"Plate_{int(n)}hole") o.BaseLength = f"{l} mm" o.BaseWidth = f"{w} mm" o.Height = f"{h} mm" o.HoleCount = int(n) MountPlate(o) return o for spec in ["150,100,30,6", "150,100,30,8", "200,120,40,10"]: create_mount_plate(spec)省下来的不只是时间:参数和几何永远同源,客户改需求时你只改一个字符串数组,还可以顺手批量导出 STEP 给制造端。
往哪儿延伸
- 用属性表达式绑定把跨对象参数串起来,一个总参数驱动整个装配
- 生成的零件直接喂给 FEM 模块,顺手跑一次壁厚和应力校验
- 打通 CAM 模块,从参数一路走到刀路
选一个你最近反复改过三遍以上的零件,把它最容易变的那 3 个参数变成addProperty,再跑一次批量生成——这条流水线就算真正长在你手上了。
【免费下载链接】FreeCADOfficial source code of FreeCAD, a free and opensource multiplatform 3D parametric modeler.项目地址: https://gitcode.com/GitHub_Trending/fr/FreeCAD
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考