 |
| (setq pfirst (polar sp pangle pd))
| (setq pctile (polar pfirst angp90 offset))
| (setq p1tile pctile)
| (while (< (distance pfirst p1tile) (- hwidth trad))
| (command "circle" p1tile trad)
| (setq p1tile (polar p1tile angp90 (+ tspac trad trad)))
| )
| (setq p1tile (polar pctile angm90 (+ tspac trad trad)))
| (while (< (distance pfirst p1tile) (- hwidth trad))
| (command "circle" p1tile trad)
| (setq p1tile (polar p1tile angm90 (+ tspac trad trad)))
| )
| )
|
| ; Draw the rows of tiles
|
| (defun drawtiles ()
| (setq pdist (+ trad tspac))
| (setq off 0.0)
| (while (<= pdist (- plength trad))
| (drow pdist off)
| (setq pdist (+ pdist (* (+ tspac trad trad) (sin (dtr
60)))))
| (if (= off 0.0)
| (setq off (* (+ tspac trad trad) (cos (dtr 60))))
| (setq off 0.0)
| )
| )
| )
Для лучшего понимания работы этой функции, обратимся к рисунку на
следующей странице. Функция DROW рисует ряд плиток на расстоянии друг
от друга вдоль дорожки, задаваемым первым аргументом функции, и
сдвигает этот ряд перпендикулярно дорожке на расстояние, задаваемое
вторым аргуменнтом функции. Мы будем сдвигать плитки, чередуя их ряды,
для более плотного заполнения дорожки плитками.
Функция DROW определяет место расположения в ряду первой плитки,
используя функцию POLAR для отступа от края дорожки на расстояние,
которое задается первым аргументом; затем функция POLAR используется
снова, находя расстояние, перпендикулярное дорожке, для последующей
сдвижки рядов. С помощью функции WHILE продолжается отрисовка
окружностей, пока не будет достигнута граница дорожки. Функция SETQ,
которой завершается WHILE-цикл вычисляет место расположения следующей
плитки, сдвигая ее на расстояние, равное двум радиусам плитки плюс
пространство между плитками.
После этого, с помощью второго WHILE-цикла, рисуется ряд плиток в
- 18 -
Руководство пользователя по АВТОЛИСПу
другом направлении, пока не будет достигнута следующая граница
дорожки.
Функция DRAWTILES многократно вызывает функцию DROW, для
отрисовки всех рядов плиток. Здесь WHILE-цикл "шагает" по дорожке,
обращаясь к функции DROW для отрисовки каждого ряда. Смежные плитки
расположены в виде правильного треугольника, как показано на рисунке.
Сторона треугольника равна двум радиусам плитки плюс расстояние между
ними. Таким образом, как следует из тригонометрии, расстояние вдоль
дорожки между рядами равно синусу 60 градусов, умноженному на эту
величину, а смещение нечетных рядов - косинусу 60 градусов,
умноженному на нее.
Обратите внимание на то, как используется функция IF в функции
DRAWTILES для смещения каждого следующего ряда. Функция IF тестирует
свой первый аргумент и, если значением его является "истина" -
выполняет второй аргумент, иначе - выполняет третий аргумент. Таким
образом, если значение переменной OFF равно нулю, мы присваиваем ей
значение, равное произведению расстояния между центрами плиток на
косинус 60 градусов. Если же значение OFF не равно нулю, мы
присваиваем ей значение, равное нулю. Так организуется чередование
рядов, что и требовалось.
Для проверки работы функции, запишите обновленный файл GP.LSP на
диск, войдите в AutoCAD, начните новый рисунок и загрузите LISP-файл
так же, как Вы делали это раньше. Введите:
Command: (gpuser)
и сообщите информацию о дорожке, как прежде. Введите:
Command: (drawout)
и появится контур дорожки. Hаконец, введите:
Command: (drawtiles)
и контур заполниться плитками.
3.7 Добавим Hовую Kоманду В AutoCAD
Теперь мы готовы собрать из наших кусочков команду AutoCADа. Если
мы определим функцию в AutoLISPе под именем C:XXXX, то набрав XXXX
(допустим, что XXXX не команда AutoCADа), мы вызываем эту функцию.
Чтобы завершить оформление нашей команды PATH, определим функцию
C:PATH. Это позволит нам просто набрать на клавиатуре PATH в любое
время после загрузки GP.LSP, чтобы выполнить команду, рисующую
парковую дорожку.
Вызовите Ваш текстовый редактор и добавьте отмеченные строки в
программу:
; Convert angle in degrees to radians
(defun dtr (a)
(* pi (/ a 180.0))
- 19 -
Руководство пользователя по АВТОЛИСПу
)
; Acquire information for garden path
(defun gpuser ()
(setq sp (getpoint "\nStart point of path: "))
(setq ep (getpoint "\nEnd point of path: "))
(setq hwidth (getdist "\nHalf width of path: " sp))
(setq trad (getdist "\nRadius of tiles: " sp))
(setq tspac (getdist "\nSpacing between tiles: " sp))
(setq pangle (angle sp ep))
(setq plength (distance sp ep))
(setq width (* 2 hwidth))
(setq angp90 (+ pangle (dtr 90))) ;Path angle + 90 deg
(setq angm90 (- pangle (dtr 90))) ;Path angle - 90 deg
)
; Draw outline of path
(defun drawout ()
(command "pline"
(setq p (polar sp angm90 hwidth))
(setq p (polar p pangle plength))
(setq p (polar p angp90 width))
(polar p (+ pangle (dtr 180)) plength)
"close"
)
)
; Place one row of tiles given distance along path
; and possibly offset it
(defun drow (pd offset)
(setq pfirst (polar sp pangle pd))
(setq pctile (polar pfirst angp90 offset))
(setq p1tile pctile)
(while (< (distance pfirst p1tile) (- hwidth trad))
(command "circle" p1tile trad)
(setq p1tile (polar p1tile angp90 (+ tspac trad trad)))
)
(setq p1tile (polar pctile angm90 (+ tspac trad trad)))
(while (< (distance pfirst p1tile) (- hwidth trad))
(command "circle" p1tile trad)
(setq p1tile (polar p1tile angm90 (+ tspac trad trad)))
)
)
; Draw the rows of tiles
(defun drawtiles ()
(setq pdist (+ trad tspac))
(setq off 0.0)
(while (<= pdist (- plength trad))
(drow pdist off)
(setq pdist (+ pdist (* (+ tspac trad trad) (sin (dtr
- 20 -
Руководство пользователя по АВТОЛИСПу
60)))))
(if (= off 0.0)
(setq off (* (+ tspac trad trad) (cos (dtr 60))))
(setq off 0.0)
)
)
)
| ; Execute command, calling constituent functions
|
| (defun C:PATH ()
| (gpuser)
| (drawout)
|