"Select by material name" with python and/or rhinocommon

I have been trying to perform “select by material” with script in python or rhinocommon.
Couldn’t find anything similar in the doc…

There is a series of findby… methods under Rhino.DocObjects.Tables.ObjectTable
but I don’t see findbymaterial listed here or anywhere else.

Any lead is greatly appreciated!!!

Hi @yang, below seems to work:

import Rhino
import scriptcontext
import rhinoscriptsyntax as rs

def SelMaterialName(name):
    
    settings = Rhino.DocObjects.ObjectEnumeratorSettings()
    settings.NormalObjects = True
    objs = scriptcontext.doc.Objects.GetObjectList(settings)
    
    rc = filter(lambda i: i.RenderMaterial and i.RenderMaterial.Name==name, objs)
    if not rc: return
    
    rs.SelectObjects(rc)
    
SelMaterialName(name="Gem")

alternatively, if you do not need the rhino objects and just select, you could script the Rhino command

_SelMaterialName

_
c.

1 Like

Hi Clement, thank you so much!
This is amazing.

I am curious to know if you can explain a little bit what does these two lines do??

    rc = filter(lambda i: i.RenderMaterial and i.RenderMaterial.Name==name, objs)
    if not rc: return

I tried

rs.command( "!_SelMaterialName " + str(MaterailName))

But I ran into two problems:

  1. some of my material names have space in it for ex. “Blue Carpet” and rs.command would stop at the space after blue instead of putting in “Blue Carpet” as a single material name.
  2. I couldn’t select geometries without name with this method

What do you think about these issues?
Thanks again!

Hi @yang, in this line i am just using pythons build in filter function, it is just a short for iterating over all objs and finding out which of these objects have a RenderMaterial assigned and if the RenderMaterial.Name equals the name we’re searching for. It then puts the found objects into a new list called rc

If you script the SelMaterialName command, you must enclose the name of the material into quotes so the command line does not interpret the space as an Enter. You can do this for example like this:

import rhinoscriptsyntax as rs

def MySelMaterialName(name):
    
    cmd = "_-SelMaterialName {}{}{}".format(chr(34), name, chr(34))
    rs.Command(cmd, True)
    
MySelMaterialName("Gem")

If you use the above example which scripts the _-SelMaterialName command, you can select all objects without material by calling it with an empty string:

MySelMaterialName("")

It also allows to to use wildcards for selection by material name, which means you could do:

MySelMaterialName("Blue*")

this would select objects with materials where the material name starts with “Blue”, eg. “Blue Carpet” or “Blue chair” etc.

btw. note that i call the command like this: “_-SelMaterialName”. The underscore _ makes the command usable on different languages and interprets it in english language. The minus - suppresses the dialog from popping up and routes the command options to the command prompt.

_
c.

1 Like

Hi Clement,

Thanks again for sharing.
I definitely couldn’t come up with the {}{}{}".format(chr(34), name, chr(34)) myself.

This is great!