Тема: Расширенные примитивы

Спасибо, ShaggyDoc и Олег. Просьба помочь в решении еще одной проблемы (может, когда-нибудь в чем-нибудь и я кому-нибудь сгожусь wink Надо добавить в базу данного примитива расширенные данные. Пытаюсь использовать функцию
(defun extendprim (prom44)
   (setq point77 (getpoint "Указать точку"))
   (setq point771 (entget (ssname (ssget point77) 0)))
   (if (NOT (tblsearch "appid" "NEW155"))
               (regapp "NEW155")
   )
   (setq z (list -3 (list "NEW155" (cons 1070 prom44))))
   (setq new1 (list point771 z)) ; *)
   (entmod new1)
   (entget (ssname (ssget point77) 0) '("NEW155")) ; проверка присоединения расширенного примитива
)
В теории рекомендуют вместо (setq new1 (list point771 z))  использовать (setq new1 (append point771 z)). Однако при этом списки сливаются, а не добавляет список расширенных данных к уже существующим. Тем не менее, ни тот, ни другой вариант не срабатывает:   (entmod new1) отказывается записать в базу изменения.

Re: Расширенные примитивы

1. Ошибка в тексте такая.
Вместо строки (setq new1 (list point771 z)) должно быть
(setq new1 (cons z point771))

2. Вместо строк
(setq point77 (getpoint "Указать точку"))
(setq point771 (entget (ssname (ssget point77) 0)))

удобнее использовать
(setq point771 (car (entsel "Указать объект")))

3. Вообще я сейчас всем советую (уже 3-й раз в разных конференциях за неделю) для записи-чтения расширенных данных использовать функции VisualLisp vlax-ldata
Запись: (vlax-ldata-put [Примитив] [Ассоциатор] [Данные])
Чтение: (vlax-ldata-put [Примитив] [Ассоциатор])
Достоинства этого способа: простота, не надо думать о типах данных и групповых кодах, преобразовании данных, возможны списки любой сложности, быстрота, для больших массивив данных Автокад сам рапределет их по нескольким XRECORD.
Недостатки: Нельзя выполнять поиск примитивов с расширенными данными по ssget и нельзя использовать точки с пересчитываемыми координатами (что часто удобно).
Естественно, надо сначала выполнить (vl-load-com)

Re: Расширенные примитивы

Олег совершенно прав. Особенно насчет использования новых функций VisualLisp. Это очень мощное средство. VLAX-, VLR- делают VisualLisp очень интересным. Жаль только, что "Visual" просто маркетинговый ход, но "невизуальные" возможности его для версий 15.хх очень хороши.

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

Re: Расширенные примитивы

Огромное спасибо за рекомендации, однако я уже столько настругал в 14-м Акаде, что надо довести это дело до конца. И все-таки, прошу извинить меня за назойливость, гуру Олег и гуру ShaggyDoc, есть ли какая возможность цеплять и читать эти треклятые расширенные примитивы, исправив данную функцию:
(defun extendprim (prom44 / point771 z new1)
   (setq point771 (entget (car (entsel "Указать объект"))))
   (if (NOT (tblsearch "appid" "NEW155"))
               (regapp "NEW155")
   )
   (setq z (list -3 (list "NEW155" (cons 1070 prom44))))
   (setq new1 (list point771 z))
   (entmod new1)
   (entget (ssname (ssget point77) 0) '("NEW155"))
)
Конструкция (setq new1 (cons point771 z)) тоже не проходит: команда cons добавляет z к point771 не как подсписок, а поглощает его новым списком. В общем, так или иначе entmod напрочь отказывается производить какие-либо изменения в существующем списке примитива! HELP!!!
И попутно еще один вопрос: у меня Акад 14.5 (рус.), и я читал, что Vlisp работает в 14-ом. Однако у меня нет никакого намека на Vlisp (по крайней мере, папки соответствующей нет).
Может можно было бы как-то подключить Vlisp к моему Акаду 14.5?

Re: Расширенные примитивы

Попробуй так:

(defun extendprim (prom44 / point771 z new1)
   (setq point771 (entget (car (entsel "Указать объект"))))
   (if (NOT (tblsearch "appid" "NEW155"))
     (regapp "NEW155")
   ) ;_ end of if
   (setq z (list (list -3 (list "NEW155" (cons 1040 prom44)))))
;;;
;;; Если нужны только короткие целые числа, то можно
;;; использовать код 1070
;;;
   (setq new1 (append point771 z))
   (entmod new1)
;;;
;;;  (entget (car (entsel "Указать объект")) '("NEW155"))
;;; Как я понял эта строка только для проверки
;;;
)

Проверял в R15, но должно работать и в R14

Re: Расширенные примитивы

А если всё работает, то стоит привести функцию к виду:

(defun extendprim (prom44)
   (if (NOT (tblsearch "appid" "NEW155"))
     (regapp "NEW155")
   ) ;_ end of if
   (entmod
     (append (entget (car (entsel "Укажите объект: ")))
        (list (list -3 (list "NEW155" (cons 1040 prom44))))
     ) ;_ end of append
   ) ;_ end of entmod
) ;_ end of defun

Re: Расширенные примитивы

Могу предложить для записи чтения расширенных данных две свои старые функции:

Запись:
APP-имя приложения
Prim - имя примитива
DataList - список расширенных данных
Список одноуровневый из чисел, строк и точек
(defun SetExtData (App Prim DataList / AList)
  (if (not (tblsearch "APPID" App)) (regapp App))
  (setq AList '((STR 1000)(REAL 1040)(INT 1070)(LIST 1010))
    DataList (mapcar
         '(lambda (x) (cons (cadr (assoc (type x) AList)) x))
         DataList
        )
  )
  (entmod (cons (list -3 (cons App DataList)) (entget Prim)))
)

Чтение:
APP-имя приложения
Prim - имя примитива
Возвращает список
(defun GetExtData (App Prim)
  (mapcar 'cdr (cdadr (assoc -3 (entget Prim (list App)))))
)

Пример использования

(SetExtData Prim "NEW155" '("Мои данные" 25))
(GetExtData Prim "NEW155")

Есть функция и для списков произвольной иерархии - но она большая.

Re: Расширенные примитивы

Попробуй использовать конструкцию:
(setq new1 (append point771 (list z)))

Re: Расширенные примитивы

Огромное спасибо всем, кто ответил на такой для меня животрепещущий вопрос. Однако получается несколько не то, что я хотел. Задача состояла в том, чтобы связать с данным графическим примитивом дополнительную информацию, отражаемую на экране после ВВОДА ЕЁ пользователем. Использование расширенных данных позволяет ввести только наперед заданную константу, прописанную в поле точечной пары. Я решил эту задачу путем записи атрибута в примитив. Вот такое решение получилось (за оптимальность кода не ручаюсь):
; Запись атрибута в притимив
(defun atrib_in ( / a aa ab) 
   (setq a (entsel "Указать объект"))
   (setq aa (car (reverse a)))
   (setq ab (getstring "Текст"))
   (command "_.ATTDEF" "" ab "" "" aa "" "")
)
; Считывание атрибута с указанного примитива
(defun atrib_out ( / atrib77)
   (setq atrib77 (entget  (entnext (car (entsel)))))
   (if (/= atrib77 nil)
        (setq textt (cdr (assoc 2 atrib77)))
   )
)

P.S. Понимаю, что работать это будет, если у примитива не было атрибутов.
А с расширенными примитивами я так и не понял: можно решить такую задачу или нет...

Re: Расширенные примитивы

Поздравляю всех с Наступающим Новым годом! Желаю успехов на благородном поприще помощи нуждающимся и желающим поправить свое незавидное знание за счет Великих Гуру!

Re: Расширенные примитивы

Хот я и не "гуру"... Насчёт оптимальности кода, как минимум не:

(setq aa (car (reverse a)))

а

(setq aa (cadr a)) ;_ это стандартное решение

По самому решению. Такой вариант непригоден для решения вопроса более чем для одного пользователя (причём именно того, кто это решение создал).

Вариантов корректного решения может быть несколько. Как пример схемы такого решения: в расширенной части DXF основного примитива можно хранить метку указывающую на примитив типа TEXT в который и записывается некая информация (его, естественно, надо корректно сформировать и лучше через entmake). Информацию можно хранить как в расширенной части DXF основного примитива, так и в словаре, а можно ограничиться собственно строкой текстового примитива. Обновление содержания можно реализовать и как функцию запрашивающую пользователя и как реактор срабатывающий на какое то условие. В расширенной части DXF дочернего примитива стоит сохранять метку основного примитива, что бы можно было организовать доступ к основному примитиву через дочерний. Метки, естественно, должны быть включены. Обязательно надо делать реактор, который обрабатывал бы ситуацию с изменением или удалением основного примитива, другой реактор на изменение / удаление дочернего, ну и ещё всякие мелочи...

Re: Расширенные примитивы

По поводу расширенных данных (РД), то некоторых ГИС,  в них  хранятся и номера домов и улицы и т. д. Информация вносится изменением (дополнением) РД через диалоговые окна (DCL, VBA), точно также и считывается, если необходимо узнать про какой либо примитив поподробнее. Один из путей - классификация сведений и сведение их в одну строку через определенные символы ("99:Код объекта\44:Наименование\22:Признак" и т. д.). Удачи! С Новым Годом!

Re: Расширенные примитивы

Спасибо, Alaspher, Sergej! Все работает как надо! Я снова провел ревизию в своих взглядах на возможности расширенных примитивов.
Кажется, с ними я смогу вершить ба-а-альшие дела! Еще раз огромное Спасибо!!!
Но человек - существо неугомонное: если есть какие-нибудь соображения по поводу
моего второго вопроса (от 20.12 прошлого года): "...у меня Акад 14.5 (рус.), и я читал, что Vlisp работает в 14-м...".
Может, что нибудь можно посоветовать?

Re: Расширенные примитивы

Для Акада 14 Vlisp поставляется отдельно. У меня есть. Инсталяция 5.3 Mb + документация VLGUIDE.PDF 4.35Mb
Могу кинуть на e-mail. Пиши на мой адрес если не возражаеш.

Re: Расширенные примитивы

Спасибо всем, кто помог мне разобраться с расширенными примитивами. Но я так ими увлекся, что хочется "расшарить" их до конца. Подскажите, где можно почитать более глубоко о структуре расширенной части примитива, как корректно ссылаться на другой примитив, что такое словарь и т.д., и т.п. Буду очень признателен - я и так ваш должник ;)

Re: Расширенные примитивы

Читай Николая Полещука "Visual Lisp и секреты адаптации AutoCAD". Там все подробно, с примерами, высокопрофессионально. Это лучшая книга последних лет.

И не читай похожих по названию книг Кудрявцева. Чтобы мозги не искалечить.

Успехов!

Re: Расширенные примитивы

Спасибо за совет. Нашел я эту книгу в магазине, да только в виртуальном (MISTRAL). Пока достать не могу. А разобраться надо сейчас.  Может быть где-то хоть какие-то её кусочки лежат в открытом электронном виде? Подскажите, кто может. Буду вельм? ?дзячны ;))

Re: Расширенные примитивы

Не нашел в Инете этой книги, кроме как в электронных магазинах (Mistral и пр.). Может есть где-нибудь на безбрежных просторах сети?