Erratic issue with the General Fuse algorithm

Hello everyone, I am having some issues using BOPAlgo_Builder to perform a General Fuse operation. I have a CAD of a thin portion of a toroidal wall [think of a 45 degrees wedge cut off a torus-like cake] and I want to add pipes that enter the wall from its outer surface, run along the inner surface for a bit and then exit. Each pipe is created by extruding a square section along five paths: a straight line, a quarter circumference, a line for which I have an analytical expression, another quarter circumference and finally another straight line. The five paths together should make a C1-continuous line. I then fuse the five resulting solids to make a single pipe and all my pipes are saved as brep files.

On to the fuse, my code looks like this:

TopoDS_Shape fws; // This is the wall section
std::vector<TopoDS_Shape> pipes; // This is a list containing all the pipes as read by BRepTools::Read

BOPAlgo_Builder partitioner;
partitioner.AddArgument(fws); // Add the wall

for (int i = 0; i < nPipes; ++i) {
    partitioner.AddArgument(pipes[i]); // Add all the pipes
}

partitioner.Perform(); // Do the deed

Now, what I noticed is that the general fuse fails for some seemingly random pipes. Some pictures for context:

  1. 2pipes.png shows two of the pipes I have
  2. 2pipesAndWall.png shows the same two pipes and the wall they should be fused with. I am very confident that the pipes are properly placed.
  3. generalFuseMainSolid.png shows the main component that I extract from the compound resulting from the general fuse. You can see that the pipe on the right was correctly removed from the wall but the one on the left was not.
  4. closeUp.png shows a close up of the two central holes from the previous picture. You can see that the one on the left only has three sides, which seems to suggest that the general fuse could not correctly find an intersection between the two solids. I suspect that the whole issue lies here.

Now, as I said this happens only sporadically and erratically for some pipes that don't seem to have much in common. Out of 2400 of my latest run, 12 pipes were defective. [Some of them with a different defect but we'll get to that later on].

What's even more interesting is that I was preparing an example to upload that performs the same operations with a smaller portion of my wall, 9 degrees wide instead of 45, and with that example [same pipe] the algorithm worked just fine! Again: the only difference was that I changed the wall, which I generate from a bigger geometry doing a general fuse with a wedge [think of a proper slice of cake] but the surface should otherwise be the same. This seems to suggest that there are some relative tolerances at play that somehow make the algorithm work in one case but not in the other. I tried compiling OCCT in debug mode and catching floating point exceptions but none were thrown...

Has anyone seen this before or can anyone share some help on how to solve this?

Thanks in advance!

Massimiliano

Massimiliano Leoni's picture

I have some additional information to provide. If I take the defective pipe and I translate it by half a millimetre along x, then the boolean operation works as expected.

The surface of the wall was generated with a grid of points and GeomAPI_PointsToBSplineSurface. If I change the parameters of the GeomAPI_PointsToBSplineSurface::Init method, such as interpolation degree or continuity, this pipe will fuse ok but different pipes will fail to fuse cleanly.

Massimiliano Leoni's picture

I've been following the code execution in the debugger, comparing a case that works with one that doesn't, and it boils down to OpenCASCADE failing to detect the intersection between a specific Edge [arc of circumference] with my surface [BSpline surface]. I suspect things are going wrong inside Extrema_GenExtCS::Perform but finding out exactly what is proving challenging.

If anyone has a clue as to how to help, it would be very appreciated! I can provide an MWE with geometries if anyone is willing to look into it.

Massimiliano Leoni's picture

And to add insult to injury, my colleague fired up bloody ANSYS SpaceClaim and performed the same operation seamlessly D:

How can I sleep knowing that good Open Source software took such a hit? Unacceptable! Fellow FOSS developers, let's join forces and strike back!

Mikhail Sazonov's picture

Your pictures are totally unclear.
However, I can suggest that you use FuzzyValue as option of the Boolean operations. Imagine between your shape's parallel walls there is a gap that you cannot see by eyes, but you can imagine a tolerance of some value, e.g. 1e-5. Set FuzzyValue to that value, and it must help.

Massimiliano Leoni's picture

Hello Mikhail, thank you for replying! I am sorry that my pictures are not clear, let me try again. I tracked down the issue to the following minimal working example, I'm attaching more pictures in hope of achieving more clarity.

I have a solid which is a thin shell [wall.png] and two arcs that cross the surface. I know for a fact that the arcs intersect the solid and I verified it by making it a bit transparent. This setting is analogous to "Case 9: An Edge and a Solid intersecting at a point" from https://dev.opencascade.org/doc/overview/html/specification__boolean_ope... .

Now, when I perform a General Fuse operation with the code I showed above and these shapes, opencascade correctly detects that the arc on the left intersects the solid and the resulting shape contains two separate parts of the original arc [successfulOperation.png]. The object explorer shows the shape's hierarchy.
Conversely, with the arc on the right, opencascade fails to detect the intersection and the resulting shape is just a compound of the solid and the arc [failedOperation.png]. You can see from the object browser that the solid does not contain an edge, as it instead should.

Regarding your suggestion, I had already tried to use a fuzzy tolerance but that didn't change the result.

Please do not hesitate to let me know if the description and the pictures are still unclear!

Thanks for your help :)
Massimiliano

Dmitrii Pasukhin's picture

Hello, thank you for your research. Could you share the code to reproduce the problem(the minimum sample that you explain). I will create an issue to fix that problem.

Best regards, Dmitrii.

Massimiliano Leoni's picture

Hello Dmitrii! Thanks for your help :)
I attach the minimal working example, do let me know if anything is unclear or missing.

All the best,
Massimiliano

Attachments: 
Dmitrii Pasukhin's picture
Massimiliano Leoni's picture

Thanks! Just a couple of questions: if the issue is fixed could I access the feature branch before it makes it to master/main?

Can you guesstimate how long it might take?

And if I manage to patch it myself would I be able to open a pull request to submit my code?

All the best,
Massimiliano

Dmitrii Pasukhin's picture

Hello, yes. We always push into temporary branch and that branch available for everyone.

Unfortunately, that issue is not estimated yet and not planned for nearest releases.

Yes, you can create you own patch, but you need to sign CLI to be able to contribute, more details https://dev.opencascade.org/get_involved

Best regards, Dmitrii.

Massimiliano Leoni's picture

Ok, then I'll give it another spin next week. Conceptually it doesn't look like a difficult fix, maybe I'll be lucky.

Massimiliano Leoni's picture

Hello again Dmitrii! I spent the last three days diving deep into the source code. I know it's deep because code comments started to be in French rather than in English :D
Unfortunately I could not yet pinpoint where the problem is but I was wondering if there's anything I can do to help the issue being solved earlier; this issue is very important for me since the bug is blocking me in my work. I thought that if I met [digitally] with you or some other OCCT developer we might be able to get this fixed much more quickly. Is that a possibility at all?

Thanks and all the best,
Massimiliano

Dmitrii Pasukhin's picture

Hello, for now we can't allocate the person for an issue. The issue is not planned for nearest releases.

The way to resolve issue quick - custom development contract, but there is low limit for contract :(

More details: Technology Support - Open Cascade (occt3d.com)

Unfortunately, I'm out of context of that field.

Best regards, Dmitrii.

Massimiliano Leoni's picture

Hello, thanks for the quick reply! What does it mean that there is a low limit for contract? In principle we're open to this option so long as we don't get stalled in legal labyrinths...

Can you tell me more about this?

Massimiliano

Dmitrii Pasukhin's picture

I'm out of sales, I just know that we have some lower bound of unit that can be buy.

You can "contact to Us" and sales team can help you more.

Best regards, Dmitrii.