Open cascade中如何使用BRepAlgoAPI_Splitter分割一个Face
理论介绍
在OpenCASCADE几何建模内核中,BRepAlgoAPI_Splitter
是一个强大的工具,用于将一个形状(Shape)用另一个形状(Tool)进行分割。这种操作在CAD建模中非常常见,比如用平面切割实体、用曲线分割曲面等。
BRepAlgoAPI_Splitter
的工作原理是基于布尔运算的切割算法。它能够处理各种拓扑形状之间的分割操作,包括:
- 用边分割面
- 用面分割体
- 用线分割边
分割操作的结果取决于输入形状和工具的几何关系。当工具完全穿过被分割形状时,通常会产生多个子形状;当工具只部分接触时,则可能只修改原有形状而不分割。
核心代码分析
1. 创建被分割的面
TopoDS_Face makeFace(){gp_Pnt P1(-1.0/2.0, -1.0/2.0, 0);gp_Pnt P2(-1.0/2.0, 1.0/2.0, 0);gp_Pnt P3(1.0/2.0, 1.0/2.0, 0);gp_Pnt P4(极1.0/2.0, -1.0/2.0, 0);BRepBuilderAPI_MakePolygon mkPoly(P1,P2,P3,P4);mkPoly.Add(mkPoly.FirstVertex());TopoDS_Wire wire = mkPoly.Wire();BRepBuilderAPI_MakeFace face(wire);return face.Face();
}
这个函数创建一个正方形面,位于XY平面,边长1个单位,中心在原点。我们使用BRepBuilderAPI_MakePolygon
创建多边形,然后将其闭合为Wire,最后用Wire创建Face。
2. 创建分割工具
TopoDS_Face makeTool(){static constexpr double bigNumber {100};gp_Pnt P1(0, -bigNumber, -bigNumber);gp_Pnt P极2(0, -bigNumber, bigNumber);gp_Pnt P3(0, bigNumber, bigNumber);gp_Pnt P4(0, bigNumber, -bigNumber);BRepBuilderAPI_MakePoly极gon mkPoly(P1,P2,P3,P4);mkPoly.Add(mkPoly.FirstVertex());TopoDS_Wire wire = mkPoly.Wire();BRepBuilderAPI_MakeFace tool(wire);return tool.Face();}
这里创建一个无限大的YZ平面(实际用大数100近似),作为分割工具。这个平面将垂直于X轴,穿过原点。
3. 执行分割操作
TopoDS_Face face = makeFace();TopoDS_Face tool = makeTool();TopTools_ListOfShape originalArguments;originalArguments.Append (face);TopTools_ListOfShape firstSplitLine;firstSplitLine.Append(tool);auto squareSplitOnce = BRepAlgoAPI_Splitter();squareSplitOnce.SetArguments(originalArguments);squareSplitOnce.SetTools(firstSplitLine);squareSplitOnce.Build();
关键步骤:
- 创建被分割的面和分割工具
- 将面添加到参数列表(Arguments)
- 将工具添加到工具列表(Tools)
- 创建
BRepAlgoAPI_Splitter
对象并设置参数和工具 - 调用
Build()
方法执行分割
4. 分析结果
Handle(BRepTools_History) hist = squareSplitOnce.History();hist->Dump(std::cout);auto generated = squareSplitOnce.Generated(face);std::cout << "generated: " << generated.Size() << '\n';auto modified = squareSplitOnce.Modified(face);std::cout << "modified: " << modified.Size() << '\n';
History()
方法返回操作的历史记录,可以查询哪些形状被修改、生成或移除。Generated()
和Modified()
方法分别返回由输入形状生成的新形状和被修改的形状。
完整代码
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepAlgoAPI_Splitter.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <iostream>TopoDS_Face makeFace()
{gp_Pnt P1(-1.0/2.0, -1.0/2.0, 0);gp_Pnt P2(-1.0/2.0, 1.0/2.0, 0);gp_Pnt P3(1.0/2.0, 1.0/2.0, 0);gp_Pnt P4(1.0/2.0, -1.0/2.0, 0);BRepBuilderAPI_MakePolygon mkPoly(P1,P2,P3,P4);mkPoly.Add(mkPoly.FirstVertex());TopoDS_Wire wire = mkPoly.Wire();BRepBuilderAPI_MakeFace face(wire);return face.Face();
}TopoDS_Face makeTool()
{static constexpr double bigNumber {100};gp_Pnt P1(0, -bigNumber, -bigNumber);gp_Pnt P2(0, -bigNumber, bigNumber);gp_Pnt P3(0, bigNumber, bigNumber);gp_Pnt P4(0, bigNumber, -bigNumber);BRepBuilderAPI_MakePolygon mkPoly(P1,P2,P3,P4);mkPoly.Add(mkPoly.FirstVertex());TopoDS_Wire wire = mkPoly.Wire();BRepBuilderAPI_MakeFace tool(wire);return tool.Face();
}void CountSubShape(const TopoDS_Face& face)
{TopTools_IndexedMapOfShape faces;TopTools_IndexedMapOfShape wires;TopTools_IndexedMapOfShape edges;TopTools_IndexedMapOfShape vertexes;for (TopExp_Explorer it(face, TopAbs_FACE); it.More(); it.Next()) {faces.Add(it.Current());}for (TopExp_Explorer it(face, TopAbs_WIRE); it.More(); it.Next()) {wires.Add(it.Current());}for (TopExp_Explorer it(face, TopAbs_EDGE); it.More(); it.Next()) {edges.Add(it.Current());}for (TopExp_Explorer it(face, TopAbs_VERTEX); it.More(); it.Next()) {vertexes.Add(it.Current());}std::cout << " faces=" << faces.Size()<< " wires=" << wires.Size()<< " edges=" << edges.Size()<< " vertexes=" << vertexes.Size()<< '\n';
}void PrintHistory(const TopTools_IndexedMapOfShape& map, Handle(BRepTools_History) hist)
{for (Standard_Integer i = 1; i <= map.Extent(); i++) {const TopoDS_Shape& shape = map(i);std::cout << " modified: " << hist->Modified(shape).Size() << '\n';std::cout << " generated: " << hist->Generated(shape).Size() << '\n';std::cout << " removed: " << hist->IsRemoved(shape) << '\n';}
}void PrintHistory(const TopoDS_Face& face, Handle(BRepTools_History) hist)
{TopTools_IndexedMapOfShape faces;TopTools_IndexedMapOfShape wires;TopTools_IndexedMapOfShape edges;TopTools_IndexedMapOfShape vertexes;for (TopExp_Explorer it(face, TopAbs_FACE); it.More(); it.Next()) {faces.Add(it.Current());}for (TopExp_Explorer it(face, TopAbs_WIRE); it.More(); it.Next()) {wires.Add(it.Current());}for (TopExp_Explorer it(face, TopAbs_EDGE); it.More(); it.Next()) {edges.Add(it.Current());}for (TopExp_Explorer it(face, TopAbs_VERTEX); it.More(); it.Next()) {vertexes.Add(it.Current());}std::cout << " faces:\n";PrintHistory(faces, hist);std::cout << " wires:\n";PrintHistory(wires, hist);std::cout << " edges:\n";PrintHistory(edges, hist);std::cout << " vertexes:\n";PrintHistory(vertexes, hist);
}int main()
{TopoDS_Face face = makeFace();//CountSubShape(face);TopoDS_Face tool = makeTool();//CountSubShape(tool);TopTools_ListOfShape originalArguments;originalArguments.Append (face);TopTools_ListOfShape firstSplitLine;firstSplitLine.Append(tool);auto squareSplitOnce = BRepAlgoAPI_Splitter();squareSplitOnce.SetArguments(originalArguments);squareSplitOnce.SetTools(firstSplitLine);squareSplitOnce.Build();Handle(BRepTools_History) hist = squareSplitOnce.History();hist->Dump(std::cout);auto generated = squareSplitOnce.Generated(face);std::cout << "generated: " << generated.Size() << '\n';auto modified = squareSplitOnce.Modified(face);std::cout << "modified: " << modified.Size() << '\n';
#if 0std::cout << "\nface:\n";PrintHistory(face, hist);std::cout << "\ntool:\n";PrintHistory(tool, hist);
#endif
}
结论
通过BRepAlgoAPI_Splitter
,我们可以方便地在OpenCASCADE中实现形状的分割操作。本文展示了如何用一个大平面分割一个正方形面,实际应用中可以根据需要调整被分割形状和分割工具的几何参数。操作的历史记录功能对于理解分割过程和结果分析非常有帮助。
在实际项目中,分割操作常用于创建复杂几何形状、进行几何分析或准备有限元网格划分等场景。掌握这些基础操作是使用OpenCASCADE进行高级几何建模的重要一步。