Code snippets
Эта страница содержит примеры, обрывки, куски FreeCAD python кода, собранный для получения пользователями оптыта и обсуждения на форумах. Читайте и используете их как начало для ваших собственных сценариев...
Обычный файл InitGui.py
Каждый модуль должен содержать, помимо основного файла модуля, файл InitGui.py , ответственного за вставку модуля в главное Gui. Это простой пример
class ScriptWorkbench (Workbench): MenuText = "Scripts" def Initialize(self): import Scripts # предполагается что Scripts.py ваш модуль list = ["Script_Cmd"] # Этот список должен содержать имена команд, которые были заданы в Scripts.py self.appendToolbar("My Scripts",list) Gui.addWorkbench(ScriptWorkbench())
Обычный файл модуля
Это пример головного файла модуля, содержащего всё что ваш модуль делает. Это Scripts.py файл вызванный в предыдущем примере. Вы можете установить здесь все ваши пользовательские команды.
import FreeCAD, FreeCADGui class ScriptCmd: def Activated(self): # Здесь вы описываете что ваш ScriptCmd делает... FreeCAD.Console.PrintMessage('Hello, World!') def GetResources(self): return {'Pixmap' : 'path_to_an_icon/myicon.png', 'MenuText': 'Short text', 'ToolTip': 'More detailed text'} FreeCADGui.addCommand('Script_Cmd', ScriptCmd())
Импорт нового типа файлов
Создание ипортировщика в нового типа файлов в FreeCAD, просто. FreeCAD не считает что вы импортируете данные в открытый документ, а скорее что вы просто можете непосредственно открыть новый тип файла. Так что все что вам нужно сделать, это добавить новое расширение файла в список известных расширений FreeCAD , и написать код, который будет читать файл и создавать FreeCAD объекты:
Это строка должна быть добавлена в InitGui.py файл для добавления нового расширения файлов в список:
# Предполагается что, Import_Ext.py это файл, который с кодом для открытия и чтения .ext файлов FreeCAD.addImportType("Your new File Type (*.ext)","Import_Ext")
Тогда в файле Import_Ext.py:
def open(filename): doc=App.newDocument() # here you do all what is needed with filename, read, classify data, create corresponding FreeCAD objects doc.recompute()
Экспорт вашего документа в новые типы файлов работает схожим образом, исключая того что вы используете:
FreeCAD.addExportType("Your new File Type (*.ext)","Export_Ext")
Добавление линии
Простейшая линия через две точки.
import Part,PartGui doc=App.activeDocument() # добавляет элемент линию в документ и устанавливает её точки l=Part.Line() l.StartPoint=(0.0,0.0,0.0) l.EndPoint=(1.0,1.0,1.0) doc.addObject("Part::Feature","Line").Shape=l.toShape() doc.recompute()
Добавление многоугольника
Многоугольник это просто набор соединенных отрезков (polyline в AutoCAD). Он необязательно должен быть замкнутым.
import Part,PartGui doc=App.activeDocument() n=list() # создает 3D вектор, устанавливает его набор координат и добавляет их в список v=App.Vector(0,0,0) n.append(v) v=App.Vector(10,0,0) n.append(v) #... повторяется для всех узлов # Создает объект - многоугольник(polygon) и задает его вершины p=doc.addObject("Part::Polygon","Polygon") p.Nodes=n
doc.recompute()
Добавление и удаление объекта из группы
doc=App.activeDocument() grp=doc.addObject("App::DocumentObjectGroup", "Group") lin=doc.addObject("Part::Feature", "Line") grp.addObject(lin) # добавление объекта lin в группу grp grp.removeObject(lin) # удаление объекта lin из группы grp
Примечание: Вы также можете добавлять другие группы в группу...
Добавление Полигиональной модели
import Mesh doc=App.activeDocument() # создаем новую пустую сетку m = Mesh.Mesh() # строим блок из 12 граней (6 граней и по два труегольника в квадрате) m.addFacet(0.0,0.0,0.0, 0.0,0.0,1.0, 0.0,1.0,1.0) m.addFacet(0.0,0.0,0.0, 0.0,1.0,1.0, 0.0,1.0,0.0) m.addFacet(0.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,1.0) m.addFacet(0.0,0.0,0.0, 1.0,0.0,1.0, 0.0,0.0,1.0) m.addFacet(0.0,0.0,0.0, 0.0,1.0,0.0, 1.0,1.0,0.0) m.addFacet(0.0,0.0,0.0, 1.0,1.0,0.0, 1.0,0.0,0.0) m.addFacet(0.0,1.0,0.0, 0.0,1.0,1.0, 1.0,1.0,1.0) m.addFacet(0.0,1.0,0.0, 1.0,1.0,1.0, 1.0,1.0,0.0) m.addFacet(0.0,1.0,1.0, 0.0,0.0,1.0, 1.0,0.0,1.0) m.addFacet(0.0,1.0,1.0, 1.0,0.0,1.0, 1.0,1.0,1.0) m.addFacet(1.0,1.0,0.0, 1.0,1.0,1.0, 1.0,0.0,1.0) m.addFacet(1.0,1.0,0.0, 1.0,0.0,1.0, 1.0,0.0,0.0) # масштабируем длинну ребер в 100 раз m.scale(100.0) # добавление сетки в активный документ me=doc.addObject("Mesh::Feature","Cube") me.Mesh=m
Добавление дуги или огружности
import Part doc = App.activeDocument() c = Part.Circle() c.Radius=10.0 f = doc.addObject("Part::Feature", "Circle") # создает в документе функционал -окружность f.Shape = c.toShape() # Устанавливает форму- окружность в свойство "форма" doc.recompute()
Получение доступа и изменение представления объекта
Каждый объект в FreeCAD документе оссоциируется с визуальным представлением объекта, которое хранит все параметры , определяющие как объект представлен, такие как цвет, длина линий, и.т.д...
gad=Gui.activeDocument() # получение доступа к активному документ содержащему все # визуальные представления функционалов # соответствующего App документа v=gad.getObject("Cube") # получение доступа к визуальному представлению Mesh функционала 'Cube' v.ShapeColor # печатает цвет в терминал v.ShapeColor=(1.0,1.0,1.0) # устанавливает цвет формы в белый
Наблюдение за поведение мыши в 3D окне через Python
Inventor позваляет добавить оди и более узлов обратного вызова(callback) в дерево сцен просмотрщика. По умолчанию в FreeCAD один узел обратного вызова установлен в кадое окно просмотра(просмотрщик), который позволяет добавить глобальные или статические C++ функции. Соответствуюе Python привязки, некоторые методы которых позволяют использовать эту технику (callback) в Python коде.
App.newDocument() v=Gui.activeDocument().activeView() #Этот класс регистрирует любые событияпроисходящие с кнопкой мыши. Когда регистрируется вызов событий двойной 'down' и #'up' мы должны ввести логический флаг, чтобы с этим справится(тут получился бред). class ViewObserver: def logPosition(self, info): down = (info["State"] == "DOWN") pos = info["Position"] if (down): FreeCAD.Console.PrintMessage("Clicked on position: ("+str(pos[0])+", "+str(pos[0])+")\n") o = ViewObserver() c = v.addEventCallback("SoMouseButtonEvent",o.logPosition)
Теперь, выберите какую нибудь область в окне 3D-просмотра и наблюдайте сообщения в окне вывода. Для завершения наблюдения просто вызовите
v.removeEventCallback("SoMouseButtonEvent",c)
Поддерживаются следующие типы событий
- SoEvent -- Все события
- SoButtonEvent -- Все события клавиш клавиатуры и мыши
- SoLocation2Event -- события 2D перемещений (обычно движение мыши)
- SoMotion3Event -- события 3D перемещений (обычно spaceball)
- SoKeyboradEvent -- события нажатие и отпускание клавиш клавиатуры
- SoMouseButtonEvent -- события нажатия и отпускания клавиш мыши
- SoSpaceballButtonEvent -- события нажатия и отпускания клавиш spaceball
Python функции которые могут быть зарегистрированы в addEventCallback() предлагающем словарь(dictionary). В зависимости от наблюдателя события словарь может содержать различные ключи.
Для всех событий существуют ключи:
- Type -- Имя типа события т.е. SoMouseEvent, SoLocation2Event, ...
- Time -- текущие время в виде строки
- Position -- набор из двух целых чисел как позиция курсорa мыши
- ShiftDown -- логическая(boolean) переменная, true если Shift нажат, в противном случае false
- CtrlDown -- логическая(boolean) переменная, true если Ctrl нажат, в противном случае false
- AltDown -- логическая(boolean) переменная, true если Alt нажат, в противном случае false
Для всех клавишных событий, т.e. для событий клавиатуры, мыши или spaceball
- State -- Строка 'UP' если кнопка была вверху, 'DOWN' если кнопка была внизу или 'UNKNOWN' во всех остальных случаях
Для событий связанных с клавиатурой:
- Key -- значение нажатоой клаывиши
Для событий связанных с мышью
- Button -- Нажаты клавиши, могут быть BUTTON1, ..., BUTTON5 или ANY
Для событий spaceball:
- Button -- Нажатые клавиши, могут быть BUTTON1, ..., BUTTON7 или ANY
и наконец события движения:
- Translation -- набор из трех переменных floats
- Rotation -- кватернион поворота, т.е. набор из четырех переменных floats
Манипулирование scenegraph в Python
Кроме того можно получить и изменить граф сцены в Python, с помощью модуля 'pivy' -- Python привязки к Coin.
from pivy.coin import * # загрузка модуля pivy view = Gui.ActiveDocument.ActiveView # получение графа, активного вида root = view.getSceneGraph() # корень это узел SoSeparator root.addChild(SoCube()) view.fitAll()
Python API для pivy создано используя инструмент SWIG. Так как мы используем в FreeCAD некоторые самостоятельно записанные узлы вы не можете создавать их напрямую через Python. Однако, возможно создать узел в его внутренним именем. Экземпляр типа 'SoFCSelection' может быть создан
type = SoType.fromName("SoFCSelection") node = type.createInstance()
Добавление и удаление объектов в/из графа сцены
Добавление новых узлов в граф сцены(scenegraph) может сделать таким образом. Всегда заботтесь о добавлении SoSeparator содержащего информацию о геометрии, координатах и материалах объекта. В следующем примере добавляется красная линия из точки (0,0,0) в (10,0,0):
from pivy import coin sg = Gui.ActiveDocument.ActiveView.getSceneGraph() co = coin.SoCoordinate3() pts = [[0,0,0],[10,0,0]] co.point.setValues(0,len(pts),pts) ma = coin.SoBaseColor() ma.rgb = (1,0,0) li = coin.SoLineSet() li.numVertices.setValue(2) no = coin.SoSeparator() no.addChild(co) no.addChild(ma) no.addChild(li) sg.addChild(no)
Чтобы удалить её, просто введите:
sg.removeChild(no)
Добавление пользовательских виджетов к интерфейсу
Вы можете содать собственные виджеты с помощью Qt designer, превратив их в сценарии на python, с помощью PyQt4, и загрузив их в FreeCAD.
Python код созданный с помощью Ui python compiler (это инструмент для конвертирования файлов ui. созданных qt-designer в python код) в основном выглядит так (это простой пример, вы также может писать этот код напряму с помощью python):
class myWidget_Ui(object): def setupUi(self, myWidget): myWidget.setObjectName("my Nice New Widget") myWidget.resize(QtCore.QSize(QtCore.QRect(0,0,300,100).size()).expandedTo(myWidget.minimumSizeHint())) # Установка размера виджета self.label = QtGui.QLabel(myWidget) # создание объекта метка(label) self.label.setGeometry(QtCore.QRect(50,50,200,24)) # установка размеров self.label.setObjectName("label") # установка значения имени, теперь его можно найти по имени def retranslateUi(self, draftToolbar): # built-in QT function that manages translations of widgets myWidget.setWindowTitle(QtGui.QApplication.translate("myWidget", "My Widget", None, QtGui.QApplication.UnicodeUTF8)) self.label.setText(QtGui.QApplication.translate("myWidget", "Welcome to my new widget!", None, QtGui.QApplication.UnicodeUTF8))
Тогда все что вам нужно сделать, это создать ссылку на FreeCAD Qt окно, вставить виджет в него, и "преобразовать" этот виджет в ваш с Ui кодом который мы только что сделали:
app = QtGui.qApp FCmw = app.activeWindow() # активное окно qt , = freecad окну, поскольку мы находимся в нем myNewFreeCADWidget = QtGui.QDockWidget() # создает новый dckwidget myNewFreeCADWidget.ui = myWidget_Ui() # загружает Ui сценарий myNewFreeCADWidget.ui.setupUi(myNewFreeCADWidget) # устанавливает ui FCmw.addDockWidget(QtCore.Qt.RightDockWidgetArea,myNewFreeCADWidget) # добавляет виджет в главное окно