Урок 12. LISP. Создание блока.

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

Объектная модель AutoCAD основана на концепции COM (Component Object Model) . Это спецификация метода создания компонентов, из которых строятся приложения. Система AutoCAD поддерживает технологию ActiveX Automation, которая реализует принципы объектно-ориентированного программирования. В этой технологии модель работающего приложения представляется совокупностью объектов, свойств, методов и событий. Для каждого из этих элементов имеется свой алгоритм реализации в виде операций и данных, которые обеспечивают взаимодействие с пользователем.

Создание блока при помощи функций технологии ActiveX.

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

(vl-load-com)

При работе с интерфейсом ActiveX  для получения доступа к объекту, расположенному в пространстве модели чертежа, мы сначала должны пройти по иерархии модели объектов AutoCAD и прочитать указатели всех объектов более высокого уровня.

В начале нам нужно получить указатель на саму программу AutoCAD:

(setq acad_object (vlax-get-acad-object))

Указатель сохраняем в переменной acad_object.

Затем указатель на активный документ:

(setq active_document (vlax-get-activedocument acad_object))

Указатель сохраняем в переменной active_document.

И указатель пространства модели чертежа:

(setq model_space (vlax-get-modelspace active_document))

Указатель сохраняем в переменной model_space.

Функции  vlax-get-acad-object, vlax-get-activedocument, vlax-get-modelspace, а также все функции, которые начинаются vla-add, возвращают VLA-объекты.

Теперь при помощи функции vla-addline мы можем построить отрезок в пространстве модели:

(vla-addline model_space  (vlax-3d-point p1) (vlax-3d-point p2))
vla-addline – добавляет новый отрезок.
model_space – указывает куда будет добавлен отрезок (в пространство модели)
(vlax-3d-point p1) – координаты первой точки (тип данных  «Вариант»).
(vlax-3d-point p2) – координаты второй точки (тип данных  «Вариант»).

При создании VLA-объектов в качестве аргументов часто используются данные новых типов. Этот новый тип носит название «Вариант».

Функция vlax-3d-point создает вариант из трех вещественных  чисел.

p1 – список с координатами первой точки.

р2 – список с координатами второй точки.

Давайте изменим программу mp_kub, рассмотренную в уроке: Простой пример программы на LISP. См. Рис.1.

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

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

И построим все отрезки в ней при помощи технологии ActiveX.

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

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

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

Добавляем функцию (vl-load-com).

Добавляем указатели на объекты более высокого уровня.

Заменяем строчки, в которых происходит построение отрезков.

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

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

Рис. 2.   Строим отрезки при помощи технологии ActiveX.

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

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

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

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

Программа построит, такой же куб как и в уроке: Простой пример программы на LISP. См. Рис. 3.

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

Рис. 3.  Построение куба.

 Но он построен уже другим способом.

Теперь давайте попробуем создать блок.

Добавляем строку:

(setq bl_name “kub200”),

которая  сохраняет в переменной bl_name имя блока “kub200”.

Для создания блока добавляем следующую строку:

(setq blk_kub (vla-add (vla-get-blocks active_document) (vlax-3d-point p1) bl_name))

(vla-get-blocks active_document) – возвращает семейство блоков активного документа.

(vla-add (vla-get-blocks active_document)  (vlax-3d-point p1) bl_name) – добавляем новый элемент в семейство блоков с базовой точкой р1 и именем, которое хранится в переменной bl_name.

(setq blk_kub (vla-add (vla-get-blocks active_document) (vlax-3d-point p1) bl_name)) – сохраняем новый элемент (блок) в переменой blk_kub

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

После того как все элементы добавлены в блок, его нужно вставить:

Строка (vla-insertblock model_space (vlax-3d-point p1) bl_name 1. 1. 1. 0) 
– вставляет блок в пространство модели.
р1 – переменная с координатами точки вставки блока.
(vlax-3d-point p1) – приводим координаты к типу «Вариант»
bl_name – переменная, в которой хранится имя вставляемого блока.
1 – масштабный коэффициент по оси X.
1 – масштабный коэффициент по оси Y.
1 – масштабный коэффициент по оси Z.
0 – угол поворота блока в радианах.

Добавляем все выше сказанное в программу. См. Рис. 4.

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

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

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

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

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

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

Программа создаст блок куба. См. Рис. 5.

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

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

Если повторит команду, Автокад нарисует блок, который содержит сразу два куба. См. Рис. 6.

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

Рис. 6.   Блок содержащий два куба.

Это произошло потому, что блок с таким именем уже существует. И вновь нарисованные отрезки добавились к уже существующим в блоке.

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

Если блока нет – мы его создает и вставляем.

Если есть – только вставляем.

Так же как, и в предыдущем уроке: «AutoLISP. Создание блока» добавляем условие существования блока:

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

См. Рис. 7.

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

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

Перейдите в AutoCAD.

Нажмите несколько раз «Отменить», пока экран не очистится от уже вставленных блоков.

Вернитесь в редактор Visual LISP.

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

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

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

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

Затем повторите команду.

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

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

Рис. 8.  Два одинаковых блока.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Повторно запустите программу.

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

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

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

Блоки созданные программным способом Вы можете вставлять и традиционным.

Перейдите на вкладку: «Вставка».

Нажмите на кнопку «Вставить». Откроется окно «Вставка блока».

Чтобы увидеть имя доступных блоков, щелкните по стрелке раскрывающегося списка «Имя:».

Мы видим, что наши блоки есть в этом списки. См. Рис. 10

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

Рис. 10.   Список существующих блоков.

Очень важно, на каком слои блок изначально был создан.

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

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

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

Запоминаем текущий слой:

(setq lay (getvar "CLAYER"))

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

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

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

(setvar "CLAYER" "0")

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

(setvar "CLAYER" lay)

См. Рис. 11.

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

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

В расширении языка AutoLISP есть свои функции отката (Отмены).

Добавляем строки:

(vla-startundomark active_document) - начало группы для отмены.
(vla-endundomark active_document) - окончание группы для отмены.

 См. Рис. 12.

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

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

Таким образом, мы рассмотрели второй способ создания блока. Каким образом лучше создавать блок решать Вам. Я думаю, любой способ имеет свои плюсы и минусы.

Одним из плюсов этого варианта создания блока – это возможность легко добавлять дополнительные данные.

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

Предварительно, давайте запомним имя вставленного блока (VLA-объекта):

(setq vla_bl (vla-insertblock model_space (vlax-3d-point p1) bl_name 1. 1. 1. 0))

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

(setq V  (strcat (rtos (/ (* Dl Dl Dl) 1000000000)) “ м3”))
(/ (* Dl Dl Dl) 1000000000) – формула, считающая объем куба в метрах кубических.
(rtos (/ (* Dl Dl Dl) 1000000000)) – функция rtos делает значение строковым.
(strcat (rtos (/ (* Dl Dl Dl) 1000000000)) " м3") - функция strcat сцепляет объем
 (строковое значение) с единицей измерения " м3")

Результат, при помощи функции setq сохраняем в переменной V.

Теперь, чтобы добавить объем куба в качестве дополнительных данных, используем функцию vlax-ldata-put:

(vlax-ldata-put vla_bl "obem" V)
vla_bl - VLA-объект к которому добавляются данные.
"obem" – код, при помощи которого эти данные можно будет прочитать.
V – переменная, в которой сохранены данные.

Чтобы найти координаты точки центра верхней грани добавляем следующую строчку:

(setq po (inters p3 p8 p4 p7))

(inters p3 p8 p4 p7) – функция inters определяет точку пересечения отрезков, один из которых проходит через точки р3 и р8, а другой  через точки р4 и р7.

Результат, при помощи функции setq сохраняем в переменной ро.

Добавляем координаты точки ро в качестве дополнительной информации к блоку:

(vlax-ldata-put vla_bl "tochka" po)

Добавляем  выше описанные строки в программу.

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

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

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

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

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

Для того, чтобы извлечь данные используется функция vlax-ldata-get:

(vlax-ldata-get vla_bl "obem") – извлекает данные из VLA-объекта vla_bl по коду "obem"

Процесс извлечения данных мы рассмотрим в одном из следующих уроков.

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

(DEFUN c:mp_kub3 (/ p1 p2 p3 p4 p5 p6 p7 p8 osm bl_name lay blk_kub vla_bl V po); начало функции 
     (vl-load-com) ; загружаем функции расширения 
     (setq acad_object (vlax-get-acad-object))                              ; указатель на программу AutoCAD 
     (setq active_document (vla-get-activedocument acad_object)) ; указатель на активный документ
     (setq model_space (vla-get-modelspace active_document))    ; указатель на пространство модели 

     (vla-startundomark active_document) ; начало группы отмены
     (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 blk_kub (vla-add (vla-get-blocks active_document) (vlax-3d-point p1) bl_name))
               (vla-addline blk_kub (vlax-3d-point p1) (vlax-3d-point p2)) ; рисуем линию 1-2
               (vla-addline blk_kub (vlax-3d-point p2) (vlax-3d-point p3)) ; рисуем линию 2-3 
               (vla-addline blk_kub (vlax-3d-point p3) (vlax-3d-point p4)) ; рисуем линию 3-4
               (vla-addline blk_kub (vlax-3d-point p4) (vlax-3d-point p1)) ; рисуем линию 4-1 
               (vla-addline blk_kub (vlax-3d-point p5) (vlax-3d-point p6)) ; рисуем линию 5-6
               (vla-addline blk_kub (vlax-3d-point p6) (vlax-3d-point p7)) ; рисуем линию 6-7 
               (vla-addline blk_kub (vlax-3d-point p7) (vlax-3d-point p8)) ; рисуем линию 7-8
               (vla-addline blk_kub (vlax-3d-point p8) (vlax-3d-point p5)) ; рисуем линию 8-5 
               (vla-addline blk_kub (vlax-3d-point p1) (vlax-3d-point p5)) ; рисуем линию 1-5
               (vla-addline blk_kub (vlax-3d-point p2) (vlax-3d-point p6)) ; рисуем линию 1-6 
               (vla-addline blk_kub (vlax-3d-point p3) (vlax-3d-point p7)) ; рисуем линию 1-7 
               (vla-addline blk_kub (vlax-3d-point p4) (vlax-3d-point p8)) ; рисуем линию 1-8             
               (setvar "CLAYER" lay);делаем текущим слой пользователя 
          ) ; end progn 
     ) ; end if 
     (setq vla_bl (vla-insertblock model_space (vlax-3d-point p1) bl_name 1. 1. 1. 0)) ; вставка блока
     (setq V (strcat (rtos (/ (* Dl Dl Dl) 1000000000)) " м3")) ; расчет объема
     (vlax-ldata-put vla_bl "obem" V)
     (setq po (inters p3 p8 p4 p7))    ; определение координат центра верхней грани
     (vlax-ldata-put vla_bl "tochka" po)
     (setvar "osmode" osm) ; возвращает привязки пользователя
     (vla-endundomark active_document) ; окончание группы отмены
 ) ; окончание функции mp_kub3

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

На этом наш урок окончен.

Пишите в комментариях:

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

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

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

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

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

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

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

Google

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

6 комментарии на “Урок 12. LISP. Создание блока.

  1. вова 19.08.2014 15:09

    всё здорово формат 800х1100

  2. power85 09.09.2014 15:46

    Спасибо. Очень интересно.

  3. Noname 18.04.2016 11:55

    здравствуйте, нарисовав линию в блоке, например P1 и P2, как сохранить линию в переменную? Функция entlast как понимаю не работает в блоке. И как применить команду _trim в блоке?

  4. Raccoon 13.09.2020 23:37

    Здравствуйте! А можно ли расчленить вхождение блока с помощью lisp`а?

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

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

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