После выполнения сложной серии поворотов и перемещений я хочу вернуть текущее направление на «север», указывающее вверху страницы.Как я могу это сделать?
Очевидный ответ - отслеживать, в каком направлении я указываю каждый раз, когда я переводю, но это кажется большой работой.Я хочу что-то вроде «0 rotateto», которое оставляет меня в текущем местоположении, но указывает на абсолютную верхнюю часть страницы;аналогично, «90 rotateto» будет указывать вправо.
Я также хочу знать, как перейти к определенной точке на странице после серии поворотов и переводов.Другими словами, я ищу инструкцию «абсолютное перемещение», которая перемещается в конкретную точку, не относящуюся к текущим переведенным координатам.
Моя цель - реализовать черепаху в стиле логотипа.Две из команд, которые распознает черепаха, это setpos (которая перемещается в абсолютную позицию) и setorientation (которая вращается в абсолютном направлении).Я пытаюсь выяснить, как реализовать эти команды в PostScript.
РЕДАКТИРОВАТЬ 1:
Спасибо, luser droog, но что-то все еще не так.Моя библиотека включает команды turtle, показанные ниже, с их эквивалентами PostScript;rotateto и setpos - определения, которые вы дали ранее, is_penup - глобальная переменная, изначально установленная в true, и я еще не учел pos и ориентацию, которые сообщают текущую абсолютную позицию xy и ориентацию черепахи:
init -- %!
/rotateto { ... } bind def
/setpos { ... } def
newpath
306 396 moveto % center 8.5x11 portrait
0 setgray 2 setlinewidth
penup -- % set global variable is_penup to true
pendown -- % set global variable is_penup to false
forward n -- if is_penup then 0 n rmoveto currentpoint translate
else 0 n rlineto currentpoint translate
backward n -- if is_penup then 0 n neg rmoveto currentpoint translate
else 0 n neg rlineto currentpoint translate
right n -- n neg rotate
left n -- n rotate
setpos x y -- x y setpos
setorientation n -- n rotateto
done -- stroke newpage
pos -- get current absolute x y position
orientation -- get current absolute orientation
Пример, который рисует два квадрата, показан ниже;квадратная команда записывает четыре строки длиной 50, за которыми следует поворот вправо на 90 градусов:
init
pendown
setpos 100 100
square 50
setpos 400 400
right 45
square 25
done
Но это не сработает.Ни одна из команд setpos не соблюдается.Есть два квадрата, и второй квадрат наклонен на 45 градусов, но оба начинаются в центре страницы.Боюсь, что каждый раз, когда я говорю, что currentpoint translate мешает тому, что вы делаете в вашей команде setpos.
Можете ли вы предложить какие-либо предложения?
EDIT 2:
Я решил не беспокоиться о возвращении текущей позиции и ориентации в Схему;это слишком много работы для моей текущей цели, хотя это может пригодиться когда-нибудь в будущем.Окончательная версия кода моей Схемы показана ниже.Send - это обычная утилита, turtle-init определяет библиотеку turtle в PostScript, далее следует остальная часть библиотеки Scheme turtle, затем пример программы, которая рисует два квадрата.Все работает нормально.
(define (send x . xs)
(cond ((null? xs) (display x) (newline))
(else (display x) (display " ") (apply send xs))))
(define (turtle-init)
(for-each send '(
"%!"
"/defmat matrix defaultmatrix def"
"/fix { currentpoint translate } def"
"/rotateto { matrix rotate"
" dup 4 matrix currentmatrix 4 2 getinterval"
" putinterval setmatrix } def"
"/setpos { defmat transform itransform moveto fix } def"
"/left { rotate } def"
"/right { neg rotate } def"
"/is-pendown false def"
"/penup { /is-pendown false def } def"
"/pendown { /is-pendown true def } def"
"/done { stroke showpage } def"
"/init { initgraphics 306 396 moveto fix 0 setgray 2 setlinewidth } def"
"/forward { 0 exch is-pendown { rlineto } { rmoveto } ifelse fix } def"
"/backward { 0 exch is-pendown { rlineto } { rmoveto } ifelse fix } def")))
(define (turtle-penup) (send "penup"))
(define (turtle-pendown) (send "pendown"))
(define (turtle-forward n) (send n "forward"))
(define (turtle-backward n) (send n "backward"))
(define (turtle-right n) (send n "right"))
(define (turtle-left n) (send n "left"))
(define (turtle-setpos x y) (send x y "setpos"))
(define (turtle-setorientation n) (send n "rotateto"))
(define (turtle-done) (send "stroke showpage"))
(define (square n)
(do ((i 4 (- i 1))) ((zero? i))
(turtle-forward n) (turtle-right 90)))
(define (squares)
(turtle-init)
(turtle-pendown)
(turtle-setpos 100 100)
(square 50)
(turtle-setpos 400 400)
(turtle-right 45)
(square 25)
(turtle-done))
(with-output-to-file "squares.ps"
(lambda () (squares)))
Это все появится в моем блоге некоторое время в январе;Я еще не уверен в точной дате.
Спасибо!
РЕДАКТИРОВАТЬ 3:
Я вернулся и прочитал документацию по черепашке с логотипом и обнаружил, что setposуважает текущее состояние пера;таким образом, если ручка не работает, setpos записывает линию из старой позиции в новую позицию.Я изменил setpos, чтобы иметь правильное поведение:
/setpos { defmat transform itransform is-pendown
{ lineto } { moveto } ifelse fix } def
Я также изменил turtle-init так, что он фактически вызывает init, а не просто определяет его.Не очень полезно, если вы никогда не звоните.