AccessViolationException in Brep.CreatePlanarBreps

I sometimes get an AccessViolationException thrown from inside a call to Brep.CreatePlanarBreps(IEnumerable) in a RhinoCommon plugin I am developing. I am trying to find a simple, reproducible test case, but it is difficult, because it happens in a fairly dense part of the plugin, and it does not happen 100% of the time (which is the way of AccessViolationExceptions, I guess). This is happening with SR9. Is there anything obvious that might be causing this?

edit: In many cases, the exception never propagates out of the call, and I only know it ever happened because I have a debugger attached. (I still expect that this is not correct behavior.) However, sometimes Rhino is brought down with an unhandled exception that seems to be somehow related to this.

Are you sure that all curves are not null and that the count is >0? I typically see access violation if non-managed code (e.g. Rhino core) tries to access a null value.

I cannot find anything like this. Also, the problem is not consistent (i.e. for a given curve sequence it will only sometimes happen), which makes that explanation seem less likely to me.

Can you try to count the breps that will be returned like:

Dim PlanarBreps() as geometry.brep = geometry.brep.CreatePlanarBreps(IEnumerable)

If PlanarBreps.Length > 0 then
  // Continue funtion.
End If

Because I can reproduce this problem. That is because the brep.CreatePlanarBreps(IEnumerable) cant create your planar brep because the curve is not planar. Then you try to do something with the planarBrep that does not exist. Then the error occurs.

Maybe loop throught the curves and check Curve.IsPlanar(doc.AbsoluteTolerance)?

The exception is thrown inside Brep.CreatePlanarBreps.

Did you check if the curves are planar before you start the Brep.CreatePlanarBreps?

Yes, I am checking that. They’re all planar, so far.

I seem to have “solved” the problem by turning this (abbreviated) code:

var curveSequence = curves1.Concat(curves2);
breps = Brep.CreatePlanarBreps(curveSequence);

into this code:

var breps1 = Brep.CreatePlanarBrep(curves1);
var breps2 = Brep.CreatePlanarBrep(curves2);
breps = breps1.Concat(breps2).ToArray();

but I don’t know why that fixes it.

If I try to use Concat it already starts to give errors.
Maybe avoid that? Try to use lists or arrays {curves1, curves2}

I think what’s happening here is late/lazy evaluation of the Concat operation not playing nice with native code interop. If I’m not mistaken it returns an IEnumerable of Curve, but the actual concatenation happens only when the IEnumerable is enumerated. I bet that if you call ToArray() on the result before putting it in PlanarSrf, which will force the enumeration early, will also solve the problem.

I would be willing to chalk it up to that (although I can’t think of any native code interop scenario that would explain it), but I’ve since discovered that Brep.CreatePlanarBreps is actually not behaving the way I thought it was.

In this particular case, each curve sequence only has one curve in it. Calling Brep.CreatePlanarBreps on each sequence individually yields two Breps, as expected. However, calling Brep.CreatePlanarBreps on the concatenated sequence only yields one Brep. Apparently the method doesn’t just walk the sequence and create a Brep for each input curve. So I guess my question is: What exactly is the behavior of Brep.CreatePlanarBreps?

I did some more investigating, and this looks like some problematic interaction between PLINQ and Brep.CreatePlanarBreps (or something else that came before). I’ve submitted an issue (#167) to github.