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;
}

画像を中央に移動させるための余白の計算は、
結果を見ながら修正したので適当です。

縮小する前の結果は、ご自身で確認してください。

20150417-1

おしまい。

Leave a Comment