Hi,
This follows on from my other thread i made. (thanks again for the help! )
https://forum.dynamobim.com/t/python-get-element-family-name-then-apply-a-filter/38261/3
So i tried to get it working with multiple view inputs, which works to some extent.
i can get the fittings per view. 14 on the first view, 2 on the second. thatâs correct.
Then i put in the code from the MEPOver package (@T_Pover), to find the connected elements and it comes out as the same number but in one list.
my question really is how do i get the duct output to match the fittings output?
i was thinking it should be be âfor s in sfittingsâ not âfor s in sfittingâ but this gives an error about not having MEP connectors.
i tried changing the indents which gave some different results and adding a zip, but i couldânt get it to work either.
import clr
#Import Revit Nodes
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference ("DSCoreNodes")
import DSCore
from DSCore import *
doc = DocumentManager.Instance.CurrentDBDocument
def tolist(obj):
if isinstance(obj, list):
return UnwrapElement(obj)
else:
return [UnwrapElement(obj)]
views = tolist(IN[0])
ducts = []
sfittings = []
sducts = []
#collection filter FamilyInstance in view list
for view in views:
sfitting = [x for x in FilteredElementCollector(doc, view.Id).OfCategory(BuiltInCategory.OST_DuctFitting).ToElements() if "Shoe" in x.Symbol.FamilyName]
sfittings.append(sfitting)
for s in sfitting:
connset = s.MEPModel.ConnectorManager.Connectors
conn_pipes = []
for c in connset:
if c.IsConnected:
for sc in c.AllRefs:
conn_pipes.append(sc.Owner)
sducts.append(conn_pipes)
OUT = sfittings, sducts
#OUT = List.Flatten(shoe_ducts,2), List.Flatten(taper_ducts,2)#,
could anyone offer any advice?
Thanks,
@c.poupin @cgartland
Hello you can try this (not test)
ducts = []
sfittings = []
sducts = []
#collection filter FamilyInstance in view list
for view in views:
sfitting = [x for x in FilteredElementCollector(doc, view.Id).OfCategory(BuiltInCategory.OST_DuctFitting).ToElements() if "Shoe" in x.Symbol.FamilyName]
#joinlist
sfittings += sfitting
for s in sfittings:
connset = s.MEPModel.ConnectorManager.Connectors
conn_pipes = []
for c in connset:
if c.IsConnected:
for sc in c.AllRefs:
conn_pipes.append(sc.Owner)
sducts.append(conn_pipes)
or make a flat list
for view in views:
sfitting = [x for x in FilteredElementCollector(doc, view.Id).OfCategory(BuiltInCategory.OST_DuctFitting).ToElements() if "Shoe" in x.Symbol.FamilyName]
sfittings.append(sfitting)
flat_sfittings = [item for sublist in sfittings for item in sublist]
for s in flat_sfittings:
.....
1 Like
why collect the elements by view? (âall viewsâ in the previous python node) Is not it easier to collect all the elements of the project in this case?
sfitting = [x for x in FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_DuctFitting).ToElements() if "Shoe" in x.Symbol.FamilyName]
1 Like
If you want to create a list per view (with sublists of your fittings) then you have to create a new list on every iteration of a view to which you can append your âconn_pipesâ. Right now you are appending everything to the âsductsâ list, which will accumulate everything from every iteration.
3 Likes
Thank for your replies guys,
I tried the first solution and i.m getting matching list now, except they are both in one list, I want to keep them in separate lists per view so as to tag them in multiple sheets later on.
@T_Pover, so would i need to do something like âfor sfittings in viewâ in between âview in viewsâ and âs in sfittingsâ?
You could do something like this:
views = tolist(IN[0])
ducts = []
sfittings = []
sducts = []
#collection filter FamilyInstance in view list
for view in views:
sfitting = [x for x in FilteredElementCollector(doc, view.Id).OfCategory(BuiltInCategory.OST_DuctFitting).ToElements()]
sfittings.append(sfitting)
connected_fittings = []
for s in sfitting:
connset = s.MEPModel.ConnectorManager.Connectors
conn_pipes = []
for c in connset:
if c.IsConnected:
for sc in c.AllRefs:
conn_pipes.append(sc.Owner)
connected_fittings.append(conn_pipes)
sducts.append(connected_fittings)
OUT = sfittings, sducts
Where I have added a variable âconnected_fittingsâ that will be filled with the fittings per view. Then append that variable to your sducts. That way you will get what you want (I think :))
1 Like
Ok this is great, thank you so much @T_Pover. its working and i think im understanding why now too!
I left in the family name filter from @c.poupin
for view in views:
for view in views:
sfitting = [x for x in FilteredElementCollector(doc, view.Id).OfCategory(BuiltInCategory.OST_DuctFitting).ToElements() if "Taper" in x.Symbol.FamilyName]
sfittings.append(sfitting)
connected_fittings = []
for s in sfitting:
it was the 2nd and 3rd line, i didnât quite get why sfitting wasnât outputting per view. It was outputting the fittings on one view (the last view in the list). then sfittings is doing it for each view because its on the view indent.
connected_fittings is outputting the last view to, and because sducts is aligned to the view indent it does it for each view.
does that sound about right?
So i changed to filter to âTaperâ, to get a situation like this, where i get a bend immediately after the âTaperâ. in this instance i want to get the duct after the bend.
I tried adding something to filter out the ducts and fittings, but its giving me an empty list and a full list.
views = tolist(IN[0])
ducts = []
sfittings = []
sducts = []
ductlist = []
fittinglist = []
#collection filter FamilyInstance in view list
for view in views:
sfitting = [x for x in FilteredElementCollector(doc, view.Id).OfCategory(BuiltInCategory.OST_DuctFitting).ToElements() if "Taper" in x.Symbol.FamilyName]
sfittings.append(sfitting)
connected_fittings = []
for s in sfitting:
connset = s.MEPModel.ConnectorManager.Connectors
conn_pipes = []
for c in connset:
if c.IsConnected:
for sc in c.AllRefs:
conn_pipes.append(sc.Owner)
connected_fittings.append(conn_pipes)
sducts.append(connected_fittings)
for duct in sducts:
if duct == "Duct":
ductlist.append(duct)
else:
fittinglist.append(duct)
OUT = ductlist, fittinglist
#OUT = sfittings, sducts
The idea is to apply the whole connected elements process again to the fittings, to get the ducts.
i know its probably notthe best way of going about, im thinking it should be added just after
conn_pipes.append(sc.Owner)
and say
if Owner == âDuctâ :
connected_fitting.append(conn_pipes)
else:
#repeat connected element process:
connected_fitting.append(conn_pipes)
That way it might be able to keep the list structureâŚ
I did try this but obviously i broke it straight away!
any advice!?