Oh!Coder

Coding Life

有趣的Processing-2D图形变换

| Comments

在之前学习中,我们学习了画图形,学习了展示图片,并且学习了组成它们的基本元素——像素。可惜的是,它们都是固定,不能移动。这一次呢,就让我们学习一下,尝试一下如何让图形移动起来!

不管是2D还是3D图形,它们的变换,通常来说分为三种类型,分别是平移,旋转和缩放。既然如此,我们就分别从这三个角度分别来看看,Processing中的2D图形变换是怎样的。好!接下来,我们就先说平移。

平移

通常来讲,Processing的窗口可以看作是一张图纸。当想在上面画出一些图形的时候,图纸上默认会有一个坐标系。所有你想画的图形或加载进来的图片,它们都会被固定的展示在这个坐标系的某个位置上。每个图形或图片,都有其自身的坐标值。平移一张图片或图形,我们一般有两种方法,第一种是改变图形自身的坐标,第二种是改变Processing窗口坐标系的坐标。

下面,我们用两个例子,来分别学习他们。

首先,让我们新建一个项目窗口,如下图所示。

processing-new-window

图片来源:Processing新项目窗口

将如下代码填入其中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 环境初始化。
// 此方法在软件启动时,被系统调用一次。
void setup()
{
  // 设置窗口大小
  size(200, 200);
  // 设置窗口背景颜色
  background(255);
  // 不显示边框
  noStroke();
  // 矩形的填充色为灰色
  fill(192);
  // 画矩形
  rect(20, 20, 40, 40);
  // 设置填充色为半透明红色
  fill(255, 0, 0, 128);
  // 画矩形
  rect(20 + 60, 20 + 80, 40, 40);
}
// 画图。
// 此方法被系统默认循环调用。
void draw(){
  // 此处无代码
}

完成后,点击项目窗口中,菜单栏里的三角形按钮,如下图所示。

processing-window-menu

图片来源:Processing新项目窗口中的菜单栏

编译并运行这段代码,会看到如下图所示的运行结果。

processing-fun-transform2d-1

图片来源:Processing程序执行结果

在上面的示例中,我们通过移动矩形的坐标,达到了平移矩形的效果。实际方法很简单,只是修改了rect()方法的x, y坐标值而已。接着,让我们看看第二种平移图形的方法,即平移Processing窗口坐标系。

首先,还是新建一个项目窗口。接着,将如下代码填入其中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 环境初始化。
// 此方法在软件启动时,被系统调用一次。
void setup()
{
  // 设置窗口大小
  size(200, 200);
  // 设置窗口背景色
  background(255);
  // 不画边框
  noStroke();
  // 设置填充色为灰色
  fill(192);
  // 画矩形
  rect(20, 20, 40, 40);
  // 改变填充色为半透明蓝色
  fill(0, 0, 255, 128);
  //保存坐标系统的当前位置
  pushMatrix();
  // 平移坐标系统位置,
  // x轴向右平移60,
  // y轴向下平移80
  translate(60, 80);
  // 画矩形
  rect(20, 20, 40, 40);
  // 恢复坐标系统之前的位置
  popMatrix();
}
// 画图。
// 此方法被系统默认循环调用。
void draw(){
  // 此处无代码
}

点击菜单栏里的倒三角按钮,编译并运行这段代码。

processing-fun-transform2d-2

图片来源:Processing程序执行结果

运行结果如上图所示。看!除了设置的颜色不同以外,平移位置的效果是一样的。例子中出现了三个新面孔,分别是pushMatrix()popMatrix()以及translate()。这里的pushMatrix()popMatrix()两个方法通常来讲都是成对使用。pushMatrix()方法的作用,是保存窗口坐标系的当前位置,也就是说,pushMatrix()方法会暂时保存已经执行了的坐标系状态。紧接着调用translate(60, 80)方法,将接下来的坐标系的x轴坐标向右移动60, y轴向下移动80。然后调用rect(20, 20, 40, 40)方法,画出矩形。需要理解的是,虽然这里的画出矩形的坐标位置是(20, 20),但因为此时整个窗口的坐标系x轴已经向右移动了60,y轴向下移动了80,所以实际上,矩形在整个窗口的显示位置是(20 + 60, 20 + 80)。最后调用popMatrix()方法,恢复调用pushMatri()之前的坐标系位置。此时如果在popMatrix()方法后再画图,则整个坐标系又会恢复到窗口左上角为(0, 0)点的位置状态。

旋转

对于旋转来讲,常见方法就只有一种了,需要配合使用pushMatrix()方法和popMatrix()方法。下面我们还是以例子来进行说明。

新建一个项目窗口,将下面代码填入其中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 环境初始化。
// 此方法在软件启动时,被系统调用一次。
void setup()
{
  // 设置窗口大小
  size(200, 200);
  // 设置背景色
  background(255);
  // 设置填充色为灰色
  fill(192);
  // 需要显示边框
  noStroke();
  // 画矩形
  rect(40, 40, 40, 40);
  // 保存当前坐标系位置 
  pushMatrix();
  // 旋转坐标系45弧度,
  // 角度值是90度
  rotate(radians(45));
  // 设置填充色为白色
  fill(0);
  // 画矩形
  rect(40, 40, 40, 40);
  // 恢复当前坐标系位置
  popMatrix();
}
// 画图。
// 此方法被系统默认循环调用。
void draw(){
  // 此处无代码
}

运行上面的示例代码,如果一切顺利,可看到如下运行结果。

processing-fun-transform2d-3

图片来源:Processing程序执行结果

这个小示例中出现了一个新面孔,就是rotate()方法。和上一个示例中的translte()方法类似,这个方法起到的作用是旋转整个坐标系。图中黑色的图形就是我们旋转之后的矩形。咦?你会发现这个图形是个三角形,不是之前的矩形了。其实它还是矩形,只不过因为之前旋转了整个坐标系,导致窗口把矩形挡住了一半。它的本来面目其实是这样的:

processing-fun-transform2d-4

图片来源:Processing官网

通过这张图,就可以很清晰的看明白,矩形为什么只显示一半了。

方法rotate()传入的参数类型为弧度,如果你想通过360度的角度单位做参数,那么需要借助radians()方法,将角度转换成弧度,就像我们示例中那样,如果想顺指针旋转45度,可以调用radians(45),如果想逆时针旋转45度,可以调用radians(-45)。先将坐标系旋转,然后再画出矩形。

缩放

平移,旋转,缩放是最基本的三种图形变换。下面我们学习最后一种,对图形的缩放。

我们还是通过小例子来学习。首先还是新建一个项目窗口。把如下代码添加进去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 环境初始化。
// 此方法在软件启动时,被系统调用一次。
void setup()
{
  // 设置窗口大小
  size(200,200);
  // 设置背景色
  background(255);
  // 设置边框颜色
  stroke(128);
  // 画矩形
  rect(20, 20, 40, 40);
  // 设置边框颜色
  stroke(0);
  // 保存当前坐标系位置 
  pushMatrix();
  // 将坐标系比例放大2倍
  scale(2.0);
  // 画矩形
  rect(20, 20, 40, 40);
  // 恢复当前坐标系位置
  popMatrix();
}
// 画图。
// 此方法被系统默认循环调用。
void darw(){
  // 此处无代码
}

编译并运行上述代码,运行结果类似如下图所示。

processing-fun-typography-7

图片来源:Processing程序执行结果

这里出现了一个新面孔,那就是scale()方法。此方法的使用很简单,传进去的值,如果大于1.0,则是放大,如果大于0小于1.0,则是缩小。从运行结果中也可以看出,矩形缩放的焦点是中心。对于图形缩放来说,当然也可以直接修改图形的大小,以此来达到同样的效果。

总结

通过这次学习,我们知道了2D图形的基本变换,包括平移,旋转和缩放。涉及到的方法,除了基本的平移方法translate(),旋转方法rotate()以及缩放方法scale()以外,还有pushMatrix()方法和popMatrix()方法。后两个方法,通常需要成对使用。

下期预告

这次学习完成后,我们知道了图形的基本变换。为了巩固这次的学习,下次我们将利用这次学习的知识,完整的做一个会动的机器人!

Comments