Selection of the list of coordinates by parameters

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

Edit: You could also argue, that the way to OP is collecting elements from multiple categories, could be handled more elegantly :slight_smile:

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.
sn1

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

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

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