What magic does baking do to make Breps more realer?

I am doing this work in a C# script node;

I tried to CreateBooleanUnion on a list of Breps. It failed.

I tracked down the problem to just one Brep. (deck1)

I unioned the rest into a Brep called: union. This gives me a valid, solid, closed Brep with no bad edges (open , not manifold).

Things go horribly wrong when this line is executed:
Brep saucer = Brep.CreateBooleanUnion(new Brep[]{union, deck1}, 0.01)[0];

  1. error: Object reference not set to an instance of an object. (line: 176)

0.01 is RhinoDocument.ModelAbsoluteTolerance;

The strange thing is…

if I do this: A = new Brep[]{union, deck1};

and I bake A…

and do this…

image_2022-09-14_182806564

where the two baked breps are put into the Brep node (Set Multiple Breps)

and the code in the script node is: A = Brep.CreateBooleanUnion(x, 0.01)[0];

then it works and A contains a valid, closed Brep.

Things break again if I connect A directly to x.

So it looks like the process of baking does something to make the two Breps more better than they were when un-baked.

What on earth is baking doing? If I knew then maybe I could do that too.

I have tried:

    foreach(Brep b in x)
    {
      b.Compact();
      if (BrepSolidOrientation.Inward == b.SolidOrientation)
      {
        b.Flip();
      }
    }

    A = Brep.CreateBooleanUnion(x, 0.01)[0];

but to no avail.

It just seems that baking a Brep makes it better somehow.

I should have said: this is in the latest Rhino 7 on Windows but I have seen this in previous versions of Rhino.

I have a workaround where I

  1. split the script into 2 scripts
  2. bake the output of the first
  3. put that into a Brep node and internalize it
  4. Put that Brep into the second node

Obviously that sucks but it works(ish).

I feel dirty but there might be a hack to get the magic baking goodness…

I could try:

  • adding the Breps to the document - note their Guids
  • load them back into my script
  • perform the union on the loaded Breps
  • remove the temporary Breps from the document

I’m going to try that when I get home tonight.
Has anyone had experience of this? Any tips?

I will let you know how I get on…

what does
deck1.GetType();
return ?
check also:
deck1.IsValidTopology();
IsValidTopology

Grasshopper does a lot of casting and conversion between the output and input of the components. This might explain the described “baking behaviour”.

GetType says that both are Rhino.Geometry.Breps and IsValidTopology is true

The temporary bake hack works!!! :slight_smile: I am so happy :slight_smile:

So…

  • If you have boolean or fillet ops that fail in code
  • if you expected them to work
  • and they work when you bake the objects
  • then try something like the temporary bake hack below
Guid unionGuid = RhinoDocument.Objects.AddBrep(union);
Guid deck1Guid = RhinoDocument.Objects.AddBrep(deck1);
union = (Brep) RhinoDocument.Objects.FindGeometry(unionGuid);
deck1 = (Brep) RhinoDocument.Objects.FindGeometry(deck1Guid);

Brep saucer = Brep.CreateBooleanUnion(new Brep[]{union, deck1}, t)[0];

RhinoDocument.Objects.Delete(unionGuid, true);
RhinoDocument.Objects.Delete(deck1Guid, true);

I hesitate to mark this as an answer because I still don’t understand why baking helps.

it s a unexpected workarround, not a solution.

Can you somehow reproduce the error in a simplified version and post both the .3dm and .gh file so others can reproduce what you’re seeing ?
if there is a bug in the background, would be sad if it s not tracked.

Where does the geometry of deck1 comes from ?
Are you doing some geometry modification of “deck1” ? before you run the boolean operation ?

@dale
does AddBrep() perform some cleaning / updating of the geometry ?

I’m going to try to make an example 3dm and grasshopper file to illustrate.

I use custom C# components to build geometry and many other C# script nodes so I don’t know yet if I have to include the built components and a large chunk of everything else.

But I will know once I try…

Well, I have tried and it looked like I had a minimal example that showed failure. I deleted some “unused” layers and saved the files.

I then opened them and I can’t get it to fail.

I tried opening the grasshopper file in the big 3dm with all the layers. Didn’t fail.

Tried running Rhino in the debugger but to no avail.

Still fails if I use the big 3dm and the big grasshopper file but that would need the built component assemblies as well.

Hi @Tom_P,

When you add a Brep to the document, two things happen:

1.) If kink splitting is enabled (which it is unless it is being overridden temporarily by a plug-in), then BrepFaceList.SplitKinkyFaces() is called, which splits any faces with creases into G1 pieces.

2.) If the Brep’s solid orientation is inward, then it is flipped using Brep.Flip().

– Dale

2 Likes

This fixes things without a bake.


      union.Faces.SplitKinkyFaces(RhinoDocument.ModelAngleToleranceRadians);
      deck1.Faces.SplitKinkyFaces(RhinoDocument.ModelAngleToleranceRadians);
      saucer = Brep.CreateBooleanUnion(new Brep[]{union, deck1}, t)[0];

How do I know if a face is kinky? I would like to bake them and have a look at the offending faces.

I brute forced it.

      List<Brep> theKinkyOnes = new List <Brep>();
      foreach(BrepFace face in union.Faces)
      {
        Brep b = face.DuplicateFace(false);
        int initialCount = b.Faces.Count;
        b.Faces.SplitKinkyFaces(RhinoDocument.ModelAngleToleranceRadians);
        if (b.Faces.Count > initialCount)
        {
          //theKinkyOnes.Add(face.DuplicateFace(false));
          foreach(var v in b.Faces)
          {
            theKinkyOnes.Add(v.DuplicateFace(false));
          }
        }
      }
      A = theKinkyOnes;

got this

I know where that is and can find where I make it and fix it at source (make it better or split it immediately after making)

Thanks Dale. I will mark your post as the answer.