Boolean difference speed for many holes


#1

In an attempt to generate a perforation pattern with a grid of round holes, I am generating a list of circles, generating individual brep cylinders from each circle that intersect my main body and then boolean differencing each cylinder from the main body. This process works, but is extremely slow as the number of holes increases. It doesn’t appear that the “Make Hole” feature from Rhino has been implemented in the SDK yet – though it also seems slow when the number of holes is increased (maybe its just using bool diff behind the scenes anyway).

Is there any other way that I can create holes in a solid that may be more computationally efficient than individually diffing each cylinder?

I’ve tried using rg.Brep.CreateBooleanDifference in two ways:

  1. looping through each cylinder as an individual bool diff and replacing the breps[‘front’] with the result after each iteration
    rg.Brep.CreateBooleanDifference(breps[‘front’],hole,sc.doc.ModelAbsoluteTolerance)[0]
  2. calling the booldiff once using two lists
    rg.Brep.CreateBooleanDifference([breps[‘front’]],holesBrepList,sc.doc.ModelAbsoluteTolerance)[0]

The first method takes about 25 seconds for 200 holes
The second method takes about 38 seconds for 200 holes


(Rajaa Issa) #2

I would have thought the second method would be faster. @chuck can probably give feedback here.


(Chuck Welsh) #3

BooleanDifference first finds the union of all objects in the second set, then subtracts each component of that result from the first set. In many cases this is the best way to go, but not in yours. In your case, you know that the cylinders do not intersect. The difference in time comes from the first step. That step could be done more efficiently in your case, but that would be at the expense of others. One way you could speed things up when you know that the second set has no intersections is to put all the cylinders into a single brep. This is possible using the opennurbs sdk. ON_Brep::Append(). There may be other ways to access the same functionality. Any ideas @dale ?


(Menno Deij - van Rijswijk) #4

Another method could be to calculate by intersection, or mathematically (depending on the shape of the main body) the intersection curves between the cylinders and the main body.

Then use BrepFace.Split to split with the intersection curves.

This method depends on the complexity of your main body - if you have many BrepFaces in the main body it may be difficult to figure out which of the split results to keep and which to remove.

Do you have a real-life example file for which you want to do this?

Yet another method (C++ SDK or Rhino_DotNet) is to create the trims yourself given the intersection curves. This can be quite complicated if one cylinder intersects with multiple BrepFaces though.


#5

Just wanted to follow up and say that I ended up implementing @chuck’s recommendation to Append the breps into a single object before calling the boolean difference. This did cut down on the processing time to about 14 seconds (down from 25). Thank you for the suggestion and the insight on how the methods are working under the hood!