Vlax ename vla object что это
Здесь вы можете скачать документацию и программы для САПР AutoCAD, PCAD, 3DS, Inventor, Pro/E, Solidworks и других CAD CAM CAE EDA GIS
Четрые правила для работы с ActiveX в Visual Lisp
Размышления о объектах, свойствах и методах не свойственно для традиционного программиста AutoLISP. Недостаток доступной в изложении документации по по vla- функциям заставляет многих избегать интерфейса ActiveX. Так где же документация? Прежде чем я сообщу вам об этом давайте сначала рассмотрим некоторые базовые понятия.
Объекты, свойства и методы
Объект, это “ что-то воображаемое или физическое к которому направлено действие” В AutoCAD, объект может быть видимым, как линии, дуги и текст. Он так же может быть не видимым, как слой или стиль текста. Другой, связаный термин, коллекция, просто ссылка к совокупности схожих объектов, к примеру коллекция слоев.
Очевидно, что объекты имеют свойства. К примеру, вы интуитивно знаете, что линия имеет начальную и конечную точку. Она так же имеет другие свойства в AutoCAD, к примеру, слой. Некоторые свойства доступны для изменения (TrueColor) а другие доступны только для чтения (управляемые объектом).
Объекты так же имеют методы. Методы это действия, которые поддерживают объекты. К примеру, линия поддерживает методы перемещения, копирования и вращения. Различные объекты поддерживат различные методы.
Теперь вы понимаете базовые термины, которые используются в интерфейсе ActiveX. Пришло время показать документацию на функции vla- и мои 4 простых правила.
4 Простых правила
Докупентация по функциям vla- всегда расположена в руководстве по ActiveX и VBA. Проблема в том, что она была написана для программистов на VBA, а не для программистов Visual LISP. Однако, Autodesk знает что “перевод” VBA-документации в Visual LISP был бы настолько прост, что нет реальной необходимости ее дублировать.
рис. 1
Потратьте одну минуту, чтобы посмотреть на карту объектной модели в руководстве (рис. 1). Эта карта — лучьший способ начать ознакомление с документацией. Вы можете кликнуть на любой из объектов или коллекций, чтобы напрямую перейти в описание этого объекта или коллекции. Это так же даст вам понимание иерархии объектов в интерфейсе ActiveX. Обратите внимание, что объект Application — начало для большинства объектных моделей.
рис. 2
Когда вы видите карту объектной модели на экране, выберите объект Line. Отобразится список всех методов и свойств (так же событий, мы еще не говорили о них), доступных для этого объекта (рис. 2). Это говорит вам о том, что объекты могут содержать линию. Мы не видим ничего о Visual LISP здесь. Однако, перевод “VBA-языка” в функции vla- требует только эти четыре правила:
1. Вы должны всегда описывать объект как первый аргумент.
Помните, свойства и методы не могут существовать без объектов. Каждая vla-функция будет требовать объект. Поэтому, первый параметр каждой функции vla- будет объектом непосредственно.
2. Ваш запрос значения значения свойства должен осуществляться добавлением имени свойства к vla-Get-
Все свойства запрашиваеются в Visual LISP потем добавления имени свойства к vla-Get-, к примеру, vla-Get-Layer. Поскольку вы только запрашиваете свойство, здесь только один аргумент — объект.
3. Модификация значение свойства осуществляется добавлением имени свойства к vla-Put-
Все свойства, которые доступны не только для чтения, модифицируются в Visual LISP добавлением имени свойства к vla-Put-, к примеру, v l a — P u t — L a y e r . Так как вы модифицируете свойство, вам необходимо два аргумента: объект, и данные для изменения свойства. Тип данных, необходимый для изменения свойства описан в разделе Signature.
4. Выполнение метода осуществляется добавлением имени метода к vla-
Все методы доступны в Visual LISP путем добавления имени метода к vla-, к примеру, vla-Delete. Количество аргументов будет зависеть от конкретного метода и будет включать объект как первый аргумент, наряду с описанными в документации параметрами. Типы данных, необходимый для аргументов методов описаны в разделе Signature.
Запрос свойства
Как вы увидели, задача «перевода» руководства ActiveX тривиальна. Теперь рассмотрим несколько примеров.
Начертим единичную линию в AutoCAD. Мы будем использовать эту линию для примера кода, размещенного ниже. Сохраним объект line в переменной AutoLISP. (vl-Load-Com загружает интерфейс ActiveX и vlax-EName- >vla-Object переводит имя примитива в объект.)
Command: (vl-Load-Com) Command: (setq myLine (vlax-EName->vla-Object (entlast))) #
Посмотрим что руководство по ActiveX и VBA говорит нам о том, что мы можем сделать с нашим объектом. Выберем объект Line в карте объектной модели. Это вызовет переход к документации по объекту line. Предположим, что мы хотим узнать, на каком слое находится линия, используя при этом средства ActiveX. Выберем свойство Layer в документации. Теперь применим наши четыре правила.
Мы работаем с методом или со свойством? Это свойство, используем правило 2. Значить нам нужно добавить имя свойства Layer к vla-Get-, т.е., используем функцию vla-Get-Layer. Так как мы только запрашиваем свойство Layer мы можем пропустить правила 3 (модификация свойства) и 4 (префикс метода). Правило 1 гофорит нам, что первым аргументом является непосредственно сам объект. Таким образом выражение AutoLISP, которое будет возвращать имя слоя, на котором расположена линия будет:
Command: (vla-Get-Layer myLine) "0"
Какой тип данных мы ожидаем, когда запрашиваем свойство? Обратите внимание, что документация в разделе Signature указывает что свойство layer имеет тип string. Различные своства будут иметь различные типы данных. К примеру, свойство StartPoint имеет тип variant, и будет содержать массив чисел. В Visual LISP массив называется SafeArray.
Command: (vla-Get-StartPoint myLine) #
Однако, тип variant, который содержит SafeArray необходимо обследовать глубже, чтобы получить актулаьные для нас числа. Две функции используются для того чтобы получить данные, сохраненные в типе variant и SafeArray, это: vlax-Variant-Value и vlax-SafeArray->List. Большинство программистов на Visual LISP предпочитают объединять эти две функции в одну и использовать простую функцию, типа показаной ниже.
(defun i:Array->List (variant) (vl-Load-Com) (vlax-SafeArray->List (vlax-Variant- Value variant)))
Теперь мы можем использовать эту функцию чт обы получить список чисел, которые нам нужны:
Command: (i:Array->List (vla-Get- StartPoint myLine)) (15.4375 16.1814 0.0)
Модификация свойства
В этом примере мы будем изменить свойство, в данном случае слой, на котором расположена линия. Теперь мы применим правила 1 и 3. Правило 3 говорит, что нам нужно добавить перфикс — имя свойства (Layer в нашем случае) к vla-Put-, таким образом вызываем функцию vla-Put-Layer. У нее будут два аргумента. Не забудьте правило 1! Первый агрумент всегда является сам объект. Так как мы изменяем свойство, имеет смысл что бы второй параметр был бы значением непосредственно. В документации написано, что его тип string, т.о. мы должны предоставить строку. Перед тем как мы введем код, показанный ниже, создайте слой с именем “Test” который бы визуально отстоял от текущего слоя, на котором расположена линия.
Command: (vla-Put-Layer myLine "Test") nil
Обратите внимание на то, что после успешного выполнения данное выражение возвращает nil. Если выражение завершается с ошибкой (к примеру, слой не существует) возвращается сообщение “Automation Error”. Строки и простые числа, такие как типы integer и double (выражаясь в терминах AutoLISP) легко обеспечить. Но некоторые свойства требуют тип variant, в обльшинстве случае это точки для объектов, к примеру линий и полилиний. В этом случае, многие программисты на Visual LISP пишут функцию подобную показанной ниже для быстрой конвертации списка вещественных чисел в SafeArray.
(defun i:Points (ptList) (vl-Load-Com) (vlax-SafeArray-Fill (vlax-Make-SafeArray vlax-vbDouble (cons 0 (1- (length ptList)))) ptList))
Мы используем эту функцию чтобы изменить свойств линии StartPoint на 0,0,0.
Command: (vla-Put-StartPoint myLine (i:Points '(0.0 0.0 0.0))) nil
Выполнение метода объекта
И наконец, используем метод для того чтобы переместить линию. Перейдем к методу Move в руководстве по ActiveX и VBA. Обратите внимание, что этот метод содержит два аргумента, Point1 и Point2. Не забывайте правило 1. Объект — всегда первый аргумент. Т.о. в Visual LISP мы будем иметь три аргумента: объект, первую точку и вторую точку. Правило 4 говорит что имя метода будет идти за префиксом vla-, т.о., мы будем использовать функцию vla-Move.
Используем то, что мы изучили, чтобы переместить линию.
Command: (vla-Move myLine (i:Points '(0.0 0.0 0.0)) (i:Points '(12.0 0.0 0.0))) nil
Если выражение отработало верно, возвращается nil.
Помычим 🙂
Вы нашли полезный для себя код на Лиспе и хотите его использовать. Можно выделить 3 шага:
сохранение программного кода на своем компьютере
загрузка файла
запуск приложения
Примечание: AutoLISP программы могут быть запущены только на полной версии Автокада, они не работают под AutoCAD LT. (исключая случаи загрузки дополнительных приложений типа LT Extender и ему подобных, которые специально разработаны для запуска lisp и (или) arx приложений в среде AutoCAD LT.)
Сохранение программного кода на своем компьютере
С помощью курсора выделяем этот код и копируем его в буфер обмена, нажав правую кнопку мыши и выбрав пункт Копировать (илиCtrl+C).
Запускаем «Блокнот» и вставляем наш код с помощью меню Правка >> Вставить (или Ctrl+V):
(defun C:OFF2 (/ d obj ent adoc *error* undo lays Flag) (defun *error* (msg)(vla-EndUndoMark adoc)) (vl-load-com)(setq adoc (vla-get-activedocument (vlax-get-acad-object)) lays (vla-get-layers adoc))(vla-StartUndoMark adoc)(setvar "CMDECHO" 0) (if (null *OFF2*)(setq *OFF2* (abs (getvar "OFFSETDIST")))) (if (zerop *OFF2*)(setq *OFF2* 1))(setq d (getvar "UNDOCTL")) (cond ((= d 0) (vl-cmdf "_.UNDO" "_All")) ((= d 3) (vl-cmdf "_.UNDO" "_Control" "_All")) (t nil)) ;_ end of cond (princ "\n Величина смещения <")(princ *OFF2*)(princ ">: ") (initget 6)(if (null (setq d (getdist))) (setq d *OFF2*)) (setq *OFF2* d undo 0 Flag t) (initget "Undo Отмени Г J Exit Выход У D _Undo Undo Undo Undo Exit Exit Exit Exit") (while Flag (setq obj (entsel (strcat "\n Выберите объект [" (if (not (zerop undo)) "Отмени/" "") "Выход] : "))) (cond ((= obj "Undo")(if (not (zerop undo))(progn (vl-cmdf "_UNDO" "_B")(setq undo (1- undo)))(alert "Нечего больше отменять"))) ((= obj "Exit")(setq Flag nil)) ((null obj)(if (= (getvar "ERRNO") 52)(setq Flag nil)(princ " *** Мимо ***"))) (t (setq ent (vlax-ename->vla-object (car obj))) (cond ((= (vla-get-lock (vla-item lays (vla-get-layer ent))) :vlax-true) (alert "На блокированном слое!")) ((vlax-method-applicable-p ent 'Offset)(vl-cmdf "_UNDO" "_M")(setq undo (1+ undo)) (vla-offset ent d)(vla-offset ent (- 0 d))) (t (alert "Не удается создать объект, подобный данному"))))) (initget "Undo Отмени Г J Exit Выход У D _Undo Undo Undo Undo Exit Exit Exit Exit")) (vla-EndUndoMark adoc)(princ)) (princ "\nНаберите в командной строке OFF2"))
После того как вставили код в блокнот, мы должны иметь что-то наподобие этого:
Теперь мы должны сохранить файл. Файл можно назвать, как вам нравится, но расширение у него должно быть .LSP. Правильнее (но не обязательно) будет назвать файл так же, как названа команда в найденном Вами коде. Команде всегда предшествует префикс C: после слова defun. В примере выше видно, что команду назвали OFF2, соответственно файл называем off2.lsp. Таким образом, мы можем избежать беспорядка, т.к. будем знать, что в файле off2.lsp находится команда OFF2.
Иногда в коде представлено несколько функций. Необходимо найти «главную». Такая функция либо имеет префикс С:, либо сам автор кода уточняет, что «использовать как «. В случае нескольких «главных» именование файла не может иметь никаких рекомендаций.
Загрузка lisp файла
Далее, запускаем Автокад и выбираем Сервис >> Автолисп >> Загрузить (Tools >> AutoLISP >> Load) или набираем в командной строке _appload.
Мы должны увидеть диалоговое окно как представлено ниже:
Используйте следующую последовательность, чтобы загрузить off2.lsp:
Перейдите к папке, куда Вы сохранили lisp файл.
Выберите файл, который Вы хотите загрузить из списка.
Нажмите кнопку Загрузить.
(Если все прошло удачно, Вы должны увидеть надпись «off2.lsp успешно загружено»)
Нажмите кнопку Закрыть для завершения команды.
Команда или функция ?
Для начала необходимо определиться, что у нас: команда или функция?
Немного теории.
В описании практически любого кода есть такая строка, как
и потом после нее чего-то там написано. Так вот то, что там написано и есть имя функции.
Если первыми символами являются C:, то функция готова к вызову из командной строки. Если такого нет, то вызывать функцию надо, заключая ее имя в круглые скобки.
Например, есть функция
Ее вызывать (при условии, что она подгружена) с командной строки можно напрямую:
И будут выполнены действия
А вот такую:
Можно будет вызывать только так:
И будут выполнены действия .
С точки зрения AutoCAD’a это 2 разных модуля.
Запуск lisp программы
Как только lisp файл загружен, Вы можете вызвать команду из командной строки. Команда вызывается по ее имени. В нашем примере необходимо набрать в командной строке OFF2.
Запомните, имя команды содержит префикс C: после слова defun. Если Вы видите в коде:
то в командной строке необходимо набрать без префикса C:.
Tips: Вы можете также загрузить lisp файл путем перетаскивания (drag-and-drop) иконки файла в графическое окно открытого документа Автокада.
AutoCAD ; error: no function definition:
Если Ваша функция или команда не работает или завершает работу с сообщением как в примере ниже, то Вам может помочь простой способ.
Команда: (vlax-get-acad-object)
; error: no function definition: VLAX-GET-ACAD-OBJECT
Наберите в командной строке (vl-load-com) или (предпочтительнее) добавьте ее в начало lisp файла.
Теперь ваш lisp должен работать без ошибок.
Что такое это (vl-load-com) ?
Данная функция загружает большое количество функций, входящих в расширение AutoLisp, позволяющее работать с объектами, свойствами, методами и событиями ActiveX. Признаком необходимости загрузки расширения AutoLisp является наличие в тексте Вашей программы функций, начинающихся с префиксов vla- (например vla-get-activedocument), vlax- (например vlax-get-acad-object), vl-(например vl-catch-all-apply) и vlr- (например vlr-pers).
В любом случае никогда не помешает добавить (vl-load-com) в начало файла, чтобы избежать подобных ошибок.
Организация библиотеки лисп файлов.
Что делать, если набралось достаточное количество файлов? Каждый раз набирать _appload для загрузки того или иного приложения? Наиболее эффективным будет организация своей библиотеки. Для начала условимся, что все наши файлы будем складывать в одну папку. Например, D:\MyLisp. Пропишем эту папку в путях доступа Автокада. Для этого выбираем Сервис >> Настройка (Tools >> Options) или набираем в командной строке _options. Переходим на закладку Файлы (Files) и раскрываем список Путь доступа к вспомогательным файлам (Support File Search Path).
Мы должны увидеть диалоговое окно, как представлено ниже:
Используйте следующую последовательность, чтобы прописать папку в путях доступа:
Нажмите кнопку Добавить.
Нажмите кнопку Обзор и выберите целевую папку (в нашем случае , D:\MyLisp)
Путь к папке должен появиться в диалоговом окне.
Нажмите кнопку OK для завершения команды.
Теперь наша папка прописана в путях доступа Автокада. Что это нам дает? Мы можем загружать наши файлы не указывая конкретного пути, а только имя файла.
Мы можем набрать в командной строке (load «») для загрузки необходимого кода, например (load «off2»). Заметьте, что добавлять расширение .lsp не обязятельно, хотя и не запрещается.
И, наконец, самое главное — это позволит нам создать панели с кнопками для загрузки той или иной программы. Кнопка будет иметь следующее содержание:
^C^C(if (null C:OFF2)(load «off2»));OFF2;
Вместо текста мы должны будем подставлять имя нужной нам команды, а вместо текста имя того файла, в котором эта команда сохранена. Напоминаю, что файл должен иметь расширение .lsp. Более подробно по организации меню можно почитать еще здесьhttp://www.kulichki.com/cadhlp/pdmnu.htm
Если есть необходимость загружать свои lsp файлы при открытии чертежа, то нужно добавить необходимые файлы в список автозаргузки.
Запускаем Автокад и выбираем Сервис >> Автолисп >> Загрузить (Tools >> AutoLISP >> Load) или набираем в командной строке_appload.
В открывшемся диалоговом окне жмем на кнопку Приложения рядом с изображение портфеля
В следующем диалоговом окне жмем на кнопку Добавить и указываем на необходимые файлы.
Они должны появиться в списке приложений.
Теперь перечисленные файлы будут загружаться каждый раз при открытии рисунка.
Важно понимать, что (по крайней мере в полной версии AutoCAD) загрузка приложений, помещенных в Автозагрузку (Startup Suite), как правило, выполняется во все профили и сессии AutoCAD’a.
Кроме того, есть еще один момент. Если существует 2 или более файлов, в которых описаны функции с одинаковыми именами, выполняться будет та, которая загрузилась последней. Поскольку предсказать, в какой последовательности будет выполняться загрузка приложений, невозможно, подобных ситуаций следует избегать.
Автор статьи: Владимир Азарко aka VVA
Комментарии
Порядок: от новых к старым
Комментарии 1-10 из 10
vig2006, 07 февраля 2016 в 08:06
#10
Спасибо, отличная статья
цитировать
Sizova_AA, 23 мая 2015 в 12:11
#9
Спасибо))))
цитировать
VVA, 23 мая 2015 в 11:19
#8
Цитата:
Сообщение #7 от Sizova_AA
Добрый вечер, у меня выдает ошибку — лишняя закрывающая скобка на входе, что это значит подскажите пожалуйста как исправить ошибку.
нарушен баланс скобок. Если знаешь lisp — секундное дело. Я бы посоветовал создать тему в разделе программирования и выложить файл. Думаю помогут очень быстро.
цитировать
Sizova_AA, 22 мая 2015 в 16:30
#7
Добрый вечер, у меня выдает ошибку — лишняя закрывающая скобка на входе, что это значит подскажите пожалуйста как исправить ошибку.
цитировать
meyrin, 11 мая 2014 в 11:21
#6
Спасибо
цитировать
Asaneck, 29 апреля 2014 в 09:05
#5
Спасибо, будем знать.
цитировать
DMZ, 17 октября 2013 в 17:38
#4
Спасибо!
цитировать
Магнолик, 24 декабря 2012 в 18:07
#3
А видео есть?))))
цитировать
st2008, 12 декабря 2012 в 13:51
#2
Спасибо за публикацию!
цитировать
Hennic, 04 ноября 2012 в 00:23
#1
Прописывать папку с lsp файлами в путях доступа Автокада не обязательно, вернее вовсе не нужно. Всё работает и без этого.
цитирова
Ошибка no function definition: VLAX-ENAME->VLA-OBJECT
Здравствуйте.
При загрузке всех лиспов срабатывает данная ошибка.
Работаю в автокад 2018 + спдс графикс 12
Добавлял в начало (vl-load-com) — не помогло;
Переустанавливал автокад с чисткой реестра-не помогло.
Что делать?
Просмотров: 1402
LISP, C# (ACAD 200[9,12,13,14])
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 39,745
__________________
Моя библиотека lisp-функций
—
Обращение ко мне — на «ты».
Все, что сказано — личное мнение.
Кулик Алексей aka kpblc |
Посмотреть профиль |
Посетить домашнюю страницу Кулик Алексей aka kpblc |
Найти ещё сообщения от Кулик Алексей aka kpblc |
Особенности vla-функций и их применения, часть 2
В предыдущей части уже были рассмотрены некоторые особенности работы vla-функций применительно к графической составляющей dwg-файла. Но были рассмотрены далеко не все вопросы. В частности, не было освещено «создание примитива через ActiveX без явного указания необязательных настроек». И никак не был затронут вопрос о модификации созданного примитива (точнее, удобства и очевидности изменения).
Начнем, пожалуй, с «настроек по умолчанию». Если в DXF Reference напрямую указываются необязательные параметры (то есть принимаемые текущими), то при работе через ActiveX ситуация иная: указываются только необходимые для создания примитива параметры. Все остальное необходимо задавать отдельными вызовами соответствующих функций. К таким параметрам можно отнести, например, цвет примитива (принимается текущий); тип линии примитива; слой примитива и т.п.
Создадим и активируем пользовательскую систему координат, ось Z которой непараллельна мировой и запустим следующие коды:
( entmakex ‘ ( ( 0 . «CIRCLE» )
( 10 100 . 10 . 20 . )
( 40 . 10 . )
)
) ;_ end of entmakex
( vla — addcircle
( vla — get — modelspace
( vla — get — activedocument ( vlax-get-acad-object ) )
) ;_ end of vla-get-modelspace
( vlax-3d-point ‘ ( 100 . 10 . 20 . ) )
10 .
) ;_ end of vla-addcircle
Обратите внимание, что в первом случае окружность создается в мировой системе координат, а вторая — в текущей. При этом координаты центра у них не совпадают. Поигравшись с trans, можно добиться полного соответствия результатов vla- и ent-функций. Но пока разговор немного не об этом.
Разберемся с модификацией примитивов.
Как правило, текущие настройки мало кого устраивают, и создаваемые примитивы (это касается не только графических элементов) приходится менять. Иногда при создании, иногда — уже готовые, но пришедшие из других файлов.
Сначала разберем вариант внесения изменений в ename-представление примитива:
_$ ( setq ent ( entlast ) )
< Entity name: - 401519e8 >
Преобразуем его в список:
_$ ( entget ent )
( ( 0 . «CIRCLE» ) ( 100 . «AcDbEntity» ) ( 8 . «0» ) ( 100 . «AcDbCircle» ) ( 10 100.0 20.0 — 10.0 ) ( 40 . 10.0 ) ( 210 0.0 — 1.0 0.0 ) )
Ненужные и некритичные элементы списка удалены.
Последовательность изменения такова: сначала надо изменить список; потом — модифицировать примитив; потом — обновить его графическое представление. Для этого обычно используются соответственно subst, entmod, entupd. Допустим, мы хотим изменить значение 210 группы на ‘(-1.0 0.0 0.0). Сначала проверим работу subst:
_$ ( subst ‘ ( 210 — 1.0 0.0 0.0 )
( assoc 210 ( entget ent ) )
( entget ent )
) ;_ end of subst
( ( 0 . «CIRCLE» ) ( 100 . «AcDbEntity» ) ( 8 . «0» ) ( 100 . «AcDbCircle» ) ( 10 100.0 20.0 — 10.0 ) ( 40 . 10.0 ) ( 210 — 1.0 0.0 0.0 ) )
Получилось? Получилось (еще бы!). Теперь обновляем примитив:
_$ ( entmod ( subst ‘ ( 210 — 1 . 0 . 0 . )
( assoc 210 ( entget ent ) )
( entget ent )
) ;_ end of subst
) ;_ end of entmod
; <. >
_$ ( entupd ent )
Активируем AutoCAD и наблюдаем за изменениями примитива. Казалось бы, достаточно просто. Но не без некоторых подводных камней.
Например, в примитиве могут повторяться ключи точечных пар (пример можно посмотреть чуть выше — в частности, это группы 100), и использованный assoc вернет «не то». Можете попробовать, используя представленный механизм, заменить координаты второй (или n-дцатой) вершины обычной полилинии. Кроме того, некоторые точечные пары могут вообще отсутствовать при создании примитива (например, пара 370 — вес линии; или группа 3 в многосточном тексте), и в таком случае приходится ее принудительно добавлять. Внесение же изменений, например, в трехмерную полилинию для неподготовленного человека сродни шаманству.
Теперь возьмемся за изменение vla-представления.
Отменим только что сделанные изменения и вернемся в VLIDE:
_$ ( setq ent ( vlax — ename -> vla — object ( entlast ) ) )
# < VLA - OBJECT IAcadCircle 01f43c0c >
Результат немногим более информативен, чем показанный ранее (entget (entlast)). Посмотрим свойства и методы vla-примитива:
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
_$ ( vlax-dump-object ent t )
; IAcadCircle: AutoCAD Circle Interface
; Property values:
; Application (RO) = #
; Area = 314.159
; Center = (100.0 10.0 20.0)
; Circumference = 62.8319
; Diameter = 20.0
; Document (RO) = #
; Handle (RO) = «1FB»
; HasExtensionDictionary (RO) = 0
; Hyperlinks (RO) = #
; Layer = «0»
; Linetype = «ByLayer»
; LinetypeScale = 1.0
; Lineweight = -1
; Material = «ByLayer»
; Normal = (0.0 -1.0 0.0)
; ObjectID (RO) = -1075124712
; ObjectName (RO) = «AcDbCircle»
; OwnerID (RO) = -1075131144
; PlotStyleName = «ByLayer»
; Radius = 10.0
; Thickness = 0.0
; TrueColor = #
; Visible = -1
; Methods supported:
; ArrayPolar (3)
; ArrayRectangular (6)
; Copy ()
; Delete ()
; GetBoundingBox (2)
; GetExtensionDictionary ()
; GetXData (3)
; Highlight (1)
; IntersectWith (2)
; Mirror (2)
; Mirror3D (3)
; Move (2)
; Offset (1)
; Rotate (2)
; Rotate3D (3)
; ScaleEntity (2)
; SetXData (2)
; TransformBy (1)
; Update ()
T
_$
Здесь сначала показываются доступные свойства примитива; следом идут его методы. Мы пока будем работать именно со свойствами, а методы оставим «на потом, если руки дойдут. И если кому-то понадобится».
Внесение изменений в vla-представления отличается от изменений ename-представлений. И отличия тут достаточно серьезные.
Прежде чем мы продолжим, следует напомнить, что при работе через ActiveX есть непреложное правило: первым аргументом функции обязательно идет указатель на объект, с которым выполняется работа. Без этого дальнейшее движение невозможно. Дополнительные данные по работе с ActiveX внутри VisualLISP можно посмотреть здесь.
Итак, отличия.
Во-первых, существует два варианта задания / чтения свойств: сокращенная и полная. У каждой есть свой плюс и свой минус. Сокращенная короче; полная — устойчивее.
Во-вторых, обновление большинства примитивов (спасибо Евгению Елпанову) при работе через ActiveX происходит после выхода из функции, в которой выполнялось изменение свойства примитива. То есть если написать код вида:
1
2
3
4
5
6
7
8
9
10
11
12
13
( defun test ( / ent )
( setq ent ( vlax — ename -> vla — object ( car ( entsel ) ) ) )
( test1 )
( test2 )
) ;_ end of defun
( defun test1 ( )
( vla — put — color ent 1 )
) ;_ end of defun
( defun test2 ( )
( vla — put — lineweight ent aclnwt211 )
) ;_ end of defun
то обновление примитива будет выполнено 3 раза: первый раз при выходе из test1, второй — при выходе из test2, третий — при выходе из test. При работе, например, с большими и насыщенными блоками, бездумное использование подобного подхода породит приличные проблемы с быстродействием готового кода. Особняком здесь стоят таблицы AutoCAD, но разговор о них впереди.
При «разборе» ename-представлений мы рассматривали изменений нормали объекта (группа 210). В vla-представлении это Normal. Проверим свойство Normal у пока неизмененного объекта (проверку будем выполнять в сокращенной и в полной форме):
_$ ( vla — get — normal ent )
# < variant 8197 . >
_$ ( vlax-get-property ent ‘normal )
# < variant 8197 . >
_$ ( vlax-get-property ent «normal» )
# < variant 8197 . >
И списком здесь, казалось бы, и не пахнет.
Ну, на самом деле не совсем так. Точнее, совсем не так. Это просто ActiveX-представление списка (так называемый variant). Его можно преобразовать в обычный список:
_$ ( vlax — safearray -> list ( vlax-variant-value ( vlax-get-property ent ‘normal ) ) )
( 0.0 — 1.0 0.0 )
Но нам-то надо наоборот: готовый список (точнее, трехмерные координаты точки) преобразовать во что-то «этакое».
Именно для списков из 3 чисел Autodesk внедрила функцию (vlax-3d-point). Вот ее-то и используем:
_$ ( vlax-put-property ent ‘normal ( vlax-3d-point ‘ ( — 1 . 0 . 0 . ) ) )
nil
И все бы хорошо, да вот незадача — координаты центра окружности в мировой системе координат при изменении через entmod меняются, а при vlax-put-property — нет. И это только потому, что для окружности в ename=представлении в группе 10 хранятся координаты в системе координат объекта (OCS). Мы же не трогали группу 10? Не трогали. Вот и получаем «ускакавший» примитив.
И если бы это был один примитив с подобным поведением! Так ведь нет — для примитива POINT (точка) координаты (кстати, тоже группа 10) хранятся в мировой системе координат; для LINE (отрезки) — тоже мировая; для TEXT (текста) — в OCS и т.д.
Поэтому при работе через ename приходится постоянно отслеживать — какой примитив и как меняется.
Пока это была только графика. Дальше попробую рассмотреть вопросы создания и модификации неграфических данных.