Vlax ename vla object что это
Перейти к содержимому

Vlax ename vla object что это

  • автор:

проблема с vlax-ename->vla-object

Возникла проблема с функцией vlax-ename->vla-object. передаю в DEFUN имя примитива (3dface), где собираюсь через ActiveX взять координаты. Получаю ошибку, LISP не видит примитива, а значит vla-об-ект = nil.
Примитв есть, его имя есть, а vlax-ename->vla-object дает nil.
Проверяю
(if (and imya (= (type imya) ‘ENAME))
(princ «\n переменная imya верна»)
(princ «\n переменная imya ошибочно»)
) ;_ end of if
и все нормально! Более того все это делается в цикле и до определенного момента работает. И впечатление такое, что попадает какая то «кривая» 3Dface. Но какая бы она не была кривая Entyti-name то есть. Почему же vlax-ename->vla-object его не берет? Кто подскажет что нибудь.

Просмотров: 3706

LispBox

~ This blog was initially created for people, who love autolisp routines, as I love it.

Tag Archives: динамические блоки

Изменение динамического блока из LISP-программы.

11 Thursday Dec 2014

Tags

В последнее время в AutoCAD стали широко применяются динамические блоки.

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

В этом уроке мы рассмотрим пример изменении динамических свойств блока из LISP-программы.

В начале, проведем не большие приготовления:

1) Создадим, блок с дополнительными данными, при помощи программы mp_kub3. См. рис. 1

LISP. Динамический блок.

Эта программа рассмотрена в уроке: «LISP. Создание блока».

Откройте программу mp_kub3.lsp в редакторе Visual LISP.

Перейдите в Автокад.

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

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

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

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

Динамический блок.

2) Вставим динамический блок «Vyn«, при помощи программы Udim.lsp. См. Рис. 3.

Динамический блок.

Динамический блок мы создавали в уроке: «Создание динамического блока». Если у Вас нет динамического блока «Vyn», скачайте его и разместите в путях поддержки Автокад.

Откройте программу Udim.lsp в редакторе Visual LISP.

Перейдите в Автокад.

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

На запрос «Выберите блок :» — Укажите блок куба.

На следующий запрос «Выберите блок :» – нажмите .

Программа нарисует выноску. См. Рис. 4

Динамический блок.

Мы видим, что динамический блок размещен не совсем удачно. Хотелось удлинить как выносную линию, так и длину полки.

Давайте посмотрим, какие динамические свойства нам доступны для изменения.

Выделите динамический блок и нажмите Ctrl+1. Откроется палитра свойств. См. Рис. 5.

Динамический блок.

На вкладке «Настройка» мы видим, что для изменения нам доступны:

Положение1 X – положение точки 1 относительно точки bр по координате X;

Положение1 Y – положение точки 1 относительно точки bр по координате Y;

Расстояние1 – длина выносной линии;

Угол1 – угол наклона выносной линии к оси X.

Расстояние2 – длина полки.

Давайте начнем с параметра Расстояние1 и попробуем изменить длину выносной линии.

Сохраните программу Udim.lsp под другим именем (Udim2.lsp).

Измените имя функции defun (Udim2).

После вставки динамического блока, используя функцию (entlast), возвращаем имя вставленного объекта.

Потом переводим обычный примитив в VLA-объект:

И сохраняем его в переменной din_bl:

(setq din_bl (vlax-ename->vla-object (entlast)))

Кроме этого, давайте добавим переменную sv1, в которой мы будем хранить имя изменяемого свойства:

(setq sv1 «Расстояние1″)

Динамический блок.

При помощи функции vla-getdynamicblockproperties считываем динамические свойства у VLA-объект din_bl:

Давайте, чтобы следим за ходом наших действий, откроем Консоль Visual LISP.

Выделим строки, как на рис. 7, и загрузим выделенный фрагмент.

Динамический блок.

В окне Консоль Visual LISP мы видим, что наши динамические свойства вернулись в виде:

Чтобы, прочитать значение типа данных variant, используем функцию vlax-variant-value:

(vlax-variant-value (vla-getdynamicblockproperties din_bl))

Выделите эту строку и загрузите выделенный фрагмент. См. Рис. 8.

Динамический блок.

В окне Консоль Visual LISP мы видим, что наши динамические свойства вернулись в виде безопасного массива:

При помощи функции vlax-safearray->list преобразуем массив в список:

(vlax-safearray->list(vlax-variant-value (vla-getdynamicblockproperties din_bl)))

Выделите эту строку и загрузите выделенный фрагмент. См. Рис. 9.

Динамический блок.

Эта строка вернет нам список с нашими динамическими свойствами (Положение1 X, Положение1 Y, Расстояние1 и так далее), которые представлены в виде VLA-объектов:

Чтобы, в списке оставить только то динамическое свойство, которое нам нужно, применим функцию vl-remove-if-not, которая в общем виде выглядит так:

Функция vl-remove-if-not удаляет из списка все элементы, возвращающие nil при проверке тест-функцией.

— функция, применяемая для проверки поочередно к каждому элементу списка.

— список из которого нужно удалить объекты.

В качестве тест-функции мы будем использовать следующее выражение:

(lambda (x) (= (vla-get-propertyname x) sv1))

Функция lambda создает безымянные пользовательские функции, которые можно определить и тут же выполнить. В общем виде она выглядит так:

Функция vla-get-propertyname считывает имя свойства.

Выражение (= (vla-get-propertyname x) sv1) – сравнивает имя свойства, полученное из элемента списка, с именем, которое хранится в переменной sv1 («Расстояние1»). Если они = , то возвращает Т, в противном случаи nil.

Добавляем в программы следующие строки:

(vl-remove-if-not ‘(lambda (x) (= (vla-get-propertyname x) sv1))
) ; end vl-remove-if-not

Выделим строки, как на рис. 10, и загрузите выделенный фрагмент.

Динамический блок.

Функция vl-remove-if-not оставит в списки, только одно динамическое свойство.

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

(car (vl-remove-if-not '(lambda (x) (= (vla-get-propertyname x) sv1))
(vlax-safearray->list(vlax-variant-value (vla-getdynamicblockproperties din_bl)))
); end vl-remove-if-not
); end car

И сохраняем его в переменной din_sv:

(setq din_sv (car (vl-remove-if-not '(lambda (x) (= (vla-get-propertyname x) sv1))
(vlax-safearray->list(vlax-variant-value (vla-getdynamicblockproperties din_bl)))
); end vl-remove-if-not
); end car
); end setq

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

Выделите строки, как на рис. 11, и загрузите выделенный фрагмент.

Динамический блок.

Мы видим, что выделенный фрагмент возвращает нам, только одно динамическое свойство в виде VLA-объекта.

Давайте проверим то ли свойство мы получили. Для этого добавим следующую строку:

(vla-get-propertyname din_sv) – которая считывает имя свойства. См. Рис. 12.

Динамический блок.

Мы видим, что в переменной din_sv хранится динамическое свойство (VLA-объект), которое нам нужно. Последнюю строчку из программы можно удалить (мы использовали ее, только для проверки).

Нам остается, только изменить значение динамического свойства. Давайте поменяем значение свойства «Расстояние1» на 350.

В начале нужно привести это значение к типу variant. Для этого используем функцию vlax-make-variant, которая в общем виде выглядит так:

— значение присваиваемое варианту.

— тип данных значения (вещественное число, строка и так далее)

Нужно, чтобы новое значение было того же типа, что и старое.

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

(vlax-variant-type (vla-get-value din_sv))

vla-get-value – считает значение din_sv

vlax-variant-type – возвращает его тип.

Добавьте, эту строку в программу.

Выделите ее и загрузите выделенный фрагмент. См. Рис. 13.

Динамический блок.

Строка вернет нам код типа «5», что соответствует типу: Вещественное число с двойной точностью.

Преобразуем наше новое значение в тип variant:

(vlax-make-variant 350 (vlax-variant-type (vla-get-value din_sv)))

При помощи функции vla-put-value меняем старое значение на новое.

В общем виде функция vla-put-value выглядит так:

— свойство значение которого нужно изменить;

— новое значение. Должно иметь тип variant

Добавляем выражение, которое меняет значение:

(vla-put-value din_sv (vlax-make-variant 350 (vlax-variant-type (vla-get-value din_sv))))

Чтобы значение вступило в силу vla-объект динамического блока нужно обновить. Делаем это при помощи функции vla-update

Добавляем все выше сказанное. Выделите строки, как на рис. 14, и загрузите выделенный фрагмент.

Динамический блок.

Перейдите в Автокад. Выносная линия у динамического блока стала длинней. См. Рис. 15.

Динамический блок.

Чтобы остальные динамические свойства нам изменять стало проще, преобразуем часть кода в пользовательскую функцию Change_din_sv:

(defun Change_din_sv (din_bl sv new_value / din_sv)
(setq din_sv (car(vl-remove-if-not '(lambda (x) (= (vla-get-propertyname x) sv))
(vlax-safearray->list(vlax-variant-value (vla-getdynamicblockproperties din_bl)))
); end vl-remove-if-not
); end car
); end setq
(vla-put-value din_sv (vlax-make-variant new_value (vlax-variant-type (vla-get-value din_sv))))
(vla-update din_bl)
) ; end defun

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

(Change_din_sv din_bl sv new_value) , где:

din_bl – динамический блок, в котором нужно поменять значение динамического свойства;

sv – имя динамического свойства;

new_value – новое значение динамического свойства.

Добавляем в программу пользовательскую функцию Change_din_sv, и вызываем ее используя в качестве имени динамического свойства «sv1», а в качестве нового значения «350». См. Рис. 16.

Динамический блок.

Теперь, для того, чтобы поменять угол наклона выносной линии достаточно добавить две строчки:

(setq sv2 "Угол1") – создаем переменную sv2 с именем изменяемого свойства

(Change_din_sv din_bl sv2 (/ pi 2)) – меняем значения свойства на (/ pi 2).

(/ pi 2) – угол 90 градусов в радианах.

Добавляем эти строки. См. Рис. 17.

Динамический блок.

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

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

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

На запрос «Выберите блок :» — Укажите блок куба.

На следующий запрос «Выберите блок :» – нажмите .

Программа нарисует выноску. См. Рис. 18.

Динамический блок.

Мы видим, что значения динамических свойств (Расстояние1 и Угол1) изменились.

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

Попросим пользователя указать точку «1», при помощи функции getpoint:

(setq p1 (getpoint po "\nУкажите выносную линию: "))

Значения сохраним в переменной p1.

Расстояние между точками ро и р1 определим при помощи функции distance:

(setq ras (distance po p1))

Значения сохраним в переменной ras.

Угол наклона определим при помощи функции angle:

(setq ugl (angle po p1))

Значения сохраним в переменной ugl.

В функцию Change_din_sv меняющую свойства «Расстояние1» вместо 350 вставим ras.

В функцию Change_din_sv меняющую свойства «Угол1» вместо (/ pi 2) вставим ugl.

Добавим две сточки меняющие длину полки на значение 290.

(setq sv3 "Расстояние2")
(Change_din_sv din_bl sv3 290)

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

Динамический блок.

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

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

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

На запрос «Выберите блок :» — Укажите блок куба.

На запрос «Укажите выносную линию:» — Укажите вторую точку линии.

На запрос «Выберите блок :» — Снова укажите блок куба.

На запрос «Укажите выносную линию:» — Укажите вторую точку линии в другом месте.

На следующий запрос «Выберите блок :» – нажмите .

Программа нарисует две выноски к одному блоку. См. Рис. 20.

Динамический блок.

В заключение добавляем локальные переменные в список временных переменных функции defun.

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

Динамический блок.

(defun c:Udim2 (/ obj vla_obj V po bl_name osm p1 ras ugl din_bl sv1 sv2 sv3) (vl-load-com) ; загружаем функции расширения ;———————————————————————————————————- ;————— Функция изменения динамического свойства ——————— ;———————————————————————————————————- (defun Change_din_sv (din_bl sv new_value / din_sv) (setq din_sv (car (vl-remove-if-not ‘(lambda (x) (= (vla-get-propertyname x) sv)) (vlax-safearray->list(vlax-variant-value (vla-getdynamicblockproperties din_bl))) ); end vl-remove-if-not ); end car ); end setq (vla-put-value din_sv (vlax-make-variant new_value (vlax-variant-type (vla-get-value din_sv)))) (vla-update din_bl) ); end defun ;————————————————————————————————————— (while T (setq obj (car (entsel “\nВыберите блок: “))) (if (not (= obj nil)) (progn (setq vla_obj (vlax-ename->vla-object obj)) ; переводим в vla-object (setq V (vlax-ldata-get vla_obj “obem”)) ; объем (setq po (vlax-ldata-get vla_obj “tochka”)) ; координаты центра (setq p1 (getpoint po “\nУкажите выносную линию: “)) ; запрос точки 1 (setq ras (distance po p1)) ; определение расстояния (setq ugl (angle po p1)) ; угол наклона прямой (setq bl_name (cdr (assoc 2 (entget obj)))) ; имя блока (setq osm (getvar “osmode”)) ; запоминаем привязки пользователя (setvar “osmode” 0) ; отключаем привязки (command “_insert” “Vyn” po 1 1 0 bl_name V) ; вставка блока (setq din_bl (vlax-ename->vla-object (entlast))) (setq sv1 “Расстояние1”) (Change_din_sv din_bl sv1 ras) (setq sv2 “Угол1”) (Change_din_sv din_bl sv2 ugl) (setq sv3 “Расстояние2”) (Change_din_sv din_bl sv3 290) (setvar “osmode” osm) ; возвращает привязки пользователя );end progn ); end if ); end while ); end_defun

На этом наш урок окончен. В нем мы рассмотрели, как из LISP-программы можно управлять свойствами динамического блока.

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

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

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

Если, что-то не получилось. Пишите, постараюсь помочь.

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

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

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

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

Программное создание поля.

В AutoCAD 2005 появился очень интересный объект — поле. Что это такое и с чем его едят, описывать не буду, все это есть в справке. Но вот про создание поля как-то не очень все понятно. Попробую заполнить этот пробел (может, и сам чего еще пойму ;))

Известно, что поле может располагаться в однострочном или многострочном тексте, в атрибуте, а также в ячейке таблицы. Короче, в любом текстоподобном примитиве.
Создадим в пространстве модели всего 3 примитива: отрезок, обычный однострочный текст и однострочник, хранящий в себе поле — длину отрезка. Запустим теперь код, который будет просто печатать в консоли значение текстовой строки и FieldCode:

1
2
3
4
5
6
7
8
9
10

( defun test ( / ent )
( setq ent ( vlax — ename -> vla — object ( car ( entsel ) ) ) )
( princ ( strcat » \n TextString : »
( vla — get — textstring ent )
» \n FieldCode : »
( vla — fieldcode ent )
) ;_ end of strcat
) ;_ end of princ
( princ )
) ;_ end of defun

Простой текст Поле
_$ (test)

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

% %).’Свойство объекта‘ ‘Ключи форматирования‘>

И все хорошо, пока не встает вопрос об использовании готового и отлаженного lisp’а в AutoCAD другой разрядности. Например, сделали код в 32-разрядной системе, а в 64-разрядном AutoCAD он работать не будет. Все дело именно в ObjectID объекта.

Спасибо Александру Ривилису, он привел решение:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

;;———————————————————
;; Функция получает строковое представление ObjectID
;; вне зависимости от того AutoCAD x86 или x64
;; Источник: https://discussion.autodesk.com/forums/message.jspa?messageID=6172961
;;———————————————————
( defun get — objectid — x86 — x64 ( obj / util )
( setq util ( vla — get — utility ( vla — get — activedocument ( vlax-get-acad-object ) ) ) )
( if ( = ( type obj ) ‘ename )
( setq obj ( vlax — ename -> vla — object obj ) )
) ;_ end of if
( if ( = ( type obj ) ‘vla — object )
( if ( > ( vl-string-search «x64» ( getvar «platform» ) ) 0 )
( vlax-invoke-method util «GetObjectIdString» obj :vlax — false )
( rtos ( vla — get — objectid obj ) 2 0 )
) ;_ end of if
) ;_ end of if
) ;_ end of defun

Теперь для программного создания поля, отображающего, например, длину указанного отрезка, можно сделать такое:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

( defun c:insfld ( / adoc ent pt )
( vla — startundomark ( setq adoc ( vla — get — activedocument ( vlax-get-acad-object ) ) ) )
( if ( and ( = ( type
( setq
ent ( vl-catch-all-apply
( function
( lambda ( )
( vlax — ename -> vla — object
( car
( entsel » \n Укажите отрезок, полилинию или сплайн : » )
) ;_ end of car
) ;_ end of vlax-ename->vla-object
) ;_ end of lambda
) ;_ end of function
) ;_ end of vl-catch-all-apply
) ;_ end of setq
) ;_ end of type
‘vla — object
) ;_ end of =
( vlax-property-available-p ent ‘ length )
( = ( type ( setq pt ( vl-catch-all-apply
( function
( lambda ( )
( getpoint » \n Укажите точку для простановки поля : » )
) ;_ end of lambda
) ;_ end of function
) ;_ end of vl-catch-all-apply
) ;_ end of setq
) ;_ end of type
‘ list
) ;_ end of =
pt
) ;_ end of and
( vla — addtext
( vla — objectidtoobject
adoc
( vla — get — ownerid ent )
) ;_ end of vla-ObjectIDToObject
( strcat «% < \\ AcObjProp Object(%< \\ _ObjId "
( vl-princ-to-string ( get — objectid — x86 — x64 ent ) )
«>%).Length \\ f \\ » % lu6\\ «>%»
) ;_ end of strcat
( vlax-3d-point pt )
2.5
) ;_ end of vla-addtext
) ;_ end of if
( vla — endundomark adoc )
( princ )
) ;_ end of defun

Ошибка: no function definition: VLAX-GET-OR-CREATE-OBJECTct

а также vlax-get-property, vlax-invoke-method, vlax-get-object, vlax-dump-object и некоторые другие c префиксом vlax.
А некоторые функции, например vl-acad-defun, vl-remove, vlax-add-cmd ЛИСП узнаёт.
Что я делаю не так?
Очень непонятно, ведь в хелпе про них написано без всякого намёка на возможные проблемы.
Как мне догадывается, проблема связана с КОМ взаимодействием, потому что не работают именно эти функции.
Ещё у меня Автокад 05 русифицирован (довольно криво), но это не должно влиять вроде.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *