Опубликован: 21.02.2012 | Уровень: специалист | Доступ: платный
Лекция 3:

AutoLISP в среде Visual LISP

Функции, работающие с расширенными данными

К любому примитиву рисунка можно добавлять расширенные данные, т. е. текстовые или числовые данные, которые желательно хранить вместе с геометрией (например, марки материалов, наименования узлов, секций и т. п.). Обычно наличие такой информации позволяет разрабатывать программы связи с базами данных (рассмотрение таких программ не является предметом настоящей книги). Расширенные данные связываются с именем определенного приложения. У одного графического примитива могут быть данные нескольких приложений, которые располагаются последовательно в определенной структуре.

Если расширенные данные присоединены к примитиву, то в базе рисунка они следуют за обычными данными (DXF-коды этих данных находятся в диапазоне от -2 до 239). Извлечь расширенные данные можно с помощью функции entget, при обращении к которой нужно указывать имя приложения, с которым они связаны. В списке, возвращаемом функцией entget, расширенные данные находятся в подсписке, начинающемся с DXF-кода -3 (признак наличия расширенных данных), в котором далее располагаются точечная пара с кодом 1001 (начало расширенных данных и имя приложения, с которым они связываются) и точечные пары с DXF-кодами 1000, 1002-1071. Назначение DXF-кодов расширенных данных описывается в табл. 3.6.

Таблица 3.6. Назначение DXF-КОДОВ расширенных данных
Код Назначение
1000 Строковая константа длиной не более 255 знаков (256-й знак зарезервирован под символ с кодом 0)
1001 Строковая константа, используемая только для указания имени приложения, длиной не более 31 знака (если код 1001 попадает внутрь списка, организуемого с помощью DXF-КОДОВ 1002, то он интерпретируется как обычная константа, а не имя приложения; см. далее описание DXF-кода 1002). Имя приложения должно состоять только из цифр, латинских букв и символов
1003 Имя слоя, с которым связываются расширенные данные
1005 Метка объекта в базе чертежа
1010 Трехмерная точка (три вещественных числа)
1040 Вещественное число
1070 16-битовое целое число (со знаком или без знака)
1071 32-битовое целое число со знаком (длинное целое). Хотя система AutoCAD хранит данные группы с кодом 1071 как длинное целое, AutoLISP возвращает их как вещественные числа. Функциям entmake и entmod в точечной паре с кодом 1071 можно подавать либо целые числа, либо вещественные. ObjectARX трактует данные группы 1071 как длинные целые
1002 Строка, принимающая значения "{" или "}" и имеющая тот же смысл, что и левая и правая круглые скобки в обозначении списка. С помощью группы с кодом 1002 можно формировать в расширенных данных списковые структуры (они должны начинаться открывающей скобкой с кодом 1002, затем должны идти данные, включаемые в список, а закрывающая скобка с кодом 1002 завершает оформление списка). См. также замечание об интерпретации данных группы 1001 в таком списке
1004 Двоичные данные длиной не более 127 байт. Обрабатываются только в ObjectARX
1011 Трехмерная точка, интерпретируемая как положение в МСК. Такая точка перемещается, масштабируется, поворачивается и симметрируется одновременно с родительским примитивом рисунка. Если точка попадает в рамку выбора команды РАСТЯНУТЬ (STRETCH), то она подвергается операции растягивания вместе с родительским примитивом
1012 Трехмерная точка, интерпретируемая как перемещение в МСК. Такая точка не перемещается и не растягивается одновременно с основным примитивом, но участвует вместе с ним в операциях масштабирования, поворота и симметрирования
1013 Трехмерная точка, интерпретируемая как направление в МСК. Такая точка не масштабируется, не перемещается и не растягивается одновременно с основным примитивом, но участвует вместе с ним в операциях поворота и симметрирования. Вектор с координатами, взятыми из группы с кодом 1013, является нормализованным, т. е. единичной длины
1041 Вещественное число, интерпретируемое как расстояние. Оно масштабируется одновременно с родительским примитивом
1042 Вещественное число, интерпретируемое как масштабный коэффициент. Масштабируется одновременно с родительским примитивом

Как было сказано выше, расширенные данные связываются с именем конкретного приложения. Имена приложений хранятся в рисунке в таблице символов "APPID". Чтобы занести имя приложения в эту таблицу, следует пользоваться функцией rеgарр:

(rеgарр <приложение>) 

Параметр <приложение> должен быть текстовой строкой (по возможности нужно выбирать имя приложения таким, чтобы оно не совпадало с именами приложений других разработчиков - иначе это приведет к неправильной работе с расширенными данными). Функция rеgарр возвращает nil в случае ошибки (nil возвращается также, если приложение с таким именем уже регистрировалось).

Функция entmake может создать примитив и сразу присоединить к нему расширенные данные. С помощью функции entmod можно добавить расширенные данные к существующему графическому объекту.

Пример

Предположим, что к последнему существующему примитиву рисунка (пусть им является отрезок) нужно добавить расширенные данные, связанные с приложением "GENHULL":

  • (setq le (entget (entlast) ) ) - сохраняет в переменной le список последнего примитива, у которого еще нет расширенных данных: ((-1 . <Имя объекта: 14аа578>) (0 . "LINE") (330 . <Имя объекта: 14aa4f8>) (5 . "2F") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (62 . 1) (100 . "AcDbLine") (10 85.4655 223.335 0.0) (11 187.712 167.209 0.0) (210 0.0 0.0 1.0)) ;
  • (setq edata '((-3 ("GENHULL" (1000 . "Пластмасса") (1070 . 57))))) - сохраняет в переменной edata список с расширенными данными, которые будут добавлены к списку le (добавляются текстовая строка с DXF-кодом 1000 и целое число с DXF-кодом 1070);
  • (setq le2 (append le edata)) - объединяет списки le и edata и формирует новый список le2: ((-1 . <Имя объекта: 14аа578>) (0 . "LINE") (330 . <Имя объекта: 14aa4f8>) (5 . "2F") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (62 . 1) (100 . "AcDbLine") (10 85.4655 223.335 0.0) (11 187.712 167.209 0.0) (210 0.0 0.0 1.0) (-3 ("GENHULL" (1000 . "Пластмасса") (1070 . 57)))) ;
  • (entmod le2) - модифицирует примитив по новому списку и возвращает то же значение, что и предыдущее выражение;
  • (entget (entlast) '("GENHULL")) - получает список нового последнего примитива вместе с расширенными данными, относящимися к приложению "GENHULL": ((-1 . <Имя объекта: 14аа578>) (0 . "LINE") (330 . <Имя объекта: 14aa4f8>) (5 . "2F") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (62 . 1) (100 . "AcDbLine") (10 85.4655 223.335 0.0) (11 187.712 167.209 0.0) (210 0.0 0.0 1.0) (-3 ("GENHULL" (1000 . "Пластмасса") (1070 . 57)))) .

Размер расширенных данных любого примитива не должен превышать 16 килобайт (16383 байта). Поэтому по мере добавления таких данных их размер нужно контролировать. Этой цели служат две функции:

  • (xdsize <список>) - получает размер в байтах, необходимый для сохранения расширенных данных; аргумент <список> - это список с расширенными данными, начинающийся с DXF-кода -3;
  • (xdroom <примитив>) - возвращает целое число - количество свободных байтов в зоне расширенных данных примитива.

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

Другие функции

Коротко рассмотрим другие функции языка AutoLISP.

Функция alert позволяет вывести на экран диалоговое окно с сообщением системы AutoCAD. Синтаксис функции:

(alert <сообщение>) 

Функция возвращает nil. Максимальная длина строки <сообщение> зависит от многих вещей (в частности, от платформы) и может быть вычислена пользователем самостоятельно. В случае превышения допустимой длины AutoCAD обрезает сообщение. При необходимости вывести сообщение в несколько строк нужно использовать знаки конца строки ("\n").

Пример:

(setq lines (strcat "Я вас любил: любовь еще, быть может,\n" 
"В душе моей угасла не совсем;\nНо пусть она вас больше не тревожит-\n" 
"Я не хочу печалить вас ничем.")) 
(alert lines) выводит на экран окно, изображенное на рис. 3.4.
 Диалоговое окно, вызываемое функцией alert

Рис. 3.4. Диалоговое окно, вызываемое функцией alert

В данном примере выведены четыре строки, поскольку трижды был использован знак конца строки. Выход из диалогового окна, изображенного на рис.3.5, - щелчок по кнопке ОК.

Рассмотрим несколько полезных геометрических функций.

  • (inters <точка1> <точка2> <точка3> <точка4> [<признак>]) - если аргумент <признак> отсутствует или задан отличным от nil, функция вычисляет пересечение двух отрезков. Первый имеет концы в точке1 и точке2, а второй - в точкеЗ и точке4. Точки заданы соответствующими аргументами: <точка1>, <точка2>, <точка3> и <точка4>. Если аргумент <признак> задан и равен nil, то функция вычисляет пересечение двух прямых, проходящих через отрезки. Если все аргументы точки являются трехмерными, то функция inters ищет пересечение в трехмерном пространстве. Если хотя бы одна из точек имеет только две координаты, то вычисляется пересечение проекций отрезков на текущую плоскость построений. Точки задаются как списки из двух или трех вещественных чисел;
  • (polar <точка> <угол> <расстояние>) - возвращает координаты точки, которая отстоит от исходной точки, определяемой аргументом <точка> на заданное расстояние с помощью аргумента <расстояние>; вектор, идущий из исходной точки в вычисляемую новую точку, должен образовывать (в проекции на текущую плоскость построений) с осью Х заданный угол, определяемый аргументом <угол>, в радианах;
  • (textbox <список>) - возвращает список из двух точек, являющихся точками диагоналей прямоугольника, описанного вокруг надписи. Надпись задается с помощью аргумента <список>, который должен иметь формат списка текстового примитива (в том виде, в каком его вернула бы функция entget). Если аргумент <список> не содержит каких-либо параметров, то функция textbox при вычислении дополняет его текущими установками рисунка;
  • (osnap <точка> <режим>) - возвращает результат применения к точке, заданной аргументом <точка>, функции объектной привязки с установками режимов, заданными в аргументе <режим>. Режимы привязки указываются с помощью строки, в которой без пробелов, через запятую перечисляются наименования режимов: "_end", "_mid", "_int", "_nea", "_nod" и т. д. На результат операции оказывает влияние значение системной переменной APERTURE.

Примеры:

  • (inters '(2.25 4.50) '(-2.25 6.335) '(1.27 0.50) '(-8.65 -2.30)) - возвращает nil;
  • (inters '(2.25 4.50) '(-2.25 6.335) '(1.27 0.50) '(-8.65 -2.30) nil) - возвращает (7.64593 2.29966);
  • (polar '(16.32 4.782) 0.345 4.79) - возвращает (20.8278 6.40196);
  • (osnap '(16.32 4.782) "_end,_mid") - возвращает координаты точки, уточненной с помощью применяемых одновременно функций объектной привязки к конечной и средней точкам.

К полезным функциям, кроме того, относятся функции работы с элементами меню:

  • menucmd - операции с пунктами меню;
  • menugroup - работа с группой меню.

Подробности описания этих функций можно найти в справочной системе AutoCAD.

В языке AutoLISP есть некоторое количество функций для работы с диалоговыми окнами. Функции работы с диалогами - load_dialog, unload_dialog, start_dialog, done_dialog, term_dialog, new dialog.

Функции работы С ПОЛЯМИ - action_tile, get_tile, set_tile, mode tile, get_attr, client_data_tile.

Функции работы с графическим кнопками - slide_image, start_image, vector image, end_image, dimx_tile, dimy_tile, fill_image.

Функции работы со списками - start_list, end_list, add_list.

К рассматриваемой версии языка AutoLISP в качестве расширения могут быть добавлены более ста функций, реализующих технологию ActiveX и дополняющих возможности пользователя по созданию эффективных программных продуктов на базе системы AutoCAD 2000. Все эти функции начинаются с префиксов vir-, via- и vlax-, и перед первым обращением к любой из них надо выполнить функцию загрузки (без этого они не будут доступны):

(vl-load-com) 

Технология ActiveX облегчает и ускоряет доступ к примитивам и их характеристикам. К примитивам рисунка можно прикрепить другие объекты, называемые реакторами. Реакторы отслеживают определенные будущие события (например, перемещение или удаление примитива, открытие, сохранение или закрытие рисунка, вставку блока или внешней ссылки). Как только проверяемое событие происходит, реакторы с помощью специальных средств выполняют запрограммированные операции.

Упражнение

С помощью справочной системы определите назначение функций cons, load, polar.

Ключевые термины

Возвращаемое значение - результат вычисления интерпретатором AutoLISP выражения, записанного в процедуре.

Переменная - именованный участок памяти для хранения данных.

Символы AutoLISP- это слова, состоящие из группы буквенно-цифровых знаков и являющиеся именами функций или переменных, используемых для хранения данных пользователя.

Загрузка файла в AutoCAD - операция загрузки файла AutoLISP в программу с помощью функции Load.

Функции присвоения setq - функция, которая присваивает переменной значение выражения.

Функция command - функция AutoLISP, которая имитирует ввод пользователя в командной строке AutoCAD с клавиатуры.

Краткие итоги

AutoLisp является внутренним языком программы AutoCAD. Процедуры AutoLisp представляют собой набор функций с задаваемыми параметрами и аргументами. Встроенные функции обладают широкими возможностями создания и редактитования чертежных объектов.

Вопросы

  1. Когда начинает работать интерпретатор AutoLISP?
  2. С какими типами объектов работает AutoLISP?
  3. Какая функция имитирует ввод данных пользователем в командную строку?
  4. Каков синтаксис функций в AutoLISP?
  5. На какие группы по назначению можно разбить встроенные функции?
  6. Как используются битовые флаги в аргументах функций?
Алексей Тимонин
Алексей Тимонин
Алексей Потапкин
Алексей Потапкин

Здравствуйте.

Подскажите, пожалуйста, каким образом можно передать параметры в макрос написанный в Autocad на VBA? Например, есть процедура, которая отрисовывает заштрихованный прямоугольник (см. ниже). Как её изменить, чтобы на входе от пользователя требовалось ввести также в качестве параметров координаты углов прямоугольника?

Public Sub DrawHatchedBox()

...

End Sub

Сергей Ивков
Сергей Ивков
Россия, Геленджик
Юлия Мягчилова
Юлия Мягчилова
Россия