acg数字绘画(用数学代码画画你见过吗)(1)

用代码画画,必需要懂很多数学知识?如果数学基础没那么好,是否就无法肆意表达,领略其中的乐趣?

其实不然。很多时候,只要用简单的数学知识,也能做出复杂精妙的作品。

希望通过下文,可以让你破除对数学的恐惧,从基础的概念入手,与三角函数“共舞”。

什么是三角函数?

如果要问哪个数学函数在图形创作上使用频率最高,那三角函数估计能排在前几位。

三角函数,用简单的话来讲,是用来描述直角三角形边长和角度关系的函数。常用的三角函数有正弦函数( sin ),余弦函数( cos ),正切函数( tan )。

用一张图来举例。假如有一个直角三角形 ABC,其中 a,b 是直角边,c 是斜边。

acg数字绘画(用数学代码画画你见过吗)(2)

关于三角函数我们可以记住这样一个性质:直角三角形中,边与角的这种比例关系是固定的,所以无论是多大或多小的三角形,只要两个三角形比例相似,相对应两个角的 sin 值,总是恒定的,因为边长的比例固定。反过来,如果我们已知某三角形某个角的 sin,cos 或 tan 值,结合一定条件,也能反过来推算出角度值。

为了更好地理解,这里再拿一个特殊的直角三角形来举例。假如一个直角三角形它的各个角分别为 30 度,60 度,90 度。那它的对边之比,就分别为 1:√3:2。

acg数字绘画(用数学代码画画你见过吗)(3)

现在,我们只要将各边对应的比例关系代入,就能手动计算出正弦函数和余弦函数的数值。比如 sin 30 度就为 1/2 ,即 0.5。cos 30 度就为 √3/2,约等于 0.866。

这就是三角函数的数学定义。看到这里,相信你已经对它有了基本的了解,接下来我们可以学习在程序上的使用方法。

在 Processing 中使用三角函数

假如我们现在需要用程序来直接获取 sin 30 度的值,可以在 Processing 中这么写。

println(sin(PI/6));

输出结果为 0.5

acg数字绘画(用数学代码画画你见过吗)(4)

cos 30 度,则是这么写

println(cos(PI/6));

结果约等于 0.866

acg数字绘画(用数学代码画画你见过吗)(5)

但为何这里写的是 PI/6,而不是 30?这是因为 Processing 中规定,sin 函数中传入的参数采取的是弧度制。

所谓的弧度制,就是用单位圆的弧度长来表示角度。

acg数字绘画(用数学代码画画你见过吗)(6)

假设单位圆的半径为 1。根据周长公式 l = 2 π r, 那圆的周长就是 2 π。而 2 π 的弧长(周长),就对应 360 度。同理,一个角的角度如果是 30 度。那它对应的弧长(图中红线部分),就为整个圆弧长十二分之一,即 2 * π / 12,为 PI / 6。

所以程序中写 sin(PI/6) ,意思就是求 30 度的 sin 值是多少。

当然,如果你更习惯用角度制来表示。程序中还可以这么写,只要使用函数 radians,它就能自动将角度值换算成弧度值,相当方便。

println(sin(radians(30)));

acg数字绘画(用数学代码画画你见过吗)(7)

输出结果与原来一样,都为 0.5。

通过图像中认识三角函数

前面铺垫完基础知识,下面就进入正题,开始在程序中作画。首先,我们需要把三角函数的函数曲线画出来

绘制函数曲线

例子01:

PVector posA, posB; void setup() { size(700, 400); background(255); posA = new PVector(0, 0); posB = new PVector(0, 0); } void draw() { float speed = 0.02; posA.x ; posA.y = height/3 sin(posA.x * speed) * 40; posB.x ; posB.y = height/3 * 2 cos(posA.x * speed) * 40; strokeWeight(5); point(posA.x, posA.y); point(posB.x, posB.y); }

acg数字绘画(用数学代码画画你见过吗)(8)

代码浅析:

接下来,我们试着在上例的基础上,把 speed 的值改成 0.2

acg数字绘画(用数学代码画画你见过吗)(9)

又或是改得非常小,写成 0.005;

acg数字绘画(用数学代码画画你见过吗)(10)

对比原图,会发现图形被拉伸或是压缩。这是由于输入值的变化速度发生改变了。输入值变化越慢,输出值也会越慢,因而起伏越小。

如果在绘制的时候,我们还想严格地控制“波峰”“波谷”的数量。那就需要注意输入值的变化范围。

acg数字绘画(用数学代码画画你见过吗)(11)

由于 sin 函数和 cos 函数,他们的周期都为 2 π。所以当输入值的范围恰好是 2 π 的整数倍时,就可以在屏幕上绘制出与倍数相同的“波峰”“波谷”,并且是可以首尾衔接的。

试着将 speed 写成

float speed = 2 * PI * 0.01;

acg数字绘画(用数学代码画画你见过吗)(12)

因为屏幕宽为 700,所以恰好就能绘制出 7 段重复的波形,可以代入到例子中仔细思考其中的含义。

三角函数的简单应用

在程序中使用三角函数,基本就是靠这个输出值来做文章。因为 sin 和 cos 函数是可以互相转换的,所以在具体应用时,使用 sin 还是 cos 并没有太大差别。

现在,试着把 sin 值的变化,映射到圆的半径,就能产生这样的效果

例子02:

void setup() { size(700, 400); } void draw(){ background(255); float l = sin(frameCount/100.0) * 200; fill(0); ellipse(width/2,height/2,l,l); }

acg数字绘画(用数学代码画画你见过吗)(13)

映射到角度

例子03:

void setup() { size(700, 400); } void draw(){ background(255); float angle = sin(frameCount/100.0) * PI/2; translate(width/2,height/2); rotate(angle); rectMode(CENTER); fill(0); rect(0,0,200,200); }

acg数字绘画(用数学代码画画你见过吗)(14)

映射到圆的位移,利用输入值的差异产生错落效果

例子04:

void setup() { size(700, 400); } void draw() { background(255); fill(0); for (int i = 0; i <= 7; i ) { float h = sin(i/2.0 frameCount/10.0) * 100; ellipse(i * 100, 200 h, 80, 80); } }

acg数字绘画(用数学代码画画你见过吗)(15)

从上面三个小实例可以看出,若想精确地控制图形元素,就要熟悉它的周期性,控制它的输入输出范围。位移的多少,角度的变化快慢,都与之息息相关。

使用三角函数实现圆周运动

三角函数的一个重用应用,就是使用它画圆

例05:

PVector pos; void setup(){ pos = new PVector(); } void draw(){ background(255); float r = 180; pos.x = r * cos(frameCount/100.0); pos.y = r * sin(frameCount/100.0); translate(width/2,height/2); fill(0); ellipse(pos.x,pos.y,40,40); }

acg数字绘画(用数学代码画画你见过吗)(16)

具体原理可以查看下图,它可以根据三角函数的定义推导得出。想象在圆周上有一个黑色圆点在运动,它构成的直角三角形的两个直角边,就对应它的坐标值。

acg数字绘画(用数学代码画画你见过吗)(17)

而从中围成的三角形,由于

cos(α) = x / r sin(α) = y / r

很容易能推出

x = r * cos(α)y = r * sin(α)

所以我们只要在 α 处,传入一个不断自增的参数。x,y 的坐标就会输出圆周运动。

网上有其他朋友制作了这样一张动图,非常形象直观地揭示了底层原理

acg数字绘画(用数学代码画画你见过吗)(18)

巧妙!

综合应用

前面介绍的圆周运动,经过特殊组合,可以“编织”出一些非常有意思的图案

例06:

PVector posA,posB; void setup(){ size(700,700); background(0); posA = new PVector(); posB = new PVector(); } void draw(){ float r1 = 300; float speed1 = frameCount/100.0 * 4; posA.x = r1 * cos(speed1); posA.y = r1 * sin(speed1); float r2 = 150; float speed2 = frameCount/100.0; posB.x = r2 * cos(speed2); posB.y = r2 * sin(speed2); translate(width/2,height/2); stroke(255,100); line(posA.x,posA.y,posB.x,posB.y); }

acg数字绘画(用数学代码画画你见过吗)(19)

代码浅析:

试着改变传入的速度,半径

acg数字绘画(用数学代码画画你见过吗)(20)

acg数字绘画(用数学代码画画你见过吗)(21)

也可以开启叠加模式,实时改变线条的颜色

例07:

PVector posA,posB; void setup(){ size(700,400); background(0); posA = new PVector(); posB = new PVector(); } void draw(){ float r1 = 300; float speed1 = frameCount/300.0 * 4; posA.x = r1 * cos(speed1); posA.y = r1 * sin(speed1); float r2 = 150; float speed2 = frameCount/300.0; posB.x = r2 * cos(speed2); posB.y = r2 * sin(speed2); translate(width/2,height/2); colorMode(HSB); blendMode(ADD); stroke(frameCount/10.0 % 255,255,255,30); line(posA.x,posA.y,posB.x,posB.y); }

acg数字绘画(用数学代码画画你见过吗)(22)

下面的图片都是在同一个结构中,修改不同参数产生的。只是画布设置得更大,同时让线条的运动变得更平缓,这样就能产生丰富细腻的层次变化

acg数字绘画(用数学代码画画你见过吗)(23)

acg数字绘画(用数学代码画画你见过吗)(24)

acg数字绘画(用数学代码画画你见过吗)(25)

acg数字绘画(用数学代码画画你见过吗)(26)

acg数字绘画(用数学代码画画你见过吗)(27)

利用 sin 函数实现动态画笔

接下来再分享两个有关画笔的实例,这节的介绍就快到尾声

先看基础版

例08:

ArrayList<PVector> brushLines = new ArrayList<PVector>(); void setup() { size(700,700); } void draw() { background(0); for (int i = 0; i < brushLines.size(); i ) { PVector tempPos = brushLines.get(i); float l = sin(frameCount/20.0 i/4.0) * 50; ellipse(tempPos.x,tempPos.y,l,l); } } void mouseDragged() { brushLines.add(new PVector(mouseX, mouseY)); }

acg数字绘画(用数学代码画画你见过吗)(28)

拖动鼠标,就会记录绘制轨迹。sin 函数此时会控制圆点的半径。

下面再看加强版

例09:

ArrayList<PVector> brushLines = new ArrayList<PVector>(); PImage myPic; void setup() { size(1200, 700); myPic = loadImage("pic.jpg"); myPic.resize(width, height); } void draw() { background(0); noStroke(); tint(125); image(myPic, 0, 0); for (int i = 0; i < brushLines.size(); i ) { PVector tempPos = brushLines.get(i); float r = 10 * sin(i/3.0 millis()/200.0); fill(myPic.get(int(tempPos.x), int(tempPos.y))); ellipse(tempPos.x, tempPos.y, r, r); } } void mouseDragged() { brushLines.add(new PVector(mouseX, mouseY)); } void keyPressed(){ if(key == 'c'){ brushLines.clear(); } }

拖动鼠标绘制图案,按 c 键清空画布

在运行实例前,需要先寻找一张图片素材放到所在文件夹中,来作为程序的背景图片。绘制的笔触会吸取背后的图片颜色,与经过变暗处理的背景相组合,就会产生类似于发光的效果。推荐使用梵高的作品做测试,绚丽的色彩和奔放的笔触,会更相得益彰。

acg数字绘画(用数学代码画画你见过吗)(29)

acg数字绘画(用数学代码画画你见过吗)(30)

acg数字绘画(用数学代码画画你见过吗)(31)

如果做出满意作品,可以试着导出 Gif (Processing3.0 Gif动图导出技巧)

三角函数其他应用

三角函数还有其他用法吗?非常多。最后再截选一些之前的习作,它们都有用到三角函数。

(控制关节的旋转角度,模拟翅膀摆动效果)

acg数字绘画(用数学代码画画你见过吗)(32)

(使用三角函数确定关节坐标)

acg数字绘画(用数学代码画画你见过吗)(33)

acg数字绘画(用数学代码画画你见过吗)(34)

(已知方向和步长,计算下个生长的坐标点)

acg数字绘画(用数学代码画画你见过吗)(35)

acg数字绘画(用数学代码画画你见过吗)(36)

acg数字绘画(用数学代码画画你见过吗)(37)

acg数字绘画(用数学代码画画你见过吗)(38)

acg数字绘画(用数学代码画画你见过吗)(39)

acg数字绘画(用数学代码画画你见过吗)(40)

艺考查查全国首发2018年各地统考联考报名时间表,2018年艺考重要招生录取信息,2018艺考简章汇总等。每天,我们将会为全国艺术生推送艺考信息,让你在第一时间详细而全面的掌握艺考相关信息,不会有后顾之忧。有我们的一路陪伴,艺考之路,不会孤单不会害怕。总有一天,你挥洒汗水,会凝结成晶莹剔透珍珠闪闪发光。

,