向北旋转 [英] Rotate to North

查看:79
本文介绍了向北旋转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

经过一系列复杂的旋转和平移之后,我想将当前方向返回指向页面顶部的北。我该怎么做?

After doing a complicated series of rotations and translations, I want to return the current direction to "North" pointing at the top of the page. How can I do that?

显而易见的答案是每次翻译时都要跟踪我所指的方向,但这似乎是很多工作。我想要类似 0rotateto的内容,使我停留在当前位置,但指向页面的绝对顶部;类似地, 90 rotationto将指向右。

The obvious answer is to keep track of what direction I am pointing each time I translate, but that seems like a lot of work. I want something like "0 rotateto" that leaves me at the current location but pointing to the absolute top of the page; similarly, "90 rotateto" would point right.

我还想知道在一系列旋转和平移后如何移动到页面上的特定点。换句话说,我正在寻找一条绝对移动到指令,该指令移动到特定点,而不是相对于当前翻译的坐标。

I also want to know how to move to a specific point on the page after a series of rotations and translations. In other words, I'm looking for an "absolute moveto" instruction that moves to a specific point, not relative to the current translated coordinates.

我的目的是实现徽标风格的乌龟。乌龟可以识别的两个命令是setpos(移动到绝对位置)和setorientation(旋转到绝对方向)。我试图弄清楚如何在PostScript中实现这些命令。

My purpose is to implement a logo-style turtle. Two of the commands that a turtle recognizes are setpos (which moves to an absolute position) and setorientation (which rotates to an absolute direction). I'm trying to figure out how to implement those commands in PostScript.

编辑1:

感谢luser droog,但还是有问题。我的库中包括以下显示的turtle命令及其PostScript等效项; rotationto和setpos是您之前提供的定义,is_penup是一个初始设置为true的全局变量,我还没有考虑过pos和orientation,它们报告了乌龟当前的绝对xy位置和方向:

Thanks luser droog, but something is still wrong. My library includes the turtle commands shown below with their PostScript equivalents; rotateto and setpos are the definitions you gave previously, is_penup is a global variable initially set to true, and I haven't yet considered pos and orientation, which report the current absolute x y position and orientation of the turtle:

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

绘制两个正方形的示例如下所示; square命令将写入四行长度为50的行,每行之后右转90度:

An example that draws two squares is shown below; the square command writes four lines of length 50, each followed by a 90 degree right turn:

init
pendown
setpos 100 100
square 50
setpos 400 400
right 45
square 25
done

但这不起作用。两个setpos命令都不被接受。有两个正方形,第二个正方形倾斜45度,但两者都始于页面中心。恐怕每次我说currentpoint翻译时,都会干扰您在setpos命令中所做的工作。

But that doesn't work. Neither of the setpos commands is honored. There are two squares, and the second square is tilted at 45 degrees, but both begin at the center of the page. I'm afraid that each time I say currentpoint translate I interfere with what you are doing in your setpos command.

您能提供任何建议吗?

编辑2:

我决定不担心将当前的职位和方向返回给Scheme;就我目前的目的而言,这太繁琐了,尽管将来可能会有用。我的Scheme代码的最终版本如下所示。 Send是一个常见的实用程序,turtle-init在PostScript中定义了乌龟库,随后是Scheme乌龟库的其余部分,然后是绘制两个正方形的示例程序。一切正常。

I decided not to worry about returning the current position and orientation to Scheme; that's too much work for my current purpose, though it may be useful sometime in the future. The final version of my Scheme code is shown below. Send is a common utility, turtle-init defines the turtle library in PostScript, the rest of the Scheme turtle library follows, then the sample program that draws two squares. It all works fine.

(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)))

这些都将出现在我的博客一月的某个时候;我不确定确切的日期。

This will all appear at my blog some time in January; I'm not yet sure of the exact date.

谢谢!

编辑3:

我回过头来阅读徽标龟的文档,发现setpos符合笔的当前状态。因此,如果笔向下,setpos会从旧位置到新位置写一条线。我将setpos更改为正确的行为:

I went back and read the documentation for the Logo turtle, and discovered that setpos honors the current state of the pen; thus, if the pen is down, setpos writes a line from the old position to the new position. I changed setpos to have the correct behavior:

/setpos { defmat transform itransform is-pendown
    { lineto } { moveto } ifelse fix } def

我还更改了turtle-init,以便实际上调用init而不是仅仅定义它。

I also changed turtle-init so that it actually calls init instead of merely defining it. Not much use if you never call it.

推荐答案

首先,y轴默认指向北。因此,可以使用 matrix defaultmatrix setmatrix 重置任何常规平移和旋转。您可以重置缩放和旋转,而无需使用 matrix currentmatrix dup 0 matrix defaultmatrix 0 4 getinterval putinterval setmatrix 之类的东西进行修改。

Well, to start with, the y-axis points north by default. So any normal translations and rotations can be reset with matrix defaultmatrix setmatrix. You can reset the scaling and rotation without modifying the translation with something like matrix currentmatrix dup 0 matrix defaultmatrix 0 4 getinterval putinterval setmatrix.

如果您可以忽略缩放比例,则可以执行如下所示的rotateto(假设当前位置是用户空间的原点):

If you can ignore scaling, you could do rotateto (assuming the current position is the origin of user space) like this:

/rotateto { % angle  rotateto  -
    matrix rotate % create a rotation matrix
    dup 4
    matrix currentmatrix 4 2 getinterval %get the current translation
    putinterval setmatrix % put translation into rot. matrix and install
} bind def

要设置绝对位置,您需要进行一些转换。

To set an absolute position, you'll need to do a few transformations.

通常,指定的任何坐标都指向用户空间。这意味着在生效之前,将它们乘以当前转换矩阵。设置绝对位置意味着将坐标解释为是指绝对空间。唯一的特权空间是默认矩阵。

Normally, any coordinates specified refer to user space. That means they are multiplied by the Current Transformation Matrix before taking effect. To set an "absolute" position means interpreting coordinates as refering to an "absolute space". The only such priviledged space is the Default Matrix.

/setpos { % x-abs y-abs  setpos  -
    matrix defaultmatrix transform % x' y'  %to device space
    itransform % x y  %back to current user space
    translate
} def

编辑:这很棘手!我能够让您的测试与这套程序一起使用。

This is tricky stuff! I was able to get your test to work with this suite of procedures.

%!
/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
/pos { matrix currentmatrix 4 2 getinterval {} forall } def
/forward { 0 exch is-pendown { rlineto } { rmoveto } ifelse fix } def
/backward { 0 exch is-pendown { rlineto } { rmoveto } ifelse fix } def

/square { 4 { dup forward 90 right } repeat pop } def
init
pendown
100 100 setpos
50 square
400 400 setpos
45 right
25 square
done

一件事使我绊倒记得每次移动(包括初始移动)后都进行当前点翻译

One thing that tripped me up was remembering to currentpoint translate after every move (including the initial move).

对于方向,则必须解释矩阵。 在提出建议之前,我需要对此进行一些思考。首先,请记住旋转矩阵看起来像[cosA sinA -sinA cosA 0 0]。

For orientation, you'll have to "interpret" the matrix. I'll need to do some pondering on this before making suggestions. For a head-start, remember that a rotation matrix looks like [ cosA sinA -sinA cosA 0 0 ].

这篇关于向北旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆