Установка и сброс системных переменных — AutoCAD LISP

Я пытаюсь максимально упростить рисование электрических схем в AutoCAD, почти не нажимая кнопок, кроме моих запрограммированных.

Один включает в себя LISP, который не очень хорошо работает с установкой системных переменных, а затем сбрасывает их до того, что они были раньше. Программа, кажется, выполняет намеченную функцию, но не с ожидаемыми результатами.

Как только моя команда PLINE запускается, переменные сбрасываются. Мне нужно, чтобы PLINE запустилось, закончилось, а затем переменные сбрасывались.

Я пытался установить OrthoMode и SnapMode в команде LISP, а также с помощью команд (setvar (getvar ...)).

(defun varget ()
    (setq lis '("orthomode" "snapmode"))
    (setq var (mapcar 'getvar lis))
    (setq var1 '(1 1))
    (setq no 0)
    (repeat (length lis)
        (setvar (nth no lis) (nth no var1))
        (setq no (1+ no))
    )
    (princ)
 )

(defun varset ()
    (setq no 0)
    (repeat (length lis)
        (setvar (nth no lis) (nth no var))
        (setq no (1+ no))
    )
(princ)
)

(princ)

(defun C:wire ()
(progn
(varget)
(setq prevlayer (getvar "clayer"))
(setq P (getstring "Audio(A)/Video(V)/Comm(CO)/Coax(R)/Control(C)/(N)etwork/(P)ower:"))
(IF (= P "V")(command "-LAYER" "M" "VIDEO" "C" "150" "" "" "PLINE" PAUSE))
(IF (= P "A")(command "-LAYER" "M" "AUDIO" "C" "94" "" "" "PLINE" PAUSE))
(IF (= P "CO")(command "-LAYER" "M" "COMM" "C" "206" "" "" "PLINE" PAUSE))
(IF (= P "R")(command "-LAYER" "M" "COAX" "C" "44" "" "" "PLINE" PAUSE))
(IF (= P "C")(command "-LAYER" "M" "CONTROL" "C" "10" "" "" "PLINE" PAUSE))
(IF (= P "N")(command "-LAYER" "M" "NETWORK" "C" "210" "" "" "PLINE" PAUSE))
(IF (= P "P")(command "-LAYER" "M" "POWER" "C" "7" "" "" "PLINE" PAUSE))
(setvar "clayer" prevlayer)
(varset)
(princ)
);Progn
);defun

Нет сообщений об ошибках.

Я ожидаю, что переменные будут сброшены после выполнения команды PLINE.


person Perry Chapman    schedule 09.07.2019    source источник


Ответы (1)


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

Вместо этого вам нужно будет использовать цикл для непрерывной паузы для пользовательского ввода, прежде чем продолжить оценку программы.

Например:

;; Define function, declare local symbols
(defun c:wire ( / col lay opt val var )

    ;; System variables to be modified within the program
    (setq var '(clayer orthomode snapmode cmdecho)
    ;; Retrieve current sys var values
          val  (mapcar 'getvar var)                
    ) ;; end setq

    ;; Predefine the getkword options
    (initget "Audio Video COmm R Control Network Power")
    ;; Prompt the user for input, default to "Audio" on null input
    (setq opt (cond ((getkword "\n[Audio/Video/COmm/Coax(R)/Control/Network/Power] <Audio>: ")) ("Audio")))

    ;; Define the layer & colour based on the option returned
    (cond
        (   (= opt "Audio")   (setq lay "AUDIO"    col  94))
        (   (= opt "Video")   (setq lay "VIDEO"    col 150))
        (   (= opt "COmm")    (setq lay "COMM"     col 206))
        (   (= opt "R")       (setq lay "COAX"     col  44))
        (   (= opt "Control") (setq lay "CONTROL"  col  10))
        (   (= opt "Network") (setq lay "NETWORK"  col 210))
        (   (= opt "Power")   (setq lay "POWER"    col   7))
    ) ;; end cond

    ;; Suppress command-line output for the -LAYER command
    (setvar 'cmdecho 0)
    ;; Create & set the layer & layer colour
    (command "_.-layer" "_M" lay "_C" col "" "")

    ;; Set everything except the first sys var
    (mapcar 'setvar (cdr var) '(1 1 1))
    ;; Initiate the PLINE command
    (command "_.pline")
    ;; Continuously pause for user input
    (while (= 1 (logand 1 (getvar 'cmdactive))) (command "\\"))

    ;; Reset system variables
    (mapcar 'setvar var val)

    ;; Suppress the value returned by the last evaluated expression
    (princ) 
) ;; end defun

Несколько замечаний:

  • Всегда объявляйте свои локальные переменные, чтобы избежать конфликтов с переменными с одинаковыми именами в пространстве имен документа. См. мое руководство здесь для получения дополнительной информации о том, как и почему вы это делаете.

  • Используйте getkword вместо getstring для контроля и проверки ввода пользователя.

  • Используйте "\\" вместо символа pause, так как символ pause является незащищенной глобальной переменной и может быть легко непреднамеренно переопределен за пределами вашей программы, что приведет к сбою вашей программы. Поскольку символ pause оценивается как "\\", вы также можете использовать буквальную обратную косую черту.

В качестве расширения вы также можете рассмотреть реализацию локального обработчика ошибок для обработки, когда пользователь неизбежно нажимает Esc во время оценки программы (в противном случае системные переменные не были бы сброшены при таких обстоятельствах). Я описываю, как это сделать, в своем руководстве здесь.

Вот простой пример, демонстрирующий включение локального обработчика ошибок:

;; Define function, declare local symbols
(defun c:wire ( / *error* col lay opt val var )

    ;; Define local error handler
    (defun *error* ( msg )
        ;; Reset system variables
        (mapcar 'setvar var val)
        ;; Suppress the output of standard cancellation messages
        (if (not (wcmatch (strcase msg t) "*break,*cancel*,*exit*"))
            ;; Print critical errors
            (princ (strcat "\nError: " msg))
        ) ;; end if
        (princ) ;; Suppress the value returned by the last evaluated expression
    ) ;; end defun

    ;; System variables to be modified within the program
    (setq var '(clayer orthomode snapmode cmdecho)
    ;; Retrieve current sys var values
          val  (mapcar 'getvar var)                
    ) ;; end setq

    ;; Predefine the getkword options
    (initget "Audio Video COmm R Control Network Power")
    ;; Prompt the user for input, default to "Audio" on null input
    (setq opt (cond ((getkword "\n[Audio/Video/COmm/Coax(R)/Control/Network/Power] <Audio>: ")) ("Audio")))

    ;; Define the layer & colour based on the option returned
    (cond
        (   (= opt "Audio")   (setq lay "AUDIO"    col  94))
        (   (= opt "Video")   (setq lay "VIDEO"    col 150))
        (   (= opt "COmm")    (setq lay "COMM"     col 206))
        (   (= opt "R")       (setq lay "COAX"     col  44))
        (   (= opt "Control") (setq lay "CONTROL"  col  10))
        (   (= opt "Network") (setq lay "NETWORK"  col 210))
        (   (= opt "Power")   (setq lay "POWER"    col   7))
    ) ;; end cond

    ;; Suppress command-line output for the -LAYER command
    (setvar 'cmdecho 0)
    ;; Create & set the layer & layer colour
    (command "_.-layer" "_M" lay "_C" col "" "")

    ;; Set everything except the first sys var
    (mapcar 'setvar (cdr var) '(1 1 1))
    ;; Initiate the PLINE command
    (command "_.pline")
    ;; Continuously pause for user input
    (while (= 1 (logand 1 (getvar 'cmdactive))) (command "\\"))

    ;; Reset system variables
    (mapcar 'setvar var val)

    ;; Suppress the value returned by the last evaluated expression
    (princ) 
) ;; end defun
person Lee Mac    schedule 09.07.2019
comment
Потрясающе, огромное спасибо! Поигравшись еще немного с кодом, я придумал добавить (в то время как (› («cmdactive») 0)) паузу) после операторов IF, и это сработало. Спасибо за эти указатели. Обязательно включу их в свои будущие программы. - person Perry Chapman; 10.07.2019