Введение в Автолисп

Рыжиков Роман Клавдиевич

3. ВЗАИМОДЕЙСТВИЕ АВТОЛИСПА С АВТОКАДОМ

 

 

3.1. Вызов команд Автокада в Автолисп

Вызов команд Автокада Автолисп осуществляет с помощью функции command. Необходимо помнить, что эта функция не имеет ничего общего с командами Автокада, которые входят в эту функцию в качестве аргументов. Количество аргументов функции не ограничивается, они могут представлять собой строки, списки, числа, но во всех случаях их тип должен соответствовать типу, ожидаемому Автокадом. Введение пустой строки (“”) соответствует нажатию на клавишу Space или Enter, например:

(command “line” pt1 pt2 “”).

Здесь Автолисп передает Автокаду команду line для проведения отрезка прямой из точки pt1 к точке pt2. Пустая строка завершает ввод параметров. При организации строки параметров следует обратить внимание на то, что она практически описывает символами действия оператора, вводящего параметры с клавиатуры или с помощью мыши. Действительно, при ручном вводе последовательность действия оператора выглядела бы следующим образом:

Command: _line

From point: pt1

To point: pt2

To point: Enter

Команды Автокада, вызываемые функцией command, не отражаются на экране, если системная переменная CMDECHO установлена в ноль. Если необходим ввод данных с клавиатуры или с помощью мыши, нужно либо осуществлять эту операцию до использования функции command, либо организовать паузу внутри команды (см. разд. 4.1).

 

3.2. Создание новой функции

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

(defun имя ([ аргументы ]/[ локальные переменные ])),

например:

(defun my_prog (a b / temp)).

Здесь функция my_prog содержит два аргумента (a, b) и одну локальную переменную (temp). Пара круглых скобок после имени функции обязательна, даже если аргументы отсутствуют.

Переходя к изложению техники программирования на Автолиспе, автор считает необходимым еще раз подчеркнуть, что настоящее пособие не является справочником по функциям языка. Описываемые функции сгруппированы по назначению лишь частично и лишь в той степени, которая необходима для понимания рассматриваемых программ. Детальное изучение языка требует привлечения дополнительных материалов (например [1, 2]).

 

3.3. Создание новой команды Автокада

 

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

(defun C:FUNCNAME ([ / переменные])

...... ; тело функции

).

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

(defun C:FUNCNAME ()

........

).

Работу в Автокаде над новым чертежом конструктор начинает с организации инструментария, в частности с создания нескольких необходимых слоев чертежам В прототипах чертежей acad.dwg (12-я), unnamed.dwg (13-я), drawing.dwg (14-я) и drawingN.dwg (15-я версия) заложен по умолчанию один нулевой слой с присущим ему белым цветом и сплошными линиями. Изначальная установка пределов изображения (limits) позволяет назначить границы экрана, но не исключает необходимости организации слоев. Заложенные в последних версиях готовые рамки с угловыми штампами, соответствующие международным и региональным стандартам, расположены в пространстве бумаги и не соответствуют стандартам отечественным. Разумеется, создание аналогичной графической базы, опирающейся на отечественные стандарты, не представляет сложностей, однако не лишним представляется и другой путь - программное описание необходимых установок.

Предлагаемая в качестве иллюстрации программа используется в практике выполнения графических работ как в учебных курсах компьютерной графики, так и в ряде специальных дисциплин. Цель программы заключается в выводе на экран стандартных рамок, соответствующих принятым в отечественной практике форматам A0...A4, и организации поля чертежа с заранее установленными характерными слоями. Программа рассматривается на примере формата A1.

 

3.3.1. Функция обрисовки рамки

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

(defun C:A1()

;;; Устанавливаем угловые точки внешней рамки,

(setq pt1 (list -20 -5)

(setq pt2 (polar pt1 0 840))

(setq pt3 (polar pt2 (/ pi 2) 594))

(setq pt4 (polar pt3 pi 840))

;;; Устанавливаем таковые для внутренней рамки.

(setq pt5 (list 0 0))

(setq pt6 (polar pt5 0 815))

(setq pt7 (polar pt6 (/ pi 2) 584))

(setq pt8 (polar pt7 pi 815))

)

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

(defun ramka()

(command '‘Iine” pt1 pt2 pt3 pt4 “с”)

(command “pline” pt5 “w” “0.4” “” pt6 pt7 pt8 “с”)

)

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

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

(defun C:A1 ()

(setq pt1 (list -20 -5))

(setq pt2 (list 821 589))

(setq pt3 (list 0 0))

(setq pt4 (list 816 584))

(ramka)

)

А функция (ramka) предстанет в форме:

(defun ramka ()

(command "rectangle" pt1 pt2)

(command "rectangle" pt3 pt4)

(setq e1 (entlast))

(command "pedit" e1 "w" "0.4" "")

)

 

3.3.2. Создание слоев

Процедура создания слоев может быть осуществлена автоматически при загрузке формата. В функции sloy, описанной далее, устанавливаются слои CONTUR, CENTER, DIM и HIDDEN, которым присваиваются соответственно цвета: белый, красный, зеленый и желтый, а в слои CENTER и HlDDEN загружаются соответственно типы линий AcadISO04w100 и AcadISO02w100. Поскольку любая функция может записываться в несколько строк, воспользуемся этим для построения программы.

(defun sloy ()

(command “linetype” “load” “AcadISO04w100” “acadiso.lin”

“load” “AcadISO02w100” “” “”)

(command “layer” “new” “contur”

“new” “center”

“new” “dim”

“new” “hidden”

“Itype” “AcadISO04w100” “center”

“Itype” “AcadlSO02w100” “hidden”

“color” “red” “center”

“color” “green” “dim”

“color” “yellow” “hidden”

“set” “contur” ""

) ; конец command

) ; конец defun

Последняя команда устанавливает в качестве текущего слой CONTUR.

 

3.3.3. Организация поля изображения

Поле изображения чертежа можно ограничить внешней рамкой. Но это неудобно, если в процессе работы над чертежом необходимо осуществить к внешней рамке объектную привязку. Поэтому многие пользователи предпочитают, чтобы размеры поля изображения превосходили размеры рамки. Организуем границы поля изображения таким образом, чтобы между рамкой и границами экрана оставалось не менее 10 мм. Для этого укажем координаты левого нижнего p1 и правого верхнего рЗ углов поля.

(defun pole ()

(setq p1 (polar pt1 (+ pi (/ pi 4)) 15))

(setq рЗ (polar pt3 (/ pi 4) 15))

(command “limits” p1 рЗ)

(command “zoom” “all”)

)

Дальнейших пояснений функция не требует.

 

3.3.4. Работа с системными переменными

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

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

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

(defun sysvar()

(setq svarold (getvar “cmdecho”))

(setvar “cmdecho” 0)

).

Здесь использованы две не описанные ранее функции: getvar и setvar. Обе они предназначены для работы только с системными переменными. Первая извлекает текущее значение системной переменной, вторая - приписывает ей значение заданное.

На этом подготовительная работа заканчивается и можно записать программу полностью.

 

3.3.5.  Объединение нескольких команд

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

(defun C:A3 ()

(setq pt1 '(-20 -5))

(setq pt2 '(400 292))

(setq pt3 '(0 0))

(setq pt4 '(395 287))

)

Написав подобные функции для всех форматов (А0 ... A4), можно объединить их в одном файле. Далее приводится пример объединения двух команд обрисовки рамок форматов A2 и A4. Кроме них в программу включен еще один функциональный модуль, позволяющий установить границы экрана, не выводя форматные рамки. Особенно это удобно при работе над объектами большой протяженности (например, в строительных или геоинформационных чертежах). Поскольку Автокад допускает применение аббревиатур при вводе многих опций, это обстоятельство частично использовано при написании программы.

;;; ======================================

;;;    FORMAT.LSP

;;;    Программа вычерчивания рамок форматов А2, А4

;;; и организации поля изображения.

;;; Для вызова программы следует ввести в командную

;;; строку наименование нужного формата (например, A2)

;;; и нажать клавишу [Enter]

;;; ======================================

;;; Функция создания слоев

(defun sloy ()

(command “linetype” “load” “Acad_ISO04w100” “acadiso.lin”

“load” "Acad_ISO02w100" “” “”)

(command “layer” “new” “contur”

“new” “center”

“new” “dim”

“new” “hidden”

“I” "Acad_ISO04w100” “center”

“I” "Acad_ISO02w100” “hidden”

“c” “red” "center”

“c” “green” “dim”

“c” “yellow” “hidden”

“s” “0” ""

)

)

;;; Функция сохранения переменной CMDECHO

(defun sysvar ()

(setq svarold (getvar “cmdecho”))

(setvar “cmdecho” 0)

)

;;; Функция установки границ экрана

(defun pole ()

(setq p1 (polar pt1 (+ pi (/ pi 4)) 15))

(setq p3 (polar pt3 (/ pi 4) 15))

(command “limits” p1 p3)

(command “zoom” “a”)

)

;;; Функция вычерчивания рамки

(defun ramka ()

(command “rectangle” pt1 pt2)

(command “rectangle” pt3 pt4)

(setq e1 (entlast))

(command "pedit" e1 "w" "0.4" "")

)

;;; Текст основных функций

(defun C:A2 ()

(sysvar)

(setq pt1 '(-20 -5))

(setq pt2 '(574 415))

(setq pt3 '(0 0))

(setq pt4 '(569 410))

(pole)

(ramka)

(sloy)

(setvar “cmdecho” svarold).

(princ)

)

(defun C:A4 ()

(sysvar)

(setq pt1 '(-20 -5))

(setq pt2 '(190 292))

(setqpt3 '(0 0))

(setq pt4 (185 287))

(pole)

(ramka)

(sloy)

(setvar "cmdecho” svarold)

(princ)

)

(defun C:SCR ()

(sysvar)

(setq pt1 '(-40 -20))

(setq a (getreal "\nВведите координату X

правой границы экрана:_”))

(setq b (* a 0.75))

(setq pt2 (list a b))

(command “limits” pt1 pt2)

(command “zoom” “a”)

(sloy)

(setvar “cmdecho” svarold)

(princ)

)

 

3.3.6. Автоматическая загрузка программы

Автокад позволяет любую функцию, написанную на Автолиспе и определенную форматом C:XXX, использовать в качестве встроенной команды. Ее лишь следует загрузить, например, вызовом функции Applications... из группы Tools падающих меню. Однако целый ряд программ Автокад загружает автоматически. Этим процессом управляет файл acad*.lsp, имеющий в разных версиях разные имена (acadrl4.lsp в 14-й версии). Раскрыв этот файл с помощью текстового редактора, следует отыскать в нем группу AutoLoad LISP Application и добавить в нее имя созданного файла.

Присвоим созданному программному файлу, имя formats.lsp и поместим его в папку SUPPORT Автокада. Тогда строка в файле acad*.lsp, автоматически загружающая файл formats.lsp в Автокад, позволяющая обрисовать пять стандартных форматов и создать поле изображения нужных размеров, должна выглядеть следующим образом:

(autoload "formats” ‘("А0" “A1” “A2" “A3” “A4” “scr”)).

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

В заключение необходимо отметить следующее. Описанная программа, равно как и предлагаемые далее, приведена в качестве примера программирования. В связи с этим в программах, используемых для иллюстрации, могут присутствовать структуры, не являющиеся обязательными. В частности, в программе format.lsp, строго говоря, не обязательна функция pole, так как расширить границы видового экрана до границ рамки можно, используя команду View → Zoom → Extents, а границы поля изображения расширять командой limits. Однако всегда имеет смысл предусматривать возможные результаты действия программ и сводить к минимуму операции доводки чертежа вручную.

И еще одно замечание. Программа будет работать без сбоев лишь при определенных условиях, а именно: в чертеже должны отсутствовать загружаемые слои и типы линий и отключена автоматическая объектная привязка. Возможности создания программ, исключающих эти неудобства, рассмотрены в разделах 6.6 и 6.7.