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); }