OCCT BRepAlgoAPI_Fuse fuser(box1, box2);

我们来详细介绍一下 BRepAlgoAPI_Fuse 这个在 Open CASCADE Technology (OCCT) 中非常核心和常用的类。

BRepAlgoAPI_Fuse 是OCCT中用于执行**布尔运算之并集(或称熔合、Fuse)**的高级API。它的主要作用是将两个或多个拓扑形体(TopoDS_Shape)合并成一个单一的形体,同时正确地处理它们相交或接触部分的拓扑结构。

调用 BRepAlgoAPI_Fuse fuser(box1, box2); 这行代码,实际上是创建了一个 BRepAlgoAPI_Fuse 类的实例,并初始化了要进行熔合操作的两个主要对象:box1 和 box2。


BRepAlgoAPI_Fuse 详解

1. 它是做什么的? (Purpose)

想象一下将两块橡皮泥捏在一起。它们接触的部分会融合,形成一个整体,而不再是两个独立的部分。BRepAlgoAPI_Fuse 在三维模型上做的就是类似的事情。

  • 计算并集: 它计算两个形体在空间上占据的总体积。

  • 重建拓扑: 这是最关键的一步。它会:

    • 移除两个形体内部重叠的部分。

    • 在它们相交的地方创建新的边和面。

    • 将原本属于不同形体但现在相邻的面合并。

    • 最终生成一个单一、有效、流形(manifold)的拓扑结构。

与简单的将两个形体放入一个 TopoDS_Compound(组合体)不同,Fuse 操作创建了真正的拓扑连接。

2. 构造函数:BRepAlgoAPI_Fuse(const TopoDS_Shape& S1, const TopoDS_Shape& S2)

这是 BRepAlgoAPI_Fuse最常用的构造函数之一。

  • const TopoDS_Shape& S1: 第一个操作对象(工具体或参数体)。在这个例子中是 box1。

  • const TopoDS_Shape& S2: 第二个操作对象。在这个例子中是 box2。

发生了什么?
当这行代码被执行时:

  1. 一个名为 fuser 的 BRepAlgoAPI_Fuse 对象被创建。

  2. box1 和 box2 的引用被传递给 fuser 对象。

  3. fuser 对象内部会进行一些初始化的准备工作,比如设置操作对象和参数,但此时真正的布尔运算还没有开始。它只是做好了计算的准备。

3. 典型使用流程 (Workflow)

使用 BRepAlgoAPI_Fuse 通常遵循一个固定的三步流程:

步骤 1:创建和初始化 (Instantiation)

    // 假设 box1 和 box2 是已经创建好的 TopoDS_Shape (例如 TopoDS_Solid)
BRepAlgoAPI_Fuse fuser(box1, box2);
  

这一步就如上所述,仅仅是准备阶段。

步骤 2:执行运算 (Execution)

    fuser.Build();
  

Build() 方法是真正触发大规模计算的地方。它会调用底层的布尔运算算法来计算 box1 和 box2 的并集。这个过程可能非常耗时,因为它涉及到复杂的几何相交计算和拓扑重建。

步骤 3:检查结果和获取形体 (Check & Get Result)

    if (fuser.IsDone())
{
    // 如果 IsDone() 返回 true,说明运算成功完成
    TopoDS_Shape resultShape = fuser.Shape();
    // resultShape 就是 box1 和 box2 熔合后的新形体
}
else
{
    // 运算失败,可能是因为输入形体有问题(如非流形、自相交等)
    // 或者算法无法处理某些退化的几何情况。
    // 可以通过 fuser.ErrorStatus() 等方法获取更多错误信息。
}
  
  • IsDone(): 在调用 Build() 之后,必须先调用这个方法来检查运算是否成功。这是一个非常重要的好习惯。

  • Shape(): 如果 IsDone() 返回 true,就可以调用此方法来获取运算结果,即那个新的、合并后的 TopoDS_Shape。

4. 结果的类型

fuser.Shape() 返回的结果类型取决于输入形体的相对位置:

  • TopoDS_Solid: 如果两个实体(Solid)接触或重叠,并且它们的并集形成了一个单一、封闭的空间,结果通常是一个 TopoDS_Solid。

  • TopoDS_CompSolid: 如果两个实体仅仅通过共享面连接,但没有形成一个单一的封闭外壳(例如,两个相邻的房间),结果可能是一个 TopoDS_CompSolid(复合体)。

  • TopoDS_Compound: 如果两个实体完全分离(没有接触或重叠),Fuse 操作不会改变它们,结果将是一个包含原始 box1 和 box2 的 TopoDS_Compound(组合体)。如果输入的是多个不相连的物体,结果也通常是 Compound。

5. 内部机制(简化版)

BRepAlgoAPI_Fuse 是一个高级封装,它内部调用了更底层的、复杂的布尔运算内核,通常是 BOPAlgo_Builder。其大致过程如下:

  1. 参数准备: 接收输入的形体。

  2. 相交计算: 计算两个形体所有面与面之间的交线。

  3. 拓扑分裂: 使用计算出的交线来分割原始形体上的面和边,创建新的拓扑元素(新顶点、新边、新面)。

  4. 分类: 将所有新的拓扑元素标记为“在形体A内部”、“在形体B内部”、“在公共部分”等。

  5. 结果构建: 根据布尔运算的类型(对于 Fuse 来说是并集),选择所有位于形体A、形体B或两者公共部分的拓扑元素,并将它们重新组合成一个新的、有效的拓扑形体。

总而言之,BRepAlgoAPI_Fuse fuser(box1, box2); 是发起一个三维模型熔合操作的起点,它为你封装了布尔运算中所有复杂且易错的细节,让你能以一种清晰、简洁的方式来合并几何体。

下面给出一个代码示例:

#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <TopoDS_Solid.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_CompSolid.hxx>
#include <BRep_Builder.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <TopoDS.hxx>
#include <iostream>


#include <BRepTools.hxx>
#define FULL_PATH(fname) "D:/GeneratedModels/" #fname ".brep"
#define WRITE_SHAPE(shape) BRepTools::Write(shape, "D:/GeneratedModels/" #shape ".brep")
std::string file_path(std::string f) {
    std::string file = "D:/GeneratedModels/" + f + ".brep";
    return file;
}

std::string command(std::string path) {
    std::string comm = "D:\\Software\\CAD_Assistant\\CADAssistant.exe " + path;
    return comm;
}

void run_command(std::string f) {
    std::string f1 = file_path(f);
    std::string command1 = command(f1);
    system(command1.c_str());

}
int main()
{
    // 1. 创建两个相邻的立方体
    // 第一个立方体在原点,尺寸为 10x10x10
    TopoDS_Solid box1 = BRepPrimAPI_MakeBox(10., 10., 10.).Solid();
    WRITE_SHAPE(box1);
    run_command("box1");

    // 第二个立方体紧邻第一个,共享一个面
    // 平移第一个立方体来创建第二个
    gp_Trsf translation;
    translation.SetTranslation(gp_Vec(10., 0., 0.));
    BRepBuilderAPI_Transform transformer(box1, translation);
    TopoDS_Solid box2 = TopoDS::Solid(transformer.Shape());
    WRITE_SHAPE(box2);
    run_command("box2");

    // 2. 使用布尔熔合操作
    // 这将合并两个立方体,并处理共享的面
    BRepAlgoAPI_Fuse fuser(box1, box2);
    fuser.Build();

    if (fuser.IsDone())
    {
        TopoDS_Shape fusedShape = fuser.Shape();

        // 检查布尔操作的结果类型
        if (fusedShape.ShapeType() == TopAbs_COMPSOLID)
        {
            std::cout << "布尔操作直接生成了一个 CompSolid." << std::endl;
            TopoDS_CompSolid compSolid = TopoDS::CompSolid(fusedShape);
            WRITE_SHAPE(compSolid);
            run_command("compSolid");
        }
        else if (fusedShape.ShapeType() == TopAbs_COMPOUND)
        {
            std::cout << "布尔操作生成了一个 Compound,现在从中构建 CompSolid." << std::endl;

            // 3. 从熔合后的 Compound 中构建 CompSolid
            TopoDS_CompSolid compSolid;
            BRep_Builder builder;
            builder.MakeCompSolid(compSolid);

            // 遍历 Compound 中的所有实体,并添加到 CompSolid 中
            TopExp_Explorer explorer(fusedShape, TopAbs_SOLID);
            while (explorer.More())
            {
                const TopoDS_Solid& solid = TopoDS::Solid(explorer.Current());
                builder.Add(compSolid, solid);
                explorer.Next();
            }

            std::cout << "CompSolid 构建完成." << std::endl;
            WRITE_SHAPE(compSolid);
            run_command("compSolid");
        }
        else if (fusedShape.ShapeType() == TopAbs_SOLID)
        {
            std::cout << "布尔操作生成了一个单一的 Solid (因为完全重叠或连接紧密)." << std::endl;
        }
        else
        {
            std::cout << "布尔操作生成了未处理的类型." << std::endl;
        }
    }
    else
    {
        std::cerr << "布尔熔合操作失败。" << std::endl;
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值