Processing 的2D坐标

在我们开始玩Processing的时候,凌顺实验室(lingshunlab.com)觉得需要先认识的是processing的坐标系。

因为在绘图的时候,有很多2D的绘画函数方法都需要XY坐标,如果构建3D立体的话更是需要XYZ坐标。

不过,这次先把焦点放在2D上,试试理解Processing 2D的坐标系。通过获取这个坐标系,我们也学会一些绘图函数方法。例如,画线段,圆形,写文字,鼠标属性。

定义画布

首先,要理解画布的概念,
例如我要开始画画,先拿一张A4大小的纸,297 mm × 210 mm。
就好比,我在processing/p5.js使用size(600,400)这个代码,定义了Processing画布的大小,长(x轴)为600像素,宽(y轴)400像素。

size(600,400)中的第一个参数是是定义画布的宽度,也是X轴的长度,第二个参数 定义的是 画布的高度,也就是 Y周的长度。在Processing中最小的画布限制在宽100像素,高100像素中,如果设置小于此像素的画布会强制设定为100x100。

要是在画布外的区域画东西,例如在坐标(700,600)里画一个点 , 其结果是看不到的,但程序还是会处理的。

size() 官方详细说明请点击
https://processing.org/reference/size_.html

设定背景颜色

接下来,设置一下背景色,默认背景为浅灰色。
设置画布的背景色使用background(0);这函数就可以设置,其中如果只是输入一个参数的话,就是指定介于白色和黑色之间的值,0为黑色,255为白色。
也可以输入3个参数,例如background(100,100,100);,这时第一个参数表示红色(R),第二个参数表示绿色(R),第三个参数表示蓝色(B)。通过三个参数的不同数值,可以设置不同颜色的背景色。

在本示例中,我使用白色作为背景色,可以更好的看清楚绘制的东西,其他颜色的可以自行尝试。

现在代码修改成如下:

size(600, 400);
background(255);

点击运行,我们将获得一张600x400像素,白色背景的画布

background() 官方详细说明请点击
https://processing.org/reference/background_.html

X轴上,画一条线

此时,我们在x轴的方向,画一条直线
使用line(0,0,600,0),这个线段函数有4个参数(如果是在2D的情况下)
第一个参数,是线段的起始点坐标的x,
第二个参数,是线段的起始点坐标的y,
第三个参数,是线段的结束坐标的x,
第四个参数,是线段的结束点坐标的y,

其实,就是代表线段的两个点的坐标。在本示例中,我在x轴的0点 位置,画一条直线,现在代码如下:

size(600, 400);
background(255);
line(0,0, 600,0);

WX20230113-1215312x

line() 官方详细说明请点击
https://processing.org/reference/line_.html

Y轴上,画一条线

用同样的方法在Y轴上也画一条线段,
使用line(0, 0, 0, 400);
但是,黑色线,感觉看不出太明显,现在我把代表x轴和代表y轴的2条线段用红色绘画。

// Welcome to www.lingshunlab.com

size(600, 400);
background(255);
line(0,0, 600,0); 
line(0, 0, 0, 400);

WX20230113-1816192x

设置线段的颜色

但是,发现黑色线,不太明显,
这时候,可以使用stroke(255, 0, 0); 改变颜色,这里的设置把边线改成红色。
值得注意的是,颜色的设定需要在绘画前,就要定义好,
就好比,我要先拿起红色笔,才能画出红色的线段。

stroke(255, 0, 0) 函数有三个参数,
第一个代表的红色值(R),
第二个代表的蓝色值(G),
第三个代表的绿色值(B),

现在代码改成如下,在line()函数前就设置边线的颜色:

// Welcome to www.lingshunlab.com

size(600, 400);
background(255);
stroke(255, 0, 0);
line(0,0, 600,0);
line(0, 0, 0, 400);

WX20230113-1823082x

stroke() 官方详细说明请点击
https://processing.org/reference/stroke
.html

XY轴上,画一些圆形标记

现在已经把0点X轴和Y轴都画出来了,并以设定的呈现出来。
为了更好的理解坐标的方向,现在开始在X轴和Y轴上标记一些图形和数值。

首先,在X轴和Y轴上用圆形标记轴的0,20,40......的位置
画圆,可以使用circle(0, 0, 5);函数,
这个函数也是有3个参数,
第一个参数是,圆形中心点的坐标X
第二个参数是,圆形中心点的坐标Y
第三个参数是,圆形的半径,单位为像素

可以这样编写,

// 标记X轴的关键位置
circle(0, 20, 5);
circle(0, 40, 5);
circle(0, 60, 5);
circle(0, 80, 5);
...

// 标记Y轴的关键位置
circle(20, 0, 5);
circle(40, 0, 5);
circle(60, 0, 5);
circle(80, 0, 5);
...

但是,上面的这种编写方法有点笨,而且不好管理
可以使用for循环语句,

for(int i = 0; i < 600;i = i + 20) {
    circle(0, i, 5);
    circle(i, 0, 5);
}

现在完整的代码如下:

// Welcome to www.lingshunlab.com

size(600, 400);
background(255);
stroke(255, 0, 0);
line(0,0, 600,0);
line(0, 0, 0, 400);

for(int i = 0; i < 600;i = i + 20) {
  circle(0, i, 5);  // 标记X轴的关键位置
  circle(i, 0, 5);  // 标记Y轴的关键位置
}

WX20230113-2023092x

for语句 官方详细说明请点击
https://processing.org/reference/stroke_.html

关键点添加数字

有了关键点,现在把关键点的数值都标记上去。
这里会使用到 两个函数,

一个是fill(0);用于设置填充色,在这里设置字体的颜色.
fill(0);有一个参数,指定介于白色和黑色之间的值,0为黑色,255为白色。
也有三个参数代表RGB设置其他颜色的用法,具体请查看fill()函数的文档。
fill(0);函数和stroke()函数类似,前者是设置填充色,后者是设置边线颜色。都需要在绘画前就定义好,
对于字体没有边线,所用需要设置填充色定义文字的颜色。

另一个是text(str, x, y);,指定坐标为起点,绘画出文字内容。
第一个参数,是绘画出的内容,
第二个参数,是绘画出内容的起始坐标X,
第三个参数,是绘画出内容的起始坐标Y,

现在,代码修改成如下:

// Welcome to www.lingshunlab.com

size(600, 400);
background(255);
stroke(255, 0, 0); 
line(0,0, 600,0); 
line(0, 0, 0, 400);

fill(0); //定义填充色为黑色
for(int i = 0; i < 600;i = i + 20) {
  circle(0, i, 5);  // X轴
  circle(i, 0, 5);  // Y轴
  text(i, i-5, 15);       // X轴关键点的数值
  text(i, 15, 10+ i - 5); // X轴关键点的数值
}

WX20230113-2105352x

fill() 官方详细说明请点击
https://processing.org/reference/fill_.html
text() 官方详细说明请点击
https://processing.org/reference/text_.html

大致上,processing 2D的坐标系,就绘制出来了,可以看到坐标的0点是在画布的左上角。

显示当前鼠标的坐标

现在,可以添加一些交互,例如显示鼠标当前的坐标值,这样就更好的理解2D的坐标系。

但由于刚才我们所编程的程序,都是只执行一次的,所用没办法,不断的检测鼠标当前的位置,所以在这里引用一个编程概念,在processing/p5.js中有setup()draw()这两个函数。代码结构如下,也是一个标准的processing/p5/js 的代码格式

// 初始化函数
void setup(){
    ...
    //setup内可以放置程式启动时要做的事情,例如是设定背景颜色或画布大小。
    //setup只运行一次。
}

void draw() {
    ...
    //draw内的代码则是每次画面更新要做什麽事情,像是各种绘制的变化等等
    //draw会不断重复运行里面的代码,如果玩过Arduino 就感觉这不就是loop()函数吗
}

通过这样的代码结构,就可以开始思考,怎么把刚才的代码分一分,哪些是只需要执行一次,哪些是需要执行多次的。

只需要执行一次的就是画布大小
要不断执行的是需要绘制坐标的代码和不间断检测和绘制出测鼠标当前位置的代码。
代码改动如下

    // Welcome to www.lingshunlab.com
void  setup() {  // // 初始化
  size(600, 400);
}

void draw() { // 重复
  background(255);
  stroke(255, 0, 0);
  line(0,0, 600,0);
  line(0, 0, 0, 400);

  fill(0); //定义填充色为黑色
  for(int i = 0; i < 600;i = i + 20) {
    circle(0, i, 5);  // X轴
    circle(i, 0, 5);  // Y轴
    text(i, i-5, 15);       // X轴关键点的数值
    text(i, 15, 10+ i - 5); // X轴关键点的数值
  }
}

这时候,可能想问,为什么绘制坐标的代码也要不断显示呢?不是只需要绘制一次坐标就可以了吗?
在这里我们会认识并使用一个函数clear();,用于清除画布上所有绘制的东西包括画布背景颜色,也就是清空画面,如果我每次获取并显示鼠标的位置,不用clear()这个函数的话,就会不断的重叠鼠标位置的信息,新的旧的都会一直显示。

接下来,开始添加鼠标事件。
其实,processing/p5.js 的开发就是用于更简单的做交互艺术,生成艺术的。
所以内置了一些变量,可以直接用非常的方便。
例如鼠标的坐标位置,可以通过mouseXmouseY这两个变量轻松获取。
鼠标的位置画一个小圆的代码如下:

circle(mouseX, mouseY, 2);
// Welcome to www.lingshunlab.com
void  setup() {
  size(600, 400);
}

void draw() {
  clear();
  background(255);
  stroke(255, 0, 0); 
  line(0,0, 600,0); 
  line(0, 0, 0, 400);

  fill(0); //定义填充色为黑色
  for(int i = 0; i < 600;i = i + 20) {
    circle(0, i, 5);  // X轴
    circle(i, 0, 5);  // Y轴
    text(i, i-5, 15);       // X轴关键点的数值
    text(i, 15, 10+ i - 5); // X轴关键点的数值
  }

  //文字方式显示鼠标当前的坐标数值
  text(" ( "+ str(mouseX)+ ", " + str(mouseY)+ " )", mouseX+5, mouseY+5);
  //在鼠标当前坐标上画一个小圆
  circle(mouseX, mouseY, 2);
}

WX20230113-2230052x

现在在画布上移动,鼠标,就会看到鼠标当前位置的XY坐标值。
有兴趣的,还可以试试去掉clear()后,会发生什么改变,就能对为什么要使用clear()这个函数有更深刻的理解。

关于mouseX和mouseY的官方文档
https://processing.org/reference/mouseX.html
https://processing.org/reference/mouseY.html
clear()的官方文档
https://processing.org/reference/clear_.html