Hello Dynamo Friends 
I want to create a little tool that lets a user select a wall or wall face in the model and create and assign a material to it. The materials are called from a catalogue on a server.
Only problem is IĀ“m a noob if it comes to wall layers!
Current status:
IĀ“m using these methods to get the structure and set the material to the layers.
compound_structure = wall_type.GetCompoundStructure()
layer_count = compound_structure.LayerCount
compound_structure.GetMaterialId(layer_index)
compound_structure.SetMaterialId(layer_index, material_id)
wall_type.SetCompoundStructure(compound_structure)
Questions:
- Are there nodes or API methods that let me select only one side of the wall and not the whole wall like IĀ“m doing it now?
- How can I identify the finishing layers if the wall has more layers? Or how to identify if a wall has no finishing like my basic wall? Is it all just about count and index?
- What other special cases I have to consider to make such a tool work properly?
Appreciate any advice 
Edit: now I see that IĀ“ll have to ask the user if he wantĀ“s to change the wall type or if he wants a new type created for the selected wall.
1 Like
Count and index is the way forward. Check out the nodes for wall layers in Clockwork for more info.
2 Likes
OK just using first and last index for applying the material is an easy one.
if compound_structure is not None:
layer_count = compound_structure.LayerCount
for layer_index in [0,layer_count-1]:
layer_id = compound_structure.GetMaterialId(layer_index)
compound_structure.SetMaterialId(layer_index, material_id)
wall_type.SetCompoundStructure(compound_structure)
Now itĀ“s about selecting one side of the wall, IĀ“ll see what node I can find.
1 Like
Selecting one face of the wall and getting the wall from that face is also pretty easy
reference = uidoc.Selection.PickObject(ObjectType.Face, "Please select a face")
wall = doc.GetElement(reference.ElementId)
But now IĀ“m in trouble because walls donĀ“t have a back side and a front side like columns. If they did have a front side and the layer would always start from there it would all be good. But I donĀ“t see any chance to match the face with the appropriate wall side or layer 
Dynamo research tells me I could sort the faces and references but that does not help me at allā¦I would need an āIĀ“m the frontsideā identifier like i have it in other families like columnsā¦
Sure they do.
There is a āflippedā property which should help you get sorted, but there is also an example of finding āinsideā and āoutsideā of a wall in Clockwork if memory serves.
1 Like
It looks like I can just rely on the order of element.faces!
If index 0 is always the same face I am save.
Here 2 walls drawn in different directions.
Right - if you know the āinside to outsideā order, then you can build any wall type.
If you have an instance of a type and want to add a layer on a particular side (such as adding a layer of impact resistant GWB in the garage walls) that is the where knowing which side is which comes into play.
1 Like
Perfect, everything working now.
I compare face normals to see if i have selected front or back
options = Options()
geometryElement = wall.get_Geometry(options)
# Get the selected face's normal
selected_face = doc.GetElement(reference).GetGeometryObjectFromReference(reference)
selected_normal = get_face_normal(selected_face)
# Iterate through the geometry to find faces
face_index = 0
for geometryObject in geometryElement:
if isinstance(geometryObject, Solid):
for face in geometryObject.Faces:
normal = get_face_normal(face)
# Compare normals and determine face side
if normal.IsAlmostEqualTo(selected_normal):
if face_index == 0:
side = "back"
elif face_index == 1:
side = "front"
break
face_index += 1
and then i use the side for setting the material.
if compound_structure is not None:
layer_count = compound_structure.LayerCount
if side == "front":
layer_index = 0
elif side == "back":
layer_index = layer_count-1
layer_id = compound_structure.GetMaterialId(layer_index)
compound_structure.SetMaterialId(layer_index, material_id)
wall_type.SetCompoundStructure(compound_structure)
Thanks for the help jacob!
1 Like