Как расширить FreeCAD для импорта нового формата данных

Как расширить FreeCAD для импорта нового формата данных

Определение формата данных

Для примера определим импровизированный формат данных .box, описывающий параметры модели параллелепипеда. За основу формата возьмем JSON и объявим три параметра параллелепипеда: ширину, высоту и толщину. Тогда файл модели model.box будет содержать:

{
  "width": 100,
  "height": 200,
  "depth": 300
}

Структура расширения FreeCad

Расширение FreeCad (или аддон) реализуется на Python и в простоте своей имеет структуру как показано на схеме ниже. Файлы Init.py и InitGui.py являются обязательными. Файл Init.py используется FreeCad в консольном режиме, но вызывается и в режиме GUI. Файл InitGui.py содержит функциональность для расширения пользовательского интерфейса.

/Mod/
 +-- FreecadMod/
     +-- Init.py
     +-- InitGui.py

Для загрузки расширения в FreeCad достаточно разместить папку с расширением в Mod-директорию. В Windows эта директория обычно находится здесь: C:\Users\<username>\Appdata\Roaming\FreeCAD\Mod.

Реализация расширения

Создадим модуль FreecadImportMode.py в папке расширения и разместим в нем реализацию импорта файлов формата .box. Определим две функции: addExtension() и insert().

Функция addExtension() добавляет новый импортируемый формат данных в систему FreeCad.

def addExtension():
    FreeCAD.addImportType("Box file type (*.box)", "FreecadImportMod")

Функция insert() будет вызываться системой FreeCad автоматически при открытии файла формата .box. Первый аргумент функции - имя импортируемого файла, а второй - название документа, в который происходит импорт.

Внутри функции необходимо открыть входящий файл и прочитать параметры модели параллелепипеда:

def insert(file_name, document_name):
    with open(file_name) as box_file:
        data = json.load(box_file)
        width = data["width"]
        height = data["height"]
        depth = data["depth"]

Далее получаем объект документа и создаем эскиз с прямоугольником:

doc = FreeCAD.getDocument(document_name)

doc.addObject('Sketcher::SketchObject', 'Sketch')
doc.Sketch.Placement = FreeCAD.Placement(FreeCAD.Vector(0.0, 0.0, 0.0), 
                                         FreeCAD.Rotation(0.0, 0.0, 0.0, 1.0))
line1 = Part.LineSegment()
line1.StartPoint = (0.0, 0.0, 0.0)
line1.EndPoint = (width, 0.0, 0.0)
doc.Sketch.addGeometry(line1, False)

line2 = Part.LineSegment()
line2.StartPoint = (width, 0.0, 0.0)
line2.EndPoint = (width, height, 0.0)
doc.Sketch.addGeometry(line2, False)

line3 = Part.LineSegment()
line3.StartPoint = (width, height, 0.0)
line3.EndPoint = (0.0, height, 0.0)
doc.Sketch.addGeometry(line3, False)

line4 = Part.LineSegment()
line4.StartPoint = (0.0, height, 0.0)
line4.EndPoint = (0.0, 0.0, 0.0)
doc.Sketch.addGeometry(line4, False)

После создания эскиза выполняем операцию "выдавливания" на заданную величину "depth" и обновляем документ:

doc.addObject('Part::Extrusion','Extrude')
doc.Extrude.Base = doc.Sketch
doc.Extrude.DirMode = "Normal"
doc.Extrude.DirLink = None
doc.Extrude.LengthFwd = depth
doc.Extrude.LengthRev = 0.0
doc.Extrude.Solid = True
doc.Extrude.Reversed = False
doc.Extrude.Symmetric = False
doc.Extrude.TaperAngle = 0.0
doc.Extrude.TaperAngleRev = 0.0

doc.recompute()

В случае такого расширения изменений в интерфейсе FreeCad не требуется, поэтому файл InitGui.py оставляем пустым. При этом в файле Init.py необходимо вызвать функцию добавления нового формата в FreeCad:

import FreecadImportMod
FreecadImportMod.addExtension()

Получается такая структура файлов расширения:

/Mod/
 +-- FreecadImportMod/
     +-- Init.py
     +-- InitGui.py
     +-- FreecadImportMod.py

Размещаем папку с расширением в директории Mod (C:\Users\<username>\Appdata\Roaming\FreeCAD\Mod).

Результат

Запускаем FreeCad, создаем новый документ и переходим в меню "Файл -> Импортировать...", где выбираем файл нашей модели model.box.

По нажатию кнопки "Открыть" выполняется сценарий функции insert() расширения FreecadImportMode и в результате строится модель параллелепипеда с заданными в файле параметрами.

Исходный код рассмотренного примера доступен на GitHub.