Create restricted Surface from TopoDS_Shell and TopoDS_Wire (plate extraction)

Lingkan

CAD practitioner
Hey guys,

I'm trying to create a restricted Surface from a TopoDS_Shell, which internally is made up of a collection of Geom_BSplineSurfaces (on the geometry level).
Now this surface gets referenced multiple times and cut by a TopoDS_Wire to create new surfaces...

I have code that implements the mentioned use-case for planar surfaces, but the wrong shape is constructed for curved surfaces. I'm using the BRepBuilderAPI_MakeFace API, which also states that it will only work for non-planar surfaces when the surface contains p-curves for every edge inside TopoDS_Wire:
BRepBuilderAPI_MakeFace: Make a face from a Surface and a wire. If the surface S is not plane, it must contain pcurves for all edges in W, otherwise the wrong shape will be created.

I could need some help, as I have no idea how to approach this problem.

Here is a code prototype of how I handle this for planar surfaces:
C++:
TopoDS_Wire wire = ...;

std::vector<TopoDS_Face> faces =
      OCCUtils::ShapeComponents::AllFacesWithin(shape);

BRepBuilderAPI_Sewing shellMaker;
for (TopoDS_Face const &face : faces) {
    GeomAdaptor_Surface surfaceAdapter =
        OCCUtils::Surface::FromFace(TopoDS::Face(face));
    // TODO: Currently cutting curved surfaces with a wire is not supported
    // BRepBuilderAPI_MakeFace: Make a face from a Surface and a wire. If the
    // surface S is not plane, it must contain pcurves for all edges in W,
    // otherwise the wrong shape will be created.
    auto faceBuilder =
        BRepBuilderAPI_MakeFace(surfaceAdapter.Surface(), wire, Standard_True);
    faceBuilder.Build();
    if (!faceBuilder.IsDone()) {
        // ...
        return {};
    }

    ShapeFix_Face fix(faceBuilder.Face());
    fix.Perform();
    if (fix.Status(ShapeExtend_FAIL)) {
        // ...
        return {};
    }
    shellMaker.Add(fix.Face());
}

shellMaker.Perform();
TopoDS_Shape sewedShape = shellMaker.SewedShape();

int numShells = 0;
auto shell = TopoDS_Shell();
TopExp_Explorer shellExplorer(sewedShape, TopAbs_SHELL);
for (; shellExplorer.More(); shellExplorer.Next()) {
    shell = TopoDS::Shell(shellExplorer.Current());
    numShells++;
}

if (numShells != 1) {
    // ...
}

return shell;

The actual code lives here.

And images for context:
 

Attachments

  • Screenshot 2022-11-25 172502.png
    Screenshot 2022-11-25 172502.png
    62.4 KB · Views: 8
  • Screenshot 2022-11-25 172432.png
    Screenshot 2022-11-25 172432.png
    113.2 KB · Views: 8

Quaoar

Administrator
Staff member
We solved a somewhat similar problem back in the day. Here are some notes on it: http://quaoar.su/blog/page/on-geometric-imprinting-and-debugging-hints

To put it simply, the procedure was as follows:
  1. Prepare the input contour to make it composed of splines instead of polylines. We had polylines mainly because it was defined like that in the target system (ship hull modeling system, where plates were captured for subsequent unfolding).
  2. Imprint the prepared contour onto the shell. Here we implemented this Contour Capture algorithm mentioned in the link above. You can try using "General Fuse" operator of OpenCascade like here: https://gitlab.com/ssv/AnalysisSitus/-/blob/master/src/asiAlgo/auxiliary/asiAlgo_Utils.cpp#L3427
  3. Once the contour is imprinted, it's necessary to filter out all faces lying outside the contour. This can be done by properly iterating the imprinted edges using, e.g., left-turn rule.
From your pictures and code, I'm not sure I understand how exactly are you imprinting (read: projecting and making a part of your shape) your contour onto the input hull?
 

Lingkan

CAD practitioner
From your pictures and code, I'm not sure I understand how exactly are you imprinting (read: projecting and making a part of your shape) your contour onto the input hull?
Currently, there is no such implementation on how to imprint my contour. As it's right now, I'm just relying on the fact that the contour lies on the surface, and BRepBuilderAPI_MakeFace knows how to handle it. In the case of the Ship-Hull Reference surface and given outer contour, it doesn't seem like it is the case. That's why, for now, it's failing.

I'll have a look at the provided resources and provide feedback. Thanks for the input!
 

Quaoar

Administrator
Staff member
I'll have a look at the provided resources and provide feedback. Thanks for the input!
If you attach a piece of a ship hull and a contour wire, we can easily check if Booleans ("general fuse") work on your data.
 

Lingkan

CAD practitioner
3. Once the contour is imprinted, it's necessary to filter out all faces lying outside the contour. This can be done by properly iterating the imprinted edges using, e.g., left-turn rule.
Could you further elaborate on this part? What would a prototype of this method look like?
 

Quaoar

Administrator
Staff member
That's the result of imprinting:

1669704903820.png

But I slightly preprocessed your contour, as it was a single spline. With split-by-continuity you can turn it into a wire with C1 edges. And then I also used 0.1 as a fuzzy tolerance for Booleans. Otherwise, the shape turned out to be corrupted.

Could you further elaborate on this part? What would a prototype of this method look like?
Well, actually, I might have misled you here. What you need after imprinting is to find all faces inside a contour. For that, one stupidly simple approach might be:

1. Find the center point of the contour and the face closest to this center point. This would be your starting face.
2. Iterate over the neighbor faces until you reach the imprinted contour bounds (Boolean operation would return you the images of those edges, so you can check if your next face contains these edges or not to decide whether to stop propagation).

All faces propagated that way would give you the trimmed plate.

Out of curiosity, are you going to unfold the extracted plate after this?
 
Top