
简介一份名为 CAAKcNurbsPluginFrm 的 CATIA CAA 扩展插件包发布于2020年4月30日面向汽车、航空、机械等需要处理复杂自由曲面的 CAD 设计师以及希望扩展 Nurbs 功能的二次开发工程师。插件聚焦曲线编辑、曲面创建与几何优化可显著提升 CATIA 中 Nurbs 建模效率。压缩包共包含 929 个文件整体约 11.16MB。核心内容为 C/C 源码.cpp/.h与编译中间产物.obj/.o并配有 .mk/.mkdg 构建配置、.catnls/.catdlg 界面与本地化资源同时涵盖 .tsrc/.catrsc 等模块注册与元数据文件便于完整了解插件工程结构并重新编译。已有324人浏览学习适合用作 CAA 二次开发入门参考或实际项目集成。包内提供创建点、编辑控制点与权重等 Nurbs 操作的实现代码并带有对应的对话框、位图图标及语言环境文件从中既能学习 CAA 组件架构与用户界面挂接方法也能参考 Nurbs 几何算法同 CATIA 的集成流程适合作为自研插件开发、调试与扩展的起始模板。目录组织呈现典型 CAA 工程布局对梳理组件依赖与构建流程很有帮助。1. CAAKcNurbsPluginFrm 是什么一个 CATIA CAA Nurbs 插件框架的完整画像第一次拿到CAAKcNurbsPluginFrm_20200430_CAANurbs_CATIACAA_catia_dirtyo6w_zi这种名字的压缩包老手的反应不是急着解压而是先把文件名拆一遍。这一长串里几乎写完了整个工程的背景CAA 二次开发、Nurbs 曲面、插件框架、构建日期和编译时的源码状态。所谓 CAA是 CATIA 给第三方做插件的整套 C 接口与运行时想跳过 VBA 脚本的性能上限、把几何运算真正跑在内核里基本都会落到 CAA 上。而这个 NurbsPluginFrm 要解决的是最实在的一类需求用代码生成、导入、批量改写 Nurbs 曲面和曲线比如把 STEP 文件里的自由曲面转成 CATIA 原生 Nurbs、读取控制点做公差分析、离线批量改曲面阶数。接下来我把这类插件怎么看、怎么搭环境、怎么编译部署、参数怎么设以及最容易在哪一步翻车一次讲透。2. 先把文件名拆明白CAA、Nurbs、PluginFrm、dirtyo6w_zi 各是什么意思拿到包先别急着找 README名字本身就是第一份文档。这个命名不是乱拼的每一段都对应着工程里的一个真实决策拆完之后你对这个插件该依赖什么、该用什么工具链编译心里基本就有数了。2.1 “Kc”与“PluginFrm”CAA 模块命名里藏着分工CAAKc里那个Kc是 CAA 社区和官方示例里很常见的缩写指 Kernel Command也就是内核命令。CAA 二次开发里大量命令类继承自CATCommand命令本身的逻辑放在一个以CAAKc开头的类里跟界面层、数据层分开。这样做的理由是命令层不依赖具体对话框可以在批处理里被脚本调用也能被别的命令复用它。Nurbs说明主题是 Nurbs 几何对应 CAA 几何内核里CATNurbsSurface、CATNurbsCurve这一族对象。PluginFrm是 Plugin Framework 的简写意思是这是一个“插件框架工程”不是单个功能点而是包含命令入口、资源字典、工厂方法的完整框架。20200430是构建日期CATIACAA表示它是面向 CATIA 的 CAA API 构建后面的catia则是目标应用名。字段含义对后续操作的影响CAAKcCAA 内核命令类继承 CATCommand决定命令注册方式与 .dico 字典写法Nurbs主题是 Nurbs 曲面/曲线需要依赖几何内核相关框架PluginFrm插件框架工程按 framework 结构建工程而非单个 DLL20200430构建日期判断环境依赖是否已经过时CATIACAA / catia面向 CATIA 的 CAA API 与目标应用决定 API 版本匹配哪个 CATIA 版本dirtyo6w_zi构建签名表示构建时源码有未提交改动不是报错2.2 Framework、Module、ImakefileCAA 工程的三层骨架CAA 工程的组织方式跟普通 VS 项目不一样它是 workspace、framework、module 三层。一个 workspace 下可以挂多个 framework每个 framework 下又可以挂多个 module。编译时 mkmk 只认这套结构你把一个 .cpp 丢进普通目录是编不出来的。# 一个 CAA 插件框架工程的典型目录结构 NurbsPluginFr/ # workspace 根目录 └── NurbsPluginFrm/ # framework 名 ├── IdentityCard # 声明依赖的其它 CAA 框架 ├── Imakefile # 本 framework 的构建入口 ├── NurbsPluginFrm.m # 模块定义列出参与编译的文件 ├── NurbsPluginCmd.cpp # 命令类实现 ├── NurbsPluginCmd.h └── resources/ # 菜单、命令字典、NLS 资源IdentityCard是个无扩展名文本文件写的是本框架依赖哪些其它框架比如几何内核、机械设计、数学库。Imakefile是构建脚本入口声明模块列表和链接依赖。.m文件才是模块清单列出这个模块要编译的源文件和头文件。CAA 不认你目录里有多少 .cpp只认.m文件里写了谁这一点新手最容易栽。2.3 CATIACAA 环境与版本匹配看清 V5 各版本再动手CAA 的 API 版本跟 CATIA V5 版本强相关v5r21、v5-6r2018、v5-6r2022对应不同年代的 CAA 发行版头文件和链接库都有差异。常见的一个坑是用新版 RADE 编出来的 DLL 放进旧版 CATIA 里启动时直接报接口不匹配连命令都注册不进去。版本匹配的第一条经验是编译用的 CAA 版本必须和运行用的 CATIA 版本一致跨版本跑等于给自己挖坑。平台目录也随版本走老版本常见intel_a新版本 64 位常见win_b64CAA 生成文件的路径会跟着 CATIA 的平台目录走。另外网上很多人遇到过 win11 更新后p3 v5-6r2018打不开的情况这种时候别怀疑是插件问题先查 CATIA 本体能不能起来再查插件加载顺序反了会白忙半天。至于结尾的dirtyo6w_zidirty表示构建时源码树里有未提交的改动o6、w、zi这类片段更像是编译优化级别和调试信息开关的拼接比如 MSVC 体系里的/O优化和/Zi调试信息。看到它不用紧张它只是构建签名说明这个包不是从干净 tag 直接编出来的仅此而已。3. 把 CAA 编译环境跑起来workspace、Imakefile 与 mkmk 的最小流程环境起不来后面全是空谈。CAA 开发环境和普通 C 开发差异很大它不靠 IDE 的工程文件靠的是一套独立的目录体系和命令行工具链。我一般把这一步拆成三件事搭好 workspace、写好构建文件、跑通 mkmk 和 cnext。3.1 workspace 与 BSC/RSC先分清两个家底CAA 环境里有两套支撑组件经常被搞混。BSCBuild Support Components是编译时用的头文件和静态库RSCRuntime Support Components是运行时用的 DLL 和资源。装好 RADE 后这两套东西会在安装目录下生成比如常见的C:\CAA\BSC和C:\CAA\RSC。你自己的 workspace 则负责放源码和生成物编译输出默认落在 workspace 下的generated目录。启动 CATIA 运行插件时不能靠双击桌面图标而要给它一份环境文件让 CATIA 知道去哪个 workspace 找你的框架。这个文件就是.CATEnv文本格式直接用记事本改。常见写法大致是这样# NurbsPlugin.CATEnv —— 运行前让 CATIA 知道去哪里找插件 # 路径按你机器上的实际安装位置改 V5R21_BSC C:\CAA\BSC V5R21_RSC C:\CAA\RSC NURBSPLUGINFR C:\CAADev\NurbsPluginFr注意不同 RADE 版本生成的.CATEnv模板在字段细节上会有出入我习惯先打开安装目录里已有的 .CATEnv 照着改而不是凭记忆手写。这个文件的作用是告诉系统两个家底在哪里编译组件在哪你的插件生成物在哪。路径写错的话编译能过但运行时 CATIA 根本扫不到你的字典和 DLL。3.2 搭 NurbsPluginFrm 框架最少需要的三个文件在 workspace 下建一个 framework最少要Imakefile、.m文件、IdentityCard三样东西。下面是我常用的一份Imakefile示例字段含义写在注释里# Imakefile —— NurbsPluginFrm 框架的构建入口 # mkmk 编译时第一个读的就是它 # 本 framework 下要编译的 module MODULES \ NurbsPluginFrm # 链接依赖的 CAA 官方框架 LINK_WITH \ CATApplicationFrame \ CATMechanicalModeler \ CATGeometricOperators \ CATMathematics # 只生成 DLL不生成可执行程序 LINK FALSELINK_WITH里的框架名要跟IdentityCard里声明的依赖对上两边不一致时 mkmk 会报依赖解析错误。.m文件则负责列源文件命名规则是模块名加.m后缀# NurbsPluginFrm.m —— 本模块参与编译的文件清单 NurbsPluginCmd.cpp NurbsPluginCmd.h NurbsPluginFrm.cpp NurbsPluginFrm.h这里有个容易忽略的点.m文件里列的文件必须真实存在于模块目录下而且要跟实际文件名完全一致包括大小写。CAA 的依赖计算器会对这个清单做哈希比对漏一个文件或者拼错一个字母增量编译就会变得不正常。IdentityCard则是一份依赖声明文本里面逐行列出本框架要用到的其它框架名可以用 RADE 自带的校验工具检查依赖是否闭环。3.3 用 mkmk 编译并用 cnext 启动最小命令组合文件就位后编译只用一个命令。进入 RADE 提供的命令行环境后# 编译整个 NurbsPluginFrm 框架 mkmk -o C:\CAADev\NurbsPluginFr NurbsPluginFrm # 只重编一个模块改动小时比全量快很多 mkmk -o C:\CAADev\NurbsPluginFr NurbsPluginFrm NurbsPluginFrm # 全量编译 workspace 下所有框架 mkmk -a C:\CAADev\NurbsPluginFr-o后面跟 workspace 路径接着是 framework 名再往后可以精确到 module 名。我平时的习惯是先全量编一次确认骨架没问题之后就只编改动的 module。编译产物默认落在generated\win_b64\NurbsPluginFrm\code\bin老版本平台目录可能是intel_a里面有你的 DLL 和资源。部署和启动用这一条命令# 用 .CATEnv 启动 CATIA而不是双击桌面图标 cnext -env NurbsPlugin.CATEnvcnext是 CATIA 的启动程序-env指定环境文件。这一步的意义在于CATIA 启动时会按.CATEnv里的路径扫描框架资源把命令字典合并进去。如果你直接双击图标CATIA 用的是默认环境你的 Nurbs 插件哪怕编译得再好也加载不出来。这个区别就是 CAA 开发和普通桌面开发的本质差异——插件能不能被看见不完全取决于 DLL 是否存在还取决于运行时扫描路径有没有覆盖到它。4. 在插件里读写 Nurbs 曲面核心 API 与四个必调参数环境通了接下来是重头戏在插件代码里真正操作 Nurbs 曲面。Nurbs 全称是非均匀有理 B 样条CATIA 内核里对应CATNurbsSurface和CATNurbsCurve操作它们不像操作普通平面那样拿坐标点就够还要管阶数、控制点、节点向量这些参数。4.1 从 CATGeoFactory 到 CATNurbsSurface先认识三个对象CAA 里不直接new一个CATNurbsSurface所有几何对象都由CATGeoFactory创建工厂负责统一管理生命周期。然后是CATNurbsSurface代表一张 Nurbs 曲面核心数据是 u/v 两个方向的节点向量和网格控制点。最后是CATMathPoint用来传坐标。这三个对象的关系一句话就能说清工厂负责生曲面负责存数学点负责搬数据。4.2 创建 Nurbs 曲面并读回控制点一段最小 CAA 代码下面这段是创建一张 Nurbs 曲面、写入一个控制点、再读回来验证的最小流程。方法名在不同 CAA 版本里个别有出入写之前先翻本版本头文件确认别背写法// nurbs_sample.cpp —— CAA Nurbs 曲面创建与读写最小样例 #include CATGeoFactory.h #include CATSoftwareConfiguration.h #include CATNurbsSurface.h #include CATMathPoint.h // 创建几何工厂 CATSoftwareConfiguration* pConfig 0; CATGeoFactory* pFactory CATGeoFactory::CreateFactory(pConfig); if (0 pFactory) { return; // 工厂创建失败多半是环境变量没加载先查 .CATEnv } // 阶数是“次数 1”这里 3 表示曲面上等参数线最多是二次曲线 CATLONG32 uOrder 3, vOrder 3; // 每个方向的控制点个数4 表示 4x4 网格 CATLONG32 uNb 4, vNb 4; // 节点向量长度 控制点数 阶数 CATLONG32 uKnotNb uNb uOrder; CATLONG32 vKnotNb vNb vOrder; // 由工厂创建 Nurbs 曲面 CATNurbsSurface* pNurbs pFactory-CreateNurbsSurface( uOrder, vOrder, uNb, vNb, uKnotNb, vKnotNb); // 写入控制点(i, j) 是参数网格下标不是空间坐标 // 默认节点向量是均匀分布控制点坐标决定曲面形状 CATMathPoint pt; pt.Set(10.0, 0.0, 0.0); pNurbs-SetControlPoint(0, 0, pt); // 读回控制点验证写入是否生效 CATMathPoint ptRead; pNurbs-GetControlPoint(0, 0, ptRead); // 此时 ptRead 应该等于 (10, 0, 0) // 用完必须成对 ReleaseCAA 对象没有智能指针兜底 pNurbs-Release(); pFactory-Release();这段代码的逻辑分三步第一步用工厂创建曲面注意CreateNurbsSurface的参数顺序是 u 方向阶数、v 方向阶数、u 方向控制点数、v 方向控制点数、u 方向节点数、v 方向节点数写反了曲面形状会完全错乱。第二步用SetControlPoint写控制点这里有个高频误区(0,0)是参数网格里的行列不是空间坐标。第三步读回验证养成“写完就读回来”的习惯能帮你第一时间发现索引写错的问题。最后一步的Release是 CAA 里最容易被忽略的纪律。CAA 对象不是 C 标准库容器它靠引用计数管理谁创建谁释放漏掉Release就是内存泄漏提前Release再访问就是崩溃。没有智能指针兜底只能靠代码纪律。4.3 阶数、控制点、节点向量、容差四个绕不开的参数真正写业务逻辑时控制你的不是语法是这四个参数的语义。我见过不少项目把参数调了一周最后发现是“阶数”理解错了参数含义常见踩坑阶数 Order数学次数 1误把阶数当次数曲面次数比预期高 1光顺性全变控制点决定曲面大致形状的控制网格控制点坐标是模型空间注意单位换算节点向量参数区间分布默认均匀要表达尖角必须用重复节点容差几何判定精度STEP 导入时容差过紧会导致特征保留过度、面片数量爆炸先讲阶数。很多人查 Nurbs 资料看到“三阶”以为是三次曲线其实三阶等于二次。CATIA 里阶数和次数永远差 1写代码前先把这条换算关系钉在脑子里。节点向量是 Nurbs 区别于普通 Bezier 的核心均匀节点适合绝大多数曲面但你要做带尖角的形体时必须在尖角位置重复节点否则曲面会在那里被强制抹圆。容差则是另一个坑源。用这个插件做 STEP 转 CATIA 时导入流程里step文件转catia的转换质量在很大程度上由转换容差决定。容差设得过紧微小碎面全都保留后续操作卡成幻灯片设得过松小圆角特征直接消失。我的做法是先输出一份原始曲面的控制点密度和阶数统计再定容差而不是拍脑袋填数。还有一个常见需求是用法则曲线创建平行曲线当你对一张 Nurbs 曲面的等参数线做偏移时偏移量往往不是常数而是由法则曲线控制。这种场景在 CAA 里会用到 law 对象把偏移量包成一个带参函数传给偏移工具底层生成的还是一张新的 NURBS 曲面。理解这四个参数之间的约束关系你才不会被这种需求绕进去。5. CAAKcNurbsPluginFrm 编译与加载的 5 条避坑记录这部分是我做 CAA 插件这几年攒下的血泪经验。每条都是“现象、原因、解决”三段式排在前面的发生频率最高。5.1 现象DLL 编译出来了CATIA 里却看不到命令mkmk 全绿生成的 DLL 也躺在 code/bin 目录里但启动 CATIA 后菜单和命令都找不到这个 Nurbs 插件。原因不是代码逻辑错而是 CAA 命令的注册机制命令类必须通过模块的.dico字典被 CATIA 的资源管理器扫描到DLL 存在不等于资源字典被合并。最常见的是.CATEnv里的路径没指向 workspace 的generated目录或者.dico里CATCommandHeader的类名写法跟代码里CATDeclareClass不一致。解决方法是先确认.dico文件内容与类名完全一致再确认.CATEnv路径正确最后用cnext -env启动而不是双击图标。顺序别反先查环境再查代码。5.2 现象读 Nurbs 控制点时程序直接崩溃调用GetControlPoint读某个网格点时报访问冲突或者读回来数据完全错乱。原因一般是两类一是索引从 0 开始而代码里按 1 开始写了二是从外部文件导入的曲面u/v 方向控制点数量跟代码里硬编码的 4x4 不符越界访问。解决的办法是先通过曲面对象查询实际的控制点数量再遍历。调试时我会把控制点矩阵整体 dump 到一个 txt 文件肉眼核对边界比单步断点快得多。5.3 现象只改了一个 .cppmkmk 却全量重编这是一个让很多人觉得 CAA 是玄学的场景。明明只改了一个文件mkmk 却把整个模块甚至整个框架重新编译。原因通常是.m文件或者IdentityCard被改动过哪怕只是加了一个空格依赖哈希变了mkmk 就会重算整个依赖图。另一个常见诱因是源码放在网络盘上时间戳不稳定mkmk 误判所有文件都比生成物新。解决方法是源码永远放本地盘.m文件一旦写好就不要随手动依赖有变化单独提交一次后立刻全量编译一次。5.4 现象启动开发环境时提示 DS License Server 连不上刚开始排查插件加载问题时经常会看到 DS License Server 相关的报错。这不是插件代码的问题而是开发许可没有生效。现象是 CATIA 启动时弹许可超时或者 RADE 环境起不来而你还在拼命查代码。原因通常是许可服务器地址配置不对或者开发许可里没有包含 CAA 对应的 feature。解决方法是先确认许可服务器地址和端口在环境配置里正确再联系许可管理员确认开发 feature 已分配。别想着绕开许可验证去跑开发环境许可配不好后面每一步都在跟空气搏斗。5.5 现象把 dirtyo6w_zi 当成报错或者病毒拿到xxx_dirtyo6w_zi这种文件第一反应是编译报错或者打包出了问题。其实它只是构建系统自动拼出来的签名。dirty表示构建时源码树里有未提交的修改这本身不影响产物正确性但会带来一个隐患你无法从产物反推它对应哪个干净的提交。o6、w、zi这类片段是编译选项和调试信息开关的痕迹。我的习惯是看到dirty就回头把源码提交一次再重新构建否则后面排查问题时会发现产物和源码对不上那时候连后悔药都没有。6. 验证插件真正生效一条命令加一个参数 dump 技巧编译通过、命令能弹出来只证明插件加载了不证明 Nurbs 逻辑是对的。Nurbs 曲面不报错不代表曲线正确控制点写歪了、阶数算错了在没有可视化的情况下都看不出来。我验证插件是否真正生效靠的是一个参数 dump 技巧让命令把曲面的控制点、阶数、节点向量、容差全部写到一个 txt 文件然后跟预期值比对。这样不用打开 CATIA 图形界面在命令行里就能完成验证。# 假设 NurbsPluginCmd 已注册到 .dico用宏脚本驱动它执行 cnext -env NurbsPlugin.CATEnv -macro CheckNurbs.CATScript # 执行后检查插件输出的参数文件 notepad nurbs_dump.txtCheckNurbs.CATScript里干的事很简单调用NurbsPluginCmd让它对一张已知的 Nurbs 曲面执行读写然后把结果写到nurbs_dump.txt。我检查的时候只看三行控制点第 (0,0) 的坐标是否等于写入值阶数是否等于预期节点向量长度是否符合“控制点数 阶数”。这三个数对上了插件基本就是活的。还有一个进阶技巧把 dump 文件直接提交进版本管理。每次改动 Nurbs 相关代码后重新生成一份 dump跟历史版本 diff。控制点矩阵几十行数据靠肉眼看不出问题但 diff 一眼就能看到哪一排数据飘了。这比任何单步调试都好用尤其是处理导入转档这种数据量大的场景。我现在的习惯是每接手一个 CAA Nurbs 插件包先看文件名确认环境匹配再搭 workspace 编译最后留一份参数 dump 当基线。顺序固定从不跳过。这份流程帮我挡掉了大部分所谓“玄学”问题——CAA 的坑九成都在环境、依赖和参数语义里。希望帮到你。本文还有配套的精品资源点击获取