Convert RhinoObjects to Brep

Hi, I am trying to create a solid component from a user defined selection. Following is my code.

 var go = new GetObject();
        go.SetCommandPrompt("Select objects ");
        
        go.GroupSelect = true;
        go.SubObjectSelect = false;
        
        for (; ; )
        {
            go.ClearCommandOptions();
            go.AddOptionToggle("CoordinateSystem", ref cs_option);

            var res = go.GetMultiple(1, -1);

            if (res == GetResult.Option)
                continue;
            else if (res != GetResult.Object)
                return Result.Cancel;

            break;
        }

        var n = go.ObjectCount;
        var geom = new Rhino.DocObjects.RhinoObject[n];


        for (var i = 0; i < n ; i++)
        {
            geom[i] = go.Object(i).Object();
           
        }
        var solid1 = Rhino.Geometry.Brep.CreateSolid(geom, RhinoMath.UnsetValue);

I start by assigning the variable ‘go’ to the objects selected by the user. Next, I check the number of objects in the selection and run a for loop to create an array called “geom” to be used with the CreateSolid method. This is of type Rhino.DocObjects.RhinoObject. But to create the solid component Rhino.Geometry.Brep is required.

Is there a way to convert RhinoObject to Brep ? Or any other alternative to this?
Thanks in advance

Hi @raghav.pathak

You can do this to convert all input geometries to Brep.
var breps = go.Objects().Select(_ => Brep.TryConvertBrep( _.Geometry()));

Hi @mingo1214

Thanks for the reply.

But I am not sure where to put the line of code you mentioned in my code. According to me it should be before the for loop for ‘geom’ array. But it still has the issue of mismatched types RhinoObject and Brep.
Or I think I can get rid of all the extra loop with this one line.
Could you help me with this?

Here is all you need to do after you get user’s input objects.

var breps = go.Objects().Select(_ => Brep.TryConvertBrep( _.Geometry()));
var solid1 = Rhino.Geometry.Brep.CreateSolid(breps, doc.ModelAbsoluteTolerance);

geom[i] = go.Object(i).Object().Geometry;

Does this work?

Hi @raghav.pathak,

Try something like this:

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
  var go = new GetObject();
  go.SetCommandPrompt("Select intersecting surfaces and polysurfaces to automatically trim and join into a closed polysurface");
  go.GeometryFilter = ObjectType.Surface | ObjectType.PolysrfFilter;
  go.SubObjectSelect = false;
  go.GetMultiple(1, 0);
  if (go.CommandResult() != Result.Success)
    return go.CommandResult();

  var in_breps = new List<Brep>();
  foreach (var objref in go.Objects())
  {
    var brep = objref.Brep();
    if (null == brep)
      return Result.Failure;
    in_breps.Add(brep);
  }

  var out_breps = Brep.CreateSolid(in_breps, doc.ModelAbsoluteTolerance);
  if (null != out_breps)
  {
    foreach (var brep in out_breps)
      doc.Objects.AddBrep(brep);
  }

  doc.Views.Redraw();

  return Result.Success;
}

– Dale

Hi @dale
Thanks for making the effort.
This code works perfectly. I have one more issue though. The solid obtained using this code has to be subtracted from another solid obtained from a brep box (which is trivial to obtain). I use the booleandifference method to do this. However, the resulting brep type array has no solid objects.
Another issue with booleandifference method is that it only works when the 2 objects involved intersect each other.
I was wondering if there are any other methods to perform this(referring to the A minus B in “Boolean Two Objects” and “Difference” methods in the Rhino Environment).
Could you please give some idea about this?
Thanks

Hi @dale
Could you please have a look at the previous thread?
Thanks

Hi @raghav.pathak,

To be of any help, I’ll need a sample model and your sample source code.

– Dale

Hi @dale
Following are the .rhi and .3dm files.

RhinoTdynBoundingBox2.rhi (584.5 KB)
Wigley_hull.3dm (29.1 KB)

Hi @raghav.pathak,

Since your surfaces join nicely, calling Brep.CreateSolid is a bit of a sledge hammer. Better to use Brep.JoinBreps.

Also, BoundingBox.ToBrep returns a nice, closed and oriented Brep. Thus, there is no reason to try to create a solid from the faces - as the Brep is already solid.

Not knowing what you are doing with the bounding box, I typed up a sample that demonstrates some of what I talked about.

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
  var go = new GetObject();
  go.SetCommandPrompt("Select surfaces");
  go.GeometryFilter = ObjectType.Surface;
  go.SubObjectSelect = false;
  go.GetMultiple(1, 0);
  if (go.CommandResult() != Result.Success)
    return go.CommandResult();

  var in_breps = new List<Brep>();
  foreach (var objref in go.Objects())
  {
    var brep = objref.Brep();
    if (null == brep)
      return Result.Failure;
    in_breps.Add(brep);
  }

  var joined_breps = Brep.JoinBreps(in_breps, doc.ModelAbsoluteTolerance);
  if (null != joined_breps && 1 == joined_breps.Length)
  {
    var hull_brep = joined_breps[0];

    // Because kinked surface can cause problems down stream, Rhino
    // always splits kinked surfaces when adding Breps to the document. Since
    // we are not adding this Brep to the document, lets split the kinked
    // surfaces ourself.
    hull_brep.Faces.SplitKinkyFaces(RhinoMath.DefaultAngleTolerance, true);

    // The profile curve, created by the input points, is oriented clockwise.
    // Thus when the profile is extruded, the resulting surface will have its
    // normals pointed inwards. So lets check the orientation and, if inwards,
    // flip the face normals.
    if (BrepSolidOrientation.Inward == hull_brep.SolidOrientation)
      hull_brep.Flip();

    var bbox = hull_brep.GetBoundingBox(true);
    var origin = bbox.Corner(true, true, true);
    var sx = (bbox.Corner(false, true, true) - origin).Length / 10.0;
    bbox.Inflate(-sx, 1.0, 1.0); // deflate in x-direction...
    var box_brep = bbox.ToBrep();

    var diff_breps = Brep.CreateBooleanDifference(box_brep, hull_brep, doc.ModelAbsoluteTolerance);
    if (null != diff_breps && 1 == diff_breps.Length)
      doc.Objects.AddBrep(diff_breps[0]);

    doc.Objects.AddBrep(box_brep);
  }

  doc.Views.Redraw();

  return Result.Success;
}

Hope this helps.

– Dale

Hi @dale
Thanks for the code
However, I have one issue which is still persistent. If I change only this part of the code according to my manipulations of the bounding box keeping everything same, the boolean difference still fails.

I am using this piece of code which is already in the file that I sent before. Here, p1x,p2x etc. are corner points considering various factors which change the lengths at front, side etc.

Rhino.Geometry.Point3d pt0 = new Rhino.Geometry.Point3d(p1x, p1y, p1z);
Rhino.Geometry.Point3d pt1 = new Rhino.Geometry.Point3d(p2x, p2y, p2z);
Rhino.Geometry.BoundingBox box1 = new Rhino.Geometry.BoundingBox(pt0, pt1);
var box_brep = box1.ToBrep();

But now the boolean difference fails. Could you please tell what could be the reason because I dont think the factor affecting p1x,p2x etc can cause this.

Edit: I just realized both methods work but only when both solids intersect each other. But what I am trying to achieve is that the original geometry is subtracted from the bigger box whose dimensions could be as large as the user gives(may or may not intersect the original geometry).

The code I posted works with your model.

Perhaps your box brep does not intersect with your hull brep?

– Dale

Hi @dale, thanks for the clarification.

Yes, that’s what I am saying. The code works perfectly only if the box is intersecting with the brep. But, this geometry is only 1 of several test cases that may arise and ideally, the box should not intersect and still, the boolean difference operation should work.

The end result should be something like a cavity of the original brep inside a cuboidal volume.

Rhino’s Boolean operations will not do this, as a closed Brep is hollow.

– Dale