Как создать аннотативный стиль / описание блока?
По результатам обсуждения статьи "О создании стилей".
Начиная с 2008 версии в dwg появилось понятие аннотативности. О пользе этой вещицы здесь говорить не будем, попробуем разобраться с тем, как создавать аннотативность для стиля или описания блока, и как ее удалять при необходимости.
Скажу честно - я разбирался именно со стилями, с объектами я не воевал. Может быть, потом как-нибудь и получится объекты победить, но пока загадывать не буду
Итак, поехали. Прежде всего: при работе со стилями намного проще работать через entmod, чем через vla-методы. По крайней мере у меня сложилось именно так.
В любом файле, создаваемом в AutoCAD начиная с 2008 версии (естественно, при условии, что шаблон не правился) создается как минимум 2 текстовых стиля - Standard (ну куда ж без него) и Annotative (или Аннотативный в русской локализации).
Если через (entget Style '("*")) снять все данные о стиле, становится видно, что вся разница только в группе -3:
Standard | Annotatibe | ||
|
Значит, для добавления аннотативности стилю достаточно просто добавить этот список?
Ну, как бы да, потому что на самом деле не совсем:
Во-первых, версия AutoCAD должна быть не ниже 2008.
Во-вторых, приложение "AnnotativeData" должно быть зарегистрировано в файле.
И, наконец, в третьих, объект должен быть неаннотативным. Это уже в принципе перестраховка, пока что AutoCAD не позволяет дважды на один и тот же элемент зарегистрировать одно и то же приложение. Но, как говорится, береженого Бог бережет, а небереженого конвой стережет.
Шаг первый. Проверяем версию AutoCAD. Один из вариантов - через (ver): перевести в верхний регистр, обрубить символы VISUALP и переконвертировать в число:
1 | (atoi (vl-string-trim "VISUALP " (strcase (ver)))) |
Но можно же и уже готовым решением воспользоваться _lispru-acad-version.lsp. Для 2008 версии эта функция вернет значение 17.1. От этого и будем "отталкиваться".
Второй шаг целиком и полностью (для увеличения быстродействия) возложим на AutoCAD. Простая строчка (regapp "AnnotativeData") будет выполнена быстро и безболезненно.
И, наконец, третье. Собственно проверка на "уже-аннотативность". Вещь в принципе не очень обязательная, но для вящего спокойствия сделаем.
Предположим, что у нас а) есть указатель на преобразовываемый объект и б) этот указатель в ename-представлении.
Следовательно, можно проверку сделать так: если (assoc "AcadAnnotative" (cdr (assoc -3 (entget st '("*"))))) вернет не nil, значит, объект уже аннотативный.
Объединяя все вместе, получаем в первом приближении:
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 | (defun _lispru-ent-make-annotative (ent / res) ;| * Добавление аннотативности объекту * Параметры вызова: ent ename-указатель на объект |; (if (and (> (_lispru-acad-version) 17.) (not (assoc "AcadAnnotative" (cdr (assoc -3 (entget ent '("*"))))) ) ;_ end of not ) ;_ end of and (progn (regapp "AcadAnnotative") (setq res (entmod (list (cons -1 ent) '(-3 ("AcadAnnotative" (1000 . "AnnotativeData") (1002 . "{") (1070 . 1) (1070 . 1) (1002 . "}") ) ) ) ;_ end of list ) ;_ end of entmod ) ;_ end of setq ) ;_ end of progn ) ;_ 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 52 53 54 55 56 57 | (defun _lispru-ent-make-annotative (ent make / res) ;| * Добавление аннотативности объекту * Параметры вызова: ent ename-указатель на объект make делать аннотативным или снимать аннотативность |; (if (and (> (_lispru-acad-version) 17.0) (not (assoc "AcadAnnotative" (cdr (assoc -3 (entget ent '("*"))))) ) ;_ end of not ) ;_ end of and (if make (progn (regapp "AcadAnnotative") (setq res (entmod (list (cons -1 ent) '(-3 ("AcadAnnotative" (1000 . "AnnotativeData") (1002 . "{") (1070 . 1) (1070 . 1) (1002 . "}") ) ) ) ;_ end of list ) ;_ end of entmod ) ;_ end of setq ) ;_ end of progn (setq res (entmod (append (entget ent) (list (cons -3 (append '(("AcadAnnotative")) (vl-remove-if (function (lambda (x) (= (car x "AcadAnnotative")) ) ;_ end of lambda ) ;_ end of function (cdr (assoc -2 (entget ent '("*")))) ) ;_ end of vl-remove-if ) ;_ end of append ) ;_ end of cons ) ;_ end of list ) ;_ end of append ) ;_ end of entmod ) ;_ end of setq ) ;_ end of if ) ;_ end of if ) ;_ end of defun |
Конечно, код можно и дальше дополнять (например, добавить проверку на тип ent, на то, что он вообще принадлежит к соответствующим типам примитивов и т.д.), но у меня сейчас на это просто нет времени.
Исходные файлы кодов:
_lispru-ent-make-annotative.lsp; _lispru-acad-version.lsp. Для корректной работы в текущий документ должны быть загружены оба лиспа.
Отлично! Думаю, пригодится не только мне! Спасибо!
Не в укор, а с целью улучшения статьи: ссылки на файл не открываются, требуют авторизации. Или так и задумано?
Спасибо Проверь, вроде сейчас уже должно нормально работать.
Да, сейчас как надо!
Кстати, в статье про сохранение данных в файле тоже есть такое.
В той статье тоже вроде бы все исправил. Спасибо:)
В коде функции _lispru-ent-make-annotative ошибка. Вместо (entget st '("*")) нужно (entget ent '("*"))
Вроде исправил Спасибо
Алексей, ссылка на исходный файл кодов _lispru-ent-make-annotative.lsp никуда не ведет
Спасибо, завтра проверю - сегодня уже сил нет никаких )))
Исправил - вроде работает
(= (car x "AcadAnnotative")) ошибка нужно (= (car x) "AcadAnnotative")
Ну и во втором приближение не будет работать удаление аннотативности, т.к. первый If не пропустит туда объект с аннотативностью
Выяснились интересные подробности: http://adn-cis.org/forum/index.php?topic=7494.new#new