Brep.JoinBrep creates invalid breps


I’m attempting to join two breps together using Brep.JoinBreps and while the join succeeds the breps created are not valid and cannot be added to the document. When checking IsValidWithLog it says the following:

ON_Brep.m_T[1].m_bRev3d = false, but closed curve directions are opposite

            Rhino.Input.RhinoGet.GetMultipleObjects("Sel Breps", false, ObjectType.Brep, out ObjRef[] objRefs);

            Brep brep1 = objRefs[0].Brep();
            Brep brep2 = objRefs[1].Brep();

            var joinedBreps = Brep.JoinBreps(new Brep[] { brep1, brep2 }, 0.001);

            foreach (Brep brep in joinedBreps)
                var valid = brep.IsValidWithLog(out string log);
                RhinoApp.WriteLine($"Brep valid? {valid} \nlog{log}");
                if (!valid)

                    foreach (var trim in brep.Trims)
                        if (!trim.ProxyCurveIsReversed)
                            bool trimReversed = trim.Reverse();
                            RhinoApp.WriteLine($"Trim Reversed? {trimReversed}");


When I attempt to reverse the trim it fails and returns false. Could someone explain what’s wrong with the geometry after joining and why the trim cannot be reversed?

FailedJoinBrep.3dm (245.9 KB)

The tolerance used - even though it is the same in the document - is just not exactly enough to join the two Breps into one joined Brep. Try either a tolerance directly of 2*documentTolerance or use an iterative approach like this:

double tol = 0.001;
double maxTol = 0.1;
    joined = Brep.JoinBreps(toJoin, tol);
    tol *= 2;
} while(joined.Length != 1 && tol <= maxTol);
1 Like

Wow that works, thank you Menno! Could you explain to me how you came to that conclusion and how the error message relates?

I’ve tried your code and saw that the join did not give one joined Brep, while it works in the Join command. If I’m not mistaken, the join command will always use 2*document_tolerance, so that’s what led me to this iterative approach.

What’s still a bit disconcerting is that the Breps in the resulting array are invalid, so I’ll make a YouTrack ticket for that.

There are a couple of problems with your analysis.

First of all if the edges are out of tolerance, then the Brep.JoinBreps operation should just fail to join and return nothing as the RhinoCommon documentation says it will do. The fact that instead it creates invalid geometry is a Bug that should be fixed and not ignored as you seem to be doing.

Second if you join these in ordinary Rhino the two will join and then go to Rhino Property details, it reports:

` Edge Tolerances: 0 to 0.00017368437991116274

That is also a Bug.
If that report is to be believed then the edges were well within tolerance before joining. In fact, the edges are 10 times more out of tolerance than what Rhino claims they are. And this is not an isolated incident. The reporting of edge tolerance has become significantly less accurate in Rhino7 and Rhino8.

@jim Agreed. Ticket can be viewed at

Thank you.