Podręcznik:Tworzenie obiektów parametrycznych

From FreeCAD Documentation
Revision as of 12:55, 6 March 2024 by Kaktus (talk | contribs) (Created page with "Badając zawartość ParamRectangle, możemy sprawdzić, czy zawiera ona naszą klasę ParametricRectangle.")

W rozdziale Tworzenie i obróbka geometrii widzieliśmy, jak tworzyć geometrię części i jak wyświetlać ją na ekranie, dołączając ją do "pospolitego" (nieparametrycznego) obiektu dokumentu. Jest to uciążliwe, gdy chcemy zmienić kształt tego obiektu. Musielibyśmy utworzyć nowy kształt, a następnie ponownie przypisać go do naszego obiektu.

Jednak we wszystkich poprzednich rozdziałach tego podręcznika widzieliśmy również, jak potężne są obiekty parametryczne. Wystarczy zmienić tylko jedną właściwość, a kształt zostanie przeliczony w locie.

Wewnętrznie obiekty parametryczne nie robią nic innego niż przed chwilą: Ponownie obliczają zawartość swojej właściwości Kształt, w kółko, za każdym razem, gdy zmieni się inna właściwość.

FreeCAD zapewnia bardzo wygodny system do budowania takich w pełni parametrycznych obiektów w Pythonie. Składają się one z prostej klasy Python, która definiuje wszystkie właściwości potrzebne obiektowi i co się stanie, gdy jedna z tych właściwości ulegnie zmianie. Struktura takiego obiektu parametrycznego jest bardzo prosta:

class myParametricObject:

    def __init__(self, obj):
        obj.Proxy = self
        obj.addProperty("App::PropertyFloat", "MyLength")
        ...

    def execute(self,obj):
        print ("Recalculating the shape...")
        print ("The value of MyLength is:")
        print (obj.MyLength)
        ...

Wszystkie klasy Pythona zazwyczaj posiadają metodę __init__. To, co znajduje się wewnątrz tej metody, jest wykonywane, gdy klasa jest instancjonowana (co oznacza, w slangu programistycznym, że obiekt Pythona jest tworzony z tej klasy. Potraktuj klasę jako "szablon" do tworzenia jej żywych kopii). W naszej funkcji __init__ robimy dwie ważne rzeczy:
1- przechowujemy naszą klasę w atrybucie "Proxy" naszego obiektu dokumentu FreeCAD, co oznacza, że obiekt dokumentu FreeCAD będzie przenosił ten kod wewnątrz siebie, oraz
2- tworzymy wszystkie właściwości, których potrzebuje nasz obiekt. Dostępnych jest wiele rodzajów właściwości, pełną listę można uzyskać, wpisując ten kod:

FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "dummy").supportedProperties()

Drugą ważną częścią jest metoda execute. Każdy kod w tej metodzie zostanie wykonany, gdy obiekt zostanie oznaczony do ponownego obliczenia, co nastąpi, gdy właściwość zostanie zmieniona. To już wszystko. Wewnątrz execute musisz zrobić wszystko, co trzeba, czyli obliczyć nowy kształt i przypisać go do samego obiektu za pomocą czegoś takiego jak obj.Shape = myNewShape. Dlatego właśnie metoda execute przyjmuje argument "obj", który będzie samym obiektem dokumentu FreeCAD, dzięki czemu możemy nim manipulować wewnątrz naszego kodu Python.

Ostatnia rzecz jest ważna do zapamiętania: Podczas tworzenia takich obiektów parametrycznych w dokumencie FreeCAD, po zapisaniu pliku, powyższy kod Python nie jest przechowywany wewnątrz pliku. Wynika to ze względów bezpieczeństwa, gdyby plik FreeCAD zawierał kod, ktoś mógłby rozpowszechniać pliki FreeCAD zawierające złośliwy kod, który mógłby uszkodzić komputery innych osób. Tak więc, jeśli dystrybuujesz plik, który zawiera obiekty wykonane przy użyciu powyższego kodu, taki kod musi być również obecny na komputerze, który otworzy plik. Najłatwiejszym sposobem na osiągnięcie tego jest zazwyczaj zapisanie powyższego kodu w makrze i rozpowszechnianie makra wraz z plikiem FreeCAD lub udostępnienie makra na Repozytorium makr FreeCAD, skąd każdy może je pobrać.

Poniżej wykonamy małe ćwiczenie, budując obiekt parametryczny, który jest prostą parametryczną prostokątną powierzchnią. Bardziej złożone przykłady są dostępne na stronie Obiekty tworzone skryptami oraz w samym kodzie źródłowym FreeCAD.

Nadamy naszemu obiektowi dwie właściwości: Długość i Szerokość, które wykorzystamy do skonstruowania prostokąta. Następnie, ponieważ nasz obiekt będzie już miał wstępnie zbudowaną właściwość Umiejscowienie (wszystkie obiekty geometryczne mają ją domyślnie, nie trzeba jej dodawać samodzielnie), przesuniemy nasz prostokąt do lokalizacji / obrotu ustawionego w Placement, dzięki czemu użytkownik będzie mógł przenieść prostokąt w dowolne miejsce, edytując właściwość Umiejscowienie.

class ParametricRectangle:

    def __init__(self,obj):
        obj.Proxy = self
        obj.addProperty("App::PropertyFloat", "Length")
        obj.addProperty("App::PropertyFloat", "Width")

    def execute(self, obj):
        # We need to import the FreeCAD module here too, because we might be running out of the Console
        # (in a macro, for example) where the FreeCAD module has not been imported automatically:
        import FreeCAD
        import Part

        # First we need to make sure the values of Length and Width are not 0
        # otherwise Part.LineSegment will complain that both points are equal:
        if (obj.Length == 0) or (obj.Width == 0):
            # If yes, exit this method without doing anything:
            return

        # We create 4 points for the 4 corners:
        v1 = FreeCAD.Vector(0, 0, 0)
        v2 = FreeCAD.Vector(obj.Length, 0, 0)
        v3 = FreeCAD.Vector(obj.Length,obj.Width, 0)
        v4 = FreeCAD.Vector(0, obj.Width, 0)

        # We create 4 edges:
        e1 = Part.LineSegment(v1, v2).toShape()
        e2 = Part.LineSegment(v2, v3).toShape()
        e3 = Part.LineSegment(v3, v4).toShape()
        e4 = Part.LineSegment(v4, v1).toShape()

        # We create a wire:
        w = Part.Wire([e1, e2, e3, e4])

        # We create a face:
        f = Part.Face(w)

        # All shapes have a Placement too. We give our shape the value of the placement
        # set by the user. This will move/rotate the face automatically.
        f.Placement = obj.Placement

        # All done, we can attribute our shape to the object!
        obj.Shape = f

Zamiast wklejać powyższy kod w konsoli Python, lepiej zapiszmy go gdzieś, abyśmy mogli go później ponownie wykorzystać i zmodyfikować. Na przykład w postaci nowej makrodefinicji (menu Przybory → Makrodefinicje → Utwórz). Nazwij je na przykład "ParamRectangle". Jednak makra FreeCAD są zapisywane z rozszerzeniem .FCMacro, którego Python nie rozpoznaje podczas importowania . Tak więc, przed użyciem powyższego kodu, będziemy musieli zmienić nazwę pliku ParamRectangle.FCMacro na ParamRectangle.py. Można to zrobić z poziomu eksploratora plików, przechodząc do folderu Macros wskazanego w menu Przybory → Makrodefinicje.

Gdy to zrobimy, możemy teraz zrobić to w konsoli Python:

import ParamRectangle

Badając zawartość ParamRectangle, możemy sprawdzić, czy zawiera ona naszą klasę ParametricRectangle.

To create a new parametric object using our ParametricRectangle class, we will use the following code. Observe that we use Part::FeaturePython instead of Part::Feature that we have been using in the previous chapters (The Python version allows to define our own parametric behaviour):

myObj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Rectangle")
ParamRectangle.ParametricRectangle(myObj)
myObj.ViewObject.Proxy = 0 # This is mandatory unless we code the ViewProvider too.
FreeCAD.ActiveDocument.recompute()

Nothing will appear on screen just yet, because the Length and Width properties are 0, which will trigger our "do-nothing" condition inside execute. We just need to change the values of Length and Width, and our object will magically appear and be recalculated on-the-fly.

Of course it would be tedious to have to type these 4 lines of Python code each time we want to create a new parametric rectangle. A very simple way to solve this is placing the 4 lines above inside our ParamRectangle.py file, at the end, after the end of the ParametricRectange class (We can do this from the Macro editor).

Now, when we type import ParamRectangle , a new parametric rectangle will automatically be created. Even better, we can add a toolbar button that will do just that:

  • Open menu Tools -> Customize
  • Under the "Macros" tab, select our ParamRectangle.py macro, fill in the details as you wish, and press "Add":

  • Under the Toolbars tab, create a new custom toolbar in the workbench of your choice (or globally), select your macro and add it to the toolbar:

  • That's it, we now have a new toolbar button which, when clicked, will create a parametric rectangle.

Remember, if you want to distribute files created with this new tool to other people, they must have the ParamRectangle.py macro installed on their computer too.

Read more