2012年3月13日

用Processing 學日影畫太極

之前寫了這篇太極由觀測日影而來之後,心裡一直很想要自己來動手畫看看。

本來想要用Inkscape自己一條一條慢慢畫,但是又覺得那樣很蠢,一定畫不好。
要畫這種規律的圖,應該要用程式來畫,於是我想起之前玩arduino的時候,認識Processing這套軟體,可以寫程式來畫圖。

寫程式本身不難,難是難在要用什麼語法和結構,我找了一個Processing 基本教學的講義,和一個範例,花了一個晚上修改那個範例變成我要的東西。

果然啊,用日影是可以畫出太極圖的!

sundial

我的作法是直接到網路天文館找太陽表,把全年過中天時的仰角都匯整起來,藉此來換算成日影。

我覺得如果太極圖真是古人觀測日影所畫出來的,那麼他的作法可能是拿根竹枝去折成當日最短日影的長度,每隔幾天就會做一次,一年下來就會蒐集到很多根竹枝。這這些竹枝按照順序排一排,就可以排出上圖下方的類似鐘型曲線的圖。後來古人可能又發現把這上百根竹枝排列成一個圓形,就會自然形成一個特別的弧度,也就變成太極的模樣。

那麼古人用來排太極的竹枝有沒有可能每天都測日影呢?我覺得不大可能,因為如果有360根竹枝,那會很難排成一個圓。

為了避免以後我忘記怎麼弄這個程式,我特地把程式貼在底下。以下是我參考其他範例所寫的程式,複製後貼到Processing 裡的PDE執行環境,就可以了
=================================



float px, py;
float px2,py2;
float shadowLength;
float radius = 500;
float x;

int[] sunangle = {88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,87,87,87,87,87,87,87,87,86,86,86,86,86,85,85,85,85,85,84,84,84,84,84,83,83,83,83,82,82,82,82,81,81,81,80,80,80,79,79,79,79,78,78,78,77,77,77,76,76,76,75,75,74,74,74,73,73,73,72,72,72,71,71,70,70,70,69,69,69,68,68,67,67,67,66,66,65,65,65,64,64,64,63,63,62,62,62,61,61,60,60,60,59,59,59,58,58,57,57,57,56,56,56,55,55,54,54,54,53,53,53,52,52,52,51,51,51,50,50,50,49,49,49,49,48,48,48,47,47,47,47,46,46,46,46,45,45,45,45,45,44,44,44,44,44,43,43,43,43,43,43,43,42,42,42,42,42,42,42,42,42,42,42,42,42,42,41,41,41,41,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,43,43,43,43,43,43,44,44,44,44,44,44,45,45,45,45,46,46,46,46,47,47,47,47,48,48,48,49,49,49,49,50,50,50,51,51,51,52,52,52,53,53,53,54,54,54,55,55,56,56,56,57,57,57,58,58,59,59,59,60,60,61,61,61,62,62,63,63,63,64,64,64,65,65,66,66,66,67,67,68,68,68,69,69,70,70,70,71,71,71,72,72,73,73,73,74,74,74,75,75,76,76,76,77,77,77,78,78,78,79,79,79,79,80,80,80,81,81,81,82,82,82,82,83,83,83,83,84,84,84,84,85,85,85,85,85,86,86,86,86,86,86,87,87,87,87,87,87,87,87,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88};

void setup(){
  size(600, 800);

}

void draw(){
  background (0);
  stroke(100);
  fill(255);

  ellipse(300, 300, radius, radius);

  for(int i =0 ;i <180;i=i+3){

  stroke(200,200,200);
  px = 300 + cos(radians(i))*(radius/2);
  py = 300 + sin(radians(i))*(radius/2);
  line(300,300,px,py);
 
  stroke(0,0,5);
  shadowLength = radius/2 * cos(radians(sunangle[i])) / sin(radians(sunangle[i])) ;
  px2 = px + cos(radians(i-180))*(shadowLength);
  py2 = py + sin(radians(i-180))*(shadowLength);
  line(px,py,px2,py2);  
 
  stroke(255,255,255);
  line(100+i,750,100+i,750-shadowLength/2);
 
  }

for(int i =180 ;i <360;i=i+3){

  stroke(200,200,200);
  px = 300 + cos(radians(i))*(radius/2);
  py = 300 + sin(radians(i))*(radius/2);
  line(300,300,px,py);
 
  stroke(0,0,5);
  shadowLength = radius/2 * cos(radians(sunangle[i])) / sin(radians(sunangle[i])) ;
  px2 = 300 + cos(radians(i))*(shadowLength);
  py2 = 300 + sin(radians(i))*(shadowLength);
  line(300,300,px2,py2);  
 
  stroke(255,255,255);
  line(100+i,750,100+i,750-shadowLength/2);  
  }
}