Line drawing function/ru

На этой странице показано лего можно создать продвинутую фукнкциональность в Python. В данном примере, мы создадим новый инструмент, для рисования линии. Этот инструмент может быть свзае с командой FreeCAD, и эта команда может быть вызвана из любого элемента интерфейса, таком как как опция меню или кнопка на панели инструментов.

Сам сценарий
Сначало мы напишем сценарий содержащий всю о нашу функциональность. Затем, мы сохраним его в файле и импортируем в FreeCAD, так все классы и функции что мы описали будут доступны в FreeCAD. Так что, запускатите ваш любимы текстовый редактор, и введите следующие строки:

Подробное описание
В Python, когда вам требуется использовать функции из другого модуля, вам нужно импортировать его. В нашем случае, нам нужны функции из Модуля Деталей, для создания линии, и из Gui модуля (FreeCADGui), для доступа к 3D виду. Нам также нужно полное содержание библиотеки coin, так мы сможем напрямую использовать все coin объекта такие как SoMouseButtonEvent, и.т.д... Здесь мы задаем наш основной класс. Почему мы используем класс а не функцию? Причина в том чтобы нащ инструмент оставался "живым" когда мы ждем что пользователь нажмет на экран. Функция завершится когда её задача будет выполнена, но объект (класс заданый как объект) остается живым пока не будет уничтожен. В Python, каждый класс или функция могут обладать строкой описания. Это особенно полезно в FreeCAD, потому что когда вы будете вызывать этот класс через интепритатор, строка описания будет отображатся в виде всплывающей подсказки. Python класс всегда может содержать __init__ функцию, которая выполняется когда класс вызывается для создания объекта. Таким образом, мы положим сюда всё что мы хотим чтобы случилось, когда запустится наш инструмент "линия". В классе, вам обычно нужно добавить self. перед именем переменной, для того чтобы получить легкий доступ к функциям в и вне класса. Здесь мы используем self.view для доступа к управлению активным 3D видом. Здесь мы создаем простой список содержащий 3D точки, переданные функцией getpoint. Это важная часть: Посколько это фактически coin3D сцена(в смысле окно отображения), FreeCAD использует механизм обратного вызова coin, что позваляет вызывать функцию каждый раз когда на сцене что-то происходит. В нашем случае, мы создаем обратный вызов для события SoMouseButtonEvent, и мы привязываем его getpoint функции. Теперь, каждый раз когда клавиша мыши будет нажата или отпущена, будет выполнятся функция getpoint.

Замети также что существует альтернативна addEventCallbackPivy, зовется addEventCallback которая обходится без использование pivy. Но так как pivy это очень эффективный и естественный способ получить доступ к любой части coin сцены, он гораздо лучше для использования так как вы можете! Теперь вы задали getpoint функцию, которая выполняется когда клавиша мыши щелкает по окну 3D вида. Эта функция будет получать аргумент, который мы назовем event_cb. В время обратного вызова мы можем получить доступ к объекту события, который содержит некоторую информацию (информационный режим описан здесь). Getpoint функция будет вызыватся когда клавиши мыши будет нажата или отжата. Но мы хотим фиксировать 3D точку только когда нажимаем (в противном случае мы мы можем получить две 3D точки очень близко друг от друга). Так что мы проверяем это. Здесь мы получаем координаты курсора мыши Эта функция дает нам FreeCAD вектор (x,y,z) содержащий точку лежащую в фокальной плоскости, т.е. под вашим курсором. Если вы находитесь в режиме камеры, изображается луч идущий из камеры проходящий через курсор мыши, и достигающий фокальной плоскости. Это наша 3D точка. Если мы находимся в режиме ортогонального отображения, луч паралелен направлению вида. Мы добавляем новую точку в stack Если у вас, уже достаточное количество точек? если да, тогда давайте рисовать линию! Здесь мы используем Line функцию из Модуля Деталей которая создает линию по двум FreeCAD векторам. Все что мы создаем и модифицируем внутри модуля Деталей, остается в модуле(Part module). Так что, до сих пор, когда мы создавали Line Part. Она не была привязана к какому либо объекту в нашем документе, поэтому ничего и не отображалось на экране. FreeCAD документ может принимать только формы(shapes) из модуля Деталей. Формы являются наиболее универсальным типом из модуля Деталей. Таким образом, мы должны преобразовать нашу линию в форму и добавить её в документ. The Part module has a very handy show function that creates a new object in the document and binds a shape to it. We could also have created a new object in the document first, then bound the shape to it manually. Since we are done with our line, let's remove the callback mechanism, that consumes precious CPU cycles.

Testing & Using the script
Now, let's save our script to some place where the FreeCAD python interpreter will find it. When importing modules, the interpreter will look in the following places: the python installation paths, the FreeCAD bin directory, and all FreeCAD modules directories. So, the best solution is to create a new directory in one of the FreeCAD Mod directories, and to save our script in it. For example, let's make a "MyScripts" directory, and save our script as "exercise.py".

Now, everything is ready, let's start FreeCAD, create a new document, and, in the python interpreter, issue: If no error message appear, that means our exercise script has been loaded. We can now check its contents with: The command dir is a built-in python command that lists the contents of a module. We can see that our line class is there, waiting for us. Now let's test it: Then, click two times in the 3D view, and bingo, here is our line! To do it again, just type exercise.line again, and again, and again... Feels great, no?

Registering the script in the FreeCAD interface
Now, for our new line tool to be really cool, it should have a button on the interface, so we don't need to type all that stuff everytime. The easiest way is to transform our new MyScripts directory into a full FreeCAD workbench. It is easy, all that is needed is to put a file called InitGui.py inside your MyScripts directory. The InitGui.py will contain the instructions to create a new workbench, and add our new tool to it. Besides that we will also need to transform a bit our exercise code, so the line tool is recognized as an official FreeCAD command. Let's start by making an InitGui.py file, and write the following code in it: By now, you should already understand the above script by yourself, I think: We create a new class that we call MyWorkbench, we give it a title (MenuText), and we define an Initialize function that will be executed when the workbench is loaded into FreeCAD. In that function, we load in the contents of our exercise file, and append the FreeCAD commands found inside to a command list. Then, we make a toolbar called "My Scripts" and we assign our commands list to it. Currently, of course, we have only one tool, so our command list contains only one element. Then, once our workbench is ready, we add it to the main interface.

But this still won't work, because a FreeCAD command must be formatted in a certain way to work. So we will need to transform a bit our line tool. Our new exercise.py script will now look like this: What we did here is transform our __init__ function into an Activated function, because when FreeCAD commands are run, they automatically execute the Activated function. We also added a GetResources function, that informs FreeCAD where it can find an icon for the tool, and what will be the name and tooltip of our tool. Any jpg, png or svg image will work as an icon, it can be any size, but it is best to use a size that is close to the final aspect, like 16x16, 24x24 or 32x32. Then, we add the line class as an official FreeCAD command with the addCommand method.

That's it, we now just need to restart FreeCAD and we'll have a nice new workbench with our brand new line tool!

So you want more?
If you liked this exercise, why not try to improve this little tool? There are many things that can be done, like for example: Don't hesitate to write your questions or ideas on the talk page!
 * Add user feedback: until now we did a very bare tool, the user might be a bit lost when using it. So we could add some feedback, telling him what to do next. For example, you could issue messages to the FreeCAD console. Have a look in the FreeCAD.Console module
 * Add a possibility to type the 3D points coordinates manually. Look at the python input function, for example
 * Add the possibility to add more than 2 points
 * Add events for other things: Now we just check for Mouse button events, what if we would also do something when the mouse is moved, like displaying current coordinates?
 * Give a name to the created object