Pagina's op IkLeerBIM

vrijdag 30 september 2022

Custom Dynamo Node - RoomsToSolidRepresentation

In mijn IkLeerBIM Dynamo Package zitten enkele Nodes waar ik het over wil hebben. Waarom heb ik ze gemaakt. Wat doen ze. En hoe werken ze. Vandaag RoomsToSolidRepresentation.




Ik ben bezig geweest om met Dynamo een sterk vereenvoudigde representatie te genereren van een gebouw. Dit moet werken in elk stadium van een lopend project. De basis van deze representatie zijn ruimtes. En daarnaast levels die als building storey zijn aangemerkt. Het resultaat is een groep volumes die compleet aaneengesloten een nieuw ‘gebouw’ volume vormen, zonder gaten. 
Zo veel mogelijk een Topologic model zeg maar.


Toepassingen zijn logischerwijs voor allerhande analyses. Hoeveelheden, Energie, daglicht, logistiek etc. Een schematische weergave is in veel gevallen zinnig omdat in een live project vaak te veel en te gedetailleerde informatie zit. Het klinkt een beetje tegenstrijdig. Maar te veel info maakt een snelle analyse vaak traag en soms zelfs onmogelijk. Ik denk dat we in de toekomst soepel heen en weer moeten kunnen van schematisch naar gedetailleerd en terug. En dit proces moet zich meerdere keren kunnen herhalen, voor zover nodig. 

In principe is het plug and play. Maar mogelijk krijg je een onverwacht resultaat bij een snelle test. Vandaar een (uitgebreide) toelichting. šŸ˜‰

Veel van mijn Nodes zijn compleet in Python geschreven. Maar roepen soms nog wel, via Python, enkele Dynamo Nodes op. Dat is bewust. En het zorgt voor mogelijkheden en beperkingen. Als deze native Dynamo Nodes ooit veranderen bijvoorbeeld. Mijn Nodes werken dan ook vanaf Revit 2021.
Waarom dan toch Python? Eigenlijk heel simpel. In Python heb ik meer toegang tot de Revit API. Kan ik efficiƫnter allerlei list voorwaarden inbouwen zodat het script niet meer doet dan nodig. Kan ik gebruik maken van efficiƫnte function aanroepen. Zelfs een counter toevoegen, met afbreek optie. En hoe minder grafisch aanroepen er zijn, hoe sneller een script kan draaien. Nadeel is natuurlijk wel dat het slechter leesbaar is, en daardoor moeilijker aanpasbaar is.

SpaceBoundaryLevel 2 in een IFC

Kan dit ook anders? Zeer zeker! De ‘goede’ oplossing zou zijn om de space boundary level 2 te gebruiken in een IFC. Mogelijk komt er, of vind ik nog, een Dynamo package die dit kan halen uit een IFC. (IFC.js / ifcopenshell ?) Ook weet ik nog niet alle achtergronden van de CalculateSpatialElementGeometry. In mijnscript maak ik gebruik van de zogenaamde ClosedShell van een Room . Hier zou nog een verbeterslag in kunnen zitten.
Een ander punt van verbetering is dat het script alleen werkt in een METRIC omgeving. Op meerdere plekken worden maten opgegeven. En die zijn vooralsnog metrisch. Waarschijnlijk een kleine aanpassing. Maar dit is nog niet doorgevoerd. Het script breekt af in een IMPERIAL project en geeft een melding dat het script alleen werkt in een METRIC project.

een eenvoudig voorbeeld van de werking van RoomsToSolidRepresentation

Laten we stap voor stap eens kijken wat het script doet.

Het script begint met het binnenhalen van de benodigde bibliotheken. Waaronder een progressbar. (bron) Vanaf 75 ruimtes gaat er een progressbar meelopen, en ontstaat er een mogelijkheid om het script voortijdig af te breken. Een ander bijzonderheid is de optie om het script in een soort van debug mode uit te laten voeren. Hiermee kunnen er ook meer tussentijdse resultaten gerapporteerd worden. Vooral handig tijdens het maken of aanpassen van het script dus.
Vervolgens worden variabelen ingesteld. Waaronder een timer. Deze geeft per onderdeel aan hoe lang een handeling heeft geduurd. Dit is belangrijk om achteraf te kunnen vaststellen welke ruimtes meer dan gemiddeld complex bleken te zijn. En mogelijk een vereenvoudiging nodig hebben in Revit zelf. Je moet je realiseren dat sommige Revit Rooms niet 3D gemaakt kunnen worden door Revit en/of Dynamo. Een bijzonder fenomeen waar weinigen bij stil staan. Ik ga daar nu ook niet verder op in.

Een belangrijke variabele is het Document waar het script op moet draaien. Sinds kort is het ook mogelijk het script te draaien op een gelinked model.  De mogelijkheden zijn dan wel iets beperkter. 

De eerst volgende stap is namelijk om enkele ‘room  bounding’ objecten niet meer room  bounding te maken. Het gaat vooralsnog om ceilings en structural columns. Als deze objecten wel room  bounding zijn wordt de Room  geometrie ingewikkelder dan nodig. En room  bounding ceilings hebben we voor deze toepassing ook niet nodig. We willen de geometrie namelijk bepalen op basis van floors, roofs en building storey levels.

Om de 3D geometrie van de rooms goed te krijgen wordt vervolgens gecontroleerd of de ‘Room Volume Computational’ aan staat. En anders wordt deze tijdelijk aan gezet, gevolgd door een regenerate. Het moge duidelijk zijn dat al deze tijdelijke aanpassingen niet in een gelinked model kunnen.

Hierna wordt er een lijst met levels samengesteld. Dit gebeurd op basis op levels die een building storey zijn. En dit gecombineerd met de daadwerkelijke hoogtes van de ruimtes die geplaatst zijn. Met name de hoogste level is een punt van aandacht. Daarmee bepaal je hoe hoog je analytisch model wordt bij eenvoudige ruimtes.  

Ruimtes die meedoen in het script zijn of, alle geplaatste ruimtes Of, een opgegeven lijst met ruimtes. Bij het openen van de custom node zit nog een extra optie verborgen. Verborgen, omdat die optie nog in ontwikkeling is. Hiermee kan je ruimtes uitsluiten op basis van een opgegeven waarde in een opgegeven parameter. Deze optie is zoals gezegd nog in bewerking en zit wat verborgen in de custom node. De bedoeling is dat je bijvoorbeeld buitenruimtes kan wegfilteren. Of anders zou kunnen behandelen

Tot zover alle noodzakelijke voorbereidingen. 

Nu gaat het script echt lopen. Bij meer dan 75 ruimtes verschijnt de progressbar. Via deze progressbar is het script na elke ruimte af te breken. 

Het script maakt op meerdere momenten gebruik van Python functions. Deze hebben een eigen geheugen omgeving, die leeggemaakt wordt bij verlaten van de function. Hierdoor blijft het totale script lekker snel.

het vergroten van de top faces
samen met het geraamte om uitstekende delen te knippen

Per ruimte probeert het script eerst een vergrote polysurface bovenkant te maken. De eerste stap is het pakken van de ClosedShell via de Revit API. Elke face hiervan wordt nagelopen. Eerst wordt er gecontroleerd hoe regelmatig de bovenkant van de ClosedShell is. Als er faces bijzitten die niet helemaal verticaal omhoog staan, zijn er complexe geometrische aanpassingen nodig om de nieuwe ruimte geometrie te maken. Maar in de meeste gevallen is er maar 1 verticaal vlak. En is de transformatie redelijk straight forward. Je hebt dan alleen een Z-waarde nodig. Toch gaat zoals gebruikelijk de meeste aandacht naar het goed afhandelen van de uitzonderingen.

Met de uitzonderingen gaan we nu eerst verder. Van alle faces die enigszins verticaal gericht zijn wordt de buiten contour en eventuele binnen contouren opgeslagen voor later gebruik. 
Voor alle verticale vlakken wordt eerst de snijlijn bepaald van 1 of meer van de andere vlakken. Die snijlijn wordt vervolgens verlengt met een vaste offset maat. Dit geraamte hebben we later weer nodig als knip gereedschap.

Van alle verticale vlakken wordt de buitencontour als closed polycurve vergroot met een offset. Vervolgens wordt er weer een surface van gemaakt. En van alle oude verticale vlakken wordt 1 polysurface gemaakt. Ook dit hebben we later nodig als referentie wanneer we gaan knippen. 
Elke vergroot verticaal vlak wordt nu geknipt met de curves uit het geraamte van net. Op basis van de polysurface weten we welk vlak van de geknipte vlakken bewaard moet worden. Alle goede vlakken worden samengevoegd tot 1 nieuwe polysurface.

Bij deze transformatie wordt de bovenkant van elke ruimte met een vaste maat (500mm) groter gemaakt. In het script zijn nog wat checks ingebouwd om mogelijke uitzonderingen op te vangen. Toch zijn er goed situaties denkbaar waar het niet lukt. Een kegel en bolvorm lijken niet te lukken, omdat de contour niet alles bepalend is voor de vorm. En complexe ruimte vormen waarbij er niet 1 aansluitend topvlak is te definiĆ«ren gaat ook snel fout. (misschien is hier nog een verbetering mogelijk) Ook kunnen ruimtes met minimale sprongen problemen opleveren bij een offset. Daarnaast zijn er situaties denkbaar waarbij de eerste stap wel lukt, maar dat de vorm dusdanig complex is dat er verderop in het script iets niet lukt.  Ik meld deze zaken voor de compleetheid, maar de meeste situaties lukken prima. Mocht deze stap niet lukken, dan vermeld de node bij het report dat de bewuste room niet gelukt is.

een opening IN het gebouw wordt opgevuld
een opening aan de ZIJkant van het gebouw niet..

Nu er per ruimte, of een polysurface bovenvlak is gedefinieerd. Of 1 z-waarde bij een vlakke bovenkant. Kan de rest van geometrie worden gemaakt. Dit gebeurd in een andere Python function. 
Per ruimte wordt de centerboundary opgeroepen via de Revit API. Dit kan bestaan uit 1 of meerdere contouren in elkaar. Het script gebruikt alleen  de buitencontour. Hiermee voorkomen we dat er per ongeluk gaten ontstaan in het gebouw. En blijft het model clean. Nadeel is wel dat een ruimte in een ruimte -zonder een relatie met de buitenste contour- dubbel is. Geen eilandjes maken dus. Voeg eventueel 1 roomboundary toe, tussen de buitencontour van de grote ruimte en de kleine ruimte als 'eiland'.


meerdere topvlakken per ruimte lukt soms net wel en vaak niet
de ClosedShell uit Revit zelf wordt dan gebruikt

hier lukt het net wel maar je ziet nog een stukje contour van de ClosedShell direct uit Revit

Als een ruimte alleen een hoogte heeft krijgt de gevonden contour simpelweg een extrusie via ExtrudeAsSolid. In het andere geval wordt de gevonden contour 5m1 hoger geextrudeerd dan de maximale hoogte van het bovenvlak. Het bovenvlak krijgt vervolgens een dikte . En als solid knipt het de ruimte extrusie in 2 of meer stukken. De onderste wordt bewaard. Voor de zekerheid wordt de gemaakte geometrie gecombineerd met de ruimte geometrie die direct uit Revit komt. Als deze stappen om wat voor redenen niet lukt, wordt geprobeerd om de 3D ruimte (ClosedShell) via de Revit API te gebruiken. In het script is nog een alternatief stukje script te vinden, wat op dit moment is uit gezet. Het resultaat daarvan was niet helemaal naar mijn zin. 


Nu alle ruimtes er zijn als solid. Gaat het script de ruimte solids groeperen per level voor het invullen van wat gaten en eventueel aanpassen van hoge ruimtes. 
Per level groep worden de ruimte solids samengevoegd tot 1 solid. De onderkant van deze solid wordt onderzocht op gaten. De gevonden gaten worden geextrudeerd tot de maximale hoogte van deze level solid. Meestal is dit goed. Maar als er foute ruimte solids zijn, of als de omliggende ruimte solids geen regelmatig bovenvlak hebben, kan dit wel eens verrassende stukken geometrie opleveren. 
De standaard Revit woning van Autodesk bevat bijvoorbeeld een niet ingevuld stukje plattegrond onder een schuin dak. Dit gat wordt uiteindelijk een soort van schoorsteen, met de hoogte van de nok. Een ander onverwacht resultaat levert de standaard Revit school van Autodesk op. Deze school bevat een soort van schachten zonder ruimte die tegen de gevel aanliggen. Omdat deze niet als ‘gat’ worden herkend ontbreken deze. Iets soortgelijk komt ook voor als er veel dubbele wandjes gebruikt worden als ruimtescheiding. Via de logica van dit script zijn dit of gaten die opgevuld moeten worden. Of het zijn instulpingen van de gevel.
De extra solids worden toegevoegd aan het eind van de ruimtelijst. Alsof het een aparte verdieping is. Dit is belangrijk voor vervolgscripts en nodes die de eigenschappen van de ruimtes willen koppelen aan de getransformeerde ruimte solids. Hier komen we de volgende keer op terug als we RoomSolidIntersectionByParameterValue behandelen.


Nu er per level 1 solid is gemaakt, kunnen hoge ruimtes eventueel een correctie krijgen in de vorm van de ruimte. Van boven naar beneden wordt elke ruimte solid weggesneden door de bovenliggende level solids. Dit gebeurd vervolgens nogmaals maar dan voor de level solids zelf. Soms lukt dit splitsen niet. Dit staat dan in de report van de node. 

Tenslotte worden de solids per level gecombineerd tot 1 grote solid. Het hele gebouw zeg maar. Als dit niet lukt staat dit ook in de report van de node. 




Dat was het voor vandaag. Een erg lang stuk, maar het leek nodig. Volgende keer wat meer over een toepassing van deze node samen  met RoomSolidIntersectionByParameterValue. 
Toepassing klinkt altijd goed, maar dit wordt zeker leuk.

Geen opmerkingen:

Populaire berichten

Zoeken in deze blog