Тема: LISP, DCL. Порядок следования заливки (штриховки SOLID)

К написанию этой программы побудила трудность выделения
сплошной заливки в AutoCAD'ах до 2006. К примеру, я имею
план здания с большим количеством объектов и мне надо
заливками выделить специальные зоны: палаты, коридор, ну,
и т.п. Как правило заливка перекрывает все объекты и надо
ее отправить "вниз". Начинаешь "тыркать" ее и никак не попадешь,
все время выбираются объекты, находящиеся "под" заливкой.
А вот если сознательно создать заливку (штриховку SOLID)
на отдельном слое, скажем, с именем "Зеленый", то с помощью этой
программы можно запросто отправить "вниз" все объекты (в данном
случае заливку зеленого цвета) вниз. Программа использует
диалоговое окно выбора слоя. Сама программ выборы и установки
текущего слоя может работать автономно, но она очень урезана
по сравнению с AutoCAD'овской.
Все три файла должны находится на пути доступа к файлам AutoCAD'а.
Для запуска программы порядка следования можно применить такой
макрос для кнопки или пункта меню:

^C^C^P(load "fil_order")

А для запуска автономной программы выбора слоя:

^C^C^P(if (not C:SETCL) (load "ddcl")) SETCL
;******* fil_order.lsp ******************************************
;                Порядок следования заливки (штриховки)
;                       Автор Владимир Громов
;
(apply '(lambda ()
  (setvar "cmdecho" 0)
  (setq slt (getvar "CLAYER"))
  (C:SETCL)
  (setq lay (getvar "CLAYER"))
  (setq ss1 (ssget "X"
            (list (cons 8 lay))
            )
  )
  (if ss1
      (progn
      (princ "\n Найдено на слое '") (princ lay) (princ "' ") (princ (sslength ss1)) (princ " объектов.")
      (initget "В П")
      (setq move (getstring "\n Поместить объекты [Впереди всех/Позади всех] <Позади>: "))
      (cond
      ((= move "В") (command "_DRAWORDER" ss1 "" "Е"))
      ((or (= move "П") (= move "")) (command "_DRAWORDER" ss1 "" "А"))
      )
      )
      (princ "\n На этом слое ничего нет!")
  )
      (setvar "CLAYER" slt)
      (setq lay nil ss1 nil move nil)
      (princ)
)
'()
)
;************* 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;
}

Re: LISP, DCL. Порядок следования заливки (штриховки SOLID)

AutoCad 2005 SP1.
Создал 3 файла: ddcl.dcl, ddcl.lsp, fil_order.lsp, скинул в папку поддержки, посадил макрос на кнопку и, получил, при нажатии на нее:
Command:  ; error: no function definition: C:SETCL
Command:  Unknown command "FIL_ORDER".
P.S. Другие (понравившиеся) программы из этого раздела форума запускаются нормально.

Re: LISP, DCL. Порядок следования заливки (штриховки SOLID)

> Демиан
Тут такая штука. Для работы программы необходимо, чтобы сначала был загружен файл ddcl.lsp. Это автономная программа выбора текущего слоя. В этом случае будет доступно диалоговое окно выбора слоя. У меня эта программа сидит в автозагрузке, потому что диалоговое окно выбора слоя используется и в других программах. Если программу выбора слоя неохота ставить в автозагрузку, то тогда код основной программы будет выглядеть так:

;******* fil_order.lsp ******************************************
;                Порядок следования заливки (штриховки)
;                       Автор Владимир Громов
;
(apply '(lambda ()
  (setvar "cmdecho" 0)
  (setq slt (getvar "CLAYER"))
  (if (not C:SETCL) (load "ddcl"))
  (C:SETCL)
  (setq lay (getvar "CLAYER"))
  (setq ss1 (ssget "X"
            (list (cons 8 lay))
            )
  )
  (if ss1
      (progn
      (princ "\n Найдено на слое '") (princ lay) (princ "' ") (princ (sslength ss1)) (princ " объектов.")
      (initget "В П")
      (setq move (getstring "\n Поместить объекты [Впереди всех/Позади всех] <Позади>: "))
      (cond
      ((= move "В") (command "_DRAWORDER" ss1 "" "Е"))
      ((or (= move "П") (= move "")) (command "_DRAWORDER" ss1 "" "А"))
      )
      )
      (princ "\n На этом слое ничего нет!")
  )
      (setvar "CLAYER" slt)
      (setq lay nil ss1 nil move nil)
      (princ)
)
'()
)

Макрос тот же:

^C^C^P(load "fil_order")

Команда работает только при нажатии кнопки.

Re: LISP, DCL. Порядок следования заливки (штриховки SOLID)

> Владимир Громов
Как вариант:

(defun _drawback (/ selset)
  (setq selset (ssget "_X" '((0 . "HATCH") (2 . "SOLID"))))
  (sssetfirst selset selset)
  (command "_.draworder" "_Back")
  ) ;_ end of defun

Re: LISP, DCL. Порядок следования заливки (штриховки SOLID)

> kpblc
Ну, конечно, в этом случае ВСЕ заливки отправятся "вниз". А если они перекрываются и надо их отсортировать? В моей программе можно ЛЮБЫЕ объекты, находящиеся на указанном слое, вытащить "вверх" или "опустить", ^~.

Re: LISP, DCL. Порядок следования заливки (штриховки SOLID)

> Владимир Громов
Ну тады ой, тады да, я пас :)
Сорри за сленг - настроение такое ;)

Re: LISP, DCL. Порядок следования заливки (штриховки SOLID)

Программа запускается, но работает с ошибками: сначала спрашивает по русски: "Поместить объекты [Впереди всех/Позади всех] <Позади>". Правый клик - ошибка. Затем переспрашивает по английски - правый клик - все Ок.

Re: LISP, DCL. Порядок следования заливки (штриховки SOLID)

Да, программа писалась под русскую версию AutoCAD 2005.
Окончательный, переработанный вариант:

;*******FIL_ORDER.LSP - Порядок следования заливки (штриховки) **********
;
;
(defun C:FIL_ORDER ( / echo lay ss1 move)
  (setq echo (getvar "CMDECHO"))
  (setvar "cmdecho" 0)
  (setq slt (getvar "CLAYER"))
  (if (not C:SETCL) (load "ddcl"))
  (C:SETCL)
  (setq lay (getvar "CLAYER"))
  (setq ss1 (ssget "X"
            (list (cons 8 lay))
            )
  )
  (if ss1
      (progn
      (princ "\n Найдено на слое '") (princ lay) (princ "' ") (princ (sslength ss1)) (princ " объектов.")
      (initget "В П")
      (setq move (getstring "\n Поместить объекты [Впереди всех/Позади всех] <Позади>: "))
      (cond
      ((= move "В") (command "_DRAWORDER" ss1 "" "_F"))
      ((or (= move "П") (= move "")) (command "_DRAWORDER" ss1 "" "_B"))
      )
      )
      (princ "\n На этом слое ничего нет!")
  )
      (setvar "CLAYER" slt)
      (setvar "CMDECHO" echo)
      (princ)
)

Новый макрос для кнопки:

^C^C^P(if (not C: FIL_ORDER) (load "fil_order")) FIL_ORDER

Re: LISP, DCL. Порядок следования заливки (штриховки SOLID)

Пробел как-то влез в макрос.
Надо так:

^C^C^P(if (not C:FIL_ORDER) (load "fil_order")) FIL_ORDER