Обучение AutoLISP в восьми уроках
ИМЯ ЯЗЫКА
ЛИСП осначает "обработку списков" или " программирование списков
". В ЛИСПЕ, основным обрабатывающим средством есть " нахождение
значения объекта "; то-есть обработка - метод которым Lisp опре-
деляет значение любого выражения, сложного объекта, или простого
объекта.
ОБЪЕКТЫ
Имеются два общих типа объектов в AutoLISP - АТОМЫ и СПИСКИ. Ато-
мы - простые объекты; списки - сложные объекты.
Атомы и списки взаимно исключающие. Что-нибудь что является ато-
мом не может быть список, и наоборот ( здесь одно исключение ко-
торое доказывает это правило, объект Нуль; мы будем рассказывать
о нем позже ).
АТОМЫ
Атомы могут быть целым, вещественным числом, текстовой строкай,
функцией AutoLISP, символом, или специальными объектами которые
соответствуют примитивам AutoCAD, наборам выбора, и файлам.
Все они - атомы:
1 ; Целое число 1
4.5 ; Вещественное число 4.5
" A String of Pearls " ; Текстовая строка
Setq ; AutoLISP функция
Ename ; Определяемый пользователем символ
ЗНАЧЕНИЯ AТОМОВ
Значения любого атома, за исключением функций AutoLISP и опреде-
ляемых пользователем символов, является он сам. Например, атом 1
имеет значение 1; Атом 4.5 имеет значение 4.5; атом " A String of
Pearls " имеет значение " A String of Pearls ".
Вы можете определять значение любого атом в командной строке
AutoCAD. Напечатайте знак восклицания "!" сопровождаемый атомом.
AutoLISP будет находить и возвращать значение атома в командную
строку. Например, это выражение находит значение атома ( и вещес-
твенное число ) 4.5:
Command: !4.5
4.5
СПИСКИ
Списки - сложные объекты, упоминаемые в некоторых описаниях как
символические выражения, или " s-выражения ".
Списки сформирова-
ны вне атомов и ( или ) других списков. Список синтаксически
прост; он должен ограничиваться согласованными круглыми скобками,
и объекты внутри списка должны отделяться от друга друга пробелом.
Примеры списков:
( + 1 3 ) ; Сложить 1 и 3
( - 9 5 ) ; Вычесть 5 из 9
( + 1 ( + 2 3 )) ; Добавить 1 к результату сложения 2 и 3
Что-нибудь ограниченное согласованными круглыми скобками должно
быть списком; что-нибудь не ограниченное согласованными круглыми
скобками должно быть атомом.
ЭЛЕМЕНТЫ СПИСКОВ
Индивидуальные члены списка известны как элементы. Ниже пример
списка с тремя элементами, каждый из которых - атом:
(+ 1 2)
Элементы списков могут быть или атомами или другими списками. Ни-
же пример списка с тремя элементами; два - атомы, третий - самос-
тоятельный список трех элементов:
(+ 1 (+ 2 3))
| | \ /
| | \ /
| | |
Элементы
Элементы списка должны отделяться от друга друга по крайней мере
одним пробелом. Нет никакого ограничения числа пробелов отделяю-
щих элементы, но должен иметься по крайней мере один. Это совер-
шенно допустимый список:
(+ 1 (+ 1 3))
ПУСТОЙ СПИСОК
Имеется один объект в AutoLISP который является и атомом и спис-
ком. Это - пустой список; то-есть список не имеющий никаких эле-
ментов, обычно называемый НУЛЬ (NIL).
( ) или нуль
Нуль ( пустой список ) в AutoLISP не " никакое значение ". Когда
объект в AutoLISP не имеет никакого значение, тогда значение
объекта - нуль.
УПРАЖНЕНИЕ
Которые из этих объектов являются атомами и которые являются
списками?
1. 73.5
2. "0,0"
3. (1.0 2.0 3.0)
4. "string"
5. ( "string" )
6. ()
Найдите значения этих атомов в командной строке AutoCAD.
1. 4.5
2. "text"
3. 17
4. setq
5. xyz
6. nnil
Сколько элементов содержатся внутри каждого списка?
1. (1.0 2.0 3.0)
2. (+ 1 2)
3. (+ 1 (+ 2 3))
4. (+ 1 2 (+ 3 4) 5)
5. (+ 1 (+ 2 (+ 3 4)) 5)
6. ()
Следующие занятие: Списки и их оценка
ПРЕДИКАТЫ, ЛОГИЧЕСКИЕ ОПЕРАТОРЫ И УСЛОВНЫЕ ВЫРАЖЕНИЯ
УСЛОВНЫЙ ПЕРЕХОД
Способность исследовать состояние одного или больше назначений (
или переменных ) и принимать решение основанное на том, выпол-
няется или нет выражение в программе - фундаментальное и мощное
средство в AutoLISP. Эта форма принятия решения может оцени-
ваться как условный переход, то-есть переход в логике программы,
говорящий, выполнять или не выполнять специфическое выражение
программы, или выполнять одно выражение программы скорее чем дру-
гой, основанный на некотором существующем условии.
Вы и я принимаем эти решения все время. Если сегодня солнечно, мы
не будем брать с собой на работу зонтик. Если бензин стоит дешев-
ле на одной бензоколонке, тогда Мы будем приобретать его там, а
не на другой, где он дороже.
В обеих предыдущих примерах, слово "если" используется как услов-
ное выражение, то-есть функция которая выполняет тест чтобы опре-
делить существует ли специфическое состояние или условие. Фун-
кция AutoLISP IF имеет фактически то же самое значение что и сло-
во "если", используемое в предыдущих, реальных примерах.
Условный оператор IF
Функция IF используется чтобы проверить состояние одиночного ус-
ловия. Если условие сравнивается с не-нулевым значением, то-есть
чему-нибудь НE нуль, тогда выражение программы немедленно после
проверки будет выполняться.
( if <выражение проверки> <выражение> [<выражение>] )
Должно существовать одно выражение после выражения проверки. Мо-
жет существовать также второе, необязательне выражение, которое
будет оцениваться если выражение проверки возвращает нуль.
Например определеим функцию, которая бы проверяла, большее ли 0
значение переменной X. Если так, тогда это вывести на дисплей "X
greater than 0".
Создайте файл с именем GREATER.LSP и определите эту функцию.
(defun GREATER ()
(if
(> x 0)
(prompt "\nX is greater than 0.")
)
(prin1)
)
Command: (setq x 1)
1
Command: (load "greater")
GREATER
Command: (greater)
X is greater than 0.
Command: (setq x -1)
-1
Command: (greater)
Имеются несколько вещей, которые Вы можете выполнить чтобы де-
лать функцию GREATER более универсальной. Сначала, сделайте зна-
чение для выражения проверки аргументом функции, чтобы GREATER
больше не зависила от значения специфической глобальной перемен-
ной X. Затем, добавьте второй оператор к выражению IF который бы
выводил на экран сообщение, если значение требуемого параметра
МЕНЬШЕ или РАВНО нулю.
Отредактируйте файл GREATER.LSP и сделают эти два изменения в
функции GREATER.
(defun GREATER (x)
(if
(> x 0)
(print "\nArgument is greater than 0.")
(print "\nArgument is less than or equal to 0.")
)
(prin1)
)
Command: (load "greater")
GREATER
Command: (greater 1)
Argument is greater than 0.
Command: (greater -1)
Argument is less than or equal to 0.
Command: (setq y 1)
1
Command: (greater y)
Argument is greater than 0.
ПРАКТИЧЕСКОЕ ИСПОЛЬЗОВАНИЕ ОПЕРАТОРА IF
Одна из недавних тем на CompuServe ADESK Форуме были желание из-
менять команду END, что бы она запрашивала у пользователя, сохра-
нять или нет текущее состояние рисунка перед выходом из AutoCAD,
тем же самым способом как запрашивает пользователя команда QUIT.
В следующем примере, Вы будете записывать функцию AutoLISP заме-
няющую родную команду END AutoCAD, и делающую неопределенной род-
ную команду END, чтобы AutoCAD использовал функцию AutoLISP вмес-
то нее.
Новая функция будет поэтому определена так, что сможет вызы-
ваться непосредственно из командной строки AutoCAD без включения
в круглые скобки, и будет самостоятельно вызывать местную коман-
ду END ( независимо от того была ли команда END сделана неопреде-
ленной ) указав перед именем команды точку ".".
Создайте новый файл назвав его END.LSP и добавте туда эту функцию.
(defun C:END (/ usr)
; Запросить пользователя и получить ответ
(setq usr (getstring "\nReally want to END the drawing? "))
; Преобразовать его ответ в символы верхнего регистра
(setq usr (strcase usr))
; Проверяют был ли его ответ "y" или "Y"
(if
(equal "Y" usr)
; Если это было, тогда завершить чертеж, иначе вывести сообщение
(command ".END")
(prompt "\nRemaining in drawing editor.")
)
; тихий выход из функции
(prin1)
)
Родная команда END может отключаться командой UNDEFINE и поэтому
может заменяться функцией AutoLISP C:END .
Command: UNDEFINE
Command name: END
Command: (load "end")
C:END
Command: END
Really want to END the drawing? n
Remaining in drawing editor.
Command: END
Really want to END the drawing? y
Для эффективности и не выполненя ненужного связывания переменных,
которое может быть относительно дорого в смысле компьютерного
времени, функция C: END может также быть написана так:
(defun C:END ()
(if
(eq "Y"
(strcase
(getstring "\nReally want to END the drawing? ")
)
)
(command ".END")
(prompt "\nRemaining in drawing editor.")
)
(prin1)
)
Однако, поскольку Вы только начинаете изучать AutoLISP, очевидно
что Вы будете использовать много операций связывания переменных,
так как это поможет Вам лучше разбираться в ваших программах.
Имеются много средств, которые позволят Вам в AutoLISP записать
более эффективный код, но пока Вы имеете только твердое понима-
ние базисных механизмов, такое усилие - вероятно будет непроизво-
дительно. Кто заботится, использовались ли дополнительные 40 мил-
лисекунд компьютерного времени для связыванием переменной, это
строго говоря не столь важно если оно делает логику программы бо-
лее понятной для Вас?
Упражнения
1. Записать новую функцию HIGHER. Вот что она должна делать:
a) Запросить у пользователя две точки.
b) Сохранить значения обеих точек.
c) Проверить значения Y обеих точек.
d) Если значение Y первой точки большее, напечатать сообще-
ние, указывающие пользователю, что первая точка выше.
e) Если значение Y второй точки большее, напечатайте сообще-
ние, указывающие пользователю, что вторая точка выше.
Функции который Вы можете захотеть использовать - GETPOINT, IF,
DEFUN, CAR, CDR, и >.
Обратите Внимание что Вы можете включать два раздельных условных
оператора IF, или описать два возможных ответа как два выражения
после выражения проверки в одиночном условном операторе IF. Пос-
ледний случай обычно упоминается как оператор IF-THEN-ELSE.
( if
< это выражение проверки истинно >
< тогда выполнить это выражение >
< иначе выполнить это выражение >
)
КАЖДЫЙ ОБЪЕКТ ИМЕЕТ ЗНАЧЕНИЕ
Имеются два типа объектов в AutoLISP; атомы и списки. Каждый атом
и каждый список имеет значение. Процесс которым AutoLISP опреде-
ляет значение объекта называется "оценка".
ОЦЕНКА АТОМОВ
атомы - простые объекты, и они оцениваются используя простые пра-
вила согласно их типу данных. Имеются другие типы данных кроме
перечисленных ниже; они будут исследоваться подробно в следующем
уроке. Значение символа не может быть очевидно пока процесс "свя-
зывания" не обсуждается наряду с оценкой списков.
Тип атома Пример Оценка Значение
Целое 1 Значение - он сам 1
Вещественное 4.5 Значение - он сам 4.5
Строка "text" Значение - он сам "text"
Символ X Текущее связывание будет назначен
любой тип
ОЦЕНКА СПИСКОВ
Значение списка может определяться одним из двух способов; или
принимая список таким как он есть, или оценивая список. Первый
метод будет давать отличные результаты, или отличное значение от
второго.
Если список принимается таким как он есть, тогда значение - он
сам. Это будет становиться более понятно после объяснения фун-
кции (quote) позже в этом уроке.
Списки оцениваются согласно первому элементу списка. Если первый
элемент - имя внутренней функции AutoLISP, или процедуры, остаю-
щиеся элементы списка передаются процедуре как формальные пара-
метры и оцениваются ею.
Пример: список трех элементов, процедуры + и целых чисел 1 и 2.
(+ 1 2)
Далее рассатривается процесс оценки которым AutoLISP определяет
значение этого списка. Все оценки того же самого списка происхо-
дят точно так же, каждый раз. Тот же самый общий процесс оценки
применяется к каждому списку который может быть, и оценивается
точно таким же способом, каждый раз.
(+ ..
AutoLISP рассматривает первый элемент списка, где как ожидается
можно найти функцию. Функции - любые внутренние функции AutoLISP,
или процедуры, или определяемые пользователем функций созданных
функциями (lambda) или (defun).
AutoLISP оценивает функциональный, или первый элемент список.
Функция оценивается для определения набора команд который сооб-
щает AutoLISP что делать далее.
( Не изящно ли это? Каждое сложное выражение в AutoLISP несет
собственные команды обработки вместе с ним, в том же самом месте
каждый раз; в голове списка. )
В этом случае функции + оценивает набор команд который сообщает
AutoLISP, "Иди искать значение каждого последующего элемента в
этом списке. Когда все сделаешь, сложи все значения и возврати
результат как значение всего списка. "
(.. 1 ..)
Следуя набору команд, AutoLISP находит значение следующего эле-
мента в списке, атома и целого числа 1. Целые Числа оценивают как
такими как они есть, так что AutoLISP сохраняет значение 1 и про-
должает следовать набору команд.
(.. .. 2)
Значение целого числа 2 - 2. AutoLISP сохраняет это значение и
продолжает далее.
Элементы в списке после функции - параметры функции; то-есть они
- данные по которым функция выполняется. При не нахождении дру-
гих элементов в списке, или параметров функции, AutoLISP заканчи-
вает выполнение команд которые он получил оценивая функцию и
складывает значения аргументов, возвращая целое число 3 как зна-
чение списка.
Command: ( + 1 2 )
3
БОЛЕЕ СЛОЖНЫЙ ПРИМЕР
AutoLISP ( любой ЛИСП, фактически ) всегда оценивает элементы в
списке справа налево. Вы можете оценивають эти элементы вложен-
ным способом, изнутри, однако это неправильно. Это может быть
удобно для нас в некоторых случаях чтобы следить за процессом
оценки изнутри списка, но AutoLISP так никогда не оценивает спи-
сок. Он всегда работает справа налево.
Рассмотрим список трех элементов, функция ( или процедуры ) +,
атома 1, и списка ( + 2 3 ).
(+ 1 (+ 2 3))
AutoLISP оценивает этот список следующим образом:
(+ ..
AutoLISP рассматривает первый элемент списка и оценивает это. Так
как это - функция, то возвращает как значение набор команд по ко-
торому AutoLISP должен действовать далее.
(.. 1 ..
После команд для функции + , AutoLISP находит значение второго
элемента в списке (первый аргумент функции + ), атом 1, запоми-
нает его значение, и продолжает дальше.
(.. .. (+ 2 3)
AutoLISP находит значение третьего элемента в списке, второй ар-
гумент функции + . Третий элемент - самостоятельный список. Как
AutoLISP оценивает список?
Во первых, оценивает функцию + и получает команды. Далее находит
значения параметров, складывает их, и возвращает результат, кото-
рый в этом случае является целым числом 5.
Если элементов в списке больше нет, AutoLISP заканчивает набор
команд складывая значение двух элементов вместе и возвращает зна-
чение целого числа 6.
(+ 1 (+ 2 3))
| \ /
| \ /
| | ------------ Значение объекта - целое число 5
| ----------------- Значение объекта - целое число 1
ПРИНЯТИЕ СПИСКА ТАКИМ КАК ОН ЕСТЬ
Функция (quote) может использоваться чтобы возвратить список (
или атом ) неоцененный; то-есть таким как он есть. (quote) берет
один параметр, и возвращает как значение неоцененный параметр.
Например, это выражение возвращает список ( 1.0 2.0 3.0 ) таким,
какой он есть:
Command: ( quote ( 1.0 2.0 3.0 ))
(1.0 2.0 3.0)
Что случиться если у AutoLISP запросят оценить список?
Почему?
Command: ( 1.0 2.0 3.0 )
?
СВЯЗЫВАНИЕ СИМВОЛА И ЗНАЧЕНИЮ
Связывание - процесс в котором значение присваивается определяе-
мому пользователем символу, или переменной.
В AutoLISP, мы сооб-
щаем что символ ( или переменная ) связывается со значению. Это
сравнимо с высказыванием на языке БЕЙСИК что значение равно пере-
менной.
Функция (setq) используется чтобы связать символ ( или перемен-
ную ) со значению. Например, это выражение связывает символ X и
значение 4.5.
Command: ( setq x 4.5 )
4.5
Command:! X
4.5
В БЕЙСИКЕ, та же самая операция могла выражаться как:
LET X = 4.5
Значение (setq) - набор команд который указывает:
Найти значение второго параметра функции setq ( третий элемент в
списке ). Берется первый параметр как он есть, не оценивая его.
Связать первый параметр со значением второго параметра.
УПРАЖНЕНИЕ
Который из этих списков может оцениваться и который должен прини-
маться как он есть ?
1. (+ 1 2)
2. (+ 1 (+ 2 3))
3. (1.0 2.0 3.0)
4. ( quote ( 1.0 2.0 3.0 ))
5. ( setq x 4.5 )
6. ( setq y ( 1.0 2.0 3.0 ))
Используя функций +, -, /, и * преобразовать следующие алгебраи-
ческие выражения в выражения AutoLISP. Например, выражение:
1 + 2
Будет преобразовываться в выражение AutoLISP:
(+ 1 2)
1. 3 + 10 + 5
2. 20 * 15
3. 16 - 10
4. 15 / 3
5. 5 + (10 * 2)
6. (5 + 10) * 2
Используя функции (setq) и (quote) ( как необходимо ), свяжите
переменную X со следующими значениями. Проверьте значение пере-
менной используя ! для определения результата.
1. 1
2. 4.5
3. "text"
4. (1.0 2.0 3.0)
Далее: Типы Данных
Ответ на упражнения Урока 1 :
1. Атом
2. Атом
3. Список
4. Атом
5. Список
6. Атом и список
1. 4.5
2. "text"
3. 17
4. <Subr: xxxx >
5. nil
6. nil
1. 3
2. 3
3. 3
4. 5
5. 4
6. Ни один
ТИПЫ ДАННЫХ
Имеются два вида объектов в AutoLISP.
Атомы - простые объекты;
списки - сложные объекты, ограниченные круглыми скобками. Среди
простых объектов, имеются большое количество под-категорий извес-
тных как типы данных.
Чистое понимание типов данных в AutoLISP очень важно. Наряду с их
прародителями классами объектов атомами и списками, они форми-
руют важные составляющие блоки для всех программ AutoLISP.
Типы данных описывают характер данных, что атом должен содержать,
и количество места ( или памяти ) которое AutoLISP должен выде-
лить чтобы создать атом и сохранить его значение. Этот урок бу-
дет сконцентрирован на вышеупомянутой теме; управление памятью
будет обсуждаться в следущих уроках.
Ниже - список типов данных поддерживаемы AutoCAD версии 10. Все
за исключением одной под-категории атомов; исключение - тип дан-
ных "list". Перечисляются квалифицируемые как явные типы данных.
* Список
* Символы
* Строки
* Вещественные числа
* Целые числа
* Описатели файла
* "Имена" примитивов AutoCAD
* Наборы выбор AutoCAD
* встроенные функции
ОПРЕДЕЛЕНИЕ ТИПОВ ДАННЫХ
Функция AutoLISP (type) может использоваться чтобы определить тип
данных любого объекта. (type) берет один требуемый параметр, и
возвращает символ, который указывает тип данных параметра.
Например, определить тип данных целого числа 1.
Команда: ( type 1 )
INT
ПРИМЕРЫ ТИПОВ ДАННЫХ
Пример кода AutoLISP, который связывает переменную x с рядом
объектов с различными типами данных и определяет тип данных свя-
зывания с помощю функции (type). Вы можете захотеть набрать выра-
жения в командной строке AutoCAD.
В случаях где шестнадцатеричный номер появляется как часть типа
данных, невозможно точно представить номер, поскольку он изме-
няется время от времени. Взамен, номер представляется в примерах
просто как " xxxx ".
СПИСОК
Command: ( setq x ( quote ( 1 2 3 )))
(1 2 3)
Command:!x
(1 2 3)
Command: ( type x )
LIST
СИМВОЛЫ
Command: ( setq x 'A )
A
Command:!x
A
Command: ( type a)
SYM
СТРОКИ
Текстовые строки могут иметь любую длину, до максимального объе-
ма памяти который может им выделяться. Их значение изменяется в
зависимости от количества кода AutoLISP и данных используемых в
настоящее время, и типа AutoLISP который используеися ( Обычный
или Расширенный ).
Строковые Константы ограничиваются максимальной длиной 100 симво-
лов.
Command: ( setq x " Text string " )
" Text string "
Command:!x
" Text string "
Command: ( type x )
STR
ВЕЩЕСТВЕННЫЕ ЧИСЛА
AutoLISP представляет вещественные числа как числа двойной точ-
ности с плавающей запятой, точные по крайней мере 14 значащими
цифрам. Нет никакого типа данных чтобы представить в AutoLISP
числа одиночной точности с плавающей запятой; все вещественные
числа - двойной точности, и представляются в AutoLISP тем же са-
мым способом каким они представляются в AutoCAD.
ТОЧНОСТЬ ОТОБРАЖЕНИЯ И ВНУТРЕННЯЯ ТОЧНОСТЬ
Точность отображения вещественных чисел в AutoLISP - только точ-
ность отображения. Внутреннее представление всегда точно по край-
ней мере до 14 цифр. Если необходимо отобразить или набрать зна-
чение вещественного числа с некоторой произвольной точностью вне
точности отображения AutoLISP-а по умолчанию, вещественное число
обычно преобразовывается в строку функцией AutoLISP (rtos) и
отображается или печатается в желаемой точности отображения.
(rtos) будет обсуждаться в будущем уроке о преобразовании типов
данных.
Command: ( setq x 4.5 )
4.5
Command:!x
4.5
Command: ( type x )
REAL
ЦЕЛЫЕ ЧИСЛА
В AutoCAD для DOS, целые числа - 16 битные числа со знаком в ин-
тервале между -32768 и +32767. Во всех других версиях AutoCAD,
они - 32 битные числа со знаком в интервале между -2,147,483,648
и +2,147,483,647. Целые числа перемещаемые между AutoLISP и
AutoCAD ограничиваются значениям в 16 бит. Для совместимости вер-
сий AutoCAD, лучше всего использовать в программах AutoLISP
только 16 битные значения.
Command: ( setq x 1 )
1
Command:!x
1
Command: ( type x )
INT
ОПИСАТЕЛИ ФАЙЛА
Описатель файла - внутренний указатель на файл, который открыт
для операции read/write/append. Функции желающие воздействовать
на открытый файл должны использовать описатель файла чтобы обра-
титься к файлу; следовательно, когда файл открывается, перемен-
ная должна связываться с описателем файла или файл не может быть
снова доступным.
В этом примере, функция (open) используется чтобы открыть файл
"file.ext" в каталоге и дисководе по умолчанию для операции запи-
си. Функция (open) возвращает описатель файла для "file.ext".
Command: ( setq x ( open "file.ext" "w" ))
<File: xxxx >
Command:!x
<File: xxxx >
Command: ( type x )
FILE
Command: ( setq x ( close x ))
nil
"ИМЕНА" ПРИМИТИВОВ AUTOCAD
Имя примитива - указатель на примитив в текущем сеансе редактора
AutoCAD. Имена примитивов изменяются от сеанса к сеанса, и то же
самое имя допустимо только в сеансе редактирования где оно найде-
но ( но оно будет допустимо для всего этого сеанса ).
Нет никакого способа сохранять имя примитива внутри рисунка
AutoCAD или внешнего файла для последующего использования в пос-
ледующих сеансах редактора; это средство преднамеренно недопусти-
мо.
Имена примитивов позволяют программам AutoLISP действовать на
уникальный, индивидуальный примитив. Методы выполняющие это бу-
дут исследоваться в следующих уроках; только краткий пример ил-
люстрируется здесь.
Функция (entlast) используемая в этом примере возвращает имя пос-
леднего примитива, добавляемого к рисунку.
Command: LINE
From point: 1,1
To point: 5,5
To point: return
Command: ( setq x (entlast) )
<Entity name: xxxx >
Command:!x
<Entity name: xxxx >
Command: ( type x )
ENAME
Command: ERASE
Select objects: !x
Select objects: return
НАБОРЫ ВЫБОРА AUTOCAD
Набор выбора - совокупность имен примиттивов, сохраненных во вре-
менном файле. Не более, чем шесть наборов выбора может открывать
AutoLISP в одно и тоже время. Для того, чтобы закрыть ненужную
переменную набора выбора, надо связывать переменную с нулем.
Функция (ssget) используемая в этом примере, запрашивает у
пользователя создать набор выбора и возвращает набор выбора как
значение выражения.
Command: LINE
From point: 1,1
To point: 5,5
To point: 10,1
To point: return
Command: ( setq x (ssget) )
Select objects: выбрать первую линию
Select objects: выбрать вторую линию
Select objects: return
<Selection set: xxxx >
Command:!x
<Selection set: xxxx >
Command: ( type x )
PICKSET
Command: ERASE
Select objects: !x
Select objects: return
ВСТРОЕННЫЕ ФУНКЦИИ
Command:!setq
<Subr: xxxx >
Command: ( type setq )
SUBR
ВОПРОСЫ
1. Какова внутренняя точность вещественных чисел в AutoLISP?
2. Имеет ли AutoLISP тип данных для чисел одиночной точности с
плавающей запятой?
3. Почему надо использовать в программх только 16-битные целые
числа а не 32-битные в не-DOS версиях AutoCAD?
4. Что случается когда файл открывается но описатель файла не
связан с переменной?
5. Как наборы выбора сохраняются в AutoLISP?
6. Сколько наборов выбора может быть открыто одновременно?
7. Что такое имя примитива?
8. Как может то же самое имя примитива сохраяться и ис-
пользуються в различных сеансах редактирования рисунка?
9. Каковы максимальные длины для строковой константы и строковой
переменной?
10. Какая функция может использоваться чтобы определить тип дан-
ных любого примитива или переменной?
Следующая тема: AutoLISP и AutoCAD Калькулятор
Отвечет на упражнения урока 3 :
1. Допустимый
2. Допустимый
3. Значение как оно есть
4. Допустимый
5. Допустимый
6. Значение как оно есть
1. (+ 3 10 5)
2. (* 20 15)
3. (- 16 10)
4. (/ 15 3)
5. (+ 5 (* 10 2))
6. (* (+ 5 10) 2)
1. ( setq x 1 )
!x
2. ( setq x 4.5 )
!x
3. ( setq x "text" )
!x
4. ( setq x ( quote ( 1.0 2.0 3.0 )))
!x
AUTOLISP: КАЛЬКУЛЯТОР AutoCAD
AutoCAD не имеет вычислителя, похожего на всплывающий калькуля-
тор в Sidekick чтобы выполнить арифметические операции и возвра-
щать соответствующее значение в командную строку AutoCAD, но он
имеет язык программирования чтобы вычислять и сохранять значения
и передавать их AutoCAD. Комментарий " AutoCAD не имеет встроен-
ный калькулятор " - истина, поскольку это бессмысленно, потому
что он имеет взамен весь встроенный язык программирования!
AutoLISP может использоваться в любое время в редакторе рисунка.
Он может использоваться в командной строке при запросе размернос-
ти, и при любом запросе сгенерированном любой командой AutoCAD.
Синтаксис не такой простой чтобы овладеть им сразу как у просто-
го калькулятора с 10 клавишами; однако, это еще более мощно. И
синтаксис, если он изучен, является простым и непротиворечивым.
ВОЗВРАТ ЗНАЧЕНИЯ В КОМАНДНУЮ СТРОКУ
Значение выражения AutoLISP передается от AutoLISP к AutoCAD как
ответ в командную строку AutoCAD.
Если командная строка активна, значение выражения просто печа-
тается в командной строке. Любой побочный эффект который происхо-
дит во время выполнения выражения, типа нового связывания симво-
лов, является несоответствующим для приглашения ко вводу команды
( пока команда AutoCAD не вызывается в выражении ). Например, эта
форма ( форма являясь любое сложное выражение которое обрабаты-
вается как код программы а не как данные ) связывает символ X и
результ сложения 4 и 6 а затем передает значение 10 в AutoCAD,
который просто печатает результат в командной строке.
Command: ( setq x ( + 4 6 ))
10
Нет никаких требование для связывания символов. Любая форма мо-
жет оцениваться в приглашении ко вводу команды просто чтобы воз-
вратить расчетное числовое значение.
Например, эта форма возвращает значение деления квадратного кор-
ня 50 на вещественное число 9.
Command: ( / ( sqrt 50.0 ) 9.0 )
0.785674
Эта форма возвращает значение умножения результата сложения 2.5 и
6.3 на 24.0.
Command: ( * ( + 2.5 6.3 ) 24.0 )
211.2
ВОЗВРАТ ЗНАЧЕНИЯ КОМАНДЕ AutoCAD
Если команда AutoCAD активна, тогда оценка формы AutoLISP возвра-
щает значение в AutoCAD. Значение становится ответом к текущей
подсказке команды AutoCAD.
В этом примере, команда ARRAY получает как число элементов масси-
ва результат формы AutoLISP которая делит 6.0 на 0.35; другими
словами, мы не знаем вначале сколько приходится величин 0.35 на
величину 6.0, так что мы просим AutoLISP вычислить это значение
для нас и возвратить ответ в AutoCAD. Так как подсказка из ARRAY
принимает только целочисленные значения, мы будем использовать
AutoLISP функцию ( fix <real> ) чтобы округлить полученное значе-
ние к самому близкому целому числу.
Command: ( / 6.0 0.35 )
17.1429
Command: ( fix 17.1429 )
17
Command: ( fix ( / 6.0 0.35 ))
17
Command: LINE
From point: 1,1
to point: 5,5
to point: <return>
Command: ARRAY
Select objects: L
Select objects: <return>
Rectangular or Polar array (R/P): R
Number of rows (---) <1>: 1
Number of columns (|||) <1>: (fix (/ 6.0 0.35))
Distance between columns: 0.35
В этом случае, AutoCAD создает 17 элементов в массиве.
Важным есть указание на то, что форма AutoLISP использовалась в
интерактивном режиме, в середине команды AutoCAD, для вычисления
значение ( в этом случае, целого числа ) которое впоследствии ав-
томатически предалось команде в этом же месте в качестве ответа
на запрос.
В этом примере AutoLISP вычисляет размер радиуса для команды
fillet.
Command: FILLET
Polyline/Radius/<Select two lines>: R
Enter fillet radius <1.0>: (/ 28.0 8.0)
Так как оба параметра для (/) - вещественные числа, результат ве-
щественен, и размер радиуса для команды fillet устанавливается в
3.5.
ИНТЕРАКТИВНОЕ ВЫЧИСЛЕНИЕ
Другой метод передавать значения команде AutoCAD состoит в том,
чтобы использовать форму AutoLISP которая непосредственно запра-
шивает пользователя набрать необходимые значения, а затем выпол-
няет некоторые операции над этими значениями, в конечном счете
возвращая ответ в AutoCAD. Это вероятно более легко для использо-
вания чем для объяснения.
Прежде, чем мы выполним некоторое сложное вычисление с запрошен-
ными у пользователя значениями, мы будем представлять две новых
функции AutoLISP: (getdist) и (getpoint).
ДВЕ НОВЫХ ИНТЕРАКТИВНЫХ ФУНКЦИИ
(getdist) останавливает выполнение формы и позволяет пользовате-
лю определять расстояние набрать на клавиатуре значение, или выб-
рать с помощю мыши две точки; точно такой же механизм использует-
ся каждой подсказкой AutoCAD которая запрашивает пользователя
указать расстояние.
(getpoint) останавливает форму и позволяет пользователю выбрать
точку, используя любой из стандартных методов выбора точки: ука-
зать на экране; ввести значение в абсолютных, относительных, или
относительных полярных координатах; используя обьектную привязку,
координатные фильтры, или спецификацию lastpoint.
GETDIST
Этот пример использует подсказку в функции (getdist), которая
запрашивает у пользователя расстояние. Пробуйте использовать эту
форму в командной строке и ответить на нее один раз набирая зна-
чение, а другой - выбирая две точки на дисплее.
Управляющие символы \n, или наклонная черта влево и нижний ре-
гистр n, означают переход на новую строку. Они необходимы для то-
го, что бы подсказка появилась на новой строке в области пригла-
шения ко вводу команды.
Command: ( getdist " \nEnter distance: " )
Enter a distance: <enter a number>
Command: (getdist "\nEnter a distance: ")
Enter a distance: <pick two points>
В обоих случаях, (getdist) возвращает расстояние введенное
пользователем как вещественное число.
GETPOINT
Этот пример использует подсказку для функции (getpoint), которая
запрашивает у пользователя точку. Пробуйте использовать эту фор-
му введя значение в абсолютных координатах, указав на экране, и
используя объектную привязку.
Command: ( getpoint " \nPoint: " )
Point: 1,1
(1.0 1.0 0.0)
AutoLISP возвращает точку как список трех вещественных чисел. 3-D
точки возвращаются как список трех вещественных чисел; 2-D точки
как список двух вещественных чисел. По умолчанию, все точки выб-
ранные в Версии 10 полностью 3-D, с X, Y, и Z значениями.
Первый элемент в списке точки - значение X, второй - значение Y,
и третий - значение Z.
Это выражение ( 1.0 1.0 0.0 ) не форма, потому что оно не может
оцениваться. Оно не содержит никакой функции в первом элементе
списка. Это - пример использование списка в AutoLISP чтобы сохра-
нить данные предпочтительнее чем код программы.
Command: ( getpoint " \nPoint: " )
Point: <pick point>
Command: LINE
From point: 1,1
To point: 5,5
To point: <return>
Command: (getpoint "\nPoint: ")
Point: MID
of <pick line>
(3.0 3.0 0.0)
НЕОБЯЗАТЕЛЬНЫЕ ПОДСКАЗКИ
Нет никаких жестких правил которые бы сообщали, что Вы должны
включать необязательный строковый аргумент в (getdist) или
(getpoint) как подсказку для пользователя. Однако, это - хорошая
практика если вы делать так. Можете предположить почему?
Пробуйте использовать (getdist) и (getpoint) без необязательного
строкового аргумента.
Command: (getdist)
?
Command: (getpoint)
?
ЕЩЕ БОЛЬШЕ ВЫЧИСЛЕНИЙ
Так как компьютер - по существу калькулятор с памятью, то вычис-
ления требуют чтобы AutoLISP помнил расстояния и точки.
В этом примере, переменная X связывается со списком трех вещес-
твенных чисел которые формируют координаты 1,1,0.
Command: ( setq x ( getpoint " \nPoint: " ))
Point: 1,1
(1.0 1.0 0.0)
Имеются другой способ связать X и список трех вещественных чисел
без того, чтобы использовать функцию (getpoint). Можете Вы не за-
были что это? Это функция которая сообщает чтобы AutoLISP брал
следующий аргумент в его значении (как данные), скорее чем пробо-
вал оценивать это (как форма )...
В этом примере, выберите произвольную точку где-нибудь на экране
с помощю курсора.
Command: ( setq x (getpoint) )
<pick a point>
Затем, начертите линию, начинающуюся в 0,0 и заканчивающий в точ-
ке сохраненной в переменной X. Как можно запросить AutoLISP ис-
пользовать текущее значение переменной?
Command: LINE
From point: 0,0
To point: !x
To point: <return>
Связывание переменных с очень точками просто. Это позволяет
пользователю сохранять так много точек сколько необходимых имен в
текущем сеансе редактирования чертежа, и обращаться к ним по име-
нам в любое время, когда AutoCAD просит точку.
Command: CIRCLE
3P/2P/TTR/<Center point>: !x
Diameter/<Radius>: 1.0
Command: (setq origin (quote (0.0 0.0 0.0)))
(0.0 0.0 0.0)
Command: MOVE
Select objects: Last
Select objects: <return>
Base point or displacement: !x
Second point of displacement: !origin
Предыдущий пример должен переместить окружность и расположить ее
центральную точку в 0,0. Можете ли Вы определить почему?
Вот другой пример команды ARRAY. Здесь AutoLISP будет вычислять
расстояние между двумя точками и использовать его затем, чтобы
определить сколько двойных элементов можно будет создать.
Сначала мы будем формировать некоторую произвольную геометричес-
кую конструкцию.
Command: LINE
From point: 1.1143,5
To point: 8.9178,5
To point: <return>
Command: CIRCLE
3P/2P/TTR/<Center point>: 1.1143,5
Diameter/<Radius>: 0.5
Теперь, мы будем использовать (getdist) чтобы помочь обеспечить
средства для ARRAY. В начале для ARRAY необходимо: в интерактив-
ном режиме вычислить число элементов которые должны появляться в
массиве основанном только на расстоянии между каждым элементом и
общими расстоянием в массиве! В этом примере, мы будем выделять
каждому элемету 0.5 едениц в отдельности.
Command: ARRAY
Select objects: Last
Select objects: <return>
Rectangular or Polar array (R/P): R
Number of rows: 1
Number of columns: (fix (/ (getdist "\nDistance: ") 0.5))
Distance: END
of <pick start point of line>
Second point: END
of <pick end point of line>
Distance between columns: 0.5
Вот другой пример который приспосабливает определенное пользова-
телем число элементов к вычисленному расстоянию.
Command: UNDO
Auto/Back/Control/End/Group/Mark/<number>: 1
Command: ARRAY
Select objects: Last
Select objects: <return>
Rectangular or Polar array (R/P): R
Number of rows: 1
Number of columns: 10
Distance between columns: (/ (getdist) 10)
END
of <pick start point of line>
Second point: END
of <pick end point of line>
Следующие занятие: Запись новых команд AutoCAD
Для этого урока нет никакх вопросов. Пожалуйста экспериментируй-
те самостоятельно, использование выражения AutoLISP в приглаше-
нии ко вводу команды и внутри команд AutoCAD чтобы вычислять и
сохранять ответы для AutoCAD.
ДОПОЛНИТЕЛЬНЫЙ КРЕДИТ
Одна из наиболее интересных форм которая содержится в Версии 10 -
файл REF.LSP, который вы можете найти на диске. Он описан в При-
ложении A Справочника Программиста на AutoLISP.
Исследуйте форму в REF.LSP. Сможете ли Вы определить как она ра-
ботает! Если Вы можете, тогда Вы имеете чистое понимание того как
AutoCAD и AutoLISP работают друг с другом. Сведение 1: функция
(setvar) делает ту же самое что и команда SETVAR AutoCAD.
ОТВЕТЫ НА УРОК 3
1. Вещественные числа сохраняются как числа двойной точности с
плавающей запятой, точные по крайней мере до четырнадцати знача-
щих цифр.
2. НЕТ.
3. Для совместимости кода с DOS версии AutoCAD.
4. Файл не может быть доступным для чтения, записи, или дополне-
ния, ни быть закрытым. ( AutoCAD самостоятельно будет закрывать
файл при завершении работы ).
5. Наборы выбора занимают временные слоты файла, и поэтому долже-
ны обрабатываться как драгоценные ресурсы. Переменная должна
всегда связываться с последним созданым набором выбора, иначе не-
возможен доступ к более поздним операциям внутри AutoLISP.
6. До шести; однако, не используйте больше чем четыре если вомож-
но.
7. Указатель на примитив записывают в сеансе редактирования ри-
сунка.
8. Не может; однако, программы обработки примитива могут сохра-
няться во время сеанса редактирования и использоваться чтобы
отыскать те же самые примитивы.
9. 100 символов; ограничение доступного пространства "кучи" кото-
рое может распредяться как пространство для строки, другими сло-
вами, ограничение доступной памяти.
10. Функция (type).
ЗАПИСЬ НОВЫХ КОМАНД AutoCAD
ПОДПРОГРАММЫ КАК АТОМЫ
AutoLISP имеет два вида объектов: атомы и списки. Каждый объект в
AutoLISP - один или другой. Пустой список nil () - определяет и
атом и список, и единственый объект в AutoLISP который также мо-
жет быть.
Атомы имеют большое количество различных типов данных. Один из
этих типов данных - SUBR, или подпрограмма. Подпрограммы - имена
для внутренних функции AutoLISP.
ФУНКЦИИ, СНАЧАЛА В ФОРМАХ
Когда сложное выражение создается для оценки, оно состоит из
списка с подпрограммой ( или внутренней функцией ) как первым
элементом. Такое выражение также известно как форма.
Пример формы:
( setq x 10 )
Какова подпрограмма в этом примере? Какую позицию она занимает в
списке?
Ниже пример списка который не является формой, то-есть список ко-
торый должен обрабатываться только как данные и не может оцени-
ваться.
(1.0 2.0 3.0)
Что случиться если AutoLISP попытался оценивать последнее выраже-
ние? Почему?
Это ведет нас к важному ограничению, что любой список который мо-
жет оцениваться ( любая форма ) должен иметь первым элементом
функцию.
ОПРЕДЕЛЯЕМЫЕ ПОЛЬЗОВАТЕЛЕМ ФУНКЦИИ
Кроме большого количества подпрограмм, AutoLISP позволяет соз-
двать определяее пользователем функции, то-есть функций чьи сис-
темы команд и имена определились пользователем.
Рассмотрим процесс оценки типичной формы которая использует под-
программу.
( setq x 10 )
AutoLISP оценивает первый элемент, где он ожидает найти функцию.
Здесь он находит подпрограмму SETQ, и отыскивает связывание SETQ.
Связывание SETQ ( фактически, связывание любой подпрограммы ) -
набор команд по которому должна проходить обработка. Затем,
AutoLISP оценивает параметры к SETQ по порядку, и в заключение
применяет связывание SETQ ( обработку команд ) со значением пара-
метров.
Результат в этом случае - значение 10 для выражения, и побочный
эффект - переменная X связывается с 10.
SETQ - подпрограмма, и ее команды были предопределены в AutoLISP;
пользователь не может изменять их. Однако, можно создавать пол-
ностью новые функции которые выполняют любые команды обработки по
желанию пользователя.
Новые функциональные связывания создаются используя подпрограмму
DEFUN, имя которой расшифровывается как DEfine FUNction.
КАК ИСПОЛЬЗОВАТЬ DEFUN
Синтаксис DEFUN является несколько отличным от других функций ко-
торые вы использовали в этом руководстве, но результат тот же са-
мый.
( Defun <имя функции > <список аргументов / список локальных переменных >
<выражение> ... )
DEFUN берет два требуемых параметра, и переменное число парамет-
ров после первых двух.
ПАРАМЕТРЫ К DEFUN
Первый требуемый параметр к DEFUN должен быть имя новой функции
которую вы хотите определить. Никогда не используйте имя встроен-
ной функции или символ как <имя функции>, так как это будет де-
лать встроенную функцию недоступной. Используйте новое имя, пред-
почтительно то которое описывает действия функции. Использование
в имени функции шести или меньше символов будет сохранять место в
памяти ( больше про это в последующих уроках ).
В этом примере, первый аргумент DEFUN - слово MYFUN, который ста-
новится именем определяемой пользователем функции.
( Defun MYFUN <список аргументов / список локальных переменных >... )
Второй необходимый аргумент DEFUN должен быть список требуемых
параметров и(или) локальных переменных. Этот аргумент будет об-
суждаться подробно позже в этом уроке. Теперь, достаточно ис-
пользовать пустой список, то-есть список без требуемых аргумен-
тов или локальных переменных.
Предыдущий пример расширим, чтобы включить список требуемых аргу-
ментов и (или) локальных переменных.
( Defun MYFUN() <выражение>... )
Параметры после списка требуемых параметров - выражения которые
нужно оценить когда определяемая пользователем функция выполняет-
ся. Они - команды обработки которые будут выполняться когда фун-
кция вызывается.
ПРИМЕР ПРОСТОГО ОПРЕДЕЛЕНИЯ ФУНКЦИИ
В следующих нескольких примерах выражения будут добавляться к те-
лу MYFUN. Различные наборы выражений будут давать различное зна-
чение MYFUN.
В этом примере, команды MYFUN сообщают чтобы были запрошены у
пользователя две точки, и затем было отображено расстояние между
этими двумя точками. Используется подпрограмма AutoLISP DISTANCE.
DISTANCE берет две точки как параметры, и вычисляет 3-D расстоя-
ние между ним.
(defun MYFUN ()
(setq pt1 (getpoint "\nFrom point: "))
(setq pt2 (getpoint pt1 "\nTo point: "))
(distance pt1 pt2)
)
Наберите этот пример. AutoLISP будет возвращать имя функции кото-
рая была определена; в этом случае, MYFUN. Вызовите MYFUN как Вы
бы вызвали любую подпрограмму.
Command: (MYFUN)
From point: <pick>
To point: <pick>
<возвратить расстояние как вещественное число >
ЗНАЧЕНИЯ ВОЗВРАЩЕННЫЕ ОПРЕДЕЛЯЕМЫМИ ПОЛЬЗОВАТЕЛЕМ ФУНКЦИЯМИ
Любая функция, созданная DEFUN будет возвращать значение когда
она вызывается, точно также как любая подпрограмма возвращает
значение. Значение возвращенное определяемой пользователем фун-
кцией будет значение последнего выражения в теле выражений кото-
рые включают команды обработки.
Например, в предыдущем примере значение выражения (myfun) будет
значение выражения ( distance pt1 pt2 ).
(Myfun) < ----- форма вызывающая определяемую пользователем функцию
(defun MYFUN ()
(setq pt1 (getpoint "\nFrom point: "))
(setq pt2 (getpoint pt1 "\nTo point: "))
(distance pt1 pt2 ) < ----- значение последнего выражения
) становится значением формы
СОХРАНЕНИЕ ОПРЕДЕЛЕННЫХ ФУНКЦИЙ НА ДИСКЕ
Хотя можно создавать определяемые пользователем функции набирая
соответствующий коде в командной строке, вероятно что лучшая идея
- использовать текстовый редактор по вашему выбору и записать
этот текст в новый файл с расширением .LSP; Затем загрузите файл
в AutoCAD функцией AutoLISP LOAD.
Функция LOAD берет в качестве аргумента строку, которая должна
содержать имя .LSP файла для загрузки.
(load "<имя файла>" )
Не забудьте что команда Load AutoCAD - совершенно другая вещь от
функции LOAD AutoLISP.
Например, если Вы добавляете код предыдущего примера в файл
MYFUN.LSP, тогда Вы можете загружать файл в AutoCAD следующим об-
разом:
Используйте текстовый редактор чтобы создать текстовый файл наз-
ванный MYFUN.LSP и включить код который создает эту определяемую
пользователем функцию. Затем загрузите файл в AutoCAD.
Command: (load "MYFUN")
MYFUN
AutoLISP будет искать этот файл в текущем каталоге, и в других
каталогах определенных в пути к библиотекам AutoCAD. Если это
файл будет найден, он будет загружен в редактор.
Если AutoLISP генерирует сообщение об ошибке при загрузке файла,
Вы должны отредактировать файл и устранить проблему.
ВЫЗОВ КОМАНДЫ AutoCAD ИЗ AUTOLISP
Очень популярная подпрограмма AutoLISP для определяемых пользова-
телем функций может создавать сокращенные имена для команд
AutoCAD, и объединять две или больше команд ( или команду и оп-
ции ) в одиночную команду.
Функция COMMAND вызывает команды AutoCAD непосредственно из
AutoLISP. COMMAND берет строковый аргумент который должен быть
именем команды AutoCAD и любых ее параметров, которые должны быть
переданы в командную строку AutoCAD.
Например, эта форма вызывает команду Line и чертит линию от 1,1
до 5,5. Форма возвращает нуль, потому что функция COMMAND всегда
возвращает нуль. Вообще, побочный эффект формы COMMAND еще более
интересен чем значение.
Command: (command "LINE" "1,1" "5,5" "")
nil
Нулевой параметр строки в конце списка параметров обрабатывается
как возврат каретки командой Line ( или любой командой ).
Кроме строковых аргументов для опций к командам, COMMAND будет
принимать вещественные или целые числа в соответствующих местах,
наряду с списками двух или трех вещественных числ как точек.
COMMAND также принимает переменные с соответствующими значениями.
Ниже другой способ начертания линии от 1,1 до 5,5.
(command "LINE" (quote (1.0 1.0)) (quote (5.0 5.0)) "")
В примере ниже, три формы используются чтобы начертить круг с
центральной точкой, выбранной пользователем и радиусом в 1.5.
Первые две формы используются чтобы собрать и сохранить данные, а
последняя - чтобы вызвать команду Circle и использовать предвари-
тельно сохраненные переменные как параметры к функции COMMAND.
Command: (setq pt1 (getpoint "\nCenter: "))
Center: <pick>
Command: (setq rad (getdist pt1 "\nRadius: "))
Radius: <pick>
Command: (command "CIRCLE" pt1 rad)
nil
ОПРЕДЕЛЕНИЕ НОВЫХ КОМАНД
Создадим простую и полезную функцию, которая бы объединяла коман-
ду Zoom с опцией Window.
В этом примере, специальное ключевое слово AutoLISP pause ис-
пользуется как аргумент для функции COMMAND. pause останавливает
оценку выражения и позволяет пользователю ответить на текущее
приглашение в командной строке.
Наберите этот код в новом текстовом файле, назвав его ZW.LSP, а
затем загрузите файл в AutoCAD.
( Defun ZW()
(command "ZOOM" "Window" pause pause)
)
Command: (load "ZW")
ZW
Command: (zw)
First corner: <pick>
Other corner: <pick>
nil
Недостаток этой функции - некоторое неудобство при вызове ее как
формы, то-есть надо набрать ее имя в круглых скобках и вызывать
ее как функцию AutoLISP. Это требование означает дополнительный
набор на клавиатуре конечным пользователем, и потребность пом-
нить, какие команды заключены в круглые скобки и какие нет.
AutoLISP позволяет создавать определяемые пользователем функции,
которые могут вызываться из командной строки без того, чтобы пе-
редавать их как формы, то-есть без того, чтобы включать имя фун-
кции в круглые скобки. Перед именем функции должен быть префикс
C:, как иллюстрируется ниже.
Добавьте этот код к новому текстовому файлу назвав его ZW.LSP.
Загрузите файл.
(defun C:ZW ()
(command "ZOOM" "Window" pause pause)
)
Command: (load "zw")
C:ZW
Command: ZW
or
Command: (C:ZW)
Ниже пример новой команды AutoCAD названной CD. CD чертит окруж-
ности по центральной точке и диаметру.
Добавьте этот код к новому текстовому файлу названному CD.LSP.
Загрузите файл.
(defun C:CD ()
(command "CIRCLE" pause "Diameter" pause)
)
Command: (load "cd")
C:CD
Command: CD
or
Command: (C:CD)
ПОДАВЛЕНИЕ ЗНАЧЕНИЯ ВОЗВРАЩЕННОГО ОПРЕДЕЛЯЕМОЙ ПОЛЬЗОВАТЕЛЕМ
КОМАНДОЙ
Значение последнего выражения в теле выражений после списка тре-
буемых параметров и локальных переменных в функциональном опреде-
лении всегда возвращается как значение функции. В большинстве
случаев, лучше не разрешать AutoLISP выводить это значение на
дисплей после того, как функция завершается.
Подпрограмма AutoLISP PRIN1 будет выводить пустую строку на дис-
плей если PRIN1 - последнее выражение в определении функции.
Например, эта модифицированная версия команды CD не печатает
"nil" в командной строке после завершения выполнения.
(defun C:CD ()
(command "CIRCLE" pause "Diameter" pause)
(prin1)
)
ТРЕБУЕМЫЕ АРГУМЕНТЫ К ФУНКЦИИ
Некоторые функции не берут никаких аргументов; некоторые требуют
одного или больше, или переменное число аргументов. Функция SETQ,
например, требует по крайней мере два параметра.
Параметры могут требоваться во время обращения к функции если они
включены в ее определение. Значения параметров будут отобра-
жаться в выражениях после указания в списке требуемых параметров
везде, где использовались переменные с теми же самыми именами как
и определенные в списке требуемых параметров.
Рассмотрим функциональное определение, которое не требует ника-
ких параметров. Оно запрашивает у пользователя вещественное чис-
ла, обрабатывает его как десятичное число, и возвращает значение
числа преобразованное в радианы.
(defun dtr ()
(setq degree (getreal "\nDegrees: "))
(/ (* degree pi) 180.0)
)
Эта функция должна вызываться с только одним объектом в форме -
самой функцией.
Command: (dtr)
Degrees: 180
3.14159
Можно создать эквивалентное выражение, которое бы требовало чис-
ленное значения как аргумент для формы, которая содержит функцию.
(defun dtr (degree)
(/ (* degree pi) 180.0)
)
В этом случае, функция должна вызываться с параметром.
Command: (dtr 180)
3.14159
Значение параметра 180 в предыдущей форме становится значением
требуемого параметра для DEGREE и AutoLISP впоследствии будет ис-
пользовать значение 180 где-нибудь в выражениях после списка тре-
буемых параметров где используется переменная DEGREE.
Следующий урок: Запись новых команд AutoCAD, Часть 2
Вопросы:
1. Что такое подпрограммы в AutoLISP?
2. Что такое форма в AutoLISP?
3. Каково различие между формой и списком ( или сложным выраже-
нием ), что должно обрабатываться строго как данные?
4. Какой вид атома должен всегда быть первым элементом в любой
форме?
5. Какая подпрограмма AutoLISP позволяет пользователю создавать
его собственные функции?
6. Каковы два требуемых параметра функции, обсуждаемой в пункте 5?
7. Каковы необязательные параметры функции обсуждаемой в пункте 5?
8. Какое значение возвращается определяемой пользователем фун-
кцией?
9. Как Вы можете использовать внешний файл, который содержит код
AutoLISP в AutoCAD ?
10. Какое ключевое слово позволяет пользователю отвечать на зап-
росы, сгенерированные командами AutoCAD, вызываемыми функцией
COMMAND AutoLISP?
11. Как можно устранить необходимость для пользователя вызывать
функцию включая ее имя в круглых скобках?
12. Какая функция будет возвращать пустую строку если она включе-
на как последнее выражение в определении функции?
13. Как может пользователь определить, требуется ли функции пара-
метр?
14. Где используются значения требуемых параметров внутри выраже-
ний, которые включают команды обработки определенной пользовате-
лем функции?
ЗАПИСЬ НОВЫХ КОМАНД AutoCAD ( Часть 2 )
ГЛОБАЛЬНЫЕ И ЛОКАЛЬНЫЕ ПЕРЕМЕННЫЕ
Имеются два вида переменных в AutoLISP. Это глобальные перемен-
ные и локальные переменные.
Глобальные переменные обьявляются в верхнем уровне интерпретато-
ра AutoLISP. Глобальные переменные и их значения доступны любому
выражению, в или вне тела функции. Значения могут восстанавли-
ваться. Они могут также изменяться.
Изменение значение глобальный переменной - это изменение которое
оценивается для всех выражений которые обращаются к переменной в
глобальном режиме.
Например, это выражение связывает переменную X со значением 1.
( setq x 1 )
1
!x
1
Другое выражение который использует X будет находить значение ко-
торое будет 1.
( defun FINDX()
( * x 1 )
)
FINDX
(findx)
1
Размещение выражения которое связывает X со значением внутри фун-
кционального определения имеет точно такой же самый эффект когда
функция вызывается, то-есть изменение глобального значения X.
( defun XGLOBAL()
( setq x 2 )
)
XGLOBAL
(xglobal)
2
!x
2
(findx)
2
Локальная переменная отличается от глобальной переменной следую-
щими свойствами:
1. Она обьявляется локально внутри определения функции.
2. После ввода функции в которой эта переменная была обьявлена как
локальная, AutoLISP будет сохранять текущее значение переменной.
3. Значение может изменяться внутри тела функции в которой пере-
менная была обьявлена, но как только функция заканчивает выполне-
ние, AutoLISP восстанавливает первоначальное значение переменной,
или восстанавливает ее в ноль, если она не существовало до обьяв-
ления внутри тела функции.
Отсюда следуют важные выводы. Переменные с одинаковыми именами
могут свободно использоваться внутри прикладных программ без опа-
сения конфликта. Пространство Памяти в "куче " оптимизируется по
мере возвращения переменных к их предыдущему значению или к нулю
при выходе из функции в которой они описываются как локальные.
Переменная можно обьявить локальной в функции помещая ее имя в
списке требуемых параметров и(или) локальных переменных в опреде-
лении функции.
Например, переменная X была обьявлена локальной в функции XLOCAL.
Но прежде, чем Вы создаете XLOCAL, проверьте текущее значение пе-
ременной X, оно должно быть 2 ( если нет, используйте SETQ чтобы
присвоить X 2 ).
!x
2
( defun XLOCAL ( / x )
( setq x 0 )
)
XLOCAL
Обратите Внимание На косую черту предшествующую переменной X. Она
используется чтобы отделить требуемые параметры для функции от
локальных переменных.
Вызовите функциональный XLOCAL в такой форме:
(xlocal)
0
Как Вы будете ожидать, XLOCAL возвращает значение последнего вы-
ражения в теле функции, которое является ( setq x 0 ). X связал-
ся со значением 0 во время выполнения функции. Но каково значе-
ние теперь?
!x
2
Значение X восстановилось к значению которое имело до ввода фун-
кции XLOCAL.
Добавьте оператор PRINT XLOCAL чтобы исследовать значение X в то
время когда оно еще внутри функции, и используют PRIN1 чтобы на-
печатать пустую строку при выходе из функции. Функция PROMPT ге-
нерирует строку для пользователя чтобы описать переменную кото-
рая напечатана.
(defun XLOCAL (/ x)
(setq x 0)
(prompt "The value of X is: ")
(print x)
(prin1)
)
XLOCAL
!x
2
(xlocal)
The value of X is:
0
!x
2
КОГДА ИСПОЛЬЗОВАТЬ ЛОКАЛЬНЫЕ ПЕРЕМЕННЫЕ
В общем случае, переменные должны быть обьявлены локальными внут-
ри функций в которых они используются. Это позволяет избежать
возможности конфликта между переменными с тем же самым именем в
другом месте в прикладной программе или внутри других прикладных
программ, и может помочь уменьшать количество используемой памяти.
Однако, переменные не должны никогда быть обьявлены локальными
пока прикладная программа не полностью отлажена. Причина для это-
го проста. Если прикладная программа аварийно завершается или
дает непредсказуемые результаты, невозможно исследовать значения
локально обьявленых переменных поскольку они связывались внутри
вызова функции, и поэтому возвращаются к их предыдущему состоя-
нию как только функция завершается.
КОГДА ИСПОЛЬЗОВАТЬ ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
Глобальные переменные должны использоваться всякий раз, когда
больше чем одна прикладная программа или функция должна использо-
вать значение той же самой переменной.
Следующие занятие: Запись новых команд AutoCAD, Часть 3
Упражнения
1. Перезаписать функцию MYFUN из Урока 5 обьявив переменные PT1 и
PT2 локальными в этой функции.
2. Перезаписать функцию MYFUN из Урока 5 чтобы она требовала два
параметра. Параметры переданные MYFUN должны оценивать как точки.
Ответ на вопросы Урока 5
1. Subr - тип данных в AutoLISP для внутренних функций.
2. Выражение чей первый элемент - функция, созданно для того что
бы оценить его.
3. Форма должна иметь функцию первым элементом чтобы оцениваться.
Списки, созданные чтобы содержать данные не обязательно оцени-
ваются, следовательно, в них первый элемент не обязательно дол-
жен быть функцией.
4. subr ( или определяемая пользователем функция ).
5. defun
6. Имя определяемой функции и список требуемых параметров и(или)
локальных переменных.
7. Выражения в теле определения которые включают команды обработ-
ки которые будут выполняться когда функция вызывается.
8. Значение последнего выражения в теле определения.
9. Использовать функции AutoLISP (load) чтобы загрузить файл.
10. pause
11. Префикс C: и имя функции как оно определено в (defun).
12. prin1
13. Включить символическое имя в список требуемых параметров.
14. Значения любых требуемых параметров переданных определяемой
пользователем функции используются во всех местам в выражениях в
теле функции, где используется имя переменной, указаной в списке
требуемых параметров.
ЗАПИСЬ НОВЫХ КОМАНД AutoCAD ( Часть 3 )
ПРОЕКТИРОВАНИЕ НОВОЙ КОМАНДЫ AUTOCAD
В предшествующих уроках, Вы научились определять функции, созда-
вать новые команды AutoCAD, описывать требуемые параметры фун-
кции, глобальные и локальные переменным.
Теперь время чтобы использовать то что Вы изучили ( наряду с дру-
гими темами которые мы обсуждлии в других уроках ) чтобы создать
новую команду AutoCAD.
Имеются некоторые общие правила проектирования, которые должны
применяться к всем новым командам AutoCAD которые Вы будете запи-
сывать в AutoLISP.
1. Подражать интерфейсу команд AutoCAD.
2. Покинуть среду чертежа когда Вы находите это нужным.
3. Избегать конфликта с другими прикладными программами.
Команда который Вы будете создавать на этом уроке будет запраши-
вать у пользователя две противоположные точки прямоугольника, и
чертит прямоугольник с помощю 2-D полилинии.
ИНТЕРФЕЙС ПОЛЬЗОВАТЕЛЯ
Основанные на AutoLISP команды должны подражать интерфейсу ко-
манд AutoCAD насколько это возможно. Пользователь будет находить
команду AutoCAD более простой чтобы работать с ней чем с той ко-
мандой в которой изобретается собственный интерфейс, только пото-
му что последовательность запросов пользователь уже знает.
Сначала определим команду BOX. Сначала не будем определять ника-
ких требуемыех параметров к функции, ни локальные переменных; по
крайней мере, пока функция не полностью отлажена.
Откройте новый текстовый файл назвав его BOX.LSP и начните запи-
сывать вашу новую команду.
( Defun C: BOX()
)
Затем, сгенерируете подсказку для пользователя чтобы он выбрал
первую точку. Подсказка сходна с приглашением ко вводу команды
ZOOM/Window, которое также запрашивает у пользователя две точки
диоганали прямоугольника.
( Defun C: BOX()
( Setq pt1 ( getpoint " \nFirst corner: " ))
)
Теперь кажется наступило временем визуально показать пользовате-
лю прямоугольник который будет чертится когда будет указана вто-
рая точка. Функция GETPOINT не обрабатывает этот случай, так что
теперь имеет смысл просмотреть руководство по AutoLISP чтобы оп-
ределить, существует ли функция,в которой мы нуждаемся. Всегда
лучше проверить, существует ли колесо, прежде повторно его изоб-
ретать.
Вы нашли функцию GETCORNER?
Как Вы можете видеть, GETCORNER берет как параметр базовую точку.
В нашей функции, это будет первая точка которую выбрал пользова-
тель. После запроса у пользователя второй точки, GETCORNER будет
изменять размеры "резинового" прямоугольника по мере перемещения
курсора и возвратит точку когда ее выберет пользователь.
(defun C:BOX ()
(setq pt1 (getpoint "\nFirst corner: "))
(setq pt2 (getcorner pt1 "\nOther corner: "))
)
Пробуйте новую команду BOX в текущем состоянии чтобы проверить
интерфейс пользователя.
Command: (load "box")
C:BOX
Command: BOX
First corner: <pick>
Other corner: <drag and pick>
Интерфейс теперь работает. Все что теперь необходимо - это пос-
троить полилинию, основанную на значениях сохраненных в PT1 и PT2.
Вызывается функция COMMAND, чтобы начать чертить полилинию. Пе-
ред именем команды ставится точка, чтобы гарантировать что мес-
тная команда PLINE доступна в случае если она обьявлена UNDEFINE
в текущем сеансе AutoCAD ( см. команду UNDEFINE в Справочном опи-
сании AutoCAD ). PT1 используется как параметр для запроса "From
point:" команды PLINE.
(defun C:BOX ()
(setq pt1 (getpoint "\nFirst corner: "))
(setq pt2 (getcorner pt1 "\nOther corner: "))
(command ".PLINE"
pt1
)
)
Здесь начинается полилиния от PT1. Следующий шаг в алгоритм ко-
манды будет вычисление двух других точек, основаное на PT1 и PT2,
и посылка этих точек в соответствующем порядке команде PLINE.
РАБОТА С ТОЧКАМИ КАК СПИСКАМИ ВЕЩЕСТВЕННЫХ ЧИСЕЛ
AutoLISP сохраняет координаты точки как список трех вещественных
чисел. Например, это выражение связывает переменную PT и список
(1.0 2.0 3.0).
Command: (setq pt (getpoint "\nPoint: "))
Point: 1,2,3
(1.0 2.0 3.0)
Обратите внимание, что о 3-D точке не обязательно думать как о
одиночном обьекте. Истинно что список сохраняющий координатные
значения - одиночный объект, но он - сложный объект, непосред-
ственно состоящий из списка трех элементов. При размышлении об
этом таким образом, легко представить точку, как раздельные зна-
чения X, Y, и Z объединенные вместе в некоторой произвольном но
очень полезное соединении.
AutoLISP имеет большое количество функций чтобы отыскивать и за-
менять элементы ( в этом случае, отделять координатные значения )
внутри существующего списка. Наиболее простая - функции CAR и CDR.
Каждая из функций CAR и CDR берет один требуемый параметр, кото-
рый должен быть списком.
CAR возвращает первый элемент списка.
CDR возвращает список и все в нем КРОМЕ первого элемента.
Если функцию CAR применить к переменной PT, какой значение она
будет возвращать? К какой координате его можно приравнять?
Command: (car pt)
1.0
CAR возвращает первый элемент PT, который является значением
координаты X.
Что будет возвращать функция CDR когда она будет применена к PT?
Command: (cdr pt)
(2.0 3.0)
На первый взгляд, это не является особенно полезным. Но что слу-
чится если мы применим CAR к результату описному выше? Какое
координатное значение будет возвращать комбинация CAR и CDR?
Command: (car (cdr pt))
2.0
CDR возвращает список после того, как первый элемент удаляется, в
этом случае список ( 2.0 3.0 ). Когда CAR получает этот список
как параметр, она возвращает первый элемент, который является Y -
координатой точки.
(car <точка>) возвращает X - координату точки.
(car (cdr <точка>)) возвращает Y - координату точки.
И, наконец, (car ( cdr ( cdr <точка> ))) возвращает Z - координа-
ту точки.
ВЫЧИСЛЕНИЕ ДРУГИХ ТОЧЕК
Если PT1 и PT2 содержат значения двух точек которые формируют
диагональ прямоугольника, тогда другие его точки могут быть опре-
делены объединяя X и Y значения PT1 с Y и X значениями PT2. В на-
шем случае, мы игнорируем значения Z, потому что мы имеем дело с
2-мерной полилинией.
PT3 совместно использует значение X от PT1 и значением Y от PT2.
PT4 совместно использует значение X от PT2 и значением Y от PT1.
PT3 -------------------------------- PT2
| |
| |
| |
| |
PT1 -------------------------------- PT4
Как мы будем использовать функции CAR и CDR чтобы извлечь соот-
ветствующие значения из PT1 и PT2?
Значение X PT1: ( car pt1 )
Значение Y PT1: ( car ( cdr pt1 ))
Значение X PT2: ( car pt2 )
Значение Y PT2: ( car ( cdr pt2 ))
СОЗДАНИЕ СПИСКОВ ДЛЯ НОВЫХ ТОЧЕК
Если Вы понимаете как отыскивать индивидуальные значения коорди-
нат из PT1 и PT2, Вы можете захотеть узнать как объединять от-
дельные значения в новые списки которые AutoLISP будет обрабаты-
вать как точки.
Функция LIST берет произвольное число параметров и возвращает
список элементы которого состоят из параметров этой функции.
Например, это выражение возвращает список трех элементов:
Command: (list 1.0 2.0 3.0)
(1.0 2.0 3.0)
LIST возвращает значения своих аргументов.
Command: (setq x 1.0)
1.0
!x
1.0
Command: (setq y 2.0)
2.0
!y
2.0
Command: (setq z 3.0)
3.0
!z
3.0
Command: (list x y z)
(1.0 2.0 3.0)
Command: (setq pt (list x y z))
(1.0 2.0 3.0)
!pt
(1.0 2.0 3.0)
Добавим к определению нашей функции BOX вычисление других точек
прямоугольника. Опция "C" закрывает полилинию и завершает коман-
ду PLINE.
(defun C:BOX ()
(setq pt1 (getpoint "\nFirst corner: "))
(setq pt2 (getcorner pt1 "\nOther corner: "))
(command ".PLINE"
pt1
(list (car pt2) (car (cdr pt1)))
pt2
(list (car pt1) (car (cdr pt2)))
"C"
)
)
Проверите текущее определение функции BOX загрузив ее в AutoCAD.
Помните, AutoLISP не найдет изменений которые Вы сделаете в ис-
ходном файле, пока Вы не загрузите этот файл после этого, как
сделаете изменения.
Command: (load "box")
C:BOX
Command: BOX
First corner: <pick>
Other corner: <drag and pick>
From point:
Current line-width is 0.0000
Arc/Close/Halfwidth/Length/Undo/Width/<Endpoint of line>:
Arc/Close/Halfwidth/Length/Undo/Width/<Endpoint of line>:
Arc/Close/Halfwidth/Length/Undo/Width/<Endpoint of line>:
Arc/Close/Halfwidth/Length/Undo/Width/<Endpoint of line>: C
Command: nil
BOX должен вывести замкнутую, прямоугольную 2-мерную полилинию
ограниченную двумя противоположными точками, которые Вы выбрали.
Если это не случилось, отладьте программу и устанавливал пробле-
му прежде, а затем продолжим.
ОЧИСТКА ИНТЕРФЕЙСА
Часть интерфейса BOX, отвечающая за ввод данных работает хорошо,
но есть несколько тонкостей, которые лучше решить, чтобы сделать
работу нашей функции более эффективной.
1. Нет необходимости выводить эхо и подсказки команды PLINE в ко-
мандной строке; фактически, это замедляет работу программы.
2. Нуль который возвращает BOX должен подавляться.
3. Не необходимости чертить крестики в углах прямоугольника.
Функции GETVAR и SETVAR используются, наряду с SETQ, для сохране-
ния значений системных переменных CMDECHO и BLIPMODE при загруз-
ке C:BOX, изменения их значений во время выполнения C:BOX, и вос-
становления первоначальныех значений при выходе из C:BOX.
PRIN1 вызывается как последнее выражение в теле C:BOX чтобы вы-
вести пустую строку на на экран после выхода из С:BOX, для подав-
ления нуля, который будет возвращаться иначе.
(defun C:BOX ()
(setq old_cmdecho (getvar "CMDECHO")
old_blipmode (getvar "BLIPMODE")
)
(setvar "CMDECHO" 0)
(setvar "BLIPMODE" 0)
(setq pt1 (getpoint "\nFirst corner: "))
(setq pt2 (getcorner pt1 "\nOther corner: "))
(command ".PLINE"
pt1
(list (car pt2) (car (cdr pt1)))
pt2
(list (car pt1) (car (cdr pt2)))
"C"
)
(setvar "CMDECHO" old_cmdecho)
(setvar "BLIPMODE" old_blipmode)
(prin1)
)
Проверьте BOX. Если все работает как ожидается, определите пере-
менные используемые подпрограммой, которые являются локальными в
функции.
(defun C:BOX (/ pt1 pt2 old_cmdecho old_blipmode)
...
Поздравляем. Теперь позвольте вашему воображению наполнится ди-
кой и необузданой фантазией и думать о самых различных способах
какими Вы можете использовать AutoLISP чтобы изменять структуру
команд AutoCAD, и добавлять в него новые команды чтобы выполнять
ваши задачи по проектированию более просто!
Это ваше задание!
Следующий урок: Предикаты, логические операторы и условные выра-
жения.