You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

OpenCascade提取产品层级/树形结构问题

OpenCascade提取产品层级/树形结构问题

嘿,我看你已经能从STEP文件里捞出所有组件的实例名和产品名了,但卡在父子层级关系上对吧?其实OpenCascade里的装配层级是通过标签(TDF_Label)的父子结构来维护的,只要用对方法就能轻松遍历出树形结构~

核心思路

在XCAF文档中,每个装配组件都对应一个TDF_Label,父组件的标签下会嵌套子组件的标签。我们可以通过递归遍历标签的直接子组件来构建完整的层级结构,同时用XCAFDoc_ShapeTool提供的方法获取组件的名称信息。

完整实现代码

首先定义一个递归遍历的函数,用来处理层级输出:

#include <XCAFDoc_ShapeTool.hxx>
#include <TDF_Label.hxx>
#include <TDF_LabelSequence.hxx>
#include <TCollection_AsciiString.hxx>
#include <iostream>

// 递归遍历装配层级
void TraverseAssemblyHierarchy(const Handle(XCAFDoc_ShapeTool)& shapeTool, const TDF_Label& currentLabel, int depth = 0)
{
    // 用缩进展示层级关系
    for (int i = 0; i < depth; ++i) {
        std::cout << "  ";
    }

    // 获取组件的产品名和实例名
    TCollection_AsciiString productName;
    TCollection_AsciiString instanceName;
    bool hasProductName = shapeTool->GetProductName(currentLabel, productName);
    bool hasInstanceName = shapeTool->GetInstanceName(currentLabel, instanceName);

    // 输出组件信息
    if (hasProductName && hasInstanceName) {
        std::cout << "组件: " << productName.ToCString() << " (实例名: " << instanceName.ToCString() << ")" << std::endl;
    } else if (hasProductName) {
        std::cout << "组件: " << productName.ToCString() << std::endl;
    } else if (hasInstanceName) {
        std::cout << "实例: " << instanceName.ToCString() << std::endl;
    } else {
        std::cout << "未知组件" << std::endl;
    }

    // 获取当前组件的直接子组件
    TDF_LabelSequence childComponents;
    shapeTool->GetChildren(currentLabel, childComponents);

    // 递归处理每个子组件
    for (Standard_Integer i = 1; i <= childComponents.Length(); ++i) {
        const TDF_Label& childLabel = childComponents.Value(i);
        // 过滤掉非组件类型的标签(避免属性等无关标签)
        if (shapeTool->IsComponent(childLabel)) {
            TraverseAssemblyHierarchy(shapeTool, childLabel, depth + 1);
        }
    }
}

然后把这个函数集成到你的现有代码中:

Handle(XCAFDoc_ShapeTool) assembly = XCAFDoc_DocumentTool::ShapeTool(hDoc->Main());
TDF_LabelSequence freeShapes;
assembly->GetFreeShapes(freeShapes);

// 遍历所有根组件(通常STEP装配只有一个根节点)
for (Standard_Integer freeShapeIndex = 1; freeShapeIndex <= freeShapes.Length(); ++freeShapeIndex)
{
    TDF_Label freeShape = freeShapes.Value(freeShapeIndex);
    std::cout << "=== 根组件 ===" << std::endl;
    // 启动递归遍历
    TraverseAssemblyHierarchy(assembly, freeShape);
}

关键细节说明

  • GetChildren vs GetComponentsGetChildren只获取当前组件的直接子组件,适合构建树形层级;而你之前用的GetComponents(..., Standard_True)会递归获取所有后代组件,没法区分层级。
  • IsComponent判断:确保只处理真正的组件标签,避免遍历到一些存储属性或辅助信息的无关标签。
  • 层级缩进:通过depth参数控制输出缩进,让树形结构一目了然。
  • 额外扩展:如果需要获取组件对应的几何形状,可以用shapeTool->GetShape(currentLabel)获取TopoDS_Shape对象。

备注:内容来源于stack exchange,提问作者RocketSearcher

火山引擎 最新活动