Тема: LISP, DCL. Выбор всех объектов на указанном слое

Вариант 1.

;******************* sel_lay.lsp *****************************************
;        Выбор всех объектов на слое выбранного объекта.
;        Автор Владимир Громов.
;
(defun C:SEL_LAY ( / echo sen ent lay ss len da)
      (setq echo (getvar "CMDECHO"))
      (setvar "CMDECHO" 0)
      (princ "\n Определение слоя по объекту.")
      (setq sen (entsel " Выберите нужный объект: "))
(if sen
      (progn
      (setq ent (entget (car sen)))
      (setq lay (cdr (assoc 8 ent)))
      (setvar "CLAYER" lay)
      (setq ss (ssget "_X" (list (cons 8 lay))))
      (setq len (sslength ss))
      (sssetfirst nil ss)
      (initget 6 "Да Нет Yes No _ Yes No")
      (setq da (getkword "\n Отключить остальные слои? [Да/Нет] <Да>: "))
      (if (or (= da "Yes") (= da nil))
          (progn
          (vl-cmdf "_-LAYER" "_OF" "*" "_Y" "")
          (vl-cmdf "_-LAYER" "_ON" LAY "")
      )); if da
      (sssetfirst ss ss)
      (princ "\n Слой: ") (princ lay)
      (princ "  Количество объектов = ") (princ len)
      )
      (princ "\n Объект не выбран!")
); if sen
      (setvar "cmdecho" echo)
      (princ)
)

Возможный макрос для кнопки или пункта меню:

^C^C^P(if (not C:SEL_LAY) (load "sel_lay")) SEL_LAY

---------------------------------------------------------------------------------
Вариант 2.

;******************* lay_sel.lsp *****************************************
;        Выбор всех объектов на указанном слое.
;        Предполагается, что все слои в рисунке включены,
;        не заморожены и не заблокированы.
;        Автор Владимир Громов.
;
(defun C:LAY_SEL ( / echo lay ss len da)
      (setq echo (getvar "CMDECHO"))
      (setvar "CMDECHO" 0)
      (if (not C:SETCL) (load "ddcl"))
      (C:SETCL)
      (setq lay (getvar "CLAYER"))
      (setq ss (ssget "_X" (list (cons 8 lay))))
      (setq len (sslength ss))
      (sssetfirst nil ss)
      (initget 6 "Да Нет Yes No _ Yes No")
      (setq da (getkword "\n Отключить остальные слои? [Да/Нет] <Да>: "))
      (if (or (= da "Yes") (= da nil))
          (progn
          (vl-cmdf "_-LAYER" "_OF" "*" "_Y" "")
          (vl-cmdf "_-LAYER" "_ON" LAY "")
      )); if da
      (sssetfirst ss ss)
      (princ "\n Слой: ") (princ lay)
      (princ "  Количество объектов = ") (princ len)
      (setvar "cmdecho" echo)
      (princ)
)

Для работы этой программы необходимы еще 2 файла:

;************* ddcl.lsp ***********************************
;              Выбор и установка текущего слоя.
;              Работает с диалоговым окном setcl.
;
  (defun laylist_act (index)
         (setq lay_idx (atoi index))
         (setq layname (nth lay_idx sortlist))
         (set_tile "list_l" (itoa lay_idx))
         (mode_tile "list_l" 3)
  )
   (defun laindex ( / m n)
         (setq n (length sortlist))
         (setq m (length (member (getvar "CLAYER") sortlist)))
         (- n m)
  )
(defun C:SETCL ( / layname)
         (setvar "CMDECHO" 0)
         (princ "\n Установите текущий слой: \n ")
         (setq sortlist nil)
         (setq templist (tblnext "LAYER" T))
    (while templist
           (setq name (cdr (assoc 2 templist)))
           (setq sortlist (cons name sortlist))
           (setq templist (tblnext "LAYER"))
    )
           (if (>= (getvar "maxsort") (length sortlist))
           (setq sortlist (acad_strlsort sortlist))
           (setq sortlist (reverse sortlist))
           )
       ;Загрузка диалогового окна
       (setq dcl_id (load_dialog "ddcl"))
       (if (not (new_dialog "setcl" dcl_id)) (exit))
       (start_list "list_l")
       (mapcar 'add_list sortlist)
       (end_list)
       ;Активизация переменных
       (set_tile "list_l" (itoa (laindex)))
       (mode_tile "list_l" 3)
       (action_tile "list_l" "(laylist_act $value)")
       (action_tile "accept" "(done_dialog)")
       ; Взять значения переменных
       (start_dialog)
       (unload_dialog dcl_id)
               (if (not layname) (setq layname (getvar "clayer")))
               (setq laylist (tblsearch "layer" layname))
               (setq color (cdr (assoc 62 laylist)))
               (setq bit_70 (cdr (assoc 70 laylist)))
           (if (and (minusp color) (/= bit_70 65) (/= bit_70 68) (/= bit_70 69))
               (progn
               (princ "\n Указанный слой отключен! Включаю его.")
               (command "_LAYER" "_ON" layname "")
           ))
           (if (and (/= bit_70 65) (/= bit_70 68) (/= bit_70 69))
               (setvar "CLAYER" layname)
           )
           (if (= bit_70 65)
               (princ "\n Указанный слой заморожен! Разморозьте его.")
           )
           (if (= bit_70 68)
               (princ "\n Указанный слой заблокирован! Разблокируйте его.")
           )
           (if (= bit_70 69)
               (princ "\n Указанный слой заблокирован и заморожен! \n Разблокируйте и разморозьте его.")
           )
           (princ "\n Текущим установлен слой: ") (princ layname)
           (setq sortlist nil laylist nil color nil layname nil templist nil
                 lay_idx nil n nil m nil)
    (princ)
)

Следующие строки необходимо сохранить в файле ddcl.dcl

setcl:dialog {
         label = "Выбор слоя";
         fixed_width = true;
         :row {
            :list_box {
                width = 12;
                height = 16;
                key = "list_l";
            }
         }
ok_only;
}

Возможный макрос для кнопки или пункта меню:

^C^C^P(if (not C:LAY_SEL) (load "lay_sel")) LAY_SEL

Далее можно, например, скопировать выбранные объекты в буфер обмена для вставки в другой рисунок.

Re: LISP, DCL. Выбор всех объектов на указанном слое

Вот подумал, а вдруг на слое, который мы выбираем в программе Вариант 2 нет объектов. Тогда программа вылетает аварийно. Пришлось подправить и теперь новый код для Варианта 2:

;******************* lay_sel.lsp *****************************************
;        Выбор всех объектов на указанном слое.
;        Предполагается, что все слои в рисунке включены,
;        не заморожены и не заблокированы.
;        Автор Владимир Громов.
;
(defun C:LAY_SEL ( / echo slt lay ss len da)
      (setq echo (getvar "CMDECHO"))
      (setvar "CMDECHO" 0)
      (setq slt (getvar "CLAYER"))
      (if (not C:SETCL) (load "ddcl"))
      (C:SETCL)
      (setq lay (getvar "CLAYER"))
      (setq ss (ssget "_X" (list (cons 8 lay))))
(if ss
      (progn
      (setq len (sslength ss))
      (sssetfirst nil ss)
      (initget 6 "Да Нет Yes No _ Yes No")
      (setq da (getkword "\n Отключить остальные слои? [Да/Нет] <Да>: "))
      (if (or (= da "Yes") (= da nil))
          (progn
          (vl-cmdf "_-LAYER" "_OF" "*" "_Y" "")
          (vl-cmdf "_-LAYER" "_ON" LAY "")
      )); if da
      (sssetfirst ss ss)
      (princ "\n Слой: ") (princ lay)
      (princ "  Количество объектов = ") (princ len)
      ); progn ss
      (progn
      (setvar "CLAYER" slt)
      (princ "\n На этом слое нет объектов!")
      ); progn ss
); if ss
      (setvar "cmdecho" echo)
      (princ)
)

Re: LISP, DCL. Выбор всех объектов на указанном слое

> Владимир Громов
Извините, что влезаю, но (initget 6 "Да Нет Yes No _ Yes No") - так писать не следует. Должно быть: (initget 6 "Да Нет Yes No _ Yes No Yes No"), т.е. сколько локализованных ключей, столько и глобальных. При вызове в AutoCAD 2006 этой функции в том виде как Вы записали и вводе ключевого слова Y (getkword) возвращает "", а потом уже не реагирует и на на мою запись (initget ...) - что-то с ним происходит.

Re: LISP, DCL. Выбор всех объектов на указанном слое

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

;|=============================================================================
*    Переназначение обработки ошибок.
*    Переназначен или нет обработчик проверяется по значению
* переменной *kpblc-error*
=============================================================================|;
(defun kpblc-error-init    ()
  (if (not *kpblc-error*)
    (setq *kpblc-error*
       *error*
      *error* kpblc-error
      ) ;_ end of setq
    ) ;_if
  (princ)
  ) ;_defun
;|=======================================================================================
*    Стандартный обработчик ошибок AutoCAD
=======================================================================================|;
(defun kpblc-error (message)
  (if (member message
          '("console break"          "Function cancelled"
        "Функция отменена"      "quit / exit abort"
        "выйти прервать"
        ) ;_list
          ) ;_member
    (princ "\nКоманда прервана пользователем")
    (princ
      (strcat "\ERRNO # "
          (itoa (getvar "ERRNO")) ;_itoa
          ": "
          message
          "\n"
          ) ;_strcat
      ) ;_princ
    ) ;_if
  (vla-endundomark *kpblc-activedoc*)
  (princ)
  ) ;_defun
;|=============================================================================
*    Функция возвращает указатели на активный документ и приложение. Также
* выполняет активацию измененного обработчика ошибок.
*    Параметры вызова:
*    нет
*    Примеры вызова:
(lib:vla-pointers)
=============================================================================|;
(defun lib:vla-pointers    ()
  (setq    *kpblc-acad-object*
     (vlax-get-acad-object)
    *kpblc-activedoc*
     (vla-get-activedocument *kpblc-acad-object*)
    ) ;_ end of setq
  (kpblc-error-init)
  ) ;_ end of defun
 ;|=============================================================================
*    Функция возвращает набор объектов, лежащих на слое выбранного объекта.
*    Параметры вызова:
*    нет
*    Примеры вызова:
(lib:select-similar-object)
=============================================================================|;
(defun lib:select-similiar-object (/
                   sel_ent
                   sel_set_list
                   _answer_
                   )
  (vla-pointers)
  (while (not (setq sel_ent (entsel "\nУкажите объект : ")))
    (princ "\nНе указан объект!")
    ) ;_ end of while
  (setq sel_ent (entget (car sel_ent)))
  (initget "Слою Типу Все _ Layer Type All")
  (setq    _answer_
     (getkword "\nВыбирать аналогичные по [Слою/Типу объекта/Все] <Все> :")
    ) ;_ end of setq
  (if (not _answer)
    (setq _answer_ "All")
    ) ;_ end of if
  (setq _answer_ (strcase _answer_ t))
  (cond
    ((= _answer_ "layer")
     (setq sel_set_list (list (assoc 8 sel_ent)))
     )
    ((= _answer_ "type")
     (setq sel_set_list (list (assoc 0 sel_ent)))
     )
    (t
     (setq sel_set_list (list (assoc 0 sel_ent) (assoc 8 sel_ent)))
     )
    ) ;_ end of cond
  (ssget "_x" sel_set_list)
  ) ;_ end of defun
;;; Это просто проверка.
(defun c:hide-layer-objects (/ selset)
  (vl-load-com)
  (setq selset (lib:select-similiar-layer-object))
  (sssetfirst selset selset)
  ) ;_ end of defun

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

Re: LISP, DCL. Выбор всех объектов на указанном слое

> Александр Ривилис
Каюсь, упустил. На самом деле, я обычно вообще не применяю в (initget) английские ключевые слова из принципа, а здесь бес попутал, то бишь Александр Ривилис. smile
Но контекстное меню работает.

Re: LISP, DCL. Выбор всех объектов на указанном слое

Как я пропустил эту программу? Это же классный инструмент для правки чужих чертежей. Начнем тестирование :)

Re: LISP, DCL. Выбор всех объектов на указанном слое

А по-моему в Pro Menu уже существует даная функция. Разве никто не использует Pro Menu?

Re: LISP, DCL. Выбор всех объектов на указанном слое

> Игорь
Я не использую. Я даже не знаю, что это такое.

Re: LISP, DCL. Выбор всех объектов на указанном слое

> Владимир Громов
www.multicim.com/us/CAD/Buy_ProMenu.html
Если интерисует могу выслать.

Re: LISP, DCL. Выбор всех объектов на указанном слое

> Игорь
Я посмотрел описание команд в Pro Menu. По-моему, там нет именно такой функции, как нет ее и в "Express Tools".

Re: LISP, DCL. Выбор всех объектов на указанном слое

А чем вам не нравится команда _qselect или соответствующий пункт контекстного меню? Там можно выделять объекты по слою, по цвету, и вообще по всему чему угодно. Или я чего-то недопонял?

Re: LISP, DCL. Выбор всех объектов на указанном слое

> Hacker
А чем вам не нравятся программы, приведенные здесь? Да даже, если и не нравятся, кто заставляет вас использовать их? Плюньте и забудьте.

Re: LISP, DCL. Выбор всех объектов на указанном слое

Я не говорил, что программы не нравятся. Просто почитал тему и подумал, зачем писать программу, если эта функция уже есть в Акаде.

Re: LISP, DCL. Выбор всех объектов на указанном слое

> Hacker
Просто такая тема была... Из нее родились программы.