Manual:Creating parametric objects/ru: Difference between revisions

From FreeCAD Documentation
(Created page with "{{Manual:TOC/ru}}")
 
(Updating to match new version of source page)
 
(30 intermediate revisions by 2 users not shown)
Line 1: Line 1:
<languages/>
{{Manual:TOC/ru}}


<div class="mw-translate-fuzzy">
In the [[Manual:Creating and manipulating geometry|previous chapter]], we saw how to create Part geometry, and how to display it on screen, by attaching it to a "dumb" (non-parametric) document object. This is tedious when we want to change the shape of that object. We would need to create a new shape, then attribute it again to our object.
{{Docnav/ru
|[[Manual:Creating and manipulating geometry/ru|Creating and manipulating geometry]]
|[[Manual:Creating interface tools/ru|Creating interface tools]]
|[[Manual:Introduction/ru|Manual start]]
|IconC=Crystal Clear manual.png
}}
</div>


{{Manual:TOC}}
However, we also saw in all the preceding chapters of this manual how parametric objects are powerful. We only need to change one property, and the shape is recalculated on-the-fly.


В [[Manual:Creating and manipulating geometry/ru|предыдущей главе]] мы видели создание геометрии Part, и как показать её на экране присоединением её к "пустому" (непараметрическому) объекту документа. Это муторно, когда мы хотим изменить форму объекта. Нам нужно создать новую форму, затем снова приписать её к нашему объекту.
Internally, parametric objects don't do anything different than we just did: They recalculate the contents of their Shape property, over and over, each time another property has changed.


Однако мы видели в предыдущих главах этого руководства, как велики возможности параметрических объектов. Мы можем изменить один параметр, и форма пересчитывается на лету.
FreeCAD provides a very convenient system to build such parametric objects fully in Python. They consist of a simple Python class, which defines all the properties that the object needs, and what will happen when one of these properties changes. The structure of such parametric object is as simple as this:


Внутри параметрические объекты не делают ничего иного кроме того, что мы делали: они пересчитывают содержимое параметра Shape, раз за разом когда другие параметры изменяются.
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)
...


FreeCAD обеспечивает очень удобную систему для построения таких параметрических объектов полностью в Python. Они состоят из простых классов Python, которые определяют все нужные объекту параметры, и что случится если один из этих параметров изменится. Структура этих параметрических объектов так проста, как это:
All Python classes usually have an __init__ method. What is inside that method is executed when that class is instantiated (which means, in programming slang, that a Python Object is created from that class. Think of a class as a "template" to create live copies of it). In our __init__ function here, we do two important things: 1) store our class itself into the "Proxy" attribute of our FreeCAD documetn object, that is, the FreeCAD document object will carry this code, inside itself, and 2) create all the properties our object needs. There are many types of properties available, you can get the full list by typing this code:


{{Code|code=
FreeCAD.ActiveDocument.addObject("Part::FeaturePython","dummy").supportedProperties()
class myParametricObject:


def __init__(self, obj):
Then, the second important part is the execute method. Any code in this method will be executed when the object is marked to be recomputed, which will happen when a property has been changed. That is all there is to it. Inside execute, you need to do all that needs tobe done, that is, calculating a new shape, and attributing to the object itself with something like obj.Shape = myNewShape. That is why the execute method takes an "obj" argument, which will be the FreeCAD document object itself, so we can manipulate it inside our python code.
obj.Proxy = self
obj.addProperty("App::PropertyFloat", "MyLength")
...


def execute(self,obj):
One last thing is important to remember: When you create such parametric objects in a FreeCAD document, when you save the file, the python code above is not stored inside the file. This is for security reasons, if a FreeCAD file contained code, it would be possible for someone to distribute FreeCAD files containing malicious code that could harm other people's computers. So, if you distribute a file that contains objects made with the above code, such code must also be present on the computer that will open the file. The easiest way to achieve that is usually to save the code above in a macro, and distribute the macro together with your FreeCAD file, or share your macro on the [[Macros_recipes|FreeCAD macros repository]] where anybody can download it.
print ("Recalculating the shape...")
print ("The value of MyLength is:")
print (obj.MyLength)
...
}}


Все классы Python обычно имеют метод __init__. Всё, что внутри этого метода, исполняется когда создаётся экземпляр этого класса (что знает, на программистском сленге, что объект Python создаётся из этого класса. Представляйте класс как "шаблон" для создания живых копий). В наших функциях __init__ мы здесь делаем две важные вещи: 1- сохраняем наш класс в атрибут "Proxy" объекта нашего документа FreeCAD, то есть документ FreeCAD будет носить этот код в себе, и 2- создает все параметры, которые нужны нашему объекту. Доступны множество типов параметров, Вы можете получить полный список, набрав следующий код:
Below, we will do a small exercise, building a parametric object that is a simple parametric rectangular face. More complex examples are available on the [[Scripted_objects|parametric object example]] and in the [https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/TemplatePyMod/FeaturePython.py FreeCAD source code] itself.


{{Code|code=
We will give our object two properties: Length and Width, which we will use to construct a rectangle. Then, since our object will already have a pre-built Placement property (all geometric object have one by default, no need to add it ourselves), we will displace our rectangle to the location/rotation set in the Placement, so the user will be able to move the rectangle anywhere by editing the Placement property.
FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "dummy").supportedProperties()
}}


Следующая важная часть это исполняемый метод. Любой код в этом методе исполняется когда объект маркирован для пересчёта, что происходит когда объект изменяется. Это всё, что есть. Внутри исполнения требуется сделать всё, что надо, то есть вычисление новой формы, и приписывания объекту чего-то вроде obj.Shape = myNewShape. Вот почему исполняемый метод принимает аргумент "obj", которых будет самим документом FreeCAD, так что мы можем манипулировать им внутри нашего кода python.
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 Part,FreeCAD
# first we need to make sure the values of Length and Width are not 0
# otherwise the Part.Line 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.Line(v1,v2).toShape()
e2 = Part.Line(v2,v3).toShape()
e3 = Part.Line(v3,v4).toShape()
e4 = Part.Line(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


Последняя вещь, которую важно запомнить: когда Вы создаёте такой параметрический объект в документе FreeCAD, когда Вы сохраняете файл, вышеуказанный код python не сохраняется в файле. Это происходит из соображений безопасности, если бы файлы FreeCAD содержали код, у злоумышленников была бы возможность распространять файлы FreeCAD с вредоносным кодом, который мог бы повреждать чужие компьютеры. Так что если Вы распространяете файл, который содержит объекты, сделанные с помощью вышеуказанного года, этот код должен так же находиться на компьютерах, которые откроют файл. Простейший путь достичь этого - сохранить код в макросе, и распространять макрос вместе с файлом, или делиться своим макросом на [[Macros_recipes/ru|репозитории макросов FreeCAD]], где каждый сможет загрузить его.
Instead of pasting the above code in the Python console, we'd better save it somewhere, so we can reuse and modify it later. For example in a new macro (menu Tools -> Macros -> Create). Name it, for example, "ParamRectangle". However, FreeCAD macros are saved with a .FCMacro extension, which Python doesn't recognize when using import . So, before using the above code, we will need to rename the ParamRectangle.FCMacro file to ParamRectangle.py. This can be done simply from your file explorer, by navigating to the Macros folder indicated in menu Tools -> Macros.


Ниже мы выполним маленькое упражнение, создав параметрический объект - простейшая параметрическая прямоугольная грань. Более сложные примеры доступны в [[Scripted_objects/ru|примере параметрического объекта]] и в [https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/TemplatePyMod/FeaturePython.py коде самого FreeCAD].
Once that is done, we can now do this in the Python Console:


Мы придадим нашему объекту два параметра: Length и Width, которые мы будем использовать для создания прямоугольника. Затем, поскольку наш объект уже имеет встроенный параметр Placement (все геометрические объекты имеют его по умолчанию, их не надо добавлять самостоятельно), мы поместим наш прямоугольник в положение/наклон, установленные в Placement, так что пользователь сможет перемещать прямоугольник редактированием параметра Placement.
import ParamRectangle


{{Code|code=
By exploring the contents of ParamRectangle, we can verify that it contains our ParametricRectangle class.
class ParametricRectangle:


def __init__(self,obj):
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):
obj.Proxy = self
obj.addProperty("App::PropertyFloat", "Length")
obj.addProperty("App::PropertyFloat", "Width")


def execute(self, obj):
myObj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Rectangle")
# We need to import the FreeCAD module here too, because we might be running out of the Console
ParamRectangle.ParametricRectangle(myObj)
# (in a macro, for example) where the FreeCAD module has not been imported automatically:
myObj.ViewObject.Proxy = 0 # this is mandatory unless we code the ViewProvider too
import FreeCAD
FreeCAD.ActiveDocument.recompute()
import Part


# First we need to make sure the values of Length and Width are not 0
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.
# 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:
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).
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:
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:
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:
* Open menu '''Tools -> Customize'''
w = Part.Wire([e1, e2, e3, e4])
* Under the "Macros" tab, select our ParamRectangle.py macro, fill in the details as you wish, and press "Add":

# 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
}}

Вместо того чтобы вставить вышеуказанный код в консоль Python, лучше сохраним его где-нибудь, чтобы мы могли повторно использовать и модифицировать его позднее. Например, в макросе (меню Tools -> Macros -> Create). Назовём его, например, "ParamRectangle". Тем не менее, макрос FreeCAD сохраняется с расширением .FCMacro, который Python не разспознаёт при импорте. Поэтому перед использованием этого кода нам надо переименовать ParamRectangle.FCMacro в ParamRectangle.py. Это легко делается в вашем менеджере файлов, найдя папку Macros, показанную в меню Tools -> Macros.

Когда это сделано, мы можем сделать это в консоли Python:

{{Code|code=
import ParamRectangle
}}

Открывая содержимое ParamRectangle, мы убедимся, что он содержит лишь наш класс ParametricRectangle.

Для создания нового параметрического объекта с использованием нашего класса ParametricRectangle мы будем использовать следующий код. Заметьте, что мы используем Part::FeaturePython вместо Part::Feature, который мы использовали в предыдущих главах (версия Python позволяет определить наш собственное параметрическое поведение):

{{Code|code=
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()
}}

Пока ничего на экране не появилось, поскольку параметры Length и Width равны 0, что включает наше правило "do-nothing" внутри execute. Нам надо просто изменить значения Length и Width, и наш объект волшебно появится и будет пересчитан на лету.

Разумеется, было бы утомительно вводить эти 4 строки кода Python каждый раз, когда нам нужно создать новый параметрический прямоугольник. Простой путь решить это - поместить эти 4 строки в наш файл ParamRectangle.py в конце, после класса ParametricRectange (Мы можем делать это в редакторе макросов).

Теперь, когда мы напишем import ParamRectangle , новый параметрический прямоугольник создастся автоматически. Даже лучше, мы можем добавить кнопку панели инструментов, которая сделает это:

* Открыть меню '''Tools -> Customize'''
* На вкладке "Macros" выберите наш ParamRectangle.py, заполните детали по желанию и нажмите "Add":
[[Image:Exercise_python_04.jpg]]
[[Image:Exercise_python_04.jpg]]


* На вкладке Toolbars создайте новую панель инструментов в каком хотите верстаке (или глобально), выделите ваш макрос и добавьте его в панель инструментов:
* 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:


[[Image:Exercise_python_05.jpg]]
[[Image:Exercise_python_05.jpg]]


* Это всё, мы уже имеем новую кнопку панели инструментов, которая при клике создаст параметрический прямоугольник.
* That's it, we now have a new toolbar button which, when clicked, will create a parametric rectangle.


Запомните, если Вы хотите распространять файлы, созданные с помощью этого нового инструмента среди других людей, они должны так же иметь установленный на своём компьютере макрос ParamRectangle.py.
Remeber, 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'''
'''Читать далее'''


* [[Macros_recipes|The FreeCAD macros repository]]
* [[Macros_recipes/ru|Репозиторий макросов FreeCAD]]
* [[Scripted_objects|Parametric object example]]
* [[Scripted_objects/ru|Пример параметрического объекта]]
* [https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/TemplatePyMod/FeaturePython.py More examples in the FreeCAD code]
* [https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/TemplatePyMod/FeaturePython.py Дополнительные примеры в коде FreeCAD]



<languages/>
<div class="mw-translate-fuzzy">
{{Docnav/ru
|[[Manual:Creating and manipulating geometry/ru|Creating and manipulating geometry]]
|[[Manual:Creating interface tools/ru|Creating interface tools]]
|[[Manual:Introduction/ru|Manual start]]
|IconC=Crystal Clear manual.png
}}
</div>

{{Powerdocnavi{{#translation:}}}}
[[Category:Developer Documentation{{#translation:}}]]
[[Category:Python Code{{#translation:}}]]

Latest revision as of 19:34, 4 November 2023

Other languages:

В предыдущей главе мы видели создание геометрии Part, и как показать её на экране присоединением её к "пустому" (непараметрическому) объекту документа. Это муторно, когда мы хотим изменить форму объекта. Нам нужно создать новую форму, затем снова приписать её к нашему объекту.

Однако мы видели в предыдущих главах этого руководства, как велики возможности параметрических объектов. Мы можем изменить один параметр, и форма пересчитывается на лету.

Внутри параметрические объекты не делают ничего иного кроме того, что мы делали: они пересчитывают содержимое параметра Shape, раз за разом когда другие параметры изменяются.

FreeCAD обеспечивает очень удобную систему для построения таких параметрических объектов полностью в Python. Они состоят из простых классов Python, которые определяют все нужные объекту параметры, и что случится если один из этих параметров изменится. Структура этих параметрических объектов так проста, как это:

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)
        ...

Все классы Python обычно имеют метод __init__. Всё, что внутри этого метода, исполняется когда создаётся экземпляр этого класса (что знает, на программистском сленге, что объект Python создаётся из этого класса. Представляйте класс как "шаблон" для создания живых копий). В наших функциях __init__ мы здесь делаем две важные вещи: 1- сохраняем наш класс в атрибут "Proxy" объекта нашего документа FreeCAD, то есть документ FreeCAD будет носить этот код в себе, и 2- создает все параметры, которые нужны нашему объекту. Доступны множество типов параметров, Вы можете получить полный список, набрав следующий код:

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

Следующая важная часть это исполняемый метод. Любой код в этом методе исполняется когда объект маркирован для пересчёта, что происходит когда объект изменяется. Это всё, что есть. Внутри исполнения требуется сделать всё, что надо, то есть вычисление новой формы, и приписывания объекту чего-то вроде obj.Shape = myNewShape. Вот почему исполняемый метод принимает аргумент "obj", которых будет самим документом FreeCAD, так что мы можем манипулировать им внутри нашего кода python.

Последняя вещь, которую важно запомнить: когда Вы создаёте такой параметрический объект в документе FreeCAD, когда Вы сохраняете файл, вышеуказанный код python не сохраняется в файле. Это происходит из соображений безопасности, если бы файлы FreeCAD содержали код, у злоумышленников была бы возможность распространять файлы FreeCAD с вредоносным кодом, который мог бы повреждать чужие компьютеры. Так что если Вы распространяете файл, который содержит объекты, сделанные с помощью вышеуказанного года, этот код должен так же находиться на компьютерах, которые откроют файл. Простейший путь достичь этого - сохранить код в макросе, и распространять макрос вместе с файлом, или делиться своим макросом на репозитории макросов FreeCAD, где каждый сможет загрузить его.

Ниже мы выполним маленькое упражнение, создав параметрический объект - простейшая параметрическая прямоугольная грань. Более сложные примеры доступны в примере параметрического объекта и в коде самого FreeCAD.

Мы придадим нашему объекту два параметра: Length и Width, которые мы будем использовать для создания прямоугольника. Затем, поскольку наш объект уже имеет встроенный параметр Placement (все геометрические объекты имеют его по умолчанию, их не надо добавлять самостоятельно), мы поместим наш прямоугольник в положение/наклон, установленные в Placement, так что пользователь сможет перемещать прямоугольник редактированием параметра Placement.

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

Вместо того чтобы вставить вышеуказанный код в консоль Python, лучше сохраним его где-нибудь, чтобы мы могли повторно использовать и модифицировать его позднее. Например, в макросе (меню Tools -> Macros -> Create). Назовём его, например, "ParamRectangle". Тем не менее, макрос FreeCAD сохраняется с расширением .FCMacro, который Python не разспознаёт при импорте. Поэтому перед использованием этого кода нам надо переименовать ParamRectangle.FCMacro в ParamRectangle.py. Это легко делается в вашем менеджере файлов, найдя папку Macros, показанную в меню Tools -> Macros.

Когда это сделано, мы можем сделать это в консоли Python:

import ParamRectangle

Открывая содержимое ParamRectangle, мы убедимся, что он содержит лишь наш класс ParametricRectangle.

Для создания нового параметрического объекта с использованием нашего класса ParametricRectangle мы будем использовать следующий код. Заметьте, что мы используем Part::FeaturePython вместо Part::Feature, который мы использовали в предыдущих главах (версия Python позволяет определить наш собственное параметрическое поведение):

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()

Пока ничего на экране не появилось, поскольку параметры Length и Width равны 0, что включает наше правило "do-nothing" внутри execute. Нам надо просто изменить значения Length и Width, и наш объект волшебно появится и будет пересчитан на лету.

Разумеется, было бы утомительно вводить эти 4 строки кода Python каждый раз, когда нам нужно создать новый параметрический прямоугольник. Простой путь решить это - поместить эти 4 строки в наш файл ParamRectangle.py в конце, после класса ParametricRectange (Мы можем делать это в редакторе макросов).

Теперь, когда мы напишем import ParamRectangle , новый параметрический прямоугольник создастся автоматически. Даже лучше, мы можем добавить кнопку панели инструментов, которая сделает это:

  • Открыть меню Tools -> Customize
  • На вкладке "Macros" выберите наш ParamRectangle.py, заполните детали по желанию и нажмите "Add":

  • На вкладке Toolbars создайте новую панель инструментов в каком хотите верстаке (или глобально), выделите ваш макрос и добавьте его в панель инструментов:

  • Это всё, мы уже имеем новую кнопку панели инструментов, которая при клике создаст параметрический прямоугольник.

Запомните, если Вы хотите распространять файлы, созданные с помощью этого нового инструмента среди других людей, они должны так же иметь установленный на своём компьютере макрос ParamRectangle.py.

Читать далее