Unexpectedly, some points of the TopoDS_Face are not on its Geom_Surface.

jianbaoxia

CAD master
Today I encountered a very strange situation that confuses me whether it is a flaw in OCCT or an issue with my usage.

Next, I will do my best to describe this situation clearly and provide a demo.

It starts like this: I have a TopoDS_Face `face_origin`, and I intend to generate a wire using the function `BRepBuilderAPI_MakeFace (const Handle< Geom_Surface >& S, const TopoDS_Wire& W, const Standard_Boolean Inside=Standard_True)` to create a new surface. However, unexpectedly, some points in `face_origin` are not on its Geom_Surface, which leads to the failure of constructing the TopoDS_Face using the wire and Geom_Surface."

There is the face_origin, it is a part of cylinder
1691051760136.png
I used it to construct a section of a cylindrical surface, and by calling BRepClass3d_SolidClassifier, I found that some points on the original surface are not on the cylindrical surface. This makes me wonder if it's an issue with OCCT or if there's a problem with my usage. As show:
1691060318478.png
Even when I use the wire of `face_origin`, I am unable to obtain the original TopoDS_Face from the Geom_Surface.

There is my demo:
Code:
TopoDS_Face DowncastShape2Face(const TopoDS_Shape& faceShape)
{
    //
    TopTools_MapOfShape FACE_map;
    for (TopExp_Explorer exp(faceShape, TopAbs_FACE); exp.More(); exp.Next())
        FACE_map.Add(exp.Current());
    if (FACE_map.Size() != 1) std::cout << "DowncastShape2Face 的输入 shape 中只能有一个 TopoDS_Face" << std::endl;

   //
    TopoDS_Face aFace;
    for (TopExp_Explorer exp(faceShape, TopAbs_FACE); exp.More(); exp.Next())
        aFace = TopoDS::Face(exp.Current());

    return aFace;
}

TopoDS_Wire DowncastShape2Wire(const TopoDS_Shape& wireShape)
{
    //
    TopTools_MapOfShape Wire_map;
    for (TopExp_Explorer exp(wireShape, TopAbs_WIRE); exp.More(); exp.Next())
        Wire_map.Add(exp.Current());
    if (Wire_map.Size() != 1) std::cout << "DowncastShape2Face 的输入 shape 中只能有一个 TopoDS_Face" << std::endl;

    //
    TopoDS_Wire aWire;
    for (TopExp_Explorer exp(wireShape, TopAbs_WIRE); exp.More(); exp.Next())
        aWire = TopoDS::Wire(exp.Current());

    return aWire;
}

TopoDS_Vertex DowncastShape2Vertex(const TopoDS_Shape& faceShape)
{
    //
    TopTools_MapOfShape FACE_map;
    for (TopExp_Explorer exp(faceShape, TopAbs_VERTEX); exp.More(); exp.Next())
        FACE_map.Add(exp.Current());
    if (FACE_map.Size() != 1) std::cout << "DowncastShape2Vertex 的输入 shape 中只能有一个 TopoDS_Vertex" << std::endl;

    //
    TopoDS_Vertex aFace;
    for (TopExp_Explorer exp(faceShape, TopAbs_VERTEX); exp.More(); exp.Next())
        aFace = TopoDS::Vertex(exp.Current());

    return aFace;
}

bool IsPointOnFace(const gp_Pnt& point, const TopoDS_Face& face) {

    BRepClass3d_SolidClassifier classifier(face);
    classifier.Perform(point, Precision::Confusion());

    TopAbs_State state = classifier.State();

    return state == TopAbs_ON;
}

int main()
{
    //! 1、read .brep
    TopoDS_Shape shape;
    BRep_Builder bb;
    BRepTools::Read(shape, "../aFace.brep", bb);

    //! 2、get TopoDS_Face\Geom_Surface\TopoDS_Wire
    TopoDS_Face face_origin = DowncastShape2Face(shape);
    Handle(Geom_Surface) sur = BRep_Tool::Surface(face_origin);

    TopoDS_Wire wire = DowncastShape2Wire(face_origin);
    BRepTools::Write(wire, "../test/aWire.brep");

    //! 3、create face from Geom_Surface
    TopoDS_Face faceExtent = BRepBuilderAPI_MakeFace(sur, 0, 2 * M_PI, -1, 2, Precision::Confusion());

    /* debug */
    TopoDS_Compound com1;
    bb.MakeCompound(com1);
    bb.Add(com1, wire);
    bb.Add(com1, faceExtent);
    BRepTools::Write(com1, "../test/aDebug.brep");
    // ------------

    //! 4、Check if the points on the original surface(face) are on the reconstructed surface(faceExtent)
    TopTools_MapOfShape VERTEX_map;
    for (TopExp_Explorer exp(face_origin, TopAbs_VERTEX); exp.More(); exp.Next())
    {
        VERTEX_map.Add(exp.Current());
    }

    TopoDS_Compound com;
    //BRep_Builder bb;
    bb.MakeCompound(com);
    bb.Add(com, faceExtent);
    bb.Add(com, wire);

    TopTools_MapIteratorOfMapOfShape mapIt(VERTEX_map);
    for (; mapIt.More(); mapIt.Next())
    {
        const TopoDS_Shape& verShape = mapIt.Key();
        gp_Pnt aPnt = BRep_Tool::Pnt(DowncastShape2Vertex(verShape));
        if (!IsPointOnFace(aPnt, faceExtent))
            bb.Add(com, verShape);
    }
    BRepTools::Write(com, "../test/aCom.brep");

    //! 5、create face from Geom_Surface and wire
    //TopoDS_Face faceRebuild = BRepBuilderAPI_MakeFace(sur, wire);
    TopoDS_Face faceRebuild = BRepBuilderAPI_MakeFace(faceExtent, wire);
    BRepTools::Write(faceRebuild, "../test/aFace_rubuild.brep");
    return 0;
}
 

Attachments

  • aFace.brep
    16.5 KB · Views: 2
Last edited:

Quaoar

Administrator
Staff member
I wouldn't assume that it is legal to use BRepClass3d_SolidClassifier for checking if a point lies on a face. You would rather have to project a point onto a face and check the distance.
 
Top