1. ПОНЯТИЕ О ПРОГРАММИРОВАНИИ. РАЗРАБОТКА АЛГОРИТМОВ ПРОГРАММ НА ПСЕВДОКОДЕ
1.1. Программы и программирование
1.2. Псевдокод - средство разработки алгоритмов
2.1. Назначение и возможности языка Автолисп
2.2. Основные понятия языка Автолисп
2.3. Разработка простейших программ на языке Автолисп
2.4. Построение параметризованных изображений
2.5. Использование программ на языке Автолисп при работе в системе AutoCAD
3. АВТОЛИСП КАК ЯЗЫК ПРОГРАММИРОВАНИЯ
3.1. Функции для работы с числами 1 +, 1-, REM, GCD, MIN, MAX
3.2. Функции для проверки условий BOUNDP, MINUSP, NUMBERP, NULL, ZEROP, EQUAL
3.3. Функции для работы с текстами STRLEN, STRCAT, SUBSTR
3.4. Функции для изменения типа данных ANGTOS, ASCII, ATOP, ATOI, CHR, FIX, FLOAT, ITON, RTOS, TRANS
3.5. Программирование управляющих структур. Функции COND, PROGN, REPEAT
3.6. Функции для работы с файлами OPEN,CLOSE
3.7. Ввод и вывод данных
4. АВТОЛИСП - ЯЗЫК ОБРАБОТКИ СПИСКОВ
4.1. Списки и их применение. Точечные пары
4.2. Создание списков. Функции LIST, CONS, APPEND, REVERSE
4.3. Выделение элементов списков. Функции типа CAR и CDR. Функции LAST, MEMBER, NTH, ASSOC
4.4. Анализ списков. Функции LISTP, ATOM, EQ
4.5. Работа со списками. Функции APPLY, FOREACH,MAPCAR
4.6. Примеры
5. АВТОЛИСП - ЯЗЫК СОЗДАНИЯ И АНАЛИЗА ИЗОБРАЖЕНИЙ
5.1. Специфика языка Автолисп как части системы AutoCAD
5.2. Объектная привязка с помощью функции OSNAP
5.3. Воздействие на экран. Функции GRAPHSCR, TEXTSCR, GRCLEAR, REDRAW, MENUCMD
5.4. Работа с системными переменными и сим вольными таблицами. Функции GETVAR и SETVAR
5.5. Формирование и анализ наборов примитивов. Функции типа SS
5.6. Работа с примитивами. Функции ENTNEXT, ENTLAST, ENTSEL, ENTDEL. Операция REDRAW над примитивом
5.7. Работа с данными примитивов и модификация примитивов. Функции ENTGET, ENTMOD, ENTUPD
5.8. Примеры
Система AutoCAD - это наиболее распространенная в настоящее
время
система
для ПЭВМ, ориентированная на автоматизированное проектирование в
машиностроении, а также в строительстве. По данным на 1991 г. в мире имелось
около 500 тыс. зарегистрированных копий AutoCAD. Можно утверждать, что на каждом
предприятии, где имеются ПЭВМ, совместимые с семейством IBM PC, и где стоят
задачи автоматизации конструкторских работ AutoCAD
используется или осваивается. Первым объектом освоения обычно является графический редактор
ACAD, составляющий основу системы. ACAD позволяет создавать, исследовать и
модифицировать геометрические модели объектов, в том числе пространственные
(трехмерные), но главным образом предназначен для автоматизации выпуска
чертежей. Любой графический редактор позволяет скомпоновать чертеж на
экране графического дисплея с помощью устройств ввода ЭВМ и вывести его на
бумажный носитель. Однако конструктор, освоивший графический редактор,
обнаружит, что выигрыш во времени по сравнению с традиционным способом
незначителен, а иногда его и вовсе нет. Экспертные оценки дают следующие цифры:
от уменьшения времени на 20% до его увеличения в 2-3 раза! В каждом конкретном
случае эффект
сокращения времени сильно зависит от характера чертежа. Перечислим возможные источники, обеспечивающие сокращение
времени. 1. Полуавтоматические простановка размеров и, главным образом,
штриховка, нанесение условных обозначений, построение рамки и штампа. 2. Наличие в чертеже повторяющихся фрагментов и в особенности в
том случае, если эти фрагменты повторяются в различных чертежах. Такая ситуация
характерна, например, для строительных чертежей. 3. Наибольший эффект достигается в том случае, когда чертеж,
созданный с помощью графического редактора, в дальнейшем неоднократно
модифицируется, причем каждая модификация затрагивает небольшую часть чертежа, а
выпускать новый чертеж приходится целиком. Суммарное время по всем модификациям
может оказаться в несколько раз меньше, чем при ручной разработке. Конструктор, освоивший графический редактор ACAD и убедившийся
на практике, что эффект от автоматизации чертежных работ незначителен, может
обнаружить, что система AutoCAD предоставляет гораздо более эффектные
возможности, чем возможности графического редактора. Оказывается, чертежи можно
получать безо всякий затрат времени и усилий на "рисование". Чертеж, который в
ручном варианте или с помощью графического редактора получается за несколько часов и даже дней, может быть
сформирован за минуты (не считая времени автоматического вывода чертежа на
графопостроитель). Более того, чертеж может получить конструктор, практически
ничего не знающий о системе AutoCAD. Но чтобы получить такой эффект, кто-то
предварительно должен был написать программу для генерации семейства сходных
чертежей. Именно этой программой теперь может пользоваться любой конструктор для
получения любого чертежа, принадлежащего данному семейству. Для создания программ, выпускающих чертежи, в системе AutoCAD
имеется мощное средство - язык AutoLISP (далее будем писать русский вариант
названия - Автолисп). Но чтобы использовать богатые возможности Автолиспа, нужно
научиться программировать на этом языке. Конструктору, ранее не знакомому с
программированием, освоить язык графического программирования Автолисп сложнее,
чем язык графического редактирования (или, как говорят, "электронный кульман").
Однако, практика показывает, что это вполне по силам конструктору. Предлагаемая читателю книга предназначена для конструкторов,
уже овладевших графическим редактором ACAD и желающих сделать следующий шаг в
использовании возможностей системы AutoCAD. Материал книги построен так, чтобы разделить этот шаг на "две
ступеньки". Гл. 1 и 2 дают начальное представление о специфике
программирования как области деятельности; знакомят с псевдокодом - средством
описания алгоритмов; дают начальные сведения о языке Автолисп, достаточные для
решения многих задач, например такой, как построение параметризуемых чертежей
(наиболее "массовая" задача для Автолиспа). Гл. 3-5 содержат систематизированное изложение функций языка
Автолисп и практически исчерпывающий материал о том, что следует знать
конструктору об Автолиспе. Изложение сопровождается примерами программ, которые подробно
обсуждаются. Разумеется, чтобы освоить язык, необходимо на нем "говорить", т.е.
самому писать и отлаживать программы на Автолиспе. Поэтому изучение этой книги
должно сопровождаться выполнением практических заданий. Книга позволит научиться программировать на Автолиспе. При
написании практических программ следует использовать фирменную документацию по
Автолиспу для имеющейся у пользователя версии AutoCAD. Рассмотрим, что такое программа (и, в частности, графическая
программа, формирующая изображение), отталкиваясь от графического редактирования -
же знакомого способа формирования изображения. Этот способ заключается
в следующем: конструктор определяет характер очередного действия;
конструктор вводит соответствующую
команду в ЭВМ;
программа ACAD интерпретирует эту команду, т.е. разворачивает ее в
последовательность команд процессора ЭВМ;
затем эта последовательность команд
выполняется;
результат выполнения отображается на экране. Таким образом, рассматриваемый способ характеризуется тем, что
конструктор мыслит дискретными командами, а вся их последовательность заранее не
определена и присутствует в его голове лишь как общий замысел, который
уточняется и корректируется в ходе создания изображения. В ACAD имеются средства создания сценариев. Сценарий - это тоже
последовательность
команд графического редактора, но составленная заранее и записанная в
виде файла на магнитном диске. Преимущество сценария в том, что его можно
использовать многократно. Однако, составить сценарий значительно сложнее, чем
работать на "электронном кульмане", так как он записывается на бумаге без
мгновенного отображения на экране. Такая работа "вслепую" приведет к тому, что в
сценарии могут остаться ошибки, которые после запуска сценария придется
отыскивать в его тексте и исправлять. Сценарий, написанный на языке команд ACAD, можно рассматривать
как частный случай программы на графическом языке программирования. Программа -
это тоже заранее составленный текст, который хранится на магнитном диске и может
быть использован для генерации изображения. Технология составления и
использования программы такая же, как и для сценария. Отличие программы (в данном случае, программы на Автолиспе) от
сценария состоит в том, что язык программирования обладает дополнительными
возможностями по сравнению с системой команд ACAD и позволяет выполнять более
сложные действия и записывать действия более компактно. Такие возможности характерны для любого языка программирования.
К ним относятся:
обращение из программы к подпрограммам (в сценарии аналогичный эффект
может быть достигнут запуском из сценария других сценариев, а также командой
INSERT - ВСТАВЬ);
компактная запись повторяющихся последовательностей действий - циклов (в
сценарии некоторым подобием цикла может служить команда ARRAY - МАССИВ); ввод данных пользователем в процессе выполнения программы, а
также вывод сообщений из программы;
проверка выполнения разного рода условий и выбор
направления действий в зависимости от результатов проверки. Последние две операции не могут быть реализованы в сценарии.
Именно они позволяют написать программу, которая в зависимости от данных,
введенных конструктором, генерирует тот или иной, каждый раз новый, чертеж. Определим несколько понятий,
связанных с созданием и использованием
программ. Язык программирования, на котором человек пишет программу, -
это не тот язык, который непосредственно воспринимается процессором ЭВМ. Поэтому
перед выполнением программы она должна быть переведена на язык команд ЭВМ. Такой
перевод осуществляется специальной программой - транслятором. Существуют два
вида транслятора: интерпретатор и компилятор. Интерпретатор считывает каждую очередную строку (команду,
функцию) программы, транслирует ее и передает на исполнение. Преимущество такого
режима в том, что программу удобно отлаживать: по ходу ее выполнения пробовать
различные варианты команд. Интерпретатор, в сущности, не требует наличия заранее
подготовленной программы в виде файла на магнитном диске: команды можно вводить
и с клавиатуры (правда, при этом введенная программа не сохраняется). В этом
смысле графический редактор ACAD можно рассматривать как интерпретатор.
Недостаток режима интерпретации - значительные дополнительные затраты времени на
трансляцию
программы в процессе ее выполнения. Компилятор позволяет разделить во времени процесс трансляции и
процесс выполнения программы. Если программа, предназначенная для интерпретации,
хранится только в одном виде - в том, который создал человек на языке
программирования, то при использовании компилятора дело обстоит сложнее. Учтем,
что программа может собираться из отдельных, относительно самостоятельных
(возможно даже разработанных ранее для других программ) "строительных блоков",
которые называются модулями. В связи с этим программа, написанная человеком,
может подвергнуться следующим превращениям:
из исходных модулей, т.е. модулей, написанных на
языке программирования, транслятор формирует объектные модули; из набора объектных модулей специальная программа, входящая в
состав операционной системы, формирует загрузочный модуль, готовый к
выполнению. Эти превращения осуществляются заранее и притом только один
раз, а не при каждом выполнении программы, что сокращает время ее
реализации. Таким образом, программа на магнитном диске может хранится в
виде: набора исходных модулей, удобного для внесения изменений в
программу; набора объектных модулей, удобного для построения новых
программ; загрузочного модуля, который используется каждый раз, когда
нужно получить результаты работы программы. Автолисп работает в режиме интерпретации, хотя существует и
компилятор Автолиспа (который здесь не рассматривается). Технология программирования существенно отличается от
технологии создания чертежа с помощью "электронного кульмана" и включает
следующие этапы: постановку задачи, разработку алгоритма, написание программы,
ввод программы в ЭВМ, отладку программы. Постановка задачи заключается в четком определении всех деталей
и особенностей задачи, которая должна быть решена на ЭВМ: входных и выходных
данных, формул, условий, правил выбора вариантов и т.д. [1]. Например, если
создается программа для семейства чертежей, то постановка задачи может включать
такие работы, как: подбор чертежей всех деталей данного семейства; составление на
их основе чертежа комплексной детали; определение условий, которые влияют на выбор конкретной
конфигурации детали из комплексной детали; определение постоянных размеров на
чертеже; определение параметров, которые должны вводиться конструктором
при работе с программой; описание соотношений, позволяющих получить все переменные
параметры на основе параметров, вводимых конструктором; разделение текстовой части чертежа на постоянную и переменную
части, определение правил ввода переменных частей текста и связывания постоянных
и переменных частей; перечисление сообщений, которые программа должна выдавать
конструктору. Таким образом, на этапе постановки задачи точно определяется,
что будет делать программа. При разработке алгоритма решаются два следующих вопроса: как
будет устроена программа и как она будет выполняться. На этом этапе определяется
состав модулей программы и разрабатываются алгоритмы каждого модуля. Алгоритм - это подробная схема программы. Можно даже считать,
что алгоритм это уже программа, но написанная на языке, недостаточно
формализованном для того, чтобы ее мог обработать транслятор. Более подробно
разработка алгоритмов рассмотрена в п.1.2. Написание программы - это перевод алгоритма на язык
программирования. Программа записывается на бумаге и тщательно проверяется. Ввод
программы в ЭВМ осуществляется, как правило, с клавиатуры при использовании
программы - редактора текста (программы типа Norton Editor, Lexicon, WordStar и
др.). В результате создается файл на магнитном диске. (Если предполагается
использование компилятора, то этот файл или набор файлов является исходным
модулем или набором исходных модулей программы.) Если исходный модуль программы не содержит ошибок, то программу
можно запускать на выполнение. Однако, чаще всего ошибки имеются, поэтому
необходим этап отладки программы. Отладка - это поиск и устранение ошибок в
программе. После того как программа отлажена, т.е. получены первые
результаты, полностью удовлетворяющие пользователя, работа программиста может
считаться законченной. Теперь программа, хранящаяся на магнитном диске, в любое
время может быть вызвана на выполнение любым пользователем. В процессе
выполнения программы пользователь ведет диалог с ЭВМ: принимает сообщения программы и вводит в программу
данные. Короткую простую программу можно написать непосредственно по
постановке задачи без предварительной разработки алгоритма. Однако, реальную
программу так же трудно создать без алгоритма, как трудно изготовить достаточно
сложную деталь без чертежа. Правильность алгоритма - залог правильной работы
программы. Показателем правильности алгоритма может служить его понятность, а
понятным он будет, если будет простым. Итак, основное противоречие, которое должен разрешить
разработчик алгоритма - это противоречие между объективной сложностью задачи и
требованием простоты алгоритма. Сложность задачи может привести к тому, что
алгоритм станет, во-первых, длинным, а во-вторых, запутанным: с множеством
условий, выборов, разветвляющихся и пересекающихся цепочек действий. Разрешить
это противоречие можно методом последовательной детализации алгоритма
"сверху-вниз". Такой же метод используется и при проектировании технических
объектов, когда, например, сначала прорабатывается общий вид объекта, затем -
узлы, далее -детали. Для записи алгоритмов естественный язык, как правило,
оказывается неудобным, поэтому используются специальные средства. Наиболее,
распространенными являются блок-схемы, HIPO-диаграммы, псевдокод [1-3]. В этом параграфе рассматривается псевдокод, т.к. описание
алгоритма на псевдокоде в наибольшей степени приближается к тексту программы на
языке программирования. Ряд языков программирования, в том числе Автолисп, имеют
в составе своих средств полные аналоги конструкций псевдокода. Таким образом,
изучение псевдокода - наиболее простой путь к изучению языка программирования
для начинающего. (Собственно, само название "псевдо-код" является синонимом
названия "почти программа".) Основные идеи, заложенные в псевдокоде, сводятся к
следующему: алгоритм на псевдокоде делится на сегменты, каждый сегмент
соответствует относительно самостоятельной законченной функции и может
детализироваться в последующих сегментах: таким образом обеспечивается
последовательная детализация алгоритма "сверху-вниз", а каждый сегмент в
отдельности удовлетворяет критерию понятности; правила псевдокода предусматривают удобную организацию
управляющих структур типа "Принятие решения", "Цикл", что устраняет
"запутанность" и повышает понятность сегментов; оформление алгоритма на псевдокоде предусматривает средство
повышения наглядности (а следовательно, понятности) - ступенчатую запись
текста. Поясним назначение конструкций типа "Принятие решения" и
"Цикл". Наиболее простым и понятным описанием действий программы является
последовательная цепочка обозначений простых действий. Но такие "линейные"
программы получаются редко. Например, если приходится выбирать конфигурацию
конкретной детали из комплексной детали, то это означает ветвление программы.
"Принятие решения" -
это процедура проверки выполнения какого-либо условия или комплекса
условий и выбора направления ("ветви") дальнейших действий. Если в программе требуется много раз подряд выполнить одну и ту
же последовательность действий, но каждый раз с новыми данными или с несколько
изменившимися; условиями, то такая процедура называется циклом. Однократное
выполнение последовательности действий называется шагом цикла. Для каждого цикла
должно существовать условие окончания или выхода из цикла. Например, количество
шагов цикла может быть известно заранее. В других случаях это условие
формируется и проверяется на каждом шаге цикла. Пример - формирование детали
типа "вал", имеющей несколько ступеней: в этом случае можно описать
последовательность действий по изображению на чертеже одной ступени и повторить
эту последовательность в цикле. Основные правила псевдокода сводятся к следующему. 1. Описание действий на псевдокоде разделяется на сегменты.
Каждый сегмент содержит описание законченной функции. Желательно, чтобы сегмент
был обозрим (т.е. занимал не более одной страницы) и чтобы для его понимания не
требовалось привлекать другие сегменты. Сегмент имеет вид: Наименование функции Описание функции КОНЕЦ Здесь КОНЕЦ - служебное слово, или слово-ограничитель. Здесь и
далее в тексте на псевдокоде слова-ограничители будут выделяться заглавными
буквами. Наименование функции -текст на русском языке, служащий в качестве
заголовка сегмента. Желательно, чтобы наименование начиналось с глагола в
повелительном наклонении и подчеркивало, что требуется сделать в данном
сегменте. Наименование функции может быть использовано в другом сегменте для
ссылки на данный сегмент, т.е. для обозначения последовательности действий,
описанной в данном сегменте. Описание функции - это тоже текст, раскрывающий
характер действий и условия их выполнения. Текст может быть записан как на
естественном языке, так и любым другим способом (например, в виде
последовательности математических формул). Для отделения последовательно
выполняемых действий друг от друга используются привычные средства: красная
строка, простановка номера и т.д. 2. Для записи принятия решений и циклов предусмотрены
управляющие структуры. С ними и связаны правила записи, которые отличают
псевдокод от обычного текста. Основных управляющих структур четыре. 2а. Структура ЕСЛИ-ТО-ИНАЧЕ используется, если нужно описать
проверку выполнения условия и выбор одного из двух действий в зависимости от
выполнения или невыполнения данного условия. Структура оформляется следующим
образом: ЕСЛИ Обозначение условия ТО Обозначение действий А ИНАЧЕ Обозначение действий В ВСЕ ЕСЛИ Структура ЕСЛИ-ТО-ИНАЧЕ подразумевает, следующее. Проводится
проверка обозначенного условия. Если оно выполняется, то выполняются "Действия
А". Если условия не выполняются, то выполняются "Действия В". Вторая часть
структуры (после слова ИНАЧЕ) может быть опущена. В этом случае, если условие не
выполняется, то не выполняются никакие действия. Пример: ЕСЛИ габаритный размер L >100 TO Выбрать масштаб 1:10 ИНАЧЕ Выбрать масштаб 1:5 ВСЕ ЕСЛИ 2.б Структура ВЫБОР используется, если существует N вариантов
действий, причем выбор варианта зависит от значения некоторой переменной (т.е. в
отличие от предыдущей структуры структура ВЫБОР реализует многопозиционный
переключатель). Структура оформляется следующим образом: ВЫБОР Обозначение переменной ИЗ СЛУЧАЙ 1 (Значение переменной 1) Обозначение действий А СЛУЧАЙ 2 (Значение переменной 2) Обозначение действий В СЛУЧАЙ N (Значение переменной N) Обозначение действий Z ВСЕ ВЫБОР Структура ВЫБОР подразумевает следующее. Имеется некоторая
"переменная", которая может принимать несколько значений, и для каждого значения
имеется свой вариант действий. Проводится проверка значения переменной. Далее
ищется вариант действий - "случай", соответствующий данному значению переменной.
Если такой случай найден, то выполняются действия, соответствующему этому
случаю. Прочие действия, описанные в структуре ВЫБОР, не выполняются. Пример: ВЫБОР по типу детали ИЗ СЛУЧАЙ 1 (тип детали = вал) Сформировать чертеж вала СЛУЧАЙ 2 (тип детали = фланец) Сформировать чертеж фланца СЛУЧАЙ 3 (тип детали = колесо) Сформировать чертеж колеса ВСЕ ВЫБОР 2в. Структура ПОКА-ЦИКЛ используется, если последовательность
действий требуется повторять многократно, т.е. в цикле. Действия в цикле
повторяются до тех пор, пока выполняется некоторое условие. Причем цикл
начинается с проверки условия, и если оно перед началом цикла не выполняется, то
действия в цикле не выполняются ни разу. Структура оформляется следующим
образом: ПОКА Обозначение условия ЦИКЛ Обозначение действий ВСЕ ЦИКЛ ПОКА 2г. Структура ЦИКЛ ДО используется для тех же целей, что и
предыдущая структура. Отличие состоит в том, что действия в цикле повторяются до тех пор, пока не будет
достигнуто выполнение условия; проверка условий происходит после выполнения действий, т.е., по
крайней мере, один шаг цикла будет сделан в любом случае. Структура оформляется следующим образом
: ЦИКЛ ДО Обозначение условия Обозначение действий ВСЕ ЦИКЛ ДО Отметим, что любой из этих двух структур было бы достаточно для
описания любого цикла. Однако, в одних случаях удобнее оказывается ПОКА-ЦИКЛ, в
других - ЦИКЛ ДО. Пример построения цикла: Ввести количество ступеней вала N I=1 ЦИКЛ ДО обработки последней ступени (I=N) Ввести параметры очередной 1-й ступени Сформировать изображение 1-й ступени Увеличить I на единицу ВСЕ ЦИКЛ ДО В перечисленных структурах "Обозначение действий" следует
понимать как последовательность, содержащую наименования простых действий или
функций (сегментов) и (или) управляющие структуры псевдокода. Таким образом,
структуры могут быть вложены одна в другую. Это позволяет описать любую логику
действий с помощью указанных четырех структур. 3. Помимо управляющих структур в псевдокоде существуют правила
ступенчатой записи, которые также повышают формализованность и наглядность
текста на псевдокоде по сравнению с обычным текстом. Правила ступенчатой записи
состоят в следующем. За. Каждое обозначение действия в последовательности должно
начинаться с новой строки. 3б. Каждое
последующее обозначение действия должно начинаться с той же позиции, что и
предыдущее обозначение. Зв. В сегменте описание функции должно смещаться на три позиции
вправо относительно наименования функции (и слова КОНЕЦ), как показано выше. Зг. При записи управляющих структур должны соблюдаться сдвиги
на три позиции обозначений действий относительно служебных слов. Правила сдвига
наглядно представлены в приведенных выше образцах. Ступенчатая запись позволяет легко выделить управляющие
структуры, что особенно важно при использовании вложенных структур (см. пример,
приведенный ниже). 4. Наряду с подчиняющимся определенным правилам описаниям
действий, в псевдокоде допускается запись любых пояснений, справочных данных и
тому подобных в форме комментариев. Правила записи комментариев не
оговариваются, однако, предлагается так выделять комментарии, чтобы они не были
восприняты как описания функций (например, заключать их в скобки). Пример фрагмента алгоритма, содержащего два последовательных
сегмента: Разработать чертеж детали. Выдать на экран перечень групповых деталей. Выбрать тип групповой детали (действие
конструктора) ВЫБОР по типу детали ИЗ СЛУЧАЙ 1 (тип детали - тело вращения) Выдать на экран перечень деталей ТВ Выдать подтип детали из перечня (действие конструктора) ВЫБОР по подтипу детали ИЗ СЛУЧАЙ 1 (подтип - вал) Сформировать чертеж вала СЛУЧАЙ 2 (подтип - фланец) Сформировать чертеж фланца ВСЕ ВЫБОР СЛУЧАЙ 2 (тип детали - корпус) Проектировать корпус СЛУЧАЙ 3 (тип детали - плоская) Проектировать плоскую деталь ВСЕ ВЫБОР Сформировать рамку и штамп КОНЕЦ Сформировать чертеж вала Ввести количество ступеней вала N (действие
конструктора) I=1 ПОКА не сформирована последняя ступень (I>N) ЦИКЛ Ввести параметры 1-й ступени (действие
конструктора) Сформировать изображение 1-й ступени Увеличить I на единицу ВСЕ ЦИКЛ ПОКА Ввести указание о наличии отверстия (действие конструктора)
ЕСЛИ отверстие имеется ТО Сформировать изображение отверстия ВСЕ ЕСЛИ Указать базу для простановки размеров (действие
конструктора) Проставить размеры ступеней вала у Проставить диаметры КОНЕЦ (Далее предполагаются другие сегменты, в которых сущность
действий должна быть раскрыта полностью с учетом всех подробностей.) Основные правила псевдокода достаточно просты и без труда могут
быть освоены на практике человеком, не знакомым с программированием. Описание
действий на псевдокоде представляет собой иерархическую систему сегментов, где
наименование функции, встретившееся в последовательности действий внутри
сегмента верхнего уровня, является заголовком сегмента нижнего уровня, т.е.
раскрывается в этом сегменте (как в предыдущем примере). Таким образом,
псевдокод обеспечивает иерархическое описание "сверху-вниз". Трудность (или искусство) описания действий на псевдокоде
состоит в том, что необходимо творчески использовать принцип сегментации,
добиваясь того, чтобы каждый сегмент был максимально понятен без обращения к
другим сегментам. Этого можно достичь путем последовательной декомпозиции
задачи. Первоначально (в первом сегменте) действия описываются от начала до
конца, при этом отражается один или несколько принципиальных моментов, а другие
(возможно, очень важные) детали остаются непроработанными. При этом
предполагается, что нераскрытые действия будут раскрыты в следующих сегментах, а
пока известны результаты этих действий. Такой же подход применяется по отношению
к каждому следующему сегменту. Прежде чем приступить к изучению Автолиспа, рекомендуем Вам
поупражняться в написании алгоритмов на псевдокоде. Попытайтесь описать алгоритм
той графической программы, которую Вы хотели бы создать. Отметим в заключение, что структуре ЕС-ЛИ-ТО-ИНАЧЕ в Автолиспе
соответствует функция IF, структуре ВЫБОР - функция COND, структуре ПОКА-ЦИКЛ -
функция WHILE. Графический язык программирования Автолисп является расширением
языка программирования Лисп. Лисп - это язык высокого уровня, ориентированный на
обработку списков, который выбран в качестве базового потому, что графические
примитивы (начиная, с точки), блоки, наборы примитивов и блоков удобно
представляются в виде списков. В составе системы AutoCAD поставляется интерпретатор с языка
Автолисп (входящий в модуль ADE-3). Если при генерации AutoCAD интерпретатор
Автолиспа был подключен, то он загружается в оперативную память после запуска
графического редактора ACAD и доступен в течение всего сеанса работы с ACAD.
Таким образом, графический редактор ACAD и интер-претататор Автолиспа
представляют собой единую систему: любая функция Автолиспа может быть вызвана из
графического редактора и любая команда редактора может быть использована в
программе на Автолиспе. Возможности применения Автолиспа весьма широки и разнообразны.
Наиболее характерны следующие классы применений. 1. Программирование чертежей с параметризацией. Создается
программа, позволяющая при каждом обращении к ней формировать новый чертеж,
отличающийся от предыдущих 26 чертежей, построенных этой же программой,
размерами, а также, возможно, и топологией:
могут появиться новые элементы обогащения,
сечения, измениться текстовая часть чертежа и т.д. Время получения чертежа с
помощью такой программы может быть в десятки раз меньше времени, необходимого
для его создания с помощью редактора ACAD, и, что не менее важно, получить
чертеж сможет любой конструктор, не знакомый ни с командами ACAD, ни с
Автолиспом. 2. Создание и использование графических баз данных. Если
накоплено большое количество чертежных файлов, программ на Автолиспе,
соответствующих чертежным фрагментам, деталям, узлам, то их можно в некотором
смысле считать графической базой данных. Программы на Автолиспе в сочетании с
пользовательскими меню могут организовывать просмотр, поиск, подключение к
объектам их частей и т.п. Тогда работа конструктора в системе AutoCAD будет
сводиться к поиску нужных объектов (сборочных единиц, деталей) или частей
чертежа, обращению к соответствующим Лисп-программам и ответам на вопросы этих
программ. Отметим одно очень важное обстоятельство:
хранение графических данных в виде
набора программ на Автолиспе дает возможность в десятки и сотни раз сократить
требуемую память на магнитном диске по сравнению с памятью, необходимой для
хранения чертежных файлов ACAD, так как, во-первых, одна программа позволяет
получить не один, а множество чертежей, во-вторых, текст программы на Автолиспе
занимает на порядок меньше памяти, чем DWG-файл, который может быть получен в
результате работы этой программы. 3. Анализ и (или) автоматическое преобразование изображений.
Программа на Автолиспе может воспринимать чертеж на экране, построенный с
помощью графического редактора и обсчитывать его; например, могут быть решены
такие задачи:
обнаружение пересечений трубопроводов, разведенных в
пространстве;
подсчет суммарной длины трасс;
расчет центра масс и моментов инерции;
выдача на печать спецификации
по сборочному чертежу и т.п. Программа также может быстро осуществить преобразование
изображения, на которое при работе в графическом редакторе пришлось бы затратить
значительное время, например:
заменить все вставки одного типа на вставки
другого типа из какого-либо чертежного файла;
перенести все объекты с одного слоя на другой
слой; повернуть
все блоки на заданный угол - каждый относительно своей базовой точки и т.п. 4. Расширение системы команд графического редактора ACAD и
построение на основе универсального редактора специализированных САПР, имеющих
гораздо более простой и естественный для пользователей язык, ориентированный на
конкретную предметную область. В этом случае хорошим дополнением к Автолиспу
является возможность создания пользовательских меню. В языке Автолисп (версия 10) определены около 150 различных
операций, которые называются встроенными функциями. По назначению их можно подразделить на функции: для работы с числовыми данными, реализующие шесть
арифметических операций, а также наиболее часто используемые математические
функции. Эти функции позволяют вычислять координаты примитивов, рассчитывать
длины, площади и т.п. для проверки выполнения различных условий: операции сравнения,
булевские функции ("и", "или", "не") и др., а также функции, организующие
ветвления по условиям. С помощью этих функций можно, например, получать
топологически различные чертежи из одной программы; для работы со строками текстов: формирование, сцепление,
сравнение строк, выделение символов из строки и т.п. Эти функции позволяют,
например, формировать технические требования на чертеже путем совмещения
переменной и постоянной частей. для ввода с клавиатуры, устройств указания, и вывода на экран и
принтер, с помощью которых реализуется диалог пользователя с программой. Вывод
на принтер позволяет получать из программы текстовые документы, например,
спецификацию по сборочному чертежу; для создания и чтения текстовых файлов на магнитных дисках,
благодаря чему обеспечивается возможность связи по данным между различными
программами на Автолиспе, а также между программой на Автолиспе и программами на
других языках. Например, в программу на Автолиспе в качестве параметров могут
быть введены результаты расчетов из программы на языке С; характерные для всех языков программирования и обеспечивающие
компактное описание действий в программе за счет таких конструкций, как циклы и
подпрограммы; характерные для языков типа Лисп: создание, анализ и
преобразование списков. Поскольку данные о графических объектах-примитивах и
блоках представляются в виде списков, то эти функции используются для обработки
внутрипрограммных описаний графических объектов. Далее перечислены функции, определяющие специфику языка
Автолисп, т.е. функции, связанные с графикой и работой в среде графического
редактора ACAD: для внутрипрограммных геометрических построений; важнейшая из
этих функций - определение точки, заданной через другую точку, угол луча и
расстояние по лучу. С помощью этой функции можно формировать из программы
опорные точки примитивов чертежа, задавая их параметры с помощью переменных; для приема геометрических данных, т.е. данных, которые могут
задаваться перемещением курсора на экране: точки, угла, расстояния; для выделения примитивов построенного на экране чертежа и
наборов примитивов, выделения и изменения характеристик примитивов и блоков,
анализа и измнения системных переменных и содержимого символьных таблиц
ACAD; для включения в программу любой команды ACAD. Причем аргументы
и опции команды могут быть заданы не только из программы, но и в режиме
графического диалога в точности так, как если бы эта команда выполнялась просто
в редакторе ACAD. Из всего многообразия функций Автолиспа в этой главе
рассмотрены 37, среди них - наиболее часто употребимые представители различных
классов функций (но не всех). Знания этих функций в совокупности со знанием
команд ACAD достаточно для программирования несложных параметризованных
чертежей. Соглашения по форме записи правил языка. В дальнейшем
изложении приведены правила построения выражений языка Автолисп. Введем
некоторые "правила описания этих правил", а именно поясним смысл символов
::=; < > (угловые скобки); [] (квадратные скобки); ...
(многоточие). Все эти символы не встречаются в выражениях Автолиспа, и поэтому
их можно использовать для записи правил Автолиспа. ::= - означает "это есть"; < объект > - означает, что на данное место можно
подставить любой объект указанного класса; [(объект >] - означает, что объект может присутствовать, а
может и не присутствовать в данном выражении; < объект >... - означает, что объектов данного класса
может быть несколько. Использование таких обозначений поясним на понятном всем
примере: сформулируем правило обычной записи целых чисел в виде: < целое >::=[-]< цифра >... Программа. Программа на языке Автолисп представляет собой
построенный с помощью любого редактора текстов с соблюдением правил языка
текстовый файл, который хранится на магнитном диске под определенным именем. Он
может быть загружен в ОЗУ в ходе сеанса графического диалога в системе ACAD и
может быть выполнен путем соответствующего ответа на подсказку
ACAD COMMAND: (в русской версии - Команда) Программа - это последовательность функций Автолиспа и функций,
определенных самим программистом. Помимо функций в тексте программы могут присутствовать
комментарии. Комментарий -это любой текст (он может быть и на русском языке),
начинающийся со знака ";". Комментарием считается весь текст от знака ";" до
конца . строки. Комментарии не обрабатываются интерпретатором, а служат только
для лучшего понимания текста программы читателем. Атом (типы данных в Автолиспе). Атомы -это элементарные
объекты, из которых формируются выражения Автолиспа. В данной главе рассмотрены
атомы следующих типов: константы целые, действительные, текстовые (строковые), а
также переменные (символические имена). < целая константа >::=[+/-]< цифра
>... Здесь +/- означает плюс или минус. Целые -числа могут
задаваться в пределах от -32768 до 32767. Целое число без знака - от 0 до
65535. действительная константа >:: = [+/-]< цифра > ...
.< цифра >... Здесь точка отделяет целую часть от дробной части. Для чисел с большими порядками удобна запись [+/-]< цифра >....< цифра > Е[-] < цифра > [
< цифра > ] Здесь "Е" означает "10 в степени", а показатель степени
ставите^ после Е. В Автолиспе определена также константа, обозначаемая PI и
имеющая значение 3.1415926. < текстовая константа >::='< символ
>..." Длина текстовой константы не более 100 знаков. Если в тексте
встречается знак "\",то он должен быть удвоен (т.е. вместо "\" должно быть
записано "\\". Это связано с тем, что символ "\" используется для ввода
управляющих символов: \n - перевод строки, \r - возврат каретки, \t -
табуляция. <переменная> ::=< символ >... Переменные формируются из любого количества символов, кроме
знаков ().,":' пробел, перевод строки. Первым символом должна быть буква.
Переменная, так же как и в математике, - это объект, имеющий имя и значение. Имя
служит для обозначения объекта. Правила записи переменных, приведенные выше,
это, по сути дела, правила записи имен. Конкретное значение переменная
приобретает в процессе выполнения программы, например, переменная, имеющая имя
XI, может последовательно принимать значения 10,
12.3, "НАЧАЛО", NIL ... Помимо перечисленных атомов определен еще "пустой атом",
обозначаемый как NIL, что означает "ничего", т.е. атом, не имеющий никакого
значения. Примеры правильной записи данных: 0 -123 0.0 целые
константы; 12.3 -12.34Е8
действительные константы; "ABCD" "Укажите точку" "\nУкажите
точку" текстовые
константы; А1 ABCD CROSS_POINT_2
переменные (имена переменных); NIL - пусто. Примеры неправильной записи данных: -100000 - целая константа за пределами допустимых
значений; .25 - действительная
константа без целой части; 25. - действительная константа без дробной части; "AB\CD" - управляющий символ "\С" не определен, символ "\" должен повторяться дважды; "ABCD - отсутствуют закрывающие кавычки; АВCD - такая запись возможна (см. ниже), но это уже не имя
переменной, т.к. внутри имеется пробел. Список. Составной элемент программы на Автолиспе, состоящий из атомов
или других списков, отделенных друг От друга пробелами, называется списком. Он
всегда заключается в скобки,таким образом: < список> ::=([< элемент >...])
<список> здесь < элемент >::= < атом > Как следует из приведенной записи, возможен список и без
элементов, т,е. список вида (). Такой список имеет значение NIL. Примеры правильной записи списков: (Al Bl Cl) - атомами
являются переменные; ("А" "В" "С") - атомами являются текстовые константы; (А 10.0 20.0 NIL) - "смешанный" список: второй и третий атомы - действительные числа, последний -
пусто. Примеры неправильной записи списков: А В С - отсутствуют скобки; (А (В С) - число закрывающих скобок меньше числа открывающих -
наиболее распространенная ошибка при написании программ на Автолиспе. Функция. Частным случаем списка является функция, определяемая следующим
образом: < функция >::=(< имя функции >[< аргумент
>...]) Здесь <имя функции > - это символическое имя. Каждая
функция имеет свое, связанное с ней имя. Аргументы функции - это выражения, построенные по правилам
Автолиспа, в том числе другие функции. Для каждой конкретной функции характерны
определенное количество, типы и порядок следования аргументов. Примеры функций: 1) (COS
<угол>) Здесь COS - имя функции для вычисления косинуса; <угол> - аргумент, который может быть действительной
константой или целой константой или переменной. 2)(+
<число> <число>.„) Здесь знак "+" - имя функции для вычисления суммы; < число -
действительная или целая константа или переменная. Из записи следует, что аргументов этой функции может быть два и
более. Как указывалось; программа на Автолиспе -это последовательность
функций. Выполнение программы заключается в том, что интерпретатор читает текст
очередной функции и после завершения чтения выполняет ее. В ходе выполнения
функции могут происходить какие-то события, видимые пользователем, например
будет появляться или изменяться изображение на экране. Помимо всех видимых и
невидимых результатов выполнения функции после ее завершения появляется
некоторое новое значение (число, список, NIL и др.), которое .может быть
использовано программой. В терминологии Автолиспа это называется так: "Функция
возвращает значение". Пример: (COS(+ABC)) В этом примере функция сложения производит суммирование трех
слагаемых, обозначенных именами А, В, С, и возвращает результат, имеющий форму
числа и равный сумме А+В+С. Этот результат используется программой, а именно -
подставляется в качестве аргумента в функцию COS. В свою очередь, функция COS
возвращает свой результат (новое число), который тоже может быть использован. В
дальнейшем в книге при описании каждой конкретной функции будут приведены ее
имя, характеристика аргументов и возвращаемое значение. Описание функции. Все функции, которые Вы можете
использовать в своей программе, можно разделить на три группы: первая - встроенные функции Автолиспа, т.е. те функции, имена
которых и правила работы с которыми изложены в соответствующем фирменном
руководстве по Автолиспу; вторая - функции, которые Вы сами придумали и описали в своей
программе средствами Автолиспа; третья - функции, описанные в других программах, которые Вы
можете подключить при выполнении своей программы. Описание новой функции в программе должно предшествовать
обращению к этой функции. Описание новой функции в Автолиспе -это тоже функция,
имеющая имя DEFUN: <описание функции >::=(DE
FUN <имя функции> ([ < аргумент >...][/ <локальная переменная >...])
< выражение >) Здесь <имя функции > - это имя, которое Вы придумали для
новой функции. Список аргументов - это список имен, обозначающих те данные,
которые будут посылаться в функцию перед ее выполнением. Локальные
переменные - это
переменные, определение которых действует только внутри описываемой функции
(т.е. Вы можете одним и тем же именем обозначать совершенно разные данные в
разных функциях, и это не приведет ни к каким конфликтам, если эти имена
определены Вами как локальные)
. Как аргументы, так и локальные переменные могут
и отсутствовать, но скобки () после имени функции обязательны. < Выражение > - это любая запись, выполненная по правилам
Автолиспа. Именно выражение показывает, какие действия должна выполнять
описываемая функция. Значение, возвращаемое функцией DEFUN
- это имя описанной функции, т.е.
после выполнения функции DEFUN можно в любом месте программы обращаться к
описанной новой функции по ее имени. Примером использовав ния функции DEFUN
является приведенная ни-\ же простая программа на Автолиспе. ;Программа 1. Вычисление суммы SIN(A) + COS(A) (DEFUN SINCOS (A) ;
имя функции и список ; аргументов ( + (SIN A) (COS А)); выражение: SIN(A) + COS(A)
) ;конец программы -
закрывающая скобка")" Программа 1 состоит из единственной функции DEFUN. Эта функция
описывает придуманную нами функцию, которую мы назвали SINCOS. Функция SINCOS имеет один аргумент, который мы обозначили
именем А. Выражение Автолиспа в составе функции показывает, что должна делать
данная функция. Любой текст от знака";" до конца строки - комментарий для
читателя. Текст Программы 1 можно набрать в сеансе работы с ACAD в ответ
на приглашение COMMAND:. Этот текст будет обработан интерпретатором Автолиспа. В
результате такой обработки, т.е. в результате выполнения функции DEFUN, будет
возвращено имя функции SINCOS, а значит эта функция в дальнейшем может быть
выполнена. Для выполнения функции SINCOS можно в ответ на очередное
приглашение ACAD набрать строку (SINCOS 0) Тем самым интерпретатору Автолиспа будет задана новая
программа, состоящая из од-. ной функции SINCOS с определенным значением
аргумента, в нашем случае равным нулю. Эта функция возвращает ' число, равное
SIN(0)+COS(0), в нашем случае 1.0. Это число будет отображено на экране
дисплея. Подробнее об использовании программ Автолиспа в среде ACAD -
см. в п. 2.5. Программирование вычислений. Математические функции.
Для
программирования вычислений можно использовать следующие функции: + (сложение);- (вычитание);* (умножение);/(деление);ЕХРТ
(возведение в степень); ABS (определение модуля числа); SIN (синус); COS (косинус); ATAN (арктангенс); SORT (квадратный корень); ЕХР (экспонента); LOG (натуральный логарифм); и некоторые другие (см. п. 3.1.).
Аргументы этих функций -. целые или действительные числа. Углы
выражаются в радианах. Функции "+","-", "*","/" могут иметь два аргумента и
более, при этом у функции "-" первый аргумент обозначает уменьшаемое, остальное
-вычитаемое, у функции "/" первый аргумент -делимое, остальные - делители.
Функция ЕХРТ должна иметь два аргумента (первый - основание, второй - показатель
степени), остальные функции должны иметь один аргумент. Тип возвращаемого значения зависит от функции и типов
аргументов. Функции SIN, COS, ATAN, SORT, EXP, LOG всегда возвращают
действительные числа. Использование команд ACAD в Автолиспе. Функция COMMAND.
Любая команда графического редактора ACAD может быть включена в программу на
Автолиспе, что позволяет строить изображения из программы автоматически или с
участием пользователя. Это делается с помощью функции COMMAND, имеющей
вид (COMMAND * < имя команды >" [ < аргумент
>...]) Здесь <имя команды > - имя требуемой команды,
определенной в данной версии ACAD. Если командой предусмотрены аргументы, то их значения
перечисляются. Аргументами могут быть координаты точек, опции и др. Аргументы
перечисляются в той последовательности, в которой Вы задавали бы их, формируя
команду для ACAD в режиме диалога. В качестве аргументов могут использоваться
выражения Автолиспа. При этом необходимо, чтобы значение, возвращаемое
выражением, соответствовало тому значению, которого требует данная команда ACAD.
В качестве аргументов могут быть заданы переменные, если значения этих
переменных были ранее определены в программе, или непосредственно заданы
значения. Такие значения
необходимо заключать в кавычки. Слово PAUSE в качестве аргумента обозначает переключение в
режим графического диалога, т.е. после чтения PAUSE команда ожидает одного
аргумента (опцию, точку и др.) с клавиатуры, от "мыши" и тд., в точности так,
как если бы команда выполнялась просто в ACAD. Дополнительные сведения о функции COMMAND: в одной функции может вызываться не одна команда, а
последовательность команд; (COMMAND "") соответствует вводу пробела с клавиатуры; (COMMAND) равносильно нажатию клавиши CTRL/C. Примеры: (COMMAND "LINE" "1,1" "10,10" "") ; Эта функция строит линию по точкам 1,1 и
10,10 (COMMAND "CIRCLE" "2P" "10,10" "20,20") ; Строится окружность по точкам на концах
диаметра (COMMAND "CIRCLE" "10,10" PAUSE "LINE" "10,10" "10,5") В последнем примере строится окружность с центром в точке 10,10
и с радиусом, задаваемым пользователем, затем строится ломаная линия: две первые
точки ее задаются из программы, а для задания последующих предполагаются
действия пользователя, как при выполнении команды LINE в ACAD. Любую из этих функций можно набрать в ответ на приглашение
ACAD, и соответствующая команда будет выполнена. Обратите внимание на то, как вводятся координаты точки в
функции COMMAND: координаты X и Y отделяются запятой, и все эти заключается в
кавычки. (COMMAND "CIRCLE" PC R) В этой функции точка центра и радиус окружности заданы
переменными. Такая строка не может быть выполнена отдельно, а только в составе
программы, где перед данной функцией выполняются другие функции, определяющие
конкретные значения PC и R. Такие программы будут рассмотрены ниже. Использование переменных. Функция SETQ. Функции GET. Если при выполнении функции какой-либо аргумент представлен
переменной, то этой переменной должно быть ранее присвоено значение (число,
строка текста, список и др.). Основное средство для присвоения значений
переменных - функция SETQ: (SETQ < переменная! >< выражение! >
[<перемен-ная2> <выражение2>]„.) Функция действует следующим образом: выполняются действия,
задаваемые выражением 1, и результат, возвращаемый этим выражением, становится
текущим значением переменной 1. Если имеются другие "пары", то с ними функция
поступает аналогично. Функция SETQ возвращает значение последнего выражения. Примеры: (SETQ А 10.0)
; записывает 10 в А (SETQ В (+ 123)) ;
записывает в В результат сложения ; 1, 2 и 3, т.е. 6
(SETQ A 1 В 2 С 3)
; записывает 1 в А, 2 в В, 3 в С, ; возвращает значение 3
; Поэтому (SETQ D (SETQ А 1 В 2 С 3)) ; записывает 3 в
D Любую из этих функций вы можете набрать в ответ на приглашение
ACAD. Для ввода значений переменных пользователем служат функции типа
GET. К ним относятся: GETINT - ввод целого числа; GETREAL - ввод вещественного числа; GETSTRING - ввод
строки текста; GETPOINT - ввод точки; GETDIST - ввод расстояния; GETANGLE - ввод угла и некоторые другие функции. . Работу функций GETINT, GETREAL, GETSTRING рассмотрим на примере
функции GETINT, которая в общем виде выглядит так: (GETINT [ < подсказка > ]) Эта функция создает паузу в выполнении программы и ожидает,
пока пользователь введет с клавиатуры целое число. Функция возвращает введенное
число. Необязательный аргумент < подсказка > - это текстовая константа.
Если этот аргумент присутствует, то во время паузы на экране будет высвечиваться
текст подсказки. Аналогично записываются и действуют функции GETREAL и
GETSTRING. (GETPOINT[< точка >] [< подсказка
>]) Функция создает паузу и ожидает ввода точки. Точка может быть
введена путем указания на экране или путем набора ее координат на клавиатуре в
виде X, Y. Функция возвращает координаты точки (в виде списка - см. п. 2.4.).
Аргумент < подсказка > имеет тот же смысл, что и для функций GETINT. Если
задан аргумент < точка >, то при перемещении курсора на экране будет
отображаться "резиновая линия" от данной "опорной" точки до текущего положения
курсора. (GETDIST [< точка >][< под сказка
>]) Функция создает паузу и ожидает ввода расстояния. Расстояние
может быть указано тремя способами: как действительное число с клавиатуры; путем указания двух точек (будет определено расстояние между
точками); путем указания второй точки при наличии аргумента < точка
>. В двух последних случаях между первой точкой и текущим
положением курсора рисуется "резиновая линия". Функция возвращает действительное число, равное введенному
расстоянию. Нетрудно видеть, что первый способ задания расстояния для
пользователя (и для программы) будет эквивалентен действию функции GETREAL. Аналогично записывается и действует функция GETANGLE, которая
возвращает угол (в радианах) между прямой, заданной двумя точками, и осью X,.
Примеры: ; Программа 2.
Построение окружности (SETQ PC (GETPOINT "\nВведите центр:")) ; Ввод центра (SETQ R (OETDIST PC "\nВведите радиус:")) ; Ввод радиуса
(COMMAND "CIRCLE" PC: R) ; Окружность появляется на экране Но программа в таком виде неудачна, так как для ее выполнения
придется набирать строку за строкой, ввод строк будет чередоваться с их
выполнением, а для повторного использования программы ее придется набрать
заново. Реальный пользователь так работать не будет. Окончательный вариант: ; Программа 3. Построение окружности (DEFUN OKR 0 ; Имя описываемой функции (SETQ PC (GETPOItff "\nВведите центр:")) (SETQ R (GETDIST PC "\nВведите радиус:")) (COMMAND "CIRCLE" PC R) ) Такую программу можно записать на диск, затем в любое время
вызвать с диска (подробнее об этом см. в п, 2.5) и запустить на выполнение,
набрав (OKR) в ответ на приглашение ACAD. (Напомним, символ "\n" в тексте
подсказок означает "перевод строки"). Функции QUOTE, POLAR, ANGLE, DISTANCE, INTERS. Приведенные
ранее простые примеры не демонстрируют все преимущества программирования на
Автолиспе по сравнению с использованием редактора ACAD, В этом параграфе
рассмотрена программа, иллюстрирующая принцип построения параметризуемых
изображений. Для такого построения требуется задавать геометрические объекты
"внутри программы", т.е. без участия пользователя. Чтобы показать, как задается геометрическая точка в программе,
необходимо предварительно рассмотреть функцию QUOTE: (QUOTE < выражение >) Эта функция возвращает выражение, не вычисляяего. Примеры: (QUOTE А) -возвращает А (QUOTE (А В С )) - возвращает (А В С) QUOTE (1.0 1.0)) - возвращает (1.0 1.0) В тексте программы, создаваемой в виде файла, символ QUOTE, как
правило, заменяют эквивалентным обозначением ’
, т.е. (QUOTE A) то же самое, что 'А. Но
непосредственно в ответ на приглашение ACAD можно набирать только текст в форме
(QUOTE...). Геометрическая точка в программе может быть задана пятью
способами. Первый нам уже известен - ввод точки пользователем через
функцию GETPOINT. Второй - непосредственное указание координат точки в виде
списка из двух (двухмерная точка) или трех (трехмерная точка) элементов с
помощью функции QUOTE. Примеры: (QUOTE (1.0 1.0)) - точка с координатами 1,1; '(1.0 1.0) - аналогично; '(1.0 2.0 3.0) - точка в трехмерном пространстве с координатами
X=1,Y=2,2=3. Третий способ - задание точки нерез'другую точку, угол и
расстояние с помощью функции POLAR: (POLAR <точка> <угол>
<расстояние>) Эта функция возвращает точку, находящуюся под углом
<угол> и на расстоянии < расстояние > от заданной < точки >. У
тол указывается в радианах против часовой стрелки. POLAR - основная функция для внутрипрог-раммных геометрических
построений. Ее можно и удобно использовать практически во всех случаях. Четвертый способ - определение точки пересечения двух отрезков
с помощью функции INTERS. (INTERS <точка1> <точка2> <точка3>
<точка4> [< признак:"]) Функция INTERS находит точку пересечения двух отрезков -
отрезка от < точки! > к <точке2> с отрезком от <точки3> к
<точке4> -и возвращает найденную точку. < Признак > -любое выражение
Автолиспа. Если < признак > равен NIL, то будет определена точка
пересечения линий бесконечной длины, наложенных на заданные отрезки. Если <
признак > имеет любое значение, отличное от NIL, или если аргумент <
признак > вообще отсутствует, то ищется точка пересечения только внутри
отрезков. Если
точка пересечения в этой ситуации не найдена, то функция INTERS возвращает
NIL. Для геометрических построений могут оказаться полезными функции
ANGLE и DISTANCE. (ANGLE < точка 1 > < точка2 > ) Функция возвращает действительное число, / равное углу в
радианах, образованному прямой, проходящей через < точку! > и
<точку2>, с осьюХ. (DISTANCE <точка1> <точка2>) Функция возвращает действительное число, равное расстоянию
между < точкой! > и <точкой2>. ' Принцип построения параметризованных изображений иллюстрирует
Программа 4, позволяющая построить квадрат с задаваемой стороной и вписанную в
него окружность. Аналогично можно строить и более сложные изображения: для
получения нового изображения с помощью программы пользователь задает новые
значения параметров (точки, расстояния, числа и др.). Из этих данных в программе
могут быть получены другие переменные данные с помощью математических функций,
функции POLAR и т.п. Переменные данные будут использованы в качестве аргументов
команд ACAD посредством функции COMMAND. ; Программа 4. Квадрат с вписанной окружностью (DEPUN CQUADR ( ) ;
заголовок описываемойфункции ; Зададим начальную точку - левый нижний угол квадрата:(SETQ PI
(GETPOINT "\nНач. точка:")) ; Зададим длину квадрата: (SETQ L (GETDIST "\nДлина стороны:")) ; определим три оставшиеся вершины квадрата: (SETQ Р2 (POLAR PI 0.0 L)) (SETQ P3 (POLAR P2 (/ PI 2) L)) ; угол = PI/2 (SETQ P4 (POLAR P3 PI L)); угол = PI ; Построим квадрат на экране: (COMMAND "LINE" PI P2 P3
P4 "С") ; (Здесь "С" задает опцию "Замыкание") ;Определим радиус окружности: (SETQR(/L2));R=L/2 ; Определим центр окружности РС: (SETQ PR (POLAR PI 0.0 R)) ;PR - точка касания ; на нижней стороне (SETQ PC (POLAR PR (/ PI 2) R)) ; Построим окружность на экране: (COMMAND "CIRCLE" PC R) ) ; Конец описания функции QUADR Обратите внимание на несколько необычное имя функции - C:QUADR.
Символы "С:" имеют определенный смысл, который будет разъяснен в разделе
2.5. Подпрограммы, ветвления и циклы. Логические функции. Функции
WHILE и IF. В любом языке программирования есть средства для создания
подпрограмм, циклов, ветвлений в программах в зависимости от результатов
проверки условий. Такие средства есть и в Автолиспе. Подпрограмма позволяет описать некоторую последовательность
действий один раз, а использовать ее в различных местах программы и даже
включать в другие программы, что значительно упрощает программирование. Для этих целей в Автолиспе служит уже известная функция DEFUN.
Описание некоторой функции с помощью DEFUN и можно считать подпрограммой, а
обращение к описанной ранее функции - вызовом подпрограммы. При обращении на
место символических аргументов в описании функции подставляются истинные
значения этих переменных. Например, описанная в Программе 1 функция
SINCOS(A) может
рассматриваться как подпрограмма. А строка (SINCOS 0.0), встречающаяся в
какой-либо программе, является обращением к этой подпрограмме, причем аргумент А
принимает значение 0. Ветвления в программе организуются с помощью функции
IF: (IF <условие> <функция1>
[<функция2>]) Здесь < условие > - такое выражение Автолиспа, которое
среди прочих значений может в какой-то ситуации получить значение NIL. Функция IF вычисляет значение условия и, если оно не NIL, то
выполняет < функцию! >, иначе - выполняет <функцию2>, если она
присутствует. Функция IF возвращает результат выполнения функции. Таким образом,
функция IF соответствует управляющей структуре псевдокода ЕСЛИ-ТО-ИНАЧЕ. Для записи условий чаще всего используются функции, которые
назовем логическими. К ним относятся функции = (равно) < (меньше) > (больше) / = (не равно) < = (меньше или равно) > = (больше или равно) которые позволяют выполнять сравнение чисел или текстов, а
также функции AND, OR, NOT, обеспечивающие возможность строить сложные условия
из простых. Все эти функции могут возвращать одно из двух значений: NIL
("нет", условие не выполняется) или Т ("да", условие выполняется). Например, функция" =" имеет вид: (= <атом> <атом>...) Здесь в качестве атомов могут стоять либо числа (как целые, так
и вещественные), либо текстовые данные. Функция возвращает Т, если все атомы
равны между собой, иначе - NIL. Функция "/=" определена только, для двух атомов. Функция"<": (< <атом>
<атом>.„) Если каждый предыдущий атом меньше последующего, то
возвращается Т, иначе - NIL. Аналогично определяются остальные функции сравнения. Для
текстовых констант понятие "меньше" означает следующее: сравнение производится
по первой несовпадающей букве. "Меньшей" считается тот символ, ASCII-код ко- .
торого меньше. Для букв алфавита коды нарастают в алфавитном порядке (отдельно
для заглавных, отдельно для строчных букв). Функции AND, OR, NOT являются функциями алгебры
логики. (AND < выражение >...) Функция выполняет операцию логического 'И' над списком
выражений, т.е. функция возвращает NIL, если хотя бы одно выражение имеет
значение NIL. Иначе возвращается Т. (OR < выражение >...) Выполняется операция логического 'ИЛИ'. Возвращается Т, если
хотя бы одно выражение имеет значение Т, иначе - NIL. (NOT <выражение>) Выполняется логическая функция 'НЕ'. Если выражение имеет
значение NIL, то возвращается Т, во всех остальных случаях возвращается NIL.
Примеры: Пусть имеются следующие значения: А-5 В - "ТЕХТ1" С-NIL Тогда ( = А 5) возвращает Т ("А5.0)-Т (>=A10)-NIL (< В "ТЕХТ2") - Т (AND А В С) - NIL (ORABC)-T (NOT С)-Т (OR(=A5)(=AIO))-T Приведенная ниже Программа 5 иллюстрирует ветвление по условию
с использованием функции IF. ; Программа 5. Вычисление тангенса (DEFUN TAN (A / S С) ; Заголовок функции ; А - аргумент функции - угол, S, С - локальные переменные (SETQ S (SIN А)) (SETQ С (COS A)) ' (IP (/ = С 0.0) (/ S С) "бесконечность") ); Конец функции Здесь, если С не равно нулю, вычисляется тангенс (и значение
тангенса будет возвращено функцией). Если же С равно нулю, то. тангенс не
вычисляется, а функция возвращает строку "бесконечность" - это слово и появится
на экране. Цикл в Автолиспе организуется с помощью функции
WHILE. (WHILE <условие> < выражение
>...) Здесь < условие > - это выражение, которое в некоторых
ситуациях может принимать значение NIL. Функция WHILE вычисляет значение условия и, если оно не NIL,
вычисляет выражения, затем снова условие и т.д. Это продолжается, пока условие
не станет равно NIL. Затем WHILE возвращает последнее значение последнего
выражения. Таким образом, функция WHILE соответствует структуре псевдокода
ПОКА-ЦИКЛ. Приведенная ниже Программа 6
иллюстрирует использование цикла, позволяющего
компактно записать построение сложного изображения: строится семейство из 20
квадратов, каждый из которых повернут на угол 0.1*Р1 относительно предыдущего и
имеет периметр в 0.9 раз меньше предыдущего. Для построения 20 замкнутых линий
имеется всего одна команда LINE ; Программа 6. Построение семейства квадратов: ; Получение исходных данных (описание функции) (DEPUN ID ( ); Заголовок функции (SETQ PI (GETPOINT "\n Нач. точка:")) (SETQ L (GETDIST P1 "\n Нач. длина:")) ) ; Построение одного квадрата: (DEFUN QUADR (L A /P2 R3 й4); Заголовок функции ; Здесь P2, РЗ, Р4 объявлены как локальные ; переменные (SETQ P2 (POLAR PI A L)) (SETQ РЗ (POLAR P2 (+ А (/ PI 2)) L)) (SETQ P4 (POLAR РЗ (+ A PI) L)) (COMMAND "LINE" PI P2 P3 P4 "C") ) ; Построение семейства квадратов: (DEFUN QN ( ) ;
Заголовок функции (SETQ В 0.0) ; Задан начальный угол В=0 (ID) ; Выполнена
функция ID (WHILE (< = В (*
2 PI)); Начало цикла ; Выполним функцию QUADR с ; параметрами L, В: (QUADR L В) ; Увеличим угол на 0.1 PI (SETQ В (+В (* PI 0.1))) ; Изменим L в 0.9 раз: (SETQ L (* L 0.9)) ); Конец цикла ) Результат выполнения .Программы 5 показан на рис.1. В
предыдущих примерах каждая программа содержала по одному описанию функции.
Пример Программы 6 демонстрирует, что такое соответствие не обязательно.
Программа может содержать несколько описаний функций (несколько функций DEFUN).
Рис. 1. Результат двухкратного выполнения Программы 6 с разными исходными данными ВВЕДЕНИЕ
1. ПОНЯТИЕ О ПРОГРАММИРОВАНИИ. РАЗРАБОТКА АЛГОРИТМОВ ПРОГРАММ НА ПСЕВДОКОДЕ
1.1 Программы и программирование
1.2. Псевдокод - средство разработки алгоритмов
2. ВВЕДЕНИЕ В ЯЗЫК АВТОЛИСП
2.1. Назначение и возможности языка Автолисп
2.2. Основные понятия языка Автолисп
2.3. Разработка простейших программ на языке Автолисп
2.4. Построение параметризованных изображений
А становится равно В;
L (которое будет работать внутри QUADR) становится равным L (которое существовало
вне QUADR).
Следовательно, А и В, L и L - это разные данные, и не имеет значения, выбраны для их обозначения разные имена (как А и В) или одинаковые (как L). Изменения, которые происходят с В и L внутри функции, никак не отражаются на значениях А и L в остальной программе.
В Приложении приведена Программа и для построения чертежа детали - вала с произвольным количеством ступеней. На примере этой программы модно видеть, как для построения чертежа могут использоваться функции, рассмотренные в данной главе:, DEFUN, COMMAND, POLAR, IF, WHILE, функции типа GET. Программа 13, так же как Программа 6, иллюстрирует общую схему построения программ для получения параметризованных чертежей:
ввод исходных данных (в том числе - базовой точки);
определение точек внутри программы с помощью функции POLAR с использованием введенных данных;
построение примитивов на экране с помощью функции COMMAND по определенным точкам.
Вместе с тем для построения простого чертежа в Программе 13 приходится использовать и другие функции, которые будут рассмотрены в следующих главах.
До сих пор рассматривался вопрос о том, как писать программы на Автолиспе, но, по существу, не затрагивался вопрос о том, как их применять. Для использования Автолиспа в сеансе работы с графическим редактором ACAD необходимы следующие условия.
Используемая версия AutoCAD должна иметь модуль ADE-3. При настройке системы AutoCAD Автолисп должен быть подключен. При Выполнении этих условий Вы можете обращаться к Автолиспу, т.е. выполнять функции Автолиспа в любой момент, когда редактор выдает подсказку COMMAND: (КОМАНДА:).
Возможны пять способов использования программ на Автолиспе в зависимости от того, куда помещена разработанная программа и какое имя дано основной (т.е. последней) функции программы.
Непосредственный ввод программы с клавиатуры. В ответ на приглашение COMMAND: можно ввести первую функцию программы (набрать ее текст на клавиатуре), и она будет выполнена, в ответ на следующее приглашение -следующую функцию и тд. Изображение будет строиться постепенно, как при работе с редактором ACAD. Значение, возвращаемое каждой функцией, будет выдаваться на экран ( в нижнюю строку).
Итак, любой текст, начинающийся с символа "(", редактор ACAD воспринимает как функцию Автолиспа и передает интерпретатору Автолиспа. Именно такой способ упоминался в п.2.4. Очевидно, что он неудобен, так как при каждом повторном выполнении программу нужно вновь полностью набирать.
Ввод программы, оформленной как описание функции. Программа, набранная на клавиатуре в сеансе работы с ACAD, может быть использована повторно, если она оформлена как описание функции или несколько описаний функций, т.е. начинается с DEFUN. Повторный вызов такой программы реализуется .как обращение к описанной функции в любой момент до завершения текущего сеанса работы с ACAD. После выхода из графического редактора программа "теряется".
Запись программы в виде файла и вызов в виде функции Автолиспа. Программу можно создать как текстовый файл с помощью любого редактора текстов. Такой файл следует записать в доступный каталог, дав ему имя (любое) с расширением LSP.
До того, как решено выполнить данную программу, ее следует загрузить в ОЗУ с помощью функции Автолиспа LOAD. Функция имеет вид:
(LOAD < имя файла > )
Имя файла, в котором хранится данная программа, следует задавать в текстовом виде без расширения, но при необходимости с префиксом.
Теперь в ответ на подсказку COMMAND: в любой момент можно ввести строку с именем любой функции программы, определенной в программе с помощью DEFUN, заключив это имя в скобки. Если требуется, то после имени функции указываются ее аргументы. Например, текст Программы 1 (см. п.2.3) можно набрать в текстовом редакторе и записать на диск под именем SC.LSP. В сеансе работы с ACAD в ответ на COMMAND: ввести строку:
(LOAD "SC")
На экране появится имя загруженной функции - SINCOS.
После этого на любой запрос COMMAND:
можно набрать ответ:
(SINCOS 0) или
(SINCOS PI) и т.д.
В результате этого Программа 1 будет выполнена (с аргументами 0, Tt и др.). Аналогично можно подготовить, загрузить и выполнить другие программы,
приведенные выше:
Программа 3 вызывается Строкой (OKR)
Программа 5 вызывается строкой (TAN значение угла)
Программа 6 вызывается строкой (QN)
Оформление программы как готовой команды ACAD. Программу можно оформить так, чтобы после загрузки файла с этой программой, ее можно было вызывать по имени точно так же, как вызываются команды ACAD (т.е. без скобок).
Для этого имя главной функции в программе (последней, которая описана через DEFUN) нужно начать с символов "С:". Например, в Программе. 4 (см. п.2.4) описана функция C:QUADR. Такую программу можно вызвать на выполнение, набрав строку QUADR. Таким образом, можно оформлять только функции, не имеющие аргументов. -
Аналогично оформлена головная функция C:VAL в Программе 13 (см. Приложение). Таким образом, программу можно вызвать командой VAL.
Автоматическая загрузка программ. Может возникнуть желание обойтись без команды LOAD и загружать программу автоматически. Это можно сделать, если добавить текст программы в файл ACAD.LSP. Такой файл будет загружен в ОЗУ при вызове редактора ACAD.
Возможности работы с числами, описанные в п.2.3, дополняются следующими функциями
(1+ <число>) и
(1- < число >)
Эти функции возвращают число, соответственно увеличенное или уменьшенное на еденицу. Аргумент может быть целым или действительным, таков же и результат.
(GCD <число1> <число2>)
Функция возвращает наибольший общий делитель двух целых чисел.
(REM <число1> <число2> ….)
Функция делит <число1> на <число2> и т.д. и возвращает остаток от деления.
(МАХ<число> <число> ….) и
(MIN < число < число >….)
Эти функции возвращают соответственно максимальное и минимальное число из списка чисел: как целых, так и действительных.
Наряду с функциями для проверки условий, описанными в п.2.4 (типа =, /=, > и т.п.), имеются следующие функции.
BOUNDP <атом>)
Функция возвращает Т, если < атом > имеет какое-либо значение, кроме NIL. Если <атом> равен NIL, то возвращается NIL.
(NULL < элемент >)
Функция возвращает Т, если < элемент > имеет значение NIL, иначе возвращается NIL. Примеры:
Пусть (SETQ А 2) Тогда (BOUNDP А) -- > Т
(SETQ В NIL) (BOUNDP В) -- > NIL
(SETQ С В) (BOUNDP D) -- > не определено
(SETQ D '( )) (NULL A) -- > NIL
(NULLC)--> T (NULLD)->T
(NULL (1+ A))--> NIL
(NUMBERP < элемент >)
Функция возвращает Т, если < элемент > -число (целое или действительное). Для остальных типов элементов возвращается NIL.
(MINUSP < число)
Если аргументом функции является отрицательное число, то возвращается Т, если число неотрицательное, то NIL. Если аргумент не является числом, то функция не определена (интерпретатор Автолиспа выдает сообщение об ошибке).
(ZEROP < число)
Если аргумент имеет числовое значение, равное нулю, то возвращается Т, если число не равно нулю, то NIL. Если аргумент не является числом, то функция не определена.
(EQUAL <выражение1> <выражение2> [<допуск>])
Функция возвращает Т, если оба выражения равны между собой, иначе - NIL. Эту функцию можно применять во всех случаях, где используется функция =, однако возможности EQUAL шире:
аргументами EQUAL могут быть не только атомы, но и более сложные конструкции - списки, например, геометрические точки, заданные списками координат;
аргумент < допуск > позволяет задавать точность сравнения.
Пример:
(SETQ A (GETREAL)) ; Вводится число 3.14
(EQUAL A PI O.I) ; Возвращает Т, т.к. различия
; 3.14 и PI лежат в поле допуска.
Функции EQ и ATOM для анализа списков рассмотрены в п.4.4.
В Автолиспе имеются некоторые возможности для работы с текстовыми данными, т.е. с переменными, имеющими значение строк символов. Для этих целей служат следующие функции.
(STRLEN < строка >)
Функция возвращает целое число, равное длине текстовой переменной < строка >, т.е. количеству символов в строке.
(STRCAT < строка! > <строка2>...)
Функция возвращает строку, образующуюся в результате "сцепления" строк - аргументов.
(SUBSTR <строка> <начало> [<длина>])
Функция возвращает строку текста, являющуюся частью < строки >, заданной в качестве аргумента (выделяет подстроку). Здесь < начало - номер первого символа подстроки, < длина > - количество символов в выделяемой подстроке; если оно не задано, то подстрока продолжается до конца строки.
Примеры:
Пусть задано: Тогда
(SETQ A "ABCD") (STRLEN A) - > 4
(SETQ В "CDEFG") (STRCAT А В) - > "ABCDCDEFG"
(SUBSTR A 2)-> "BCD"
(SUBSTRB32)-> "EF"
Сцепление строк в программе удобно использовать для формирования текстовой части чертежей из данных, поступающих из различных источников, например из постоянной и переменной частей.
Выделение подстрок можно использовать для анализа данных, поступающих в программу извне (например, из файла; см.п.3.7), а также данных из текстовой части чертежа.
В Автолиспе имеются довольно богатые возможности для. получения данных одного типа из данных другого типа. Эти возможности обеспечиваются с помощью следующих функций.
(ANGTOS <угол> [< представление > [<точность>]]
Функция преобразует <угол>, выраженный в виде действительного числа в радианах, в форму текстовой строка-Аргумент < представление > указывает, в каком формате должен бь^ть представлен угол:
0 -градусы
1 - грацусы/минуты/секунды
2 - градусы
3 - радианы
4 - топографические единицы ("N", "W",
"S". "О")
Аргумент <точность> - это целое число, задающее число знаков после запятой. Если аргументы не указаны, то используются значения переменных ACAD: AUNITS и AUPREC. Если значение угла отрицательное, то выполняется преобразование в эквивалентный положительный угол в пределах 0...2П.
Таким образом, в текстовой части чертежа может быть записан угол, взятый с чертежа.
(ASCII < текст >)
Функция преобразует текстовую переменную <текст> следующим образом: выделяет первый символ и возвращает соответствующий ему ASCII-код (т.е. целое число).
Функция может оказаться полезной, если при вводе текста с клавиатуры нажимают на "несимвольные" клавиши, такие, как Enter. Сигналы от таких клавиш могут быть отслежены в программе только по их кодам.
(CHR < число)
Функция выполняет преобразование, обратное ASCII: преобразует < число в символьный ASCII-код и возвращает соответствующий символ в форме текстовой константы. Число должно быть целым, и его значение должно соответствовать коду какой-либо клавиши.
Функция может быть использована для формирования в программе последовательности символов, эквивалентных последовательности нажатия клавиш, например, последовательности управляющей графическим дисплеем через ANSI-драйвер MS-DOS.
Примеры:
(ASCII "A") - > 65 (CHR 65) - > "А"
(ASCII "В") - > 66 (CHR 66) - > "В"
(ASCII "ABBA") -> 65 (CHR 27) -> эквивалентно нажатию клавиши ESC
(ATOP < текст >) и
(ATOI < текст >)
Функции осуществляют преобразование аргумента, имеющего тип строки текста, в соответственно действительное и целое числа. При этом содержание < текста > должно допускать такое преобразование (например, не содержать в своем составе букв, кроме "Е").
С помощью этих функций можно превратить данные, считанные из внешнего файла (а эти данные всегда имеют текстовую форму), в числовые значения параметров, используемых для построения изображения.
Примеры:
(ATOF "123.7") --> 123.700000
(ATOI "123.7") --> 123
(ATOI "123") --> 123
(ATOF "123") --> 123.000000
(ATOF "1.2E-3") --> 0.001200
(ATOI "A2")--> не определено
(ITOA < целое число> ) и
(RTOS < число> [< режим > [< точность >]])
Функции осуществляют преобразование из соответственно целого или действительного числа в текст.
Аргумент < режим > может иметь значение от 1 до 5 и задавать форму представления действительного числа в виде:
1-< мантисса > Е < порядок >;
2- < целая часть >.< дробная часть >,
3-5 - см. в "Руководстве по программированию" (Автолисп, версия 10. Autodesk Ltd.,1989).
Аргумент < точность > задает число знаков после запятой. Если режим и точность не указаны, то используются значения системных переменных ACAD: LUNITS и LUPREC.
С помощью этих функций можно использовать числовые значения, формируемые программой, для выдачи на экран сообщений пользователю. Например, в функции ID (см. Приложение) (ITOA i) позволяет включать в строку сообщения переменную i - номер ступени вала.
(FIX <число>) и
(FLOAT < число)
Эти функции совершают преобразование числового аргумента в соответственно целую и действительную формы. Приведение к целому выполняется путем отбрасывания дробной части (а не округлением).
Развитой язык программирования должен обеспечивать реализацию управляющих структур типа "ветвление" и "цикл". Такие структуры реализуются на Автолиспе с помощью функций IF и WHILE (см. п.2.4). Функции, рассмотренные ниже, расширяют возможности программирования управляющих структур.
Функция COND реализует управляющую структуру ВЫБОР из нескольких вариантов действий и позволяет заменить использование многократно вложенных IF.
(COND ( <условие1 > < выражение! >...)...)
Здесь < выражение > -любая последовательность функций Автолиспа.
Функция реализуется следующим образом: вычисляется <условие1> и, если оно выполняется, то вычисляется < выражение! >. На этом функция работу заканчивает, возвращая значение последнего выражения. Но если < условие1 > не выполняется, то это выражение вычисляться не будет. Тогда функция COND переходит к проверке следующего <условия2> и тд., т.е. будет выполнено только то выражение, которое следует за первым выполняющимся условием.
Пример:
(COND (( > А 0) (SETQ В "PLUS"))
((= А 0) (SETQ В "ZERO"))
((< А 0) (SETQ В "MINUS"))
(Т NIL)
)
Если перед выполнением этой функции в переменную А было записано положительное число, то в результате вычисления функции в В будет записан текст "PLUS", функция возвратит "PLUS". Аналогично отработаются случаи, когда окажется, что А=0 и А<0. Если же А вообще не число, то первое выполняющееся условие функция COND найдет в последней строке. При этом никаких действий осуществлено не будет, функция возвратит NIL.
Функция PROGN является вспомогательной для конструирования функции IF. Напомним, что функция IF записывается так:
(IF <условие> < функция1 > [<функция2>])
Часто оказывается необходимым, чтобы при выполнении <условия> вычислялась не одна < функция! >, а последовательность функций. Это и позволяет сделать PROGN.
(PROGN < функция >...)
Функция PROGN объединяет последовательность функций в "макрофункцию". PROGN возвращает значение последней функции в последовательности.
Пример:
(IF (>=А 0)
(PROGN (SETQ В (/1 А))
(SETQ C(SQRTA)
)
(SETQ В "А <=0")
)
Здесь, если А>0, вычисляются В и С (и возвращается значение С), иначе возвращается текст "А< =0". Без функции PROGN такую конструкцию не удалось бы реализовать.
Функция REPEAT позволяет реализовать цикл в некоторых специфических ситуациях более удобно, чем функция WHILE, а именно тогда, когда заранее известно число шагов цикла:
(REPEAT < число> < выражение >)
Здесь < число должно иметь целое положительное значение. Выражение вычисляется заданное число раз. Возвращается значение последней выполненной функции.
Пример:
(SETQ STR "МАТЕРИАЛ:")
(REPEAT 3 (SETQ S (GETSTRING))
(SETQ STR (STRCAT STR S))
)
Здесь трижды с клавиатуры вводятся текстовые строки, которые "сцепляются" с начальной строкой "МАТЕРИАЛ".
Циклическая обработка списков может также быть организована с помощью функций FOREACH и MAPCAR (см. п.4.5).
В Автолиспе имеются возможности для обмена данными между программами через магнитные носители, при этом могут быть использованы данные не только из различных программ на Автолиспе, но и из программ на других языках. Например, расчетная программа на языке ФОРТРАН (Паскаль, С и др.) может записать свои результаты на диск, а программа на Автолиспе прочитает эти данные и использует как параметры для построения чертежа.
Файл с данными можно также использовать для "пакетного ввода" исходных данных в программу, вместо организации ввода в режиме диалога. Это целесообразно, когда при каждом запуске программы вводится большой объем данных, изменяющихся незначительно. Тогда проще отредактировать текстовый файл, чем заново набирать эти данные. Операции ввода-вывода с использованием файлов рассмотрены в п.3.7.
Перед тем как начать работу с файлом, его нужно открыть с помощью функции OPEN:
(OPEN < имя файла > < режим >)
Здесь < имя файла > - обозначение открываемого файла в среде MS-DOS (имя.расширение). При необходимости указывается префикс.
Значение < режима > может быть символами "г", или "w", или "а", где:
"r" - существующий файл открывается для чтения; если такого файла нет, то функция вернет NIL;
"w" - файл открывается для записи; если файла с таким именем нет, то создается новый файл с указанным именем; если такой файл уже существует, то он заменяется новым файлом с тем же именем;
"а" - файл открывается для добавления; если такого файла нет, то он создается; если файл уже существует, то появляется возможность добавления новых записей "в хвост" уже существующим. (В ряде случаев при добавлении новых записей в файл могут возникнуть затруднения; см. об этом в "Руководстве по программированию".)
Функция OPEN всегда используется в сочетании с функцией SETQ, так как OPEN возвращает условное имя файла, используемое внутри программы, которое будем называть дескриптором файла. (Дескриптор файла и имя файла, известное операционной системе, - это два разных понятия.) Дескриптор файла необходимо записать с помощью SETQ в какую-либо переменную, эту переменную затем придется использовать в операциях ввода-вывода.
Таким образом, строка
(SETQ F1 (OPEN "/K1/FILE1.DAT" "r"))
означает, что на рабочем диске в подкаталоге К1 ищется файл FILE1 с расширением DAT, этот файл открывается для чтения, значение дескриптора файла присваивается переменной Fl. Обратите внимание на то, что в текстовых константах Автолиспа символ "/" используется там, где по правилам MS-DOS должен стоять символ "\". Это вызвано тем, что символ "\" в Автолиспе используется для ввода управляющих символов.
После того как работа с данным файлом закончена, его следует закрыть с помощью функции CLOSE:
(CLOSE <дескриптор файла >)
например, файл F1 должен быть закрыт так:
(CLOSE F1)
Итак, любой вид работы с файлом должен ткрываться" функцией OPEN и "закрываться" функцией CLOSE. Например, пусть в програм-е предусмотрены сброс промежуточных данных на магнитный диск, а затем использование их данных в следующей части программы. го может быть организовано следующим образом:
…………………………..
(SETQ F (OPEN "FD.DAT" "w"))
…………………………..
(В том числе операции записи в файл)
(CLOSE F)
…………………………..
(SETQ F (OPEN "FD.DAT" "r"))
…………………………..
(В том числе операции чтения из файла)
(CLOSE F)
В Автолиспе имеется также функция NDFILE для поиска файла по имени: она возвращает полное имя с префиксом каталога:
(FINDFILE <имя файла >)
В ходе работы программы на Автолиспе возможен обмен данными с пользователем и с файлами на магнитном диске, открытыми к моменту начала обмена.
Ввод данных пользователем. Функции типа GET, READ. Функция INITGET. Пользователь может ввести в программу числа, символы и строки символов, в том числе ключевые слова, сигналы с функциональной клавиатуры, геометрические данные. Ввод чисел производится с помощью функций GETINT и GETREAL (см. п.2.3). Для ввода строк символов могут быть использованы функции:
(GETSTRING [ < флаг пробела > ] [ < подсказка > ]) или
(READ-LINE)
Обе эти функции создают паузу и ждут строку, набранную на клавиатуре. Но GETSTRING обладает более богатыми возможностями:
если флаг пробела отсутствует, то концом строки будет считаться первый пробел (а не только нажатие ENTER); если имеется флаг пробела (любое значение, кроме NIL), то конец строки отслеживается по ENTER;
на экран может выдаваться подсказка.
(READ-CHAR)
Функция READ-CHAR работает следующим образом. Если на клавиатуре не был набран никакой текст, то эта функция создает паузу для набора текста, заканчивающегося нажатием ENTER. После этого функция возвращает ASCII-код первой из нажатых клавиш. Каждое последующее обращение к READ-CHAR "сканирует" текст, включая клавишу ENTER (код 10). Например, пусть в программе имеются последовательно пять обращений к READ-CHAR. Тогда возможен следующий обмен данными:
READ-CHAR-1-пауза
Пользователь набирает QQW < ENTER >
READ-CHAR-I срабатывает и возвращает 81 (код Q)
READ-CHAR-II возвращает 81
READ-CHAR-III возвращает 87 (код W)
READ-CHAR-IV возвращает 10
READ-CHAR-V – пауза
Функцию READ-CHAR можно использовать в тех случаях, когда необходимо проверить код нажатой клавиши, не связанный с каким-либо символом. Например, в функции RZM (см. Приложение) таким образом проверяется, была ли нажата клавиша Enter (как утвердительный ответ на вопрос программы), код этой клавиши 10. Эта проверка осуществляется, как
(= (READ-CHAR) 10)
Геометрические данные вводятся с помощью функций, описанных в п.2.3: GETDIST, GETANGLE, GETPOINT. Первые две возвращают числа, третья - точку в виде списка координат. Помимо них для получения точки можно использовать:
(GBTCORNER < точка > [< подсказка >])
а для ввода угла
(GETORIENT [<точка>] [< подсказка >])
Функция GETCORNER отличается от GETPOINT только тем, что при движении курсора рисуется не "резиновая линия", а прямоугольник от базовой точки.
Функция GETORIENT работает так же, как GETANGLE, если в ходе сеанса работы действует выбор нуля и направления отсчета по умолчанию (рис. 2а). Если же с помощью системных переменных ACAD эти величины изменяются, то значения, возвращаемые GETANGLE и GETORIENT,-He совпадают (см. рис.2 и табл.1).
Как следует из рис.2 и табл.1, GETORIENT воспринимает задание и "нулевой оси", и направления угла, a GETANGLE - только направления. Поэтому GETANGLE можно использовать при повороте вставляемого блока, так как угол, равный 0, всегда будет давать 0. А GETORIENT можно использовать для введения таких углов, как угол базовой линии для команды TEXT.
Имеется возможность модифицировать условия работы функций GET с помощью функции INITGET:
(INITGET [ <управляющий признак>] [<текст>])
Хотя бы один из аргументов должен присутствовать, иначе в функции INITGET нет смысла.
Рис.2. Иллюстрация различий между функциями GETANGLE и GETORIENT:
а - направления для отсчета углов по умолчанию;
б - направления, заданные с помощью системных переменных;
в - интерпретация углов функцией GETANGLE в условиях рис.26;
г - интерпретация углов функцией GETORIENT в условиях рис.26.
Таблица 1. Значения, возвращаемые функциями, при задании аргументов (в градусах) в условиях рис. 26.
Значение (GETANGLE A) (GETORIENT A)
аргумента А
0 0.0 1.5708
90 4.71239 0.0
180 3.14159 4.71239
-90 1.5708 3.14159
<Управляющий признак> - это целое число, которое может принимать любое из значений, указанных в табл.2, или любую сумму этих значений.
Таблица 2. Управляющий признак INITGET
Признак Интерпретация
1 Запрещен пустой ввод (т.е. <ENTER>)
2 Запрещен ввод нуля
4 Запрещен ввод отрицательных чисел
8 Не контролируются лимиты, даже если LIMCHECK включено
16 Возвращаются трехмерные точки
32 Для "резиновой линии" или рамки применяется пунктир
Условия, заданные функцией INITGET, действуют на ближайшую функцию типа GET. "Запрет" функции INITGET действует так, что при его нарушении пользователем функция GET срабатывает повторно до тех пор, пока не будут введены приемлемые данные. С такой целью функция INITGET используется в функции C:VAL (см. Приложение), что гарантирует правильный ввод числа ступеней вала.
Значение признака, задаваемого функцией INITGET, должно соответствовать назначению последующей функции GET (табл.3).
Таблица 3. Функции GET, для которых имеют смысл управляющие признаки
Признаки
Функции
1 2 4 8 16 32
GETINT + + +
GETREAL + + +
GETDIST + + + + +
GETANGLE и
GETORIENT + + +
GETPOINT и
GETCORNER + + + +
GETSTRING
GETKWORD +
Аргумент < текст > в функции INITGET имеет форму текстовой константы. А по содержанию - это список ключевых слов, которые может ввести пользователь в ответ на функцию GET. Список ключевых слов строится по следующим правилам:
ключевые слова в списке разделяются пробелами;
допускается задавать не только полные слова, но и их сокращенные варианты по началу слова, тогда начало выделяется заглавными буквами;
тот же результат может быть достигнут иначе: за полным вариантом слова через запятую записывается сокращенный вариант.
Ключевые слова, разрешенные функцией INITGET, могут вводиться пользователем с клавиатуры в ответ на функцию GET. Такое слово будет возвращено функцией GET в виде строки текста (вне зависимости от назначения функции, т.е. от того, какие данные она формирует обычно). Это позволяет пользователю управлять работой программы (ввести "команду") в любой точке, где ему предлагается ввести данные с помощью GET-функции.
Пример:
(INITGET 7 "REZba FASKA 1,FAS1 FASKA2,FAS2")
Пусть первая встретившаяся после INITGET функция типа GET имеет вид:
(SETQ A (GETINIT "\nNOMER/REZba/PASl/FAS2"))
Тогда пользователь может ввести следующие данные с клавиатуры: положительное целое число (так как в INITGET записано 7=1+2+4); строки REZBA, REZ, FASKA1, FAS1, FASKA2, FAS2. Любой другой ввод будетвосприниматься как неправильный, и GETINT будет снова запрашивать данные. Отметим, что работа организуется именно функцией INITGET, a текст в функции GETINT служит только подсказкой пользователю.
Знакомство с INITGET позволяет понять ункцию GETKWORD:
(GETKWORD [< подсказка >])
Функция запрашивает ключевое слово у пользователя и возвращает введенное ключевое в виде строки текста. Применение GETKWORD имеет смысл, если перед этим (ючевые слова были определены функцией INITGET.
С помощью сочетания функций INITGET, GETKWORD и COND удобно организовывать ветвления в программе, управляемые пользователем.
Вывод данных на экран. Функции типа HNT и WRITE, функция PROMT. Управление выводом . Программа в процессе работы может выдавать на экран символы, строки текста, а также значения любых выражений Автолиспа том числе числа и списки). Во многих случаях один и тот же результат может быть получен различными функциями.
Функции различаются оформлением результата и возвращаемым в программу значением. Рассмотрим эти функции.
(WRITE-CHAR < целое число > )
Печатает символ, ASCII-код которого задан иым числом, и возвращает этот код.
(WRITE-LINE < текст >)
Печатает текст (без кавычек) и возвращает текст в форме текстовой константы (в качках).
(PRIN1 < выражение >)
Печатает и возвращает значение выражения (если < выражение > - текст, то он выдается в кавычках).
Функция PRIN1 (так же как PRINC и PRINT) без аргументов может быть использована для "тихого завершения" программы, так как эти функции в отсутствие аргумента ничего не возвращают. Такой прием использован в Программе 13 (см. последнюю строку программы в Приложении). Без этой строки программа выдала бы в строку подсказки значение, возвращенное функцией COMMAND, т.е. NIL.
(PRINC < выражение >)
Печатает и возвращает значение выражения (текст печатается без кавычек).
(PRINT < выражение >)
Печатает и возвращает значение выражения, при этом печать производится с новой строки с последующим пробелом (текст - в кавычках).
(PROMPT < текст >)
Печатает текст и возвращает NIL.
Примеры:
(WRITE-CHAR 88) Печатает Х Возвращает 88 (код X)
(WRITE-LINE "ABCD") ABCD "ABCD"
(PRIN1 "ABCD") "ABCD" "ABCD"
(PRIN1 (+123)) 6 6
(PRIN1'(А В С)) (А В С) (А В С)
(PRINC "ABCD") ABCD "ABCD"
(PRINT "ABCD") "ABCD" "ABCD"
(PROMPT "ABCD") ABCD NIL
Возможности управления выводом обеспечиваются тем, что в выводимой на экран строке текста используются управляющие символы:
\n - перевод строки;
\г - возврат к началу строки;
\t - табуляция.
Печать с новой строки обеспечивается также функцией PRINT. Для перевода строки служит и функция TERPRI, которая возвращает NIL.
Ввод и вывод через файлы. Вывод на печать. Как указывалось в п.3.6., программа может работать с файлами на магнитном диске, для этого служат уже известные нам функции, меющие в этом случае следующий формат.
(READ-LINE <Ф>)
(READ-CHAR <Ф>)
(WRITE-CHAR < целое число > < Ф > )
(WRITE-LINE < текст> <Ф>)
(PRIN1 <выражение> <Ф>)
(PRINC <выражение> <Ф>)
(PRINT <выражение> <Ф>)
Здесь буквой "Ф" для краткости обозначен дескриптор файла, заданный в SETQ с помощью функции OPEN для данного файла.
Каждая функция WRITE и PRINT формирует очередную запись файла последовательного доступа. Таким образом, в запись файла можно занести данные любого типа. При записи происходит преобразование данных в форму строки текста.
Функция READ-LINE считывает очередную запись и воспринимает ее как строку текста (возвращая эту строку). Функция READ-CHAR воспринимает очередной символ из считанной записи, а если такого символа нет, то считывает новую запись и воспринимает первый символ (возвращая ASCII-код, т.е. число).
Таким образом, читать из файла можно только текст.
С помощью функций типа WRITE и PRINT можно выдавать данные на устройство печати. Для этого в функции OPEN в качестве имени файла необходимо указать логическое имя устройства печати.
Использование возможностей ввода и вывода в Автолиспе иллюстрирует Программа 7. Она позволяет считывать текстовые данные из файла и включать строки текста в чертеж по желанию пользователя. Одна запись файла соответствует одной строке текста. Все строки располагаются одна под другой [7].
Пример:
Алгоритм, реализуемый Программой 7:
Ввести имя файла, содержащего текст
Ввести начальную точку для первой строки текста
Открыть файл
Считать первую запись файла
Разместить первую строку текста на экране
ПОКА очередная запись файла существует ЦИКЛ
Считать очередную запись файла
Выдать текст очередной строки для просмотра
Ввести сигнал пользователя
ЕСЛИ сигнал ="Да" ТО
Разместить очередную строку текста на экране
ВСЕ ЕСЛИ
ВСЕ ЦИКЛ ПОКА
Закрыть файл
КОНЕЦ
; Программа 7: Чтение текста из файла и размещение в чертеже
(DEFUN С: TXTIN (/bn pn f st)
(SETQ fn (GETSTRING "\nИмя файла:")
pn (GETPOINT "\n Нач. точка:")
f(OPEN fn "r")
st (READ-LINE f )
)
(COMMAND "TEXT" pn ".2" "" st)
(WHILE (SETQ st (READ-LINE 0)
(PRINT st)
(IF(= (READ-CHAR) 10)
(COMMAND "TEXT" "" st)
);конец IF
); Конец WHILE
); Конец программы
Примечание. В этой программе сигналом ”Да" считается нажатие на клавишу Enter AСП-код клавиши равен 10). Любой другой ответ воспринимается как "Нет".
Приведенную программу можно использовать для усовершенствования Программы 13 (см. Приложение). Для этого в конец программы (перед строкой (PRIN1)) следует вставить строки:
(LOAD "TXTIN") TXTIN
(при условии, что программа находится в файле TXTIN.LSP текущего каталога). Тогда после построения изображения вала пользователь получит возможность нанесения на чертеж текста технических требований, набор которых хранится в каком-либо текстовом файле.
Любой, кто знаком с языками программирования, такими, как Бэйсик, Паскаль, С, Фортран, заметит в Автолиспе ряд отличий от этих зыков, в частности, отсутствие такого важного способа организации данных, как массивы (переменные с индексами), обеспечивающего компактную запись повторяющихся действий с помощью циклов. Подобные задачи решаются в Автолиспе с помощью списков.
Как уже известно (п.2.4), геометрические точки представляются в Автолиспе в форме тисков из двух или трех координат. В дальнейшем (см. гл.5) будет показано, что примитивы CAD также представляются в виде сложных тисковых структур. Таким образом, для понимания специфики Автолиспа и его возможностей по обработке геометрических и графических данных ACAD, необходимо изучить функции работы со списками.
Как указывалось в п.2.2, список - это объект формы:
< список >::=([< элемент > ...]),
где < элемент > - это список или атом.
Особым случаем списка является точечная паpa:
< точечная пара >::=(< атом > . <атом>)
При хранении точечных пар требуется меньше места в памяти, чем при хранении обычных списков. Точечная пара может быть сформирована функцией CONS (см. ниже). Некоторые функции обработки списков не могут работать с точечными парами. Если точечная пара выдается на экран, то между атомами Автолисп печатает точку. Об использовании точечных пар будет сказано в п. 5.7.
Можно сформировать список (из двух или трех элементов) и записать его в качестве значения переменной путем ввода точки с помощью GETPOINT.
Список можно сформировать и путем указания примитива на экране, "развернуть" его функцией ENTGET (см. гл.5). Кроме того, имеются функции, позволяющие конструировать списки из данных, определенных ранее в программе.
(LIST < элемент > ...)
Функция LIST формирует список из любого числа элементов (атомов или списков) и возвращает список.
(CONS <элемент> <список>)
Функция CONS добавляет < элемент > (атом или список) в качестве первого элемента к уже существующему списку и возвращает обновленный список.
Таким образом, если функция LIST формирует новый список, то CONS - расширяет существующий. Однако, возможно использование CONS и в следующей форме:
(CONS <атом> <атом>)
В этом случае создается точечная пара.
(APPEND <список>...)
Функция APPEND соединяет несколько списков в один общий список. Отличие APPEND от LIST поясняется примерами, приведенными ниже.
(REVERSE <список>)
Функция REVERSE возвращает список с элементами, расставленными в обратном порядке.
Примеры:
(SETQ A '(1.0 2.0))
(SETQ В '(С D Е))
(SETQ F (LIST А В)) создает в F список ((1.0 2.0)(С D Е))
(SETQ G (LIST 'X В)) создает в G список Х (С D Е))
(SETQ G (CONS 'X В)) создает (X С D E)
(SETQ G (CONS '(X) В)) создает ((X) С D Е)
(SETQ G (CONS 34)) создает точечную пару (3.4)
(SETQ H (APPEND А В)) создает (1.0 2.0 С D Е),
т.е. происходит слияние списков в отличие от функции LIST, формирующей "список списков".
(SETQ H (APPEND '(X) В)) создает (X С D Е) - в отличие от функции CONS с такими же аргументами
(SETQ H (APPEND 'X В)) - ошибка, аргументы должны быть списками
(SETQ В (REVERSE В)) создает в В (Е D С).
Любая структура данных имеет смысл тогда, когда возможен доступ к отдельным элементам этой структуры. При работе со списками необходимо выделять элементы и другие части списков. Например, если необходимо изменить координату Х точки, заданной как (LIST X У), то элемент Х предварительно следует извлечь из списка:
(CAR < список >)
Функция возвращает первый элемент списка. Если список пуст, то возвращается NIL.
(CDR < список >)
Функция возвращает новый список, отличающийся отсутствием первого элемента (обрезает список спереди). Если список пуст, возвращается NIL. Если < список > представлен как точечная пара, то CDR возвращает второй элемент как атом, а не как список.
В Автолиспе определены функции, обеспечивающие последовательное выполнение CAR и (или) -CDR вплоть до четырех уровней вложенности: CAAR, CADR, CDDR, CADAR и т.д.
Пусть
(SETQ X '((А В) С D)),
Тогда
(CAAR X) возвращает А как (CAR (CAR X))
(CDAR X) возвращает (В) как (CDR (CAR X))
(CADAR X) возвращает В как (CAR (CDR (CAR X))) и т.п.
Функции типа CAR и CDR часто используются для выделения координат точек (CAR -для X, CADR - для У, CADDR - для Z).
(LAST < список >)
Функция возвращает последний элемент < списка >, который может быть атомом либо списком.
(MEMBER < элемент >< список>)
Функция просматривает < список > и ищет в нем заданный < элемент >. Если < элемент > найден, то возвращается список от < элемента > до конца исходного < списка >. Иначе возвращается NIL.
(NTH < номер > < список;-)
Функция возвращает элемент < списка >, имеющий заданный < номер >. < Номер > должен иметь целое неотрицательное значение. Примем во внимание, что первый элемент списка имеет номер 0. Если < номер > превышает число элементов в < списке > -1, то возвращается NIL.
Примеры:
Пусть
(SETQ А (В С (D Е)))
Тогда
(LAST А) возвращает (D E)
(MEMBER 'С А) возвращает (С (D Е))
(NTH О А) возвращает В
(NTH 2 А) возвращает (D Е)
(NTH 3 А) возвращает NIL
(ASSOC <элемент> <список>)
Функция ASSOC обеспечивает "ассоциативный поиск" в структурированном списке, т.е. в списке, элементы которого являются списками, эти списки построены по схеме:
(< ключевой элемент >< значение > ...)
Поиск проводится по совпадению < элемента >, заданного в функции ASSOC, с < ключевым элементом > в списке - элементе < списка >, заданного в ASSOC. Если поиск удался, то возвращается найденный список, иначе - NIL. Таким образом осуществляется поиск данных по ключу в сложной структуре данных.
Пусть
(SETQ DETAL '((КОД 123456) (КОДМ 001234) (М 1.45)))
Тогда
(ASSOC 'КОДМ DETAL) возвращает (КОДМ 001234)
(Теперь с помощью функции CADR можно "отрезать" ключевой элемент КОДМ и выделить значение 001234.)
(SUBST < новый элемент > < старый элемент > <список>)
Функция SUBST дополняет функцию ASSOC, позволяя заменять элементы в списке.
Производится просмотр списка, и каждый найденный < старый элемент > заменяется на < новый элемент >. Возвращается обновленный список.
Имеются функции проверки условий, связанные с анализом списков.
(LISTP < элемент >)
Функция возвращает Т, если < элемент > является списком, иначе - NIL.
(ATOM < элемент >)
Функция, обратная к LISTP, т.е. возвращает Т, если < элемент > является атомом.
(EQ < выражение1 > <выражение2>)
Функция проверяет идентичность двух выражений, которые, как правило, являются списками. Списки считаются идентичными, если они связаны друг с другом через SETQ. Если два списка идентичны (EQ), то они всегда равны (EQUAL). Если же два списка равны, то они необязательно идентичны.
Пример:
Пусть (SETQ X '(А В С)) (SETQ Y X)
Тогда
(EQUAL X Y) дает Т
(EQUAL X '(А В С)) дает Т
(ЕОХУ)даетТ
(EQ X '(А В С)) дает NIL
Как отмечалось в п.4.1, имеются возможности компактной записи некоторых действий с помощью списков. Для этого можно использовать функции APPLY, FOREACH, MAPCAR.
(APPLY'< имя функции > <список>)
Таким образом выполняется какая-либо функция Автолиспа, имя которой указано и которая может иметь несколько аргументов. Эти аргументы задаются < списком >. Например,
(APPLY '+'(12 3)) эквивалентно (+123)
(FOREACH < переменная > < список > < выражение > ...)
Функция организует циклическое выполнение < выражений >. Предполагается, что в этих выражениях присутствует < переменная >. Функция работает так: присваивает < переменной > значение первого элемента < списка >, подставляет это значение в < выражения > и выполняет их. То же самое делается для каждого последующего элемента <списка>.
Пример:
(FOREACH 1(123) (SETQ Е ( + Е I)))
эквивалентно последовательности
(SETQE(+E1))
(SETQE(+E2))
(SETQE(+ E3))
(MAPCAR'< имя функции > <cписок1>... <cписок N>)
MAPCAR также организует цикл. В нем выполняется функция, имя которой указано, имеющая N аргументов, т.е. столько, сколько перечислено < списков >. Во всех < списках > при этом должно быть одинаковое число элементов. Таким образом, цикл будет иметь столько шагов, сколько элементов в любом < списке >. Возвращается список значений функции, полученных для каждого номера элементов < списков >.
Пример:
(SETQ S (MAPCAR' + '(10 20 30) '(1 2 3)))
Формируется S в виде списка (11 22 33), каждый элемент которого есть результат применения функции "+" к паре аргументов, взятых из двух списков.
Из рассмотренных в данной главе функций работы со списками при программировании геометрических построений на Автолиспе, наверное, чаще всего используются функции LIST (для получения геометрической точки из отдельных координат), а также CAR и CADR (для выделения координат точки). Такое использование иллюстрируется следующей простой функцией:
; Программа 8. Получение трехмерной точки
; по заданной двухмерной точке и координате Z
(DEFUN 2d-3d (p z)
(LIST (CAR p) (CADR p) z)
)
Другие функции работы со списками находят применение в первую очередь при анализе элементов чертежа, которые в его базе данных представляются в виде списков. Вопросы работы с элементами чертежа рассмотрены в гл.5, поэтому пример, приведенный ниже, имеет не практический, а иллюстративный характер.
Программа 9 составлена в предположении, что есть некоторый список, являющийся схемой описания какого-либо объекта, т.е. перечнем ключевых слов. Например, описание сотрудников может представлять следующая схема:
("фамилия" "имя" "отчество" "год рождения"...)
Программа 9 содержит две функции. Функция "Синтез" позволяет построить на основе схемы описание конкретного объекта, также имеющее форму списка. Каждый элемент этого списка является списком вида:
(ключевое-слово значение-ключевого-слова)
Например, описание объекта может выглядеть так:
(("фамилия" "Попов") ("имя" "Иван")...)
Функция "Анализ" позволяет найти любой элемент описания объекта по ключевому слову и при необходимости изменить значение этого элемента.
Алгоритм, реализуемый Программой 9:
Функция "Синтез"
(Аргумент функции - список Схема)
Сформировать пустой список Объект (LIST)
ПОКА имеются элементы в списке Схема ЦИКЛ
Выдать ключевое слово и ввести значение ключевого слова
Сформировать субсписок из ключевого слова и его значения
(LIST)
Добавить субсписок в Объект (CONS)
ВСЕ ЦИКЛ ПОКА
Реверсировать список Объект
КОНЕЦ
Функция "Анализ"
Выдать запрос и ввести ключевое слово
(или Пусто)
ЕСЛИ введено не Пусто ТО
Найти значение по ключу (ASSOC) и выдать его
Выдать запрос и ввести новое значение
(или Пусто)
ЕСЛИ введено не Пусто ТО
Сформировать новый субсписок (LIST)
Подставить новый субсписок в Объект (SUBST)
ВСЕ ЕСЛИ
ВСЕ ЕСЛИ
КОНЕЦ
; Программа 9: Пример работы со списками
(DEFUN SINTEZ (Схема)
(SETQ Объект ‘())
(FOREACH Ключ Схема
(PRINC (STRCAT "\n Введите значение"
Ключ"="))
(SETQ Значение (GETSTRING))
(SETQ Элемент (LIST Ключ Значение))
(SETQ Объект (CONS Элемент Объект))
);foreach
(SETQ Объект (REVERSE Объект))
)
;
(DEFUN ANALIZE ()
(SETQ Ключ (GETSTRING "\n Введите ключевое слово (или Enter)"))
(IF (/= (ASCII Ключ) 10)
(PROGN
(SETQ Элемент (ASSOC Ключ Объект))
(SETQ Значение (CADR Элемент))
(PRINC (STRCAT Ключ "=" Значение))
(SETQ Новое_значение (GETSTRING
"\n Введите новое значение (или Enter)"))
(IF (/= (ASCII Новое_значение) 10)
(SETQ Новый_элемёнт (LIST Ключ
Новое_значение)
Объект (SUBST Новый_элемент
Элемент Объект))
);if
);progn
);if
)
Возможности работы со списками проиллюстрированы в Программе 13 (см. Приложение). Без использования списка в этой программе невозможно было бы проставить размеры длин ступеней вала, так как местоположение первой размерной линии может быть выбрано только тогда, когда все ступени вала построены (точнее, все диаметры ступеней введены). В связи с этим при построении ступеней требуется запоминать точки для последующего построения размеров. Это можно сделать только с помощью списка.
Рассмотрим, как используются функции работы со списками в Программе 13.
При построении первой ступени формируется список sp, состоящий из одного элемента -списка точек р2 и рЗ:
(SETQ sp (LIST (LIST p2 p3)))
При построении каждой следующей ступени в этот список добавляется новая пара точек:
(SETQ sp (CONS (LIST p2 p3) sp))
Обратим внимание на то, что новая пара добавляется в начало списка, т.е. порядок следования пар точек в списке обратен порядку построения ступеней вала.
Для построения диаметров организуется цикл с помощью функции FOREACH:
(FOREACH рр sp...),
т.е. на каждом шаге цикла выбирается очередной элемент списка sp и записывается в рр.
Верхняя и нижняя точки для простановки размера выделяются из рр следующим образом:
(SETQ p1 (CAR рр) p2 (CADR рр))
(Отметим, что диаметры будут проставляться, начиная с последней ступени, т.е. в том порядке, в котором организован список sp.)
Чтобы проставить размеры длин, необходимо сначала проставить один горизонтальный размер с опорой на базовую точку, а затем последовательно проставлять остальные размеры от базы. Для этого:
список sp "переворачивается":
(SETQ sp (REVERSE sp))
первая пара точек выделяется:
(SETQ рр (NTH 0 sp))
вторая (нижняя) точка из пары выделяется:
(SETQ sp (CDR sp))
После этого организуется цикл по простановке размеров с помощью FOREACH аналогично тому, как это было сделано при простановке диаметров. Однако теперь уже размеры будут проставляться в том же порядке, в каком изображался вал, т.е. слева-направо.
На примере Программы 13 можно также видеть, как функции LIST, CAR и CADR используются для внутрипрограммного построения точек. Например,
(SETQ p3 (LIST (- (CAR p1) 10) (CADR p1)))
определяет точку p3, координата Х которой смещена на десять единиц влево по отношению к точке р1. Аналогичный результат был бы получен с помощью (POLAR pi PI 10).
Помимо возможностей Автолиспа, свойственных и другим языкам программирования, а также возможностей по обработке списков, двойственных версиям языка Лисп, в Автолиспе имеются и специфические возможности, связанные с тем, что программа на Автолиспе работает в среде, созданной системой AutoCAD. Эта среда характеризуется:
определенными параметрами (системными переменными AutoCAD);
определенной организацией экрана (графического или текстового);
наличием изображения (чертежа), построенного на графическом экране и состоящего из примитивов и блоков;
определенной организацией данных об изображении в памяти ЭВМ - наличием графической базы данных чертежа, в которой содержатся описания примитивов и блоков, значения системных переменных, таблицы слоев, типов линий и т.д.
Программа на Автолиспе может воспринимать особенности этой среды и оказывать влияние на нее.
Помимо описанных ранее способов задания точки в программе имеется возможность задания точки путем объектной привязки, т.е. так же, как это делается в графическом диалоге с помощью команды OSNAP:
(OSNAP < точка > < режим >)
Предполагается, что на чертеже имеется объект, проходящий через заданную < точку >.
Аргумент < режим > - это строка текста, характеризующая режим привязки точно так же, как для команды OSNAP. Например:
"CEN" - центр окружности или дуги;
"BND" - конечная точка отрезка, дуги;
"INS" - базовая точка блока и др.
Если точка, соответствующая заданному режиму, не найдена, то возвращается NIL.
В ходе выполнения программа может влиять на состояние экрана.
(GRAPHSCR), (TEXTSCR)
С помощью этих функций можно переключать экран с текстового на графический и обратно.
Переключение экрана в текстовый режим может оказаться целесообразным, если программа выводит последовательность строк текста с помощью функций типа PRINT.
(GRCLEAR)
Функция очищает поле чертежа графического экрана.
(REDRAW)
Функция позволяет восстановить картину, стертую с помощью GCLEAR. Кроме того, EDRAW может применяться для перерисовывания текущего экрана и выполнять ту же роль, что и команда графического редактора REDRAW.
(MENUCMD < текст >)
Эта функция позволяет переключаться среди подстраниц в меню ACAD, т.е., например, вводить на экран тот раздел меню, который в данный момент необходим пользоватею. Это дает возможность упростить диалог пользователя при комбинированной работе с программой и графическим редактором.
Аргумент < текст > имеет следующий вид:
"<тип меню> = < имя раздела меню>"
Для экранного меню <тип меню> - S (другиe типы см. в "Руководстве пользователя"(АВТОКАД, версия 10. Autodesk Ltd., 1989)).
Таким образом (MENUCMD "S = S3 ") будет лзывать на экран раздел меню S3. Применение этой функции предполагает знание структуры файла меню, который используется в процессе работы данной программы (например, стандартного файла меню ACAD.MNU).
Все перечисленные здесь функции возвращают NIL.
Тем, кто полностью освоил графический редактор ACAD, известно, что при вызове ACAD устанавливаются по умолчанию значения множества системных переменных, влияющих на режим работы с редактором. В ходе графического диалога эти значения можно переустанавливать командой SETVAR. Полный список системных переменных, их типов и значений приведен в "Руководстве пользователя".
(GETVAR <имя переменной >)
С помощью этой функции значение системной переменной может быть считано в программу. < Имя переменной > должно указываться как строка текста.
(SETVAR < имя переменной > < значение переменной >)
С помощью этой функции значение системной переменной может быть переустановлено. Возвращается устанавливаемое значение.
Следует иметь в виду, что некоторые системные переменные определены только для гения (см. "Руководство пользователя"). Такие переменные нельзя переустановить. Примеры:
(SETQ A (GETVAR "ANOBASE"))
возвращается и записывается в А действительное число, определяющее направление угла 0 в этом чертеже.
(SETVAR "CMDECHO" 0)
задается значение 0 для переменной CMDECHO, что приведет к исчезновению "эха" выполняемых команд.
Режим, заданный в последнем примере, удобен на практике, в особенности тогда, когда программа интенсивно выдает пользователю полезные сообщения, между которыми эхо команд будет восприниматься как "шум". В любом случае отключение эха ускоряет выполнение программы.
В ходе работы с редактором ACAD создаются также символьные таблицы LNTYPE, LAYER другие, определяющие типы линий, слои, ви-ы, блоки, гарнитуры шрифтов. Данные из этих таблиц могут быть прочитаны с помощью функций TBLNEXT,TBLSEARCH, описанных в "Руководстве по программированию".
Программы на Автолиспе могут работать с бъектами специальных типов - графическими бъектами. К таким объектам относятся:
примитивы ACAD, имеющиеся на экране в процессе работы программы;
совокупности таких примитивов, называемые в Автолиспе наборами.
Графические объекты могут быть "введены в программу", т.е. возможно именование этих объектов с помощью имен переменных, так же как именование чисел, строк текстов, точек. После этого можно оперировать с этими объектами, обращаясь к ним по именам. В том числе можно анализировать и изменять характеристики этих объектов, что приводит к изменению изображения на экране.
Для лучшего представления о том, как происходит работа с примитивами и наборами, полезно понять следующее. При выделении каким-либо способом примитива или набора из базы данных Автолисп формирует внутрипрограммное имя этого объекта (примитива или набора). На самом деле - это не имя, а ссылка на объект, но для программиста это не имеет значения. Программист поступает следующим образом: он записывает это "имя" в какую-либо переменную с помощью SETQ. Затем эта переменная может быть использована для любого указания на объект. Например, она может быть подставлена в качестве аргумента в команду, требующую указания примитива или группы примитивов. Далее такая технология будет проиллюстрирована на примере.
Основное средство определения наборов примитивов - функция SSGET.
(SSGET [<режим>] [<точка1> [<точка2>]])
Функция возвращает определение (внутрипрограммное имя) выбранного примитива или отбора (совокупности примитивов), которое может быть "записано" в неременную Автолиспа (с помощью SETQ);
Если аргумент < режим > отсутствует, то создается набор, выбранный средствами графического редактора (указание на объекты, захват в рамку и т.п.). При этом программа выдает такой же запрос на указание способа выбора объетов, а затем запросы на выбор, как и при работе с графическим редактором.
Возможны следующие значения режима:
"Р", в русском варианте "Т" - выбирается текущий набор;
"L", русское "П" - выбирается последний сформированный на чертеже примитив;
"W", русское "Р" < точка1 > <точка2> - выбираются примитивы, попавшие в рамку с углами в < точке1 > и <точке2>;
"С", русское "С" <точка1> <точка2> - выбираются примитивы, пересекаемые рамкой. Кроме этих возможны еще две конструкции:
(SSGET < точка >)
Здесь выбираются примитивы, проходящие через < точку >.
(SSGET "х" < фильтр >)
Здесь < фильтр > - список, элементами которого являются одна или несколько точечных пар. Каждая точечная пара строится по следующей форме:
(< код >.< значение >) Здесь <код> - одно из принятых в Автолиспе чисел, показывающих, по какому признаку выбираются примитивы, например;
0 - примитивы одного типа;
2 - примитивы, входящие в один блок (INSERT) ;
6 - по типу линии;
7 - по гарнитуре шрифта;
8 - по имени слоя;
62 - по цвету и др.
< значение > - значение признака.
Например,
(SSGET "X" '((8 . "SLI")))
вернет набор, включающий все примитивы, находящиеся на слое, именованном как "SLI";
(SSGET "X" '((0. "LINE") (62 .1)))
вернет набор, состоящий из всех линий красного цвета (1 - номер красного цвета).
Выполнение последовательности функций
(SETQ sdel (SSGET "X" '((6 . "CENTER"))))
(COMMAND "ERASE" sdel)
приведет к стиранию всех примитивов, изображенных осевыми линиями.
Следующие функции позволяют анализировать набор, получаемый с помощью SSGET
(SSLENGTH < набор >)
Функция SSLENGTH возвращает целую величину, представляющую число примитивов в наборе. Таким образом, программа может "узнать", сколько объектов было выделено пользователем. По известному числу примитивов можно организовать цикл по обработке последовательно каждого примитива.
Здесь и далее < набор > - это имя переменной набора, т.е. переменной, определенной ранее следующим образом:
(SETQ < набор > (SSGET...))
(SSNAME < набор > < номер >)
Функция SSNAME возвращает внутрипрог-раммное имя примитива из < набора >, идущего под соответствующим номером.
Здесь < номер > - целая величина. Первый по порядку примитив имеет номер 0. Если < номер > меньше 0 или больше максимального номера примитива в наборе, то возвращается NIL. Таким образом, конструкция вида
(SETQ < переменная > (SSNAME < набор > <номер>))
позволяет выделить примитив из < набора >, записав его имя в < переменную >.
(SSMEMB <примитив> <набор>)
Функция SSMEMB проверяет, входит ли < примитив > в < набор >. Если да, то возвращается имя примитива, если нет, - то NIL.
Здесь и далее < примитив > - имя переменной, значение которой записано с помощью SETQ, например, путем применения функции SSNAME.
Следующие функции позволяют изменять состав набора:
(SSADD [< примитив > [< набор >]])
Функция SSADD без аргументов создает новый пустой набор. SSADD с аргументом < примитив > создает новый набор, содержащий только указанный примитив. Если указаны оба аргумента, то функция добавляет указанный примитив в набор. Если этот примитив в наборе уже имеется, то ничего не изменится. Функция возвращает имя набора. Например,
(SETQ S (SSADD р1))
Эта конструкция формирует новый набор, состоящий из одного примитива. Предполагается, что pi - переменная, в которую ранее было записано имя примитива. Имя созданного набора записывается в переменную S, которую теперь можно использовать для указания на набор.
(SSDEL <примитив> <набор>)
Функция удаляет < примитив > из < набора >, если он там присутствовал, иначе - ничего не меняется. Возвращается имя набора.
Пример работы с набором:
(SETQ SS (SSGET))
; Здесь образуется пауза, в ходе которой пользователь
; укажет несколько объектов на экране (примитивов).
; После нажатия <ENTER> программа определяет
; набор. Формируется внутрипрограммное имя
;этого набора, которое возвращается функцией SSGET в переменную SS
;Теперь в программе данный набор можно обозначить как SS.
(SETQ L (SSLENGTH SS))
;Определено количество примитивов в наборе SS и записано в L.
(SETQ SL (SSNAME SS (1-L)))
;Выделен последний примитив в наборе SS, его внутрипрограммное
;имя возвращено функцией SSNAME в переменную SL
(SETQ SN (SSADD SL))
;Создан новый набор, содержащий последний
;примитив из набора SS. Имя нового набора записано в переменную SN.
(SETQ SS (SSDEL SL SS))
;Из SS удален последний элемент. Получавшийся в результате набор будет ;также назван SS.
(COMMAND "ERASE" SS)
;Набор SS удаляется с экрана, т.е. стираются все примитивы, ранее ; помеченные пользователем, кроме последнего (SL).
Примитивы в ACAD могут быть простыми (линия, окружность, строки текста,...) или составными (полилинии, вставки блоков). Составные примитивы делятся на субпримитивы.
Например, для полилинии субпримитивами являются вершины, для вставки блоков - атрибуты. С помощью функций типа SS, рассмотренных в п.5.5, могут быть получены либо наборы примитивов, либо примитивы (простые или составные), но не субпримитивы. Функции, рассматриваемые в данном параграфе, позволяют работать с примитивами и субпримитивами.
Выбор примитивов:
(ENTNEXT [<примитив>])
Функция возвращает внутрипрограммное имя примитива или субпримитива:
если < примитив > не указан, то возвращается первый из примитивов чертежа (неудаленных);
если указан простой примитив, то ENTNEXT возвращает примитив, следующий за указанным;
если указан составной примитив; то ENTNEXT возвращает первый субпримитив указанного примитива;
если указан субпримитив, то ENTNEXT возвращает субпримитив, принадлежащий тому же примитиву, что и указанный, и следующий за указанным;
если запрашиваемый объект отсутствует, то возвращается NIL.
(ENTLAST).
Функция возвращает внутрипрограммное имя последнего примитива на чертеже (неудаленного). Субпримитив с помощью ENLAST не выделяется.
(ENTSEL [ < подсказка > ])
Эта функция создает паузу и может вывести текст < подсказки >. Пользователь в ответ должен указать примитив на экране.
Функция возвращает результат в виде списка из двух элементов:
первый элемент - внутрипрограммное имя примитива;
второй элемент - точка, в которой было проведено указание, эта точка возвращается в виде списка координат.
Возвращаемый результат может быть "записан в переменную" с помощью SETQ. Эта переменная впоследствии может быть задана в ответ на любую команду ACAD (в функции COMMAND), требующую выбрать объект и учитывающую точку указания. Кроме того, результат, записанный в данную переменную, может быть "разложен .на составные части": (CAR < переменная >) возвращает имя примитива, (CADR < переменная >) вернет точку указания.
Удаление, восстановление и обновление примитивов:
(ENTDEL < примитив >)
С помощью этой функции примитив может быть удален из чертежа. Субпримитивы таким способом не удаляются.
Пока не кончился сеанс работы с данным чертежом, удаленный примитив может быть восстановлен с помощью той же функции (ENTDEL < примитив >)
(REDRAW < примитив >)
Функция возобновляет изображение примитива после очистки экрана функцией GRCLEAR. Таким образом, рассмотренная в п.5.3 функция REDRAW может также управлять изображением примитива:
(REDRAW <примитив> <режим>)
Действие REDRAW зависит от значения аргумента < режим >: 1 - примитив перерисовывается; 2 - примитив стирается; 3 - примитив подсвечивается; 4 - подсветка примитива отменяется.
Каждый примитив с точки зрения системы AutoCAD представляет собой достаточно сложную совокупность данных. Представление об этих данных дают правила расположения данных в DXF-файле, который является текстовым описанием чертежа (см. "Руководство пользователя").
Программа на Автолиспе может сформировать сложный список, в котором будут содержаться все данные о примитиве. После этого средствами обработки списков можно выделять, анализировать и модифицировать отдельные лепные. За модификацией данных примитива может следовать отображение модифицированного примитива на чертеже.
Таким образом, программа на Автолиспе может анализировать и видоизменять чертеж, построенный, например, в режиме диалога с редактором ACAD.
Формирование списка данных примитива:
(ENTGET < примитив >)
Функция формирует и возвращает список, содержащий данные о примитиве.
Структура списка напоминает перечень данных о примитиве в DXF-файле и зависит от типа примитива и от того, насколько характеристики примитива соответствуют умолчанию.
Правила построения списка:
каждый элемент списка является списком (будем называть его субсписком);
большинство субсписков имеют вид точечных пар (кроме субсписков, описывающих точки);
первый элемент каждого субсписка - это код данных, второй элемент (и последующие) - значение (значения), соответствующие коду;
первый субсписок имеет вид (-1 . имя-примитива);
второй: (0. тип-примитива);
третий: (8. имя-слоя);
далее следуют некоторые атрибуты примитива в том случае, если их значения отличаются от значений по умолчанию, набор этих атрибутов зависит от версии ACAD, примером может служить (62. код-цвета);
далее следуют характеристики примитива, состав которых зависит от типа примитива.
Например, для отрезка прямой (тип = "LINE"):
(10 координаты-начальной-точки)
(11 координаты-конечной-точки)
Для окружности (тип = "CIRCLE"):
(10 координаты-центра)
(40. радиус)
Для дуги (тип = "ARC"):
(10 координаты-центра)
(40. радиус)
(50 . начальный-угол)
(51. конечный-угол)
Пример списка, возвращаемого функцией ENTGET для окружности, находящейся на слое "О", синего цвета (номер цвета - 5) с центром в точке (2 2 0) и с радиусом 1.5, изображенной пунктирной линией ("DASHED"):
((-1. <внутрипрограммное-имя-примитива>)
(0 . "CIRCLE")
(8. "0")
(6 . "DASHED")
(62.5)
(10 2.0 2.0 0.0) (40. 1.5)
)
Модификация примитива:
(ENTMODE < примитив >)
С помощью этой функции можно изменить изображение примитива на экране. Предполагается, что до обращения к ENTMOD происходила модификация данных в списке, полученном с помощью ENTGET.
Пример:
(SETQ PR (ENTNEXT))
; Выделяется первый примитив в базе данных,
; имя которого возвращается в PR
(SETQ SPR (ENTGET PR))
;Формируется список из данных, описывающих примитив PR, этот список ;возвращается в SPR
; Здесь следуют операции над списком SPR
; по изменению каких-либо данных в этом списке
(ENTMODE SPR)
После выполнения последней функции на экране вместо примитива PR, ранее выбранного пользователем, появится "обновленный" примитив, отличающийся какими-либо характеристиками. Для программы это по-прежнему будет примитив PR, и с ним можно продолжать работу.
На применение ENTMODE накладываются некоторые ограничения:
не может быть изменен тип примитива;
такие атрибуты как Тип линии (и некоторые другие), могут принимать только те значения, которые к данному моменту определены в сеансе работы с ACAD;
однако слой может быть задан и новый, отсутствовавший к данному моменту.
Функция ENTMODE может выполняться над примитивом или субпримитивом. Если ENTMODE выполняется над субпримитивом, то видимого изменения на экране не происходит. 122
(ENTUPD < примитив >)
С помощью этой функции можно изменить изображение примитива после того, как изменены субприпримитивы этого примитива с помощью ENTMODE.
Однократное изменение сложного примитива происходит гораздо быстрее, чем его многократная перерисовка после изменения каждого субпримитива.
Приведенные ниже примеры демонстрируют различные применения функций для работы с примитивами и наборами. Каждая из этих программ - не только иллюстрация, но и практически полезная функция, которая может пригодиться конструктору, работающему с редактором AC AD. Эти программы иллюстрируют возможности расширения системы AutoCAD с помощью Автолиспа.
; Программа 10: Удаление предпоследнего элемента
; чертежа [4]
(DEFUN С: ERASE2 ( )
(SETQ secondlast (ENTDEL (ENTLAST)))
(ENTDEL (ENTLAST))
(ENTDEL secondlast)
)
Известно, что в редакторе ACAD имеется команда ERASE ("СОТРИ"), которая позволяет стереть последний элемент чертежа или элемент, указываемый конструктором. Однако, оба эти способа могут оказаться неудобными в следующей ситуации: конструктор создает сложный насыщенный чертеж и ему не сразу удается правильно построить нужный элемент. Конструктор хотел бы повторить попытку, но при этом сохранить неправильный элемент в качестве "отправной точки", а после удачного построения - стереть этот элемент. Имея описанную выше функцию, он сможет это сделать, подав команду ERASE2.
Программа" 10 решает задачу просто и изящно:
стирается последний примитив (но его имя записывается в переменную secondlast);
стирается примитив, ставший последним, т.е. бывший предпоследний;
путем повторного применения функции ENTDEL по отношению к примитиву secondlast стертый последний элемент восстанавливается на экране.
Программа 11, приведенная ниже, дает возможность значительно упростить решение задачи, нередко встречающейся на практике при конструировании сложных объектов, - перенесение всех примитивов, находящихся на одном слое, на другой слой [6].
Средства ACAD позволяют решить такую задачу только с помощью метода последовательного указания всех переносимых примитивов -долгого и неудобного.
Алгоритм, реализуемый Программой 11:
Установить переменную found в NIL (found "NIL свидетельствует о том, что на слое не найдено ни одного примитива).
Ввести с клавиатуры и запомнить имена старого и нового слоя.
Выдать сообщение о том, что поиск начался.
Записать в entn имя первого примитива чертежа
ПОКА entn существует ЦИКЛ
Получить в cnt список, соответствующий entn
ЕСЛИ имя слоя в списке ent совпадает с именем
старого слоя ТО
Заменить слой примитива новым слоем
Установить found =t (примитив найден)
ВСЕ ЕСЛИ
Записать в entn имя очередного примитива
ВСE ЦИКЛ ПОКА
ЕСЛИ founds NIL (примитив отсутствует) ТО
Выдать сообщение об отсутствии примитивов
на слое
ВСЕ ЕСЛИ
КОНЕЦ
; Программа 11 Перенос примитивов с одного слоя
; на другой
(DEPUN C:CNGLAY (/cmd entn ent)
(SETVAR "CMDECHO" 0)
(SETQ found NIL)
(SETQ oldlyr (STRCASE (GETSTRINO
"\n Введите старое имя слоя:"))
newlyr (STRCASE (OETSTRING
"\n Введите новое имя слоя:")))
(PRINC "\n Ведется поиск примитивов на слое")
(SETQ entn (ENTNEXT))
(WHILE (/=entn nil)
(SETQ ent (ENTGET entn))
(IF ( = (CDR (ASSOC 8 ent) oldlyr)
(PROGN
(COMMAND "CHANGE" entn""
"p" "LA" newlyr"")
(SETQ found t)
);progn
);if
(SETQ entn (ENTNEXT entn))
); while
(IF (NOT found)
(PRINC (STRCAT "\n На слое" oldlyr" нет примитивов"))
);if
(SETVAR "CMDECHO" 1)
)
Возможно, два ключевых действия нуждаются в комментариях.
1. Функция (ASSOC 8 ent) выполняет ассоциативный поиск в списке ent, являющемся описанием примитива в базе данных чертежа. Это описание, как указывалось, само состоит из списков - точечных пар, среди которых обязательно имеется пара вида (8.имя_слоя). Этот подсписок и выделяется из общего списка ent с помощью ASSOC. Функция CDR "обрезает" этот подсписок, сохраняя вторую его часть -имя слоя.
2. Аргументы команды CHANGE ("Изменить") перечисляются в соответствии с тем, как происходили бЫ ответы на вопросы этой команды в диалоге 1: ACAD:
entn - имя примитива в ответ на запрос объекта;
" " указывает, что выбор объектов закончен;
"p" указывает на то, что нужно изменить одно из свойств объекта;
"LA" говорит о том^что этим свойством является слой;
newlyr указывает новое имя слоя;
" " соответствует нажатию ENTER,завершающему выполнение команды.
Обратите внимание на ряд моментов в программе, не относящихся непосредственно к ее основной задаче, но свидетельствующих о программистской культуре ее автора:
1. Используются локальные переменные.
2. Выдаются функционально необязательные, но полезные сообщения о том, что поиск происходит, и о том, что поиск не дал результатов. Первое сообщение позволяет конструктору не нервничать во время затянувшейся паузы, второе - повторить операцию, указав другое имя слоя, если при прежнем указании произошла ошибка.
3. С помощью функции STRCASE обеспечивается возможность ввода имен слоев как с верхнего, так и с нижнего регистра клавиатуры, в то время как в базе данных чертежа хранятся имена, набранные заглавными буквами (т.е. в нижнем регистре).
4. Перед началом работы программы эхо команд отключается, что позволяет ускорить выполнение цикла программы. После завершения работы эхо команд вновь включается, чтобы обеспечить последующий нормальный диалог конструктора с редактором ACAD.
Рассматриваемая далее программа 12, составленная на базе программы, приведенной в работе [5], может оказаться полезной для тех, кто решает задачи разводки коммуникаций, например трубопроводов в пространстве, где важным критерием является суммарная длина трасс. Предлагаемая программа позволяет вычислять суммарную длину всех полилиний, имеющихся в чертеже. (Если изменить вид "фильтра" в функции SSGET, то можно просчитывать полилинии, обладающие каким-либо общим свойством, например, находящиеся на заданном слое). Для понимания программы необходимо иметь представление о том, как устроен в базе данных список, соответствующий полилинии, которая является сложным примитивом, содержащим в качестве субпримитивов вершины полилинии. Достаточно знать следующее.
1. В набор, образуемый с помощью SSGET, попадают только основные примитивы. Тип примитива для полилинии - POLYLINE.
2. Для того чтобы попасть на первую вершину полилинии, нужно применить функцию ENTNEXT, где аргументом является имя основного примитива (типа PLINE). Субпримитив вершины полилинии имеет тип VERTEX. Субсписок, содержащий координаты вершин, имеет код 10.
3. Для перемещения к следующей вершине также используется ENTNEXT, где аргументом является имя субпримйтива - предыдущей вершины.
4. Признаком окончания списка для полилинии служит примитив типа SEQEND.
Алгоритм, реализуемый Программой 12:
Записать 0 в суммарную длину трасс tsum
Составить набор sspline, содержащий все полилинии чертежа
Определить число полилиний в наборе - ssl
ЕСЛИ ssl > 0 ТО
Записать номер первой полилинии 0 в num
ПОКА num < = ssl-1 ЦИКЛ
Получить имя очередной полилинии npline по ее номеру в
наборе - num
Получить имя первого субпримитива en
Записать в pi nil
Получить е1 - список для примитива en
ПОКА тип en равен VERTEX ЦИКЛ (т.е. субпримитив есть вершина)
ЕСЛИ pl= nil ТО
Записать в р1 точку - вершину
ИНАЧЕ
Найти расстояние от р1 до точки - вершины и прибавить
это расстояние к tsum
Записать в р1 точку - вершину
ВСЕ ЕСЛИ
Получить имя очередного примитива en
Получить el - список для примитива en
ВСЕ ЦИКЛ ПОКА
Увеличить пит на единицу
ВСЕ ЦИКЛ ПОКА
ВСЕ ЕСЛИ
Выдать значение суммарной длины трасс tsum
КОНЕЦ
; Программа 12: Определение суммарной длины
; полилиний
(DEFUN LTRASS (/sspline ssl num npline pi en el tsum)
(SETQ tsum 0)
(SETQ sspline (SSGET "X" '((0. “POLYLINE"))))
(SETQ ssl (SSLENGTH sspline))
(IF(>ssl 0)
(PROGN
(SETQ num 0)
(WHILE (<= num (-ssl 1))
(SETQ npline (SSNAME sspline num))
(SETQ en (ENTNEXT npline))
(SETQ el (ENTGET en))
(SETQ p1 nil)
(WHILE (= (CDR (ASSOC 0 el)) "VERTEX")
(IF (NULL p1)
(SETQ p1 (CDR (ASSOC 10 el)))
(SETQ tsum (+ tsum (DISTANCE p1
(SETQ p1 (CDR (ASSOC 10 el))))))
);if
(SETQ en (ENTNEXT en))
(SETQ el (ENTGET en))
); while
(SETQ num (1+num))
); while
);progn
);if
(PROMPT “\n Общая длина трасс =")
(PRINC tsum)
(PRINC)
)
В этой книге описаны основные функции языка Автолисп для AutoCAD версии 10. Знания этих функций достаточно для решения большинства практических задач: построения чертежей типовых деталей и узлов, расчетно-графических задач, работы с файлами, анализа и преобразования изображений, расширения системы команд графического редактора ACAD. Некоторые функции (около 20) остались за рамками описания, в том числе функции, связанные с распределением оперативной памяти, отладкой программ и др.
Все возможности языка Автолисп сохранились в последней версии системы AutoCAD (версия 11, русскоязычная, поставляется с конца 1991 г). Помимо этого, в версии 11 имеется возможность графического программирования с использованием языка С. Для выполнения программ, написанных на языке С, необходим интерпретатор Автолиспа.
Наряду с интерпретатором, разработан компилятор Автолиспа (поставляется отдельно от системы AutoCAD). Программа на Автолиспе, отлаженная в режиме интерпретации, может быть откомпилирована. Полученный в результате загрузочный модуль будет выполняться значительно быстрее и требовать меньше памяти.
Наряду с программированием на Автолиспе существует и другой способ получения модели семейства чертежей, отличающихся значениями размеров, - метод параметризации. Этот метод реализован в таких системах, как PARACAD, SYNTHESIS, CUSP, p-Design, и других, работающих совместно с системой AutoCAD. Модель формируется с помощью системы параметризации в режиме графического редактирования, т.е. значительно удобнее и быстрее, чем программирование. Однако круг задач, решаемых с помощью системы параметризации, значительно уже, чем круг задач, для решения которых используется Автолисп, и ограничен получением чертежей, различающихся только размерами. Например, чертеж вала с произвольным количеством ступеней, приведенный в Приложении, нельзя получить методом параметризации.
Пример программы на языке Автолисп для получения семейства чертежей
Представленная программа позволяет получить чертеж вала с произвольным числом ступеней. Пользователь задает начальную точку, число ступеней и для каждой ступени – длину и диаметр. Программа рисует контур детали и проставляет длины ступеней от единой базы. Программа спрашивает о необходимости простановки диаметров и при утвердительном ответе пользователя проставляет их так, как показано на рисунке 3, где приведен результат выполнения программы 13 с конкретным набором значений параметров.
При составлении программы принимались следующие решения:
масштаб изображения 1:1;
базовая точка располагается в центре левого торца первой ступени вала так, что каждая следующая ступень рисуется справа от предыдущей;
чтобы не рисовать дважды границу двух ступеней, ступень вала изображается с учетом соотношения между ее диаметром и диаметром предыдущей ступени: если следующий диаметр меньше , то формируется линия по четырем точкам (функция ST1), иначе -по шести точкам (функция ST2);
контур создается полилинией шириной 0.5, что позволяет' получать на изображении различную толщину для контурных и прочих линий;
диаметры проставляются так, что размерная линия отстоит на 10 см от правой границы данной ступени, следовательно, при слишком малой длине ступени размерный текст может наложиться на линию контура;
в связи с этим пользователю предоставлена возможность выбора способа простановки диаметров: автоматически или "вручную" с помощью команд ACAD.
; Программа 13. Формирование изображения вала
; с заданным числом ступеней
(DEFUN ID ( ) ; Функция для ввода исходных данных
(SETQ d (GETDIST (STRCAT "\nВведите диаметр ступени" (ITОА i) " d = "))
1 (GETDIST "\nВведите длину ступени 1= "))
);id
(DEFUN STO ( ) ;Функция для изображения первой
;ступени
(SETQ p1 (POLAR bp (/ PI 2) (/ d 2))
p2 (POLAR p1 01)
p3 (POLAR p2 (* 1.5 PI) d)
p4 (POLAR p3 PI 1)
pl (POLAR bp 0 1) ;pl - базовая точка для новой ступени
)
(COMMAND "PLINE" p1 "W" 0.5 0.5 p2 p3 p4 "С")
(SETQ d0 d)
(SETQ sp (LIST (LIST p2 p3))); подготовка списка
; пар точек для простановки диаметров
);st0
(DEPUN ST1 ( ) ; Функция для изображения ступени
; с меньшим диаметром
(SETQ p1 (POLAR pl (/ PI 2) (/ d 2))
p2 (POLAR pi 01)
p3(POLAR p2(*1.5PI)d)
p4 (POLAR p3 PI 1)
pl (POLAR pl 01)
)
(COMMAND "PLINE" p1 "W" 05 05 p2 p3 p4" ")
(SETQ d0 d)
(SETQ sp (CONS (LIST p2 p3) sp)) ; дополнение
;списка точек
); sti
(DEFUN ST2 ( ) ; Функция для изображения ступени
; с большим диаметром
(SETQ p1 (POLAR pl (/ PI 2) (/ d0 2))
p2 (POLAR p1 (/ PI 2) (/ d 2))
p3 (POLAR p2 01)
p4 (POLAR p3(* 1.5 PI) d)
p5 (POLAR p4 PI 1)
p6 (POLAR pl ('1.5 PI) (/ d0 2))
pl (POLAR pl 01)
)
(COMMAND "PLINE" p1 "W" 0.5 0.5 p2 p3 p4 p5p6" ")
(SETQ d0 d)
(SETQ sp (CONS (LIST p3 p4) sp))
); st2
(DEFUN RZM ( ) ; Функция для простановки размеров
;ступеней
(PROMPT "\nНужно ли проставлять диаметры? <да>")
(IF ( = (READ-CHAR) 10) ; В случае ответа
; < Enter >, т.е. "Да":
(FOREACH рр sp ; Цикл по элементам
; списка sp - парам точек
(SETQ pl (CARpp)
; Выделение первой точки
p2(CADRpp)
; Выделение второй точки
рЗ (LIST (- (CAR p1) 10) (CADR p1))
; Точка для размерной линии
)
(COMMAND "DIM1" "VER" p1 p2 рЗ
"%%с< >")
; Простановка диаметра
);foreach
);if
(SETQ pr (GETPOINT "\nУкажите точку для простановки первого размера")
sp (REVERSE sp)
; Реверсирование списка точек
рр (NTH 0 sp)
; Выделение первой пары точек из списка
pl (CADR pp)
; Выделение второй (нижней) точки из пары
)
(COMMAND "DIM" "HOR" bp p1 pr" ")
;Простановка длины первой ступени
(SETQ sp (CDR sp)) ; Удаление первой пары точек
;из списка
(FOREACH рр sp ;Цикл по оставшемуся списку пар
(SETQ p1 (CADR рр))
(COMMAND "BAS" р1" ")
;Простановка длины ступени от базы
);foreach
(COMMAND)
; Завершение команды DIM - аналог Ctrl/C
);dia
(DEFUN C:VAL ( ) ; Головная функция - построение
;изображения вала
(SETVAR "CMDECHO" 0) ;Отмена эха команд
(SETVAR "BLIPMODE" 0)
;Отмена маркировки точек примитивов
(SETQ bp (GETPOINT "\nУкажите базовую точку"))
(INITGET 7)
;3апрет на ввод неположительных чисел и пробела
(SETQ n (GETINT "\nВведите число ступеней вала n = "))
(SETQ i 1) ; i - номер ступени
(ID) ; Ввод исходных данных для
; первой ступени
(STO) ; Изображение первой ступени
(WHILE ( < i n) ;Цикл по числу ступеней
(SETQ i (1+i))
(ID); Ввод исходных данных для i-й ступени
(IF(<d d0)
(ST1) ;Изображение ступени с меньшим диаметром
(ST2) ;Изображение ступени с большим диаметром
);if
); while
(RZM) ;Простановка размеров
(COMMAND "LINETYPE" "S" "CENTER" "" "LINE"
(POLAR bp PI 5) (POLAR pi 0 5) "")
; Изображение осевой линии
(PRIN1) ;"Тихий выход" из программы
)