V6 DELMIA CAA API 开发实践指南
从结构树根节点到作业指令 —— 一步步掌握 PPT 涉及的全部 API
基于 PPT《V6 DELMIA常用功能及API介绍》 | 面向 CAA 二次开发工程师
第一章 总体介绍与基础概念
本章是全书的基石。DELMIA V6 采用 PPR(Process-Product-Resource) 模型来组织制造数据,理解 PPR 结构树、两种关联关系(Scope / Assign),以及如何获取结构树根节点,是后续所有 API 实践的前提。
1.1 PPR 模型与结构树概览
DELMIA V6 的核心数据模型由四棵结构树组成,它们共同构成了完整的制造工艺数字孪生:
| 结构树 | 含义 | 根节点类型 | 典型内容 |
|---|---|---|---|
| Product | 设计产品结构 | 实例(Instance) | 设计装配体、设计零件 |
| Process | 制造工艺结构 | 参考(Reference) | 制造装配体、制造零件 |
| System | 系统/操作结构 | 参考(Reference) | 系统、操作、先后关系 |
| Resource | 制造资源结构 | 实例(Instance) | 制造单元、人员、工具 |
关键概念:Instance vs Reference
Product 与 Resource 的根节点为 Instance(实例),对应接口
CATIPLMNavInstance;Process 与 System 的根节点为 Reference(参考),对应接口CATIPLMNavReference。这一区别直接影响后续获取根节点时使用的接口类型。
1.2 两种关联关系:Scope 与 Assign
PPR 模型中,四棵结构树之间通过两种关联关系建立联系:
| 关系类型 | 中文含义 | 帮助文档术语 | 作用 | 约束 |
|---|---|---|---|---|
| Scope | 范围关系 | Scope | 定义一个对象"管辖"哪些子对象 | 只有同一 Scope 内的对象才能创建 Assign 关系 |
| Assign | 分配关系 | Implement Link | 将设计对象分配到制造对象上(或反向) | 必须在同一 Scope 范围内 |
关联关系的创建来源
- Scope 关系:由工艺人员创建,定义"范围"层级
- Assign 关系:可由设计数据同步生成(设计装配 → 制造装配),也可由工艺人员手动编辑
操作入口
在 DELMIA 界面中,
Assignments Manager命令用于编辑对象间的 Assign 关系;Relations命令用于查看对象上已存在的所有关联关系。
1.3 结构树根节点获取 API
所有 PPR 结构树操作的起点都是获取根节点。DELIPPPRUIServices 接口提供了统一入口。
GetPPRRootsFromCurrentEditor GET
从当前编辑器中获取指定类型的 PPR 根节点列表
// 接口:DELIPPPRUIServices(模块:DELPPRProcessItf)
// 全局获取函数
HRESULT GetPPPRUIServices(DELIPPPRUIServices_var& spPPPRUIServices);
// 获取根节点列表
public virtual HRESULT GetPPRRootsFromCurrentEditor(
CATListValCATBaseUnknown_var& ioapRoots,
DELIPPPRUIServices::PPRRootType& iRootType
) = 0;
// PPRRootType 枚举值
// PRODUCT — Product PPR root(产品结构树根)
// PROCESS — Process PPR root(工艺结构树根)
// SYSTEM — System PPR root(系统结构树根)
// RESOURCE — Resource PPR root(资源结构树根)
完整代码示例:获取 Product 和 Process 根节点
// ========================================
// 获取 PPR 结构树根节点(Product + Process)
// ========================================
HRESULT rc = S_OK;
// 1. 获取 PPR UI Services 接口
DELIPPPRUIServices_var spPPPRUIServices = NULL_var;
rc = ::GetPPPRUIServices(spPPPRUIServices);
if (S_OK != rc || NULL_var == spPPPRUIServices) return E_FAIL;
// 2. 获取 Product 根节点(Instance 类型)
CATListValCATBaseUnknown_var lstProductRootUnknown;
lstProductRootUnknown.RemoveAll();
DELIPPPRUIServices::PPRRootType myProductRootType = DELIPPPRUIServices::PRODUCT;
rc = spPPPRUIServices->GetPPRRootsFromCurrentEditor(
lstProductRootUnknown, myProductRootType);
if (S_OK != rc || 0 == lstProductRootUnknown.Size()) return E_FAIL;
// Product 根节点为 Instance
CATIPLMNavInstance_var spProductRootInst = lstProductRootUnknown.operator[](1);
// 3. 获取 Process 根节点(Reference 类型)
CATListValCATBaseUnknown_var lstProcessRootUnknown;
lstProcessRootUnknown.RemoveAll();
DELIPPPRUIServices::PPRRootType myProcessRootType = DELIPPPRUIServices::PROCESS;
rc = spPPPRUIServices->GetPPRRootsFromCurrentEditor(
lstProcessRootUnknown, myProcessRootType);
if (S_OK != rc || 0 == lstProcessRootUnknown.Size()) return E_FAIL;
// Process 根节点为 Reference
CATIPLMNavReference_var spRootProcessRef = lstProcessRootUnknown.operator[](1);
注意:列表索引从 1 开始
CAA 的
CATListVal列表使用 1-based 索引,即第一个元素是operator[](1),而非operator[](0)。这是 CAA 体系的约定,不同于标准 C++ 容器。
实践练习一:获取并遍历 PPR 结构树根节点
练习一 — 获取四棵结构树的根节点并输出类型
练习目标
在一个 CAA Command 的 Activate() 方法中,依次获取 Product、Process、System、Resource 四棵结构树的根节点,并通过 CATInfo 或日志输出每个根节点的接口类型(Instance / Reference)。
练习步骤
- 创建 CAA Command:在 CAA Workbench 中创建一个继承自
CATCommand的命令类,在Activate()中编写以下逻辑。 - 获取 PPR UI Services:调用全局函数
::GetPPPRUIServices(),检查返回值和指针有效性。 - 循环遍历四种 PPRRootType:分别传入
PRODUCT、PROCESS、SYSTEM、RESOURCE,调用GetPPRRootsFromCurrentEditor。 - 输出根节点信息:对每个根节点,尝试
QueryInterface到CATIPLMNavInstance和CATIPLMNavReference,输出哪个成功,验证 Instance/Reference 区别。 - 验证结果:在 DELMIA 中打开一个包含完整 PPR 数据的文件,运行命令,确认输出 4 棵树的根节点类型符合预期。
参考代码框架
// 遍历四种 PPRRootType
DELIPPPRUIServices::PPRRootType rootTypes[] = {
DELIPPPRUIServices::PRODUCT,
DELIPPPRUIServices::PROCESS,
DELIPPPRUIServices::SYSTEM,
DELIPPPRUIServices::RESOURCE
};
const char* typeNames[] = {"PRODUCT", "PROCESS", "SYSTEM", "RESOURCE"};
for (int i = 0; i < 4; i++)
{
CATListValCATBaseUnknown_var lstRoots;
lstRoots.RemoveAll();
rc = spPPPRUIServices->GetPPRRootsFromCurrentEditor(lstRoots, rootTypes[i]);
if (S_OK != rc || 0 == lstRoots.Size())
{
CATUnicodeString msg = CATUnicodeString(typeNames[i]) + ": 无根节点";
// 输出日志...
continue;
}
CATBaseUnknown_var spRoot = lstRoots[1];
// 尝试 QI 到 Instance
CATIPLMNavInstance_var spInst = spRoot;
CATIPLMNavReference_var spRef = spRoot;
CATUnicodeString nodeType = (NULL_var != spInst) ? "Instance" :
(NULL_var != spRef) ? "Reference" : "Unknown";
// 输出: typeNames[i] + " 根节点类型: " + nodeType
}
验收标准
Product 和 Resource 输出 “Instance”,Process 和 System 输出 “Reference”。如果输出不符合预期,请检查当前编辑器中是否打开了正确的 PPR 数据。
第二章 Process 结构树开发
Process 结构树承载制造工艺数据,包括制造装配体、制造零件等。本章覆盖 Process 结构树中最常用的 API:对象类型获取、Scope/Assign 关系操作、Occurrence 同步等。
2.1 Process 模块及常用功能
Process 结构树的核心功能包括:
- 创建制造装配体 / 制造零件 — 搭建制造 BOM 结构
- 创建与设计模型间的 Scope 关系 — 建立制造-设计范围链接
- 编辑与设计模型间的 Assign 关系 — 将设计零件分配到制造零件
- 由设计模型同步制造模型 — 自动生成制造 BOM
2.2 对象类型获取 API
获取 Process 对象的类型是后续逻辑分支的基础。对应接口为 DELIPPRProcessTypeNav(模块:DELPPRProcessItf)。
| 方法名 | 方向 | 输入 | 输出 | 说明 |
|---|---|---|---|---|
GetProcessInstanceType |
Instance → Type | CATIPLMNavInstance* |
CATIType_var& |
获取实例对象类型 |
GetProcessReferenceType |
Reference → Type | CATIPLMNavReference* |
CATIType_var& |
获取参考对象类型 |
// 接口:DELIPPRProcessTypeNav
public virtual HRESULT GetProcessInstanceType(
CATIPLMNavInstance* ipiProcessInstance,
CATIType_var& oProcessInstanceType) = 0;
public virtual HRESULT GetProcessReferenceType(
CATIPLMNavReference* ipiProcessReference,
CATIType_var& oProcessReferenceType) = 0;
限制说明
这两个方法只能获取对象的 OOTB(Out-of-the-Box)基类类型,无法获取自定义的扩展类型。如果需要判断自定义类型,需要通过其他方式(如属性查询)。
2.3 Scope 关系操作 API
Scope 关系在 Process 与 Product(设计模型)之间建立"范围"链接。相关 API 分为查询和创建/移除两类。
2.3.1 Scope 查询
| 方法名 | 方向 | 说明 |
|---|---|---|
GetProductOfTheScope |
Process Ref → Product Ref | 由制造模型获取其 Scope 关联的设计模型 |
GetProcessOfTheScope |
Product Ref → Process Ref | 由设计模型获取其 Scope 关联的制造模型 |
GetProductOfTheScope GET
由 Process Reference 获取其 Scope 关联的 Product Reference
public virtual HRESULT GetProductOfTheScope(
CATIPLMNavReference* ipiProcessReference,
void** oppProductReference,
const IID& iIID = IID_CATIPLMNavReference
) = 0;
// Gets the product reference of the scope of a given process reference.
2.3.2 Scope 创建与移除
| 方法名 | 操作 | 参数 | 说明 |
|---|---|---|---|
CreateScope |
创建 | Process Ref, Product Ref | 创建制造模型与设计模型间的 Scope 关联 |
RemoveScope |
移除 | Process Ref | 移除制造模型与设计模型间的 Scope 关联 |
CreateScope CREATE
在 Process Reference 和 Product Reference 之间创建 Scope 链接
public virtual HRESULT CreateScope(
CATIPLMNavReference* ipiProcessReference,
CATIPLMNavReference* ipiProductReference
) = 0;
// Creates a scope link between a process reference and a product reference.
RemoveScope REMOVE
移除指定 Process Reference 的 Scope 链接
public virtual HRESULT RemoveScope(
CATIPLMNavReference* ipiProcessReference
) = 0;
// Removes a scope link between a process reference and associated product reference.
注意:RemoveScope 只需一个参数
RemoveScope只接收 Process Reference 一个参数,不需要 Product Reference。这是因为一个 Process 的 Scope 关系是唯一的。
2.4 Assign 关系操作 API
Assign 关系在 Process Occurrence 和 Product Occurrence 之间建立"分配"链接(又称 Implement Link)。
2.4.1 Assign 查询
| 方法名 | 方向 | 说明 |
|---|---|---|
GetListOfAssignedProducts |
Process Occ → Product Occ List | 由制造模型获取其 Assign 关联的设计模型列表 |
GetListOfAssigningProcesses |
Product Occ → Process Occ List | 由设计模型获取其 Assign 关联的制造模型列表 |
GetListOfAssignedProducts GET
获取分配给指定 Process Occurrence 的 Product Occurrence 列表
public virtual HRESULT GetListOfAssignedProducts(
CATIPLMNavOccurrence* ipiProcessOcc,
CATIPLMNavReference* ipiProductContextForOutputOcc,
CATListPtrCATIPLMNavOccurrence& oListProductOcc
) = 0;
// Gets the product occurrences that are assigned to a given process occurrence.
2.4.2 Assign 创建与移除
| 方法名 | 操作 | 参数 | 说明 |
|---|---|---|---|
AssignProduct |
创建 | Process Occ, Product Occ | 创建 Implement Link |
UnAssignProduct |
移除 | Process Occ, Product Occ | 移除 Implement Link |
AssignProduct CREATE
在 Process Occurrence 和 Product Occurrence 之间创建 Implement Link
public virtual HRESULT AssignProduct(
CATIPLMNavOccurrence* ipiProcessOcc,
CATIPLMNavOccurrence* ipiProductOcc
) = 0;
// Creates an implement link between a process occurrence and a product occurrence.
UnAssignProduct REMOVE
移除 Process Occurrence 和 Product Occurrence 之间的 Implement Link
public virtual HRESULT UnAssignProduct(
CATIPLMNavOccurrence* ipiProcessOcc,
CATIPLMNavOccurrence* ipiProductOcc
) = 0;
// Removes an implement link between a process occurrence and a product occurrence.
Scope vs Assign 操作层级
Scope 操作针对的是 Reference 层级(
CATIPLMNavReference*),而 Assign 操作针对的是 Occurrence 层级(CATIPLMNavOccurrence*)。这是因为 Scope 是结构性关系(定义范围),Assign 是实例性关系(具体分配)。
2.5 Occurrence 操作 API
Process 结构树的根节点是 Reference,但许多操作(如 Assign)需要 Occurrence。以下 API 用于在 Reference 和 Occurrence 之间转换,并同步结构树。
| 方法名 | 操作 | 说明 |
|---|---|---|
GetOrCreateRootOccurrence |
Reference → Occurrence | 由根节点 Reference 获取(或创建)对应的 Occurrence |
Synchronize |
同步结构树 | 根据当前事务中的模型事件同步 Occurrence 结构树 |
GetOrCreateRootOccurrence GET
public virtual HRESULT GetOrCreateRootOccurrence(
const CATIPLMNavReference* iRootReference,
CATIPLMNavOccurrence*& oRootOccurrence
) = 0;
Synchronize SYNC
public virtual HRESULT Synchronize(
const CATIPLMNavOccurrence* iRootOccurrence
) = 0;
// Synchronizes an occurrence tree with respect to the model events
// stored in the current transaction.
完整代码示例:获取 Occurrence 并同步
// 前提:已获取 spRootProcessRef (CATIPLMNavReference_var)
// 接口:DELIPPRProcessOccAuth(模块:DELPPRProcessItf)
// 1. 由根节点 Reference 获取 Occurrence
CATIPLMNavOccurrence* pRootOcc = NULL;
rc = spProcessOccAuth->GetOrCreateRootOccurrence(
(const CATIPLMNavReference*)spRootProcessRef, pRootOcc);
if (S_OK != rc || NULL == pRootOcc) return E_FAIL;
CATIPLMNavOccurrence_var spRootOcc = pRootOcc;
pRootOcc->Release();
// 2. 同步 Occurrence 结构树
rc = spProcessOccAuth->Synchronize(spRootOcc);
if (S_OK != rc) return E_FAIL;
最佳实践
在创建或移除 Scope/Assign 关系后,务必调用
Synchronize同步结构树,否则界面可能不会立即反映变更。
实践练习二:构建 Process-Manufacturing 关联模型
练习二 — 创建 Scope 与 Assign 关系并查询验证
练习目标
在已打开的 DELMIA V6 文件中,获取 Process 根节点和 Product 根节点,创建 Scope 关系,获取 Occurrence 后创建 Assign 关系,最后查询验证关系是否建立成功。
练习步骤
- 获取根节点:使用第一章的 API 获取 Process Root Reference 和 Product Root Instance。注意 Process 是 Reference,Product 是 Instance。
- 获取 Scope 操作接口:通过
QueryInterface获取DELIPPRProcessScopeNav接口(或对应 Scope 操作接口),准备创建 Scope。 - 创建 Scope 关系:调用
CreateScope(spProcessRef, spProductRef)在制造模型和设计模型间创建 Scope。 - 获取 Occurrence:通过
GetOrCreateRootOccurrence获取 Process 和 Product 的根 Occurrence。 - 创建 Assign 关系:调用
AssignProduct(spProcessOcc, spProductOcc)创建 Implement Link。 - 同步结构树:调用
Synchronize(spRootOcc)同步 Occurrence 树。 - 查询验证:调用
GetProductOfTheScope和GetListOfAssignedProducts反向查询,确认关系已正确建立。 - 清理(可选):调用
UnAssignProduct和RemoveScope移除关系,恢复初始状态。
常见陷阱
- 在创建 Assign 前必须先创建 Scope,否则 Assign 会失败。
- Assign 操作需要 Occurrence,而非 Reference。如果直接传 Reference 会编译错误或运行时崩溃。
Synchronize必须在结构变更后调用,否则后续查询可能返回过期数据。
第三章 System 结构树开发
System 结构树管理制造系统和操作序列,是工艺规划的核心。本章覆盖系统/操作的创建、Scope/Assign 关系、Product Flow 和 Precedence Link 先后关系等 API。
3.1 System 模块及常用功能
System 结构树的核心功能包括:
- 创建系统 / 创建操作 — 搭建工艺流程结构
- 创建先后关系 — Product Flow、结束-开始关系、带时间延迟的结束-开始关系
- 编辑与制造模型的 Scope / Assign 关系 — 系统与工艺、操作与工艺的关联
- 自动线平衡 / 查看甘特图 — 高级工艺分析功能
3.2 创建"系统-操作"结构树
系统结构树的创建使用 DELIPPRSystemAuth 接口(模块:DELPPRSystemItf)。
CreateSystem CREATE
创建一个系统(System)参考节点
public virtual HRESULT CreateSystem(
const CATIType_var& ihtType,
void** oppSystemReference,
const IID& iIID = IID_CATIPLMNavReference
) = 0;
// Creates a system reference.
CreateOperation CREATE
创建一个操作(Operation)参考节点
public virtual HRESULT CreateOperation(
const CATIType_var& ihType,
void** oppOperationReference,
const IID& iIID = IID_CATIPLMNavReference
) = 0;
// Creates an operation reference.
参数说明
ihtType/ihType指定要创建的系统或操作的具体类型,通过CATCkePLMNavPublicServices::RetrieveKnowledgeType获取。iIID默认为IID_CATIPLMNavReference,因为系统和操作的根节点都是 Reference 类型。
完整代码示例:创建系统和操作
// 前提:已获取 spSystemAuth (DELIPPRSystemAuth 接口)
// 以及父节点的 Reference: spFatherRef
// 1. 获取系统类型
CATIType_var spSystemType = NULL_var;
rc = CATCkePLMNavPublicServices::RetrieveKnowledgeType(
"DELPPRSystemReference", spSystemType);
if (S_OK != rc || NULL_var == spSystemType) return E_FAIL;
// 2. 创建系统
CATIPLMNavReference* pSystemRef = NULL;
rc = spSystemAuth->CreateSystem(spSystemType, (void**)&pSystemRef);
if (S_OK != rc || NULL == pSystemRef) return E_FAIL;
CATIPLMNavReference_var spSystemRef = pSystemRef;
pSystemRef->Release();
// 3. 获取操作类型并创建操作
CATIType_Var spOpType = NULL_var;
rc = CATCkePLMNavPublicServices::RetrieveKnowledgeType(
"DELPprOperationReference", spOpType);
if (S_OK != rc) return E_FAIL;
CATIPLMNavReference* pOpRef = NULL;
rc = spSystemAuth->CreateOperation(spOpType, (void**)&pOpRef);
if (S_OK != rc || NULL == pOpRef) return E_FAIL;
CATIPLMNavReference_var spOpRef = pOpRef;
pOpRef->Release();
3.3 Scope 与 Assign 关系操作
3.3.1 Scope 关系(System ↔ Manufacturing)
Scope 关系在 System 和 Manufacturing(Process)之间建立范围链接。Scope 关系只存在于"系统"节点上,不会存在于"操作"节点上。
| 方法名 | 操作 | 参数 | 说明 |
|---|---|---|---|
CreateScope |
创建 | System Occ, Process Occ | 创建系统模型与制造模型间的 Scope 关联 |
RemoveScope |
移除 | System Occ, process Occ | 移除系统模型与制造模型间的 Scope 关联 |
GetProcessOfTheScope |
查询 | System Ref | 由系统模型获取其 Scope 关联的制造模型 |
GetSystemOfTheScope |
查询 | process Ref | 由制造模型获取其 Scope 关联的系统模型 |
CreateScope (System) CREATE
在 System Occurrence 和 Process/Workplan Occurrence 之间创建 Scope
public virtual HRESULT CreateScope(
CATIPLMNavOccurrence* ipiSystemOccurrence,
CATIPLMNavOccurrence* ipiProcessOrWorkplanOccurrence
) = 0;
3.3.2 Assign 关系(Operation ↔ Manufacturing)
Assign 关系在 Operation 和 Manufacturing(Process)之间建立分配链接。Assign 关系只存在于"操作"节点上,不会存在于"系统"节点上。
| 方法名 | 操作 | 参数 | 说明 |
|---|---|---|---|
AssignProcess |
创建 | Operation Occ, Process Occ | 创建操作与制造模型间的 Assign 关联 |
UnAssignProcess |
移除 | Operation Occ, Process Occ | 移除操作与制造模型间的 Assign 关联 |
GetListOfAssignedProcesses |
查询 | Operation Occ | 由操作获取其 Assign 关联的制造模型 |
GetListOfAssigningOperations |
查询 | Process Occ | 由制造模型获取其 Assign 关联的操作 |
AssignProcess CREATE
在 Operation Occurrence 和 Process Occurrence 之间创建 Implement Link
public virtual HRESULT AssignProcess(
CATIPLMNavOccurrence* ipiOperationOcc,
CATIPLMNavOccurrence* ipiProcessOcc
) = 0;
// Creates an implement link between an operation occurrence and a process occurrence.
关键约束
Scope 只在"系统"节点上,Assign 只在"操作"节点上。在"系统"节点上创建 Assign 或在"操作"节点上创建 Scope 都会失败。这是 System 结构树最重要的规则之一。
3.3.3 Occurrence 操作
System 结构树同样需要通过 GetOrCreateRootOccurrence 和 Synchronize 在 Reference 和 Occurrence 之间转换,用法与第二章 Process 结构树完全一致。
3.4 Product Flow 先后关系
Product Flow 用于创建系统之间的先后关系(如物料流)。对应接口为 DELIPPPRProductFlowManagementNav(模块:DELPPRSystemItf)。
| 方法名 | 方向 | 说明 |
|---|---|---|
GetProductFlowSystemsTo |
获取先前对象 | 获取当前系统之前的系统(上游) |
GetProductFlowSystemsFrom |
获取后续对象 | 获取当前系统之后的系统(下游) |
GetListOfPortsForProductFlow |
获取端口列表 | 获取 Product Flow 的端口信息 |
GetListOfPortsForProductFlow GET
public virtual HRESULT GetListOfPortsForProductFlow(
CATIPLMNavReference* ipiSystemReference,
int iDirection,
CATListPtrCATBaseUnknown& oPortsList
) = 0;
方向参数
iDirection参数指定查询方向:GetProductFlowSystemsTo获取先前(上游)对象,GetProductFlowSystemsFrom获取后续(下游)对象。
3.5 Precedence Link 先后关系
Precedence Link 用于创建操作之间的先后关系(如先后顺序约束)。对应接口为 DELIPPRSystemTimeConstrNav(模块:DELPPRSystemItf)。
| 方法名 | 方向 | 说明 |
|---|---|---|
GetConstrainingOperationsList |
获取先前对象 | 获取约束当前操作的先前操作列表 |
GetConstrainedOperationsList |
获取后续对象 | 获取被当前操作约束的后续操作列表 |
GetConstrainedOperationsList GET
获取被指定操作约束的后续操作列表(含延迟时间)
public virtual HRESULT GetConstrainedOperationsList(
CATIPLMNavOccurrence* iOperationSourceOcc,
CATListPtrCATIPLMNavOccurrence& oTargetsOccList,
CATListOfDouble& oDelaysList
) = 0;
// Retrieves the list of occurrences of Operations that the given
// occurrence of Operation is constraining.
延迟时间
GetConstrainedOperationsList的第三个参数oDelaysList返回与每个后续操作对应的延迟时间列表,用于表示带时间延迟的结束-开始关系。列表索引与oTargetsOccList一一对应。
完整代码示例:遍历操作的先后关系
// 前提:已获取 spOpOcc (CATIPLMNavOccurrence_var) 和 spTimeConstrNav 接口
// 1. 获取后续操作列表
CATListPtrCATIPLMNavOccurrence lstConstrainedOps;
CATListOfDouble lstDelays;
rc = spTimeConstrNav->GetConstrainedOperationsList(
spOpOcc, lstConstrainedOps, lstDelays);
if (S_OK == rc)
{
for (int i = 1; i <= lstConstrainedOps.Size(); i++)
{
CATIPLMNavOccurrence* pTarget = lstConstrainedOps[i];
double delay = lstDelays[i];
// 输出: "后续操作 #" + i + ", 延迟: " + delay + "s"
}
}
// 2. 获取先前操作列表
CATListPtrCATIPLMNavOccurrence lstConstrainingOps;
CATListOfDouble lstDelays2;
rc = spTimeConstrNav->GetConstrainingOperationsList(
spOpOcc, lstConstrainingOps, lstDelays2);
if (S_OK == rc)
{
for (int i = 1; i <= lstConstrainingOps.Size(); i++)
{
CATIPLMNavOccurrence* pSource = lstConstrainingOps[i];
double delay = lstDelays2[i];
// 输出: "先前操作 #" + i + ", 延迟: " + delay + "s"
}
}
实践练习三:构建 System 操作序列
练习三 — 创建系统-操作结构树并建立先后关系
练习目标
创建一个系统节点,在其下创建三个操作(Op1、Op2、Op3),建立 Op1→Op2→Op3 的先后关系,并查询验证。
练习步骤
- 获取 System 根节点:使用
GetPPRRootsFromCurrentEditor传入SYSTEM获取 System 根 Reference。 - 获取创建接口:通过
QueryInterface获取DELIPPRSystemAuth接口。 - 创建系统:调用
CreateSystem创建一个系统节点。 - 创建三个操作:调用
CreateOperation三次,创建 Op1、Op2、Op3。为每个操作设置名称属性。 - 创建 Scope 关系:获取系统 Occurrence 和 Process Occurrence,调用
CreateScope在系统与制造模型间建立 Scope。 - 创建 Assign 关系:对每个操作调用
AssignProcess在操作与制造模型间建立 Assign。 - 建立先后关系:使用 Precedence Link API 创建 Op1→Op2、Op2→Op3 的先后约束。
- 查询验证:调用
GetConstrainedOperationsList(Op1)确认返回 Op2;调用GetConstrainingOperationsList(Op3)确认返回 Op2。
注意
创建系统/操作后需要
Synchronize同步 Occurrence 树,才能进行后续的 Scope/Assign 和先后关系操作。先后关系使用 Occurrence 层级的操作对象。
第四章 Resource 结构树开发
Resource 结构树管理制造资源(制造单元、人员、工具等),并将其分配到操作上。本章覆盖资源节点创建和 Scope/Assign 关系操作。
4.1 Resource 模块及常用功能
Resource 结构树的核心功能包括:
- 创建制造单元 — 用于搭建资源结构树
- 创建人员 / 创建工具 — 具体资源类型
- 编辑与系统模型的 Scope 关系 — 制造单元与系统的范围链接
- 编辑与操作模型的 Assign 关系 — 具体资源与操作的分配
4.2 创建资源节点
资源节点的创建使用 DELIPPRResourceAuth 接口(模块:DELPPRResourceItf)。
DELIPPRResourceAuth CREATE
资源创建接口,用于创建制造单元、人员、工具等资源节点
// 接口:DELIPPRResourceAuth(模块:DELPPRResourceItf)
// 通过 CreateSubSystemOrOperation 或类似方法创建资源节点
// 资源类型包括:
// - 制造单元(用于搭建资源结构树)
// - 人员
// - 工具
创建资源的通用模式
// 1. 获取 Resource 根节点(Instance 类型)
CATListValCATBaseUnknown_var lstResourceRoots;
DELIPPPRUIServices::PPRRootType resType = DELIPPPRUIServices::RESOURCE;
rc = spPPPRUIServices->GetPPRRootsFromCurrentEditor(lstResourceRoots, resType);
if (S_OK != rc || 0 == lstResourceRoots.Size()) return E_FAIL;
CATIPLMNavInstance_var spResourceRootInst = lstResourceRoots[1];
// 2. 获取资源创建接口
DELIPPRResourceAuth_var spResourceAuth = spResourceRootInst;
if (NULL_var == spResourceAuth) return E_FAIL;
// 3. 获取资源类型(如制造单元类型)
CATIType_var spResType = NULL_var;
rc = CATCkePLMNavPublicServices::RetrieveKnowledgeType(
"DELPPRManufacturingCellReference", spResType);
if (S_OK != rc) return E_FAIL;
// 4. 创建资源节点
CATIPLMNavInstance* pCreatedInst = NULL;
rc = spResourceAuth->CreateSubSystemOrOperation(
spFatherRef, spResType, (void**)&pCreatedInst,
CATIPLMNavInstance::ClassId());
if (S_OK != rc || NULL == pCreatedInst) return E_FAIL;
4.3 Scope 与 Assign 关系操作
4.3.1 Scope 关系(Resource ↔ System)
Scope 关系在 Resource(制造单元)和 System 之间建立范围链接。Scope 关系只存在于"制造单元"节点上。
| 方法名 | 操作 | 参数 | 说明 |
|---|---|---|---|
CreateScope |
创建 | Resource Occ, System Occ | 创建资源模型与系统模型间的 Scope 关联 |
RemoveScope |
移除 | Resource Occ, System Occ | 移除资源模型与系统模型间的 Scope 关联 |
GetSystemOfTheScope |
查询 | Resource Ref | 由资源模型获取其 Scope 关联的系统模型 |
GetResourceOfTheScope |
查询 | System Ref | 由系统模型获取其 Scope 关联的资源模型 |
4.3.2 Assign 关系(Resource ↔ Operation)
Assign 关系在具体资源(人员、工具等)和 Operation 之间建立分配链接。Assign 关系只存在于具体资源节点上。
| 方法名 | 操作 | 说明 |
|---|---|---|
AssignResource |
创建 | 创建资源模型与操作模型间的 Assign 关联 |
UnAssignResource |
移除 | 移除资源模型与操作模型间的 Assign 关联 |
GetAssignedOperation |
查询 | 由资源模型获取其 Assign 关联的操作模型 |
GetAssignedWhoResource |
查询 | 由操作获取其 Assign 关联的"Who"资源(人员) |
GetAssignedWhereResource |
查询 | 由操作获取其 Assign 关联的"Where"资源(位置/设备) |
关键陷阱:E_FAIL 返回值
GetAssignedWhoResource接口在 Operation 没有分配资源时会返回 E_FAIL。不要随意判断返回值进行操作 — E_FAIL 不一定代表错误,可能只是表示"当前操作未分配 Who 资源"。应该将 E_FAIL 视为"无分配"的正常情况处理。
Who vs Where
在 DELMIA 资源分配中:"Who"资源指人员/操作者类资源;"Where"资源指位置/设备类资源。两者都通过 Assign 关系关联到操作上,但查询方法不同。
实践练习四:资源分配与查询
练习四 — 创建资源并分配到操作
练习目标
在练习三创建的系统-操作结构树基础上,创建制造单元和人员资源,将制造单元 Scope 到系统,将人员 Assign 到操作,并查询验证分配关系。
练习步骤
- 获取 Resource 根节点:使用
GetPPRRootsFromCurrentEditor传入RESOURCE获取根节点。 - 创建制造单元:使用
DELIPPRResourceAuth接口创建一个制造单元节点。 - 创建人员:在制造单元下创建一个人员节点。
- 创建 Scope 关系:获取制造单元 Occurrence 和系统 Occurrence,调用
CreateScope建立范围链接。 - 创建 Assign 关系:获取人员 Occurrence 和操作 Occurrence,调用
AssignResource建立分配链接。 - 同步结构树:调用
Synchronize同步 Occurrence 树。 - 查询验证:调用
GetAssignedWhoResource查询操作的 Who 资源。注意正确处理 E_FAIL 返回值。 - 移除分配(可选):调用
UnAssignResource移除人员分配,再次查询确认返回 E_FAIL(无分配)。
注意事项
- Scope 关系只在制造单元节点上创建,不在人员/工具节点上。
- Assign 关系只在具体资源(人员、工具)上创建,不在制造单元上。
- 处理
GetAssignedWhoResource返回值时,E_FAIL 表示"无分配"而非"出错"。
第五章 作业指令编制
作业指令(Work Instruction)是指导现场操作的具体文档。本章覆盖文本指令的创建、文本内容的读写,以及视图的打印导出。
5.1 作业指令模块及常用功能
作业指令编制的核心功能包括:
- 创建文本指令 — 在工艺节点下创建文本类型的作业指令
- 创建视图 — 创建 3D 视图/快照
- 读写文本内容 — 通过属性读写指令文本
- 打印视图 — 导出视图为图片
5.2 创建文本指令
创建文本指令的核心是通过 CreateSubSystemOrOperation 方法创建类型为 DELWkiInstructionReference 的实例。
CreateSubSystemOrOperation CREATE
在父节点下创建子节点(用于创建文本指令实例)
HRESULT CreateSubSystemOrOperation(
CATIPLMNavReference* iFatherRef,
CATIType_var& iType,
void** oCreated,
const CLSID& iClsid
);
完整代码示例:创建文本指令
// 前提:已获取父节点 Occurrence: ispFatherOcc
// 已获取创建接口: spPPRServicesAuth
// 输入参数: istrName (指令名称)
// 1. 获取父节点 Reference
CATIPLMNavReference* pFatherRef = NULL;
rc = ispFatherOcc->GetRelatedReference(pFatherRef);
if (S_OK != rc || NULL == pFatherRef) return E_FAIL;
// 2. 获取文本指令类型
CATIType_var spRefType = NULL_var;
rc = CATCkePLMNavPublicServices::RetrieveKnowledgeType(
"DELWkiInstructionReference", spRefType);
if (S_OK != rc || NULL_var == spRefType) return E_FAIL;
// 3. 创建指令实例
CATIPLMNavInstance* pCreatedInst = NULL;
rc = spPPRServicesAuth->CreateSubSystemOrOperation(
pFatherRef, spRefType, (void**)&pCreatedInst,
CATIPLMNavInstance::ClassId());
if (S_OK != rc || NULL == pCreatedInst) return E_FAIL;
// 4. 设置实例名称
CATICkeObject_var spInstCkeTemp = pCreatedInst;
if (NULL_var == spInstCkeTemp) return E_FAIL;
rc = CATCkeObjectAttrWriteServices::SetValueWithString(
spInstCkeTemp, CATUnicodeString("Name"),
istrName + CATUnicodeString(".1"));
if (S_OK != rc) return E_FAIL;
// 5. 获取 Reference 并设置名称
CATIPLMNavReference* pCreatedRef = NULL;
rc = pCreatedInst->GetReferenceInstanceOf(pCreatedRef);
if (S_OK != rc || NULL == pCreatedRef) return E_FAIL;
CATICkeObject_var spRefCkeTemp = pCreatedRef;
if (NULL_var == spRefCkeTemp) return E_FAIL;
rc = CATCkeObjectAttrWriteServices::SetValueWithString(
spRefCkeTemp, CATUnicodeString("V_Name"), istrName);
if (S_OK != rc) return E_FAIL;
命名约定
实例使用
"Name"属性,命名格式为"指令名.1";Reference 使用"V_Name"属性,命名格式为"指令名"。这是 PLM V6 的标准命名规范。
5.3 读写文本指令内容
文本指令的内容存储在 V_WIInstruction_Text 属性中,格式为 HTML(包含 <p>、<br/> 等标签)。
读取文本内容
// 前提:spChildRefCke 为指令对象的 CATICkeObject_var
// 1. 读取指令名称
CATUnicodeString strInstructionName = CATUnicodeString("");
rc = CATCkeObjectAttrReadServices::GetValueAsString(
spChildRefCke, CATUnicodeString("V_Name"), strInstructionName);
if (S_OK != rc) continue;
// 2. 读取文本内容(HTML 格式)
CATUnicodeString strInstructionText = CATUnicodeString("");
rc = CATCkeObjectAttrReadServices::GetValueAsString(
spChildRefCke, CATUnicodeString("V_WIInstruction_Text"),
strInstructionText);
if (S_OK != rc) continue;
// 3. 解析 HTML,提取纯文本
int iStart = strInstructionText.SearchSubString(
CATUnicodeString("<p>"));
int iEnd = strInstructionText.SearchSubString(
CATUnicodeString("</p>"));
CATUnicodeString strContent = CATUnicodeString("");
if (0 <= iStart && 0 <= iEnd && iStart + 3 < iEnd)
strContent = strInstructionText.SubString(iStart + 3, iEnd - iStart - 3);
// 4. 将 <br/> 替换为换行符
strContent.ReplaceAll(CATUnicodeString("<br/>"), CATUnicodeString("\n"));
写入文本内容
// 将纯文本包装为 HTML 格式后写入
CATUnicodeString strHtmlContent = CATUnicodeString("<p>") +
strPlainText + CATUnicodeString("</p>");
rc = CATCkeObjectAttrWriteServices::SetValueAsString(
spInstCke, CATUnicodeString("V_WIInstruction_Text"),
strHtmlContent);
HTML 格式
V_WIInstruction_Text属性存储的是 HTML 格式的文本,外层包裹<p>...</p>标签,换行使用<br/>。读取时需要解析 HTML 标签提取纯文本;写入时需要将纯文本包装为 HTML 格式。
5.4 打印视图
打印视图的核心是使用 Selection 搜索 Review Slide,获取缩略图并导出为图片文件。
完整代码示例:导出视图为 BMP
// 前提:_pCATIASelection 为 CATIASelection 接口
// ispRootOcc 为根 Occurrence
// spOccAliasTemp 为操作别名
if (S_OK == _pCATIASelection->xClear())
{
// 1. 将根节点添加到选择集
if (S_OK == _pCATIASelection->Add(
(CATIABase*)(CATIPLMNavOccurrence*)ispRootOcc))
{
// 2. 搜索 Review Slide
CATUnicodeString strSearch = CATUnicodeString("Review.Slide,sel");
CATBSTR bstrSearch;
strSearch.ConvertToBSTR(&bstrSearch);
if (S_OK == _pCATIASelection->Search(bstrSearch))
{
// 3. 遍历选择结果
CATLONG lCount = 0;
_pCATIASelection->get_Count(&lCount);
for (CATLONG i = 1; i <= lCount; i++)
{
CATIASElectedElement* pSelEle = NULL;
rc = _pCATIASelection->Item(i, pSelEle);
if (S_OK != rc || NULL == pSelEle) continue;
CATBaseDispatch* pBase = NULL;
rc = pSelEle->get_Value(&pBase);
if (S_OK != rc || NULL == pBase) continue;
// 4. 获取 Slide 接口
CATIREVSlide* pSlide = NULL;
rc = pBase->QueryInterface(
CATIREVSlide::ClassId(), (void**)&pSlide);
if (S_OK == rc && NULL != pSlide)
{
CATIAlias_var spSlideAlias = pSlide;
if (NULL_var == spSlideAlias) continue;
// 5. 获取缩略图
CATPixelImage* pImage = NULL;
rc = pSlide->GetThumbnail(&pImage);
if (S_OK == rc && NULL != pImage)
{
// 6. 构建文件名并保存
CATUnicodeString strPath = CATUnicodeString("D:\\");
CATUnicodeString strOpName = spOccAliasTemp->GetAlias();
CATUnicodeString strSlideName = spSlideAlias->GetAlias();
CATUnicodeString strFile = CATUnicodeString("Operation_") +
strOpName + CATUnicodeString("_Slide_") +
strSlideName + CATUnicodeString(".bmp");
char path[CATMaxPathSize];
CATMakePath(strPath.ConvertToChar(),
strFile.ConvertToChar(), path);
pImage->WriteToFile("BMP", path);
}
}
}
}
}
_pCATIASelection->Clear();
}
关键类说明
CATIREVSlide— Review Slide 接口,代表一个视图快照。
CATPixelImage— 像素图像类,支持WriteToFile导出为 BMP 等格式。
CATIAlias— 别名接口,用于获取对象名称。
实践练习五:生成作业指令文档
练习五 — 创建文本指令、写入内容并导出视图
练习目标
在练习三的操作节点下创建一条文本指令,写入 HTML 格式的指令内容,读取并解析为纯文本输出,最后将操作关联的视图导出为 BMP 图片。
练习步骤
- 创建文本指令:在操作节点下使用
CreateSubSystemOrOperation创建类型为DELWkiInstructionReference的指令实例。 - 设置指令名称:分别设置 Instance 的
"Name"和 Reference 的"V_Name"属性。 - 写入文本内容:将一段纯文本包装为
<p>...</p>格式,通过SetValueAsString写入V_WIInstruction_Text属性。 - 读取文本内容:使用
GetValueAsString读取V_WIInstruction_Text,解析 HTML 标签提取纯文本,将<br/>替换为换行。 - 导出视图:使用 Selection 搜索
Review.Slide,sel,获取 Slide 缩略图,导出为 BMP 文件。 - 验证结果:检查导出的 BMP 文件是否正确生成,文件名是否包含操作名和 Slide 名。
验收标准
- 创建的文本指令在 DELMIA 结构树中可见。
- 读取的纯文本内容与写入的内容一致(换行符正确转换)。
- BMP 文件成功生成在指定路径,文件名格式为
Operation_XXX_Slide_YYY.bmp。
第六章 常用查询方法
在 CAA 开发过程中,遇到不熟悉的 API 是常态。PPT 总结了 8 种常用的 API 查询途径,掌握这些方法可以大幅提升开发效率。
| 查询方法 | 适用场景 | 特点 |
|---|---|---|
| 3DE 帮助文档 | 查找界面操作和功能说明 | 随软件安装,面向终端用户 |
| CAA 帮助文档 | 查找接口定义、方法签名 | 面向开发者,最权威的 API 参考 |
| CAADoc 查询 | 搜索具体接口或方法 | 可按关键字搜索,快速定位 |
| Object Browser | 浏览接口继承关系和方法列表 | Visual Studio 内置,直观查看类结构 |
| 请教同事 | 解决疑难问题和经验性问题 | 最高效,但依赖团队经验 |
| VBA 接口 | 快速验证 API 行为 | 通过 VBA 宏快速测试接口调用 |
| EKL 接口 | 使用 EKL(Engineering Knowledge Language)验证 | 声明式语言,适合知识规则验证 |
| 达索官网 | 查找最新文档、论坛问答 | 访问 https://swym.3ds.com/ |
6.1 查询策略建议
推荐查询流程
第一步:使用 CAA 帮助文档或 CAADoc 查询搜索接口名/方法名,获取签名和说明。
第二步:使用 Object Browser查看接口的完整方法列表和继承关系。
第三步:使用 VBA 接口或 EKL 接口快速验证 API 行为,确认参数和返回值。
第四步:遇到疑难问题,请教同事或到达索官网搜索。
第五步:查阅 3DE 帮助文档理解功能背景和业务含义。
6.2 达索官网资源
达索官方社区网址为 https://swym.3ds.com/,可在其中搜索技术问题、查看官方文档更新、参与社区讨论。建议加入相关的 DELMIA CAA 开发社区,获取最新资讯和同行经验。
附录 API 速查表
A.1 根节点获取
| API | 接口 | 说明 |
|---|---|---|
GetPPPRUIServices |
全局函数 | 获取 PPR UI Services 接口 |
GetPPRRootsFromCurrentEditor |
DELIPPPRUIServices | 获取指定类型的 PPR 根节点列表 |
A.2 Process 结构树 API
| API | 操作类型 | 层级 | 说明 |
|---|---|---|---|
GetProcessInstanceType |
查询 | Instance | 获取实例对象类型 |
GetProcessReferenceType |
查询 | Reference | 获取参考对象类型 |
GetProductOfTheScope |
查询 | Reference | Process → Product (Scope) |
GetProcessOfTheScope |
查询 | Reference | Product → Process (Scope) |
CreateScope |
创建 | Reference | 创建 Scope 关系 |
RemoveScope |
移除 | Reference | 移除 Scope 关系 |
GetListOfAssignedProducts |
查询 | Occurrence | Process → Product 列表 (Assign) |
AssignProduct |
创建 | Occurrence | 创建 Assign 关系 |
UnAssignProduct |
移除 | Occurrence | 移除 Assign 关系 |
GetOrCreateRootOccurrence |
转换 | Ref → Occ | 获取/创建根 Occurrence |
Synchronize |
同步 | Occurrence | 同步结构树 |
A.3 System 结构树 API
| API | 操作类型 | 节点约束 | 说明 |
|---|---|---|---|
CreateSystem |
创建 | - | 创建系统 Reference |
CreateOperation |
创建 | - | 创建操作 Reference |
CreateScope |
创建 | 仅系统节点 | System ↔ Process Scope |
RemoveScope |
移除 | 仅系统节点 | 移除 System ↔ Process Scope |
AssignProcess |
创建 | 仅操作节点 | Operation ↔ Process Assign |
UnAssignProcess |
移除 | 仅操作节点 | 移除 Operation ↔ Process Assign |
GetProductFlowSystemsTo |
查询 | 系统 | 获取先前系统(上游) |
GetProductFlowSystemsFrom |
查询 | 系统 | 获取后续系统(下游) |
GetConstrainingOperationsList |
查询 | 操作 | 获取先前操作(含延迟) |
GetConstrainedOperationsList |
查询 | 操作 | 获取后续操作(含延迟) |
A.4 Resource 结构树 API
| API | 操作类型 | 节点约束 | 说明 |
|---|---|---|---|
CreateSubSystemOrOperation |
创建 | - | 创建资源节点 |
CreateScope |
创建 | 仅制造单元 | Resource ↔ System Scope |
RemoveScope |
移除 | 仅制造单元 | 移除 Resource ↔ System Scope |
AssignResource |
创建 | 具体资源 | Resource ↔ Operation Assign |
UnAssignResource |
移除 | 具体资源 | 移除 Resource ↔ Operation Assign |
GetAssignedWhoResource |
查询 | 操作 | 获取 Who 资源(注意 E_FAIL) |
GetAssignedWhereResource |
查询 | 操作 | 获取 Where 资源 |
A.5 作业指令 API
| API / 属性 | 说明 |
|---|---|
CreateSubSystemOrOperation |
创建文本指令实例(类型: DELWkiInstructionReference) |
CATCkeObjectAttrReadServices::GetValueAsString |
读取属性值(V_Name, V_WIInstruction_Text) |
CATCkeObjectAttrWriteServices::SetValueWithString |
写入属性值 |
V_WIInstruction_Text |
文本内容属性(HTML 格式) |
CATIREVSlide::GetThumbnail |
获取视图缩略图 |
CATPixelImage::WriteToFile |
导出图片为 BMP 等格式 |
A.6 关键接口模块映射
| 接口 | 模块 | 用途 |
|---|---|---|
DELIPPPRUIServices |
DELPPRProcessItf | PPR 根节点获取 |
DELIPPRProcessTypeNav |
DELPPRProcessItf | Process 对象类型获取 |
DELIPPRProcessOccAuth |
DELPPRProcessItf | Process Occurrence 操作 |
DELIPPRSystemAuth |
DELPPRSystemItf | System/Operation 创建 |
DELIPPPRProductFlowManagementNav |
DELPPRSystemItf | Product Flow 先后关系 |
DELIPPRSystemTimeConstrNav |
DELPPRSystemItf | Precedence Link 先后关系 |
DELIPPRResourceAuth |
DELPPRResourceItf | Resource 节点创建 |
A.7 常见陷阱速查
| 陷阱 | 正确做法 |
|---|---|
| 列表索引从 0 开始 | CAA 列表使用 1-based 索引 |
| 未创建 Scope 就创建 Assign | 必须先创建 Scope,再创建 Assign |
| Scope/Assign 传错层级 | Scope 用 Reference,Assign 用 Occurrence |
| 结构变更后未同步 | 调用 Synchronize 同步结构树 |
| 系统节点创建 Assign | Assign 只在操作节点,Scope 只在系统节点 |
| 制造单元创建 Assign | Assign 只在具体资源,Scope 只在制造单元 |
| GetAssignedWhoResource 返回 E_FAIL 当错误处理 | E_FAIL 表示"无分配",不是错误 |
| 文本指令内容直接读写纯文本 | 内容为 HTML 格式,需解析/包装 |
| 类型获取返回自定义类型 | 只能获取 OOTB 基类类型 |
评论