Autodesk Fusion 360 — современная, динамично развивающаяся платформа для представления конструкторских идей в электронном формате. Система содержит среды для трехмерного моделирования, визуализации, инженерных анализов, работы с ЧПУ, подготовки документации и коллективной работы. Все удобно, практично, функционально. Чего же еще пожелать?! Может быть, более полного контроля? Иногда, кажется, программа сама делает то, что только зарождается в мыслях проектировщика. Интригует, правда, кнопка Scripts and AddIns ,
скромно расположившаяся справа на панели инструментов. Скрипты, дополнения, программные коды… Нужно ли в них «копаться», когда все и так работает неплохо? Попробуем разобраться. А для этого поставим несложную прикладную задачу. Пусть необходимо автоматически построить трехмерную модель цветка (рис. 1) по заданному максимальному диаметру (pDF).
Рис. 1
Начинаем с запуска упомянутой команды Scripts and AddIns. В открывшемся окне на вкладке Scripts щелкаем по кнопке Create (рис. 2).
Рис. 2
В следующем окне (рис. 3) выбираем язык программирования (в нашем случае Python), даем скрипту название (Flower), приводим описание и указываем автора. В окне создания скрипта особое внимание следует уделить полю Folder Location, где указывается расположение не только самого скрипта, но и всех необходимых для проекта папок и файлов.
Рис. 3
Помимо файла скрипта (Flower.py) в нашем проекте понадобится использовать изображение для текстурирования модели и текстовый документ для записи и считывания главного параметра — диаметра цветка. Таким образом, структура каталога проекта (Flower) будет иметь вид, показанный на рис. 4.
Рис. 4
В папке s проекта находится текстовый файл для хранения текущего значения диаметра бутона (в сантиметрах), а каталог m предназначен для файла текстуры.
В окне создания скрипта щелкнем по кнопке Create. Найдем в общем списке созданный скрипт (рис. 5), выделим его и нажмем кнопку Edit (готовый скрипт можно будет запускать командой Run).
Рис. 5
При первом использовании скриптов Python система Fusion 360 предложит загрузить бесплатную среду разработки Spyder. В дальнейшем (после установки) эта среда будет автоматически запускаться при открытии скриптов на редактирование (рис. 6).
Рис. 6
Инструментарий Spyder включает все необходимые возможности для отладки кода. Сохранение текущего модуля производится командой Save File , а запуск на выполнение — Run File .
При создании нового скрипта автоматически создается шаблон кода, включающий справочные метаданные, блок ссылок (import) на необходимые библиотеки и заготовку стартовой процедуры (run).
Внесем изменения в шаблон кода.
#AuthorStremnev
#DescriptionFlower Generator
# Добавлена ссылка на библиотеку математических функций,
# Добавлена ссылка на файловые функции операционной системы
import adsk.core, adsk.fusion, traceback, math, os.path
# Добавлен импорт функции генерации случайных чисел
from random import random
def run(context):
try:
# Объявлены переменные, доступные во всем проекте
global app, ui, mpath, spath
app = adsk.core.Application.get()
ui = app.userInterface
# Переменная путь к файлу параметров модели
spath=os.path.join(os.path.dirname(os.path.realpath(__file__)), ‘s\conf.txt’)
# Переменная – путь к графическому файлу текстуры цветка
mpath=os.path.join(os.path.dirname(os.path.realpath(__file__)), ‘m\cv1.png’)
except:
if ui:
ui.messageBox(‘Ошибка:\n{}’.format(traceback.format_exc()))
Следует обратить внимание на структуру try … except, которая позволяет контролировать появление ошибочных ситуаций в блоке try, перенаправляя выполнение в except.
Далее в процедуре run необходимо описать и вызвать команду для генерации цветка.
# Создание переменной cmdDef для новой команды
cmdDef = ui.commandDefinitions.itemById(‘Flower’)
if not cmdDef:
# Задание окна команды с указанным названием
cmdDef = ui.commandDefinitions.addButtonDefinition(‘Flower’,’Flower Generator’,’’)
# Создание обработчика flowerHandler события выполнения команды cmdDef
onCommandCreated = flowerHandler()
cmdDef.commandCreated.add(onCommandCreated)
handlers.append(onCommandCreated)
# Вызов команды на выполнение
cmdDef.execute()
# Задание ожидания действий пользователя до завершения модуля
adsk.autoTerminate(False)
Перед процедурой run нужно не забыть проинициализировать пустым значением переменную для обработчиков событий.
handlers = []
Созданный в процедуре run обработчик flowerHandler необходимо описать. Обработчик должен формировать окно команды для генерации цветка с необходимыми элементами управления. Для этого после процедуры run создадим соответствующий класс:
class flowerHandler(adsk.core.CommandCreatedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
# Обращение к команде, связанной с обработчиком
cmd = adsk.core.Command.cast(args.command)
# Обращение к коллекции элементов управления, связанных с командой
inputs = cmd.commandInputs
# Чтение в переменную v1 диаметра бутона из файла данных
try:
f = open(spath)
v1=int(f.readline())
f.close()
except:
# Инициализация переменной при ошибке чтения файла
v1=int(6)
# Создание в окне команды ‘слайдера’ для выбора диаметра бутона
inputs.addIntegerSliderCommandInput (‘slider_1’, ‘Диаметр бутона, cm’, 2, 9)
# Инициализация переменной для обращения к элементу’слайдеру’
slider = inputs.itemById(‘slider_1’)
# Задание шага ‘слайдера’
slider.spinStep=1
# Инициализация ‘слайдера’ значением из файла данных
slider.valueOne=v1
# Создание обработчика нажатия кнопки OK в окне генератора цветка
onExecute = flowersDialogOKEventHandler()
cmd.execute.add(onExecute)
handlers.append(onExecute)
except:
ui.messageBox(‘Ошибка:\n{}’.format(traceback.format_exc()))
Теперь следует описать обработчик нажатия OK в окне генератора. Это будет «основная» программная часть нашего проекта. Именно здесь будет формироваться геометрия модели цветка по выбранному диаметру бутона и здесь же мы определим параметры отображаемого материала.
class flowersDialogOKEventHandler(adsk.core.CommandEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
‘ Получение доступа к элементам управления окна генерации цветка
command = args.firingEvent.sender
slider = command.commandInputs.itemById(‘slider_1’)
# Чтение значения из ‘слайдера’ в переменную для диаметра бутона
pDF = slider.valueOne
‘ Инициализация переменной высоты бутона цветка
pHF = 4
# Создание нового документа во Fusion 360
app.documents.add(0)
# Получение доступа к корневому компоненту модели
design=app.activeProduct
design.designType=adsk.fusion.DesignTypes.ParametricDesignType
rootComp = design.rootComponent
# Создание переменной для коллекции эскизов модели
sketches = rootComp.sketches
# Создание эскиза на плоскости XZ
Sketch1 = sketches.add(rootComp.xZConstructionPlane)
# Получение доступа к эскизным объектам типа ‘окружность’
circles = Sketch1.sketchCurves.sketchCircles
# Создание эскизной окружности для основания бутона
circles.addByCenterRadius(adsk.core.Point3D.create(0,0,0),pDF/20)
# Сохранение эскизной окружности как первого профиля
profile1 = Sketch1.profiles.item(0)
# Получение доступа к рабочим плоскостям модели
planes=rootComp.constructionPlanes
# Подготовка переменной для параметров задания плоскости
planeInput=planes.createInput()
# Определение плоскости на расстоянии от существующей (XZ)
offset= adsk.core.ValueInput.createByReal(0.65*pHF)
planeInput.setByOffset(rootComp.xZConstructionPlane,offset)
# Завершение создания плоскости для промежуточного эскиза
plane1=planes.add(planeInput)
# Создание плоскости для эскиза вершины бутона
offset= adsk.core.ValueInput.createByReal(1*pHF)
planeInput.setByOffset(rootComp.xZConstructionPlane,offset)
plane2=planes.add(planeInput)
# Создание эскизной окружности для промежуточного сечения бутона
Sketch2 = sketches.add(plane1)
circles2 = Sketch2.sketchCurves.sketchCircles
circles2.addByCenterRadius(adsk.core.Point3D.create(0,0,0),pDF/4)
profile2 = Sketch2.profiles.item(0)
# Создание эскиза для верхнего контура бутона
Sketch3 = sketches.add(plane2)
# Создание коллекции точек
points = adsk.core.ObjectCollection.create()
n=18 # Задание количества точек верхнего контура
# Цикл формирования точек эскизного контура
for number in range(n):
# Задание координат текущей точки со случайной вариацией
RF = (0.4*random()+0.6)*pDF/2
u=number*360/n
c_x = RF * math.cos(u*math.pi/180)
c_y = RF * math.sin(u*math.pi/180)
# Добавление точки с найденными координатами в коллекцию
points.add(adsk.core.Point3D.create(c_x, c_y, 0))
# Добавление в коллекцию еще одной ‘первой’ точки как замыкающей
points.add(points.item(0))
# Создание контура в виде сплайна на основе коллекции точек
Sketch3.sketchCurves.sketchFittedSplines.add(points)
profile3 = Sketch3.profiles.item(0)
# Создание элемента ‘лофта’ по заданным эскизным профилям
loftFeats = rootComp.features.loftFeatures
loftVariant=adsk.fusion.FeatureOperations.NewBodyFeatureOperation
loftInput = loftFeats.createInput(loftVariant)
loftSectionsObj = loftInput.loftSections
loftSectionsObj.add(profile1)
loftSectionsObj.add(profile2)
loftSectionsObj.add(profile3)
loftInput.isSolid = True
# Контроль возможности реализации ‘лофта’
try:
loft1=loftFeats.add(loftInput)
except:
ui.messageBox(‘Попробуйте перезапустить построение’)
# Создание элемента ‘оболочки’
entities1 = adsk.core.ObjectCollection.create()
# Удаление верхней грани ‘лофта’ бутона
entities1.add(loft1.endFace)
shellFeats = rootComp.features.shellFeatures
isTangentChain = True
shellFeatureInput = shellFeats.createInput(entities1, isTangentChain)
# Задание толщины стенок бутона
thickness = adsk.core.ValueInput.createByReal(0.04)
shellFeatureInput.insideThickness = thickness
# Контроль возможности реализации ‘оболочки’
try:
shellFeats.add(shellFeatureInput)
except:
ui.messageBox(‘Попробуйте перезапустить построение’)
# Доступ к объекту для окрашивания ‘первому’ телу из структуры модели
body = rootComp.bRepBodies.item(0)
# Обращение к стандартной библиотеке материалов Fusion 360
matLibName=’Fusion 360 Appearance Library’
fusionMaterials = app.materialLibraries.itemByName(matLibName)
# Чтение в переменную образца материала из библиотеки
sColor = fusionMaterials.appearances.itemByName(‘Oak’)
# Создание копии материала
newColor = design.appearances.addByCopy(sColor, ‘MyRedFlowerColor’)
# Назначение материала телу ( элементу модели) бутону цветка
body.appearance = newColor
# Обращение к визуальным свойствам материала
prop = newColor.appearanceProperties.itemById(«opaque_albedo»)
tex = prop.connectedTexture.properties
# Связывание графического файла с текстурой
tex.itemById(«unifiedbitmap_Bitmap»).value = mpath
# Задание масштабирования текстуры
tex.itemById(«texture_ScaleLock»).value = False
tex.itemById(«texture_RealWorldScaleX»).value = 2
tex.itemById(«texture_RealWorldScaleY»).value = 2
# Задание ‘мощения’ текстуры по модели
tex.itemById(«texture_URepeat»).value = True
tex.itemById(«texture_VRepeat»).value = True
# Скрытие всех эскизов модели в рабочей области
for each_sketch in sketches:
each_sketch.isVisible=False
# Отображение модели цветка на весь размер рабочей области
app.activeViewport.fit()
# Сохранение текущего значения диаметра бутона в файле данных
try:
f = open(spath, ‘w’)
f.write(str(pDF) + ‘\n’)
f.close()
except:
ui.messageBox(‘Ошибка записи в файл’)
except:
if ui:
ui.messageBox(‘Ошибка выполнения команды’)
Сохраняем скрипт и запускаем его одним из описанных выше способов. В открывшемся диалоговом окне Flower Generator задаем диаметр бутона, нажимаем OK и «любуемся» результатом в рабочем поле Fusion 360 (рис. 7).
Рис. 7
Рис. 8
При следующем запуске скрипта диаметр бутона из предыдущего сеанса будет загружаться в «слайдер». Затем пользователь сможет генерировать необходимые ему конфигурации модели (рис. 8).
Итак, поставленная задача решена — скрипт автоматически генерирует управляемую параметрами модель цветка, в форму которого вносятся элементы случайной трансформации. Причем нам не приходится вручную выполнять множество рутинных операций по созданию вспомогательных плоскостей, эскизов и конструктивных элементов. Все это особенно актуально, если, например, необходимо смоделировать букет или небольшую клумбу. В такой ситуации можно использовать сохраненные модели отдельных цветков или, если вы «почувствовали» код, модернизировать скрипт для генерации многокомпонентной сборки.
Полезные ссылки:
- Официальная справочная система Fusion 360
http://help.autodesk.com/view/fusion360/ENU/?guid=GUIDA92A4B103781492594C647DA85A4F65A. - Объектная модель Fusion 360
http://help.autodesk.com/cloudhelp/ENU/Fusion360API/images/Fusion.pdf. - Fusion 360 API and Scripts (официальный форум)
https://forums.autodesk.com/t5/fusion360apiandscripts/bdp/22. - Сообщество программистов Autodesk в СНГ
http://adncis.org/fusion360api/. - Разработка приложений для 3dпроектирования (учебный курс)
https://academy.autodesk.com/course/119472/developanappfor3ddesignautomation