数学から創るジェネラティブアート

すごく良い本を見つけたので、
その紹介と、Perlによる再実装を載せることにします。

アート寄りの本に載っているコードの意味を知るための唯一の本だと思います。
(コードの説明が足りない本が多々ある中で、この本は違います。)

そんなこんなで、この本に載っている「らせん」に関する内容をPerlで再実装して、
うまくやったらアニメーションにならないかなーって思って、
ちょっといじったら良い感じのGIFアニメが出力できたので載せておきます。

use strict;
use warnings;
use v5.14;

use Imager;
use Data::Dumper;

=pod

再帰的に正方形を描く

=cut

sub gen_rect {
    my ( $x, $y, $w, $h ) = @_;
    return [
        [ $x, $y ],
        [ $x + $w, $y ],
        [ $x + $w, $y + $h ],
        [ $x, $y + $h ]
    ];
}

sub new_polygon {
    my ( $points, $gap ) = @_;

    my @polygon = ();
    my $n = scalar(@{$points});
    for (my $i=0; $i<$n; $i++) {
        if ( $i < ($n - 1) ) {
            my $x = $points->[$i][0] + ($points->[$i + 1][0] - $points->[$i][0]) * $gap;
            my $y = $points->[$i][1] + ($points->[$i + 1][1] - $points->[$i][1]) * $gap;
            push @polygon, [ $x, $y ];
        }
        else {
            my $x = $points->[$i][0] + ($points->[0][0] - $points->[$i][0]) * $gap;
            my $y = $points->[$i][1] + ($points->[0][1] - $points->[$i][1]) * $gap;
            push @polygon, [ $x, $y ];
        }
    }

    return \@polygon;
}

my $margin = 20;
my ( $w, $h ) = ( 400, 400 );
my $src = gen_rect(
    -$margin, -$margin, $w + ($margin * 2), $h + ($margin * 2) );
say Dumper( $src );

my @ret = ( $src );
foreach (1..120) {
    my $tmp = new_polygon( $src, 0.04 );
    say Dumper( $tmp );
    push @ret, $tmp;
    $src = $tmp;
}

say scalar(@ret);

my $n = 4;
my @images = ();
foreach my $i ( 0..($n - 1) ) {
    my $img = Imager->new(
        xsize => $w + 0,
        ysize => $h + 0,
        channels => 3 );

    $img->box( color=> 'black', filled => 1 );

    my $j = $i;
    foreach my $p ( @ret ) {
        if ( ($j % $n) == 0 ) {
            my @closed = ( @{$p}, $p->[0] );
            $img->polyline(
                points => \@closed, color => 'white', aa => 1 );
        }

        $j++;
    }

    push @images, $img;
    $img->write( file => "test${i}.png" ) or die $img->errstr;
}

my $img = Imager->new;
$img->write_multi({
    file => 'square_anim.gif',
    gif_delay => 6,
    gif_loop => 0
}, @images) or die $img->errstr;

実装イメージですが、元々これだけの正方形が再帰的に描かれていて、

同じ色ごとに正方形を振り分けたフレームによる、
アニメーションGIFを生成するようにしたのが、上記に載せたコードです。
一応、各フレームごとの画像も出力します。

結果のアニメーションGIFは、こちら。

そんな感じで、これからも気になったものをPerlで再実装する予定です。

おしまい。

Leave a Comment