Python leren voor Revit: waar begin je?
Een eerlijk stappenplan, van je eerste regel Python tot je eigen pyRevit-knop. Met echte voorbeeldcode en de fouten die bijna iedereen maakt.
Kort antwoord: begin met gewoon Python, niet met Revit. Leer eerst variabelen, lijsten, loops, keuzes, dictionaries en functies. Leer daarna hoe een Revit-model in elkaar zit (elementen, categorieën, parameters) en schrijf een eerste pyRevit-knop die alleen iets leest. Pas als dat lukt, ga je wijzigen met een transaction. Met tien minuten per dag ben je in ongeveer twaalf weken zover dat je je eigen tools schrijft.
Waarom Python voor Revit?
Revit heeft een uitgebreide programmeerinterface: de Revit-API. Daarmee kun je alles wat je met de muis doet ook in code doen, en vooral: duizend keer achter elkaar zonder fouten. Elementen tellen, parameters in bulk invullen, een model controleren, lijsten exporteren. Precies het saaie werk dat nu uren kost.
Er zijn drie gangbare manieren om die API te gebruiken:
- C# en Visual Studio: de manier voor volwaardige add-ins. Krachtig, maar je moet compileren, en de drempel is hoog.
- Dynamo: visueel programmeren met blokjes. Handig voor geometrie, maar grotere logica wordt snel onoverzichtelijk. In Dynamo kun je ook Python-blokken gebruiken.
- pyRevit: een gratis add-in die Python-scripts als knoppen op het lint van Revit zet. Script opslaan, knop indrukken, klaar. Geen compileren.
Voor wie zelf wil leren automatiseren, is Python met pyRevit de kortste weg van idee naar werkende knop. En wat je leert, gebruik je ook in Dynamo.
Naslag die je erbij wilt houden: de documentatie van pyRevit en de doorzoekbare Revit API-documentatie op revitapidocs.com.
Wat heb je nodig?
Om te leren heb je bijna niets nodig: geen programmeerervaring en geen dure software. Om je scripts later in het echt te draaien heb je nodig:
- Revit op een Windows-pc;
- pyRevit, de gratis opensource-add-in;
- een teksteditor voor code, bijvoorbeeld Visual Studio Code;
- en bij voorkeur RevitLookup, een gratis add-in waarmee je op een element klikt en alle eigenschappen en parameters ziet.
Stap 1: leer eerst gewoon Python
De grootste fout is meteen met de Revit-API beginnen. Dan vecht je met twee dingen tegelijk: de taal én het model. Leer daarom eerst de basis van Python, in deze volgorde:
- variabelen, getallen en tekst (strings);
- lijsten en
for-loops; - keuzes met
if,elifenelse; - dictionaries, om dingen te tellen en te groeperen;
- functies, en later classes en modules.
Vooral dictionaries zijn goud waard. Dit is het patroon dat je in Revit steeds weer gebruikt: optellen per groep.
leidingen = [
{"systeem": "CV Aanvoer", "lengte": 6.0},
{"systeem": "CV Retour", "lengte": 6.0},
{"systeem": "CV Aanvoer", "lengte": 4.5},
]
per_systeem = {}
for leiding in leidingen:
naam = leiding["systeem"]
per_systeem[naam] = per_systeem.get(naam, 0) + leiding["lengte"]
print(per_systeem){'CV Aanvoer': 10.5, 'CV Retour': 6.0}Straks komen de leidingen niet uit een lijstje, maar uit je Revit-model. De rest blijft hetzelfde.
Wat je in het begin kunt overslaan: webframeworks, data-science en bekende bibliotheken als pandas en NumPy. Die werken bovendien niet in de standaard-engine van pyRevit.
Stap 2: snap hoe een Revit-model in elkaar zit
Voor je code schrijft voor Revit, helpt het om het model te zien zoals de API het ziet:
- Alles is een element. Een muur, een leiding, een deur, een aanzicht: allemaal een
Elementmet een eigenElementId. - Elementen horen bij een categorie, zoals muren, deuren of leidingen. In code:
BuiltInCategory.OST_Walls,OST_DoorsofOST_PipeCurves. - Types en exemplaren zijn verschillend. Een wandtype is iets anders dan de muur die je tekent. Daarom zie je vaak
WhereElementIsNotElementType(): alleen de echte exemplaren. - Parameters bevatten de gegevens: lengte, merk, opmerkingen, systeemnaam. Je leest ze met
get_Parameter(...)ofLookupParameter("naam"). - Revit rekent intern in voet. Een lengte van 1 betekent 304,8 mm. Reken om met
UnitUtils.ConvertFromInternalUnits.
Stap 3: je eerste pyRevit-knop
Een pyRevit-knop is gewoon een map met een script.py erin. De mapnamen bepalen waar de knop op het lint komt:
MijnTools.extension/
MijnTools.tab/
Tellen.panel/
TelDeuren.pushbutton/
script.pyVoeg de map MijnTools.extension toe in de instellingen van pyRevit (bij de mappen voor eigen extensies) en kies Reload. Je knop staat nu op het lint; de uitgebreide versie staat in pyRevit installeren en je eerste knop maken. Begin met een script dat alleen iets leest:
from Autodesk.Revit.DB import FilteredElementCollector, BuiltInCategory
doc = __revit__.ActiveUIDocument.Document
deuren = (FilteredElementCollector(doc)
.OfCategory(BuiltInCategory.OST_Doors)
.WhereElementIsNotElementType()
.ToElements())
print("Aantal deuren: {}".format(len(deuren)))Druk op de knop en pyRevit opent een venster met de uitvoer van print(). Lezen kan nooit iets kapotmaken, dus hier kun je naar hartenlust proberen. Alles over het zoeken van elementen staat in de FilteredElementCollector uitgelegd.
Stap 4: iets wijzigen met een transaction
Zodra je iets in het model wilt veranderen, moet dat binnen een transaction. Dat is ook je vangnet: gaat er halverwege iets mis, dan draait Revit alles terug. Met de hulpmodule van pyRevit ziet dat er zo uit:
from pyrevit import revit, DB
leidingen = (DB.FilteredElementCollector(revit.doc)
.OfCategory(DB.BuiltInCategory.OST_PipeCurves)
.WhereElementIsNotElementType())
with revit.Transaction("Leidingen markeren"):
for leiding in leidingen:
opmerking = leiding.get_Parameter(
DB.BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS)
opmerking.Set("Gecontroleerd")Laat je de with-regel weg, dan stopt Revit met de melding Attempt to modify the model outside of transaction. Die ga je zeker een keer zien; zo los je hem op. Meer over lezen en schrijven staat in Revit-parameters lezen en wijzigen.
Stap 5: bundel het in je eigen library
Na een paar knoppen merk je dat je steeds dezelfde stukjes code schrijft. Zet die in een eigen module in de map lib van je extensie. pyRevit maakt die map automatisch vindbaar voor al je knoppen.
from Autodesk.Revit.DB import FilteredElementCollector, UnitUtils, UnitTypeId
def elementen(doc, categorie):
"""Alle exemplaren (geen types) van één categorie."""
return (FilteredElementCollector(doc)
.OfCategory(categorie)
.WhereElementIsNotElementType()
.ToElements())
def naar_mm(waarde):
"""Revit rekent intern in voet; dit geeft millimeters."""
return UnitUtils.ConvertFromInternalUnits(waarde, UnitTypeId.Millimeters)In elke knop schrijf je daarna gewoon from kaslib import elementen, naar_mm. Dat is het begin van je eigen library, en het moment dat je echt tijd begint te winnen.
Zes fouten die bijna iedereen maakt
- Wijzigen buiten een transaction. Elke wijziging hoort in een transaction; anders krijg je de foutmelding uit stap 4.
- Vergeten dat Revit in voet rekent. Een diameter van 0,164 is geen fout, het is ongeveer 50 mm.
- Types en exemplaren door elkaar. Zonder
WhereElementIsNotElementType()tel je de types mee. - Parameters zoeken op hun naam in een Nederlandse Revit.
LookupParameter("Length")zoekt op de naam die je in Revit ziet; in een Nederlandse Revit heet die anders. Voor ingebouwde parameters isget_Parameter(BuiltInParameter...)betrouwbaarder. - f-strings in de standaard-engine. pyRevit gebruikt standaard IronPython 2.7, en dat kent geen f-strings. Gebruik
"{}".format(waarde), of kies de Python 3-engine met#! python3op de eerste regel. - Meteen testen in een echt project. Probeer een nieuw script altijd eerst op een kopie van je model.
Een haalbaar leerschema
Je hoeft geen avonden vrij te maken. Korte, dagelijkse sessies werken beter dan één lange zit per week, omdat je de stof vaker terugziet. Een schema dat werkt:
- Maand 1, Python basis: variabelen, lijsten, loops, keuzes en dictionaries.
- Maand 2, gevorderd: functies, classes, modules, fouten afvangen en bestanden.
- Maand 3, richting Revit: pyRevit, elementen verzamelen, parameters wijzigen en je eigen library.
Met tien minuten per dag, en elke dag even herhalen wat je eerder deed, kom je zo in twaalf weken van je eerste regel code tot je eerste eigen tool.