Урок 11. AutoLISP. Создание блока.

В языке программирования LISP создать блок можно несколькими способами. Рассмотрим некоторые из них. Блок мы будем создадим из куба созданного в уроке: Простой пример программы на LISP.

Первый способ. Создание блока при помощи функции «command».

Давайте в начале мы вспомним код программы, которая рисует куб. См. Рис. 1

AutoLISP. Создание блока.

Рис. 1.  Программа mp_kub.

Откройте эту программу.

Поменяйте имя пользовательской функции на mp_kub2.

Сохраните ее под другим именем.

Теперь добавим в эту программу переменную bl_name, в которой будем хранить имя блока “kub200”.

(setq bl_name “kub200”)

Кроме этого, после создания примитива нам нужно запоминать имя, которое присваивает ему Автокад.

После построения отрезка между точками р1 и р2:

(command "_line" p1 p2 "")

Запоминаем его имя в переменной np1

(setq np1 (entlast))

Функция entlast считывает имя последнего нарисованного примитива.

Функция setq присваивает переменной np1 значение функции (entlast)

Аналогичную процедуру мы проделываем для всех остальных примитивов.

В результате наша программа примет следующий вид. См. Рис. 2.

AutoLISP. Создание блока.

Рис. 2. Запоминает имена примитивов в базе данных AutoCAD.

Теперь у нас есть все переменные необходимые для создания блока.

Функция «command» имитирует командную строку Автокад и создание блока в AutoLISP происходит аналогично его созданию в AutoCAD:

В начале мы при помощи «command» запускаем стандартную команду AutoCAD по созданию блоков “_block”.

Затем вводим имя блока (bl_name).

Далее указываем базовую точку блока (p1).

Далее выбираем примитивы, которые мы хотим включить в блок (указываем имена примитивов в базе данных Автокад  np1 np2 np3 и так далее).

И в конце выбора примитивов ставим “”, которые имитируют нажатие клавиши <Enter>.

В общем виде это выглядит так:

(command “_block” bl_name p1 np1 np2 np3””)

После создания блока таким способом все примитивы вошедшие в блок удаляются автоматически. И чтобы увидеть наш блок его нужно вставить:

(command "_insert" bl_name p1 1 1 0), где
"_insert" – стандартная команда Автокад по вставке блока.
bl_name – переменная, в которой хранится имя вставляемого блока.
р1 – переменная с координатами точки вставки блока.
1 – масштабный коэффициент по оси X.
1 – масштабный коэффициент по оси Y.
0 – угол поворота блока в градусах.

Добавляем эти строки в программу. См. Рис. 3.

AutoLISP. Создание блока.

Рис. 3.      Создание и вставка блока.

Нажимаем кнопку «Загрузить активное окно редактора».

Затем на кнопку «Активизация AutoCAD».

Вводим в командной строке: mp_kub2.

На запрос «Укажите базовую точку :» щелкните мышкой в рабочем окне Автокад.

Программа создаст блок куба с размерами сторон 200. См. Рис. 4.

AutoLISP. Создание блока.

Рис. 4.   Блок куба.

Если повторит команду, Автокад нарисует куб, но поскольку блок «kub200» уже существует, программа выдаст ошибку. И предложит переопределить блок. См. Рис. 5.

AutoLISP. Создание блока.

Рис. 5.   Ошибка при создании второго блока.

Чтобы избежать этого, перед тем как создать блок необходимо проверить: может блок с таким именем уже существует в базе данных Автокад.

Для этого мы будем использовать функцию tblsearch

Функция tblsearch работает с таблицами неграфических данных Автокад.

Для того, чтобы проверить существует ли блок с определенным именем в таблице описания блоков, нужно добавить следующую строку:

(tblsearch "block" bl_name)

Если такой блок существует, функция вернет список этого блока. Если нет – функция вернет nil.

Давайте это проверим. Добавьте эту строку после строки, в которой задается имя блока. Откройте Консоль Visual LISP.

Выделите две строки и нажмите на кнопку «Загрузить выделенных фрагмент». См. Рис. 6.

AutoLISP. Создание блока.

Рис. 6. Поиск блока в таблицах неграфических данных Автокад.

В окне Консоль Visual LISP появится список с данными блока.

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

(if (not (tblsearch "block" bl_name))
    (progn
        Прорисовка блока
        Создание блока
    )
)

Функция if выполняет условную операцию. Если условие возвращает значение Т (True), то будет осуществлена прорисовка и создания блока. Если условие возвращает значение nil, то прорисовка и создания блока не произойдет.

В качестве условия у нас стоит выражение
(not (tblsearch "block" bl_name)).

Функция not выполняет операцию логического отрицания.

Если перед not стоит nil функция вернет Т (True)

Если, что-то другое, функция not вернет nil.

Таким образом, если блок существует, выражение
(tblsearch "block" bl_name) вернет его список. 
Функция not возвратит nil, и прорисовки и создания блока не произойдет.
Если блока нет, выражение
(tblsearch "block" bl_name) вернет nil.
Функция not возвратит  Т (True) и будет осуществлена прорисовка и создание блока.

Если в результате выполнения условия нужно выполнить не одно, а несколько выражений. Поэтому добавляют функцию progn.

Добавляем условие в программу. См. Рис. 7.

AutoLISP. Создание блока.

Рис. 7.   Проверка существования блока.

Теперь программа не будет выдавать ошибку, при вставки существующего блока.

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

Добавьте в начале программы запрос длины стороны куба:

(setq Dl (getreal "\nЗадайте длину стороны куба : "))

Функция getreal просит пользователя ввести вещественное чило.

Функция setq сохраняет это число в переменной Dl.

 Затем в строках определения координат нам необходимо заменить все числа 200 на переменную Dl.

Строку в которой мы задаем имя блока меняем на строку:

(setq bl_name (strcat "kub" (rtos Dl)))

Функция rtos преобразует вещественное число в строку.

Функция strcat сцепляет строчки.

Функция setq сохраняет имя блока в переменной bl_name.

В результате наша программа будет выглядеть так. См. Рис. 8.

AutoLISP. Создание блока.

Рис. 8.  Модификация программы.

Нажимаем кнопку «Загрузить активное окно редактора».

Затем на кнопку «Активизация AutoCAD».

Вводим в командной строке: mp_kub2 и нажмите <Enter>.

На запрос «Задайте длину стороны куба :» введите например 100 и нажмите <Enter>

На запрос «Укажите базовую точку :» щелкните мышкой в рабочем окне Автокад.

Программа создаст блок куба с размерами сторон 100.

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

С чем же это связано? Почему так происходит?

Все очень просто:

Если изначально Вы создали блок на слое «0», то при вставки или переносе на другой слой блок будет принимать характеристики слоя.

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

Чаще мне нужно было, чтобы блок изменялся. Поэтому мы рассмотрим этот случай.

Пользователь может находится на любом слои. И первое, что мы должны сделать – это запомнить этот слой:

(setq lay (getvar "CLAYER"))

Функция getvar считывает системную переменную CLAYER, в которой хранится имя текущего слоя.

 Функция setq сохраняем имя текущего слоя в переменной lay.

Далее при помощи функции setvar мы делаем текущим слой «0»:

(setvar "CLAYER" "0")

 И после того как блок создан, делаем текущим слой, на котором был пользователь:

(setvar "CLAYER" lay)

Добавляем эти строки в программу. См. Рис. 9.

AutoLISP. Создание блока.

Рис. 9.   Управление слоями.

Нажимаем кнопку «Загрузить активное окно редактора».

Затем на кнопку «Активизация AutoCAD».

Откройте «Диспетчер свойств слоев». См. Рис. 10.

AutoLISP. Создание блока.

Рис. 10. Создание нового слоя.

Создайте новый слой.

Поменяйте в нем цвет и вес линии.

Сделайте слой текущим.

Закройте «Диспетчер свойств слоев».

Вводим в командной строке: mp_kub2 и нажмите <Enter>.

На запрос «Задайте длину стороны куба :» введите например 300 и нажмите <Enter>.

На запрос «Укажите базовую точку :» щелкните мышкой в рабочем окне Автокад.

Программа создаст блок куба с размерами сторон 300. См. Рис.11.

AutoLISP. Создание блока.

Рис. 11.   Блок на новом слое.

Если вставите или перенесете этот блок на любой другой слой, он примет характеристики слоя.

Выделите блок и переедите на слой «0». Блок поменяет цвет и вес линий. См. Рис. 12.

AutoLISP. Создание блока.

Рис. 12.   Перенос блока на другой слой.

Если после создания блока Вы захотите отменить эту операцию. Вам придется несколько раз нажимать на кнопку Отменить (UNDO), отменяя поочередно все шаги создания блока.

Чтобы упростить отмену, добавим в программу начальную и конечную метки для группы команд, которые мы хотим отменить одним нажатием:

(command “._UNDO” “_be”)  - начало группы для отмены (Begin).
(command “._UNDO” “_end”)  - окончание группы для отмены.

См. Рис. 13.

AutoLISP. Создание блока.

Рис. 13.    Отмена группы команд.

Чтобы сократить количество переменных, мы можем вместо переменных, в которых храним имя примитива, создать набор имен.

Вначале создаем пустой набор set_name:

(setq set_name (ssadd))

Функция ssadd  без аргументов создает пустой набор.

Функция setq сохраняет этот набор в переменной set_name.

Затем после построения каждого примитива добавляем его имя в набор:

(ssadd (entlast) set_name)

Функция entlast считывает имя последнего нарисованного примитива.

Функция ssadd добавляет имя последнего примитива в набор set_name.

И теперь при создании блока вместо кучи переменных, хранящих имена примитивом мы ставим набор имен:

(command "_block" bl_name p1 set_name "")

Окончательный вариант программы выглядит так. См. Рис. 14.

AutoLISP. Создание блока.

Рис. 14.  Программа создания блоков mp_kub2

Код программы:

(DEFUN c:mp_kub2 (/ p1 p2 p3 p4 p5 p6 p7 p8 osm bl_name lay set_name) ; начало функции
     (command "._UNDO" "_be")                                           ; начало группы отмены 
     (setq Dl (getreal "\nЗадайте длину стороны куба : ")) ; запрос длины стороны 
     (setq p1 (getpoint "\nУкажите базовую точку : "))        ; запрос координат базовой точки

     (setq p2 (polar p1 0 Dl))           ; определение координат точки р2 
     (setq p3 (polar p2 (/ pi 2) Dl))   ; определение координат точки р3 
     (setq p4 (polar p3 pi Dl))           ; определение координат точки р4 
     (setq p5 (polar p1 (/ pi 4) Dl))   ; определение координат точки р5
     (setq p6 (polar p2 (/ pi 4) Dl))   ; определение координат точки р6
     (setq p7 (polar p3 (/ pi 4) Dl))   ; определение координат точки р7 
     (setq p8 (polar p4 (/ pi 4) Dl))   ; определение координат точки р8 

     (setq bl_name (strcat "kub" (rtos Dl)))  ; задаем имя блока
 
     (setq osm (getvar "osmode"))  ; запоминаем привязки пользователя
     (setvar "osmode" 0)                  ; отключаем привязки

     (if (not (tblsearch "block" bl_name)) 
          (progn 
              (setq lay (getvar "CLAYER"))  ; запоминаем текущий слой пользователя 
              (setvar "CLAYER" "0")             ; делаем текущим слой "0" 
              (setq set_name (ssadd))        ; создаем пустой набор 

              (command "_line" p1 p2 "")     ; рисуем линию 1-2 
              (ssadd (entlast) set_name)    ; добавляем в набор имя последнего примитива 
              (command "_line" p2 p3 "")    ; рисуем линию 2-3 
              (ssadd (entlast) set_name)    ; добавляем в набор имя последнего примитива 
              (command "_line" p3 p4 "")    ; рисуем линию 2-4 
              (ssadd (entlast) set_name)    ; добавляем в набор имя последнего примитива 
              (command "_line" p4 p1 "")    ; рисуем линию 4-1
              (ssadd (entlast) set_name)    ; добавляем в набор имя последнего примитива 
              (command "_line" p5 p6 "")    ; рисуем линию 5-6 
              (ssadd (entlast) set_name)    ; добавляем в набор имя последнего примитива
              (command "_line" p6 p7 "")    ; рисуем линию 6-7 
              (ssadd (entlast) set_name)   ; добавляем в набор имя последнего примитива 
              (command "_line" p7 p8 "")    ; рисуем линию 7-8
              (ssadd (entlast) set_name)   ; добавляем в набор имя последнего примитива
              (command "_line" p8 p5 "")    ; рисуем линию 8-5 
              (ssadd (entlast) set_name)   ; добавляем в набор имя последнего примитива 
              (command "_line" p1 p5 "")    ; рисуем линию 1-5 
              (ssadd (entlast) set_name)   ; добавляем в набор имя последнего примитива 
              (command "_line" p2 p6 "")    ; рисуем линию 2-6 
              (ssadd (entlast) set_name)    ; добавляем в набор имя последнего примитива 
              (command "_line" p3 p7 "")    ; рисуем линию 3-7 
              (ssadd (entlast) set_name)    ; добавляем в набор имя последнего примитива 
              (command "_line" p4 p8 "")    ; рисуем линию 4-8 
              (ssadd (entlast) set_name)    ; добавляем в набор имя последнего примитива

              (command "_block" bl_name p1 set_name "")   ; создаем блок 
              (setvar "CLAYER" lay)  ; делаем текущим слой пользователя
          ) ; end progn 
     ) ; end if 

    (command "_insert" bl_name p1 1 1 0) ; вставка блока
 
    (setvar "osmode" osm)            ; возвращает привязки пользователя 
    (command "._UNDO" "_end")  ; окончание группы отмены 
) ; end defun

 Скачать программу Mp_kub2.lsp Скачать программу Mp_kub2.lsp (Размер файла: 802 bytes)

После того, как программа отлажена нужно:

  • Если это ещё не сделано, то добавить все локальные переменные в список временных переменных функции defun.
  • Сохранить свою LISP-программу.
  • Закрыть редактор Visual LISP и AutoCAD, чтобы очистить все значения переменных.
  • Загрузить AutoCAD снова.
  • Также можно добавить нашу программу в список автоматической загрузки и создать для нее кнопку запуска. Как это сделать рассмотрено в уроке: Простой запуск LISP программ.

К сожалению многие тонкости создания блока остались за рамками этой статьи. Если у Вас появятся вопросы, пишите их  в комментариях или присылайте на почту acadprog@gmail.com.

Также пишите в комментариях:

Трудно ли было выполнить этот урок?

Была ли для Вас полезной информация, данная в этом уроке?

На какие вопросы программирования, Вы хотели бы, увидит ответы в следующих уроках?

Я с удовольствием отвечу на ваши вопросы.

В следующем уроке мы рассмотрим программу создания блока при помощи технологии ActiveX, расширения языка AutoLISP.

Если вы хотите получать новости с моего сайта. Оформляйте подписку.

До новых встреч.

 «Автор: Михаил Орлов»

Google

Также на эту тему Вы можете почитать:

2 комментарии на “Урок 11. AutoLISP. Создание блока.

  1. Антон 01.07.2015 11:16

    Как вставить существующий блок?

    • Михаил Орлов 07.07.2015 18:53

      (command «_insert» bl_name p1 1 1 0), где
      «_insert» – стандартная команда Автокад по вставке блока.
      bl_name – переменная, в которой хранится имя вставляемого блока. («Имя существующего блока»)
      р1 – переменная с координатами точки вставки блока.
      1 – масштабный коэффициент по оси X.
      1 – масштабный коэффициент по оси Y.
      0 – угол поворота блока в градусах.

      Вставка блока «Окно» в начало координат:
      (command «_insert» «Окно» (list 0 0 0) 1 1 0)

Оставить комментарий

Ваш mail не будет опубликован.

Вы можете использовать HTML теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>