书本 95 页的 beside
过程将一个框架分成左右两个部分:
e2 of e2 of
paint-left paint-right
0.0 , 1.0 0.5 , 1.0
^ ^
| |
| |
| |
| painter1 | painter2
| |
| |
| |
| |
+----------->+-----------> 1.0 , 0.0
0.0 , 0.0 0.5 , 0.0 e1 of
origin origin paint-right
of of
paint-left paint-right
&
e1 of
paint-left
below
操作和 beside
过程类似,但它将一个框架分成上下两部分:
e2 of paint-top
0.0 , 1.0
^
|
| painter2
origin of paint-top |
& 0.0 , 0.5 +------------------------> 1.0 , 0.5
e2 of paint-down ^ e1 of
| paint-top
| painter1
|
+------------------------> 1.0 , 0.0
0.0 , 0.0 e1 of
origin of paint-down
paint-down
根据这个示意图,给出 below
的定义:
;;; 51-below.scm
(define (below painter1 painter2)
(let ((split-point (make-vect 0.0 0.5)))
(let ((paint-top
(transform-painter painter2
split-point
(make-vect 1.0 0.5)
(make-vect 0.0 1.0)))
(paint-down
(transform-painter painter1
(make-vect 0.0 0.0)
(make-vect 1.0 0.0)
split-point)))
(lambda (frame)
(paint-top frame)
(paint-down frame)))))
below
的另一种定义是,不直接使用 transform-painter
,而是通过 beside
过程和 练习 2.50 的旋转过程来完成相关的工作。
以下是画出数字 7 的 painter1
和画出数字 9 的 painter2
的例子:
^ ^ ^ *****
| | | * *
| ********* | ********* | *****
| * | * * ? | *
| * | * * =====> +------------------------>
| * | ********* ^ *****
| * | * | *
| * | * | *
| * | * | *
+----------->+-----------> +------------------------>
(beside painter1 painter2) (below painter1 painter2)
以下是只使用 beside
和旋转来完成 below
过程的步骤:
painter1
和 painter2
调用 flip-horiz
,产生新的 painter1
和 painter2
:^ ^
| |
| ******** ********* |
| * * |
| * flip-horiz * |
| * ==============> * |
| * * |
| * * |
+-----------> <-----------+
^ ^
| ********* ********* |
| * * * * |
| * * flip-horiz * * |
| ********* ==============> ********* |
| * * |
| * * |
| * * |
+-----------> <-----------+
painter1
和 painter2
调用 rotate270
,产生新的 painter1
和 painter2
: ^ ^
| |
********* | | ***
* | rotate270 | **** *
* | =============> | ** *
* | | *
* | |
* | |
<-----------+ +----------->
^ ^
********* | |
* * | | **********
* * | rotate270 | * *
********* | ==============> | * *
* | | *****
* | |
* | |
<-----------+ +----------->
3: 使用 beside
,将新的 painter1
和 painter2
组合起来,产生 beside-painter
:
^ ^
| |
| *** | **********
| **** * | * *
| ** * | * *
| * | ******
| |
| |
+----------->+----------->
4: 对 beside-painter
调用 rotate90
,产生新的 beside-painter
:
***** ^
* * |
***** |
* |
<--------------------------+
***** ^
* |
* |
* |
<--------------------------+
5: 对新的 beside-painter
调用 flip-horiz
,得出和 below
一样的效果:
^ *****
| * *
| *****
| *
+-------------------------->
^ *****
| *
| *
| *
+-------------------------->
前面的这五个步骤实际上是一个回溯得出的计算结果,从最后一步往前看,会更容易弄清楚这个 below
的效果是如何实现的。
另外,在对图形进行翻转的时候,我们假设图片是自伸缩的,也即是,它可以自动地根据框架的大小来进行放大和缩小。在一个实际的图形处理语言中,进行翻转的时候,还必须进行缩放,确保图片能正确地显示在给定的框架内。
这个 below
的定义如下:
;;; 51-another-below.scm
(define (below painter1 painter2)
(lambda (frame)
((flip-horiz
(rotate90
(beside
(rotate270
(flip-horiz painter1))
(rotate270
(flip-horiz painter2)))))
frame)))