Z jednej strony Revit to świetny program do modelowania instalacji HVAC, wod-kan i innych w środowisku 3D i zgodnie z filozofią BIM. To też program dający ogromne możliwości pod względem analizy modelu jako bazy danych. Dodatkowo wykorzystując Dynamo i Pythona możemy bardziej efektywnie przetwarzać dane zawarte w modelu, ale to nadal nie wszystkie możliwości. Możemy bezpośrednio wydawać polecenia korzystając z klas i metod Revit API. Na stronie Revit API znajdziemy kompletną dokumentację programu, która pozwoli nam pracować z programem przy wykorzystaniu kodu.
Korzystanie z kodu Pythona oraz z Revit API różni się od siebie i z reguły nie należy łączyć tych dwóch możliwości w jednym skrypcie. Na przykładzie analizy sieci kanałów wentylacyjnych zaprezentuje Wam te różnice. Do wykorzystania kodu Pythona oraz Revit API wykorzystamy węzły Dynamo, co znacząco ułatwia pracę.
Sytuacja
Analizujemy model instalacji wentylacji, dla której chcemy upewnić się że w żadnym punkcie nie mamy przekroczonej prędkości przepływu powietrza 6 m/s. W przypadku odcinka kanały z wyższą prędkością zwiększymy wysokość o 50 mm.
Dynamo & Python
- Wykorzystamy węzły Dynamo aby uzyskać dostęp do wszystkich kanałów wentylacyjnych umieszczonych w modelu.
- Wyciągniemy wartości dwóch parametrów kanałów: Prędkość oraz Wysokość, ich wartości przekażemy do skryptu Pythona w postaci dwóch list: Velocity oraz Height, dodatkowo do skryptu przekazujemy listę kanałów i przypisujemy ją do listy Ducts.
- W kodzie korzystamy z pętli for aby uzyskać dostęp do każdego z elementów, następnie instrukcją warunkową if sprawdzamy wartość prędkości, w przypadku stwierdzenie prawdziwości warunku, następuje wykonanie instrukcji zwiększenia wartości zmiennej h o 50 oraz przypisanie nowej wysokości do kanału, ThisDuct, dla którego została przekroczona prędkość.
- Jako informacje zwrotne z skryptu przekazywana jest lista, out, kanałów, dla których została przekroczona prędkość oraz nowa lista, out2, wysokości wszystkich kanałów po korekcie.
[code language=”python”]
# Włącz obsługę języka Python i wczytaj bibliotekę DesignScript
import clr
clr.AddReference(„ProtoGeometry”)
from Autodesk.DesignScript.Geometry import *
clr.AddReference(„RevitNodes”)
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
# Wartości wejściowe do tego węzła będą przechowywane w postaci listy w zmiennych IN.
dataEnteringNode = IN
Velocity = IN[0]
Height = IN[1]
Ducts = IN[2]
out = []
out2 = []
# Wstaw kod poniżej tej linii
for v,d,h in zip(Velocity, Ducts, Height ):
if v > 6:
h=h+50
ThisDuct = Revit.Elements.Element.SetParameterByName(d,”Wysokość”,h)
out.append(ThisDuct)
else:
pass
out2.append(h)
# Przypisz dane wyjściowe do zmiennej OUT.
OUT = out, out2
[/code]
Revit API & Python & Dynamo
Tym razem, ten sam efekt uzyskamy wykorzystując Revit API oraz węzły Dynamo.
[code language=”python”]
# Włącz obsługę języka Python i wczytaj bibliotekę DesignScript
import clr
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.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference(„RevitAPI”)
from Autodesk.Revit.DB import *
# Wartości wejściowe do tego węzła będą przechowywane w postaci listy w zmiennych IN.
dataEnteringNode = IN
Velocity = IN[0]
Ducts = UnwrapElement(IN[2])
out = []
# Wstaw kod poniżej tej linii
dut = doc.GetUnits().GetFormatOptions(UnitType.UT_HVAC_DuctSize).DisplayUnits
TransactionManager.Instance.EnsureInTransaction(doc)
for v,d in zip(Velocity, Ducts):
if v > 6:
ThisDuctParam = d.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM)
ThisDuctHeight = ThisDuctParam.AsDouble()
ThisDuctHeightGivenUnit = UnitUtils.ConvertFromInternalUnits(ThisDuctHeight,dut)
ThisDuctHeightGivenUnit = ThisDuctHeightGivenUnit+50
ThisDuctHeightInternelUnit = UnitUtils.ConvertToInternalUnits(ThisDuctHeightGivenUnit,dut)
ThisDuctSet= ThisDuctParam.Set(ThisDuctHeightInternelUnit)
out.append(ThisDuctHeightGivenUnit)
else:
pass
TransactionManager.Instance.TransactionTaskDone()
# Przypisz dane wyjściowe do zmiennej OUT.
OUT = out
[/code]
- Wykorzystamy węzły Dynamo aby uzyskać dostęp do wszystkich kanałów wentylacyjnych umieszczonych w modelu.
- Wyciągniemy wartości parametru: Prędkość oraz przekażemy do skryptu w postaci listy: Velocity, dodatkowo do skryptu przekazujemy listę kanałów i przypisujemy ją do listy Ducts. W tym miejscu musimy skorzystać z metody UnwrapElement(). Wykorzystujemy to polecenie w celu “rozpakowania” zawartości obiektów kanał wentylacyjny w naszym skrypcie.
- Następnie do zmiennej dut (skrót od: DisplayUnitType), przypisujemy informację o jednostkach jakie są stosowane w modelu do określenia wielkości kanałów wentylacyjnych.
- Wykorzystując TransactionManager łączymy nasz skrypt w Dynamo z środowiskiem Revit’a.
- Korzystamy z pętli for aby uzyskać dostęp do każdego z elementów w listach Ducts oraz Velocity. W momencie stwierdzenia prawdy, dla warunku wartości prędkości powyżej 6 m/s, następuje wykonanie instrukcji warunkowej.
- Do zmiennej ThisDuctParam przypisujemy wartość wbudowanej zmiennej Revita, która przechowuje wysokość kanału. Następnie rzutujemy wartość zmiennej, aby uzyskać typ Double.
- Dla Revita wszystkie wielkości są stopami, my jednak do opisu wymiarów kanałów wentylacyjnych korzystamy z milimetrów. W tym miejscu musimy zmienić jednostki ze stóp na milimetry, dodać wartość 50 mm, a następnie przejść z milimetrów na stopy.
- W ostatnim kroku korzystamy z metody Set() aby przypisać nową wysokość kanału. Na zakończenie zamykamy polecenie TransactionManager.
Podsumowanie
Dobrą praktyką jest stosowanie wyłącznie jednej drogi komunikacji z Revitem w danym skrypcie. Oczywiście zdarzają się wyjątki, ale warto to przyjąć jako dobry nawyk. Obie metody pozwalają na ciekawszą i bardziej efektywną pracę z modelem.
Credits:
Icons made by https://www.flaticon.com/
Photo by Dlanor S on Unsplash