Getting sub-object material

I have a python script that gets material names from polysurface objects and tagging the objects in layouts with text objects. This works well, except that I want to get the material names from faces of polysurfaces as many of the files I’m working with have materials assigned to faces, not the whole polysurface.
I tried using materials_table.FindIndex(brep_face.MaterialChannelIndex) but this doesn’t return the correct material.
Clearly I don’t understand the MaterialChannelIndex property but cannot find any other way to get the material assigned to a face. I checked all the topics talking about materials on objects, no joy.
Anyone know how to get this?

Hi @GaryC, below might be helpful to get started:

#! python 2
import Rhino
import rhinoscriptsyntax as rs

def SubobjectMaterialNames():
    
    brep_id = rs.GetObject("Select brep with subobject materials", 16)
    if not brep_id: return
    
    brep_obj = rs.coercerhinoobject(brep_id, True, True)
    if not brep_obj.HasSubobjectMaterials: return
    
    material_names = set()
    
    for component_index in brep_obj.SubobjectMaterialComponents:
        render_material = brep_obj.GetMaterial(component_index)
        material_names.add(render_material.Name)
    
    print list(material_names)
    
SubobjectMaterialNames()

_
c.

2 Likes

Thanks @clement. That definitely helps. Now I’m struggling with how to match up the subobject, in this case a face, with the material. I want to get the dimensions of the face so I can calculate the surface area that has that material assigned. I tried various things, but can’t seem to match up the material with the face.
Thanks again for helping out. Really appreciate it.

I figured it out. Here is a little script that does the trick.
If there is a cleaner way, I’m open to suggestions. But this works for surfaces and polysurfaces.

#! python3
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

msg="Select objects to get material"
objs = rs.GetObjects(msg, 8 + 16, preselect=True)

if objs:
    for obj in objs:
        rh_obj = rs.coercerhinoobject(obj, True, True)
        if rh_obj.HasSubobjectMaterials:        
            print("Object has sub-object materials.")
            for ci in rh_obj.SubobjectMaterialComponents:            
                for f in rh_obj.Geometry.Faces:                
                    if ci.Index == f.ComponentIndex().Index:                    
                        area = Rhino.Geometry.AreaMassProperties.Compute(f).Area
                        rm = rh_obj.GetMaterial(ci)
                        print(f"{rm.Name} = {area}")
                        break
        else:
            print(f"Object has no sub-object materials. Object material is {rh_obj.RenderMaterial.Name}")

Hi @GaryC, you might get along with below. I guess the ComponentIndex.Index gives you the index of the brep face without iteration. I’ve not been sure if you need the area per face + material or the total area of all subobject materials, the script should give you both:

#! python 2
import Rhino
import rhinoscriptsyntax as rs
from collections import defaultdict

def DoSomething():
    brep_id = rs.GetObject("Select brep with subobject materials", 16)
    if not brep_id: return
    
    brep_obj = rs.coercerhinoobject(brep_id, True, True)
    if not brep_obj.HasSubobjectMaterials: return
    
    brep = brep_obj.Geometry
    dict_areas = defaultdict(lambda: 0.0)
    
    for ci in brep_obj.SubobjectMaterialComponents:
        mat = brep_obj.GetMaterial(ci)
        amp = Rhino.Geometry.AreaMassProperties.Compute(brep.Faces[ci.Index])
        msg = "Face: {}  Material: {}  Area: {}"
        print msg.format(ci.Index, mat.Name, amp.Area)
        dict_areas[mat.Name] += amp.Area
    
    for mat_name, total_area in dict_areas.iteritems():
        print "Material: {}  TotalArea: {}".format(mat_name, total_area)
    
DoSomething()

btw. if you have materials with the same name (which is allowed) you might work with material Id instead of Name when computing the cumulative (total) area for each material.
_
c.

Very nice! Thanks very much.