#!/usr/bin/perl
use strict;
use warnings;
use lib 'lib';
use Math::Fractal::Curve;
use Imager;
unless(@ARGV) {
die <<HERE . <<'GENERATOR';
generator10.pl - generate fractals from the following generator as PNG images.
Usage: $0 RecursionDepth
Generator: (The X's being start- and end points of the curve)
HERE
O O
\ /
X \ / X
\ /
O
GENERATOR
}
# Recursion depth
my $depth = shift @ARGV;
# Filename for image.
my $filename = sprintf('Generator10-Depth%02i.png', $depth);
# Image dimensions
my $max_x = 1000;
my $max_y = 700;
my $scale = 120;
# Drawing color
my ($red, $green, $blue) = (255, 100, 100);
# Starting edge
my $starting_edge = [ [-2, 0], [2, 0] ];
# O O
# \ /
# X \ / X
# \ /
# O
my $generator = rotate(
[
[0, 1/3, 1/2, -1/3 ],
[1/2, -1/3, 1, 1/3 ],
],
0 # radians
);
# ====================
# End of Configuration
# ====================
# New curve generator
my $curve_gen = Math::Fractal::Curve->new(generator => $generator);
# New curve
my $curve = $curve_gen->line(
start => $starting_edge->[0],
end => $starting_edge->[1],
);
my $img = Imager->new(xsize => $max_x, ysize => $max_y);
my $color = Imager::Color->new( $red, $green, $blue );
recur_draw($curve, $depth);
$img->write(file=>$filename) or
die $img->errstr;
# All this magic just to keep the memory footprint low!
sub recur_draw {
my $curve = shift;
my $depth = shift;
if ($depth <= 1) {
my $edges = $depth==1 ? $curve->edges() :
[ [@{$curve->{start}}, @{$curve->{end}}] ];
foreach (@$edges) {
$img->line(
color => $color,
x1 => $max_x/2 + $_->[0] * $scale,
y1 => $max_y/2 - $_->[1] * $scale,
x2 => $max_x/2 + $_->[2] * $scale,
y2 => $max_y/2 - $_->[3] * $scale,
);
}
}
else {
my $curves = $curve->recurse();
foreach (@$curves) {
recur_draw($_, $depth-1);
}
}
}
sub rotate {
my $ary = shift;
my $angle = shift;
my $cos = cos $angle;
my $sin = sin $angle;
foreach (@$ary) {
($_->[0], $_->[1]) = (
$_->[0]*$cos + $_->[1]*$sin,
-$_->[0]*$sin + $_->[1]*$cos
);
($_->[2], $_->[3]) = (
$_->[2]*$cos + $_->[3]*$sin,
-$_->[2]*$sin + $_->[3]*$cos
);
}
return $ary;
}