Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Is it possible to generate fractals with Perl? I checked CPAN and there are no fractal modules. Anyone made them with the GD modules? Any other random designs, patterns, etc.? Hints, tips, suggestions?

Thanks.

Replies are listed 'Best First'.
Re: Generating Fractals with Perl?
by fuzzyping (Chaplain) on Mar 09, 2002 at 06:44 UTC
    The third result from a Google search of "perl fractal" was this. The site is French, but there is a sample program which uses GD and appears to work quite well (only the comments are in French). Screenshot available here.

    If you have a copy of O'Reilly's Advanced Perl Programming available, chapter 18 also has some sample fractal-drawing code.

    -fuzzyping
Re: Generating Fractals with Perl?
by hossman (Prior) on Mar 09, 2002 at 06:47 UTC
    There's examples of this in Advanced Perl Programming

    I don't really remember the details, but this is in the "Extending Perl" chapter, so i think all of the hardwork is being done in C code, and the Chapter is really just showing you how to create a Perl module arround the C code.

Re: Generating Fractals with Perl?
by gellyfish (Monsignor) on Mar 09, 2002 at 10:50 UTC

    Here's a fairly crude Mandelbrot I prepared earlier:

    #!/usr/bin/perl -w use strict; use GD; use vars qw($P @Q $col $row @colours ); my ($maxcol, $maxrow, $max_colours, $max_iterations, $max_size ) = (640,350,16,512,4); my ($XMax,$XMin,$YMax,$YMin) = (1.2,-2.0,1.2,-1.2); my $deltaP = ($XMax - $XMin) / $maxcol; my $deltaQ = ($YMax - $YMin) / $maxrow; $Q[0] = $YMax; my $image = new GD::Image($maxcol,$maxrow); for ( 0 .. $max_colours - 1) { $colours[$_] = $image->colorAllocate(int(rand(256)), int(rand(256)), int(rand(256))); } for( 1 .. $maxrow ) { $Q[$_] = $Q[$_ -1] - $deltaQ; } $P = $XMin; for $col ( 0 .. $maxcol -1 ) { for $row ( 0 .. $maxrow - 1) { my ($X,$Y,$XSquare,$YSquare) = (0,0,0,0); my $colour = 1; while (( $colour < $max_iterations ) && (($XSquare + $YSquare ) < $max_size )) { $XSquare = $X * $X; $YSquare = $Y * $Y; $Y *= $X; $Y += $Y + $Q[$row]; $X = $XSquare - $YSquare + $P; $colour++; } $image->setPixel($col,$row,$colours[$colour % $max_colours] +); } $P += $deltaP; } open(PNG,">image$$.png") || die "Cannot open output - $!\n"; binmode(PNG); print PNG $image->png; close(PNG);

    If you look in the examples for my module Linux::Svgalib there are some further examples.

    /J\

      And this one draws a random Dragon Outline as a CGI program :

      #!/usr/bin/perl -w use CGI qw(:standard); use strict; use GD; use vars qw($magnitude $P $Q $scale); my ($x_centre,$y_centre) = (320,175); if ( scalar param() < 3 ) { my @configs = map {chomp; [ split ]} <DATA>; ($P,$Q,$scale) = @{ $configs[rand @configs] }; } else { $P = param('real'); $Q = param('imaginary'); $scale = param('scale'); } my $image = new GD::Image($x_centre * 2,$y_centre * 2); my $back_colour = $image->colorAllocate(255,255,255); my $fore_colour = $image->colorAllocate(0,0,0); my ($x,$y) = (0.50001,0); $magnitude = ($P*$P) + ($Q*$Q); $P = 4*$P/$magnitude; $Q = -4*$Q/$magnitude; $scale = $x_centre * $scale; for ( 1 .. 12000 ) { my $temp_x = ($x * $P ) - ($y * $Q ); $y = ($x * $Q) + ($y * $P ); my $temp_y = $y; $x = 1 - $temp_x; $magnitude = sqrt(($x * $x ) + ($y * $y)); $y = sqrt((-$x + $magnitude)/2); $x = sqrt(($x + $magnitude)/2); ($x = -$x) if ($temp_y < 0 ); if ( rand() < 0.5 ) { $x = -$x; $y = -$y; } $x = (1- $x) / 2; $y = $y / 2; my $col = int(($scale * ($x - 0.5 )) + $x_centre); my $row = int($y_centre - ($scale * $y)); if ( ($_ > 0 ) && ($col >= 0 ) && ($col < (2 * $x_centre)) && ($row >= 0 ) && ($row < ($y_centre * 2 ))) { $image->setPixel($col,$row,$fore_colour); } } print header('image/png'); binmode(STDOUT); print $image->png; __END__ 1.646009 0.967049 0.75 2.447261 -0.967049 0.75 1.325508 0.786533 0.75 1.415414 0.856803 0.75 1.255399 0.691977 0.75 2.792809 -0.657593 0.75 3.018153 -0.098854 0.75 2.998122 0.004298 0.75

      /J\

Re: Generating Fractals with Perl?
by larsen (Parson) on Mar 09, 2002 at 10:53 UTC
    Any other random designs, patterns, etc.?
    The Geometry Junkyard. *Tons* of geometry stuff. Hope this helps.
Get A Book For More On Fractals - Re: Generating Fractals with Perl?
by metadoktor (Hermit) on Mar 09, 2002 at 09:33 UTC
    A good small introductory book on fractals is Hans Lauwerier's Fractals: Endlessly Repeated Geometrical Figures. It describes the basic theory and includes many programs written in basic which are not too hard to translate to perl.

    metadoktor

    "The doktor is in."

Re: Generating Fractals with Perl?
by zentara (Cardinal) on Mar 10, 2002 at 01:12 UTC
    I went and looked at the Advanced Perl Programming example of using swig and gd to make a Fractal perl module. Just to learn about swig, I worked the example out. There are some tricks you need to work thru, since the swig docs are erratic, and the APP example has an error between it's header and c file. Anyways, here are the steps and files to create Fractal.pm with gd and swig. I modified the Advanced Perl Programming example to use Png instead of Gif. Check your perl location for the -I
    Run these commands in succession:
    1)swig -perl5 fractal.i 2)gcc -fpic -c fractal_wrap.c mandel.c -Dbool=char -I/usr/lib +/perl5/5.6.0/i586-linux/CORE 3)gcc -shared fractal_wrap.o mandel.o -lgd -o Fractal.so 4)fractal.pl #fractal.i ############################################ %module Fractal %{ #include "mandel.h" %} %include "mandel.h" ############################################## #mandel.c ############################################# #include <math.h> #include <stdio.h> #include <gd.h> #include "mandel.h" typedef struct { double r, i; } complex; int draw_mandel (char *filename, int width, int height, double origin_real, double origin_imag, double range, double max_iterations) { complex origin; int colors[51], color, white, x, y, i; FILE *out; gdImagePtr im_out; origin.r = origin_real; /* Measured from top-left */ origin.i = origin_imag; if (!(out = fopen(filename, "wb"))) { fprintf(stderr, "File %s could not be opened\n"); return 1; } im_out = gdImageCreate(width, height); /* Create a canvas */ /* Allocate some gray colors. Start from black, and increment r,g,b values uniformly. This has the effect of varying the luminosity, while keeping the same hue. (Black = 0,0,0 and white = 255, 255,255 */ for (i = 0; i < 50; i++) { color = i * 4; colors[i] = gdImageColorAllocate(im_out, color,color,color); } white = gdImageColorAllocate(im_out, 255,255,255); /* For each pixel on the canvas do ... */ for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { complex z, c ; int iter; /* Convert the pixel to an equivalent complex number c, given the origin and the range. The range acts like an inverse zoom factor.*/ c.r = origin.r + (double) x / (double) width * range; c.i = origin.i - (double) y / (double) height * range; /* Examine each point calculated above to see if repeated substitutions into an equation like z(next) = z**z + c remains within a definite boundary. If after <max_iterations> iterations it still hasn't gone beyond the white area, it belongs to the Mandelbrot set. But if it does, we assign it a color depending on how far the series wants to jump out of bounds*/ color = white; z.r = z.i = 0.0; /* Starting point */ for (iter = 0; iter < max_iterations; iter++) { double dist, new_real, new_imag; /*calculate z = z^2 + c */ /* Recall that z^2 is a^2 - b^2 + 2abi, if z = a + bi, */ new_real = z.r * z.r - z.i * z.i + c.r; new_imag = 2 * z.r * z.i + c.i; z.r = new_real; z.i = new_imag; /* Pythagorean distance from 0,0 */ dist = new_real * new_real + new_imag * new_imag; if (dist >= 4) { /* No point on the mandelbrot set is more than 2 units away from the origin. If it quits the boundary, give that 'c' an interesting color depending on how far the series wants to jump out of its bounds */ color = colors[(int) dist % i]; break; } } gdImageSetPixel(im_out, x,y, color); } } gdImagePng(im_out,out); fclose(out); return 0; } ############################################ #mandel.h ######################################### extern int draw_mandel (char *filename, int width, int height, double origin_real, double origin_imag, double range, double max_iterations); ###################################### #fractal.pl ####################################### #!/usr/bin/perl use Fractal; Fractal::draw_mandel('mandel.png', 300, 300, -1.5, 1.0,2.0, 20); # ########### file , width, height, origin x,y max-iterations #########################################