14 déc. 2020
4 déc. 2020
[Dynamo += Python] Un peu de décoration
Cyril décembre 04, 2020 BIM, Décorateur, Dynamo, DynamoBim, IronPython, Python, Revit, RevitAPI No comments
8 nov. 2020
[Dynamo += Python] Ouvrir plusieurs Vues
Cyril novembre 08, 2020 DotNet, Dynamo, DynamoBim, framework .Net, IronPython, Revit, RevitAPI, Vues No comments
19 oct. 2020
29 sept. 2020
[Dynamo += Python] Conversion de Coordonnées
Cyril septembre 29, 2020 BIM, Coordonnées, CPython, Dynamo, DynamoBim, IronPython, RevitAPI 2 comments
Vous avez des coordonnées, vous voulez les convertir vers un autre système de coordonnées, voici quelques exemples...
30 août 2020
[Dynamo+=Python]Rechercher et Filtrer des Éléments (FilteredElementCollector)
Cyril août 30, 2020 Dynamo, DynamoBim, FilteredElementCollector, Filtres, IronPython, Python, PythonNet, ViewRange No comments
La Classe FilteredElementCollector permet de rechercher une collection
d'éléments à l'aide de méthodes et/ou de filtres.
Voici un récapitulatif et quelques exemples sur son utilisation.
28 juil. 2020
[Dynamo += Python] Ajouter ou Modifier un filtre dans une nomenclature
Cyril juillet 28, 2020 Dynamo, DynamoBim, IronPython, Nomenclatures, Python, Revit, RevitAPI No comments
Travailler avec les filtres de nomenclature avec l'API Revit peut s'apparenter à première vue un peu à jeu de piste.
15 juil. 2020
[Dynamo += Python] Moduler vos noeuds Python
27 juin 2020
29 mai 2020
16 mai 2020
6 mai 2020
1 mai 2020
19 avr. 2020
[Dynamo+=Python] Debogage - Printez vos variables
Lorsqu'on développe en Python et qu'on arrive la première fois sous Dynamo, on peut être surpris par l'absence de console quand un on écrit dans un nœud Python.
À ce jour, seule la variable OUT permet d'afficher des données
16 avr. 2020
11 avr. 2020
[Revit] De l'Elec dans Revit 2021 !
Revit 2021 vient de sortir, voici quelques nouveautés intéressantes autour du domaine de l'électricité et plus.
De l'ingénierie électrique au menu dans cette version !
5 avr. 2020
[Revit+Plugin SGP] Export DWG et paramétrage des calques
Lors d'un export DWG, Revit affecte un calque pour chaque Catégorie.
Il est possible de d'ajouter/modifier les noms des calques en passant le modificateur de calque, par exemple en ajoutant le nom du sous projet à une Catégorie, mais...
21 mars 2020
[Revit] AC Consuel Verte + Revit = Quantitatif Facile
Parmi les travaux fastidieux le quantitatif le nombre de circuits 1.5² et 2.5² sur les Attestations Consuel Vertes.
Un ptit filtre sous Revit et c'est terminé en moins de 2 min...
14 mars 2020
[Python] des Infos sur les fichiers Revit sans Revit...
Connaître certaines informations comme la version d'un fichier Revit avant de l'ouvrir peut s'avérer particulièrement utile (Rétrocompatibilité)
#DynamoWin - Création de murs à partir de DWG
Et si un projet réalisé au format DWG n'était plus un obstacle pour commencer l'étude d'exécution sous Revit?
Et si la modélisation du bâtiment sous DialuxEvo (ou de pièces dans Dialux) était généré plus rapidement ? via import de fichier IFC ou STF
5 mars 2020
[Dynamo+=Python] Les Itérables et le Dynamo Wrappeur
- Unwrapping vs Wrapping
Un petit rappel sur la fonction UnwrapElement()
Les éléments dans Dynamo sont exposés par défaut à l'API de Dynamo qui enveloppe l'API de Revit (d'où la notion de wrapp et de wrapped Elements)
Les éléments dans Dynamo sont exposés par défaut à l'API de Dynamo qui enveloppe l'API de Revit (d'où la notion de wrapp et de wrapped Elements)
15 févr. 2020
[Dynamo+=Python] Transfert de Légendes
L'outil d'insertion de vue à partir de fichier de Revit ne permet pas à ce jour de copier des Légendes, mais...
11 févr. 2020
[Dynamo] Les joies du mode Périodique (épisode 1)
Sous Dynamo il existe 3 modes d'exécution :
Automatique : par défaut, les nouvelles définitions Dynamo sont définies pour s'exécuter automatiquement. Cela signifie que le graphique est exécuté par l'ordinateur, chaque fois qu'il y a un changement dans le modèle.
Manuel : le graphique Dynamo ne s'exécutera que lorsque vous appuyez sur ce bouton, ce qui signifie que vous pouvez apporter des modifications sans demander à l'ordinateur de calculer le résultat jusqu'à ce que vous soyez prêt.
C'est celui-ci qui est activé par défaut avec Dynamo Player
Remarque :
Lorsque vous recevez un script que vous (ou votre société) n'avez pas développé il est préférable de l'exécuter dans ce mode à l'ouverture.
Périodique : Dynamo a la possibilité d'exécuter le graphique de manière rythmique, toutes les X millisecondes, avec une fréquence que l'on peut définir. Cette option n'est activée que lorsqu'un nœud du canevas appelle spécifiquement ce type de comportement d'exécution.
Il s'agit du nœud standard (OOTB) DateTime.Now
Les nœuds activés périodiquement sont ceux qui pourraient injecter des informations en constante évolution dans le graphique Dynamo, telles que les données d'un capteur ou d'un microcontrôleur (comme un LeapMotion ou un Raspberry Pi couplé à un capteur) ou encore une GTB.
Sans données d'entrée dynamique, ce mode d'exécution peut également servir pour animer/déplacer des objets dans la maquette ou encore acquérir des données de la maquette toutes les X minutes afin d'auditer cette dernière (par exemple en BIM niveau 3).
Voici un exemple de déplacement périodique d'un objet le long d'une Ligne de Modèle.
Note :
Ici les localisations des instances à T-1 sont sauvegardés (via un index) localement dans un fichier txt (peut être également fait via le module Python Pickle)
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
import sys
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\Lib')
import os
def readidxfile(file):
with open(file, "r") as f:
return int(f.read())
def setidxfile(file, idx):
with open(file, "w") as f:
return f.write(str(idx))
dataEnteringNode = IN
time = IN[0] #input DateTime.Now() node
modelcurve = UnwrapElement(IN[1])
instance = UnwrapElement(IN[2])
pathuser = os.path.expanduser('~')
fullpath = pathuser + "\\Documents\\objb.txt"
try:
oldidx = readidxfile(fullpath)
indx = oldidx + 1
setidxfile(fullpath, indx)
except:
indx = 0
setidxfile(fullpath, str(indx))
#create range
rangeint = range(1,11,1)
#create simple float range
floatrange = [x * 0.1 for x in rangeint]
curveproto = modelcurve.GeometryCurve.ToProtoType()
try:
ptx = curveproto.PointAtParameter(floatrange[indx])
except:
indx = 0
setidxfile(fullpath, indx)
ptx = curveproto.PointAtParameter(floatrange[indx])
TransactionManager.Instance.EnsureInTransaction(doc)
instance.Location.Point = ptx.ToXyz()
TransactionManager.Instance.TransactionTaskDone()
OUT = ptx
github
6 févr. 2020
[Revit] Familles et formules paramétrique 2/2
- Les formules de recherche dans les tables de consultation
Les tables de consultation contiennent des données sur les types, Revit propose une fonction size_lookup qui lit les valeurs nécessaires dans un fichier CSV qui est importé dans la famille.
29 janv. 2020
[Revit] Familles et formules paramétrique 1/2
1. Échapper un caractère spécial contenu dans un nom de paramètre
Il se peut qu'un caractère spécial soit inclut dans le nom d'un paramètre dans ce cas il faut utiliser les crochets [ ]
Exemple :
- Paramètre oui-non : Alim Saillie/Encastrée
- exemple formule associée : if([Alim Saillie/Encastrée], 0 m, 0.035 m)
Note :
Si vous avez pour habitude de "piloter" vos paramètres par programmation, dans la mesure du possible éviter les caractères spéciaux, idem pour les caractères accentués (penser à l'encoding)
2. Les Maths
Concernant l'utilisation de fonctions mathématiques elles sont similaires à ceux que nous pouvons rencontrer en programmation
3. Les Opérateurs et les formules conditionnelles
La structure est similaire à celle que nous pouvons utiliser sous Excel.
- Règle n°1
Le type de paramètre conditionne la formule. Inutile d'essayer de retourner un booléen à un paramètre qui attend une longueur
- Règle n°2
Les unités doivent être compatibles entre elles.
Cependant même si elles sont compatibles, attention tout de même à ne pas additionner n'importe quoi ...
Cependant même si elles sont compatibles, attention tout de même à ne pas additionner n'importe quoi ...
Le scandale du théorème de Boucherot |
- Règle n°3
À l'instar d'un appel de fonction suivi d'arguments, les opérateurs se mettent en préfixe suivis de parenthèses englobant la condition et/ou les valeurs.
- Règle n°4
Quand Revit nous envoi booler... |
Pour les tests logiques les opérateurs supportés sont:
Opérateur Logique | Description | |
---|---|---|
< | strictement inférieur | |
> | strictement supérieur | |
= | égal | |
and | retourne Vrai si toutes les valeurs sont Vrai | |
or | retourne Vrai si une des valeurs est Vrai | |
not | retourne l'inverse de la valeur booléenne (ou du résultat de l'évaluation booléenne) | |
not(a > b) | équivalent à : a <= b | |
not(a < b) | équivalent à : a >= b |
Utilisation de l'Opérateur AND
Exemple:
x = 5
y = 4
and(x = 5, y = 5) retourne Faux (False)
Utilisation de l'Opérateur OR
Exemple :
x = 5
y = 4
or(x = 5, y = 5) retourne Vrai (True)
Utilisation de l'Opérateur NOT
Exemple :
x = 5
not(x = 6) retourne Vrai (True), x = 6 étant Faux
x = 5
not(x = 6) retourne Vrai (True), x = 6 étant Faux
4. Les Syntaxes des Formules
- La syntaxe de base est la suivante :
if (test logique, valeurA si vrai, valeurB si fausse) | retourne valeurA ou valeurB |
- Test logique avec AND
if (and(LongA = 10, LongB = 10), valeurA, valeurB) | - retourne valeurA ou valeurB - Paramètre de Type Longueur |
L'équivalent Pseudo-Code à titre de comparaison
SI LongA = 10 ET LongB = 10:
retourne valeurA
SINON:
retourne valeurB
- Test logique avec OR
if (or(LongA = 10, LongB = 10), valeurA , valeurB ) | - retourne valeurA ou valeurB - Paramètre de Type Longueur |
Pseudo-Code
SI LongA = 10 OU LongB = 10:
retourne valeurA
SINON:
retourne valeurB
- Test logique avec multiple conditions
if (test logique1, valeurA si vrai, (test logique2 si faux, valeurB si vrai, valeurC si vrai)) | retourne valeurA ou valeurB ou valeurC |
Prenons pour l'exemple 3 paramètres de longueur, nous cherchons à retourner la valeur max dans un nouveau paramètre "MaxLong:
LongA = 50
LongB = 40
LongC = 30
Pour simplifier la compréhension commençons par l’équivalent avec un Pseudo-Code
Pseudo-Code
l'expression sous Revit devient la suivante :
On peut comme cela imbriquer autant de conditions que nécessaire...dans la limite du raisonnable
SI LongA > LongB and LongA > LongC:
MaxLong = LongA
SINON SI LongB > LongA and LongB > LongC:
MaxLong = LongB
SINON:
MaxLong = LongC
l'expression sous Revit devient la suivante :
if (and(LongA > LongB, LongA > LongC), LongA , if(and(LongB > LongA, LongB > LongC), LongB, LongC )) | - retourne LongA ou LongB ou LongC - Paramètre de Type Longueur |
On peut comme cela imbriquer autant de conditions que nécessaire...dans la limite du raisonnable
Moralité (ou conseil): si vous n'êtes pas à l'aise avec les formules Revit commencer par écrire la formule sous forme Pythonesque ou Pseudo-Code ou autre
À suivre les formules de recherche dans les tables de consultation...
À suivre les formules de recherche dans les tables de consultation...
10 janv. 2020
[Revit] Interopérabilité Excel
Cyril janvier 10, 2020 Autocad, BIM, DotNet, DynamoBim, Excel, IronPython, PreviewImage, RevitAPI No comments
Analyses, modifications, import de données, transfert vers une application tierce, transmissions de quantitatifs, etc..., dans l'écosystème du BIM, l'utilisation d'Excel devient incontournable.
Le plus souvent la nécessité d'exporter vers Excel provient des Nomenclatures, plusieurs méthodes pour y parvenir.
- Avec l'export natif de Revit
Après export de rapport de nomenclatures au format texte avec choix du délimiteur, il suffit de d'importer le fichier txt en tant que données depuis Excel ou de changer directement l'extension "txt" en "csv" puis de l'ouvrir avec Excel.
- Avec des Add-Ins
Ce n'est pas le choix qui manque, exemple sur l'AutodeskAppStore
voici mes préférés (gratuit) :- Import/Export Excel de BIM One (export - import de nomenclatures, modification possible des paramètres d’Occurrence)
- SheetLink de Diroots (export - import de nomenclatures et bien plus, modification possible des paramètres d’Occurrence et de Type avec précautions)
- Avec Dynamo
- avec ses 2 nœuds natifs
- Par programmation avec les API(s)
- Pour des besoins très spécifiques, on peut également personnaliser ses propres exports avec les API de Revit et de Microsoft, par exemple pour exporter des données spécifiques ou pour personnaliser la mise en page des données sur Excel.
Pour rappel les nomenclatures sont des vues... on peut donc parcourir les éléments via la méthode
FilteredElementCollector Ici les données sont stockées dans un Array puis transférées dans un Range via la variable Value2 (sauf pour les couleurs de cellules 😕...y'en a qui ont essayé ils ont eu des problèmes 😅... bref, obligé de passer une boucle)
Plus d'informations ici
# Copyright (c) 20119- POUPIN.C
import clr
import re
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
app = DocumentManager.Instance.CurrentUIApplication.Application
clr.AddReference('System.Drawing')
from System import Array
from System.Drawing import *
clr.AddReferenceByName('Microsoft.Office.Interop.Excel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c')
from Microsoft.Office.Interop import Excel
from System.Runtime.InteropServices import Marshal
import sys
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\Lib')
import os
class ParameterProp():
def __init__(self, para):
self._para = para
self._pname = para.Definition.Name
self._pisinstance = para.IsInstance
class FamiliesCheck():
def __init__(self, dirpath):
self.dirpath = dirpath
self.full_lstP = []
for dir, subdir, files in os.walk(dirpath):
for file in files:
if file.endswith(".rfa") and re.search(r'\.\d+.rfa$', file) is None and re.search(r'[aA]ncien', dir) is None:
famDoc = app.OpenDocumentFile(dir + '\\' + file)
if famDoc.IsFamilyDocument:
famManager = famDoc.FamilyManager
lst_para = [ ParameterProp(x) for x in famManager.Parameters]
lst_para.sort(key = lambda x : x._pname)
lst_para[0:0] = [file]
self.full_lstP.append(lst_para)
famDoc.Close(False)
def XlsWriter(self):
ex = Excel.ApplicationClass()
ex.Visible = True
ex.DisplayAlerts = False
workbook = ex.Workbooks.Add()
workbook.SaveAs(self.dirpath + "\\reportFamilies.xlsx")
ws = workbook.Worksheets[1]
nbr_row = 1
for sub_lst in self.full_lstP:
nbr_col = len(sub_lst)
xlrange = ws.Range[ws.Cells(nbr_row, 1), ws.Cells(nbr_row, len(sub_lst))]
a = Array.CreateInstance(object, 1, len(sub_lst))
b = Array.CreateInstance(object, 1, len(sub_lst))
for index, i in enumerate(sub_lst):
# if i is string
if isinstance(i, str):
a[0,index] = i
#else i is a ParameterProp objet
else:
a[0,index] = i._pname
if i._pisinstance == False:
b[0,index] = 6
elif i._pisinstance == True:
b[0,index] = 8
else:
b[0,index] = None
#copy Array in range
xlrange.Value2 = a
for cell, color_index in zip(xlrange, b):
cell.Interior.ColorIndex = color_index
nbr_row += 1
used_range = ws.UsedRange
for column in used_range.Columns:
column.AutoFit()
workbook.Save()
dirpath = IN[0]
obj_check = FamiliesCheck(dirpath)
obj_check.XlsWriter()
OUT = obj_check.full_lstP
Aperçu en Vidéo avec quelques lignes supplémentaire
un 2ᵉ exemple ou l'on exporte des preview des familles vers Excel
(avec les méthodes Clipboard et Paste )
# coding: utf-8
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = uiapp.ActiveUIDocument
import System
from System import Environment
from System import Array
from System.Collections.Generic import *
clr.AddReference('System.Drawing')
import System.Drawing
from System.Drawing import *
clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import Clipboard
clr.AddReferenceByName('Microsoft.Office.Interop.Excel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' )
from Microsoft.Office.Interop import Excel
from System.Runtime.InteropServices import Marshal
class ExcelUtils():
def __init__(self, expSettings, filepath, sizebitmap):
self.expSettings = expSettings
self.filepath = filepath
self.sizebitmap = sizebitmap
print self.filepath
def exportXls(self):
ex = Excel.ApplicationClass()
ex.Visible = True
ex.DisplayAlerts = False
workbook = ex.Workbooks.Add()
workbook.SaveAs(self.filepath)
ws = workbook.Worksheets[1]
nbr_row = len(self.expSettings)
nbr_colum = len(self.expSettings[0])
#
xlrange = ws.Range[ws.Cells(1, 2), ws.Cells(nbr_row, nbr_colum )]
xlrange.EntireRow.RowHeight = self.sizebitmap.Height
ws.Range("a1").EntireColumn.ColumnWidth = self.sizebitmap.Width / 4
a = Array.CreateInstance(object, nbr_row, nbr_colum - 1)
#
for indexR, row in enumerate(self.expSettings):
for indexC , value in enumerate(row):
if indexC == 0 and value is not None:
Clipboard.SetDataObject(value)
rng = ws.Range[ws.Cells(indexR + 1, 1), ws.Cells(indexR + 1 , 1)]
ws.Paste(rng, False)
else:
a[indexR, indexC - 1] = value
#copy Array in range
xlrange.Value2 = a
used_range = ws.UsedRange
for column in used_range.Columns:
column.AutoFit()
toList = lambda x : x if hasattr(x, '__iter__') else [x]
listcat = toList(UnwrapElement(IN[0]))
#make filter
lstbipCat = [System.Enum.ToObject(BuiltInCategory, x.Id.IntegerValue) for x in listcat]
filtercat = ElementMulticategoryFilter(List[BuiltInCategory](lstbipCat))
#collector
fecSymb = FilteredElementCollector(doc).WherePasses(filtercat).WhereElementIsElementType().ToElements()
outdata = []
imgSize = Size( 100, 100 )
for symb in fecSymb:
bitm = symb.GetPreviewImage(imgSize)
famName = symb.Family.Name
symbName = Element.Name.GetValue(symb)
outdata.append([bitm, famName, symbName])
#define folder to export
directory = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
objXls = ExcelUtils(outdata, directory + '\\test.xls', imgSize)
objXls.exportXls()
OUT = directory
Bonne Année et Meilleurs vœux
Translate
I like Coffee
Rechercher dans ce blog
Blog Archive
Categories
DynamoBim
Python
IronPython
Revit
RevitAPI
Dynamo
CPython3
PythonNet
BIM
CPython
AutodeskExpertElite
DataFrame
DotNet
Revit API
DynamoDS API
DynamoWin
Famille
IFC
Pandas
Algorithme
Autocad
Catégorie
DataTable
DesignReview
Excel
Nomenclatures
Vecteurs
contextManager
framework .Net
ACC
APS
BIM360
Calque
Chemins de Câble
DWFx
DWG
DataSet
Design Review
DoEvents
Décorateur
Euroclasses
Formules
Geometry
Handler
HorsSujetBIM
IA
IfcOpenShell
IronPython2
IronPython3
Lacing
NFC 15-100
OLE
OpenAI
PLINQ
Package
Paramètres de Projet
PeriodicMode
Produit Vectoriel
Revit & Sélections
Selection
WPF
WinForm
logger
logging
module
olefile
scipy
+=
.Net
.Net 8
.Net API Inheritance
.Net Interface
2024
2025
3DView
AVF
Annotations
Assembly
Attestation de Conformité Verte
Audio
Autodesk.Revit.DB.Analysis
AverageCurve
Barre de Progression
BeautifulSoup
Bilan de Puissance
Bitmap
BrowserOrganization
Cables
Canalisation
Chemin de cable
Chute de tension
Class
Classe
Collaboration
Coller
Commandes Vocales
Construction
Consuel
Coordonnées
Copier
Coupe
Courbe
CropBox
Curve
DBSCAN
DataGrid
Deep Learning
Dialux
Dialux Evo
DynamoCore
ERP
Eclairement
ElementType.Name
Espace de Nom
Event
Export
FacingOrientation
Fenetre
FilteredElementCollector
Filtres
Fittting
GC.Collect
GetBoundaryFaceInfo
Graham
Géométrie
HTML
HTTP request
Hachures
HandOrientation
HelixToolKit
HostFace
IRVE
ImportInstance
Incendie
Interfaces
IsInside
Json
Keras
Linq
Liste
Listes
Listes imbriquées
Légendes
MVVM
Macro
Mandelbrot
Memory
Microsoft
Model Checker
Namespace
Net Core
Nomenclature
Ouverture
Parralelisme
Point
Points
Polygon
Polyligne
Porte
PowerBi
PreviewImage
Produit Scalaire
Purge
Python Nested List
Python3
RPC
Raccord
Rapport
Reflection
Revit version
SQL
Schedule
Script
Serialization
SharpDevellop
Sorted
SpatialElementGeometryCalculator
Speech Recognition
Surcharge Opérateurs
Tensorflow
Transform
TransientDisplay
UnicodeDecodeError
Utilance
Version
ViewFilter
ViewRange
Visualiseur
Vues
WebRequest
Word
alphashape
bs4
dll
débogage
exception handling
level
list level
matplotlib
mshtml
ndarray
operator
out Parameter
pip
requests
skLearn
sympy
tesseract
timeit
tkinter
visibilité & graphisme
with
xml
Électricité
Articles les plus consultés
-
Un petit rappel pour éviter les maux de têtes quand des éléments ne s'affichent pas ou ne veulent pas changer de couleur sous Revi...
-
1. Échapper un caractère spécial contenu dans un nom de paramètre Il se peut qu'un caractère spécial soit in...
-
Les formules de recherche dans les tables de consultation Les tables de consultation contiennent des données sur les types,...
-
Un petit tour d'horizon des différentes Catégories du Génie Électrique de la hiérarchie de ces éléments La catégorie de famille...
-
La Classe FilteredElementCollector permet de rechercher une collection d'éléments à l'aide de méthodes et...
-
Découverte de la librairie HelixToolKit avec Dynamo #DynamoBIM #Revit #Python #HelixToolkit #WPF #AutodeskExpertElite ...