Perlでコッホ曲線を描く(前編)
「Hokkaido.pm Casual#36に行ってきました」でコードを掲載してなかったので、
一生懸命書き直して載せようと思います。
というのも、当日に実行したコードは、
参考にした「CによるフラクタルCG」に載ってるコードに酷似していたので、
ブログにはコッホ曲線の画像だけアップしました。
今回は、元のコードでは再帰を使っていたので、
それを取り除いて、さらに富豪的な感じに仕上げてあります。
Perlの場合、関数呼び出しを減らした方が早くなるので、
結果的に高速化されて個人的に満足しております。
use v5.14; use strict; use warnings; use Imager; use constant N => 5; use constant WIDTH => 1800; use constant HEIGHT => 1800; my $tri_w = 400; my $margin = (WIDTH - $tri_w) / 2; my ( $x0, $y0 ) = ( $margin, HEIGHT - ($margin * 1.8) ); # コッホ曲線 my @gen = ( # [ 0.0, 0.0 ] は不要 [ 1/3, 0 ], [ 0.5, -sqrt(3)/6 ], [ 2/3, 0 ], [ 1.0, 0 ] ); my $points = [ [ 0, 0 ], [ $tri_w, 0 ], [ ($tri_w / 2), (($tri_w / 2) * sqrt(3.0))], [ 0, 0 ] ]; my $img = Imager->new( xsize => WIDTH, ysize => HEIGHT ); $img->box( filled => 1, color => 'white' ); foreach my $n ( 0..N ) { $img->box( filled => 1, color => 'white' ); if ( 0 < $n ) { $points = generate( $points ); } my @tmp = map { [ int($x0 + $_->[0]), int($y0 - $_->[1]) ]; } @{$points}; $img->polyline( points => \@tmp, color => 'black' ); my $dst_file = ($0 =~ s/\.pl//r) . "_${n}.png"; $img->write( file => $dst_file ) or die $img->errstr; } sub generate { my $points = shift; my $cnt = scalar( @{$points} ); my @result = ( $points->[0] ); for (my $i=1; $i<$cnt; $i++) { my ( $st, $en ) = ( $points->[$i-1], $points->[$i] ); my $dx = $en->[0] - $st->[0]; my $dy = $en->[1] - $st->[1]; push @result, map { my ( $x, $y ) = ( $_->[0], $_->[1] ); # x2 = $x * cos(a) - $y * sin(a) + st.x; # y2 = $x * sin(a) - $y * cos(a) + st.y; # sin(a) = dy / 1.0, cos(a) = dx / 1.0 [ ($x * $dx) - ($y * $dy) + $st->[0], ($x * $dy) + ($y * $dx) + $st->[1] ]; } @gen; } return \@result; }
画像を中央に移動させるための余白の計算は、
結果を見ながら修正したので適当です。
縮小する前の結果は、ご自身で確認してください。
おしまい。
Leave a Comment