2011/07/11

Math 3 : Trigonometry (processing教學)

每次默默停刊(我是富X義博?)後,要再重拾書本時真是萬分不捨,
這絕對不是成語亂用,沒辦法,只要稍一怠惰我就可以完全放軟舒服攤平,
尤其是看完之後還要打成網誌真的是挺麻煩的,
但我相信自己打過一遍後,雖然不是說完全精通,但至少記得更清楚.

不過CCC說看太慢了   ............... 
但同時他也幫我解套噢噢噢,
那就是我不需要拘泥在每篇都要完整介紹,
有些其實暫時用不到或是很少用到,
可以先挑自己有興趣的即可 ................
WOW,所以有些我有看過但覺得暫時無用我會先跳過不講,
但千萬記得自己要看過一遍.
所以讓我們先快樂的跳過p110-116的Typography 1吧! :)))

記得沒講的自己要看過一遍!!!!!!!!!!

----------------------------------------------------------------------------------------------

這次會講p117-125的Math 3 : Trigonometry (又是數學...)
基本上就是學習如何運用角度跟sin,cos的關係,另外尾巴再加上一點arc
關於角度,一定要記得processing的角度計算是以x軸順時針來看的,
以東南西北來說就是

                  270度
                      
180度            +            0,360度

                   90度

而表示一個角度除了360度數外,我們也可以用 π 來表示(廢話,這我都會.)
在processing裡面π要以大寫的PI代表,而0,90,180,270依序應寫為
TWO_PI,  HALF_PI,  PI,  PI + HALF_PI
不過這樣打我個人覺得超麻煩的,所以不如記0,  1.57,  3.14,  4.71
也就是我們熟知的π  = 3.14xxxxxxxx
processing裡也能以這樣取代π,雖然有些微差距但我覺得可以接受
所以我們可以很簡單知道在processing裡簡單的一個180度可以寫成
radians(180) 或 degree(PI) 或 degree(3.14)

在知道角度之後,就是超靠杯的sin跟cos了
首先不要被p118那個莫名其妙的diagram給蠱惑了

我們只要知道sin與cos的值永遠會介於1至-1之間
然後對應表如下

                sin()        cos()
0,2π            0             1
π /2             1             0
π                 0            -1
3π/2           -1             0

背起來之後就可以先拿p119的14-06做練習



size(400,200);
background(128);
smooth();
noStroke();


float angle = 0; //先定義一個float為angle,值為0

for(int x = 0; x <= width; x += 5){ //for loop內總共會執行81次

  fill(255);
  float y = 100 + (sin(angle) * 30);
  ellipse(x,y,4,4);

  //白色圓點線
  //隨著x的推移,同時讓y座標上下變動
  //因為無論sin或cos一定是1到-1
  //會*30只是為了讓y的增減較明顯

  fill(255,255,0);
  float k = 100 + (cos(angle) * 15);
  rect(x,k,2,8);

  //黃色長方形線
  //道理同上,只是換成用cos,所以我們可以看到兩條線
  //因為只*15,所以我們可以看到波動比較小

  angle += 3.14/10;
  //本來課本是寫PI/10,我只是改成3.14/10
  //這行是用來定義上面sin與cos的angle一次會遞增多少
}


//saveFrame("p119-##.jpg");


至於p121其實只是把一些控制項用float定義出來而已,
一大串沒什麼好怕的.基本上它把畫一條線的控制項分為三種
offset (偏移)
scaleVal (比例縮放)
angleInc (角度增加值)
直接跟上面對比就知道了,而它們三個也不是processing內的指令
只是作者方便撰寫才取的,如果重寫上面的程式就會變成

size(400,200);
background(128);
smooth();
noStroke();


float offset = 100;
float scaleValA = 30;
float scaleValB = 15;
float angleInc = 3.14/10; // or PI/10
float angle = 0;


for(int x = 0; x <= width; x += 5){ 

  fill(255);
  float y = offset + (sin(angle) * scaleValA);
  ellipse(x,y,4,4);


  fill(255,255,0);
  float k = offset + (cos(angle) * scaleValB);
  rect(x,k,2,8);


  angle += angleInc;
}

//saveFrame("p119-##.jpg");


 再進階一點的畫法就是p122那搭配我們之前在p69學過的vertex來畫



size(400,200);
background(128);
smooth();
stroke(128);


float angle = 0;

beginShape(TRIANGLE_STRIP);
for(int x = -3; x <= width + 5; x += 5){


  fill(255,255,0);
  float y = sin(angle) * 30;

  if((x%2) == 0){
    vertex(x,100 + y);
  }
  else{
    vertex(x,100 - y);
  }


  angle += 3.14/22;
}
endShape();


//saveFrame("p122-##.jpg");

基本上我們可以看到作者就是說當x整除2時y會向上升
其餘時則會向下降,而注意看那for loop,
for(int x = -3; x <= width + 5; x += 5){
依序為-3,2,7,12,17,22,27,32,......................
所以其實是很規律的2不能整除,2可以整除,2不能整除,2可以整除,.............
那就可以想像點一定是一上一下的,透過vertex的TRIANGLE_STRIP把點連起來,
色塊上成黃色,就是結果了,voila!


接著是p123的14-11,你可能會跟我一樣迷失得莫名其妙,
就讓我簡化它來讓你看清


size(400,200);
background(128);
smooth();
fill(255,20);


float scaleVal = 15;
float angleInc = 3.14/28;
float angle = 0;

//這邊就是剛剛上面提到的把控制項拉出來

for(int offset = 15; offset <= width + 10; offset += 50){ //x總共跑8次,這決定會有幾條線
  for(int y = 0; y <= height; y += 2){ //y總共跑101次,這決定線的波動多寡


 //這邊我們再次遇到for中有for的情況,要記得永遠是裡面的for先算
 //同時我們發現本來三個基本的控制項的offset被抓進for裡面了

  float x = offset + (sin(angle) * scaleVal);
  noStroke();
  ellipse(x,y,10,10);
 

  stroke(0);
  point(x,y);


  //上面不過是共用點,然後同時畫點跟半透明的圓罷了

  angle += angleInc;
  }
}


//saveFrame("p123-##.jpg");


在這要做一個簡單的算數給大家看,你們是否會覺得第一條線跟第六條線很像?
首先我們知道每次角度的增加值為3.14/28 = 0.11214xxxxx
我們同時知道當0.11一直疊加到6.28時,sin就過了一次週期然後再重新一次波動,
而每次y會跑101次,所以我們知道畫完一條曲線共疊加了0.11*101 = 11.32614
而11.32614/6.28 = 1.8,這代表著每條曲線只跑了1又0.8的sin,而不是剛好跑2次sin週期
但因為我們只有設x跟y的for loop,並未設角度增值的for,
因此不是每次新的曲線生成時,角度又從0開始,這導致前五條線扭的不太一樣,
不過正因每次只跑1.8次的sin,但跑5條線後剛好為1.8*5=9,
所以我們知道在第五條線畫完時剛好跑完9次sin,
因此第六條曲線開始畫時剛好sin為0開始,因此會跟第一條線一模一樣囉,
只要稍微改一下x跟y的遞增值你就可以畫出跟作者一樣的圖囉. :)

至於最後的arc其實就是應用前面的觀念,只是改成畫弧線而已,
p125只多用了radius而已,應該不難理解,就請自己看囉!

那要如何應用上面的技巧來畫出下面的彩色旋風呢?




size(200,200);
background(255);
smooth();
stroke(255,80);


float radius = 1;

beginShape(TRIANGLE_STRIP);
for(int deg = 0; deg < 360*60; deg += 55){
  float angle = radians(deg);
  float x = 100 + (cos(angle) * radius);
  float y = 100 + (sin(angle) * radius);
  vertex(x,y);
  fill(random(100,255),random(100,255),random(100,255),180);
  radius = radius + 0.8;
}
endShape();


//saveFrame("p125-##.jpg");


Try it. :)

沒有留言:

張貼留言