Etant donné le nombre de version du compilateur, des API Revit, et la diversité des Frameworks disponibles, on se retrouve avec un grand nombre de séquences de code possible pour résoudre un problème. Cet article aborde cette problématique en s’appuyant sur un exemple classique du développement dans Revit : insérer un élément dans le modèle. Pour faire simple, nous avons choisit un objet basique (un élément de mobilier) qui peut s’insérer avec peu de paramètre.
Le code ci-dessous permet d’insérer un symbole “chaise verte” aux coordonnées (10,10). Il s’agit du listing complet pour la version compilateur externe, type Microsoft Visual Studio.
On va s’interresser au code entre les commentaires ‘début’ et ‘fin’ de la récupération du symbole dans le modèle Revit.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.Attributes; namespace Exemple { [TransactionAttribute(TransactionMode.Manual)] public class ExempleLinq : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet) { UIDocument uidoc = commandData.Application.ActiveUIDocument; Document doc = uidoc.Document; // debut récupération d'un symbole de type 'chaise verte' FilteredElementCollector collector = new FilteredElementCollector(doc); ElementClassFilter filter = new ElementClassFilter(typeof(FamilySymbol)); IList elements = collector.WherePasses(filter).WhereElementIsElementType().ToElements(); FamilySymbol familySymbol = null; foreach (Element element in elements) { if (element.Name == "chaise verte") { familySymbol = element as FamilySymbol; break; } } // fin récupération d'un symbole de type 'chaise verte' try { using (Transaction trans = new Transaction(doc, "Exemple")) { trans.Start(); if (!familySymbol.IsActive) { familySymbol.Activate(); } doc.Create.NewFamilyInstance(new XYZ(10, 10, 0), familySymbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural); trans.Commit(); } return Result.Succeeded; } catch (Exception e) { message = e.Message; return Result.Failed; } } } } |
Dans ce code,
- on commence par récupérer tout les entités du document dans une variable que l’on nomme collection.
- on crée un filtre sur les entités de type FamilySymbol, que l’on nomme filter.
- on filtre la collection avec le filtre. A ce stade, on a récupéré toutes les entités qui sont de type FamilySymbol. Mais on ne s’intéresse qu’aux définitions de symbole, pas leurs instances.
- on ajoute donc la méthode .WhereElementIsElementType() en ce sens.
- on précise que l’on veut récupérer des objets de la classe Element.
- on obtient donc une liste d’élément.
- Il ne reste qu’a parcourir la liste afin de sélectionner l’élément qui nous intéresse à travers un test sur le nom.
Dans notre code, si l’élément recherché n’est pas trouvé, le programme va rencontrer une erreur (la variable familySymbol aura la valeur null).
Linq nous permet d’écrire de manière plus convive le code et surtout d’extraire le premier élément répondant au test.
1 2 3 4 5 | FilteredElementCollector collector = new FilteredElementCollector(doc); FamilySymbol familySymbol = collector.OfClass(typeof(FamilySymbol)) .WhereElementIsElementType() .Cast() .First(q => q.Name == "chaise verte"); |
On peut éventuellement réduire encore la syntaxe, en considérant que certaines erreurs ne peuvent survenir, mais ce n’est pas conseillé.
1 2 3 4 | ElementClassFilter filter = new ElementClassFilter(typeof(FamilySymbol)); FilteredElementCollector collector = new FilteredElementCollector(doc); collector.WherePasses(filter); var familySymbol = from elements in collector where elements.Name == "chaise verte" select elements; |
1 2 3 4 | var familySymbol = (from filter in new FilteredElementCollector(doc) .OfClass(typeof(FamilySymbol)) .Cast() where filter.Name == "chaise verte" select f).First(); |
1 2 | FilteredElementCollector collector = new FilteredElementCollector(doc); var familySymbol = collector.Where(q => q is FamilySymbol || (q.Name == "chaise") ); |