Shortest Route to BrepFace from Gets

How, from a single pick, would you most efficiently get the Face in the Brep which you clicked on? The best I could come up with was below, knowing that there is going to be a way which is elegant using Rhinocommon. Conditions are just that I want to allow picking of a surface or polysurface, and then in the condition of polysurfaces to get the Face Index at the pick location.

def DoAThing ( ):
    get_object_ex = rs.GetObjectEx( "Pick Surface or Polysurface" , rs.filter.polysurface | rs.filter.surface, preselect=False, select=False )
    point = rs.AddPoint( get_object_ex [3] ) #Use the point in closest?
    objref =rs.coercegeometry( get_object_ex [0] )
    pointref = rs.coerce3dpoint ( get_object_ex [3] )
    distances = []
    for srf in objref.Surfaces:
        rc, parameter_u, parameter_v = srf.ClosestPoint( pointref )
        rc, point3d_closest_point, bool = srf.Evaluate( parameter_u, parameter_v, 0 )
        distance_to_pt = pointref.DistanceTo( point3d_closest_point )
        distances.append( distance_to_pt )

    string_distances = [ str ( distance ) for distance in distances ] #Let the faff begin
    maximum = max( distances )
    minimum = str ( min( distances ) )
    minimum_index = string_distances.index ( minimum )
    print "Picked point is on BrepFace", minimum_index

DoAThing ()

Hi @Jonathan_Hutchinson,

you might allow to pick sub-surfaces to get the face index from a surface, brep or extrusion and stop if the selection was not done by picking (eg. by a window selection): (1.3 KB)


That’s great, thank you Clement.

Most of my confusions lie in the ballpark of the Get class - I still find it a little overwhelming. The samples help but I still haven’t quite got it to muscle memory.

The best way I could explain it to myself is that you, sort of, define the parameters of the ‘Getting’ of an object, with an object in memory (go), then do a go.Get(). And then usually followed by error checking which invariably involves the rc variable somewhere (my best guess at what this is abbreviating is rhino command?).

I didn’t think of the ObjRef class as a returning of a get operation, but more as a link to the GUIDs - looks like Rhino.Input.GetResult.Object is the key here?

I think it’s relation (or lack of) between Get >> ObjRefs >> DocObject. Any tips for better grasping this?

Hi @Jonathan_Hutchinson, you can get the object id anytime from rh_object.Id.

The easiest to get started with the custom object getters is to look at the source code of RhinoScriptSyntax file You can find the file here:

C:\Users\UserName\AppData\Roaming\McNeel\Rhinoceros\6.0\Plug-ins\IronPython (814d908a-e25c-493d-97e9-ee3861957f49)\settings\lib\rhinoscript


Gives some really good food for thought, thanks @clement.

I recognise a few other things you’ve done like the bitwise combination for f.SubSurface | f.TopSurface. Is the documentation a bit unclear on SubSurface and TopSurface? I think it might be just me. So we’re declaring here to only allow subsurface, but also not to accept subsurfaces? (which is the definition of top_surface, according to the docs)

Hi @Jonathan_Hutchinson, the f.SubSurface | f.TopSurface means that both are allowed to be picked. The f.SubSurface is for multiface breps while f.TopSurface allows a single surface brep to be picked. Check out the difference in behavior by removing one of the GeometryAttributeFilters and test with a surface and a box.

I think the key part is setting the go.GeometryFilter first, to only allow surfaces be picked and force subobject selection with these 2 lines:

go.SubObjectSelect = True
go.BottomObjectPreference = False

I admit it appears confusing at the first glance. If you split above method into 2, one for surfaces (which are single faced breps btw) and one for breps with multiple faces, it would be easier to understand.