Преобразование единиц измерения блоков в файле

Известно, что при создании блока (ручного создания) можно указывать единицы, в которых этот блок будет вставляться: миллиметры, метры, дюймы и т.д. Это удобно, если гарантируется, что вся работа всегда выполняется на основе единственного шаблона с раз и навсегда настроенными единицами. Но бывает такое не всегда (да и за смежниками, бывает, приходится "доделывать").

Оптимальным решением, как ни странно, будут "безразмерные" блоки. То есть те, у которых единицы - "Unitless" (в русской версии перевода не помню). С новыми блоками все понятно - достаточно контролировать это значение и стараться не допускать ошибок. А что делать со старыми, уже вставленными? Да очень просто - заменить!

Менять можно вручную, переопределяя блоки (к примеру). И этот подход более чем достаточен, если блоков 1-2. Ну, всяко не больше 10 (и то лично я уже на втором озверею). Программное решение намного более интересно.

Вариантов программы, конечно, может быть сколько угодно. Рассмотрим 2: либо обрабатывать все блоки в файле (независимо ни от чего), либо обрабатывать только указанные блоки. В набор обрабатываемых блоков может попадать несколько блоков. ТЗ составлено, приступаем к реализации.

Наиболее удобным будет применение ActiveX - код получится достаточно простым, читабельным и понятным.

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
(vl-load-com)

;; Вызов: (lispru-change-block-units)
(defun lispru-change-block-units (/ adoc)
  ;; Поставим метку начала отмены. Ну так, на всякий случай
  (vla-startundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object))))
  ;; Проходим по всем описаниям блоков документа
  (vlax-for blk_def (vla-get-blocks adoc)
    ;; Из обработки исключаем внешние ссылки, пространства модели и листа
    (if (and (equal (vla-get-islayout blk_def) :vlax-false)
             (equal (vla-get-isxref blk_def) :vlax-false)
             ;; И дополнительно исключаем блоки таблиц и размеров
             (not (wcmatch (strcase (vla-get-name blk_def)) "<code>*D*,</code>*T*"))
             ) ;_ end of and
      (vl-catch-all-apply
        (function
          (lambda ()
            (vla-put-units blk_def 0)
            ) ;_ end of lambda
          ) ;_ end of function
        ) ;_ end of vl-catch-all-apply
      ) ;_ end of if
    ) ;_ end of vlax-for
  ;; Теперь метка конца отмены
  (vla-endundomark adoc)
  ;; Ну и "тихий" выход
  (princ)
  ) ;_ 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
(vl-load-com)

;; Вызов: (lispru-change-block-units-by-select)
(defun lispru-change-block-units-by-select (/ _dwgru-conv-pickset-to-list adoc selset blk_list name)

  (defun fun_get-name (ent)
    ;; Получение имени блока
    (cond
      ((vlax-property-available-p ent 'effectivename)
       (vla-get-effectivename ent)
       )
      ((vlax-property-available-p ent 'name)
       (vla-get-name ent)
       )
      ) ;_ end of cond
    ) ;_ end of defun

  (defun _dwgru-conv-pickset-to-list (value / tab item)
;;; http://forum.dwg.ru/showpost.php?p=188342&postcount=21
    (repeat (setq tab  nil
                  item (sslength value)
                  ) ;_ end setq
      (setq tab (cons (ssname value (setq item (1- item))) tab))
      ) ;_ end repeat
    ) ;_ end defun

  ;; Поставим метку начала отмены. Ну так, на всякий случай
  (vla-startundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object))))
  ;; Получаем набор блоков, обрабатывая нажатие Esc
  (if (= (type (setq selset (vl-catch-all-apply
                              (function
                                (lambda ()
                                  (ssget '((0 . "INSERT")))
                                  ) ;_ end of lambda
                                ) ;_ end of function
                              ) ;_ end of vl-catch-all-apply
                     ) ;_ end of setq
               ) ;_ end of type
         'pickset
         ) ;_ end of =
    (progn
      ;; Сформируем список имен блоков, исключая дубликаты
      (foreach ent
                   ;; Преобразовываем набор в список элементов, исключая внешние ссылки.
                   ;; Это при полностью программной обработке надо отслеживать блоки листов
                   ;; и модели. Вручную их не выделить.
                   (vl-remove-if
                     (function
                       (lambda (x)
                         (equal (vla-get-isxref (vla-item (vla-get-blocks adoc) (vla-get-name x))) :vlax-true)
                         ) ;_ end of lambda
                       ) ;_ end of function
                     (mapcar (function vlax-ename->vla-object) (_dwgru-conv-pickset-to-list selset))
                     ) ;_ end of vl-remove-if
        (if (not (member (setq name (fun_get-name ent)) blk_list))
          (setq blk_list (cons name blk_list))
          ) ;_ end of if
        ) ;_ end of foreach
      ;; Запускаем новый цикл
      (foreach blk_def
                       ;; Из списка имен получаем список указателей на описания блоков
                       (mapcar
                         (function
                           (lambda (x)
                             (vla-item (vla-get-blocks adoc) x)
                             ) ;_ end of lambda
                           ) ;_ end of function
                         blk_list
                         ) ;_ end of mapcar
        (vl-catch-all-apply
          (function
            (lambda ()
              (vla-put-units blk_def 0)
              ) ;_ end of lambda
            ) ;_ end of function
          ) ;_ end of vl-catch-all-apply
        ) ;_ end of foreach
      ) ;_ end of progn
    ) ;_ end of if
  ;; Теперь метка конца отмены
  (vla-endundomark adoc)
  ;; Ну и "тихий" выход
  (princ)
  ) ;_ end of defun

У этого кода есть один, но очень серьезный недостаток: он не обрабатывает (по крайней мере на данный момент) вложенные блоки.

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

---

Добавлено: можно за компанию потом еще и выполнить регенерацию чертежа. По вкусу, как говорится :)

Размещено в Код LISP, Функции LISP · Метки:



Комментарии

Есть 2 коммент. к “Преобразование единиц измерения блоков в файле”
  1. Кулик Алексей aka kpblc пишет:

    В случае, если надо обрабатывать только выделяемые блоки, но с учетом вложенных, код становится чуть посложнее.
    [cc lang="cadlisp"](vl-load-com)

    ;; Вызов: (lispru-change-block-units-by-select-with-subblocks)
    (defun lispru-change-block-units-by-select-with-subblocks
    (/ _dwgru-conv-pickset-to-list adoc selset blk_list name)

    ;|
    * Преобразование единиц измерения блоков, включая вложенные блоки
    |;

    (defun fun_get-name (ent)
    ;; Получение имени блока
    (cond
    ((vlax-property-available-p ent 'effectivename)
    (vla-get-effectivename ent)
    )
    ((vlax-property-available-p ent 'name)
    (vla-get-name ent)
    )
    ) ;_ end of cond
    ) ;_ end of defun

    (defun _dwgru-conv-pickset-to-list (value / tab item)
    ;;; http://forum.dwg.ru/showpost.php?p=188342&postcount=21
    (repeat (setq tab nil
    item (sslength value)
    ) ;_ end setq
    (setq tab (cons (ssname value (setq item (1- item))) tab))
    ) ;_ end repeat
    ) ;_ end defun

    ;; Поставим метку начала отмены. Ну так, на всякий случай
    (vla-startundomark
    (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
    ) ;_ end of vla-startundomark
    ;; Получаем набор блоков, обрабатывая нажатие Esc
    (if (= (type (setq selset (vl-catch-all-apply
    (function
    (lambda ()
    (ssget '((0 . "INSERT")))
    ) ;_ end of lambda
    ) ;_ end of function
    ) ;_ end of vl-catch-all-apply
    ) ;_ end of setq
    ) ;_ end of type
    'pickset
    ) ;_ end of =
    (progn
    ;; Сформируем список имен блоков, исключая дубликаты
    ;; И не забываем про вложенные блоки
    (foreach ent
    ;; Преобразовываем набор в список элементов, исключая внешние ссылки.
    ((lambda (/ item lst)
    (foreach item
    (apply
    (function append)
    (mapcar
    (function
    (lambda (x / res)
    ;; применяем эту функцию
    (setq res (list x))
    (vlax-for item x
    (if
    (wcmatch
    (strcase
    (vla-get-objectname item)
    ) ;_ end of strcase
    "*BLOCK*"
    ) ;_ end of wcmatch
    (setq res (cons item res))
    ) ;_ end of if
    ) ;_ end of vlax-for
    res
    ) ;_ end of lambda
    ) ;_ end of function
    ;; begin : удаление внешних ссылок
    (vl-remove-if
    (function
    (lambda (x)
    (equal
    (vla-get-isxref
    (vla-get-name x)
    ) ;_ end of vla-get-isxref
    :vlax-true
    ) ;_ end of equal
    ) ;_ end of lambda
    ) ;_ end of function
    (mapcar
    (function
    (lambda (x)
    (vla-item
    (vla-get-blocks adoc)
    (fun_get-name
    (vlax-ename->vla-object x)
    ) ;_ end of fun_get-name
    ) ;_ end of vla-item
    ) ;_ end of lambda
    ) ;_ end of function
    (_dwgru-conv-pickset-to-list selset)
    ) ;_ end of mapcar
    ) ;_ end of vl-remove-if
    ;; end : удаление внешних ссылок
    ) ;_ end of mapcar
    ) ;_ end of apply
    (if (not (member (fun_get-name item)) lst)
    (setq lst (cons item lst))
    ) ;_ end of if
    ) ;_ end of foreach
    lst
    ) ;_ end of lambda
    ) ;_ end of foreach
    (if (not (member (setq name (fun_get-name ent)) blk_list))
    (setq blk_list (cons name blk_list))
    ) ;_ end of if
    ) ;_ end of foreach
    ;; Запускаем новый цикл
    (foreach blk_def
    ;; Из списка имен получаем список указателей на описания блоков
    (mapcar
    (function
    (lambda (x)
    (vla-item (vla-get-blocks adoc) x)
    ) ;_ end of lambda
    ) ;_ end of function
    blk_list
    ) ;_ end of mapcar
    (vl-catch-all-apply
    (function
    (lambda ()
    (vla-put-units blk_def 0)
    ) ;_ end of lambda
    ) ;_ end of function
    ) ;_ end of vl-catch-all-apply
    ) ;_ end of foreach
    ) ;_ end of progn
    ) ;_ end of if
    ;; Теперь метка конца отмены
    (vla-endundomark adoc)
    ;; Ну и "тихий" выход
    (princ)
    ) ;_ end of defun[/cc]
    Код не комментирую (хотя по-хорошему надо бы, я там немного логику поменял). Надо будет - обращайтесь :)

  2. ganjour пишет:

    Спасибо. Код пригодился для нормализации блоков геодезических условных знаков.

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


Я не робот.