CATIA 干涉检查 Clash Analysis API:DMU Space Analysis 完整实战

琛兴科技 · CATIA 二次开发系列 · 适用 V5R19~R32 / DMU Space Analysis

一、原理:Clash 的三种类型与计算原理

CATIA 的干涉检查是 DMU Space Analysis 工作台提供的核心能力。它把整个产品树的所有零件做空间布尔运算,找出三种关系:

类型枚举含义
ClashCATClashTypeClash实际穿透(体积重叠)
ContactCATClashTypeContact恰好接触(公差 ε 内)
ClearanceCATClashTypeClearance距离小于阈值但不接触

计算策略上 CATIA 用 BBox 粗筛 + 精确几何 fine 检测两阶段算法:先按零件 OBB(定向包围盒)做 O(N²) 但极快的初筛,过滤掉绝大多数明显不可能的对;剩下的少量候选对再做 BRep 级精确求交。这就是为什么大装配(10000+ 零件)也能在分钟内出结果。

结果通过 CATIClashResult 接口暴露,每个干涉对包含两个零件 reference、干涉类型、最小距离、干涉点(如果是 Clash 则是穿透量最大的点对),以及可视化用的 conflict body(共享体积的几何)。

二、流程:API 调用顺序的 6 步

  1. 打开 Product:CATDocumentServices::OpenDocument 拿到根 Product。
  2. 创建 Clash Specification:用 CATIClashSpecFactory::CreateClashSpec 新建一个分析任务,指定类型(Clash/Contact/Clearance)和阈值。
  3. 设置作用域:通过 CATIClashSpec::SetScope 决定全部 vs 选定零件 vs 两组零件互测。
  4. 触发计算CATIClashSpec::Compute。这是个同步调用,大装配可能阻塞数分钟,多线程模式要单开线程。
  5. 读取结果GetResults 返回 CATListPtrCATIClashResult,逐对遍历。
  6. 分类输出:按零件名/Body/Cell 聚合,导出 Excel/CSV/HTML 报告。

三、避坑:Clash 二开六大坑

坑 1:未激活 Visualization Mode 的零件不参与检测
设计模式(Design Mode)开着的子产品默认参与,但纯可视化(Cgr)模式必须主动 ActivateNode。批量整车时务必先 CATIClashSpec::SetActivationMode(CATClashActivateAll)
坑 2:Clearance 阈值单位是 mm
某些版本的内部存储默认单位易混淆,0.5 mm 的安全间距写成 0.5 cm 会让结果暴增 10 倍。SetClearanceValue(0.5) 实际就是 0.5mm。
坑 3:螺栓自检(自身 vs 自身镜像实例)默认参与
如果 Product 树中有同一个零件多次 Place(如 100 个相同螺栓),CATIA 默认把它们两两都测,结果数量爆炸。用 SetSelfInstanceClash(0) 关闭。
坑 4:装配约束的"几何接触"被误报为 Clash
约束 Coincidence 让两个面贴合,从空间几何看就是 Contact。批量报告里要先按"几何接触量<ε"过滤掉这部分。
坑 5:Compute 失败常因 CGR 缓存损坏
报错"Cgr file unreadable"或"GeometryStream corrupted"时,先删除 ~/CATTemp 下的 cgr 缓存重算。
坑 6:结果对象生命周期绑定 Spec
Spec 一 Release,所有 Result 指针失效。要导出报告必须先把数据 Copy 到自己的结构体里再释放。
实战建议:整车级(10万+零件)干涉检查推荐分组分批做:先粗粒度 BBox 检测找候选对,再细粒度。用 CATIClashSpec::SetComputationLevel(CATClashComputationLevelBBox) 做粗筛,精检在结果上做第二轮。

四、完整代码:批量干涉检查 + Excel 导出

// BatchClash.cpp
// 输入:Product 文件路径、间距阈值
// 输出:干涉对列表(导出到 CSV)

#include "CATIClashSpecFactory.h"
#include "CATIClashSpec.h"
#include "CATIClashResult.h"
#include "CATIProduct.h"
#include "CATDocumentServices.h"
#include <fstream>

HRESULT BatchClashCheck(
    const CATUnicodeString& productPath,
    double clearanceMM,
    const CATUnicodeString& csvOut)
{
    HRESULT rc = S_OK;
    CATDocument* pDoc = NULL;
    rc = CATDocumentServices::OpenDocument(productPath, pDoc);
    if (FAILED(rc) || !pDoc) return rc;

    // 1. 拿 Root Product
    CATIProduct_var spRoot;
    rc = GetRootProduct(pDoc, spRoot);
    if (FAILED(rc)) goto Done;

    // 2. 创建 Clash Spec
    CATIClashSpecFactory_var spFac = spRoot;
    if (spFac == NULL_var) { rc = E_FAIL; goto Done; }
    CATIClashSpec_var spSpec;
    rc = spFac->CreateClashSpec(
            CATClashTypeClearance,   // 同时报 Clash + Contact + Clearance
            spSpec);
    if (FAILED(rc) || spSpec == NULL_var) goto Done;

    // 3. 配置参数
    spSpec->SetClearanceValue(clearanceMM);
    spSpec->SetSelfInstanceClash(0);
    spSpec->SetActivationMode(CATClashActivateAll);
    spSpec->SetScope(CATClashScopeAll, NULL, NULL);

    // 4. 触发计算
    rc = spSpec->Compute();
    if (FAILED(rc)) goto Done;

    // 5. 拿结果
    CATListPtrCATIClashResult results;
    rc = spSpec->GetResults(results);
    if (FAILED(rc)) goto Done;

    // 6. 写 CSV
    {
        std::ofstream out(csvOut.CastToCharPtr());
        out << "PartA,PartB,Type,MinDist_mm,Penetration_mm\n";
        for (int i = 1; i <= results.Size(); ++i) {
            CATIClashResult* pR = results[i];
            CATUnicodeString nameA, nameB;
            pR->GetPartNames(nameA, nameB);
            int type = 0; double minDist = 0, pen = 0;
            pR->GetType(type);
            pR->GetMinDistance(minDist);
            pR->GetMaxPenetration(pen);
            const char* typeStr =
                (type==CATClashTypeClash) ? "CLASH" :
                (type==CATClashTypeContact) ? "CONTACT" : "CLEARANCE";
            out << nameA.CastToCharPtr() << ","
                << nameB.CastToCharPtr() << ","
                << typeStr << ","
                << minDist << "," << pen << "\n";
        }
        out.close();
    }
    cout << "Found " << results.Size() << " conflict pairs.\n";

Done:
    if (pDoc) CATDocumentServices::Remove(*pDoc);
    return rc;
}

© 上海琛兴科技发展有限公司 · 转载请注明出处 · CATIA 是 Dassault Systèmes 注册商标