Способы реализации API Fusion 360

Автор: | 03.02.2018

Введение
Различия между скриптами и Add-In приложениями
Основные концепции Fusion API
Организация доступа к данным:

Product;
Component;
Occurrence;
Proxies.

События в Fusion API
Редактирование и отладка приложений на языке Python

Введение

Fusion 360 API реализуется в виде скриптов (сценариев) и  Add-Ins приложений (надстроек), созданных при помощи языков программирования C++, Python и JavaScript. Процесс создания и отладки всех разновидностей приложений мало чем отличается. Поэтому рассмотрим шаги создания лишь одного вида приложений.

Выбираем на панели инструментов команду Scripts and Add-Ins.

В диалоговом окне можно выбрать скрипты или  Add-Ins приложения для запуска (Run) и редактирования (Edit), а также создать новые (Create).

Выбираем кнопку Create, откроется диалоговое окно Create New Script or AddIn. В нем указываем атрибуты приложения, включая выбор языка программирования.

В результате этих действий генерируется простое приложение, которое запускаем из окна Scripts and Add-Ins.

В результате запуска появляется  message box.

Для редактирования (или отладки) приложения в окне Scripts and Add-Ins выбирается кнопка Edit  или кнопка Debug из выпадающего списка.

Если при создании приложений были выбраны языки программирования Python, JavaScript или C++, для редактирования вызываются соответственно среды разработки приложений Spyder, Brackets или Visual Studio.

При создании script или add-in  в папке проекта  приложения  появляются файлы с соответствующими расширениями ( .py файл для Python, .js и .html файлы для JavaScript, .cpp и ряд других файлов для C++).

В дополнение к этим файлам создается .manifest файл – текстовый файл в JSON формате.  Он содержит дополнительную информацию, которую Вы, в основном, определили в диалоговом окне “Create New Script or Add-In”.

{
"autodeskProduct": "Fusion360",
"type":  "addin",
"id":    "62a9e55a-dbe4-408d-ad8b-cb802473725e",
"author":        "Brian Ekins",
"description":   {
"":      "This is a test add-in."
},
"version":       "V1",
"runOnStartup":  true,
"supportedOS":   "windows|mac"

}

Ниже приводится описание каждого из пунктов манифест файла:

    • autodeskProduct – это свойство всегда имеет значение “Fusion360”.
    • type – это свойство может быть “addin” или “script”.
    • id – идентификатор GUID приложения. Если Вы создали новое приложение, путем копирования существующего, то должны изменить GUID, чтобы он был уникальным.
    • author – имя автора.
    • description – описание приложения. Может быть выполнено на любом языке.
    • version – версия приложения, может быть “1.0.0”, “2016”, “R1”, “V2” и т.д.
    • runOnStartup – это свойство может быть true или false. Оно определяет, или приложение запускается автоматически.
    • supportedOS – это свойство может быть “windows”, “mac”, или “windows|mac”. Оно определяет, в какой операционной системе может быть загружено приложение, т.е. библиотеки какой операционной системы может использовать.
    • sourcewindows and sourcemac – это свойство для C++ и JavaScript приложений. Оно определяет, какая система вызывается для редактирования приложения, когда Вы выбираете кнопку «Edit» в диалоге «Scripts and Add-Ins» (см. рис.4.1). Например, для редактирования JavaScript приложения используется Brackets, если свойства определены как:

"sourcewindows": "AssemblyTree.js",
"sourcemac":     "AssemblyTree.js"

Различия между скриптами и Add-In приложениями

Как уже было сказано ранее, скрипты и Add-In приложения мало чем отличаются. Основное отличие заключается в том, как они выполняются, и срок их службы. Скрипт запускается пользователем через диалоговое окно Scripts and Add-Ins и останавливается сразу же после того, как функции скрипта завершат свое выполнение.

Add-In приложение обычно загружается автоматически, когда Fusion стартует. Add-In приложения, как правило, используют для создания одной или более команд, которые добавляются к пользовательскому интерфейсу. И эти команды могут запускаться в любой момент рабочей сессии  Fusion. Действие Add-In приложений может быть остановлено пользователем через диалоговое окно  Scripts and Add-Ins. При этом убирается интерфейсная часть, связанная с этим приложением.

Ниже приводится код, который автоматически генерируется, когда создается скрипт на языке Python.

import adsk.core, adsk.fusion, traceback
def run(context):
ui = None
try:
app = adsk.core.Application.get()
ui  = app.userInterface
ui.messageBox('Hello script')
except:
if ui:  ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

Следующий код приводится для автоматически созданного Add-In приложения:

import adsk.core, adsk.fusion, traceback
def run(context):
ui = None
try:
app = adsk.core.Application.get()
ui  = app.userInterface
ui.messageBox('Hello addin')
except:
if ui:  ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
def stop(context):
ui = None
try:
app = adsk.core.Application.get()
ui  = app.userInterface
ui.messageBox('Stop addin')
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

Обратите внимание, что код отличается только наличием функции stop. Эта функция вызывается Fusion когда add-in приложение выгружается пользователем через диалоговое окно Scripts and Add-Ins  или Fusion завершает свою работу. Функция stop  используется для удаления интерфейсной части, связанной с приложением.

Обе run и stop функции имеют один аргумент под названием «context «, который используется для передачи в приложение одного из 2-х значений (true или false). Эти значения определяют, как run или stop функции вызываются. Если аргумент функции run имеет значение true, это указывает, что приложение запускается автоматически, при значении false приложение запускается через диалоговое окно Scripts and Add-Ins. Если аргумент функции stop имеет значение true, это указывает, что приложение автоматически выгружается, при значении false приложение выгружается через диалоговое окно Scripts and Add-Ins.

Основные концепции Fusion API

Fusion API – объектно-ориентированное API, реализуемое через набор объектов. Многие из этих объектов имеют взаимно однозначное соответствие с теми сущностями, с которыми вы уже знакомы как пользователь Fusion. Например, выдавливание (extrusion) в модели Fusion представлено в API объектом ExtrudeFeature. Благодаря функциональным возможностям, предоставляемых объектом ExtrudeFeature, вы можете сделать то же самое, что и через пользовательский интерфейс. Например, вы можете создать новый extrusion, получить и установить его имя на временной шкале, подавить или удалить его, получить доступ и редактировать соответствующий ему эскиз.

Кроме объектов API, которые представляют собой сущности пользовательского интерфейса (User Interface, UI), есть объекты, которые обеспечивают функциональность, уникальную только для работы с API. Например, с помощью API, можно запросить модель и извлечь всю его геометрию. Кроме того, через  API можно создавать новые команды и добавлять их в пользовательский интерфейс Fusion.

Одно из основных отличий между использованием UI и API заключается в том, как конкретные объекты доступны. С помощью UI вы выбираете графические объекты в браузере. Новые объекты создаются с помощью специальных команд, например, таких как «Выдавливание» или “Box”, чтобы создать параллелепипед. С API объекты доступны через так называемую Объектную модель, которая представляет собой иерархическую структуру объектов.

На рисунке показан фрагмент объектной модели, который используется для создания элементов выдавливания.

Объект Application обеспечивает доступ к объектам-свойствам. Наиболее важным является объект-коллекция Documents. Объекты Document из этой коллекции могут содержать различные типы данных, необходимые для моделирования, и CAM данные. Объект Design в объекте Document есть корневым для представления данных моделирования. Все эскизы, особенности (features), объекты конструкционной геометрии, компоненты и т.д., содержатся в нем.

Не все API функции соотнесены к объектной модели. Есть много функций, которые отнесены к определенным классам. Это «статические» функции, к которым обращаются  через имя класса. Например, чтобы создать объект ObjectCollection, который используется для передачи группы объектов в функцию, вы можете использовать код (на языке Python), приведенный ниже.

// Create a new ObjectCollection.
objColl = adsk.core.ObjectCollection.create()

Коллекции обеспечивают доступ к набору объектов. Ниже приведен пример, в котором, начиная с объекта Sketch, получена коллекция SketchCircles и затем создан новый объект circle1, которому присваивается значение, возвращаемое методом addByCenterRadius.

# Get the SketchCircles collection from an existing sketch.
circles = sketch.sketchCurves.sketchCircles
# Call an add method on the collection to create a new circle.
circle1 = circles.addByCenterRadius(adsk.core.Point3D.create(0,0,0), 2)

Для создания более сложных объектов (например, extrude feature)  требуется предварительно ввести в диалоге множество различных данных.

Как это реализуется в программе, демонстрирует приведенный ниже код.

# Get the first profile from an existing sketch.
prof = sketch.profiles.item(0)
# Get the ExtrudeFeatures collection.
extrudes = rootComp.features.extrudeFeatures
# Create an extrusion input object that defines the input for an extrusion.
# When creating the input object, common inputs are provided as arguments.
extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
# Define the extent for the extrusion by a distance of 5 cm.
distance = adsk.core.ValueInput.createByReal(5)
extInput.setDistanceExtent(false, distance)
# Create the extrusion by calling the add method on the ExtrudeFeatures collection and passing it the ExtrudeInput object.
ext = extrudes.add(extInput)

Input-объекты обычно используются для подготовки данных для сложных объектов. Они являются эквивалентами диалогового окна. При этом метод add есть эквивалент кнопки OK. Definition-объекты похожи на Input-объекты, но используются не для создания новых объектов, а для редактирования существующих. Еще одно отличие между Definition-объектом и Input-объектом есть то, что свойства Input-объекта, которые принял Definition-объект, только для чтения.

Обратите внимание, что в приведенном выше коде, расстояние экструзии определяется путем предоставления объекта ValueInput. Объект ValueInput используется для определения каких-либо значений, которые приведут к созданию параметра. Объект ValueInput может быть определен с использованием действительного или строкового значения. Действительные значения всегда интерпретируются как единицы базы данных Fusion: длина в сантиметрах и углы в радианах. Строки по умолчанию интерпретируются с использованием текущих единиц документов. Например, указание «5» для длины интерпретируется как 5 дюймов.

В строках можно также указать единицы непосредственно. Например, строка «15 мм» интерпретируется как 15 мм, независимо от единиц документов по умолчанию. Строкой может быть также уравнение, которое может включать в себя существующие параметры вместе с числами, например, «D0/2». Любое допустимое уравнение, которое может быть введено, как значение в диалоге Fusion, может быть использовано в объекте ValueInput. Объекты ValueInput создаются статически с помощью методов createByString и createByReal класса adsk.core.ValueInput.

Организация доступа к данным

Доступ к данным Fusion осуществляется с помощью объектов Document, Product, Component, Occurrence и Proxy. Успешное использование API требует понимания каждого из этих типов объектов, как работать с ними, и как они взаимосвязаны.

Product

Группы взаимосвязанных данных хранятся внутри документа как объект класса Product. Хотя различные типы данных хранятся отдельно от документа, отношения между данными (то есть ссылки на Toolpath для разработки геометрии) сохраняются внутри документа.

Product – базовый класс, который представляет различные типы объектов product. Для получения данных проекта, есть объект класса Design, который является производным от класса Product. Документ может содержать только один объект класса Design. Ниже код JavaScript показывает, как получить объект класса activeProduct из приложения, а затем передать его объекту класса Design.

var app = adsk.core.Application.get();
var ui = app.userInterface;
var product = app.activeProduct;
var design = adsk.fusion.Design(product);
if (!design) {
ui.messageBox('No active Fusion design', 'No Design');
return;
}

Component

Fusion проект может содержать один или несколько объектов component. Component содержит различные типы Fusion геометрии (т.е. solids, sketches, construction geometry, sculpt forms и т.д.). Каждый Fusion документ по умолчанию содержит один component, который упоминается в качестве корневого компонента. В браузере корневой компонент представлен в узле верхнего уровня. В примере корневой компонент «Sample v1» содержит базовую конструкционную геометрию, два тела, один эскиз и одну конструкционную плоскость.

Ниже код JavaScript показывает, как получить корневой компонент из проекта, а затем создать новый эскиз в нем, используя XY конструкционную плоскость, входящую в этот компонент.

// Get the root component of the active design.
var rootComp = design.rootComponent;
// Create a new sketch on the xy plane.
var sketches = rootComp.sketches;
var xyPlane = rootComp.xYConstructionPlane;
var sketch = sketches.add(xyPlane, null);


Fusion UI предоставляет несколько способов для создания дополнительных компонентов в проекте. Узел добавляется в браузер для каждого нового компонента. При создании новой геометрии с помощью UI (например, эскизы, конструкционная геометрия и т.д.), он всегда создается в активном компоненте. При создании новой геометрии с использованием API, активный компонент не используется. Вместо этого, новая геометрия создается в рамках компонента, к которому API получил доступ. По умолчанию активен корневой компонент.

Occurrence

Occurrence (Вхождение) можно рассматривать как экземпляр компонента. Это есть вхождение компонента (а не сам компонент), который отображается и в браузере Fusion и в графическом виде. Когда новый компонент создан, он технически не представлен ​​в браузере в качестве компонента, а, скорее, как occurrence, который ссылается на этот компонент и носит имя этого компонента (ех.Component1:1).

Идея использования occurrences (вхождений) становится более очевидной, когда occurrence копируется, в результате чего создаются несколько экземпляров одного и того же компонента. При этом любые изменения, сделанные в одном экземпляре компонента, также отображаются во всех других экземплярах. Это потому, что вы редактируете единственный реальный компонент, и изменения отражаются во всех вхождениях, которые ссылаются на этот компонент.

Каждый Fusion документ содержит корневой компонент, представленный верхним узлом в дереве браузера.

Основные различия между компонентами и вхождениями перечислены ниже:

  1. Компонент содержит геометрию, в то время как occurrence не имеет собственной геометрии, а лишь отображает геометрию компонента, на который ссылается.
  2. Геометрия компонентов всегда определяется по отношению к пространству модели и компоненты не могут быть перемещены или связаны. Вхождения могут быть перемещены и связаны в любом месте проекта.
  3. Компоненты не отображаются непосредственно в окне браузера или графическом окне (за исключением корневого компонента). Вхождения отображаются и в браузере и в графических окнах.
  4. При изменении вида компонента изменяются все вхождения, которые ссылаются на этот компонент.
  5. Компоненты содержат не только геометрию. Они также могут содержать вхождения других компонентов, что позволяет, например, определить структуру сборки.

Для того чтобы создать новый компонент при помощи API, новое вхождение должно быть создано. За исключением корневого компонента, компонент не может существовать без, по крайней мере, одного вхождения, который ссылается на него. В примере ниже JavaScript код создает новый occurrence. Затем он создает эскиз и extrusion в этом компоненте. И, наконец, создается новый дополнительный occurrence компонента, что приводит к созданию двух экземпляров детали цилиндр.

// Create a new occurrence.
var trans = adsk.core.Matrix3D.create();
var occ = rootComp.occurrences.addNewComponent(trans);
// Get the associated component.
var newComp = occ.component;
// Create a new sketch on the xy plane and draw a circle.
var sketches = newComp.sketches;
var xyPlane = newComp.xYConstructionPlane;
var sketch = sketches.add(xyPlane, null);
sketch.sketchCurves.sketchCircles.addByCenterRadius(adsk.core.Point3D.create(0,0,0), 5.0);
// Create an extrusion.
var extInput = newComp.features.extrudeFeatures.createInput(sketch.profiles.item(0), adsk.fusion.FeatureOperations.NewBodyFeatureOperation);
var distance = adsk.core.ValueInput.createByReal(10.0);
extInput.setDistanceExtent(false, distance);
var ext = newComp.features.extrudeFeatures.add(extInput);
// Create a new occurrence for the component, offset by 15 cm in the X direction.
trans.setCell(0, 3, 15.0);
var newOcc = rootComp.occurrences.addExistingComponent(newComp, trans);

Выполнение кода приводит к созданию модели, показанной ниже.

Изменения, внесенные в компонент, влияет на оба вхождения. Тем не менее, геометрические преобразования (определяются векторами или матрицами), специфичны только для конкретного occurrence, поскольку они не влияют на содержание основного компонента.

Proxies

В приведенном выше примере с участием двух цилиндров, демонстрировалась  работа с несколькими ссылками (вхождениями) на одно представление геометрии (компонент).

На рисунке ниже одна из поверхностей компонента выделяется. В пользовательском интерфейсе для обоих вхождений рассматриваются две различные поверхности. Каждая поверхность имеет собственную позицию и ограничения на связи с гранями.

Эти поверхности есть «прокси» или копии фактической поверхности. Прокси необходимо для того, чтобы иметь возможность однозначно указать любую из двух граней. Прокси не является новой геометрией, оно лишь определяет полный путь к реальным примитивам, которые содержатся в компоненте. Например, в проекте есть два вхождения Component9.

Однако мы не видим вхождений Component9 в браузере, а вместо этого видим вхождения  (Component9:1 и Component9:2). Компонент содержит только один ‘RedFace’, но есть два экземпляра, которые отображаются в сборке. Для того, чтобы различать эти две поверхности, необходимо указать полный путь  к каждой. Поверхность в Component9:1 может быть представлена полным путем «Component9:1/RedFace». Поверхность в Component9:2 представлена полным путем «Component9:2/RedFace».

Проблема при работе с API –  Fusion не знает, какая из поверхностей двух вхождений  будет использоваться. Что необходимо для решения проблемы? Создать прокси-объект (копию) поверхности.

Пример использования прокси в теме Fusion 360 API сборка на Python:  As-Built Joint. См. также раздел темы Inventor API сборка на VBA:   Прокси-объекты.

События в Fusion API

События являются возможностью получать Вами уведомления, когда в Fusion происходят определенные действия. События являются ключевым компонентом команд Fusion. Именно через события ваша программа может знать, что пользователь нажал кнопку, связанную с вашей командой, а затем указал входные данные через командный диалог вашей надстройки, на который она может реагировать путем проверки ввода и показывая предварительный просмотр. Наконец, посредством событий Ваша программа будет уведомлена о том, чтобы выполнить команду и создать окончательный результат.

Большинство событий, поддерживаемых в настоящее время, связаны с командами, и вы можете увидеть конкретные примеры использования этих событий в теме о командах. Чтобы продемонстрировать общую концепцию, как использовать событие рассмотрим более общий случай, который исполняется Fusion, когда активируется рабочая среда. Основные понятия, обсуждаемые ниже, относятся ко всем событиям. Все поддерживаемые события перечислены в справке Fusion API под объектом, который поддерживает это событие. Например, объект UserInterface поддерживает четыре события, связанные с рабочей областью (рис.3.10): workspaceActivated, workspaceDeactivated, workspacePreActivate и workspacePreDeactivate.

Для реализации события нужно добавить функцию «handler» в ваш код и подключить этот обработчик к событию. Fusion будет вызывать функцию обработчика, когда в Fusion действие происходит, которое приводит к выполнению события. Даже если концепция реализации событий является такой же, реальная практика довольно сильно отличается для разных языков. Ниже приведены сценарии JavaScript и Python, которые делают одно и то же: подключаются к событию WorkspaceActivated и реагируют на него, но как вы видите, коды существенно отличаются.

Код JavaScript:

var MyWorkspaceActivatedHandler = function(args) {
var ws = args.workspace;
var app = adsk.core.Application.get();
var ui = app.userInterface;
ui.messageBox(ws.name + '
workspace was activated (JavaScript).');
};
function run(context) {
var app = adsk.core.Application.get();
var ui = app.userInterface;
ui.workspaceActivated.add(MyWorkspaceActivatedHandler);
ui.messageBox('Event connected.');
}

Для JavaScript обработчик событий реализован как функция MyWorkspaceActivatedHandler одним аргументом «args«. Что передано через этот аргумент отличается для различных событий.

Для подключения обработчика к событию вызывается метод add объекта WorkspaceEvent (который возвращается методом UserInterface.workspaceActivated) и ему передается обработчик события. Код JavaScript подключает событие, а затем приложение продолжает работать в фоновом режиме, что позволяет обработчику быть вызываемым и реагировать на события.

Код Python:

import adsk.core, adsk.fusion, traceback
handlers = []
class MyWorkspaceActivatedHandler (adsk.core.WorkspaceEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
ws = args.workspace
app = adsk.core.Application.get()
ui = app.userInterface
ui.messageBox(ws.name + ' workspace was activated (Python).')
def main():
app = adsk.core.Application.get()
ui = app.userInterface
onWorkspaceActivated = MyWorkspaceActivatedHandler()
ui.workspaceActivated.add(onWorkspaceActivated)
handlers.append(onWorkspaceActivated)
ui.messageBox('Event connected.')
adsk.autoTerminate(False)
main()

Для Python обработчик событий реализован как класс, который наследуется от adsk.core.WorkspaceEventHandler.

Сценарий Python (не надстройка) обычно прекращается автоматически. Чтобы сценарий продолжал работать, реагируя на события, вызывается функция autoTerminate, со значением False в качестве аргумента, чтобы указать Fusion, что сценарий должен продолжать работать в фоновом режиме.

Редактирование и отладка приложений на языке Python

При редактировании или отладке Python приложений  используется Spyder IDE (Integrated Development Environment). Когда вы создаете новое приложение, Spyder IDE уже содержит простейший код, который получает объект Fusion Application, затем использует объект Application для получения объекта UserInterface, и отображает окно сообщения.

Отладку приложения можно начать, еще находясь в Fusion. Здесь Вы выбираете приложение в диалоговом окне Scripts and Add-Ins и кнопку Debug из выпадающего меню. Это действие откроет приложение в Spyder с точкой прерывания на первой строке кода. Далее для продолжения отладки Вы можете использовать команду Debug file.

После того, как вы начали отладку вы можете использовать команды отладки на панели инструментов, чтобы перемещаться по коду. Spyder поддерживает типичные варианты пошагового выполнения кода:

  • пошаговое выполнение;
  • заход в функцию;
  • выход из текущей функции;
  • запуск до следующей точки останова;
  • выход из отладки.

Вы также можете добавлять и удалять точки остановки с помощью меню Debug или просто использовать горячую клавишу F12.

При отладке вы можете проверить значение переменной, используя окно Variable Inspector. Вы также можете использовать функцию печати в окне консоли для дальнейшего изучения переменных.

 

Автор: Николай Свирневский

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *