OpenCascade: цилиндрическая грань с граничным проводом - PullRequest
1 голос
/ 18 февраля 2020

Я хочу сделать грань половины цилиндра, используя граничные ребра (две вертикальные линии и две дуги 180 °). Я знаю, что есть более простые способы сделать это, но моя настоящая проблема гораздо сложнее, и у меня есть ребра, в основном, сплайны. Итак, я попытался сделать очень простой пример в надежде, что кто-то может мне помочь.

С моими реальными входными данными я не знаю порядок и ориентацию краевых ребер. Все, что у меня есть, это «цилиндрическое лицо» и «ведро с краями, которые образуют замкнутую l oop». Итак, если моя ориентация плохая, как я могу автоматически это исправить?

Вот мой пример кода:

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

1 Ответ

4 голосов
/ 20 февраля 2020

Всегда лучше выполнять прямое моделирование - например, построение вершин, ребер, проводов, граней надежным способом, определяющим правильную топологию.

Но, учитывая вопрос:

Итак, если моя ориентация плохая, как я могу автоматически исправить это?

Услуги исцеления формы предоставляются пакетом ShapeFix в технологии Open CASCADE. Его основная цель - решить проблемы топологии для фигур, импортированных из внешних систем САПР (применяя различные критерии достоверности или просто записав недопустимую форму в файл STEP / IGES).

Эти инструменты могут также использоваться для создания «ленивых» Алгоритм построения или для обработки пользовательского ввода. Остерегайтесь, эти инструменты предоставляют множество «исправлений» - например, алгоритмы, решающие конкретную проблему. Включение всех из них не является хорошей идеей, поскольку это сильно повлияет на производительность, и результат может быть неожиданным.

В вашем конкретном случае вы заинтересованы в исправлении ориентации проводов. Это может быть достигнуто с помощью 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); }
...