ShapeFix_Face not working

R G W

Active CAD practitioner
Hi bros, i'm RGW.
Recently I ran into another problem when rebuilding surfaces. The basic discussion of the rebuilding surface problem can be found in this question. http://analysissitus.org/forum/inde...nvert-geom_bsplinesurface-to-topods_face.249/

The problem I have now is that when I rebuild a surface, ShapeFix_Face doesn't work, or it doesn't achieve the desired effect.
When I checked the status of ShapeFix_Face, it reported ShapeExtend_DONE2, that is, the direction of some wires was fixed, and the results are as follows.
Has anyone encountered the same error and can give me some suggestions?

wrong result:
1690858302582.png


correct result:
1690858382459.png
 

R G W

Active CAD practitioner
Here is my demo.
C++:
#include <fstream>
#include <vector>

//OpenCascade include
#include <TopoDS_Shape.hxx>
#include <BRep_Builder.hxx>
#include <BRepTools.hxx>
#include <ShapeAnalysis.hxx>
#include <TopoDS.hxx>
#include <TopExp.hxx>
#include <BRepBuilderAPI_NurbsConvert.hxx>
#include <GeomConvert.hxx>
#include <Geom_BSplineSurface.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <ShapeFix_Face.hxx>

#include "viewer.h"

using namespace std;

int main()
{
    Viewer vout(50, 50, 500, 500);
    TopoDS_Shape myshape;
    BRep_Builder b;
    std::ifstream is;
    is.open("1");
    BRepTools::Read(myshape, is, b);
    is.close();

    TopTools_IndexedMapOfShape wires_map;
    TopoDS_Face faceo = TopoDS::Face(myshape);
    TopoDS_Wire outer_wire = ShapeAnalysis::OuterWire(faceo);
    TopExp::MapShapes(faceo, TopAbs_WIRE, wires_map);
    BRepBuilderAPI_NurbsConvert nurbs_convert;
    nurbs_convert = BRepBuilderAPI_NurbsConvert(faceo);
    nurbs_convert.Perform(faceo);
    TopoDS_Shape face_shape = nurbs_convert.Shape();
    Handle(Geom_Surface) h_geomface = BRep_Tool::Surface(TopoDS::Face(face_shape));
    Handle(Geom_BSplineSurface)h_bsurface = GeomConvert::SurfaceToBSplineSurface(h_geomface);
   
    std::vector<TopoDS_Wire> inner_wires;
    for (int j = 1; j <= wires_map.Extent(); j++)
    {
        if (!wires_map(j).IsSame(outer_wire))
        {
            inner_wires.push_back(TopoDS::Wire(wires_map(j)));
        }
    }

    std::vector<std::vector<Standard_Real>> parameter;
    std::vector<std::vector<Standard_Real>> parameter2;
    std::vector<Handle(Geom2d_Curve)> p_curve1;
    std::vector<Handle(Geom2d_Curve)> p_curve2;
    TopExp_Explorer edge_exp;
    Standard_Boolean flag;
    for (edge_exp.Init(outer_wire, TopAbs_EDGE); edge_exp.More(); edge_exp.Next()) {
        TopoDS_Edge edge = TopoDS::Edge(edge_exp.Current().Composed(outer_wire.Orientation()));
        Standard_Real first;
        Standard_Real last;
        Handle(Geom2d_Curve) my_handle = BRep_Tool::CurveOnSurface(edge, faceo, first, last, &flag);
        parameter.push_back(std::vector<Standard_Real>{first, last});
        p_curve1.push_back(my_handle);
    }

    for (auto inwire : inner_wires) {
        TopExp_Explorer edge_exp2;
        Standard_Boolean flag2;
        for (edge_exp2.Init(inwire, TopAbs_EDGE); edge_exp2.More(); edge_exp2.Next()) {
            TopoDS_Edge edge = TopoDS::Edge(edge_exp2.Current().Composed(inwire.Orientation()));
            Standard_Real first;
            Standard_Real last;
            p_curve2.push_back(BRep_Tool::CurveOnSurface(edge, faceo, first, last, &flag2));
            parameter2.push_back(std::vector<Standard_Real>{first, last});
        }
    }

    BRepBuilderAPI_MakeWire mkWire;
    int i = 0;
    for (auto a : p_curve1) {
        TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(a, h_bsurface, parameter[i][0], parameter[i][1]);
        i++;
        //vout << anEdge;
        mkWire.Add(anEdge);
    }

    TopoDS_Wire new_wire = mkWire.Wire();
    BRepBuilderAPI_MakeFace faceMaker(h_bsurface, new_wire, false);
    new_wire.Reverse();
    if (p_curve2.size() != 0) {
        BRepBuilderAPI_MakeWire mkWire2;
        for (int j = 0; j < p_curve2.size(); j++) {
            TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(p_curve2[j], h_bsurface, parameter2[j][0], parameter2[j][1]);
            mkWire2.Add(anEdge);
        }
        TopoDS_Wire new_wire2 = mkWire2.Wire();
        faceMaker.Add(new_wire2);
    }
    ShapeFix_Face fix(faceMaker.Face());
    fix.SetPrecision(1e-7);
    fix.Perform();
    if (fix.Status(ShapeExtend_OK))
        cout << "ShapeExtend_OK ";
    else if (fix.Status(ShapeExtend_DONE1))
        cout << "ShapeExtend_DONE1";
    else if (fix.Status(ShapeExtend_DONE2))
        cout << "ShapeExtend_DONE2";
    else if (fix.Status(ShapeExtend_DONE3))
        cout << "ShapeExtend_DONE3";
    else if (fix.Status(ShapeExtend_DONE4))
        cout << "ShapeExtend_DONE4";
    else if (fix.Status(ShapeExtend_DONE5))
        cout << "ShapeExtend_DONE5";
    else if (fix.Status(ShapeExtend_DONE6))
        cout << "ShapeExtend_DONE6";
    else if (fix.Status(ShapeExtend_DONE7))
        cout << "ShapeExtend_DONE7";
    else if (fix.Status(ShapeExtend_DONE8))
        cout << "ShapeExtend_DONE8";
    else if (fix.Status(ShapeExtend_DONE))
        cout << "ShapeExtend_DONE ";
    else if (fix.Status(ShapeExtend_FAIL1))
        cout << "ShapeExtend_FAIL1 ";
    else if (fix.Status(ShapeExtend_FAIL2))
        cout << "ShapeExtend_FAIL2 ";
    else if (fix.Status(ShapeExtend_FAIL3))
        cout << "ShapeExtend_FAIL3 ";
    else if (fix.Status(ShapeExtend_FAIL4))
        cout << "ShapeExtend_FAIL4 ";
    else if (fix.Status(ShapeExtend_FAIL5))
        cout << "ShapeExtend_FAIL5 ";
    else if (fix.Status(ShapeExtend_FAIL6))
        cout << "ShapeExtend_FAIL6 ";
    else if (fix.Status(ShapeExtend_FAIL7))
        cout << "ShapeExtend_FAIL7 ";
    else if (fix.Status(ShapeExtend_FAIL8))
        cout << "ShapeExtend_FAIL8 ";
    else if (fix.Status(ShapeExtend_FAIL))
        cout << "ShapeExtend_FAIL ";


    vout << fix.Face();

    vout.StartMessageLoop();
   
}
 

Attachments

  • demo.zip
    11.9 KB · Views: 1

Quaoar

Administrator
Staff member
This is clearly the orientation problem of the resulting wire: it becomes a gap in a topologically untrimmed (sort of) surface:

1691001239787.png

ShapeFix does not solve this problem, as sometimes you might want to model such faces intentionally (like to untrim them forcibly). It should be noted that `face_shape` as returned by the NURBS converter is still Okay, so corruption happens later on. What is the idea behind this code after conversion? Why do you have to recompose the contours?
 
Top