Perlでドラゴン曲線を描く

続いてはドラゴン曲線。

use v5.14;
use strict;
use warnings;

use Imager;

use constant N => 16;
use constant WIDTH => 900;
use constant HEIGHT => 900;

my $margin = 240;
my ( $x0, $y0 ) = ( $margin, HEIGHT - $margin );

my @gen1 = (
    # [ 0.0,  0.0 ] は不要
    [ 0.5,  0.5 ],
    [ 1.0,  0.0 ]
);

my @gen2 = (
    # [ 0.0,  0.0 ] は不要
    [ 0.5, -0.5 ],
    [ 1.0,  0.0 ]
);

my $points = [
    [ 0, 120 ],
    [ 512, 120 ]
];

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 ) = @_;
    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]
            ];
        } ( ($i & 0x1) ? @gen1 : @gen2 );
    }

    return \@result;
}

20150418-1

これは、書き直した際にバグが入って、
バグが入る事によって面白い絵ができることがあるんだけど、
今回はそんなことはなくて、ちょっと悲しかったです。

おしまい。

Leave a Comment