Faces from non planar wire and underlying faces


I have a non planar closed wire (made from an arbitrary number of 3D NURBS) and a shape made of faces (that I can sew and use to make a shell), the wire lies on this shape. I want to fill this wire (resulting in a shape made of one or more faces).

I tried to use only the wire by:
* Using BRepBuilderAPI_MakeFace but the wire is not planar.
* Building a surface with GeomPlate_MakeApprox and using BRepBuilderAPI_MakeFace with this surface without success.
* Filling the wire using GeomPlate_BuildPlateSurface and BRepFill_CurveConstraint without success.
* Filling the wire using BRepOffsetAPI_MakeFilling with some success depending on the wire.

I am now trying to use the faces. I am trying two approaches: get the shapes within the wire or cut the shell with the wire. I did not yet succeed, I am not sure I am using the right functions for this.
Could you guide me with the method / functions to use to solve my problem?

Thanks in advance!

PS: I forgot to mention, I am using version 6.9.1

jerome caucat's picture

I have successfully "drawn" the wire on the shell with BOPAlgo_Builder but now I do not know how to get the faces "inside" the wire.

jerome caucat's picture

I have tried the following method:
* extrude the wire into a prism with BRepPrimAPI_MakePrism
* make it solid with BRepPrimAPI_MakeHalfSpace
* make a shell with the faces of my underlying shape
* use BRepAlgo_Cut to cut the prism from the shell

But the cut does not seem to cut all around the prism.

See attached image:
1. the wire
2. the shape and the wire together
3. the result of the cut

jerome caucat's picture

I am able to cut the prism from my previous comment in a plane. Any idea why it does not work correctly in the shell?

jerome caucat's picture

I also try with BRepAlgoAPI_Cut/Common but results vary with the shape of the wire and with the length and orientation of the prism made from the wire. I do not understand what conditions need to be fulfilled for those algorithms to work.

Thomas Anderson's picture

I don't think extruding the wire and  boolean  operation is the way to go. After the BOPAlgo_Builder operation I would try:

Feed the 2 image shells into bounding box algo and keep the smaller shell.


using ShapeAnalysis_FreeBounds on the 2 image shells, 1 shell(the inner) should have 1 closed wire and the other(the outer) should have 2 closed wires. This assumes that the trimming wire doesn't intersect the original shell's outer wire.


in my gui application, I store the user pick location on the original shell. Then post BOPAlgo_Builder operation, I classify the original pick point on the 2 image shells and keep the shell containing the point.

jerome caucat's picture

Hi Thomas Anderson, thank you for you reply.

How can I get the two image shells you are talking about?

Here is what I have:

// wire: my wire made of a single NURBS3D edge
// shell: my shell made of 11 faces sewn together with BRepOffsetAPI_Sewing and built using BRep_Builder

BOPAlgo_Builder generalFuseBuilder;
auto fusedShape = generalFuseBuilder.Shape();
// generalFuseBuilder.Images().Size() = 28
// generalFuseBuilder.Splits().Size() = 9
// fusedShape contains 1 compound, 1 shell, 31 faces and 32 wires

auto newShell = (TopExp_Explorer{fusedShape, TopAbs_ShapeEnum::TopAbs_SHELL}).Current();
ShapeAnalysis_FreeBounds safb(newShell);
// safb.GetClosedWires() contains 2 wires
Thomas Anderson's picture

Yes, sorry. I forgot that BOPAlgo_Builder doesn't split apart wires and shells in the result images. This is starting to come back to me. You will have to write a face walking algo that doesn't cross the trimming edges. I am confused that your 1 shell result has 2 closed boundaries. Doing a similar operation here, I get 1 shell result with 1 closed boundary. Maybe you have some bad geometry?

jerome caucat's picture

Actually yes, the sewing operation apparently failed to sew two faces and an inner wire seems to have been created (it can be seen in the screenshots, there is a green line in the middle of the shell).

How can I get the trimming edges generated by BOPAlgo_Builder? I don't understand what is in .images() and .splits().

Thomas Anderson's picture

You have to be careful with sew. It is very liberal in what is acceptable output. Maybe you need to increase the tolerance to get expected results. BOPAlgo_Builder::splits has been removed in occt 7.3 so you probably shouldn't code much around that. TopTools_DataMapOfShapeListOfShape maps a single shape to a list of shapes. so, 'images' maps a single input shape to a list of output shapes and 'origins' maps a single output shape to a list of input shapes. Here is a code clip that dumps out images in a custom program:

    BOPAlgo_Builder bopBuilder;
    for (const auto &s : shapes)

    if (bopBuilder.HasErrors())
      std::ostringstream error;
      error << "error with bopBuilder. error code: "
      << std::endl;
      throw std::runtime_error(error.str());
    const TopTools_DataMapOfShapeListOfShape &images = bopBuilder.Images();
    TopTools_DataMapOfShapeListOfShape::Iterator imageIt(images);
    for (int index = 0; imageIt.More(); imageIt.Next(), index++)
      const TopoDS_Shape &key = imageIt.Key();
      std::ostringstream keyBase;
      keyBase << "Output_Images_key_" << formatNumber(index);
      std::ostringstream keyName;
      keyName << keyBase.str() << "_source_shapetype:" << occt::getShapeTypeString(key);
      project->addOCCShape(key, keyName.str());
      int count = 0;
      for (const auto &sil : imageIt.Value()) //shape in list
        assert(key.ShapeType() == sil.ShapeType());
        std::ostringstream mappedName;
        mappedName << keyBase.str() << "_result_shape_" << formatNumber(count);
        project->addOCCShape(sil, mappedName.str());

Why don't you post the shapes instead of me guessing what you have from a picture. I am on occt 7.4 so our results might differ.

jerome caucat's picture

Thanks a lot, I managed to find the section wire and test the faces attached to it.