Лекции по САПР. ПРОГРАММИРОВАНИЕ на AutoLISP.

Составитель - Толстоба Н.Д. http://aco.ifmo.ru/~nadinet

Программирование на AutoLISP

Введение

Цель этого документа - познакомить Читателя с языком программирования AutoLISP, на котором были написаны многие встроенные функции AutoCAD. Эта лекция в доступной форме описывает особенности языка, без особых углублений в подробное описание функций, которое Вы можете найти в любом справочнике.
Наша общая задача - обучить Вас программировать на новом для Вас языке в сжатые сроки. В лекции присутствует описание нескольких тренировочных заданий, которые должны помочь приобрести опыт программирования.
Автор надеется, что Читатель имеет представление об азах информатики и некие навыки программирования на любом языке.

СОДЕРЖАНИЕ:

Назначение и возможности языка AutoLISP и особенности языка
Типы данных, Комментарии
Операторы: арифметические, присваивания, ввода и вывода.
Работа со строками, файлами и списками
Условия и логические операции
Циклические и селективные конструкции
Работа с чертежом, доступ к командам AutoCAD
Определение подпрограмм и функций
Создание файла программы, загрузка, анализ ошибок.
Программирование как таковое :-)
Материалы для углубленного изучения.

Назначение и возможности языка AutoLISP

Графический язык программирования AutoLISP является расширением языка программирования LISP. LISP- это язык высокого уровня, ориентированный на обработку списков, который выбран в качестве базового потому, что графические примитивы (начиная с точки), блоки, наборы примитивов и блоков удобно представляются в виде списков.
В составе системы AutoCAD поставляется интерпретатор языка AutoLISP. Если при генерации AutoCADа интерпретатор AutoLISPа был подключен, то он загружается в оперативную память после запуска графического редактора ACAD и доступен в течение всего сеанса работы с ACAD.
Таким образом, графический редактор ACAD и интерпретатор языка AutoLISP представляют собой единую систему: любая функция AutoLISPа может быть вызвана из графического редактора, и любая команда редактора может быть использована в программе на AutoLISPе. Возможности применения AutoLISPа весьма широки и разнообразны.

Наиболее характерны следующие классы применений.

Создаётся программа, позволяющая при каждом обращении к ней формировать новый чертёж, отличающийся от предыдущих чертежей, построенных этой же программой, размерами, а также, возможно, и топологией: могут появиться новые элементы обогащения, сечения, измениться текстовая часть чертежа и т.д. Время получения чертежа с помощью такой программы может быть в десятки раз меньше времени, необходимого для его создания с помощью редактора ACAD, и, что не менее важно, получить чертёж сможет любой конструктор, даже мало знакомый с командами ACAD.

Если накоплено большое количество чертёжных файлов, программ на AutoLISPе, соответствующих чертёжным фрагментам, деталям, узлам, то их можно в некотором смысле считать графической базой данных. Программы на AutoLISPе в сочетании с пользовательскими меню могут организовывать просмотр, поиск, подключение к объектам их частей и т.п. Тогда работа конструктора в системе AutoCAD будет сводиться к поиску нужных объектов (сборочных единиц, деталей) или частей чертежа, обращению к соответствующим LISP-программам и ответам на вопросы этих программ.
Есть ещё одно очень важное обстоятельство: хранение графических данных в виде набора программ на AutoLISPе даёт возможность в десятки и сотни раз сократить требуемую память на магнитном диске по сравнению с памятью, необходимой для хранения чертёжных файлов ACAD, так как, во-первых, одна программа позволяет получить не один, а множество чертежей, во-вторых, текст программы на AutoLISPе занимает на порядок меньше памяти, чем файл, который может быть получен в результате работы этой программы.

Программа на AutoLISPе может воспринимать чертёж на экране, построенный с помощью графического редактора и обсчитывать его. Программа также может быстро осуществить преобразование изображения, на которое при работе в графическом редакторе пришлось бы затратить значительное время, например:

Расширение системы команд графического редактора ACAD и построение на основе универсального редактора специализированных САПР, имеющих гораздо более простой и естественный для пользователей язык, ориентированный на конкретную предметную область. В этом случае хорошим дополнением к AutoLISPу является возможность создания пользовательских меню.

Классификация функций языка AutoLISP

В языке AutoLISP определены более 150 различных операций, которые называются встроенными функциями.
По назначению их можно подразделить на функции:

Специфику языка AutoLISP определяют функции, связанные с графикой и работой в среде графического редактора ACAD:

Особенности языка

Скобки - основной управляющий символ языка LISP. Так как язык обрабатывает списки,то скобок там бесчисленное множество, и 50% ошибок программистов связано с подсчетом и неверным количеством скобок в программе. Тут надо сосредоточиться.

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

Свойства выражений

Выражение AutoLISP имеет вид:

(функция аргумент1 аргумент2 ... аргументN)

Функция - имя операции (в том числе и арифметической), которая должна быть выполнена. Число аргументов может быть больше 2.

Произведение трех чисел: (* 2 3 4)
Вложенные выражения: (* 4.4 (- 3.3 (+ 2.2 1.1 )))

Выражение анализируется AutoLISP слева направо, пока не встретится скобка. Если встречается закрывающая скобка, то завершается анализ выражения, выполняется функция и вычисленное значение передается на более старший уровень вложенности или в AutoCAD. Если же встречается открывающаяся скобка, AutoLISP переходит к анализу выражения более младшего уровня вложенности и, пока не завершит его анализ, не перейдет к дальнейшему анализу выражения предыдущего уровня. Предел вложенности выражений - 100.

Типы данных

Переменные любого из простых типов называют атомами. Списком называется набор разделенных пробелами атомов и/или списков, заключенных в круглые скобки.

Комментарии

Комментарии обозначаются ";" в начале строки. Все последующие выражения на данной строке интерпретатором игнорируются.

Арифметические операторы

(+ число1 число2 ...) Возвращает сумму всех аргументов.
(- число1 число2 ...) Вычитает число2 из числа1, если более двух аргументов, то из первого аргумента вычитается сумма всех остальных, если задан один аргумент, то он вычитается из нуля (инвертируется его знак).
(* число1 число2 ...) Возвращает произведение всех чисел.
(/ число1 число2 ...) Делит число1 на число2, а если аргументов более двух, то первое число делится на произведение всех остальных.
(1+ число) Увеличение целого или действительного аргумента на единицу.
(1- число) Уменьшение целого или действительного аргумента на единицу.
(atan число1 [число2]) Если не задано число2, то возвращает арктангенс переменной число1 в радианах, область допустимых значений - [-pi,pi] радиан. Если заданы оба числа, то возвращает арктангенс переменной число1/число2 в радианах. Если число2 - нуль, то в зависимости от знака переменной число1 возвращается + или - 1.570796 радиан (+90o или -90o).
(abs число) Вычисление абсолютного значения действительного или целого числа.
(cos число) Возвращает значение косинуса угла, заданного аргументом в радианах.
(exp cтепень) Вычисляет значение экспоненциальной функции с основанием е и аргументом, равным степени.
(expt основание степень) Вычисляет значение экспоненциальной функции с указанным основанием и степенью.
(gcd число1 число2 ...) Возвращает наибольший общий делитель.
(log число) Натуральный логарифм аргумента.
(max число1 число2 ...) Наибольший аргумент.
(min число1 число2 ...) Наименьший аргумент.
(rem число1 число2 ...) Остаток от деления переменной число1 на переменную число2.
(sin число) Возвращает значение синуса угла.
(sqrt число) Извлекает квадратный корень из аргумента.

Операторы присваивания

Из несложных операторов используется функция setq.
Запись B=200 эквивалентна следующей:

(setq B 200)

Операторы ввода

Для получения данных с устройств ввода созданы специальные функции ряда GET. Их структура типична, сначала идет сам оператор, затем с вариациями -текст вопроса-подсказки. Этот текст будет выводиться в командную строку для того, чтобы пользователь понимал, что ему необходимо ввести в данный момент.

(getangle точка "текст запроса-подсказки") Возвращает угол между заданным пользователем вектором и положительным направлением оси Х. Всегда в радианах.
(getcorner точка "текст запроса-подсказки") Возвращает координаты указанной пользователем точки.
(getdist точка "текст запроса-подсказки") При любых текущих единицах измерения эта функция всегда возвращает действительное число.
(getenv имя переменной) Возвращает строковое значение, присвоенное переменной среды DOS.
(getint "текст запроса-подсказки") Ввод целого числа. Только с клавиатуры.
(getorient точка "текст запроса-подсказки") То же самое, что и getangle, но измерение угла происходит относительно текущего направления измерения углов.
(getpoint точка "текст запроса-подсказки") Позволяет ввести точку.
(getreal "текст запроса-подсказки") Позволяет вводить действительное число. Только с клавиатуры.
(getstring флаг пробела "текст запроса-подсказки") Запрашивает ввод текстовой константы. Если флаг пробела указан и не равен нулю, то строковая константа может содержать пробелы, и завершением ввода считается нажатие клавиши ENTER, в противном случае строка не может содержать пробелы и клавиша ПРОБЕЛ работает как терминатор ввода.
(getpvar имя переменной) Возвращает значение системной переменной AutoCAD.

Операторы вывода

(prin1 выражение дескриптор_файла) Выражение выводится на экран и возвращается в AutoLISP. Если указан дескриптор файла и файл открыт, то запись идет сразу на два устройства: на экран и в файл. Печатается только указанное выражение; переход на новую строку не осуществляется, и никакие пробелы не печатаются.
(princ выражение дескриптор_файла) То же, что и prin1, но управляющие символы не расшифровываются, а выводятся на экран.
(print выражение дескриптор_файла) То же, что и prin1, но перед печатью осуществляется переход на другую строку.
(prompt строка_символов) Выводит сообщение в командную строку и возвращает nil.
(alert строка_символов) Выводит сообщение в диалоговое окно, и ожидает нажатия на "ОК" от пользователя.

Работа со строками

(strcase <строка> [<признак>]) - берет строковую константу, указанную аргументом <строка> и возвращает ее копию, переведя все символы алфавита в верхний или нижний регистр в зависимости от аргумента <признак>. Если <признак> опущен или равен nil, то все символы алфавита в <строке> будут переведены в нижний регистр.
(strcat <строка1> <строка2>...)Эта функция возвращает строку, которая является результатом сцепления <строки1>, <строки2> и т.д.
(strlen <строка>)Эта функция возвращает длину в символах строковой константы <строка> как целую величину.

Списки

  Простые

Функция list — это основная функция, позволяющая создать список: (list (<элемент1> [<элемент2> ... [<элементN>] ... ] ] )
В качестве аргументов <элементы>, из которых образуется список, могут выступать любые объекты, которыми оперирует AutoLISP. Самый распространенный список — это список из двух или трех вещественных чисел, представляющий точку. В качестве элементов списка могут выступать другие списки или точечные пары.

  Ассоциативные списки

Функция assoc применяется к списку, в котором элементами являются списки или точечные пары, и выбирает из этих элементов тот, у которого первый элемент имеет заданное значение: (assoc <код> <список>)

Если в аргументе <список> имеется несколько элементов, удовлетворяющих требуемому условию, то в качестве возвращаемого значения выбирается первый из них. Функция assoc — основной инструмент в операциях выборки из списка с характеристиками примитива AutoCAD того элемента, который содержит точечную пару с нужным DXF-кодом свойства (цвета, типа линии, веса и т. д.).

  Работа со списками

(append [<список1> [<список2> ... [<списокN>] ... ] ] ) - слияние списков в один;
(nth <номер> <список>) - извлечение из списка элемента по порядковому номеру (нумерация элементов списка выполняется слева направо и начинается с нуля);
(reverse <список>) - переворот списка;
(length <список>) - длина списка;

  Точки

Список из трех вещественных величин является точкою. Использование такого списка в командах AutoCAD позволяет указывать точки для отображения примитивов.

Условия и логические операции

Условия - записываются так-же, как и арифметические операции. Знаки условий: >, <, =, >=, <=, /=.
(> a b) ; эквивалентно записи a>b

Логический оператор - это функция, сравнивающая между собой два или более аргументов. Результат может быть либо истина (non-nil), либо ложь (nil).
(and выражение1 выражение2 ) Возвращает результат выполнения логического И над списком выражений.
(not аргумент ) Возвращает результат выполнения логического НЕ над своим аргументом.
(or выражение1 выражение2 ) Возвращает результат выполнения логического ИЛИ над списком выражений.

Условное ветвление программ

Каждая программа имеет свою логическую структуру. Ветвление - это способ управления ходом выполнения программы. Условные операторы - средство управления ветвлением программ. Условные конструкции и селективные позволяют управлять ветвлением программы: (if тест-выражение выражение-тогда выражение-иначе )

Иногда по условию требуется выполнить не одно, а несколько выражений. Для этого используют функцию PROGN. Последовательность выражений, объединенных функцией PROGN, считается одним выражением.

(if ( = a b)
 (progn
    (setq a ( + a 10))
    (setq b ( - b 10))
  )
)

Селективные конструкции

(cond ( тест1 результат1 ...) ...) Воспринимает в качестве аргументов любое число списков. Оценивает по очереди первые элементы списков, пока не встретится элемент, отличный от nil. Затем вычисляется то выражение, которое следует за тестом, и возвращается значение последнего выражения в субсписке. Если в субсписке только одно выражение (например, результат отсутствует), то возвращается значение выражения тест.

Циклические конструкции

(repeat число выражение1 выражение2 ... ) Функция повторяет операторы указанное число раз.
(while тест-выражение выражение1 выражение2 ... ) Выход из цикла осуществляется по условию.
(foreach имя список выражение) Эта функция, проходя по списку, присваивает каждому элементу имя и вычисляет каждое выражение для каждого элемента списка.

Работа с файлами

( open имяфайла режим ) Открыть файл - значит подготовить дескриптор файла к использованию его функциями AutoLISP. Поэтому возвращаемое функцией open значение должно присваиваться некоторой символьной переменной.

( setq a ( open "file.ext" "r" )) ;Здесь а - дескриптор файла file.ext, открытого для чтения.

(close дескриптор файла ) Закрытие файла.
(read-line дескриптор файла ) Cчитывает строку символов с клавиатуры или из открытого файла. Возвращается считываемая строка.
(write-line строка дескриптор файла ) Записывает строковую константу строка на экран или в открытый файл. Возвращает строку, взятую в кавычки, и опускает кавычки при записи в файл.

Работа с чертежом, доступ к командам AutoCAD

В этом нам поможет функция (command аргумент1 аргумент2 ...)

Аргументы - это команды AutoCAD и их опции. Если в списке встречается ключевое слово Pause, то функция COMMAND приостановит свое действие.

Определение подпрограмм и функций

(defun <символ> <список аргументов> <выражение>...)

DEFUN - определяет функцию с именем <символ>. За функцией следует список аргументов (возможно пустой), за которым следует (факультативно) косая черта (slach) и имена одного или более локальных переменных функции. Косая черта должна отстоять от первого локальной переменной и последнего аргумента хотя бы на один пробел. Если нет аргументов и локальных символов, которые следует объявлять, за именем функции следует поставить пустые скобки.

(defun myfunc (x y) ... ) ;(функция берет два аргумента)
(defun myfunc (/ a d) ... ) ;(функция имеет две локальных переменных)
(defun myfunc (x / temp) ... );(один аргумент и одна локальная переменная)
(defun myfunc () ... ) ;(без аргументов и локальных переменных)

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

Локальные переменные: это переменные, которые используются внутри данной функции без изменения их связи на внешних уровнях. По умолчанию все переменные - глобальные.

Возвращение значения: функция будет возвращать результат последнего вычисленного выражения. Все предыдущие выражения будут иметь только побочный эффект.

(defun add10 (x)(+ 10 x); возвращает ADD10
(add10 5) ;возвращает 15
(add10 -7.4) ;возвращает 2.60000

(defun dots (x y / temp)
(setq temp (strcat x "..."))
(strcat temp y)
) ;возвращает DOTS

(dots "a" "b") возвращает "a...b"
(dots "from" "to") возвращает "from...to"

Никогда не используйте имена встроенных функций или символов как <символ>, так как это сделает недоступными встроенные функции.

Создание файла программы

Необходимо в файле с расширением lsp записать текст программы. Это обычные текстовые файлы, поэтому можно использовать обычный текстовый редактор, но при условии, что выбранный текстовый редактор не добавлет в файл служебные символы. Можете использовать Aditor или Notepad.

Также в 2000 и выше версиях AutoCAD есть встроенный отладчик приложений VisualLISP. Он поддерживает и код AutoLISP, поэтому программу можно даже создавать непосредственно в отладчике.

Единственная тонкость - не все команды языка программирования VisualLISP понимают ранние версии AutoCAD, поэтому с использованием VisualLISP необходимо быть аккуратнее, и понимать, что программа становится пригодной только для последних версий AutoCAD, в то время как AutoLISP может работать хоть с 10 версией программы (от 1988 года, под ДОС).

Поэтому, отлаживаясь в среде VisualLISP старайтесь без необходимости не пользоваться его возможностями. Мы изучаем пока AutoLISP.

Загрузка программы

Простая:

Простая загрузка - это загрузка одного файла. Для такой загрузки не требуется особых усилий ни в одном из представленных способов загрузки.

Нажав на кнопку File, Вы сможете указать файл для загрузки.

Комплексная загрузка

Комплексная загрузка - загрузка сразу нескольких файлов или библиотеки файлов. В таком случае рекомендуется создать файл-загрузчик, в котором будут перечисляться все файлы, необходимые Вам для работы. Можно составить файл из строк типа:

(load "диск:\\каталоги\\файл1.lsp")
(load "диск:\\каталоги\\файл2.lsp")
...
(load "диск:\\каталоги\\файлN.lsp")

Такой вариант наиболее прост в обращении и легко корректируется. А загрузку самого файла-списка можно "повесить" на кнопку. См. раздел Для справки на сайте. Вопрос - как создать кнопку с действием.

Анализ ошибок

Ошибки, проявляющиеся после запуска программы:

error: Too many arguments - слишком много аргументов. обычно появляется в блоке IF, когда позабыл автор об использовании (progn) и много операторов пытается запустить в теле IF.
error: Too few arguments - маловато аргументов. Проявляется, когда мало аргументов указано для функции.
error: bad argument type - неверный тип агрумента, подаваемого в функцию.

Схематика вывода информации об ошибках:

Мы запускаем команду:

Command: ($getval "Введите что-нибудь!" "ку")

С заведомо неверным типом данных №2. Второй аргумент должен быть типа REAL, а не строка.

В результате сейчас получим ошибку:

error: bad argument type
(RTOS DEFLT)
(STRCAT "\n" STRING " <" (RTOS DEFLT) ">: ")
(SETQ QUESTION (STRCAT "\n" STRING " <" (RTOS DEFLT) ">: "))
($GETVAL "Введите что-нибудь!" "ку")
*Cancel*

Эта надпись обозначает следующее:
сперва выводится тип ошибки - error: bad argument type
потом пишется выражение, в котором произошла ошибка - (RTOS DEFLT)
затем идет последовательное восстановление вложенности выражений, содержащих ошибку, до тех пор, пока мы не достигнем вложенности выражения DEFUN, тогда последней строкой выводится выражение, из которого произошел запуск функции, содержащей ошибку. Таким образом можно проследить расположение ошибочной команды.

Программирование как таковое :-)

Хотелось бы обратить внимание Читателя на то, что называется стилем программирования. Несложные правила изложены в документе, прошу придерживаться их при написании кода программы. Также хочу обратить Ваше внимание на алгоритмирование своей задачи. Продумайте все хорошенько. Да, предусмотреть всего не получится, но глобальных ошибок, влекущих переписывание всей программы, Вам удастся избежать.

Материалы для изучения

Рекомендую на сайте http://aco.ifmo.ru/~nadinet посетить страницу AutoLISP, где посмотреть следующие разделы:

Также зайдите на страницы Для справки и Ссылки.

Документ обновлен