All pages
Powered by GitBook
1 of 4

Loading...

Loading...

Loading...

Loading...

Python

​Język Python to powszechnie używany język programowania, którego popularność ma wiele wspólnego z jego stylem składni. Jest wysoce czytelny, co sprawia, że łatwiej jest się go nauczyć niż wielu innych języków. Język Python obsługuje moduły i pakiety. Można go osadzać w istniejących aplikacjach. Aby uzyskać informacje na temat rozpoczynania korzystania z języka Python, skorzystaj z zasobu „Getting Started” (Pierwsze kroki) na stronie Python.org.

Python i Revit

Python i Revit

Zaprezentowaliśmy, jak używać skryptów w języku Python w dodatku Dynamo. Przyjrzyjmy się teraz połączeniu bibliotek programu Revit w środowisku skryptowym. Za pomocą czterech pierwszych wierszy bloku kodu poniżej zaimportowaliśmy węzły podstawowe dodatku Dynamo i standardowe elementy języka Python. Aby zaimportować węzły programu Revit, elementy programu Revit oraz menedżera dokumentów programu Revit, wystarczy tylko dodać kilka innych wierszy:

Zapewnia to dostęp do interfejsu API programu Revit i obsługę skryptów niestandardowych dla dowolnego zadania programu Revit. Połączenie programowania wizualnego z obsługą skryptów z użyciem interfejsu API programu Revit znacznie usprawnia współpracę i opracowywanie narzędzi. Na przykład menedżer BIM i projektant schematów mogą współpracować na tym samym wykresem. W ramach tej współpracy mogą poprawić projekt i realizację modelu.

Interfejsy API dla konkretnych platform

Zadaniem projektu Dynamo jest poszerzenie zakresu wdrożeń na platformach. W miarę dodawania do wykazu dodatku Dynamo kolejnych programów użytkownicy uzyskują dostęp do interfejsów API dla konkretnych platform ze środowiska obsługi skryptów w języku Python. Mimo że w tej sekcji analizujemy program Revit, przewidujemy przygotowanie w przyszłości kolejnych rozdziałów, które będą zawierać kompleksowe samouczki dotyczące tworzenia skryptów na innych platformach. Ponadto dostępnych jest teraz wiele bibliotek , które można importować do dodatku Dynamo.

Poniższe przykłady ilustrują sposoby implementowania operacji specyficznych dla programu Revit z dodatku Dynamo za pomocą języka Python. Aby zapoznać się z bardziej szczegółowym omówieniem powiązania języka Python z dodatkiem Dynamo i programem Revit, zobacz . Innym przydatnym zasobem dla języka Python i programu Revit jest projekt .

Ćwiczenie 1

Utwórz nowy projekt programu Revit.

Pobierz plik przykładowy, klikając poniższe łącze.

Pełna lista plików przykładowych znajduje się w załączniku.

W tych ćwiczeniach omówimy podstawowe skrypty w języku Python w dodatku Dynamo dla programu Revit. W tym ćwiczeniu zostanie omówione postępowanie z plikami i elementami programu Revit oraz komunikacja między programem Revit i dodatkiem Dynamo.

Jest to oczywista metoda pobierania pozycji doc, uiapp i app pliku programu Revit połączonego z sesją dodatku Dynamo. Programiści, którzy już wcześniej pracowali w interfejsie API programu Revit, mogą zauważyć te elementy na liście obserwowanych. Jeśli te elementy nie wyglądają znajomo, nie ma problemu. W ćwiczeniach poniżej będziemy korzystać z innych przykładów.

W ten sposób importujemy usługi programu Revit i pobieramy dane dokumentów w dodatku Dynamo.

Przyjrzyj się węzłowi Python w dodatku Dynamo. Można również skorzystać z kodu z poniższego materiału:

Ćwiczenie 2

Pobierz plik przykładowy, klikając poniższe łącze.

Pełna lista plików przykładowych znajduje się w załączniku.

W tym ćwiczeniu utworzymy prostą krzywą modelu w programie Revit za pomocą węzła Dynamo w języku Python.

Rozpocznij od utworzenia nowej rodziny brył koncepcyjnych w programie Revit.

Otwórz folder Conceptual Mass i użyj pliku szablonu Metric Mass.rft.

W programie Revit użyj skrótu klawiaturowego un, aby wywołać ustawienia jednostki projektu, a następnie zmień jednostkę długości na metry.

Uruchom dodatek Dynamo i utwórz zestaw węzłów na ilustracji poniżej. Najpierw utworzymy dwa punkty odniesienia w programie Revit z węzłów Dynamo.

  1. Utwórz węzeł Code Block i nadaj mu wartość "0;"

  2. Podłącz tę wartość do węzła ReferencePoint.ByCoordinates dla wejść X, Y i Z.

  3. Utwórz trzy suwaki o zakresach od -100 do 100 i kroku o wartości 1.

Przyjrzyj się węzłowi Python w dodatku Dynamo. Pełny kod podano poniżej.

  1. System.Array: program Revit wymaga jako wejścia szyku systemowego (a nie listy języka Python). To jeden więcej wiersz kodu, ale zwracanie uwagi na typy argumentów ułatwia programowanie w języku Python w programie Revit.

W dodatku Dynamo utworzyliśmy za pomocą języka Python dwa punkty odniesienia z łączącą je linią. W następnym ćwiczeniu rozwiniemy to.

Ćwiczenie 3

Pobierz plik przykładowy, klikając poniższe łącze.

Pełna lista plików przykładowych znajduje się w załączniku.

To ćwiczenie jest proste, ale pozwala wyjaśnić tematy łączenia danych i geometrii z programu Revit do dodatku Dynamo i odwrotnie. Zacznijmy od otwarcia pliku Revit-StructuralFraming.rvt. Po jego otwarciu uruchom dodatek Dynamo i otwórz plik Revit-StructuralFraming.dyn.

Ten plik programu Revit jest tak prosty, jak to tylko możliwe. Dwie krzywe odniesienia: jedna narysowana na poziomie 1, a druga na poziomie 2. Chcemy umieścić te krzywe w dodatku Dynamo i utrzymać aktywne połączenie.

W tym pliku znajduje się zestaw węzłów podłączonych do pięciu wejść węzła w języku Python.

  1. Wybierz węzły elementów modelu: naciśnij przycisk wyboru dla każdego z nich i wybierz odpowiednią krzywą w programie Revit.

  2. Code Block: za pomocą składni 0..1..#x;, połącz suwak liczby całkowitej o zakresie od 0 do 20 z wejściem x. Ta opcja określa liczbę belek do narysowania między dwiema krzywymi.

  3. Typy ram konstrukcyjnych: z menu rozwijanego wybierzemy domyślną belkę W12x26.

Ten kod Python jest nieco gęściejszy, ale komentarze znajdujące się w kodzie oddają to, co się dzieje w tym procesie

W programie Revit mamy szyk belek obejmujący dwie krzywe jako elementy konstrukcyjne. Uwaga: nie jest to realistyczny przykład — elementy konstrukcyjne są używane jako przykład dla natywnych wystąpień programu Revit utworzonych z dodatku Dynamo.

Również w dodatku Dynamo można wyświetlić wyniki. Belki w węźle Watch3D odnoszą się do geometrii przywołanej z elementów programu Revit.

Warto zauważyć, że mamy ciągły proces przekształcania danych ze środowiska programu Revit do środowiska dodatku Dynamo. Podsumowując: oto przebieg tego procesu:

  1. Wybierz element programu Revit

  2. Przekształć element programu Revit w krzywą Dynamo

  3. Podziel krzywą Dynamo na serię punktów Dynamo

  4. Użyj punktów Dynamo między dwiema krzywymi, aby utworzyć linie Dynamo

Może to wydawać się nieco skomplikowane, ale skrypt sprawia, że wystarczy edytować krzywą w programie Revit i ponownie uruchomić solwer (chociaż może być konieczne usunięcie poprzednich belek). Jest to spowodowane faktem, że umieszczamy belki za pomocą języka Python, przez co przerywamy powiązanie węzłów OOTB.

Po zaktualizowaniu krzywych odniesienia w programie Revit uzyskuje się nowy szyk belek.

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import RevitNodes
clr.AddReference("RevitNodes")
import Revit

# Import Revit elements
from Revit.Elements import *

# Import DocumentManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager

import System

Połącz każdy suwak z węzłem ReferencePoint.ByCoordinates.

  • Dodaj węzeł Python do obszaru roboczego, kliknij przycisk „+” na węźle, aby dodać kolejne wejście, i podłącz dwa punkty odniesienia do każdego wejścia. Otwórz węzeł Python.

  • Poziomy: wybierz „Poziom 1”.

  • Utwórz belki programu Revit przez odniesienie do linii Dynamo

  • Wygeneruj wyjściowe powierzchnie Dynamo przez zastosowanie zapytania do geometrii belek programu Revit

  • IronPython
    stronę wiki dodatku Dynamo
    Revit Python Shell
    2KB
    Revit-Doc.dyn
    Open
    10KB
    Revit-ReferenceCurve.dyn
    Open
    3MB
    Revit-StructuralFraming.zip
    archive
    Open
    # Load the Python Standard and DesignScript Libraries
    import sys
    import clr
    
    #Import DocumentManager
    clr.AddReference("RevitServices")
    import RevitServices
    from RevitServices.Persistence import DocumentManager
    
    #Place your code below this line
    doc = DocumentManager.Instance.CurrentDBDocument
    uiapp = DocumentManager.Instance.CurrentUIApplication
    app = uiapp.Application
    
    #Assign your output to the OUT variable
    OUT = [doc,uiapp,app]
    import sys
    import clr
    
    # Import RevitNodes
    clr.AddReference("RevitNodes")
    import Revit
    #Import Revit elements
    from Revit.Elements import *
    import System
    
    #define inputs
    startRefPt = IN[0]
    endRefPt = IN[1]
    
    #define system array to match with required inputs
    refPtArray = System.Array[ReferencePoint]([startRefPt, endRefPt])
    
    #create curve by reference points in Revit
    OUT = CurveByPoints.ByReferencePoints(refPtArray)
    import clr
    #import Dynamo Geometry
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    # Import RevitNodes
    clr.AddReference("RevitNodes")
    import Revit
    # Import Revit elements
    from Revit.Elements import *
    import System
    
    #Query Revit elements and convert them to Dynamo Curves
    crvA=IN[0].Curves[0]
    crvB=IN[1].Curves[0]
    
    #Define input Parameters
    framingType=IN[3]
    designLevel=IN[4]
    
    #Define "out" as a list
    OUT=[]
    
    for val in IN[2]:
    	#Define Dynamo Points on each curve
    	ptA=Curve.PointAtParameter(crvA,val)
    	ptB=Curve.PointAtParameter(crvB,val)
    	#Create Dynamo line
    	beamCrv=Line.ByStartPointEndPoint(ptA,ptB)
    	#create Revit Element from Dynamo Curves
    	beam = StructuralFraming.BeamByCurve(beamCrv,designLevel,framingType)
    	#convert Revit Element into list of Dynamo Surfaces
    	OUT.append(beam.Faces)

    Konfigurowanie własnego szablonu w języku Python

    W dodatku Dynamo 2.0 można określić domyślny szablon (.py extension), który ma być używany podczas otwierania okna języka Python po raz pierwszy. Od dawna proszono o dodanie tej funkcji, ponieważ przyspiesza ona korzystanie z języka Python w dodatku Dynamo. Dzięki możliwości użycia szablonu można przygotować domyślny import gotowy do użycia, gdy chcemy utworzyć skrypt niestandardowy w języku Python.

    Położenie tego szablonu to APPDATA dla instalacji dodatku Dynamo.

    Zwykle jest to ścieżka ( %appdata%\Dynamo\Dynamo Core\{version}\ ).

    Konfigurowanie szablonu

    Aby korzystać z tej funkcji, należy dodać następujący wiersz w pliku DynamoSettings.xml. (Edytuj w Notatniku)

    Część <PythonTemplateFilePath /> można po prostu zastąpić następującą treścią:

    Uwaga: zastąp element CURRENTUSER nazwą użytkownika

    Następnie musimy utworzyć szablon z funkcjami, które mają być wbudowane. W tym przypadku osadźmy powiązane z programem Revit importy i niektóre inne typowe elementy podczas pracy z programem Revit.

    Można rozpocząć od pustego dokumentu Notatnika i wkleić do niego następujący kod:

    Po zakończeniu zapisz ten plik jako PythonTemplate.py w lokalizacji APPDATA.

    Późniejsze zachowanie skryptu w języku Python

    Po zdefiniowaniu szablonu w języku Python dodatek Dynamo będzie go szukać po każdym umieszczeniu węzła w języku Python. Jeśli go nie znajdzie, okno będzie wyglądać jak domyślne okno języka Python.

    Jeśli szablon w języku Python zostanie znaleziony (np. nasz szablon dotyczący programu Revit), zostaną wyświetlone wszystkie domyślne wbudowane elementy.

    Dodatkowe informacje dotyczące tego wspaniałego dodatku (którego autorem jest Radu Gidei) można znaleźć tutaj. https://github.com/DynamoDS/Dynamo/pull/8122

    <PythonTemplateFilePath>
    <string>C:\Users\CURRENTUSER\AppData\Roaming\Dynamo\Dynamo Core\2.0\PythonTemplate.py</string>
    </PythonTemplateFilePath>
    import clr
    
    clr.AddReference('RevitAPI')
    from Autodesk.Revit.DB import *
    from Autodesk.Revit.DB.Structure import *
    
    clr.AddReference('RevitAPIUI')
    from Autodesk.Revit.UI import *
    
    clr.AddReference('System')
    from System.Collections.Generic import List
    
    clr.AddReference('RevitNodes')
    import Revit
    clr.ImportExtensions(Revit.GeometryConversion)
    clr.ImportExtensions(Revit.Elements)
    
    clr.AddReference('RevitServices')
    import RevitServices
    from RevitServices.Persistence import DocumentManager
    from RevitServices.Transactions import TransactionManager
    
    doc = DocumentManager.Instance.CurrentDBDocument
    uidoc=DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
    
    #Preparing input from dynamo to revit
    element = UnwrapElement(IN[0])
    
    #Do some action in a Transaction
    TransactionManager.Instance.EnsureInTransaction(doc)
    
    TransactionManager.Instance.TransactionTaskDone()
    
    OUT = element

    Węzły języka Python

    Dlaczego w środowisku programowania wizualnego Dynamo warto używać programowania tekstowego? Programowanie wizualne ma wiele zalet. Umożliwia tworzenie programów bez konieczności poznawania specjalnej składni w intuicyjnym interfejsie wizualnym. Jednak program wizualny może z czasem zawierać zbyt wiele elementów i nie działać zgodnie z założeniami. Na przykład język Python oferuje znacznie więcej dostępnych metod pisania instrukcji warunkowych (jeśli/to) i zapętlania. Język Python jest zaawansowanym narzędziem, które umożliwia rozszerzenie możliwości dodatku Dynamo i zastąpienie wielu węzłów kilkoma zwięzłymi liniami kodu.

    Program wizualny:

    Program tekstowy:

    Węzeł w języku Python

    Podobnie jak bloki kodu węzły języka Python są interfejsem skryptowym w środowisku programowania wizualnego. Węzeł Python można znaleźć w bibliotece w obszarze Skrypt>Edytor>Skrypt w języku Python.

    Dwukrotne kliknięcie węzła powoduje otwarcie edytora skryptów języka Python (można również kliknąć prawym przyciskiem myszy węzeł i wybrać polecenie Edytuj). Na górze jest wyświetlany tekst wstępny, który ma ułatwić odnoszenie się do potrzebnych bibliotek. Dane wejściowe są przechowywane w szyku IN. Wartości są zwracane do dodatku Dynamo przez przypisanie ich do zmiennej OUT

    Biblioteka Autodesk.DesignScript.Geometry umożliwia używanie zapisu kropkowego podobnego do bloków kodu (Code Block). Aby uzyskać więcej informacji na temat składni dodatku Dynamo, zapoznaj się z materiałem oraz . (Aby pobrać ten dokument PDF, kliknij prawym przyciskiem myszy łącze i wybierz opcję „Zapisz łącze jako...”). Wpisanie typu geometrii, takiego jak „Point.”, spowoduje pojawienie się listy metod tworzenia punktów i stosowania do nich zapytań.

    Metody obejmują konstruktory, takie jak ByCoordinates, akcje, takie jak Add, oraz zapytania, takie jak współrzędne X, Y i Z.

    Ćwiczenie: węzeł niestandardowy ze skryptem w języku Python do tworzenia wzorów z modułu bryłowego

    Część I. Konfigurowanie skryptu w języku Python

    Pobierz plik przykładowy, klikając poniższe łącze.

    Pełna lista plików przykładowych znajduje się w załączniku.

    W tym przykładzie napiszemy skrypt w języku Python, który tworzy wzorce z modułu bryłowego, i zmienimy go w węzeł niestandardowy. Najpierw utworzymy moduł bryłowy za pomocą węzłów Dynamo.

    1. Rectangle.ByWidthLength: utwórz prostokąt, który będzie podstawą bryły.

    2. Surface.ByPatch: połącz prostokąt z wejściem „closedCurve”, aby utworzyć dolną powierzchnię.

    1. Geometry.Translate: połącz prostokąt z wejściem „geometry”, aby przesunąć go w górę, używając węzła Code Block do określenia grubości bazowej bryły.

    2. Polygon.Points: zastosuj zapytanie do przekształconego prostokąta w celu wyodrębnienia punktów narożnych.

    3. Geometry.Translate: użyj węzła Code Block, aby utworzyć listę czterech wartości odpowiadających czterem punktom, przekształcając jeden narożnik bryły w górę.

    Teraz gdy mamy górną i dolną powierzchnię, wyciągnijmy między dwoma profilami, aby utworzyć boki bryły.

    1. List.Create: połącz dolny prostokąt i górny wielobok z wejściami indeksu.

    2. Surface.ByLoft: wyciągnij dwa profile w celu utworzenia boków bryły.

    3. List.Create: połącz górną, boczną i dolną powierzchnię z wejściami indeksu, aby utworzyć listę powierzchni.

    Po uzyskaniu bryły upuść węzeł skryptu w języku Python w obszarze roboczym.

    1. Aby dodać kolejne wejścia do węzła, kliknij ikonę „+” na węźle. Nazwy wejść to IN[0], IN[1] itd., aby wskazać, że reprezentują one elementy na liście.

    Zacznijmy od zdefiniowania wejść i wyjść. Kliknij dwukrotnie węzeł, aby otworzyć edytor języka Python. Zmodyfikuj kod w edytorze na podstawie poniższego kodu.

    Ten kod będzie bardziej przejrzysty w trakcie dalszej analizy tego ćwiczenia. Następnie należy zastanowić się, jakie informacje są wymagane, aby ułożyć moduł bryłowy w szyku. Najpierw musimy znać wymiary bryły, aby określić odległość przekształcenia. Z powodu błędu ramki ograniczającej należy użyć geometrii krzywej krawędzi, aby utworzyć ramkę ograniczającą.

    Przyjrzyj się węzłowi Python w dodatku Dynamo. Zauważ, że używamy tej samej składni, która jest używana w węzłach w dodatku Dynamo. Zapoznaj się z poniższym skomentowanym kodem.

    Ponieważ będziemy zarówno przekształcać, jak i obracać moduły brył, użyjmy operacji Geometry.Transform. Z węzła Geometry.Transform wynika, że będziemy potrzebować źródłowego układu współrzędnych i docelowego układu współrzędnych do przekształcenia bryły. Źródłem jest kontekstowy układ współrzędnych bryły, natomiast elementem docelowym będzie inny układ współrzędnych dla każdego modułu ustawionego w szyku. Oznacza to, że należy utworzyć pętlę przez wartości x i y, aby przekształcić układ współrzędnych za każdym razem w inny sposób.

    Kliknij przycisk Uruchom, a następnie Zapisz kod. Połącz węzeł w języku Python z istniejącym skryptem w następujący sposób.

    1. Połącz dane wyjściowe z węzła Solid.ByJoinedSurfaces z pierwszym wejściem węzła Python i użyj węzła Code Block, aby zdefiniować pozostałe wejścia.

    2. Utwórz węzeł Topology.Edges i użyj danych wyjściowych z węzła Python jako jego danych wejściowych.

    3. Na koniec utwórz węzeł Edge.CurveGeometry i użyj danych wyjściowych z węzła Topology.Edges jako jego danych wejściowych.

    Spróbuj zmienić wartość źródłową, aby utworzyć różne wzorce. Można również zmienić parametry samego modułu bryły w celu uzyskania różnych efektów.

    Część II. Przekształcanie węzła skryptu w języku Python w węzeł niestandardowy

    Teraz po utworzeniu przydatnego skryptu w języku Python zapiszemy go jako węzeł niestandardowy. Wybierz węzeł skryptu w języku Python, kliknij prawym przyciskiem myszy obszar roboczy i wybierz opcję „Utwórz węzeł niestandardowy”.

    Przypisz nazwę, opis i kategorię.

    Spowoduje to otwarcie nowego obszaru roboczego, w którym będzie edytowany węzeł niestandardowy.

    1. Wejścia Input: zmień nazwy wejść na bardziej opisowe i dodaj typy danych oraz wartości domyślne.

    2. Wyjście Output: zmień nazwę węzła danych wyjściowych

    Zapisz węzeł jako plik .dyf. Węzeł niestandardowy powinien odzwierciedlać wprowadzone zmiany.

    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    
    solid = IN[0]
    seed = IN[1]
    xCount = IN[2]
    yCount = IN[3]
    
    solids = []
    
    yDist = solid.BoundingBox.MaxPoint.Y-solid.BoundingBox.MinPoint.Y
    xDist = solid.BoundingBox.MaxPoint.X-solid.BoundingBox.MinPoint.X
    
    for i in xRange:
    	for j in yRange:
    		fromCoord = solid.ContextCoordinateSystem
    		toCoord = fromCoord.Rotate(solid.ContextCoordinateSystem.Origin,Vector.ByCoordinates(0,0,1),(90*(i+j%val)))
    		vec = Vector.ByCoordinates((xDist*i),(yDist*j),0)
    		toCoord = toCoord.Translate(vec)
    		solids.append(solid.Transform(fromCoord,toCoord))
    
    OUT = solids

    Polygon.ByPoints: użyj przekształconych punktów, aby odtworzyć górny wielobok.

  • Surface.ByPatch: połącz wielobok, aby utworzyć górną powierzchnię.

  • Solid.ByJoinedSurfaces: połącz powierzchnie, aby utworzyć moduł bryły.

    https://github.com/DynamoDS/DynamoPrimerNew/blob/master-plk/coding-in-dynamo/7_code-blocks-and-design-script/7-2_design-script-syntax.md
    Przewodnikiem języka DesignScript
    35KB
    Python_Custom-Node.dyn
    Open
    # Load the Python Standard and DesignScript Libraries
    import sys
    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    
    # The inputs to this node will be stored as a list in the IN variables.
    #The solid module to be arrayed
    solid = IN[0]
    
    #A Number that determines which rotation pattern to use
    seed = IN[1]
    
    #The number of solids to array in the X and Y axes
    xCount = IN[2]
    yCount = IN[3]
    
    #Create an empty list for the arrayed solids
    solids = []
    
    # Place your code below this line
    
    
    # Assign your output to the OUT variable.
    OUT = solids
    # Load the Python Standard and DesignScript Libraries
    import sys
    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    
    # The inputs to this node will be stored as a list in the IN variables.
    #The solid module to be arrayed
    solid = IN[0]
    
    #A Number that determines which rotation pattern to use
    seed = IN[1]
    
    #The number of solids to array in the X and Y axes
    xCount = IN[2]
    yCount = IN[3]
    
    #Create an empty list for the arrayed solids
    solids = []
    #Create an empty list for the edge curves
    crvs = []
    
    # Place your code below this line
    #Loop through edges an append corresponding curve geometry to the list
    for edge in solid.Edges:
        crvs.append(edge.CurveGeometry)
    
    #Get the bounding box of the curves
    bbox = BoundingBox.ByGeometry(crvs)
    
    #Get the x and y translation distance based on the bounding box
    yDist = bbox.MaxPoint.Y-bbox.MinPoint.Y
    xDist = bbox.MaxPoint.X-bbox.MinPoint.X
    
    # Assign your output to the OUT variable.
    OUT = solids
    # Load the Python Standard and DesignScript Libraries
    import sys
    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    
    # The inputs to this node will be stored as a list in the IN variables.
    #The solid module to be arrayed
    solid = IN[0]
    
    #A Number that determines which rotation pattern to use
    seed = IN[1]
    
    #The number of solids to array in the X and Y axes
    xCount = IN[2]
    yCount = IN[3]
    
    #Create an empty list for the arrayed solids
    solids = []
    #Create an empty list for the edge curves
    crvs = []
    
    # Place your code below this line
    #Loop through edges an append corresponding curve geometry to the list
    for edge in solid.Edges:
        crvs.append(edge.CurveGeometry)
    
    #Get the bounding box of the curves
    bbox = BoundingBox.ByGeometry(crvs)
    
    #Get the x and y translation distance based on the bounding box
    yDist = bbox.MaxPoint.Y-bbox.MinPoint.Y
    xDist = bbox.MaxPoint.X-bbox.MinPoint.X
    
    #Get the source coordinate system
    fromCoord = solid.ContextCoordinateSystem
    
    #Loop through x and y
    for i in range(xCount):
        for j in range(yCount):
            #Rotate and translate the coordinate system
            toCoord = fromCoord.Rotate(solid.ContextCoordinateSystem.Origin, Vector.ByCoordinates(0,0,1), (90*(i+j%seed)))
            vec = Vector.ByCoordinates((xDist*i),(yDist*j),0)
            toCoord = toCoord.Translate(vec)
            #Transform the solid from the source coord syste, to the target coord system and append to the list
            solids.append(solid.Transform(fromCoord,toCoord))
    
    # Assign your output to the OUT variable.
    OUT = solids