OpenCascade:带边界线的圆柱面
OpenCascade: Cylindrical Face with Boundary Wire
我想用边界线(两条垂直线和两个 180° 弧)制作半个圆柱体的面。我知道有更简单的方法可以做到这一点,但我真正的问题要复杂得多,而且我拥有的边大多是样条曲线。所以,我试着做了一个非常简单的例子,希望有人能帮助我。
对于我的真实输入数据,我不知道边界边的顺序和方向。我只有 "cylindrical face" 和 "bucket of edges, that form a closed loop"。那么,如果我的方向不好,我该如何自动修复?
这是我的示例代码:
// make an ARC from 'start' to 'end', counter-clockwise around 'center'.
TopoDS_Edge mkArc(gp_Pnt start, gp_Pnt center, gp_Pnt end, double normalZ) {
gp_Circ geometricCircle = GC_MakeCircle(center
, gp_Dir(0, 0, normalZ)
, center.Distance(start)
).Value()->Circ();
return BRepBuilderAPI_MakeEdge(geometricCircle, start, end);
}
// Make half-cylinder face by using boundary edges
TopoDS_Face MakeClinderFaceTest() {
// ^Z
// _
// ,´ `.
// a c b
// | _ |
// |,´ `.|
// A C B -->X
// top nodes
gp_Pnt a = gp_Pnt(-1, 0, 0);
gp_Pnt b = gp_Pnt( 1, 0, 0);
gp_Pnt c = gp_Pnt( 0, 0, 0);
// bottom nodes
gp_Pnt A = gp_Pnt(-1, 0, -1);
gp_Pnt B = gp_Pnt( 1, 0, -1);
gp_Pnt C = gp_Pnt( 0, 0, -1);
// boundary wire
std::list<TopoDS_Edge> edges;
if (0) { // 1/0 to reverse the order and direction of edges
edges.push_back(mkArc(a, c, b, -1)); // top arc
edges.push_back(BRepBuilderAPI_MakeEdge(b, B)); // right line
edges.push_back(mkArc(B, C, A, 1)); // bottom arc
edges.push_back(BRepBuilderAPI_MakeEdge(A, a)); // left line
} else {
edges.push_back(mkArc(b, c, a, 1));
edges.push_back(BRepBuilderAPI_MakeEdge(a, A));
edges.push_back(mkArc(A, C, B, -1));
edges.push_back(BRepBuilderAPI_MakeEdge(B, b));
}
BRepBuilderAPI_MakeWire wire;
for (auto& e : edges) {
wire.Add(e);
}
auto cylinder = gp_Cylinder( gp_Ax2( C, gp_Dir(0, 0, 1) ), C.Distance(A) /* =R */ );
#if 0
// surface geometry: infinite length cylinder
BRepBuilderAPI_MakeFace cylface(cylinder, wire);
#else
// cylindrical face with limits in V direction.
TopoDS_Face cylinder_face = BRepBuilderAPI_MakeFace(cylinder, 0, 2 * M_PI, 0, 1.0).Face();
// Limit cylinder by wired edges
BRepBuilderAPI_MakeFace cylface(cylinder_face, wire);
#endif
return cylface;
}
直接建模总是更好 - 例如以定义有效拓扑的可靠方式构建顶点、边、线、面。
但考虑到问题:
So, if my orientation is bad, how can I automatically fix that?
形状修复服务由 Open CASCADE 技术中的 ShapeFix 包提供。它的主要目的是解决从外部 CAD 系统导入的形状的拓扑问题(应用不同的有效性标准或只是将无效的形状写入 STEP / IGES 文件)。
这些工具还可用于制作 'lazy' 构建算法或处理用户输入。请注意,该工具提供了很多 'fixes' - 例如解决特定问题的算法。启用所有这些都不是一个好主意,因为它会显着影响性能并且结果可能出乎意料。
在您的特定情况下,您有兴趣修复电线方向。这可以在 ShapeFix_Face 的帮助下实现(如果我正确理解你的问题):
// cylindrical face with limits in V direction.
TopoDS_Face cylinder_face = BRepBuilderAPI_MakeFace(cylinder, 0, 2 * M_PI, 0, 1.0).Face();
Handle(Geom_Surface) aSurf = BRep_Tool::Surface (cylinder_face);
// Limit cylinder by wired edges
//BRepBuilderAPI_MakeFace cylface(cylinder_face, wire);
BRepBuilderAPI_MakeFace cylface(aSurf, wire);
ShapeFix_Face aFaceFixer;
aFaceFixer.FixWireMode() = 1;
aFaceFixer.FixOrientationMode() = 1;
//aFaceFixer.FixSplitFaceMode() = 1;
Handle(ShapeFix_Wire) aWireFixer = aFaceFixer.FixWireTool();
aWireFixer->FixConnectedMode() = 1;
aWireFixer->ClosedWireMode() = Standard_True;
Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape();
aFaceFixer.SetContext (aContext);
aFaceFixer.Init (cylface);
aFaceFixer.Perform();
TopoDS_Shape aFixResult = aFaceFixer.Result();
if (!aFixResult.IsNull()) { return TopoDS::Face (aFixResult); }
我想用边界线(两条垂直线和两个 180° 弧)制作半个圆柱体的面。我知道有更简单的方法可以做到这一点,但我真正的问题要复杂得多,而且我拥有的边大多是样条曲线。所以,我试着做了一个非常简单的例子,希望有人能帮助我。
对于我的真实输入数据,我不知道边界边的顺序和方向。我只有 "cylindrical face" 和 "bucket of edges, that form a closed loop"。那么,如果我的方向不好,我该如何自动修复?
这是我的示例代码:
// make an ARC from 'start' to 'end', counter-clockwise around 'center'.
TopoDS_Edge mkArc(gp_Pnt start, gp_Pnt center, gp_Pnt end, double normalZ) {
gp_Circ geometricCircle = GC_MakeCircle(center
, gp_Dir(0, 0, normalZ)
, center.Distance(start)
).Value()->Circ();
return BRepBuilderAPI_MakeEdge(geometricCircle, start, end);
}
// Make half-cylinder face by using boundary edges
TopoDS_Face MakeClinderFaceTest() {
// ^Z
// _
// ,´ `.
// a c b
// | _ |
// |,´ `.|
// A C B -->X
// top nodes
gp_Pnt a = gp_Pnt(-1, 0, 0);
gp_Pnt b = gp_Pnt( 1, 0, 0);
gp_Pnt c = gp_Pnt( 0, 0, 0);
// bottom nodes
gp_Pnt A = gp_Pnt(-1, 0, -1);
gp_Pnt B = gp_Pnt( 1, 0, -1);
gp_Pnt C = gp_Pnt( 0, 0, -1);
// boundary wire
std::list<TopoDS_Edge> edges;
if (0) { // 1/0 to reverse the order and direction of edges
edges.push_back(mkArc(a, c, b, -1)); // top arc
edges.push_back(BRepBuilderAPI_MakeEdge(b, B)); // right line
edges.push_back(mkArc(B, C, A, 1)); // bottom arc
edges.push_back(BRepBuilderAPI_MakeEdge(A, a)); // left line
} else {
edges.push_back(mkArc(b, c, a, 1));
edges.push_back(BRepBuilderAPI_MakeEdge(a, A));
edges.push_back(mkArc(A, C, B, -1));
edges.push_back(BRepBuilderAPI_MakeEdge(B, b));
}
BRepBuilderAPI_MakeWire wire;
for (auto& e : edges) {
wire.Add(e);
}
auto cylinder = gp_Cylinder( gp_Ax2( C, gp_Dir(0, 0, 1) ), C.Distance(A) /* =R */ );
#if 0
// surface geometry: infinite length cylinder
BRepBuilderAPI_MakeFace cylface(cylinder, wire);
#else
// cylindrical face with limits in V direction.
TopoDS_Face cylinder_face = BRepBuilderAPI_MakeFace(cylinder, 0, 2 * M_PI, 0, 1.0).Face();
// Limit cylinder by wired edges
BRepBuilderAPI_MakeFace cylface(cylinder_face, wire);
#endif
return cylface;
}
直接建模总是更好 - 例如以定义有效拓扑的可靠方式构建顶点、边、线、面。
但考虑到问题:
So, if my orientation is bad, how can I automatically fix that?
形状修复服务由 Open CASCADE 技术中的 ShapeFix 包提供。它的主要目的是解决从外部 CAD 系统导入的形状的拓扑问题(应用不同的有效性标准或只是将无效的形状写入 STEP / IGES 文件)。
这些工具还可用于制作 'lazy' 构建算法或处理用户输入。请注意,该工具提供了很多 'fixes' - 例如解决特定问题的算法。启用所有这些都不是一个好主意,因为它会显着影响性能并且结果可能出乎意料。
在您的特定情况下,您有兴趣修复电线方向。这可以在 ShapeFix_Face 的帮助下实现(如果我正确理解你的问题):
// cylindrical face with limits in V direction.
TopoDS_Face cylinder_face = BRepBuilderAPI_MakeFace(cylinder, 0, 2 * M_PI, 0, 1.0).Face();
Handle(Geom_Surface) aSurf = BRep_Tool::Surface (cylinder_face);
// Limit cylinder by wired edges
//BRepBuilderAPI_MakeFace cylface(cylinder_face, wire);
BRepBuilderAPI_MakeFace cylface(aSurf, wire);
ShapeFix_Face aFaceFixer;
aFaceFixer.FixWireMode() = 1;
aFaceFixer.FixOrientationMode() = 1;
//aFaceFixer.FixSplitFaceMode() = 1;
Handle(ShapeFix_Wire) aWireFixer = aFaceFixer.FixWireTool();
aWireFixer->FixConnectedMode() = 1;
aWireFixer->ClosedWireMode() = Standard_True;
Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape();
aFaceFixer.SetContext (aContext);
aFaceFixer.Init (cylface);
aFaceFixer.Perform();
TopoDS_Shape aFixResult = aFaceFixer.Result();
if (!aFixResult.IsNull()) { return TopoDS::Face (aFixResult); }