Макропрограммирование K3 в Python
Общие принципы
Команда macro в К3 может запускать два типа файлов – макропрограмму k3 (файл .mac) и макропрограмму на Python (файл .py). Расширение файла показывает системе, какой интерпретатор использовать.
Также в К3 есть возможность вставить блок кода на Python внутрь файла .mac.
Пример на макроязыке к3:
Для вставки блока кода на языке Python необходимо воспользоваться конструкцией:
<?python … ?>Например так:
key_ecd=0; //исключаем из анализа зависимости типа створки например шлегель unitcode=6900 <?python import k3 key_elemcode=k3.Var("key_ecd") elem_code=k3.GlobalVar("ElemCode") if elem_code.value in ("6900",): key_elemcode.value=1 ?> if key_ecd==1 { goto end; }
Для всех строчек кода внутри будет использоваться интерпретатор python.
Библиотека, функции и команды. Ключевые слова
Для использования функционала К3 в программу на Python нужно импортировать специальную библиотеку Import k3
Все функции и команды K3 вызываются как функции из этой библиотеки с использованием трёх основных принципов:
- Имя функции совпадает с именем команды, но обязательно должно быть написано в нижнем регистре;
- Все аргументы или ключевые слова передаются в функцию в том же порядке, как и при обычном вызове в макропрограмме;
- В Python нет специального обозначения для возвращения результата работы команды (# в макропрограмме). Поскольку команды – это тоже функции в Python, они возвращают значение обычным образом.
- Все функции К3 могут принимать на вход либо набор аргументов, либо список аргументов либо кортеж аргументов. Если на вход функции передан один список или один кортеж, то он будет "распакован", то есть функция примет элементы списка/кортежа как отдельные аргументы
Например, команда рисования линии, возвращающая ссылку на построенный объект
#line1 line 0 0 0 100 0 0 done
В python будет записываться как
line1 = k3.line(0, 0, 0, 100, 0, 0, k3.k_done)
k3.k_done – это объект соответствующий ключевому слову done. Все ключевые слова записываются для использования в Python таким образом: k3.k_<название>, где <название> — название ключевого слова.
Также аргументы могут быть переданы как список/кортеж, то есть запись
line_par = [0, 0, 0, 100, 0, 0, k3.k_done]
line1 = k3.line(line_par)
сработает так же, как предыдущая.
Учтите, что запись
line_par = [0, 0, 0, 100, 0, 0]
line1 = k3.line(line_par, k3.k_done)
уже вызовет ошибку, поскольку передан не один список, поэтому список не распаковывается, а считается первым аргументом, в качестве которого функция k3.line ожидает увидеть число - первую координату.
Ключевое слово для интерактивного ввода (то, что в макропрограмме записывалось знаком двоеточия ( : ), в Python запишется как k3.k_interact, например:
k3.line(0, 0, 0, k3.k_interact, k3.k_done)
построит линию от точки 0 до точки, введённой пользователем в интерактивном режиме.
Функции К3, запущенные через библиотеку К3 в Python, всегда возвращают числа в формате с плавающей точкой (double). Поэтому часто для дальнейшего использования их нужно перевести в целое, например
k3.getobjnum(k3.sysvar(60))вернёт ошибку, поскольку функция
getobjnumдолжна получать на вход целое число, аk3.sysvar()вернёт double. Необходимо писать так:
k3.getobjnum(int(k3.sysvar(60)))
Переменные и массивы K3
Все переменные, которые мы объявляем в коде на Python – это обычные переменные Python. Некоторые функции K3 требуют работы именно с переменными или массивами K3, например, функции objident и objgab3
k3.objident(<object>, <variable>)
k3.objgab3(<object>, <array>)
Здесь <variable> — это переменная k3, а <array> — массив К3 и именно такие объекты нужно передавать в функцию.
Переменная К3 в Python — это объект класса k3.Var, создаётся с помощью:
varname = k3.Var(<name>)
Где <name> — строка с именем переменной K3.
У этого объекта есть атрибут varname.value, который содержит значение этой переменной.
В результате, вызов функции objident будет выглядеть таким образом:
varname = k3.Var(‘obj1’) k3.objident(k3.k_interact, varname)
в результате ссылка на объект, выбранный пользователем в интерактивном режиме (ключ interact), будет присвоена переменной K3 с названием obj1, которой соответствует объект в Python с именем varname. Для того, чтобы добраться до этого объекта, используем обращение к атрибуту value
k3.move(varname.value, k3.k_done, 100, 0, 0)
Этой функцией мы сдвигаем объект, лежащий в переменной K3, на 100 по оси x
Массив K3 создаётся похожим образом:
arrname = k3.VarArray(<length>, <name>)
Здесь <length> — это длина будущего массива, а <name> — его имя в K3.
Не забывайте, что хотя Python может работать с динамическими списками, массивы K3 – статические, то есть содержат ровно столько элементов, какая длина указана при создании.
С точки зрения Python объект VarArray — это список объектов типа Var, каждый из которых – один элемент массива, например
for member in arrname: print(member.value)
выведет в консоль (в панель команд) значения всех элементов массива arrname
Аналогичным образом можно использовать и глобальные переменные и массивы, например:
gl_var = k3.GlobalVar(‘name’)
аналогично записи
global name;
в K3, то есть объявляет глобальную переменную с именем name. В результате её значение можно получить (gl_var.value), проверить, было ли оно раньше присвоено (k3.isvardef(‘name’)) и так далее.
Учтите, что функция isvardef принимает не саму переменную, а её имя, то есть её аргумент должен быть строкой.
Работа с глобальными массивами осуществляется через k3.GlobalVarArray
Получение параметров в макропрограмму (getpar)
Для того, чтобы программа на python могла получить параметры макро, переданные через строку запуска, также как и в макропрограмме, нужно воспользоваться функцией getpar.
income = k3.getpar()
в результате переменной income будет присвоен список значений, которые переданы по значению (без ключа или с ключом ByVal) и переменных K3 для того, что передано по ссылке (с ключом ByRef), в которых будут находиться переданные значения.
val0 = income[0].value val1 = income[1].value … и т.д.
В отличие от макропрограммы в Python при вызове getpar не объявляется явно количество значений, которые мы собираемся получить.
Вызов сторонней макропрограммы (команда macro)
Для вызова сторонней макропрограммы из скрипта на Python нужно передать в аргументы функции строку с путём и именем файла и список из передаваемых значений и ключей byref или byval
Например:
k3.macro(‘my_macro.mac’, [k3.k_byref, k3_var1, k3.k_byval, var2], k3.k_done)
Здесь первый параметр передаётся по ссылке (ключ byref), поэтому он должен быть переменной K3, второй параметр передаётся по значению (ключ byval), поэтому это обычная переменная с некоторым значением.
Внимание!
Версии программы до 09.10.2024 поддерживают только передачу параметров по ссылке (
byref)!
Для вызова программы на макроязыке к3 можно использовать модуль macroForPy. В этом случае не приходится заботиться о передаче ключей (ключ
byref). Достаточно вызвать функциюrunMacroи передать ей на вход имя макроса и список аргументов. Именованный параметрpathс значение по умолчанию папкаProtoнужен только если вам требуется вызвать макрос из папки отличной отProtoилиuserProto.Пример на языке python:
from macroForPy import runMacro ... def Draw(self): k3.setvarinst(1, "cZ_Fas", self.GetFasGabs()[1]) box_mac = priceinfo(self._bxtype, "MacroFile", self._default_box_macro, 2) obj2 = k3.sysvar(60) box = k3.Var() x, y, z = self.GetPosition() k3.GlobalVar("BoxKType").value = self._bxtype if len(box_mac) == 0: box.value = super().Draw() self._object = box.value else: runMacro( box_mac, [self._w, self._d, self._h, self._prmater, self._prmatdv, 0] ) objects = [] ...
Библиотека k3utils
Файл k3utils.py
Данная библиотека содержит различные по области приложения полезные функции, которые могут пригодиться при написании макро для К3 на Python
check_furntype(object, target)
Команда проверяет, является ли объект К3 object тем, что написано в target.
Например, check_furntype(panel, ‘panel’) вернёт True, если в переменной panel действительно лежит ссылка не панель К3-Мебель.
Возможные значения target:
- ‘panel’ — мебельная панель
- ‘profile’ — мебельный профиль
- ‘long’ — длинномер
- ‘accessory’ — комплектующий
- ‘hand’ — ручка
- ‘leg’ — опора
- ‘guide’ — направляющая
Проверка проводится по значению атрибута FurnType. При необходимости список доступных типов объектов можно расширить, для этого нужно пополнить словарь ключевых слов и проверочных строк checks в библиотеке.
msgwin(text_list, caption, button)
Команда выводит окно К3 с текстом, записанным в списке text_list построчно, заголовком caption и надписью на кнопке button.
errwin(text)
Команда выводит сообщение с заданной строкой текста, заголовком «Ошибка» и кнопкой OK для закрытия.
current_folder()
Команда возвращает строку с полным путём к папке, в которой находится текущий открытый файл К3
materials_from_subst(subst)
Команда возвращает список с id материалов номенклатуры из подстановки с id равным subst
putmsg_log(message, level)
Выводит в консоль К3 содержимое message.
Если message — список или кортеж — выводит его построчно
Если message — словарь, то выводит построчно пары Ключ Значение
Остальные типы message выводятся как есть
level — уровень сообщения putmsg. По умолчанию стоит 2
force_push_attr(obj, name, value)
Функция обеспечивает у объекта К3 obj наличие атрибута name с значением value.
Атрибут должен быть создан заранее.
Если у объекта не было этого атрибута, добавляет, если уже был, меняет значение на данное
get_niche(prompt)
Вызывает запрос на указание ниши с текстом запроса prompt
Возвращает None, если от выбора ниши отказались
Если ниша была выбрана возвращает список в следующем порядке:
- 0 — ссылка на изделие или каркас, в котором выбрана ниша
- 1, 2, 3 — габариты ниши
- 4, 5, 6, 7, 8, 9 — панели, ограничивающие нишу в порядке Нижняя, Верхняя, Задняя, Передняя, Правая, Левая. Если какая-то из панелей отсутствует, в этом месте будет None
Если ниша была выбрана, то функция переносит ПСК в ЛСК ниши
provide_carcase()
Проверяет наличие разобранного каркаса.
Если есть, возвращает True.
Если нет, но есть один собранный, разбирает его и возвращает True
Если есть несколько собранных, предлагает выбрать каркас для разбора и после выбора возвращает True
Если в сцене нет каркасов или несколько собранных, но пользователь отказался от выбора каркаса для разбора, возвращает False
is_salon()
Возвращает True, если программа — К3-Мебель и комплект — Салон. В остальных случаях возвращает False
acc_to_panel(acc_list, panel)
Привязывает к панели panel комплектующие из списка acc_list
k3_round(value)
Возвращает полученное число value, округленное согласно текущим настройкам округления координат K3
select_to_list()
Возвращает список с объектами, которые в данный момент являются выбранными
Пример программы для К3-Мебель на Python
Пример на языке python:
# -*- coding: utf-8 -*- # Макро для поиска объектов с плохими записями в базе import k3 #Импортируем библиотеку функций и команд К3 def Object_Is_Panel(obj): '''Функция проверяет по атрибуту FurnType, является ли объект мебельной панелью''' furntype = k3.getattr(obj, 'FurnType', '') #Функция К3 getattr return furntype[:2]=='01' and not furntype[2:]=='0000' def Check_Panel_Material(obj): '''Функция проверяет на корректность заданный для панели материал''' if not Object_Is_Panel(obj): return 1 priceid = k3.getattr(obj, 'PriceID', 0) if priceid==0: k3.putmsg('PriceID панели не задан или равен 0') #Функция К3 putmsg return 0 if k3.priceinfo(priceid, 'Thickness', 0, 1)==0: #Функция К3 priceifo k3.putmsg('Некорректный материал панели') return 0 return 1 k3.layers(k3.k_new, 'Possible_Errors') #Функция К3 layers с ключом new object_number = int(k3.sysvar(62)) #sysvar(62) – количество объектов, но в Python добавляем int() errnum=0 for current_number in range(object_number): if not Check_Panel_Material (k3.getobjnums(current_number+1)): k3.chprop(k3.k_layer, k3.k_partly, k3.getobjnums(current_number), k3.k_done, 'Possible_Errors') errnum=errnum+1 k3.putmsg(f'На слой Possible_Errors отправлено {errnum} объектов')
В основном теле программы создаётся новый слой командой layers с ключом new, затем идёт перебор всех объектов функцией getobjnums.
Заметьте, что функция getobjnums принимает в качестве аргумента номер объекта от 1 до sysvar(62), а счётчик в цикле range(object_number) в Python генерирует номера от 0 до object_number, поэтому объекты нумеруем, добавляя к значению счётчика 1.
Функция k3.putmsg() принимает на вход строку, поэтому можно использовать стандартное для Python форматирование строк.