Показаны сообщения с ярлыком Python. Показать все сообщения
Показаны сообщения с ярлыком Python. Показать все сообщения

вторник, 9 июля 2013 г.

Адаптация Autocad Plant 3D: Скрипты Python. Задание матрицы трансформации (setTransformationMatrix)

На предыдущую статью получил вопрос от Max Grigorenko:
Доброго времени суток! Хорошая статья хоть и кратенькая. но вот вопрос у меня к Вам: знаете ли вы как работает функция "Задать матрицу трансформации (obj.setTransformationMatrix)"? Если Вас не затруднит,  пример с пояснениями.

Что такое матрица трансформации

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

Для чего это нужно?

Представим ситуацию. Мы хотим создать Цилиндр и Конус, повернуть их относительно оси Y на 90 градусов и перенести вдоль X на 300 единиц, а вдоль Y на 200.
Оба элемента создаются в одной точке, а потому их можно перетаскивать одновременно. Я вижу здесь 3 способа, как выполнить эту задачу.

1. Создаем цилиндр и конус и каждый из них отдельно переносим и вращаем

сn = CONE(s, 20, 0, 200, 0).rotateY(90).translate((300, 200, 0))

cl = CYLINDER(s, 50, 10,0).rotateY(90).translate((300, 200, 0))

2. Используем матрицу трансформации для переноса и вращения

t=mTransform().rotateY(90).translate((300, 200, 0))

сn = CONE(s, 20, 0, 200, 0).setTransformationMatrix(t)

cl = CYLINDER(s, 50, 10,0).setTransformationMatrix(t)

С точки зрения программиста, этот способ лучше, так как легче для понимания и обслуживания кода. Изменения, при необходимости, нужно будет вносить только в одном месте.

3. Сначала объединяем, потом переносим

сn = CONE(s, 20, 0, 200, 0)

cl = CYLINDER(s, 50, 10,0)
 
cn.uniteWith(cl) 

cl.erase()

cn.rotateY(90).translate((300, 200, 0))

Этот вариант применим к нашей задаче, но могут возникнуть случаи, когда второй вариант окажется предпочтительнее.

 Выводы

Матрицу трансформации удобно использовать в однотипных операциях переноса и вращения. Этот инструмент делает код более удобным для чтения и поддержки, но в простых скриптах можно обойтись и без неё. Какой инструмент использовать для достижения цели - ваш выбор.

 P.S.

При использовании .NET API все операции по переносу или вращению приходится выполнять с помощью класса Matrix3d. Для более полного понимания, что же такое матрица трансформации рекомендую обратиться к описаниям этого класса или  AcGeMatrix3d в ARX.

понедельник, 24 июня 2013 г.

Адаптация Autocad Plant 3D: Создание нестандартных элементов. Скрипты Python

К сожалению, информации о написании скриптов для Plant 3d очень мало. Основной учебник по созданию скриптов можно найти здесь.

 

 Начинаем писать скрипты


Первое, что нужно знать - все нестандартные скрипты должны быть сохранены в папке  "C:\AutoCAD Plant 3D 2013 Content\CPak Common\CustomScripts\". По-умолчанию папка CustomScripts не создается при установке, её требуется создать.

Пока не будем изобретать велосипед и возьмём пример из учебника. Создадим в папке CustomScripts текстовый файл TestScript.py и запишем в него следующее:
#----------------------------------------------------------------------------------------------------
 #Раздел 1
from varmain.primitiv import *
from varmain.custom import *

#Раздел 2
@activate(Group="Valve", Ports="2", TooltipShort="Test script", TooltipLong="This is a custom Testscript", LengthUnit="mm")
@group("MainDimensions")
@param(DN1=LENGTH, TooltipLong="Length of the Cylinder")
@param(DN2=LENGTH, TooltipLong="Length of the Cylinder")
@param(D=LENGTH, TooltipShort="Cylinder Diameter", Ask4Dist=True)
@param(L=LENGTH, TooltipLong="Length of the Cylinder")
@param(OF=LENGTH0)
@group(Name="meaningless enum")
@param(K=ENUM)
@enum(1, "align X")
@enum(2, "align Y")
@enum(3, "align Z")

#Раздел 3
def TESTSCRIPT(s,DN1=30.0, DN2=50.0, D=80.0, L=150.0, OF=-1, K=1, **kw):
   o1=CYLINDER(s, R=DN1/2, H=L, O=0.0).rotateY(90)
   o2=CONE(s, R1=DN2/2, R2=0, H=L, E=0)
   o1.uniteWith(o2)
   o2.erase()
   s.setPoint((0,0,0),(-1,0,0))
   s.setPoint((L,0,0),(1,0,0))
#----------------------------------------------------------------------------------------------------

Весь этот код рисует цилиндр и конус, объединённые в единое тело, и назначает два порта. Текст программы состоит из трех разделов.
  1. Импорт требуемых библиотек
  2. Описание метаинформации для Plant 3d
  3. Непосредственно, рисовалка
Подробнее о разделах.

Раздел 1


Здесь мне рассказать особо нечего. Библиотека  varmain.primitiv служит, видимо, для отрисовки, а varmain.custom - для создания именно нестандартных элементов. Можно использовать и другие библиотеки, но мне пока хватило этих.

Раздел 2


Здесь уже интереснее. Дело в том, что программе Plant 3d требуется рассказать, какие переменные, требуемые функции рисования, следует хранить в базе данных, показывать пользователю и запрашивать у пользователя при заполнении каталога. Если в вашей функции у переменных есть значения по-умолчанию, вы, возможно, не заметите отсутствия переменной в интерфейсе программы. Разве что размеры отрисованных тел будут одинаковыми там, где используется эта переменная.
Строка @activate говорит программе, что за элемент мы создаем.
Строка @group("MainDimensions") обозначает начало списка параметров.
Строка @param(DN1=LENGTH, TooltipLong="Length of the Cylinder") - это параметр. В данном случае, параметр DN1 с подсказкой, которая будет появляться в редакторе каталогов, "Length of the Cylinder".
Назначение группы параметров @group(Name="meaningless enum") мне пока непонятно. В инструкции говорится, что этот нумератор указывает вдоль какой оси чертить элемент. Может потом разберусь.

Раздел 3


Ну и самое интересное - рисование. Вычерчивание модели элемента происходит с помощью примитивов, с которыми можно производить операции сложения, вычитания и пересечения.
Список примитивов (насколько я понял, полный):
  1. Отвод
  2. Переходный отвод
  3. Сегментный отвод
  4. Коробка (точнее, параллелепипед)
  5. Конус
  6. Цилиндр
  7. Эллиптическое днище
  8. Эллиптическое днище 2
  9. Эллипсоид вращения
  10. Полусфера
  11. Пирамида
  12. Тело перехода от прямоугольника к кругу
  13. Сегмент сферы
  14. Тор-сферическое днище
  15. Тор-сферическое днище 2
  16. Тор-сферическое днище H
  17. Тор
Список операций над примитивами:
  1. Объединение (obj.uniteWith)
  2. Вычитание (obj.subtractFrom)
  3. Пересечение (obj.intersectWith)
  4. Удаление (obj.erase)
  5. Поворот вокруг оси X (obj.rotateX)
  6. Поворот вокруг оси Y (obj.rotateY)
  7. Поворот вокруг оси Z (obj.rotateZ)
  8. Перенос (obj.translate)
  9. Задать матрицу трансформации (obj.setTransformationMatrix)
  10. Задать порт (obj.setPoint)

Тестирование скриптов - немного теории


Итак, скрипт есть. Нужно его протестировать.

Для тестирования скриптов на Python в Plant 3d используется библиотека "PnP3dACPAdapter.arx". Для её загрузки можно использовать команду _appload в командной строке Autocad, использовать меню или ленту, или команду lisp:

 (arxload "PnP3dACPAdapter.arx")

Только после загрузки этой библиотеки можно проводить тестирование скрипта. Для этого используется команда lisp TESTACPSCRIPT с параметрами или без них:
(TESTACPSCRIPT "TESTSCRIPT")
(TESTACPSCRIPT "TESTSCRIPT" "D1" "300.5")
(TESTACPSCRIPT "TESTSCRIPT" "L" "40" "D1" "300.5" "D2" "88.9")

В начале разработки у меня постоянно выходила ошибка в командной строке:

(TESTACPSCRIPT "TESTSCRIPT")
Traceback (most recent call last):
  File ".\variants\varmain\__init__.py", line 94, in create
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
nil

Оказалось, что это единственная ошибка, которая выводится (может есть и ещё, но мне выходила только эта). Забыл переменную, не поставил запятую, ошибка ли логики или синтаксиса - ошибка всегда одна и та же. Без подробностей.

Plant 3d устроен таким образом, что раз загруженный скрипт остается в памяти до окончания сеанса.

Но, прежде чем вы приступили к тестированию, скрипт должен быть зарегистрирован. Это выполняется с помощью команды Plant 3d PLANTREGISTERCUSTOMSCRIPTS. При вызове этой команды происходит следущее:
  1. Файл скрипта компилируется и создается файл .pyc (в нашем случае TESTSCRIPT.pyc) в папке CustomScripts
  2. Метаданные о скрипте вносятся в файл ScriptGroup.xml. Если этот файл отсутствует - он создается. Этот файл содержит информацию о всех созданных нестандартных скриптах и к каким группам они относятся.
  3. Создается файл TestScript.xml в папке CustomScripts. Этот файл содержит метаданные о скрипте и используемых в нем переменных.
  4. Создается или обновляется файл variants.xml. Он содержит подсказки скрипта, используемых в нем параметров, значения нумераторов.
  5. Создается или обновляется файл variants.map. Содержит служебную информацию.

 Тестирование скриптов - последовательность действий


Набив шишки на том, что скрипты не загружаются повторно, если автокад не закрывался, выработал для себя следующий алгоритм:
  1. Внести изменения в файл .py.
  2. Открыть Plant 3d
  3. Выполнить команду PLANTREGISTERCUSTOMSCRIPTS
  4. Закрыть Plant 3d
  5. Открыть Plant 3d
  6. Загрузить библиотеку для тестирования.  (arxload "PnP3dACPAdapter.arx")
  7. Выполнить скрипт (TESTACPSCRIPT "TESTSCRIPT")
  8. Если скрипт требует доработки, повторить с пункта 1 (если вносить изменения в скрипт не закрывая Plant 3d, то шаг 2 можно исключить)
Для упрощения тестирования я создал кнопку к которой привязал команду

^C^C^P(arxload "PnP3dACPAdapter.arx")(TESTACPSCRIPT "TESTSCRIPT")

Это позволило объединить шаги 6 и 7 в один шаг.

Подготовка скриншотов


Для создания изображений тела или блок в Plant 3d служит команда PlantSnapShot. После её запуска следует указать, что нам нужен снимок детали, далее выбрать саму деталь, указать размер снимка и сохранить его в png с тем же именем, что и файл скрипта + окончание в зависимости от размера снимка. Например:
  • TESTSCRIPT_32.png
  • TESTSCRIPT_64.png
  • TESTSCRIPT_200.png
В учебнике об этом ни слова, но если вы хотите создать эскиз для своей детали, чтобы он отображался в редакторе каталогов на странице с типоразмерами, следует его сохранить в размере 640px. Соответственно, название файла будет выглядеть так:

  • TESTSCRIPT_640.png

Заполнение каталога 


Теперь, создав скрипт, протестировав его, создав все требуемые изображения, мы можем добавить новый элемент в каталог.
 Я не создал снимки для детали TESTSCRIPT, поэтому она здесь без рисунка, но, тем не менее, её можно выбрать и внести для неё сведения. Далее работа с каталогами и миникаталогами происходит по обычным сценариям.

Спасибо за внимание. Буду рад комментариям, вопросам.

четверг, 20 июня 2013 г.

Адаптация Autocad Plant 3D: Создание нестандартных элементов. СППК

Мой предыдущий пост был об основных возможностях редактора спецификаций. Я постарался осветить те моменты, о которые спотыкался неоднократно, вырабатывая свою методику работы. Но, работая со стандартными элементами, не давал мне покоя вопрос: можно ли создавать нестандартные? Как оказалось, этим вопросом задавался не только я. +Александр Щетинин предложил попробовать добавить СППК в базу оборудования.

Итак. Представим ситуацию: в Plant 3d необходимо создать базу, содержащую предохранительные клапаны Благовещенского Арматурного завода. 

На мой взгляд, блок предохранительных клапанов не является оборудованием. Да и не встретил я в Plant 3d базы оборудования. Потому добавлять элементы будем в каталог.
Реализовать эту задачу можно двумя путями: используя разработанные в Autocad модели и используя программирование.
 

Путь Первый 


В стандартных обучающих роликах и материалах рассказывается, как можно создать элемент каталога из трехмерной модели, выполненной в Autocad. У этого подхода есть очевидные плюсы - добавить в каталог новый элемент может любой, кто умеет хоть сколько-нибудь работать с редактором каталогов и Autocad. Минусы тоже есть - процесс получается очень трудоёмкий.

Мне не удалось хоть сколь-нибудь продвинуться в процессе создания параметрических моделей и использования их совместно с редактором спецификаций. В стандартном варианте со статическими моделями набор работ выглядит так:
  1. Создать модель элемента
  2. Преобразовать элемент в блок
  3. Назначить в Plant 3d порты
  4. Добавить блок в редакторе спецификаций в новый каталог и назначить ему атрибутивную информацию
  5. Добавить элемент из каталога в миникаталог
  6. Можно тестировать и вставлять в модели новый элемент
Требуется также учесть, что каждый элемент обладает уникальным набором параметров, и с каждым должна быть проведена работа по указанному списку. Не думаю, что большим преувеличением будет сказать, что подобная работа может отнимать от 1 до 4 часов на элемент, в зависимости от опыта исполнителя. 

Путь Второй


Оказывается Plant 3d всё же обладает расширяемостью большей, чем об этом говорится в продающих буклетах. 

Дело в том, что все "рисовалки" в Plant 3d выполнены скриптами на языке Python.
Последовательность работ в этом случае такова:
  1. Создание скрипта для рисования модели элемента.
  2. Регистрация скрипта в Plant 3d. При этом создается ряд вспомогательных файлов.
  3. Наполнение каталога.
  4. Добавление элемента из каталога в миникаталог
  5. Использование в модели
Информации по этой теме мне удалось найти крайне мало. С этим языком сталкиваюсь впервые. Но кое-чего добиться удалось.

На рисунке представлен результат вставки элемента  БПУ 50-40 из миникаталога.
 

На панели инструментов появляется новый элемент.

В редакторе каталогов можно добавлять новый элемент - Блок предохранительных клапанов.

В каталоге можно редактировать свойства элементов и портов.


Что с трудозатратами?  На разработку скрипта мне потребовалось 4 дня. Но, нужно иметь в виду, что модель не тривиальна, язык не знаком, информации мало. Думаю, сейчас подобная задача заняла бы 1-2 дня.

О том, как писать скрипты и использовать их в Plant3d расскажу в следующий раз.