Аннотативный размерный стиль и dimscale

Столкнулся недавно с файлом, в котором не удавалось заменить значение dimscale. Ни в какую! В чем же проблема?

Как выяснилось, проблема крылась в том, что текущий размерный стиль был аннотативным. Можно, конечно, руками проверять и менять - но "это не наш метод!". Значительно интереснее разобраться, как обойти эту фичу (встретился в ACAD2018 и 2019).

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

Но существует ненулевая вероятность, что неаннотативного размерного стиля в текущем документе попросту не будет. Так что снимаем аннотативность, а потом ее возвращаем. Ну и в результате получается нечто типа:

1
2
3
4
5
6
7
8
9
10
11
12
13
;; Активируем где-нибудь в загрузчике или отдельной команде реакторы на системные переменные
(if *vlr-sysvar*
  (progn (setq *vlr-sysvar* nil) (vlr-remove-all :vlr-sysvar-reactor))
  ) ;_ end of if
(if (not *vlr-sysvar*)
  (setq *vlr-sysvar* (vlr-sysvar-reactor "pik-ind-sysvar-reactor" '((:vlr-sysvarchanged . _kpblc-vlr-sysvar-changed)
                                                                    (:VLR-sysVarWillChange . _kpblc-vlr-sysvar-will-change)
                                                                    )))
  ) ;_ end of if
;; Также для работы понадобятся глобальные переменные
(setq *kpblc-acad*  (vlax-get-acad-object)
      *kpblc-adoc*  (vla-get-activedocument *kpblc-acad*)
        )

И собственно обработки:

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
(defun _kpblc-vlr-sysvar-will-change (reactor value / sysvar dimst) ;|
*    Реактор на начало смены значения системной переменной
|;

  (setq sysvar (strcase (car value)))
  (cond ((= sysvar "DIMSCALE")
         (if (_kpblc-is-ent-annotative (setq dimst (vla-get-activedimstyle *kpblc-adoc*)))
           (progn ;; В *KPBLC-SETTINGS-DOC* Запоминаем, что текущий стиль аннотативный и снимаем анно
                  (setq *kpblc-settings-doc* (_kpblc-list-add-or-subst *kpblc-settings-doc* "annodimstyle" t))
                  (_kpblc-ent-modify-annotative dimst nil)
                  ) ;_ end of progn
           ) ;_ end of If
         )
        ) ;_ end of cond
  ) ;_ end of defun

(defun _kpblc-vlr-sysvar-changed (reactor value / sysvar descr)
  (setq sysvar (strcase (car value)))
  (cond ((= sysvar "DIMSCALE")
         ;; Можно прописать дополнительные действия. DIMSCALE уже изменен
         (if (cdr (assoc "annodimstyle" *kpblc-settings-doc*))
           (progn (_kpblc-ent-modify-annotative (vla-get-activedimstyle *kpblc-adoc*) t)
                  (setq *kpblc-settings-doc* (_kpblc-list-add-or-subst *kpblc-settings-doc* "annodimstyle" nil))
                  ) ;_ end of progn
           ) ;_ end of if
         )
        ) ;_ end of cond
  ) ;_ 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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
(defun _kpblc-conv-ent-to-ename (ent_value / _lst)
                                ;|
*    Функция преобразования полученного значения в ename
*    Параметры вызова:
*  ent_value  значение, которое надо преобразовать в примитив. Может
*      быть именем примитива, vla-указателем или просто
*      списком.
*      Если не принадлежит ни одному из указанных типов,
*      возвращается nil
*    Примеры вызова:
(_kpblc-conv-ent-to-ename (entlast))
(_kpblc-conv-ent-to-ename (vlax-ename->vla-object (entlast)))
|;

  (cond ((= (type ent_value) 'vla-object) (vlax-vla-object->ename ent_value))
        ((= (type ent_value) 'ename) ent_value)
        ((and (= (type ent_value) 'str) (handent ent_value) (entget (handent ent_value)))
         (handent ent_value)
         )
        ((and (= (type ent_value) 'str) (handent ent_value) (tblobjname "style" ent_value))
         (tblobjname "style" ent_value)
         )
        ((and (= (type ent_value) 'str) (handent ent_value) (tblobjname "dimstyle" ent_value))
         (tblobjname "dimstyle" ent_value)
         )
        ((and (= (type ent_value) 'str) (handent ent_value) (tblobjname "block" ent_value))
         (tblobjname "block" ent_value)
         )
        ((and (= (type ent_value) 'list) (cdr (assoc -1 ent_value))) (cdr (assoc -1 ent_value)))
        (t nil)
        ) ;_ end of cond
  ) ;_ end of defun

(defun _kpblc-is-ent-annotative (ent) ;|
*    Проверяет, является ли объект аннотативным
*    Параметры вызова:
  ent      ; указатель на обрабатываемый объект
|;

  (and ent
       (setq ent (_kpblc-conv-ent-to-ename ent))
       (cdr (assoc "AcadAnnotative" (cdr (assoc -3 (entget ent '("*"))))))
       ) ;_ end of and
  ) ;_ end of defun

(defun _kpblc-list-add-or-subst (lst key value)
                                ;|
*    Производит замену или дополнение элемента списка новым
*    Параметры вызова:
  lst      обрабатываемый список
  key      ключ
  value    устанавливаемое значение
|;

  (if (not value)
    (vl-remove-if (function (lambda (x) (= (car x) key))) lst)
    (if (cdr (assoc key lst))
      (subst (cons key value) (assoc key lst) lst)
      (cons (cons key value) (vl-remove-if (function (lambda (x) (= (car x) key))) lst))
      ) ;_ end of if
    ) ;_ end of if
  ) ;_ end of defun

(defun _kpblc-ent-modify-annotative (ent make / res) ;|
*    Обработка аннотативности объекта
  ent     ; Указатель на объект
  make    ; назначать аннотативноть (t) или снимать ее (nil)
|;

  (if (and ent
           (setq ent (_kpblc-conv-ent-to-ename ent))
           (> (atoi (getvar "acadver")) 17.0)
           ;; (not (assoc "AcadAnnotative" (cdr (assoc -3 (entget ent '("*"))))))
           ) ;_ end of and
    (cond ((and make (not (assoc "AcadAnnotative" (cdr (assoc -3 (entget ent '("*")))))))
           (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
           )
          ((and (not make) (assoc "AcadAnnotative" (cdr (assoc -3 (entget ent '("*"))))))
           (setq res (entmod
                       (append (entget ent)
                               (list (cons -3
                                           (append '(("AcadAnnotative"))
                                                   (vl-remove-if (function (lambda (x) (= (car x "AcadAnnotative"))))
                                                                 (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 cond
    ) ;_ end of if
  ) ;_ end of defun

Если понадобится весь код загнать в один lsp, сообщите в комментариях. Сделаю при первой возможности.



Поделитесь своим мнением


Я не робот.