#DynamoBIM #Python #Filter #RevitAPI
#AutodeskExpertElite #AutodeskCommunity 
if this article is not in your language, use the Google Translate
widget ⬈ (bottom of page for Mobile version ⬇)
Dans Revit, les filtres de vue permettent de contrôler l'affichage des éléments en fonction de critères spécifiques, facilitant ainsi l'analyse et la gestion des modèles BIM. L'API Revit offre des outils pour automatiser la création et la gestion de ces filtres.
Cet article détaille la mise en place de Filtres de Vue via l’API Revit en utilisant Python (IronPython ou Python.NET), notamment sur la création de règles imbriquées (ET/OU) qui peut s'avérer être un casse-tête.
Voyons quelques exemples,
- Exemple de création d'un filtre simple
import clr
import sys
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
#import net library
from System import Array
from System.Collections.Generic import List, IList, Dictionary
#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
sdkNumber = int(app.VersionNumber)
def get_ParameterId_byName(lst_paraIds, para_name):
dictBip = {ElementId(bip) : bip for bip in System.Enum.GetValues(BuiltInParameter)}
for pId in lst_paraIds:
if doc.GetElement(pId) is not None and doc.GetElement(pId).Name == para_name:
return pId
elif pId in dictBip and DB.LabelUtils.GetLabelFor(dictBip.get(pId)) == para_name:
return pId
else: pass
return ElementId.InvalidElementId
toList = lambda x : x if hasattr(x, '__iter__') else [x]
#Preparing input from dynamo to revit
categories = toList(UnwrapElement(IN[0]))
lstCatIds = List[ElementId]([c.Id for c in categories])
parameter_Name = IN[1]
parameter_value = IN[2]
filter_Name = IN[3]
TransactionManager.Instance.EnsureInTransaction(doc)
lstParameterIds = DB.ParameterFilterUtilities.GetFilterableParametersInCommon(doc,lstCatIds)
#
paraId = get_ParameterId_byName(lstParameterIds, parameter_Name)
if paraId != ElementId.InvalidElementId:
rule = ParameterFilterRuleFactory.CreateEqualsRule(paraId, parameter_value, True)
elementFilter = ElementParameterFilter(rule)
filter = DB.ParameterFilterElement.Create(doc,filter_Name, lstCatIds, elementFilter)
TransactionManager.Instance.TransactionTaskDone()
OUT = paraId
...
Étapes :
-
Récupération des paramètres filtrables communs aux catégories
sélectionnées avec
ParameterFilterUtilities.GetFilterableParametersInCommon()
. -
Recherche de l’ID du paramètre ciblé via la fonction
get_ParameterId_byName()
. -
Création d'une règle de filtrage avec
ParameterFilterRuleFactory.CreateEqualsRule()
. - Génération d'un filtre d’éléments (ElementParameterFilter) appliqué aux catégories définies.
-
Et enfin, on crée un
ParameterFilterElement
et l’ajoute au document actif
- Création d'un filtre avec imbrication de plusieurs règles
...
import clr
import sys
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
#import net library
from System.Collections.Generic import List
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)
#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
def get_Filter_by_name(nameFilter, lstRvt_Categories, parameterName):
"""
Get or create a ParameterFilterElement with the specified name, categories, and parameter name.
Parameters:
nameFilter (str): The name of the filter.
lstRvt_Categories (list): List of Revit categories.
parameterName (str): Name of the parameter.
Returns:
ParameterFilterElement: The created or existing parameter filter element.
"""
# if exist get it
filter_by_Name = System.Predicate[System.Object](lambda x : x.Name == nameFilter)
filter_ = List[Element](FilteredElementCollector(doc).OfClass(ParameterFilterElement)).Find(filter_by_Name)
if filter_ is not None:
return filter_
# else create it
else:
iListBic = List[ElementId]([cat.Id for cat in lstRvt_Categories ])
# search the parametere Element
filterParabyName = System.Predicate[System.Object](lambda x : x.Name == parameterName)
param_elem = List[DB.Element](FilteredElementCollector(doc).OfClass(ParameterElement).WhereElementIsNotElementType()).Find(filterParabyName)
if param_elem is None:
param_elem = List[DB.Element](FilteredElementCollector(doc).OfClass(SharedParameterElement).WhereElementIsNotElementType()).Find(filterParabyName)
if param_elem is not None:
# create 1st filter
#
filterRuleA = ParameterFilterRuleFactory.CreateContainsRule(ElementId(BuiltInParameter.KEYNOTE_PARAM), "IWS-01", False)
filterA = ElementParameterFilter(filterRuleA)
#
# create 2nd filter by multi-rules
subFilterB = List[ElementFilter]()
subrulesB = List[FilterRule]()
subrulesB.Add(FilterCategoryRule(List[ElementId]([lstRvt_Categories[0].Id])))
subrulesB.Add(ParameterFilterRuleFactory.CreateNotContainsRule(param_elem.Id, "Y", False))
subFilterB.Add(ElementParameterFilter(subrulesB))
#
subrulesB = List[FilterRule]()
subrulesB.Add(FilterCategoryRule(List[ElementId]([lstRvt_Categories[1].Id])))
subrulesB.Add(ParameterFilterRuleFactory.CreateContainsRule(param_elem.Id, "Y", False))
subFilterB.Add(ElementParameterFilter(subrulesB))
filterB = LogicalOrFilter(subFilterB)
# compute the main filter
mainFilterAB = LogicalAndFilter(filterA, filterB)
# compute the ParameterFilterElement
filter_ = ParameterFilterElement.Create(doc, nameFilter, iListBic, mainFilterAB)
return filter_
lstRvt_Categories = UnwrapElement(IN[0])
nameFilter = IN[1]
parameterName = IN[2]
#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
OUT = get_Filter_by_name(nameFilter, lstRvt_Categories, parameterName)
TransactionManager.Instance.TransactionTaskDone()
...
Étapes :
- Recherche d'un filtre existant par son nom, à défaut, on en crée un nouveau.
-
Identification du paramètre cible via un
FilteredElementCollector()
surParameterElement
etSharedParameterElement
. -
on définit une première règle avec
CreateContainsRule()
pour filtrer par une valeur spécifique. -
Puis on définit un second filtre avec plusieurs règles imbriquées
(
LogicalOrFilter
etLogicalAndFilter
). -
Et enfin, on génère un
ParameterFilterElement
et l’applique aux catégories définies.
- Un autre exemple en créant un filtre de phases
...
# Import DesignScript and Standard Python libraries
import sys
import clr
import System
from System.Collections.Generic import List
# Import native .NET functions
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
# Import RevitServices (DocumentManager for accessing the current document / TransactionManager for modifications)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
phase_Debut = UnwrapElement(IN[0])
phase_Fin = UnwrapElement(IN[1])
# Get the active view of the document
myView = doc.ActiveView
# Filter names
name_filter_future = "future_phase"
name_filter_current = "current_phase"
# List of element categories for the filter
cat_ids_list = List[ElementId]([ElementId(BuiltInCategory.OST_Walls)])
# Begin the transaction for modifications in the document
TransactionManager.Instance.EnsureInTransaction(doc)
# Get the "Phase Created" parameter (BuiltinParameter.PHASE_CREATED)
pvp = ParameterValueProvider(ElementId(BuiltInParameter.PHASE_CREATED))
# Create the filter for future elements
rule_future = FilterElementIdRule(pvp, FilterNumericGreater(), phase_Fin.Id)
future_filter = ElementParameterFilter(rule_future)
# Delete the existing filter with the same name if it exists
filter_find = System.Predicate[System.Object](lambda x: x.Name == name_filter_future)
filter_ = List[DB.Element](FilteredElementCollector(doc).OfClass(ParameterFilterElement)).Find(filter_find)
if filter_ is not None:
doc.Delete(filter_.Id)
doc.Regenerate()
# Create the filter for future elements in Revit
future_Elem_Filter = ParameterFilterElement.Create(doc, name_filter_future, cat_ids_list, future_filter)
# Create the filter for current elements
rule_start = FilterElementIdRule(pvp, FilterNumericGreaterOrEqual(), phase_Debut.Id)
rule_end = FilterElementIdRule(pvp, FilterNumericLessOrEqual(), phase_Fin.Id)
combined_rules = List[ElementFilter]()
combined_rules.Add(ElementParameterFilter(rule_start))
combined_rules.Add(ElementParameterFilter(rule_end))
current_filter = LogicalAndFilter(combined_rules)
# Delete the existing filter with the same name if it exists
filter_find = System.Predicate[System.Object](lambda x: x.Name == name_filter_current)
filter_ = List[DB.Element](FilteredElementCollector(doc).OfClass(ParameterFilterElement)).Find(filter_find)
if filter_ is not None:
doc.Delete(filter_.Id)
doc.Regenerate()
# Create the filter for current elements in Revit
current_Elem_Filter = ParameterFilterElement.Create(doc, name_filter_current, cat_ids_list, current_filter)
# Add the filters to the view
myView.AddFilter(future_Elem_Filter.Id)
myView.SetFilterVisibility(future_Elem_Filter.Id, 0)
myView.AddFilter(current_Elem_Filter.Id)
# Modify the display settings of the current filter
red = Color(255, 0, 0)
filter_pattern = System.Predicate[System.Object](lambda x: x.GetFillPattern().IsSolidFill)
solidFillPattern = List[DB.Element](FilteredElementCollector(doc).OfClass(FillPatternElement)).Find(filter_pattern)
ovg = OverrideGraphicSettings()
ovg.SetSurfaceForegroundPatternId(solidFillPattern.Id)
ovg.SetSurfaceForegroundPatternColor(red)
myView.SetFilterOverrides(current_Elem_Filter.Id, ovg)
# Finish the transaction
TransactionManager.Instance.TransactionTaskDone()
# Assign the output value
OUT = 0
...
Étapes :
- Récupération des phases de début et de fin sélectionnées.
- on définit des noms pour les filtres : future_phase et current_phase.
-
Récupération le paramètre
PHASE_CREATED
viaParameterValueProvider()
. -
Création une règle
FilterElementIdRule
pour identifier les éléments appartenant à une phase future. - Ensuite, on supprime les filtres existants du document si nécessaire.
-
On regroupe les phases futures et actuelles avec
LogicalAndFilter()
. -
Et finit par ajouter les filtres à la vue active et applique un style
graphique (
OverrideGraphicSettings
) à la phase actuelle.
- Note :
pour inverser une règle, il faut utiliser le constructeur
FilterInverseRule
« Seul un esprit éduqué peut comprendre une pensée différente de la sienne sans devoir l’accepter. » Aristote
0 commentaires:
Enregistrer un commentaire