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

AutoLISP в среде Visual LISP

Выполнение команд AutoCAD из AutoLISP

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

Синтаксис функции:

(command [<параметр1> [<параметр2> ... [<параметрN>] ... ] ] ) 

Возвращаемое значение - nil.

Функция может вызываться без параметров - это равносильно нажатию клавиши <Esc>, что прерывает действие активной команды. Если параметры используются, то их количество может быть любым. Каждый из параметров обычно является текстовой строкой, имитирующей набор символов строки на клавиатуре с последующим нажатием клавиши <Enter>. Возвращаемое значение - nil.

Предположим, что нужно нарисовать отрезками рамку формата размером 210 на 297 (левый нижний угол рамки взять в точке 0,0 и верхний правый - в точке 210,297). Вспомним, что команда рисования отрезков в системе AutoCAD называется LINE. Если вы не уверены, что ваша программа будет работать на машине с русской версией AutoCAD, то используйте английские имена команд с подчеркиванием (в данном случае - _LINE). С такими именами команды будут выполняться в любой версии системы. Если бы вы выполняли задачу без программы, то вводили бы с клавиатуры следующие команды и опции:

_LINE 
0,0 
210,0 
210,297 
0,297 
_С 

По этим указаниям AutoCAD вызовет команду _LINE, возьмет в качестве первой точки 0,0, в качестве второй - 210,0, в качестве третьей - 210,297, в качестве четвертой - 0,297, а (соответствует опции Close) замкнет отрезки на первую точку (опции тоже желательно вводить английские и с подчеркиванием). Программа, имитирующая описанный алгоритм, занимает одну строку и выглядит так:

(command "_LINE" "0,0" "210,0" "210,297" "0,297" "_С")

Можно координаты точек задавать не как строку, а как списки из двух чисел целого или вещественного типа.

(command "_LINE" '(0 0) '(210 0) '(210 297) '(0 297) "_С")

Апостроф опускать нельзя, т. к. выражение (210 0) без апострофа будет рассматриваться как обращение к функции 210 с аргументом 0.

Там, где требуется ввод чисел, можно в качестве аргументов подавать функции command именно числа, а не строки с числами, например:

(command "_COLOR" "1") (command "_COLOR" 1)

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

Можно в одной функции command обратиться сразу к нескольким командам системы AutoCAD, например:

(command "_COLOR" 1 "_ZOOM" "_E")

Эта программная строка выполнит команду COLOR для установки красного цвета и команду ZOOM с опцией EXTENTS (ГРАНИЦЫ).

Часто пользователь вместо ввода опции нажимает на клавишу <Enter>. Для имитации этого варианта в качестве параметра функции command выступает текстовая строка нулевой длины ("").

Встроенные функции

Мы уже рассмотрели некоторые функции AutoLISP, встроенные в систему AutoCAD (setq, load, command). Встроенные функции по своему назначению можно классифицировать следующим образом:

  • арифметические функции;
  • логические функции;
  • функции вычислений;
  • функции преобразований;
  • функции, работающие со строками;
  • функции, работающие со списками и точечными парами;
  • функции ввода данных и указания объектов;
  • функции доступа к файлам;
  • функции доступа к примитивам;
  • функции доступа к табличным данным;
  • функции, работающие с расширенными данными;
  • функции, использующие технологию ActiveX.

Арифметические функции

К арифметическим относятся следующие функции (вместе с описанием функций приводится их синтаксис):

  • (+ [<число1> [<число2> ... [<числоN>] ... ] ]) - сложение любого количества чисел;
  • (- [<число1> [<число2> ... [<числоN>] ... ]]) - вычитание из первого числа суммы любого количества чисел;
  • (* [<число1> [<число2> ... [<числоN>] ... ]]) - перемножение любого количества чисел;
  • (/ [<число1> [<число2> ... [<числоN>] ... ]]) -деление первого числа на произведение любого количества чисел;
  • (1+ <число>) - увеличение числа на 1;
  • (1- <число>) - уменьшение числа на 1;
  • (∼ <число>) - дополнение числа до - 1;
  • (abs <число>) - абсолютная величина числа.

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

Примеры:

(+1 3) - возвращает 4; 
(- -2 1.1 0.3) - возвращает - 3.4; 
(* -2 1.1 0.3) - возвращает - 0.66; 
(/ -2 1.1 0.3) - возвращает - 6.06061; 
(/ 5 12) - возвращает 0 (оба аргумента целые!); 
(1 + 1.1) - возвращает 2.1; 
(1 - 1.1) - возвращает -0.1; 
(∼ 3) - возвращает - 4; 
(abs -1.1) - возвращает 1.1.

Логические функции

Логические функции выполняют различные операции: проверки, логические операции, организуют повторения и циклы.

Следующие функции выполняют операции сравнения:

  • (= <аргумент1> [<аргумент2> ... [<аргументN> ]...]) - проверка на равенство любого количества аргументов (рекомендуется использовать для чисел или строк);
  • (/= <аргумент1> [<аргумент2> ... [<аргументN> ]...]) - проверка на неравенство любого количества аргументов (рекомендуется использовать для чисел или строк);
  • (< <аргумент1> [<аргумент2> ... [<аргументN> ]...]) - проверка на возрастание любого количества аргументов, слева направо (для чисел или строк);
  • (> <аргумент1> [<аргумент2> ... [<аргументN> ]...]) -Проверка на убывание любого количества аргументов, слева направо (для чисел или строк);
  • (<= <аргумент1> [<аргумент2> ... [<аргументN> ]...]) - Проверка на неубывание любого количества аргументов, слева направо (для чисел или строк);
  • (>= <аргумент1> [<аргумент2> ... [<аргументN> ]...]) - Проверка на невозрастание любого количества аргументов, слева направо (для чисел или строк).

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

Примеры:

(= -10.0 -10 -10.000) - возвращает T; 
(= "STR56" "str56" "Str56") - возвращает nil; 
(= "abcde" "abcde") - возвращает Т; 
(/= -1.0 -1) - возвращает nil; 
(/= "STR56" "Str56" "Str56") - возвращает T; 
(/= "abcde" "abcde") - возвращает nil; 
(< "a" "b" "k") - возвращает T; 
(> 2 2 30) - возвращает nil; 
(<= "q" "qa") - возвращает T; 
(>= "qa" "q") - возвращает T.

Следующие функции выполняют логические операции:

  • (and [<аргумент1> [<аргумент2> ... [<аргументN>]...]]) - операция логического "И" для любого количества аргументов (все, что отлично от nil, рассматривается как т);
  • (or [<аргумент1> [<аргумент2> ... [<аргументN>]...]]) - операция логического "ИЛИ" для любого количества аргументов (все, что отлично от nil, рассматривается как Т);
  • (not <аргумент>) - операция логического "НЕ" (все, что отлично от nil, рассматривается как Т);
  • (null <аргумент>) - операция проверки на nil (все, что отлично от nil, рассматривается как Т); идентична функции not.

Примеры:

(and т т nil) - возвращает nil; 
(and "a" "b" "k") - возвращает T; 
(or т nil т) - возвращает T: 
(or "а" "b" "k") - возвращает T; 
(not nil) - возвращает T; 
(not 15.88) - возвращает nil; 
(null '()) - возвращает T; 
(null "Tram") - возвращает nil.

Условная операция типа if-then-else (если-то-иначе) осуществляется с помощью функции IF:

(if <условие> <выражение1> [<выражение2>])

Типы аргументов: любые.

Возвращаемое значение: вычисленное значение <выражение1>, если значение <условие> отлично от nil (nil в логических операциях используется как "ложь"); или значение <выражение2>, если значение <условие> равно nil (когда <выражение2> опущено, тогда вместо >выражение2< возвращается nil).

Примеры:

(if (> a b) 1 10) - возвращает 1, если a>b, и 10 - в других случаях; 
(if (= h1 h2) (+ h1 15) (* h1 2.5)) - возвращает результат вычисления выражения (+ h1 15), 
если значения h1 и h2 равны; иначе - результат вычисления выражения (* h1 2.5);
(if (< a b) "a<b") - возвращает строку "а<b" или nil (т.к. <выражение2> опущено);
(if nil "Point") - возвращает nil (т. к. <условие> всегда ложно).

Если функция if используется для выполнения по условию не одного выражения, а нескольких, то эти выражения следует объединить с помощью функции рrоgn (иначе будет синтаксическая ошибка, вызванная неправильным количеством аргументов при обращении к функции if):

(рrоgn <выражение1> <выражение2> ... [<выражениеN>])

Функция объединяет несколько (не менее двух) выражений в одно, когда по синтаксису языка AutoLISP может использоваться только одно (как в функции if).

Типы аргументов: любые.

Рассмотрим использование функции progn. Пусть при выполнении условия (< а b) нужно выполнить выражения (setq с -1), (setq d (-cab)) и (* d b) , а при невыполнении условия - выполнить выражения (setq с 2), (setq d (* а b) ) и (* d с) .

Пример совместного использования функций if и progn:

(if (> а b) 
(progn 
(setq с -1) 
(setq d (-cab)) 
(* d b) 
); 			конец progn 
(progn 
(setq с 2) 
(setq d (* а b)) 
(* d с) 
) ;			конец progn 
); 				конец if

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

Условная операция типа case с любым количеством условий осуществляется с помощью функции cond:

(cond (<условие1> [<выражение1> ... ] ) [ (<условие2> [<выражение2> ... ])] ...) 

Аргументы: любое количество списков, в каждом из которых на первом месте стоит проверяемое условие, а затем следуют выражения, которые должны быть выполнены (вычислены), если это условие оказалось истинным.

Возвращаемое значение функции cond - последнее вычисленное выражение. Если вычисляемое выражение отсутствует (не задано в списке), то возвращается результат вычисления последнего аргумента <условие>. Если аргументы функции cond не заданы, то возвращается nil.

Примеры:

(cond) - возвращает nil; 
(cond (14)) - возвращает 14. 

Впрочем, использование функции cond с неполным количеством аргументов не имеет особого смысла.

Рассмотрим пример: переменной mycolor нужно присвоить текстовое значение с наименованием одного из основных цветов AutoCAD ("красный", "желтый", "зеленый", "голубой", "синий") в зависимости от текущего значения переменной сс, которая принимает значения 1, 2, 3, 4, 5. В случае если значение переменной сс оказалось отличным от перечисленных, то переменной mycolor нужно присвоить "" (пустая строка).

Пример 1 использования функции cond:

(setq mycolor 
  (cond 
    ((= cc 1) "красный") 
    ((= cc 2) "желтый") 
    ((= cc 3) "зеленый") 
    ((= cc 4) "голубой") 
    ((= cc 5) "синий") 
    (Т "") 
  ); конец cond 
); конец setq 

Функция setq присваивает переменной mycolor результат вычисления функции cond. Значение, возвращаемое функцией cond, вычисляется по следующей схеме. Сначала рассматривается список, заданный в качестве первого аргумента- ((= cc 1) "красный") - и проверяется условие, являющееся первым элементом этого списка. Если оказалось, что значение переменной cc равно 1 и, значит, первое условие возвращает "истину", то дальнейшее рассмотрение аргументов функции cond прекращается. В качестве возвращаемого значения принимается "красный". Если первое условие не вычислилось как "истина", то проверяется второе условие и т. д. В качестве последнего, шестого, условия стоит Т, т. е. "истина" при любых значениях. При этом, если значение переменной cc не совпало с 1, 2, 3, 4, 5, то в качестве возвращаемого значения функции cond будет принято "" (пустая строка).

Еще один пример иллюстрирует случай, когда по истинности значения <условие> выполняются несколько операторов.

Пример 2 использования функции cond

(cond 
    ((= cc 1) 
        (setq abc "красный") 
        (command "_PLINE" "-50,120.45" "97.66,23.124" "45.7,800" "_С") 
    ); = cc 1
    ((= cc 2)
        (setq abc "желтый") 
        (command "_CIRCLE" "-50,120.45" "100") 
    ); = cc 2
) ; конец cond

В этом примере функция cond проверяет значение переменной cc. Если оно равно 1, то функция setq присваивает переменной abc значение "красный", а затем AutoCAD рисует замкнутую полилинию с тремя вершинами. Если значение cc равно 2, то функция setq присваивает переменной abc значение "желтый", a AutoCAD рисует окружность радиуса 100. Если окажется, что значение cc не равно ни 1, ни 2, то функция cond вернет nil, не изменяя при этом значения переменной abc и не строя никаких новых примитивов AutoCAD. Поскольку функция command является последним выражением, как в первом, так и во втором условиях функции cond, то во всех трех случаях будет возвращено значение nil (nil является возвращаемым значением функции command). Однако в данном примере функция cond применена не ради возвращаемого значения, а ради изменения значения переменной abc и построения дополнительной полилинии или окружности.

Существует несколько проверочных функций, которые проверяют конкретные значения или типы:

  • (minusp <число>) - проверка числа на отрицательность;
  • (zerop <число>) - проверка числа на ноль;
  • (numberp <аргумент>) - проверка типа аргумента на число;
  • (listp <аргумент>) - проверка типа аргумента на список;
  • (boundp <символ>) - проверка, присвоено ли значение символу AutoLISP; для указания на имя функции его следует предварять апострофом.

Все эти функции возвращают значение Т, если аргумент удовлетворяет требуемому условию, и nil - если не удовлетворяет.

Примеры:

(minusp (-52 24 39)) -возвращает т; 
(zerop 0.0) - возвращает т; 
(numberp -10.0) - возвращает т; 
(numberp "1") - возвращает nil; 
(listp "1") - возвращает nil; 
(listp ' (-21.82)) - возвращает т; 
(boundp ' +) - возвращает т.

Функция eq проверяет равенство двух аргументов (аналогична функции =):

(eq <аргумент1> <аргумент2>) 

Типы аргументов: любые.

Тип возвращаемого значения: логическое (т, если значения аргументов совпали, и nil, если не совпали).

Примеры:

(eq -10.0 -10) - возвращает т; 
(eq о 3) - возвращает nil; 
(eq "abc" "АBC") - возвращает nil.

Функция equal проверяет равенство двух объектов (для чисел и списков из числовых величин равенство проверяется в пределах допуска):

(equal <аргумент1> <аргумент2> [<допуск>]) 

Типы аргументов: любые.

Тип возвращаемого значения: логическое (т, если абсолютная величина разности аргументов не превосходит значение аргумента <допуск>, и nil, если не совпали; если >допуск< не задан, то его значение считается равным нулю). Для аргументов, не являющихся числами или списками из чисел, <допуск> не используется.

Примеры:

(equal -10.0 -10) - возвращает Т; 
(equal 3.000 3.002 0.002) - возвращает Т; 
(equal "font" "font") - возвращает т; 
(equal ' (1.00 2.13 2.99) ' (1 2.13 3.0) 0.1) - возвращает Т. 

Функция while позволяет организовывать операции цикла по многократно проверяемому условию:

 (while <условие> <выражение1> [<выражение2> ... [<выражениеN>] ... ] ) 

Типы аргументов: любые.

Возвращаемое значение функции while: значение <выражение>, когда последнее вычисленное значение аргумента <условие> отлично от nil. При неудачном задании цикл, организуемый с помощью функции while, может оказаться бесконечным.

Рассмотрим пример. Пусть надо вычислить значение n! (факториал), т. е. произведение целых чисел от 1 до n. В данном разделе восклицательный знак используется как знак функции факториала.

Пример использовании функции while (вычисление факториала)

(setq i 1 factorial 1)
(while (< i n)
  (setq i (1+ i))
  (setq factorial (* factorial i))
); конец while

Рассмотрим работу примера, когда число n равно 11 (т. е. вычисляется 11!).

В программе используются переменные i (это переменная, являющаяся счетчиком цикла) и factorial (переменная, которая накапливает произведение чисел, формирующее факториал). Перед входом в цикл они получают начальные значения - соответственно, 1 и 1 (по определению 1! считается равным 1).

Функция while проверяет условие (< i n) для текущего значения i и, если результат вычисления условия отличен от nil, то выполняет внутренние операции (две операции с участием функции setq). Таким образом, при первом входе в цикл i равно 1, проверяемое условие (< 1 n) возвращает значение т ("истина"), и функция while увеличивает i на l (получается i=2) и умножает переменную factorial на i: factorial=l*2 (не что иное как 2!).

Далее снова передается управление на вход в цикл (уже при i=2). Проверка условия опять дает результат "истина", поэтому i получает значение 3 (2+1), a factorial - 6 (2*3). И так далее, пока i не станет равным n (11) и программа покинет цикл, не выполняя внутренних операций. Результат: при n=11 factorial=39,916,800 (запятые разделяют триады цифр).

Функция repeat используется для организации цикла с фиксированным количеством повторений:

(repeat <количество> [<выражение1> ...] ) 

Типы аргументов: <количество> - целое число (имеют смысл только положительные числа), <выражение1> - любое выражение. После аргумента <выражение1> могут идти другие выражения, которые нужно выполнить внутри цикла.

Возвращаемое значение - значение последнего вычисленного выражения. Если аргумент <количество> имеет нулевое или отрицательное значение, или после аргумента <количество> не заданы выражения, то функция repeat возвращает nil.

Воспользуемся функцией repeat вместо while в предыдущем примере.

Пример использования функции repeat (вычисление факториала)

(setq i 1 factorial 1) 
(repeat (1- n) 
(setq i (1+ i)) 
(setq factorial (* factorial i)) 
); конец repeat 

Поскольку входные значения i=1 и factorial = l! =1, то остается умножить factorial на 2, 3, ... , n. Количество таких умножений равно n-1, что на языке AutoLISP записывается как (1- n) . Остальное работает как в предыдущем примере.

Алексей Тимонин
Алексей Тимонин
Что возвращает функция chr() в таком примере (chr (- 65 1))?
Алексей Потапкин
Алексей Потапкин
как передать параметры в макрос