Why does Brep.JoinBreps not create a solid (closed polysurface) for these geometries, when Rhino's Join command does?


When I join the geometries of the objects in the attached file together using Brep.JoinBreps, I can see in the debugger that resulting Brep has its IsSolid=false. When I subsequently run the SelClosedPolysrf command, the resulting joined object isn’t selected.

However when I select these same objects in Rhino and run the Join command, it results in a closed polysurface going by the fact that SelClosedPolysrf selects the resulting object.

I’ve inspected all the surfaces and they each seem to have their normals facing outward. And the fact that the Join command is able to join them together shows that I don’t have a piece missing (a “hole”). But I am obviously missing something here.

Could anyone help me by pointing out what I’m missing in this case? Why does Rhino’s Join command does create a solid, but Rhinocommon’s Brep.JoinBreps doesn’t?


TestJoinBreps.3dm (622.2 KB)

The Brep.JoinBreps method has a tolerance value. Are you using the same tolerance as is defined in the document? If so, you may want to do this:

double tol = doc.ModelAbsoluteTolerance;
BoundingBox boundingBox = breps.GetBoundingBox(true); // this method does not exist, but you need to get the bounding box of all parts you want to join.
double threshold = 0.001*boundingBox; 
Brep joined = null;
  Brep[] result = Brep.JoinBreps(breps, tol);
  joined = result?.FirstOrDefault() ?? null;
  tol *= 2.0;
} while(joined != null && !joined.IsSolid && tol < threshold);

That is, continue trying to join while making the tolerance less strict up to a certain threshold and waiting until the result is a solid.

Hi @menno yes I use doc.ModelAbsoluteTolerance when I call JoinBreps in my Plug-in.

Normally Rhino states when it’s had to increase the tolerance but it doesn’t do that for the Join command in this example, so I’d think that I shouldn’t need to increase the tolerance when I call Brep.JoinBreps.

However I can try your loop to see if it works.



Hi @menno as a test I tried the loop below within the plug-in but the result in terms of the IsSolid value is the same - false. I chose a range of tolerances from 0.001 to 1 mm - so quite extreme:

        Brep latest;
        var tolerance = 0.001;
            var joinedBreps = Brep.JoinBreps(breps, tolerance);
            latest = joinedBreps?.FirstOrDefault() ?? null;
            tolerance = 2 * tolerance;
        } while (latest != null && !latest.IsSolid && tolerance < 2);

With this not producing a solid result I’m thinking the tolerance isn’t the issue - are there any more ideas out there as to what this could be?



Greetings Nicolas,

You have several edges occupying the same space.
Replace the blue surfaces with an extrusion, and see if it works.


Hi @denbutler

Replacing those particular surfaces with a single extrusion did work - Brep.JoinBreps produces a brep whose IsSolid = true. Thanks!

I thought edges wouldn’t be an issue in this case because the brep that JoinBreps created for me was manifold - but clearly they can still pose an issue.

Is there anything I can program to detect when such situations happen?



Greetings Nicolas,

The problem in this case is that the thickness of that specific feature at those 2 intersections is 0.0000 - null thickness.

Is there a minimum thickness you can specify, so that it must be above the absolute tolerance? This is beyond my experience, but might be a reasonable approach.

Or, this might have some good info?