Understanding the Isolated Pick Model Elements node

So I’ve seen this amazing code developed by @john_pierson that picks elements of a specified category in the revit model

After some housekeeping i ended in the following code:

import clr
clr.AddReference("RevitAPIUI")
from Autodesk.Revit.UI import *

clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

TaskDialog.Show('Isolated Selection','Pick elements of category, ' + (IN[1].lower()) + '. Press finish to complete.')

sel1 = uidoc.Selection
obt1 = Selection.ObjectType.Element

class CustomISelectionFilter(Selection.ISelectionFilter):
	def __init__(self, nom_categorie):
		self.nom_categorie = nom_categorie
	def AllowElement(self, e):
		if e.Category.Name == self.nom_categorie:
			return True
		else:
			return False
		
el_ref = sel1.PickObjects(obt1, CustomISelectionFilter(IN[1]), 'Pick elements of category, ' + (IN[1].lower()) + ' Press finish to complete.')

typelist = []
for i in el_ref:
	try:
		typelist.append(doc.GetElement(i.ElementId))
	except:
		typelist.apped([])

OUT = typelist

My question is: How exactly the method “AllowElement” from the CustomISelectionFilter class is used on the code.

Thank you all in advance

ISelectionFilter is an interface. Here, he is creating a class CustomISelectionFilter and overriding its AllowElement method to define how it should actually work once it is called. Here is an example from the API documentation written in C#:

public static IList<Element> GetManyRefByRectangle(UIDocument doc)
{
    ReferenceArray ra = new ReferenceArray();
    ISelectionFilter selFilter = new MassSelectionFilter();
    IList<Element> eList = doc.Selection.PickElementsByRectangle(selFilter, 
        "Select multiple faces") as IList<Element>;
    return eList;
}

public class MassSelectionFilter : ISelectionFilter
{
    public bool AllowElement(Element element)
    {
        if (element.Category.Name == "Mass")
        {
            return true;
        }
        return false;
    }

    public bool AllowReference(Reference refer, XYZ point)
    {
        return false;
    }
}

I assume input IN[1] is a category name. When the PickObjects method is called (although you will not explicitly call it in your script), it will use the following condition to determine which element references to actually return:

e.Category.Name == self.nom_categorie

Let’s say that IN[1] is “Electrical Equipment”. If you try to select an element from the Electrical Fixtures category, it would not return False. Even something like this would also be valid:

class CustomISelectionFilter(Selection.ISelectionFilter):
	def __init__(self, noms):
		self.noms = noms
	def AllowElement(self, e):
		if e.Category.Name in self.noms:
			return True
		else:
			return False

IN[1] = ['Electrical Equipment', 'Electrical Fixtures']
el_ref = sel1.PickObjects(obt1, CustomISelectionFilter(IN[1]), 'Pick elements')

Here, the variable noms would now contain a list of strings rather than a single string. If the name of the category is neither Electrical Equipment nor Electrical Fixtures, it would return false.

2 Likes

Thanks for your support @cgartland i understood almost everything of your explanation. But the following phrase i did not:

When the PickObjects method is called (although you will not explicitly call it in your script), it will use the following condition to determine which element references to actually return:

How this condition is automatically verified when the user tries to select an element in revit?