Введение в Автолисп

Рыжиков Роман Клавдиевич

6. РАБОТА С БАЗОЙ ДАННЫХ ЧЕРТЕЖА

 

 

Процесс создания чертежа сводится в конечном итоге к выполнению множества отдельных операций с примитивами. Все эти операции могут осуществляться программным путем, для чего Автолисп использует ряд функций, призванных создавать графические объекты, извлекать из базы данных чертежа необходимые сведения о примитивах, комплектовать наборы объектов и готовить, таким образом, исходные данные для выполнения дальнейших действий. Часть информации хранится в базе данных чертежа в виде таблиц (имена блоков, слоев, типов линий и т.п.). Далее рассматриваются наиболее употребительные функции, способствующие обработке характеристик примитивов и содержания таблиц.

 

6.1. Характеристики примитивов

В процессе создания и обработки примитивов Автолисп оперирует их характеристиками. Количество характеристик примитива зависит от его природы и сложности. Каждая характеристика определяется присущим ей так называемым DXF-кодом. Примерный смысл термина DXF (Drawing eXchange Format) - формат передачи графической информации. Полный список кодов можно найти, например, в [5, 6]. Некоторые часто используемые коды приведены в табл. 4.

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

(10 2.2 5.0 3.1),

где 10 - код начальной точки, остальные три числа - координаты x, у, z точки.

Tаблицa 4. Часто применяемые DXF-коды

Код Значение
-4 Условный оператор, используемый при создании набора примитивов
-1 Код имени примитива
0 Код типа примитива
5 Код метки
6 Код типа линий
7 Код текстового стиля
8 Код имени слоя
10 Код начальной (базовой) точки. Для линии - это начальная точка, для дуги или окружности - центр, для текста - точка вставки
11 ... 18 Коды характеристик других точек примитива
40 У дуги и окружности - код радиуса, у текста - код высоты
48 Код масштаба типа линий
62 Код номера цвета

Если подсписок содержит только два элемента, он может образовывать уже упоминавшуюся ранее точечную пару (Dotted Pair). Извлекая из чертежа характеристики отрезка прямой, мы можем получить строку, подобную следующей:

((-1. )

(0 . “LINE”)

(6. “CONTINUOUS”)

(8. “CONTUR”)

(10 3.1 4.8)

(11 5.6 8.7)

(62 . 2))

На основании этой характеристики можно утверждать, что извлечен отрезок сплошной линии красного цвета, расположенный в слое CONTUR. Координаты начальной точки (3.1 4.8), конечной - (5.6 8.7). Пять подсписков в примере являются точечными парами.

Следует заметить, что на экран возвращаются лишь те параметры примитива, которые отличаются от параметров по умолчанию.

Среди характеристик примитива находятся две, выделяющие его из всего множества элементов чертежа как единственный и неповторимый объект. Это имя примитива и его метка (handle). И то и другое создается Автокадом и сохраняется в базе данных чертежа. Но если имя примитива может меняться от сеанса к сеансу, метка сопровождает примитив на протяжении всего его существования. Кроме того, метка может быть использована для восстановления примитива, удаленного функцией entdel (см. ниже).

 

6.2. Точечная пара

Точечная пара представляет собой особый вид списка, состоящий всегда только из двух элементов. Этот список создается Автокадом для использования в графической базе данных. Достоинство точечной пары по сравнению с обычным списком из двух элементов заключается в том, что пара занимает меньший объем памяти, экономя, таким образом, дисковое пространство и оперативную память. В процессе выполнения чертежа Автокад создает множество точечных пар, используемых для численного описания характеристик примитивов, что демонстрируется примером в предыдущем параграфе.

Точечная пара не может быть создана средствами только Автолиспа. Большинство функций вообще не работают с точечными парами. Исключение составляют уже описанные ранее car, cdr и описываемая ниже функция assoc, осуществляющая ассоциативную связь между элементами пары.

Поскольку пара создается Автокадом, то функция Автолиспа, используемая для создания точечной пары, должна быть пропущена через Автокад. Например, выражение (cons 1 “One”) создает список из двух элементов. Но, будучи введенной в командную строку Автокада, та же функция является основой для возникновения точечной пары. Действительно,

command: (setq d1 (cons 1 “One”)) возвращает (1 . “One”).

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

 

6.3. Средства обработки отдельных примитивов

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

(entlast). Функция используется для вызова последнего неудаленного примитива, добавленного в базу данных явным образом или с помощью функции command. При этой операции возвращается имя примитива.

(entnext [имя_пр] ) . Если функция используется без аргумента имя_пр , она возвращает имя первого неудаленного примитива в базе данных. Если имя_пр указано, возвращается имя следующего за ним примитива. Например:

(setq e1 entnext) присваивает идентификатор e1 первому примитиву графической базы данных,

(setq e2 (entnext e1)) присваивает е2 примитиву, следующему за e1.

(entdel имя_пр ) . Если примитив имя_пр присутствует в чертеже, он удаляется. Если этот примитив был ранее удален в текущем сеансе, он восстанавливается. Например, если с помощью функции entnext были выполнены операции, указанные в предыдущем примере, использование функции entdel приводит к следующим результатам:

(entdel e1) удаляет из чертежа примитив e1,

(entdel e1) восстанавливает удаленный примитив e1.

Операция восстановления примитива может быть осуществлена на любом этапе выполнения и редактирования чертежа. В этом ее отличие от механизма действия команды undo, которая последовательно, от конца к началу, отменяет результаты действий оператора. Функция же entdel восстанавливает любой примитив, если он был именован.

(entget имя_пр ) . Функция возвращает ассоциированный список, содержащий характеристики примитива. Пусть последним созданным примитивом был отрезок прямой в слое CONTUR, цвет примитива - красный, начальная точка примитива - (3.1 4.8), конечная - (5.6 8.7). Тогда функция

(entget (entlast))

возвратит список, подобный приведенному в разделе 6.1.

(entmake список ) . Функция создает в чертеже новый примитив. Аргумент список должен содержать перечень всех необходимых характеристик примитива в формате, создаваемом функцией entget. Если введенных характеристик достаточно для однозначного описания примитива, он создается в чертеже, а функция возвращает список характеристик. В противном случае функция возвращает nil.

Перед созданием нового примитива функция проверяет, cyществуют ли в чертеже указанный слой, тип линий и цвет и при необходимости организует новый слой с указанным цветом. Что касается типа линий, то он должен быть загружен в чертеж отдельной командой. Точно так же анализируются имена блоков, текстовых и размерных стилей, если таковые указываются в списке. Все они должны уже существовать в чертеже или создаваться предварительно программным путем.

Дополнительные сведения об этих и других функциях обработки примитивов можно почерпнуть в [5, 6].

 

6.4. Наборы примитивов

На примере программы bolt.lsp можно было видеть, что организация некоторого набора примитивов оказывается полезной, если предполагается, что в дальнейшем с этим набором будут совершаться какие-либо операции. Наборы создаются функцией

(ssget [режим] [точка1 [точка2]] [список] [фильтры] ),

которая формирует набор примитивов, определяемый аргументами. Будучи введенной без аргументов, функция предлагает оператору осуществить выбор примитивов вручную. Аргумент режим - это строка, определяющая метод выбора объектов. Допустимыми являются “W”, “WP”, “С”, “CP”, “L”, “P”, “I” и “F”. Возможен еще режим “Х”, осуществляющий выбор всех примитивов, созданных в чертеже. Аргументы точка1 и точка2 - отдельные точки или их список, присущие данному выбору. Аргумент фильтры - это ассоциированный список, определяющий свойства примитивов. Приводимые далее примеры заимствованы из [5].

(ssget) предлагает пользователю свободный выбор объектов и включает их в набор.

(ssget "P") организует набор из всех примитивов, принадлежащих предыдущему выбору.

(ssget “L”) создает набор, включающий в себя последний созданный объект, видимый на чертеже.

(ssget pt1) создает набор из всех примитивов, проходящих через точку pt1.

(ssget “W” pt1 pt2) создает набор из примитивов, находящихся внутри окна с диагональными углами в точках pt1 и pt2.

(ssget “С” pt1 pt2) - то же, но определяющей является секущая рамка.

(ssget “X”) создает набор из всех примитивов, сохраненных в графической базе чертежа.

(ssget “X” список__фильтров) создает набор из всех объектов чертежа, удовлетворяющих списку фильтров.

(ssget список_фильтров) предлагает пользователю свободный выбор, но в набор включает лишь те объекты, которые удовлетворяют списку фильтров.

Организацию списка фильтров можно проследить на следующем примере:

(ssget “X” ‘((0 . “CIRCLE”) (-4 . “>=”) (40 . 2.0)))

Функция создает набор из всех окружностей, имеющихся в чертеже, радиус которых равен или превышает 2.0.

В последнем примере использован оператор соответствия (relational operator), обладающий кодом DXF, равным -4, и выделяющий из общей массы объектов лишь те, которые удовлетворяют заданному условию. Он может иметь силу, если параметр выбора является численной величиной (целым или вещественным числом, точкой или вектором). В таблице 5 приведен список некоторых операторов соответствия.

Таблица 5. Операторы соответствия для фильтров наборов

Оператор Значение
“*” Нет ограничений
“=” Равно
“<>”, “!=” или “/=” Не равно
“<” Меньше чем
“>” Больше чем
“<=” Меньше или равно
“>=” Больше или равно

Список фильтров может быть создан и с использованием логических операторов: “”, “”, “”, “”. Каждому логическому оператору присущи открывающий и закрывающий элементы. Поэтому они всегда употребляются в паре. Первые два оператора могут содержать любое количество операндов, третий - обязательно два, четвертый - только один операнд. Возможность использования логических операторов рассмотрим на следующем примере.

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

(command “layer” “new” “b1”

    “new” “b2”

    “I” “continuous” “b1”

    “|” “Acad_ISO04w100” “b2”

    “с” “white” “b1”

    “c” “red” “b2”

    “s” “b1” “”)

(command “pline” p1 “w” “0.8” “” p2 p3 p4

    “pline” p6 p7 p8 p9 “c”

    “line” p10 p11

    “line” p12 p14

    “line” p13 p15)

(command “layer” “s” “b2” “”)

(command “line” p16 p17)

(setq ss (ssget “x” ‘((-4 . “

        (8 . “b1”)

        (8 . “b2”)

        (-4 . “OR>”))

    )

)

Теперь в операциях поворота и перемещения болта можно использовать один набор ss, включающий в себя все примитивы, принадлежащие изображению болта.

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

 

6.5. Функции обработки наборов

(ssadd [имя_пр [набор]] ) . Функция добавляет примитив, определенный его именем, в существующий набор. Вызванная без аргументов, она создает пустой набор. Если указано только имя примитива, создается новый набор из одного примитива. Если примитив уже существует в наборе, функция игнорирует операцию и не воспринимает такой ввод за ошибку.

(setq e1 (entnext)) присваивает имя e1 первому примитиву в чертеже,

(setq ss (ssadd)) создает пустой набор ss,

(ssadde1 ss) включает в набор ss примитив e1,

(setq e2 (entnext е1)) присваивает имя e2 примитиву, следующему за e1,

(ssadd e2 ss) добавляет примитив e2 в набор ss.

(ssdel имя_пр набор ) . Функция удаляет примитив из набора и возвращает имя набора. Если названный, примитив в наборе отсутствует, возвращается nil. Например, если примитив e1 существует в наборе ss1, a примитив e2 нет, то

(ssdel e1 ss1) возвращает SS1 (без элемента e1);

(ssdel e2 ss1) возвращает nil.

(sslength набор ) . Функция возвращает целое число, соответствующее количеству элементов в наборе.

(ssmemb имя_пр набор ) . Функция проверяет, является ли указанный примитив элементом набора, Если да, возвращает его имя, если нет, возвращает nil.

(ssname набор индекс ) . Функция возвращает имя примитива, порядковый номер которого соответствует введенному индексу. Если индекс отрицателен или превышает число примитивов в наборе, возвращается nil. Следует помнить, что первому элементу набора присваивается индекс 0. Если необходимо извлечь имя примитива, индекс которого превышает 32767, следует вводить его как действительное число. Например,

(setq entx (ssname sset 50483.0))

возвращает имя 50484-го примитива набора, присваивая ему идентификатор entx.

 

6.6. Организация циклов при обработке наборов

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

(repeat число выражение ... ) . Функция выполняет операции, определяемые выражением заданное число раз и возвращает последний результат. Аргумент число обязателен, список выражений не должен быть пустым. Пример [2]:

(setq a 10 b 100)

(repeat 4

    (setq a (+ a 10))

    (setq b (+ b 100))

)

присваивает а значение 50, b - значение 500.

(while условие выражение ... ) . Функция оценивает условие , и если оно не nil, выполняет выражение . Процесс продолжается до тех пор, пока условие не примет значения nil. Функция возвращает значение последнего выражения.

В качестве примера организации цикла рассмотрим программу сохранения системных переменных, которая часто используется в прикладных программах (например в файле attredef.lsp; находящемся в папке support пакета AutoCAD).

(defun MODES (а)

    (setq MLST '())

    (repeat (length а)

        (setq MLST (append MLST

            (list (list (саг а) (getvar (car a))) )) )

        (setq a (cdr a))

    )

)

Каждая системная, переменная обладает именем и значением, т.е. представляет собой список из двух элементов. Первая строка программы описывает пользовательскую функцию MODES, включающую один аргумент, по содержанию имеющий определенное сходство с формальным параметром в подпрограмме Фортрана. Автолисп позволяет использовать параметр для подстановки как атомов, так и списков. В данном случае будет использован список системных переменных. Вторая строка создает пустой список MLST. Третья - открывает цикл, в котором количество повторов операции соответствует длине аргумента а, т.е. числу сохраняемых переменных. Далее в первом цикле выполняются следующие операции (для удобства чтения одна из подстрок выделена полужирным шрифтом):

(car а) - извлекается первая системная переменная из списка а сохраняемых переменных;

(getvar (car a)) - извлекается значение первой системной переменной;

(list (car a) (getvar (car а))) - формирует подсписок, состоящий из имени переменной и ее значения;

(list (list (car a) (getvar (car а))) ) - формирует список из подсписков переменных и их значений (в первом цикле список состоит из одного подсписка);

(append MLST (list (...))) - сформированный список присоединяется к пустому списку MLST;

(setq MLST (append MLST (list (...)))) - результат предыдущего действия идентифицируется со списком MLST, который теперь не пуст, а содержит имя системной переменной и ее значение;

(setq a (cdr a)) - из списка переменных исключается обработанная переменная.

Во втором цикле все операции повторяются, но присоединение второй переменной и ее значения происходит уже не к пустому списку, а к списку, хранящему имя и значение первой переменной.

Теперь достаточно из основной программы вызвать функцию MODES с перечисленными в качестве аргументов именами сохраняемых системных переменных, и все они вместе с их значениями будут сохранены в списке MLST:

(modes '(sysvar1 sysvar2 sysvar3 ...)).

После окончания всех операций, предусмотренных программой, восстановить системные переменные можно пользовательской функцией moder. Эта функция работает аналогично функции modes и дополнительных пояснений, вероятно, не требует. Следует лишь обратить внимание на то, что обрабатываемым является список MLST, уже существующий в программе. Программа выглядит следующим образом:

(defun MODER ()

    (repeat (length MLST)

        (setvar (caar MLST) (cadar MLST))

        (setq MLST (cdr MLST))

    )

)

Обе функции можно использовать без изменения при составлении любых программ на Автолиспе.

При сохранении и изменении конфигурации целесообразно обратить внимание на системную переменную OSMODE (Object Snap Mode - режим объектной привязки). Не исключены ситуации, когда объектная привязка главенствует над указанием точки и примитив строится не из указанной точки, а из точки, определенной автоматической объектной привязкой. Поэтому автоматическую привязку целесообразно отключить, установив переменную OSMODE в ноль, или изменить ее значение в нужную сторону. Значение этой переменной устанавливается в соответствии с таблицей 5.

Tаблица 6. Битовые числа опций объектной привязки

Битовое число Значение опции Битовое число Значение опции
0 Отсутствие привязки 32 Intersection
1 Endpoint 64 Insertion
2 Midpoint 128 Perpendicular
4 Centre 256 Tangent
8 Node (узел) 512 Nearest
16 Quadrant 1024 Quick
2048 Apparent Intersection
В версию Автокад 2000 включены дополнительно две опции:
4096 Extension 8192 Parallel

Ранее уже отмечалось, что на время работы программы целесообразно устанавливать в 0 системную переменную CMDECHO и устанавливать в 1 переменную BLIPMODE, если оператор при ручной работе использует маркеры.

 

6.7. Программное редактирование наборов

Чертеж, выведенный на бумагу, содержит объекты, изображаемые линиями различной ширины. До появления 15-й версии Автокада они обычно выполнялись на экране монитора линиями нулевой ширины, а требуемое значение ширины устанавливалось при настройке печатающего устройства. Автокад 2000 снял эту проблему, добавив новую системную переменную - LINEWEIGHT, управляющую шириной линии. Но и в более ранних версиях иногда удобно уже в чертеже задавать необходимую ширину линий, особенно если объекты расположены в одном слое. Автокад в этой ситуации позволяет использовать примитивы, обладающие шириной линии, например, полилинии, полосы, кольца. Однако часто бывает удобнее выполнить чертеж в линиях нулевой толщины, а впоследствии отредактировать нужные примитивы. Автокад предоставляет возможность осуществить это, применив команду Pedit, но подобную обработку, во-первых, воспринимают не все примитивы, во-вторых, она трудоемка и требует особой сосредоточенности в связи с необходимостью постоянно отслеживать информацию в поле сообщений.

Ниже приводится фрагмент программы, осуществляющей одновременное преобразование в примитивы, обладающие шириной, некоторого набора отмеченных примитивов, включающего линии, полилинии, дуги и окружности. Программа использовалась в версиях 11...14, может быть небесполезной и в версии AutoCAD 2000.

(defun MODES (a)

    (setq MLST '())

        (repeat (length a)

            (setq MLST (append MLST (list (list (car a) (getvar (сar a))))))

            (setq a (cdr a))

    ) ; Конец repeat

) ; Конец MODES

(defun MODER ()

    (repeat (length MLST)

        (setvar (caar MLST) (cadar MLST))

        (setq MLST (cdr MLST))

    )

)

(defun C:PLW (/ sset pl_w n type_e)

    (modes ‘(“BLIPMODE” “CMDECHO”))

    (setvar “CMDECHO” 0)

    (setvar "BLIPMODE” 1)

    (setq sset (ssget) n 0)

(setq pl_w (getdist “\nВведите ширину линии:_ “))

    (while (< n (sslength sset))

        (setq name (ssname sset n))

        (setq type_e (cdr (assoc 0 (cdr (entget name)))))

    (cond

((= type_e “LWPOLYLINE”)

    (command “pedit” name “” “W” pl_w “”))

((= type_e “LINE”)

    (command “pedit” name “” “W” pl_w “”))

((= type_e “ARC”)

    (command “pedit” name “” “W” pl__W “”))

((= type_e “CIRCLE”)

    (setq circ (entget name))

    (setq rad (cdr (assoc 40 circ)))

    (setq cen (cdr (assoc 10 circ)))

    (setq diamin (- (* 2 rad) pl_w))

    (setq diamout (+ (* 2 rad) pl_w))

    (command “donut” diamin diamout cen “”)

    (entdel name)

) ; Конец CIRCLE

(t (princ (strcat “\nОшибочный выбор !”)))

) ; Конец cond

(setq n (1+ n))

) ; Конец while

    (command “redraw”)

    (moder)

    (princ)

) ; Конец программы

В этой программе следует обратить внимание на три обстоятельства. В разделе 4.2 при описании функции cond не была упомянута важная ее особенность. Эта функция может производить проверку типа вводимых данных. В качестве последнего контрольного теста устанавливается условие Т. Если среди аргументов встречается аргумент, не соответствующий перечисленным типам, функция возвращает результат операции, приписанный этому условию. В программе plw подобную роль выполняет строка (t (princ (strcat “\nОшибочный выбор !”))). При выборе примитива, тип которого отличается от перечисленных (например эллипса), программа его не обрабатывает, сообщает об ошибке выбора, но продолжает обработку примитивов, тип которых соответствует перечисленным в программе.

Второе обстоятельство заключается в следующем. Три примитива - линия, полилиния и дуга — могут быть обработаны командой pedit, но окружность этой командой не обрабатывается. Поэтому окружность в чертеже заменяется кольцом, а исходный примитив удаляется из чертежа.

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

 

6.8. Извлечение данных из таблиц

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

Рассмотрим следующую ситуацию. В начале работы над чертежом была использована команда scr программы Format, в результате чего в пространстве модели организовано поле чертежа. Независимо от того, какие действия выполнялись оператором в течение сеанса, в чертеже уже присутствуют типы линий Acad_ISO02w100 и Acad_ISO04w100 и несколько слоев. При переходе в пространство бумаги и программном вызове необходимого формата происходит повторная загрузка тех же типов линий и слоев. При выполнении команды linetype Автокад сообщает, что соответствующий тип линий уже загружен, и запрашивает оператора, следует ли произвести перезагрузку. Этот запрос останавливает работу программы и все последующие запрограммированные действия приходится производить вручную.

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

Целый ряд параметров чертежа (например список слоев) хранится в виде таблиц. Для обработки таких таблиц используются функции tblnext и tblsearch. Обработке могут подвергаться таблицы с именами “АРРID”, “BLOCK”, “DIMSTYLE”, LAYER”, “LTYPE”, “STYLE”, “USC”, “VEW”, “VPORT”. Регистр записи имен не играет роли.

(tbInext имя_таблицы [символ] ) . Функция возвращает параметры первого элемента таблицы. Повторный вызов функции возвращает параметры следующего элемента и так далее. Выведенные параметры представляют собой присущий этому элементу список DXF-кодов и их значений. Параметр символ , если он присутствует и отличен от nil, влечет за собой возврат к первому элементу таблицы. Если же функция вызывается после tblsearch, то механизм ее действия несколько отличен от описанного (см. ниже). Выражение

(tblnext “block”)

может возвратить, например,

(   (0 . “BLOCK”)

    (2 . “L6”)

    (70.2)

    (10 0.0 0.0 0.0)

    (-2 . )

).

(tblsearch имя_таблицы имя_элемента [символ] ) . Функция отыскивает нужный элемент таблицы и возвращает его параметры. Например,

(tblsearch “block” “L6”)

возвратит тот же список, что и в предыдущем примере.

Аргумент символ закрепляет этот символ за искомым элементом:

(tblsearch “block” “L3” 6)

возвратит, например,

(   (0 . “BLOCK”)

    (2 . “L3”)

    (70. 2)

    (10 0.0 0.0 0.0 0.0)

    (-2 .

)

Если теперь вызвать функцию tblnext в формате

(tblnext “block” 6),

то она возвратит характеристики блока L3.

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

(if (tblsearch "Itype" "Acad_ISO04w100")

    (princ)

(command "linetype" "load" "Acad_ISO04w100"

    "acadiso.lin" "" "")

)

Если условие функции if соответствует T, выполняется первая функция, т.е. печатается пустая строка, в противном случае, если тип линий не загружен, он загружается в чертеж.

Следовательно, пользовательская функция sloy может быть представлена следующим образом:

(defun sloy ()

    (if (tblsearch "ltype" "Acad_ISO04w100") (princ)

      (command "linetype" "load" "Acad_ISO04w100"

        "acadiso.lin" "" ""))

    (if (tblsearch "ltype" "Acad_ISO02w100") (princ)

      (command "linetype" "load" "Acad_ISO02w100"

        "acadiso.lin" "" ""))

    (if (tblsearch "layer" "contur") (princ)

      (command "layer" "new" "contur" ""))

    (if (tblsearch "layer" "center") (princ)

      (command "layer" "new" "center"

        "I" "Acad_ISO04w100" "center"

        "c" "red" "center" ""))

    (if (tblsearch "layer" "hidden") (princ)

      (command "layer” "new" "hidden"

        "I" "Acad_ISO02w100" "hidden"

        ''c" "yellow" "hidden" ""))

    (if (tblsearch "layer" "dim") (princ)

      (command "layer" "new" "dim"

        "c" "green" "dim" ""))

      (command "layer" "c" "255" "0"

        "s" "0" "")

)

Можно обойтись и без ввода пустой строки, воспользовавшись структурой

(if (not (tblsearch "ltype" "Acad_ISO04w100"))

  (command "linetype" "load" "AcadJS004w100"

    "acadiso.lin" "" ""))