AutoLISP - автоматическое изменение слоев - PullRequest
1 голос
/ 16 апреля 2020

Я хочу сделать простую процедуру AutoLISP, в которой я рисую линии в слое "0", а затем возвращаюсь к исходному слою.

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

(defun c:testfunction (/ OLD)
  (setq OLD (getvar 'clayer))
  (setvar 'clayer "0")
  (command "line")
  (setvar 'clayer OLD)
)

Концепция кода

Сначала я сохраняю текущий слой в переменной OLD, затем меняю слой на "0". После команды LINE я снова переключаюсь на слой OLD.

Заранее спасибо.

1 Ответ

0 голосов
/ 16 апреля 2020

Пауза для ввода

Поскольку команда AutoCAD LINE может выдавать пользователю произвольное количество запросов (в зависимости от количества линий, которые они будут рисовать sh) вам нужно будет включить в код al oop, чтобы разрешить произвольное количество пользовательских вводов, до сброса текущего слоя.

Ваш текущий код будет оценивать выражение (setvar 'clayer OLD) до того, как пользователь указал точку первой линии, поскольку нет паузы для пользовательского ввода.

до пауза для пользовательского ввода в команде AutoCAD, вызываемой из программы AutoLISP или макроса панели инструментов вы используете backsla sh \.

Однако, поскольку backsla sh является экранирующим символом в AutoLISP, вам необходимо добавить префикс к другому backsla sh для вывода литерала backsla sh в команду, например \\.

Кроме того: символ pause также считается обратным символом sh, но, поскольку этот символ не защищен и может быть переопределен, я всегда рекомендовал бы использовать буквенный символ обратного хода sh.

И поэтому мы можем использовать:

(command "line" "\\")

Однако, это только пауза для одного входа, и команда AutoCAD LINE примет произвольное количество входов, и поэтому нам нужен способ построить al oop и определить, когда пользователь закончил с командой.

Для этого мы можем использовать CMDACTIVE системная переменная, которая является системной переменной с битовой кодировкой, указывающей текущее состояние команды - битовый код 1 указывает, что команда активна.

Чтобы проверить, установлен ли битовый код 1, мы можно использовать функцию AutoLISP logand, которая возвращает побитовые AND двух предоставленных целых чисел, например:

(logand 1 3) => 1

(logand 1 2) => 0

Комбинируя это с CMDACTIVE системная переменная у нас есть:

(logand 1 (getvar 'cmdactive))

Который будет eturn 1, если команда активна, иначе 0 в противном случае.

Следовательно, тестовое выражение для нашего l oop может быть:

(= 1 (logand 1 (getvar 'cmdactive)))

И теперь оно просто остается создайте сам l oop - для этого мы можем использовать функцию AutoLISP while:

(while (= 1 (logand 1 (getvar 'cmdactive)))
    (command "\\")
)

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

Собираем все вместе

Собираем все вместе, у нас есть:

(defun c:testfunction ( / old )
    (setq old (getvar 'clayer))
    (setvar 'clayer "0")
    (command "line")
    (while (= 1 (logand 1 (getvar 'cmdactive)))
        (command "\\")
    )
    (setvar 'clayer old)
)

Однако есть несколько других улучшений, которые мы можем сделать здесь ...

Дополнительные улучшения

  • Мы можем добавить выражение (princ) в конец определения функции, чтобы подавить значение, возвращаемое последним вычисленным выражением. Как написано, текущая функция вернет значение, возвращенное функцией setvar, которая будет именем исходного слоя.

    Мы можем использовать (princ) в конце определения, чтобы вместо этого возвратить нулевой символ в командную строку, и, следовательно, аккуратно выйти из программы:

    (defun c:testfunction ( / old )
        (setq old (getvar 'clayer))
        (setvar 'clayer "0")
        (command "line")
        (while (= 1 (logand 1 (getvar 'cmdactive)))
            (command "\\")
        )
        (setvar 'clayer old)
        (princ)
    )
    
  • Мы можем поставить префикс вызова AutoCAD LINE команда с подчеркиванием для учета локализованных версий AutoCAD (в которой команда LINE может называться как-то еще):

    (command "_line")
    

    использование префикса команды подчеркивания гарантирует, что мы вызываем нелокализованную команду Engli sh LINE.

  • Мы можем добавить префикс вызова AutoCAD LINE команда с периодом для учета возможных переопределенных версий AutoCAD LINE команда:

    (command "_.line")
    

    Поскольку возможно переопределение команд AutoCAD , использование префикса команды period обеспечивает при вызове неопределяемой стандартной LINE команды.

  • Мы можем добавить локальный обработчик ошибок для автоматического сброса текущего слоя на исходный слой, если пользователь нажимает Es c для выхода из программы:

    (defun c:testfunction ( / *error* old )
    
        (defun *error* ( msg )
            (if old (setvar 'clayer old))
            (if (not (wcmatch (strcase msg t) "*break,*cancel*,*exit*"))
                (princ (strcat "\nError: " msg))
            )
            (princ)
        )
    
        (setq old (getvar 'clayer))
        (setvar 'clayer "0")
        (command "_.line")
        (while (= 1 (logand 1 (getvar 'cmdactive)))
            (command "\\")
        )
        (setvar 'clayer old)
        (princ)
    )
    

    Для получения дополнительной информации о том, как работает локальный обработчик ошибок, вы можете sh обратиться к моему учебному пособию по AutoLISP по Обработка ошибок .

  • Мы могли бы также убедитесь, что слой 0 не заморожен, прежде чем пытаться установить его в качестве текущего слоя, но это выходит за рамки программы для начинающих.

Расширение идеи

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

Но это означает, что пользователь должен не забывать вызывать нашу пользовательскую версию команды LINE, а не стандартную команду LINE.

Что если бы был способ автоматически установить и сбросить текущий слой при вызове стандартных команд AutoCAD? Что ж, благодаря использованию Visual LISP Reactors, есть.

В моем приложении с открытым исходным кодом Layer Director я демонстрирую, как вы можете использовать Command Reactors и LISP Reactors для автоматического создания, настройки и сбросить текущий слой при вызове стандартных команд AutoCAD:

enter image description here

...