Open CASCADE学习|实现裁剪操作

1. 引言

Open CASCADE (简称OCC) 是一个功能强大的开源几何建模内核,广泛应用于CAD/CAM/CAE领域。裁剪操作作为几何建模中的基础功能,在模型编辑、布尔运算、几何分析等方面有着重要作用。本文将全面探讨Open CASCADE中的裁剪操作实现原理、应用场景及具体实现方法。

2. 裁剪操作基础

2.1 裁剪操作类型

Open CASCADE主要支持以下几种裁剪操作:

  • 布尔裁剪(BRepAlgoAPI_Cut)
  • 面域裁剪
  • 曲线裁剪
  • 高级裁剪(如带公差裁剪)

2.2 核心类介绍

实现裁剪操作主要涉及以下核心类:

  • BRepAlgoAPI_Cut:布尔裁剪操作
  • BRepAlgoAPI_Splitter:分割操作
  • BRepBuilderAPI_MakeEdge:边构建
  • Geom_TrimmedCurve:曲线裁剪

3. 实体裁剪实现

3.1 基本立方体裁剪

cpp 复制代码
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <TopoDS_Shape.hxx>
#include <BRepTools.hxx>
#include <iostream>

int main()
{
    // 创建第一个立方体 (10x10x10)
    TopoDS_Shape box1 = BRepPrimAPI_MakeBox(10., 10., 10.).Shape();
    
    // 创建第二个立方体 (5x5x15),与第一个立方体部分重叠
    TopoDS_Shape box2 = BRepPrimAPI_MakeBox(5., 5., 15.).Shape();
    
    // 执行裁剪操作:box1 剪去 box2
    BRepAlgoAPI_Cut cutter(box1, box2);
    
    if (!cutter.IsDone()) {
        std::cerr << "裁剪操作失败" << std::endl;
        return 1;
    }
    
    // 获取结果形状
    TopoDS_Shape result = cutter.Shape();
    
    // 保存结果
    BRepTools::Write(result, "box_cut_result.brep");
    
    std::cout << "立方体裁剪完成,结果已保存为 box_cut_result.brep" << std::endl;
    return 0;
}

3.2 复杂形状裁剪

cpp 复制代码
#include <BRepPrimAPI_MakeCylinder.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <gp_Ax2.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <TopoDS_Shape.hxx>
#include <BRepTools.hxx>
#include <iostream>

int main()
{
    // 创建圆柱体
    gp_Ax2 cylinderAxis(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1));
    TopoDS_Shape cylinder = BRepPrimAPI_MakeCylinder(cylinderAxis, 3., 10.).Shape();
    
    // 创建球体
    TopoDS_Shape sphere = BRepPrimAPI_MakeSphere(gp_Pnt(0, 0, 5), 2.).Shape();
    
    // 执行裁剪操作
    BRepAlgoAPI_Cut cutter(cylinder, sphere);
    
    if (!cutter.IsDone()) {
        std::cerr << "裁剪操作失败" << std::endl;
        return 1;
    }
    
    // 获取结果
    TopoDS_Shape result = cutter.Shape();
    BRepTools::Write(result, "cylinder_cut_sphere.brep");
    
    std::cout << "复杂形状裁剪完成,结果已保存" << std::endl;
    return 0;
}

4. 曲线与直线裁剪

4.1 直线重合部分裁剪

cpp 复制代码
#include <gp_Lin.hxx>
#include <TopoDS_Edge.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepTools.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>

void CutOverlappingLines()
{
    // 创建第一条直线 (沿X轴,从(0,0,0)到(10,0,0))
    gp_Lin line1(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0));
    TopoDS_Edge edge1 = BRepBuilderAPI_MakeEdge(line1, 0, 10).Edge(); // 参数范围0-10

    // 创建第二条直线 (与第一条部分重合,从(5,0,0)到(15,0,0))
    gp_Lin line2(gp_Pnt(5, 0, 0), gp_Dir(1, 0, 0));
    TopoDS_Edge edge2 = BRepBuilderAPI_MakeEdge(line2, 0, 10).Edge(); // 参数范围0-10

    // 将边转换为线(Wire)以便进行布尔操作
    BRepBuilderAPI_MakeWire wireMaker1(edge1);
    

    BRepBuilderAPI_MakeWire wireMaker2(edge2);
   

    // 执行裁剪操作:wire1 减去 wire2(重合部分)
    BRepAlgoAPI_Cut cutter(wireMaker1, wireMaker2);

    if (!cutter.IsDone()) {
        std::cerr << "裁剪操作失败" << std::endl;
        return;
    }

    // 获取结果(应该是从(0,0,0)到(5,0,0)的线段)
    TopoDS_Shape result = cutter.Shape();
    BRepTools::Write(result, "cut_overlapping_lines.brep");

    std::cout << "重合部分裁剪完成,结果已保存" << std::endl;
}
int main()
{
    CutOverlappingLines();
    return 0;
}

4.2 直线相交裁剪

cpp 复制代码
#include <gp_Lin.hxx>
#include <TopoDS_Edge.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepAlgoAPI_Splitter.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopExp_Explorer.hxx>
#include <BRep_Tool.hxx>
#include <Geom_Curve.hxx>
#include <Precision.hxx>
#include <BRepTools.hxx>
#include <TopoDS.hxx>
#include <iostream>

int main()
{
    // 创建第一条直线 (沿X轴)
    gp_Lin line1(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0));
    TopoDS_Edge edge1 = BRepBuilderAPI_MakeEdge(line1, 0, 10).Edge();

    // 创建第二条直线 (与第一条在(5,0,0)相交)
    gp_Lin line2(gp_Pnt(5, -5, 0), gp_Dir(0, 1, 0));
    TopoDS_Edge edge2 = BRepBuilderAPI_MakeEdge(line2, 0, 10).Edge();

    // 计算交点
    BRepExtrema_DistShapeShape distSS(edge1, edge2);
    if (distSS.NbSolution() == 0 || distSS.Value() > Precision::Confusion()) {
        std::cerr << "直线不相交" << std::endl;
        return 1;
    }

    // 获取交点
    gp_Pnt intersection = distSS.PointOnShape1(1);
    TopoDS_Vertex vertex = BRepBuilderAPI_MakeVertex(intersection).Vertex();

    // 使用新版Splitter API
    BRepAlgoAPI_Splitter splitter;

    // 添加要分割的形状
    TopTools_ListOfShape shapesToSplit;
    shapesToSplit.Append(edge1);
    splitter.SetArguments(shapesToSplit);

    // 添加分割工具
    TopTools_ListOfShape splitTools;
    splitTools.Append(vertex);
    splitter.SetTools(splitTools);

    splitter.Build();

    if (!splitter.IsDone()) {
        std::cerr << "分割操作失败" << std::endl;
        return 1;
    }

    // 获取分割结果
    const TopoDS_Shape& splitResult = splitter.Shape();

    // 输出分割后的各段信息
    TopExp_Explorer exp(splitResult, TopAbs_EDGE);
    int segmentCount = 0;
    for (; exp.More(); exp.Next(), segmentCount++) {
        TopoDS_Edge segment = TopoDS::Edge(exp.Current());

        double first, last;
        Handle(Geom_Curve) curve = BRep_Tool::Curve(segment, first, last);
        gp_Pnt start = curve->Value(first);
        gp_Pnt end = curve->Value(last);

        std::cout << "线段 " << segmentCount + 1 << ": 从 ("
            << start.X() << "," << start.Y() << "," << start.Z()
            << ") 到 ("
            << end.X() << "," << end.Y() << "," << end.Z() << ")" << std::endl;
    }

    // 保存结果
    BRepTools::Write(splitResult, "split_lines_result.brep");

    std::cout << "直线相交裁剪完成,共得到 " << segmentCount << " 条线段" << std::endl;
    return 0;
}

5. 高级裁剪技术

5.1 带公差裁剪

cpp 复制代码
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepTools.hxx>
#include <BOPAlgo_Options.hxx>
#include <iostream>
#include <TopTools_ListOfShape.hxx>

int main()
{
    // 创建两个几乎接触但不完全相交的立方体
    TopoDS_Shape box1 = BRepPrimAPI_MakeBox(10., 10., 10.).Shape();
    TopoDS_Shape box2 = BRepPrimAPI_MakeBox(9.99, 9.99, 15.).Shape();

    // 创建形状列表
    TopTools_ListOfShape args;
    args.Append(box1);
    TopTools_ListOfShape tools;
    tools.Append(box2);

    // 创建裁剪操作并设置公差
    BRepAlgoAPI_Cut cutter;
    cutter.SetArguments(args);
    cutter.SetTools(tools);
    cutter.SetFuzzyValue(0.02); // 设置2%的公差

    cutter.Build();

    if (!cutter.IsDone()) {
        std::cerr << "裁剪操作失败" << std::endl;
        return 1;
    }

    // 获取结果
    TopoDS_Shape result = cutter.Shape();
    BRepTools::Write(result, "fuzzy_cut_result.brep");

    std::cout << "带公差裁剪完成" << std::endl;
    return 0;
}

5.2 多对象裁剪

cpp 复制代码
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <TopTools_ListOfShape.hxx>
#include <BRepTools.hxx>
#include <iostream>

int main()
{
    // 创建基础形状
    TopoDS_Shape base = BRepPrimAPI_MakeBox(20., 20., 20.).Shape();

    // 创建多个裁剪工具
    TopTools_ListOfShape tools;
    tools.Append(BRepPrimAPI_MakeSphere(gp_Pnt(5, 5, 5), 3.).Shape());
    tools.Append(BRepPrimAPI_MakeSphere(gp_Pnt(15, 15, 15), 4.).Shape());
    tools.Append(BRepPrimAPI_MakeBox(10., 10., 2.).Shape());

    // 执行多对象裁剪
    BRepAlgoAPI_Cut cutter;
    TopTools_ListOfShape baseList;
    baseList.Append(base); // 将基础形状添加到列表中
    cutter.SetArguments(baseList); // 使用列表作为参数
    cutter.SetTools(tools);
    cutter.Build();

    if (!cutter.IsDone()) {
        std::cerr << "多对象裁剪失败" << std::endl;
        return 1;
    }

    // 获取结果
    TopoDS_Shape result = cutter.Shape();
    BRepTools::Write(result, "multi_cut_result.brep");

    std::cout << "多对象裁剪完成" << std::endl;
    return 0;
}

6. 性能优化与错误处理

6.1 裁剪操作验证

cpp 复制代码
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <BRepTools.hxx>
#include <iostream>

int main()
{
    // 创建两个立方体
    TopoDS_Shape box1 = BRepPrimAPI_MakeBox(10., 10., 10.).Shape();
    TopoDS_Shape box2 = BRepPrimAPI_MakeBox(5., 5., 5.).Shape();
    
    // 执行裁剪
    BRepAlgoAPI_Cut cutter(box1, box2);
    
    if (!cutter.IsDone()) {
        std::cerr << "裁剪操作失败" << std::endl;
        if (cutter.HasErrors()) {
            cutter.DumpErrors(std::cerr);
        }
        return 1;
    }
    
    // 验证结果
    TopoDS_Shape result = cutter.Shape();
    BRepCheck_Analyzer analyzer(result);
    
    if (!analyzer.IsValid()) {
        std::cerr << "裁剪结果无效" << std::endl;
        return 1;
    }
    
    // 保存有效结果
    BRepTools::Write(result, "validated_cut.brep");
    
    std::cout << "已验证的裁剪操作完成" << std::endl;
    return 0;
}

6.2 并行裁剪优化

cpp 复制代码
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepTools.hxx>
#include <OSD_Parallel.hxx>
#include <TopTools_ListOfShape.hxx>
#include <iostream>

int main()
{
    // 启用并行处理
    OSD_Parallel::SetUseOcctThreads(Standard_True);

    // 创建复杂形状
    TopoDS_Shape complexShape = BRepPrimAPI_MakeBox(100., 100., 100.).Shape();
    TopoDS_Shape cuttingTool = BRepPrimAPI_MakeBox(90., 90., 90.).Shape();

    // 创建形状列表
    TopTools_ListOfShape argumentShapes;
    argumentShapes.Append(complexShape);
    TopTools_ListOfShape toolShapes;
    toolShapes.Append(cuttingTool);

    // 配置并行裁剪
    BRepAlgoAPI_Cut cutter;
    cutter.SetArguments(argumentShapes);
    cutter.SetTools(toolShapes);
    cutter.SetRunParallel(Standard_True); // 启用并行
    cutter.Build();

    if (!cutter.IsDone()) {
        std::cerr << "并行裁剪失败" << std::endl;
        return 1;
    }

    // 获取结果
    TopoDS_Shape result = cutter.Shape();
    BRepTools::Write(result, "parallel_cut.brep");

    std::cout << "并行裁剪完成" << std::endl;
    return 0;
}

7. 结论

Open CASCADE提供了强大而灵活的裁剪操作功能,从简单的布尔运算到复杂的曲线处理,能够满足各种CAD/CAM应用场景的需求。通过本文的示例代码,开发者可以快速掌握:

  1. 基本实体裁剪的实现方法
  2. 曲线和直线的精确裁剪技术
  3. 高级裁剪功能如带公差处理和多对象裁剪
  4. 性能优化和错误处理的最佳实践

实际应用中,开发者需要根据具体需求选择合适的裁剪策略,并注意以下几点:

  • 始终验证输入几何体的有效性
  • 合理设置操作公差
  • 对复杂操作进行性能优化
  • 正确处理操作失败的情况

通过合理运用Open CASCADE的裁剪功能,可以高效实现各种复杂的几何建模需求。

相关推荐
m0_578267862 分钟前
从零开始的python学习(六)P86+P87+P88
python·学习
小虎卫远程打卡app5 分钟前
视频编解码学习8之视频历史
学习·音视频·视频编解码
菜一头包8 分钟前
Lua学习笔记
笔记·学习·lua
dot to one8 分钟前
C++ 渗透 数据结构中的二叉搜索树
数据结构·c++·算法·visual studio
bbqz00713 分钟前
Qml Console
c++·qt·qml
夏季疯23 分钟前
学习笔记:黑马程序员JavaWeb开发教程(2025.3.31)
java·笔记·学习
yangyang_z24 分钟前
【C++设计模式之Observer观察者模式】
c++·观察者模式·设计模式
threelab36 分钟前
01.three官方示例+编辑器+AI快速学习webgl_animation_keyframes
人工智能·学习·编辑器
ATaylorSu39 分钟前
C++ -- string
c++·学习
PyAIGCMaster1 小时前
taro的学习记录
学习·taro