PerlでカオスCGを描く(1)
フラクタルに引き続き、カオスも描いてみようと思います。
この本を参考に、Cで書かれたサンプルコードをPerlで書き直します。
use v5.14;
use strict;
use warnings;
use Imager;
use constant WIDTH => 600;
use constant HEIGHT => 600;
use constant SCALE_X => 180;
use constant SCALE_Y => 180;
my $n = $ARGV[0] // 100000;
say "N = $n";
sub f {
my ( $aa, $bb, $cc, $xx, $yy ) = @_;
my $x2 = $xx * $xx;
my $y2 = $yy * $yy;
return ($aa * ($x2 + $y2)) + ($bb * $xx * ($x2 - (3.0 * $y2))) + $cc;
}
my $width = WIDTH;
my $height = HEIGHT;
my $img = Imager->new(
xsize => $width, ysize => $height, channels => 3 );
$img->box( filled => 1, color => 'white' );
my ( $u0, $v0 ) = ( WIDTH / 2, HEIGHT / 2 );
my @result = map {
my @tmp = map {
[ 0, 0, 0 ];
} 1..WIDTH;
\@tmp;
} 1..HEIGHT;
my ( $x00, $y00 ) = ( 0.1, 0.1 );
#my ( $a0, $b0, $c0, $d0 ) = ( -1.0, 0.05, 2.275, -0.5 );
my ( $a0, $b0, $c0, $d0 ) = ( 1.0, 0.0, -1.9, 0.4 );
#my ( $a0, $b0, $c0, $d0 ) = ( 1.0, 0.0, -2.25, 0.2 );
#my ( $a0, $b0, $c0, $d0 ) = ( -1.0, 0.1, 1.6, -0.8 );
my ( $x0, $y0 ) = ( $x00, $y00 );
my ( $x, $y ) = ( 0.0, 0.0 );
my $i = 0;
my $blend = 0.1;
foreach ( 1..$n ) {
my $tmp = f( $a0, $b0, $c0, $x0, $y0 );
$x = ($tmp * $x0) + ($d0 * (($x0 * $x0) - ($y0 * $y0)));
$y = ($tmp * $y0) - (2.0 * $d0 * $x0 * $y0);
#printf( "(x, y) = (%6.3f, %6.3f)\n", $x, $y );
if ( 300 < (abs($x) + abs($y)) ) {
say 'divergence!';
( $x0, $y0 ) = ( $x00, $y00 );
}
else {
( $x0, $y0 ) = ( $x, $y );
}
my ( $u, $v ) = (
($x * SCALE_X) + $u0,
$v0 - ($y * SCALE_Y)
);
#push @result, [ $u, $v, $i++ ];
$i++;
if ( 0 < $u and $u < (WIDTH - 1)
and 0 < $v and $v < (HEIGHT - 1) ) {
my $tmp = ($i / ($n * 8));
#my $tmp = ($i / ($n * 8)) + 0.5; # <- 青っぽくなる
my $hue = ($tmp - int($tmp)) * 360;
my $color = Imager::Color->new( hue => $hue, v => 0.8, s => 1.0 );
my ( $rr, $gg, $bb, $alpha ) = $color->rgba();
$result[int($v + .5)]->[int($u + .5)][0] += ($rr * $blend);
$result[int($v + .5)]->[int($u + .5)][1] += ($gg * $blend);
$result[int($v + .5)]->[int($u + .5)][2] += ($bb * $blend);
}
}
my $iy = 0;
foreach my $line ( @result ) {
my $ix = 0;
foreach ( @{$line} ) {
my ( $rr, $gg, $bb ) = @{$_};
$rr = ( ($rr < 255.0) ? int($rr) : 255 );
$gg = ( ($gg < 255.0) ? int($gg) : 255 );
$bb = ( ($bb < 255.0) ? int($bb) : 255 );
my $color = Imager::Color->new( $rr, $gg, $bb );
$img->setpixel( x => $ix, y => $iy, color => $color );
$ix++;
}
$iy++;
}
my $dst_file = ($0 =~ s/\.pl//r) . '.png';
$img->write( file => $dst_file ) or die $img->errstr;
たくさんプロットしたところが濃くなる(明るくなる)ようにしたくて、
結果的にこんな感じになった。
自分が見たことがあるのは、滑らかに色相が変わる画像なんだけど、
プロットしてみるとそれは難しいので、とりあえずこんな感じで。
$ perl aaa.pl 400000
おしまい。

Leave a Comment