← 返回首页

V6 DELMIA CAA API 开发实践指南

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)。

练习步骤

  1. 创建 CAA Command:在 CAA Workbench 中创建一个继承自 CATCommand 的命令类,在 Activate() 中编写以下逻辑。
  2. 获取 PPR UI Services:调用全局函数 ::GetPPPRUIServices(),检查返回值和指针有效性。
  3. 循环遍历四种 PPRRootType:分别传入 PRODUCTPROCESSSYSTEMRESOURCE,调用 GetPPRRootsFromCurrentEditor
  4. 输出根节点信息:对每个根节点,尝试 QueryInterfaceCATIPLMNavInstanceCATIPLMNavReference,输出哪个成功,验证 Instance/Reference 区别。
  5. 验证结果:在 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 关系,最后查询验证关系是否建立成功。

练习步骤

  1. 获取根节点:使用第一章的 API 获取 Process Root Reference 和 Product Root Instance。注意 Process 是 Reference,Product 是 Instance。
  2. 获取 Scope 操作接口:通过 QueryInterface 获取 DELIPPRProcessScopeNav 接口(或对应 Scope 操作接口),准备创建 Scope。
  3. 创建 Scope 关系:调用 CreateScope(spProcessRef, spProductRef) 在制造模型和设计模型间创建 Scope。
  4. 获取 Occurrence:通过 GetOrCreateRootOccurrence 获取 Process 和 Product 的根 Occurrence。
  5. 创建 Assign 关系:调用 AssignProduct(spProcessOcc, spProductOcc) 创建 Implement Link。
  6. 同步结构树:调用 Synchronize(spRootOcc) 同步 Occurrence 树。
  7. 查询验证:调用 GetProductOfTheScopeGetListOfAssignedProducts 反向查询,确认关系已正确建立。
  8. 清理(可选):调用 UnAssignProductRemoveScope 移除关系,恢复初始状态。

常见陷阱

  1. 在创建 Assign 前必须先创建 Scope,否则 Assign 会失败。
  2. Assign 操作需要 Occurrence,而非 Reference。如果直接传 Reference 会编译错误或运行时崩溃。
  3. 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 结构树同样需要通过 GetOrCreateRootOccurrenceSynchronize 在 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 获取后续(下游)对象。

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 的先后关系,并查询验证。

练习步骤

  1. 获取 System 根节点:使用 GetPPRRootsFromCurrentEditor 传入 SYSTEM 获取 System 根 Reference。
  2. 获取创建接口:通过 QueryInterface 获取 DELIPPRSystemAuth 接口。
  3. 创建系统:调用 CreateSystem 创建一个系统节点。
  4. 创建三个操作:调用 CreateOperation 三次,创建 Op1、Op2、Op3。为每个操作设置名称属性。
  5. 创建 Scope 关系:获取系统 Occurrence 和 Process Occurrence,调用 CreateScope 在系统与制造模型间建立 Scope。
  6. 创建 Assign 关系:对每个操作调用 AssignProcess 在操作与制造模型间建立 Assign。
  7. 建立先后关系:使用 Precedence Link API 创建 Op1→Op2、Op2→Op3 的先后约束。
  8. 查询验证:调用 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 到操作,并查询验证分配关系。

练习步骤

  1. 获取 Resource 根节点:使用 GetPPRRootsFromCurrentEditor 传入 RESOURCE 获取根节点。
  2. 创建制造单元:使用 DELIPPRResourceAuth 接口创建一个制造单元节点。
  3. 创建人员:在制造单元下创建一个人员节点。
  4. 创建 Scope 关系:获取制造单元 Occurrence 和系统 Occurrence,调用 CreateScope 建立范围链接。
  5. 创建 Assign 关系:获取人员 Occurrence 和操作 Occurrence,调用 AssignResource 建立分配链接。
  6. 同步结构树:调用 Synchronize 同步 Occurrence 树。
  7. 查询验证:调用 GetAssignedWhoResource 查询操作的 Who 资源。注意正确处理 E_FAIL 返回值。
  8. 移除分配(可选):调用 UnAssignResource 移除人员分配,再次查询确认返回 E_FAIL(无分配)。

注意事项

  1. Scope 关系只在制造单元节点上创建,不在人员/工具节点上。
  2. Assign 关系只在具体资源(人员、工具)上创建,不在制造单元上。
  3. 处理 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 图片。

练习步骤

  1. 创建文本指令:在操作节点下使用 CreateSubSystemOrOperation 创建类型为 DELWkiInstructionReference 的指令实例。
  2. 设置指令名称:分别设置 Instance 的 "Name" 和 Reference 的 "V_Name" 属性。
  3. 写入文本内容:将一段纯文本包装为 <p>...</p> 格式,通过 SetValueAsString 写入 V_WIInstruction_Text 属性。
  4. 读取文本内容:使用 GetValueAsString 读取 V_WIInstruction_Text,解析 HTML 标签提取纯文本,将 <br/> 替换为换行。
  5. 导出视图:使用 Selection 搜索 Review.Slide,sel,获取 Slide 缩略图,导出为 BMP 文件。
  6. 验证结果:检查导出的 BMP 文件是否正确生成,文件名是否包含操作名和 Slide 名。

验收标准

  1. 创建的文本指令在 DELMIA 结构树中可见。
  2. 读取的纯文本内容与写入的内容一致(换行符正确转换)。
  3. 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 基类类型

评论