您对图像的解释是正确的。图像由单位正方形中的线段组成,其中原点 (0, 0) 是左下角,(1, 1) 是右上角。
画家使用问题中给出的变换将图像映射到框架中。这einsten
上面的图像是在默认框架(单位正方形)中绘制的,因此看起来很正常。
您可以使用以下命令创建并显示图像SICP图像语言 https://web.archive.org/web/20111105191213/http://planet.plt-scheme.org/package-source/soegaard/sicp.plt/2/1/planet-docs/sicp-manual/index.html分三步:
- 定义线段列表
- 从这些线段创建一个线段画家
- 使用新的段画家调用油漆
我通过博客文章中的几个简单图像来做到这一点SICP 2.49:定义原始画家 https://web.archive.org/web/20181023051024/http://www.billthelizard.com/2011/10/sicp-249-defining-primitive-painters.html。这是一个仅使用两条线段的简单示例:
; The painter that draws an 'X' by connecting opposite corners of the frame.
(define x-segments
(list
(make-segment
(make-vect 0.0 0.0)
(make-vect 0.99 0.99))
(make-segment
(make-vect 0.0 0.99)
(make-vect 0.99 0.0))))
(define x-painter (segments->painter x-segments))
(paint x-painter)
这是我在 DrRacket 中运行最后一个命令时的结果:
您可以通过创建要绘制的新框架来翻转和旋转图像。
框架由三个向量定义:
- 起源
- 底边 (edge1)
- 左边缘 (edge2)
您可以使用transform-painter
功能文中给出 https://web.archive.org/web/20100421220225/http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html(在标题为画家的改造与结合)使用新的原点和边来转换现有的线段绘制器。
(define (transform-painter painter origin corner1 corner2)
(lambda (frame)
(let ((m (frame-coord-map frame)))
(let ((new-origin (m origin)))
(painter
(make-frame new-origin
(sub-vect (m corner1) new-origin)
(sub-vect (m corner2) new-origin)))))))
例如,如果我想绘制向左旋转45度的原始爱因斯坦图像,我只需要传递einstein
将画家与新原点、底部边缘和左侧边缘一起分割transform-painter
它将返回一个新的段画家。换句话说,我需要告诉transform-painter
在哪里绘制图像的左下角、右下角和左上角,它将完成原始线段绘制器中所有线段的变换工作。
; rotate an image 45 degrees to the left
(define (rotate-45 painter)
((transform-painter (make-vect 0.5 0.0)
(make-vect 1.0 0.5)
(make-vect 0.0 0.5))
painter))
可以执行命令(paint (rotate-45 einstein))
查看旋转后的图像。