GDモジュールでGIFアニメを作ってみた - すぎゃーんメモã®ç¶ç·¨ã
ã¾ããã¼ãã¢ããã«ã®åãã表ç¾ãã¦ãããã®ã¯æ¤ç´¢ããã°ããããåºã¦ããã®ã ãã©ã
(http://video.google.co.jp/videosearch?q=theo%20jansen&lr=lang_ja&oe=utf-8&rls=org.mozilla:ja-JP-mac:official&client=firefox-a&um=1&ie=UTF-8&sa=N&hl=ja&tab=wv#)
ãã£ã±ãèªåã§ãä½ã£ã¦ã¿ããï¼ã¨ãããã¨ã§ãã£ã¦ã¿ãããã§ãã
ãã¼ãã¢ããã«ã®è¶³ã®æ©æ§ã¯åé¨åã®é·ããã11 holy numbersãã¨ãã¦å
¬é(ï¼)ããã¦ããã®ã§ãããããåãã£ã¦ããã°ãã¨ã¯åç¯ç¹ã®åº§æ¨ãè¨ç®ãã¦ãã£ã¦ç·ã§ç¹ãã§ãããã¨ã§æç»ãããã¨ãã§ããã
(ã¨ã¯ããwebä¸ã§ã¯ãã®11 holy numbersãè¦ã¤ãããâ¦kwappaさんã«æãã¦ããã ãã¾ããããããã¨ããããã¾ãã)
座æ¨ã®æ±ãæ¹ã«ã¤ãã¦ã¯ä¸è¨åç
§ã
三角形の2点の座標と各辺の長さから、残る1点の座標を求める - すぎゃーんメモ
ã¨ããããã§ä½ã£ãã¹ã¯ãªããã
#!/opt/local/bin/perl use strict; use warnings; use Config::Auto; use GD; use Math::Trig qw(pi atan); # 11 holy numbers my $holy_numbers = Config::Auto::parse('holy_numbers.yaml'); # å転åå¾:m (ãã®æ°åã¯ä»»æï¼) my $radius = 10.0; # GD my $image = GD::Image->new(240, 150); # è²ã®è¨å® my $white = $image->colorAllocate(0xFF, 0xFF, 0xFF); my $red = $image->colorAllocate(0xFF, 0x00, 0x00); my $green = $image->colorAllocate(0x00, 0xFF, 0x00); my $blue = $image->colorAllocate(0x00, 0x00, 0xFF); # GIFãã¼ã¿ã®ä½æ my $gifdata = $image->gifanimbegin(1, 0); for (1..36) { my $degree = $_ * 10; # ãã¬ã¼ã ã®æç» my $frame = GD::Image->new($image->getBounds); draw_frame($frame, $degree); # GIFãã¼ã¿ã¸ã®è¿½å $gifdata .= $frame->gifanimadd(0, 0, 0, 1); } $gifdata .= $image->gifanimend; # ãã¼ã¿ã®æ¸ãåºã binmode STDOUT; print $gifdata; # ãã¬ã¼ã ã®æç» sub draw_frame { my $image = shift; my $arg = pi() / 180 * shift; # åç¹åº§æ¨ my $origin = { x => $image->width / 2, y => 50, }; # å転è»é $image->arc($origin->{x}, $origin->{y}, $radius * 2, $radius * 2, 0, 360, $blue); # ååº§æ¨ my $O = { x => 0, y => 0, }; my $A = { x => $radius * cos($arg), y => $radius * sin($arg), }; my $B = { x => $holy_numbers->{a}, y => 0, }; my $C = calc_coordinate($A, $B, $holy_numbers->{j}, $holy_numbers->{b})->[0]; my $D = calc_coordinate($A, $B, $holy_numbers->{k}, $holy_numbers->{c})->[1]; my $E = calc_coordinate($B, $C, $holy_numbers->{d}, $holy_numbers->{e})->[1]; my $F = calc_coordinate($D, $E, $holy_numbers->{g}, $holy_numbers->{f})->[1]; my $G = calc_coordinate($D, $F, $holy_numbers->{i}, $holy_numbers->{h})->[1]; # å転é¨å draw_line($image, $origin, $O, $A, $green); # 11æ¬ã®ã©ã¤ã³ draw_line($image, $origin, $O, $B); draw_line($image, $origin, $B, $C); draw_line($image, $origin, $B, $D); draw_line($image, $origin, $B, $E); draw_line($image, $origin, $C, $E); draw_line($image, $origin, $E, $F); draw_line($image, $origin, $D, $F); draw_line($image, $origin, $F, $G); draw_line($image, $origin, $D, $G); draw_line($image, $origin, $A, $C); draw_line($image, $origin, $A, $D); } # ç·ãæç» sub draw_line { my ($image, $origin, $a, $b, $color) = @_; $image->line($origin->{x} + $a->{x}, $origin->{y} - $a->{y}, $origin->{x} + $b->{x}, $origin->{y} - $b->{y}, $color || $red); } # 座æ¨ã®è¨ç® sub calc_coordinate { my ($a, $b, $dist_from_a, $dist_from_b) = @_; my $alpha = atan(($b->{y} - $a->{y}) / ($b->{x} - $a->{x})); my $dist = ($b->{x} - $a->{x}) / cos($alpha); my $s = ($dist_from_a + $dist_from_b + $dist) / 2; my $tempX = ($dist_from_a ** 2 - $dist_from_b ** 2 + $dist ** 2) / ($dist * 2); my $tempY = 2 * sqrt($s * ($s - $dist_from_a) * ($s - $dist_from_b) * ($s - $dist)) / $dist; return [{ x => $tempX * cos($alpha) - $tempY * sin($alpha) + $a->{x}, y => $tempX * sin($alpha) + $tempY * cos($alpha) + $a->{y}, }, { x => $tempX * cos($alpha) + $tempY * sin($alpha) + $a->{x}, y => $tempX * sin($alpha) - $tempY * cos($alpha) + $a->{y}, }]; }
ã11 holy numbersãã¯ããã§å ¬éãã¦ãããã®ãã©ããããåãããªãã®ã§ä¸å¿ãã¡ã¤ã«å¤åºãã§ä½¿ç¨ã
ãããå®è¡ãã¦åºåãªãã¤ã¬ã¯ããããã¨ã§GIFãåºæ¥ã¾ãã
$ ./strandbeest.pl > result.gif
ã§ãåºæ¥ä¸ãã£ããã®ããã¡ãã
ã¡ãã£ã¨å¿ç¨ãã¦å対å´ã«ãåãè¦é ã§ä½ã£ã¦ããã°ããããã®ãç°¡åã«ä½ãã¾ãã
大ããæãã¦ã¿ããã
ä»åº¦ã¯ãããJavaScriptã§ã¤ã³ã¿ã©ã¯ãã£ãã«åé¨ã®é·ããå¤ããªããã¢ãã¡ã¼ã·ã§ã³ããããããããªã®ãä½ã£ã¦ã¿ãããªãã¼