Torna al Blog
RevitAPIPythonFilteredElementCollectorAutomazione BIM

Raccolta Elementi con FilteredElementCollector — Guida Completa

Paulo Giavoni

Paulo Giavoni

Ingegnere & Specialista BIM

5 gennaio 202610 min read
Raccolta Elementi con FilteredElementCollector — Guida Completa

Introduzione ai Collector di Elementi#

Il FilteredElementCollector è la base di qualsiasi automazione in Revit. Ogni volta che hai bisogno di lavorare con elementi — muri, porte, finestre, viste — devi prima trovarli nel modello. Il collector è lo strumento che lo fa.

Analogia pratica: Immagina il tuo modello Revit come un enorme magazzino. Il FilteredElementCollector è il sistema di ricerca automatizzato che trova esattamente ciò che ti serve, senza dover cercare manualmente.

Questa guida ti mostra 35+ modi diversi di filtrare elementi, dai filtri base (categoria) a quelli avanzati (geometria, parametri, posizione).

Questo è il secondo articolo di una serie in tre parti sullo sviluppo con Revit API:

  1. Primi Passi con l'Automazione BIM
  2. Raccolta Elementi con FilteredElementCollector (questo articolo)
  3. Metodi di Selezione UI

Perché Usare Collector Invece di Selezione Manuale?#

Scenario tipico senza automazione:

  • Apri Revit
  • Selezioni manualmente 50 muri
  • Cambi un parametro su ciascuno
  • Ripeti per ogni piano del progetto

Con un collector:

  • Uno script trova automaticamente tutti i muri che soddisfano criteri precisi
  • Modifica tutti in un'unica operazione
  • Può essere ripetuto istantaneamente su altri progetti

Vantaggi chiave:

  • Precisione — nessun elemento dimenticato
  • Velocità — secondi invece di minuti/ore
  • Riutilizzo — stesso script per progetti diversi
  • Documentazione — il codice documenta esattamente cosa è stato fatto

Librerie e Setup Richiesti#

Prima di iniziare, ogni script Python in Dynamo che usa Revit API deve iniziare con queste righe:

Python
1import clr
2clr.AddReference("RevitAPI")
3from Autodesk.Revit.DB import *
4clr.AddReference('RevitServices')
5from RevitServices.Persistence import DocumentManager
6
7doc = DocumentManager.Instance.CurrentDBDocument

Cosa fa questo codice:

  • clr.AddReference — carica le librerie Revit nel Python
  • from Autodesk.Revit.DB import * — importa tutte le classi Revit API (Wall, Door, FilteredElementCollector, ecc.)
  • DocumentManager — fornisce accesso al file Revit corrente
  • doc — la variabile che userai per accedere al modello

Nota: Copia questo blocco all'inizio di ogni nodo Python Script in Dynamo.


Ottenere Informazioni sull'Applicazione Revit#

Puoi recuperare varie proprietà dell'applicazione Revit usando l'oggetto Application:

Python
1app = doc.Application
2version_info = f"""
3Numero Versione: {app.VersionNumber}
4Nome Versione: {app.VersionName}
5Build Versione: {app.VersionBuild}
6Numero Sub Versione: {app.SubVersionNumber}
7Prodotto: {app.Product}
8Lingua: {app.Language}
9Cartella Dati Utente: {app.CurrentUsersDataFolderPath}
10"""
11print(version_info)

Raccolta delle Categorie del Modello#

Per iniziare a lavorare con gli elementi Revit, è utile comprendere le categorie disponibili:

Python
1from Autodesk.Revit.DB import CategoryType
2
3# Ottieni tutte le categorie
4all_categories = doc.Settings.Categories
5
6# Filtra per categorie del modello
7model_categories = [c for c in all_categories if c.CategoryType == CategoryType.Model]
8
9# Stampa i nomi delle categorie
10for category in model_categories:
11 print(category.Name)

Tipi di Categoria#

Nel Revit API, categorie e tipi sono identificati da valori enumerati. Ecco come lavorare con essi:

Python
1door_category = Category.GetCategory(doc, BuiltInCategory.OST_Doors)
2sub_categories = door_category.SubCategories
3
4print(f"La categoria 'Porte' ha {sub_categories.Size} sottocategorie:")
5for sub_category in sub_categories:
6 print(f"- {sub_category.Name}")

Modifiche in Revit 2022#

Revit 2022 ha introdotto identificatori a 64 bit per le categorie built-in:

Python
1door_category_type_id = Category.GetBuiltInCategoryTypeId(BuiltInCategory.OST_Doors)
2print(f"Il TypeId per la categoria 'Porte' è: {door_category_type_id}")

Filtrare per Classe di Elemento#

Comprendere Classi vs Categorie#

Concetto fondamentale: In Revit API, "Classe" e "Categoria" sono due cose diverse, e la confusione tra le due è l'errore più comune per i principianti.

  • Classe = Il tipo di oggetto nel codice (es: Wall, Floor, FamilyInstance)
  • Categoria = Il gruppo funzionale che vedi nell'interfaccia Revit (es: "Muri", "Pavimenti", "Porte")

Esempio pratico:

  • Una porta è un FamilyInstance (classe) della categoria "Porte" (BuiltInCategory.OST_Doors)
  • Una finestra è un FamilyInstance (classe) della categoria "Finestre" (BuiltInCategory.OST_Windows)
  • Un muro è un Wall (classe) della categoria "Muri" (BuiltInCategory.OST_Walls)

Quando filtrare per classe:

  • Quando vuoi tutti gli elementi di quel tipo di oggetto
  • Per operazioni specifiche al tipo di classe (es: solo Wall ha .Flip())

Quando filtrare per categoria:

  • Quando vuoi distinguere tra oggetti simili (porte vs finestre, entrambi FamilyInstance)
  • Per leggere parametri specifici della categoria

Usando la Scorciatoia OfClass#

Il modo più semplice per filtrare per classe è usare il metodo OfClass:

Python
1# Ottieni tutti i muri (istanze + tipi)
2walls = FilteredElementCollector(doc).OfClass(Wall).ToElements()
3
4# Ottieni solo i tipi di pavimento (non le istanze)
5floor_types = FilteredElementCollector(doc).OfClass(FloorType).ToElements()
6
7# Ottieni tutte le istanze di famiglia (porte, finestre, mobili, ecc.)
8family_instances = FilteredElementCollector(doc).OfClass(FamilyInstance).ToElements()

Cosa significa .ToElements()? Il collector non trova immediatamente tutti gli elementi — li "promette". .ToElements() dice al collector di eseguire effettivamente la ricerca e restituire la lista completa.

Alternative a .ToElements():

  • .FirstElement() — restituisce solo il primo elemento trovato (più veloce)
  • .GetElementCount() — conta gli elementi senza caricarli (molto veloce)
  • .ToElementIds() — restituisce solo gli Id invece degli oggetti completi (leggero)

Principali Classi del Revit API#

Ecco le classi più comunemente usate per il filtraggio:

ClasseDescrizione
WallElementi muro
FloorElementi pavimento
CeilingElementi controsoffitto
FamilyInstanceTutti gli elementi basati su famiglia
LevelElementi livello
GridLinee di griglia
View3DViste 3D
ViewPlanViste di pianta
ViewSectionViste di sezione
ViewSheetTavole
MaterialMateriali
FamilyFamiglie caricate

Filtri Rapidi Essenziali#

I filtri rapidi sono valutati direttamente in memoria senza aprire i dati completi dell'elemento. Questo li rende estremamente veloci — anche su modelli enormi.

Differenza tra Tipi e Istanze#

Concetto cruciale in Revit:

  • Tipo (Type) = Il template riutilizzabile (es: "Porta 90x210cm")
  • Istanza (Instance) = Ogni singola porta fisica posizionata nel modello

Ogni istanza ha un tipo genitore. Cambiare un tipo modifica tutte le sue istanze.

Esempi pratici:

Python
1# SOLO TIPI — Ottieni i template di elementi (es: tipi di muro, tipi di porte)
2types = FilteredElementCollector(doc).WhereElementIsElementType().ToElements()
3
4# SOLO ISTANZE — Ottieni gli elementi fisici posizionati nel modello
5instances = FilteredElementCollector(doc).WhereElementIsNotElementType().ToElements()
6
7# COMBINATI — Ottieni solo le istanze di una categoria specifica
8door_instances = FilteredElementCollector(doc) \
9 .OfCategory(BuiltInCategory.OST_Doors) \
10 .WhereElementIsNotElementType() \
11 .ToElements()

Quando serve questa distinzione:

  • Modificare proprietà del tipo (es: cambiare il materiale di default)
  • Contare quanti elementi fisici ci sono nel modello
  • Leggere parametri di istanza (es: altezza di ogni singola porta)

Filtrare per Categoria#

La categoria è il modo più comune di filtrare — corrisponde a ciò che vedi nell'interfaccia Revit:

Python
1# Ottieni tutte le porte (istanze + tipi)
2doors = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Doors).ToElements()
3
4# Ottieni tutti i muri
5walls = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).ToElements()
6
7# Ottieni tutte le finestre
8windows = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Windows).ToElements()

Nota importante: Le BuiltInCategory sono nomi in inglese anche nella versione italiana di Revit:

  • OST_Doors = Porte
  • OST_Walls = Muri
  • OST_Windows = Finestre
  • OST_Floors = Pavimenti
  • OST_StructuralColumns = Pilastri Strutturali

Lista completa delle BuiltInCategory


Combinare Filtri Rapidi#

Puoi concatenare più filtri per risultati più precisi:

Python
1# Ottieni tutte le istanze di porte (non tipi di porte)
2door_instances = FilteredElementCollector(doc) \
3 .OfCategory(BuiltInCategory.OST_Doors) \
4 .WhereElementIsNotElementType() \
5 .ToElements()
6
7# Ottieni tutti i tipi di muro
8wall_types = FilteredElementCollector(doc) \
9 .OfClass(WallType) \
10 .WhereElementIsElementType() \
11 .ToElements()

Filtrare per Valori dei Parametri#

Una delle funzionalità più potenti è il filtraggio per valori dei parametri:

Python
1from Autodesk.Revit.DB import FilteredElementCollector, BuiltInParameter
2from Autodesk.Revit.DB import ParameterValueProvider, FilterStringRule
3from Autodesk.Revit.DB import FilterStringEquals, ElementParameterFilter
4
5# Crea un provider di valore parametro
6provider = ParameterValueProvider(ElementId(BuiltInParameter.ALL_MODEL_MARK))
7
8# Crea una regola di filtro (elementi dove Contrassegno è uguale a "A1")
9rule = FilterStringRule(provider, FilterStringEquals(), "A1", False)
10
11# Crea e applica il filtro
12param_filter = ElementParameterFilter(rule)
13
14elements = FilteredElementCollector(doc) \
15 .OfCategory(BuiltInCategory.OST_Walls) \
16 .WherePasses(param_filter) \
17 .ToElements()

Filtrare per Livello#

Filtrare elementi associati a un livello specifico:

Python
1# Prima, ottieni il livello per cui vuoi filtrare
2levels = FilteredElementCollector(doc).OfClass(Level).ToElements()
3target_level = None
4
5for level in levels:
6 if level.Name == "Livello 1":
7 target_level = level
8 break
9
10if target_level:
11 # Crea un filtro di livello
12 level_filter = ElementLevelFilter(target_level.Id)
13
14 # Ottieni tutti gli elementi su quel livello
15 elements_on_level = FilteredElementCollector(doc) \
16 .WherePasses(level_filter) \
17 .ToElements()
18
19 print(f"Trovati {len(elements_on_level)} elementi su {target_level.Name}")

Elementi all'interno di una BoundingBox#

Trovare elementi che sono completamente all'interno di una bounding box definita:

Python
1from Autodesk.Revit.DB import BoundingBoxContainsPointFilter, Outline
2
3# Definisci gli angoli della bounding box
4min_point = XYZ(0, 0, 0)
5max_point = XYZ(100, 100, 30) # piedi
6
7# Crea un outline dai punti
8outline = Outline(min_point, max_point)
9
10# Crea il filtro bounding box
11bb_filter = BoundingBoxIsInsideFilter(outline)
12
13# Raccogli elementi dentro la box
14elements_in_box = FilteredElementCollector(doc) \
15 .WherePasses(bb_filter) \
16 .ToElements()
17
18print(f"Trovati {len(elements_in_box)} elementi dentro la bounding box")

Filtri Logici#

Combinare filtri usando operazioni logiche:

Python
1from Autodesk.Revit.DB import LogicalAndFilter, LogicalOrFilter
2
3# Crea filtri individuali per categoria
4wall_filter = ElementCategoryFilter(BuiltInCategory.OST_Walls)
5floor_filter = ElementCategoryFilter(BuiltInCategory.OST_Floors)
6door_filter = ElementCategoryFilter(BuiltInCategory.OST_Doors)
7
8# Combina con logica OR (muri O pavimenti O porte)
9or_filter = LogicalOrFilter([wall_filter, floor_filter, door_filter])
10
11# Ottieni tutti i muri, pavimenti e porte
12combined_elements = FilteredElementCollector(doc) \
13 .WherePasses(or_filter) \
14 .WhereElementIsNotElementType() \
15 .ToElements()
16
17print(f"Trovati {len(combined_elements)} muri, pavimenti e porte")

Filtro di Esclusione#

Creare un filtro che esclude elementi specifici:

Python
1from Autodesk.Revit.DB import ExclusionFilter
2
3# Ottieni gli ID degli elementi da escludere
4elements_to_exclude = [ElementId(12345), ElementId(67890)]
5
6# Crea filtro di esclusione
7exclusion_filter = ExclusionFilter(elements_to_exclude)
8
9# Raccogli tutti i muri eccetto quelli esclusi
10filtered_walls = FilteredElementCollector(doc) \
11 .OfClass(Wall) \
12 .WherePasses(exclusion_filter) \
13 .ToElements()

Filtrare Elementi Visibili nella Vista#

Raccogliere elementi visibili in una vista specifica:

Python
1# Ottieni la vista attiva
2active_view = doc.ActiveView
3
4# Raccogli elementi visibili in questa vista
5visible_elements = FilteredElementCollector(doc, active_view.Id) \
6 .WhereElementIsNotElementType() \
7 .ToElements()
8
9print(f"Trovati {len(visible_elements)} elementi visibili in {active_view.Name}")

Filtri Rapidi vs Filtri Lenti#

Comprendere la differenza è cruciale per le prestazioni:

Filtri Rapidi (Veloci)#

Valutati a livello di elemento senza aprire i dati dell'elemento:

  • OfClass()
  • OfCategory()
  • WhereElementIsElementType()
  • WhereElementIsNotElementType()

Filtri Lenti (Più Potenti)#

Richiedono che i dati dell'elemento siano aperti:

  • ElementParameterFilter
  • BoundingBoxFilter
  • ElementIntersectsFilter

Best Practice: Applica sempre prima i filtri rapidi, poi quelli lenti:

Python
1# BUONO: Filtro rapido prima, poi filtro lento
2elements = FilteredElementCollector(doc) \
3 .OfCategory(BuiltInCategory.OST_Walls) \
4 .WhereElementIsNotElementType() \
5 .WherePasses(slow_filter) \
6 .ToElements()
7
8# CATTIVO: Filtro lento su tutto il database
9elements = FilteredElementCollector(doc) \
10 .WherePasses(slow_filter) \
11 .ToElements()

Best Practice per le Prestazioni#

  1. Usa prima i filtri rapidi — Sono valutati prima che i dati dell'elemento vengano caricati

  2. Limita lo scope — Usa collector specifici per vista quando possibile:

    Python
    1FilteredElementCollector(doc, view.Id)
  3. Usa FirstElement() per risultati singoli:

    Python
    1first_wall = FilteredElementCollector(doc).OfClass(Wall).FirstElement()
  4. Usa GetElementCount() per conteggi:

    Python
    1wall_count = FilteredElementCollector(doc).OfClass(Wall).GetElementCount()
  5. Evita collector ripetuti — Memorizza i risultati in cache quando li riutilizzi:

    Python
    1walls = list(FilteredElementCollector(doc).OfClass(Wall).ToElements())

Prossimi Passi#

Continua il tuo viaggio con Revit API nel prossimo articolo di questa serie:

Share:

Questions or Feedback?

I'd love to hear your thoughts on this article. Reach out directly and let's start a conversation.

Follow me on LinkedIn for more BIM tips and updates