Kind request - custom node - Parts - get original family's CompoundStructure Layer Index

Dear colleagues,

I have a kind request for those knowledgable in Revit API and scripting cutom nodes.

I (and many of us need) a Dynamo node that is fed with Parts entities (made of any built-in family with compound structure) and returning as result their Layer Index number of entities original family’s type that actual part is made of.

Examples. I have a wall with 5 layers (structure). Those layers have index numbers (shown in edit type > structure). Then I make Parts of an instance of this Family Type. Each layer becomes a temporary part entity. I need to know the layer index number of each of those parts that they have in their original families.

From my understanding this would have to do with extracting HostObj > CompoundStructure LayerIndex…

Usage / purpose

Revit makes great schedules of wall,slab,roof etc. Breaking Walls into Parts allow to make a schedule of all layers used for each enclosure with easy sorting/filtering. This list as other schedules retain backward compatiblity, so that you can type materials/comments to each layer in such schedule.
The problem is that such lists of Parts have wrong order if layers/Parts of each Family. I need to sort this list of Family Type layers in correct order. This is imposible to get (by my knowledge) in raw Revit.

By knowing layer index numbers, we can sort these lists and provide a sound solution on monitoring/changing and scheduling all layers of all enclosures that lots of people using Revit need in everyday practice.
My proposed solution would write the index number into some parameter of Parts entities (eg. Comments oraz other Shared Parameter) allowing for Revit schedule sorting.

Then You could just pust one instance of each enclosure on some obscure level, devide it to parts a run the script copying index number to each Part.

Can anybody help me with that?

Based on a review of the api, I don’t know if this is doable as you hope - the layer order doesn’t seem to be accessible after the fact or during creation. It may be that the element IDs of the parts are sequential from outside to in at creation, but modification to existing parts would effectively ruin the capability to use that so I would avoid it.

All that said, I believe it could be done via native dynamo.

Find the host, group all parts by the host, find the “outside face”, offset it 10 units by the facing orientation, and then get the distance from each part to the corresponding point, use that as a key to sort the list of parts, generate a range for each set of parts from 1 to the count of parts, and finally use those ranges to set the parameter values.

Hi @LOESCH_PK,

Not sure it meets your needs but there is a LayerId property that can be used :

Layer%20Index

1 Like

This is making use of the element ID sorting. As I noted above, modification of parts could cause this to fail - see what happens if you divide part #2 into pieces.

Hi Jacob,

Thanks for your comment. However I don’t use the element ID of the parts in my graph.
I use a dictionary with the thickness as keys to find the right layer index. So, if I divide the part in pieces, the graph still works.
See the example below :


Thank You Alban_de_Chasteigner but I think this solution is prone to errors.

First of all for this to work You have to have all layers of different "thickness’ cause same thicknesses generate same Layer Indexes…

Other problem that I found is that if You have many walls divided into Parts, “WallType.ByName” takes into account only one WallType (“Name[0]”) and it generates errors and many null results on some layers.

To sum it up - this script works when You have only one wall divided into layers, a its structure has all compounding layers of different thicknesses.

I don’t think one can base such script on any property other than LayerIndex.

Every other property is problematic because it can be duplicated in other WallTypes.

Here is a bit of code I use to cycle through the layers and get any with a certain material to change it. I am sure its origins are a mixture of several folks / packages. Perhaps it could be modified to fit your need. It cycles through the materials in sequence.

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

items = UnwrapElement(IN[0])
elemmat = list()
elemfunc = list()

for item in items:
	try:
		counter = 0
		layermat = list()
		layerfunc = list()
		compstruc = item.GetCompoundStructure()
		num = compstruc.LayerCount
		while counter < num:
			layermat.append(item.Document.GetElement(compstruc.GetMaterialId(counter)))
			layerfunc.append(compstruc.GetLayerFunction(counter))
			counter += 1
	except:
		pass
	elemmat.append(layermat)
	elemfunc.append(layerfunc)
OUT = (elemmat, elemfunc)

API reference:
public System.Collections.Generic.IList<Autodesk.Revit.DB.CompoundStructureLayer> GetLayers()
Member of Autodesk.Revit.DB.CompoundStructure

Summary:
A copy of the layers which define this compound structure.

Returns:
The layers, returned in order (Exterior to Interior for walls, top to bottom for roofs, floors or ceilings). The index of each layer in this array can be used in other CompoundStructure methods accepting a layer index.

Hi,

You didn’t add a sample Revit file to your original post so the previous example must of course be adapted to a real project.
To get a unique key for each layer, you can combine multiple properties (Width+function or material) in a string.
(If it was possible to obtain the location line of the part, it would be the unique key)

1 Like

Has there been any update to this topic? Alban_de_Chasteigner’s solution works in a pinch but isn’t really elegant or reliable.