Макропрограммирование K3 в Python

Материал из K3-Macro
Button2 py processed.png

Общие принципы

Команда macro в К3 может запускать два типа файлов – макропрограмму k3 (файл .mac) и макропрограмму на Python (файл .py). Расширение файла показывает системе, какой интерпретатор использовать.

Также в К3 есть возможность вставить блок кода на Python внутрь файла .mac.

K3.png

Пример на макроязыке к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 до точки, введённой пользователем в интерактивном режиме.

Idea.png

Функции К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.

Idea.png

Не забывайте, что хотя 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
…
и т.д.
Idea.png

В отличие от макропрограммы в 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), поэтому это обычная переменная с некоторым значением.

Warning.png

Внимание!

Версии программы до 09.10.2024 поддерживают только передачу параметров по ссылке (byref)!

Idea.png

Для вызова программы на макроязыке к3 можно использовать модуль macroForPy. В этом случае не приходится заботиться о передаче ключей (ключ byref). Достаточно вызвать функцию runMacro и передать ей на вход имя макроса и список аргументов. Именованный параметр path с значение по умолчанию папка Proto нужен только если вам требуется вызвать макрос из папки отличной от Proto или userProto.

Button2 py processed.png

Пример на языке 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

Button2 py processed.png

Пример на языке 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 форматирование строк.