Where is rs.filter.surface coming from

python

#1

Hi,

I have seen somewhere on the forum the rs.GetObject with rs.filter.surface.
Where rs.filter.surface come from?

Thanks,
Andras


#2

Used inside the various “Get…” functions for example, it limits the selection to surface objects…


#3

Thank you,

I am basically looking for the documentation of the rs.filter to find out the options and type of filterable objects that is available for this method.


(qythium) #4

Looks like it’s an undocumented feature, but digging through the rhinoscript.selection source code reveals that filter is an enum-like class with a corresponding internal function __FilterHelper() that translates it into RhinoCommon objects.

These are the types of geometry that you can filter:

  • allobjects ( the default option - no effect )
  • point
  • pointcloud
  • curve
  • surface
  • polysurface
  • mesh
  • light
  • annotation
  • instance
  • textdot
  • grip
  • detail
  • hatch
  • morph
  • cage
  • phantom
  • clippingplane
  • extrusion

and you use it by passing it into the filter argument of the functions:

  • rs.GetObject
  • rs.GetObjectEx
  • rs.GetObjects
  • rs.GetObjectsEx

optionally combining several filters with the | bitwise-OR operator, eg.

rs.GetObjectEx(message="Choose wisely!", filter=(rs.filter.mesh | rs.filter.polysurface))

#5

The enumeration you find here in selection.py:

image

as well as here in rs.ObjectsByType():

can also be used as shorthand to pass as a geometry filter to the “Get” methods. You can add numerical values as needed, i.e. passing 8+16 does the same thing as passing rs.filter.Surface | rs.filter.polysurface… It’s less verbose, but it does save a lot of line length…


Updating coodinates of lines
(qythium) #6

I would never recommend sacrificing that much readability for a bit of line length savings though, especially in Python - imagine coming across this code without the benefit of comments or keyword arguments:

rs.GetObjects("", 1+4, True) 

versus the self-documenting

rs.GetObjects("", rs.filter.point |
                  rs.filter.curve, preselect=True) 

#7

Well, I do it all the time, each to his own. I expect most people coding to know the object type enumerations - as they are so basic and have existed since Rhinoscript has - especially 1, 2, 4, 8, 16 and 32. I was however not so happy when they added extrusions (1073741824) in V5, as that’s too hard to remember… :stuck_out_tongue_closed_eyes:

As an aside in vb Rhinoscript, the concept of filter via object type name does not exist as far as I know, all you can supply is the integer representing the object type… Rhino.ObjectType() also just returns an integer - as does rs.ObjectType() in python rhinoscriptsyntax.


(qythium) #8

No intention of starting a coding-style debate here, but the official Zen of Python says otherwise :smiley:

[…]
Explicit is better than implicit.
[…]
Readability counts.

</appeal_to_authority>

Rhino.DocObjects.ObjectType is a .NET Enum type, the whole purpose which is to enforce this sort of readability and type safety for symbolic arguments- Python doesn’t have a builtin enum type, which I guess is why rhinoscript defaults to using plain integers and then converting them to ObjectType behind the scenes.

( I’ve never used VB myself so I’m not sure if it does implicit enum-to-int casting, but certainly this doesn’t happen in C# )

PS. they’re all powers of two so you could write 1 << 30 or 0x40000000 or even 0b100000000000000000000000000000 (30 zeroes) instead of the ugly decimal representation :slight_smile:


(qythium) #9

Whoa, just spotted a typo there: rs.filter.morph should be 131072 (2^17) , not 13072 !

Bug verified in GH:
image

@piac https://github.com/mcneel/rhinoscriptsyntax/blob/rhino-6.x/Scripts/rhinoscript/selection.py#L24


#10

Me neither, I don’t consider myself a coder, just a ‘toolmaker’ who makes tools for myself and others. For me line length is important for readability so I much prefer this:

import rhinoscriptsyntax as rs

#filter solid breps + closed meshes
def clsd_vol_filt(rhino_object, geometry, component_index):
    if rs.IsMesh(geometry): return rs.IsMeshClosed(geometry)
    if rs.IsBrep(geometry): return rs.IsObjectSolid(geometry)

msg='Select closed surfaces, polysurfaces or meshes to process'
objIDs=rs.GetObjects(msg,8+16+32,preselect=True,custom_filter=clsd_vol_filt)
print '{} objects selected'.format(len(objIDs) if objIDs else 'No')

to this:

import rhinoscriptsyntax as rs

#solid breps + closed meshes
def clsd_vol_filt(rhino_object, geometry, component_index):
    if rs.IsMesh(geometry): return rs.IsMeshClosed(geometry)
    if rs.IsBrep(geometry): return rs.IsObjectSolid(geometry)

objIDs=rs.GetObjects('Select closed surfaces, polysurfaces or meshes to process' 
,rs.filter.surface | rs.filter.polysurface | rs.filter.mesh, 
preselect=True,custom_filter=clsd_vol_filt)

print '{} objects selected'.format(len(objIDs) if objIDs else 'No')

But again, whatever works…


(Giulio Piacentino) #11

Thanks @qythium, I just reported RH-44902.