Feasibility - Ways to Assign finishing material to walls

Hello Dynamo Friends :slight_smile:

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 :slight_smile:

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 :thinking:

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