Good day, probably I will have a very stupid question, but the second day in the search ended without results. I have a list of items that need to be ranked according to the coordinates on several lists. I got the coordinates, but with the block If I have any problems. I would be grateful for an example code that solves this problem.
as1 = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_ConduitFitting).WhereElementIsNotElementType().ToElements(), FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_MechanicalEquipment).WhereElementIsNotElementType().ToElements()
as2 = List.Flatten(as1,2)
lk1=[e.Location.Point.ToPoint() for e in as2]
???
Hi @Andrey_Baranov,
I must admit, that I’m not fully aware of what you are after, but is it this, perhaps:
Python:
import clr
#Import the Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
#Import DocumentManager and TransactionManager
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
#Reference the active Document and application
doc = DocumentManager.Instance.CurrentDBDocument
fec = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_ConduitFitting).WhereElementIsNotElementType().ToElements(), FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_CableTrayFitting).WhereElementIsNotElementType().ToElements()
locp = [j.Location.Point for i in fec for j in i]
OUT = locp
1 Like
Note that this will raise an AttributeError if curve-based elements (e.g. Cable Trays and Conduits) are used as their location is a LocationCurve rather than a LocationPoint. This may not be an issue for OP, but I’m also having trouble understanding their question.
1 Like
Yep, that is true. Cheers for the input
Edit: You could also argue, that the way to OP is collecting elements from multiple categories, could be handled more elegantly
This could be used, for instance: https://apidocs.co/apps/revit/2018.2/e43a304a-6931-7492-441c-3cac428f2431.htm
1 Like
Thanks. I passed the stage shown by you, but then I need to filter the list depending on the coordinates and at this point I stood up. I need an example of a coordinate filter code. Something like IF p.Z>xxx:
In my case, there is only a LocationPoint. There will be no other options. The idea of my code is to rank the items according to location.
From the list, I need to select the items highlighted by the blue line. Highlighted in red will go for further processing.I do everything by analogy and I need an example code that filters the list of coordinates.
You can use lambda function to filter the list or there is an easier way to filter by using loop iteration.
You can use the same code as @MartinSpence posted above. And then add this line:
Option1 : new_locp = list(filter(lambda x: (x.z > xxx), locp))
Option2:
new_locp = # Create new empty list
for each in locp:
if each.z > xxx:
new_locp.append(each)
1 Like
Alright! You’re on the right path then :-).
Are you interested in the point Z value, or the actual elements that pass your test?
To get point values that pass the test:
import clr
#Import the Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
#Import DocumentManager and TransactionManager
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
#Reference the active Document and application
doc = DocumentManager.Instance.CurrentDBDocument
fec = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_ConduitFitting).WhereElementIsNotElementType().ToElements(), FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_CableTrayFitting).WhereElementIsNotElementType().ToElements()
locp = [j.Location.Point.Z for i in fec for j in i if j.Location.Point.Z > 30]
OUT = locp
To get the elements which Point Z value pass the test:
import clr
#Import the Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
#Import DocumentManager and TransactionManager
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
#Reference the active Document and application
doc = DocumentManager.Instance.CurrentDBDocument
fec = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_ConduitFitting).WhereElementIsNotElementType().ToElements(), FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_CableTrayFitting).WhereElementIsNotElementType().ToElements()
locp = [j for i in fec for j in i if j.Location.Point.Z > 30]
OUT = locp
1 Like
Here’s another way to do it, that is perhaps a bit more readable.
I’ve also included the use of the ElementMulticategoryFilter i suggested you could use to collect the BuiltInCategories
import clr
#Import the Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
#Import generic collections
clr.AddReference('System')
from System.Collections.Generic import *
#Import DocumentManager and TransactionManager
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
#Reference the active Document and application
doc = DocumentManager.Instance.CurrentDBDocument
bics = List[BuiltInCategory]()
bics.Add(BuiltInCategory.OST_CableTrayFitting)
bics.Add(BuiltInCategory.OST_ConduitFitting)
filter = ElementMulticategoryFilter(bics)
fec = FilteredElementCollector(doc).WherePasses(filter).WhereElementIsNotElementType().ToElements()
locp = []
for i in fec:
for j in i:
if j.Location.Point.Z > 30:
locp.append(j.Location.Point)
OUT = locp
1 Like
Thanks. Your code seems to be the solution to my problem. I’m new to this.
Your last solution to the described problem. But to solve the General problem, I will upgrade the previous code. Many thanks.
No probs, glad to have helped
And you can give an example code to compare two lists of coordinates? Thank you very much! In General, of course, the problem for me turned out to be more complicated.
Feet *304.8
Also, I have to spread the categories on different lists and this is due to both the logic and behavior of the elements.
fec = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_ConduitFitting).WhereElementIsNotElementType().ToElements(), FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_CableTrayFitting).WhereElementIsNotElementType().ToElements()
locp = []
for i in fec:
for j in i:
if j.Location.Point.Z <=43.30708661+0.5 and j.Location.Point.Z >=43.30708661:
locp.append(j.Location.Point)#*304.8)
OUT = locp, fec,1,1
See if this works for you:
import clr
#Import the Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
#Import DocumentManager and TransactionManager
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
#Reference the active Document and application
doc = DocumentManager.Instance.CurrentDBDocument
fec = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_ConduitFitting).WhereElementIsNotElementType().ToElements(), FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_CableTrayFitting).WhereElementIsNotElementType().ToElements()
locp = []
for i in fec:
temp = []
for j in i:
if j.Location.Point.Z <= 43 and j.Location.Point.Z >= 29:
temp.append(UnitUtils.ConvertFromInternalUnits(j.Location.Point.Z, DisplayUnitType.DUT_MILLIMETERS)) #You can use the UnitUtils to handle the conversion
#See here for more info on the class: https://apidocs.co/apps/revit/2018.2/128dd879-fea8-5d7b-1eb2-d64f87753990.htm
locp.append(temp)
#This is one method to compare common values in two lists:
intersection = set(locp[0]).intersection(locp[1])
OUT = intersection #converted value outputted
1 Like
Thanks. Works. Only I need to choose from fec elements that have the same X and Y coordinates in ±xxx