Best method to get subface information into Grasshopper?

Hi all,

I keep running into a similar challenge in my models that I’m not sure about the best method to handle?

In almost all the models I am building these days, it would be really helpful to be able to assign some id-information (name or some other “key”) to Brep faces and then pull that information out again in Grasshopper, but I can’t really figure out a good method to do something like that? I wonder if anyone has any thoughts on a good method that might help in a scenario of this sort?

Scenario:

I have many Closed Brep Polysurface objects in my Rhino models, being passed over to Grasshopper where I am doing a bunch of analysis on them (architecture/engineering stuff). It would be really helpful to be able to pass along some ‘meta-data’ about the subobject faces somehow (ie: this subface is type “A”, that subface is type “B”, etc…)

For the models I’m working on it is important that all the polysurfaces are closed in Rhino, not lose individual surfaces (meaning: I can’t really use Layer name info as a “key”), and realistically I can’t use Materials as a key because of the mess that makes of the file (link) and I can’t use Face Color since that doesn’t work either (link), so I am note sure what else to try at this point?

Perhaps a custom form to assign info to the element’s UserDictionary? I wasn’t able to make that work on polycurves after a brief test (link), but maybe something of that sort would work on brep subfaces?

Is there some other more straightforward method that I might try to assign / set some data to the subfaces that I can use later on for filtering, categorizing, sorting, etc… ? Even if its just a simple name / key, I could use that for lookups later to get the full metadata I need from outside Rhino (from a CSV or something like that)?

any suggestions for some methods to try would be much appreciated.
Thanks!
@ed.p.may

Hi @ed.p.may,

You can attached user data, such as user strings, to Brep faces.

brepface_userstrings.gh (18.4 KB)

– Dale

Thanks @dale ! That’s a great idea. But unlike Brep objects, the subobject face Attribute UserText is not exposed within the normal Rhino-side Properties, right?

I suppose I could certainly build a small ETO dialog to allow a value to be set for my objects in Rhino. Unless there is an easier way that is available directly in the Rhino side UI that I am missing?

@ed.p.may

Hi @ed.p.may,

Keep in mind that an Extrusion is not a Brep, and thus does not have faces. You can, however, create a Brep from an Extrusion.

I say this because your image shows a closed Extrusion.

But you are correct, there is no interface in Rhino for setting user text on a Brep face.

– Dale

1 Like

Here is a rough example of how to use the SetUserString function to attach information to a BrepFace; And how to access them later in Grasshopper.


Rhino:

import Rhino
def SetSubObjUserText():
    go = Rhino.Input.Custom.GetObject()
    go.GeometryFilter = Rhino.DocObjects.ObjectType.Surface
    go.SubObjectSelect = True
    go.SetCommandPrompt('Select brep-face')
    go.Get()
    if go.CommandResult()!=Rhino.Commands.Result.Success:
        return go.CommandResult()
    objref = go.Object(0)
    brep = objref.Brep()
    rc, key = Rhino.Input.RhinoGet.GetString('Key', False, '')
    if rc!=Rhino.Commands.Result.Success: return rc
    rc, text = Rhino.Input.RhinoGet.GetString('Text', False, '')
    if rc!=Rhino.Commands.Result.Success: return rc
    brep.Faces[objref.GeometryComponentIndex.Index].SetUserString(key, text)
if __name__ == "__main__":
    SetSubObjUserText()

Grasshopper:

private void RunScript(Brep x, ref object Keys, ref object Texts)
{
  var keys = new DataTree<string>();
  var texts = new DataTree<string>();
  for (var i = 0; i < x.Faces.Count; i++)
  {
    var nvc = x.Faces[i].GetUserStrings();
    for(var j = 0; j < nvc.Count; j++)
    {
      keys.Add(nvc.GetKey(j), new GH_Path(i));
      texts.Add(nvc.GetValues(j)[0], new GH_Path(i));
    }
  }
  Keys = keys;
  Texts = texts;
}

SetSubObjUserText.py (744 Bytes)
SetSubObjUserText.gh (13.9 KB)

2 Likes

Fantastic - thank you so much @Mahdiyar , that script works great. With a little customization for my specific use-case this should work really well.

thank you!
@ed.p.may

Hello @Mahdiyar, After embedding the key and value in the Brep faces,
how can you select in Rhino only the Brep faces that I need?
It is basically a selection of Brep faces with indices.

var facesToSelect = new List<BrepFace>();
for (var i = 0; i < B.Faces.Count; i++)
{
  var nvc = B.Faces[i].GetUserStrings();
  for(var j = 0; j < nvc.Count; j++)
  {
    if(nvc.GetValues(j)[0] == V)
      facesToSelect.Add(B.Faces[i]);
  }
}
A = facesToSelect;

This code is just to preview, but what I need is the Selection in Rhino, this is tha idea with a button.
Any help would be appreciated, thank you!

1 Like

private void RunScript(Guid Id, string V, bool S, ref object A)
{
  if (!S) return;
  var rhobj = RhinoDocument.Objects.FindId(Id);
  var brep = (Brep) rhobj.Geometry;
  RhinoDocument.Objects.UnselectAll(true);
  foreach(var face in brep.Faces)
  {
    var nvc = face.GetUserStrings();
    for(var i = 0; i < nvc.Count; i++)
    {
      if(nvc.GetValues(i)[0] != V) continue;
      rhobj.SelectSubObject(face.ComponentIndex(), true, true, true);
      break;
    }
  }
}

Thomas.gh (6.0 KB)

1 Like