Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Plot Pretty Fractals with Perl

by tsee (Curate)
on Aug 29, 2003 at 18:39 UTC ( [id://287793]=CUFP: print w/replies, xml ) Need Help??

This is a short introduction to one of the CPAN modules dealing with fractals. According to the Merriam-Webster dictionary, a fractal is

"any of various extremely irregular curves or shapes for which any suitably chosen part is similar in shape to a given larger or smaller part when magnified or reduced to the same size."

While that's pretty hard to parse for my head, I think I can safely assume that most readers have seen one of the more famous fractals like the von-Koch Curve before. Hence I will not go into details on fractals or even the underlying mathematics. I suggest you have a look at the documents in the references section below.

Introducing Math::Fractal::Curve

The Math::Fractal::Curve module from CPAN may be used to recursively calculate fractal curves from simple generator datastructures to arbitrary precisions. These generators specify a number of distances in two dimensions and relative to the distance from (0,0) to (1,0).

Math::Fractal::Curve calculates fractals by repeatedly replacing all distances in the fractal with a scaled and rotated version of the distances specified by the generator.

Getting the feet wet

Let's start writing some code that demonstrates basic usage.

use strict; use warnings; use Math::Fractal::Curve; # This generates a von Koch-curve. my $generator = [ [0, 0, 1/3, 0 ], [1/3, 0, 1/2, sqrt(5)/6], [1/2, sqrt(5)/6, 2/3, 0 ], [2/3, 0, 1, 0 ], ]; # New curve generator my $curve_gen = Math::Fractal::Curve->new(generator => $generator); # New curve my $curve = $curve_gen->line( start => [-2, 0], end => [2, 0], ); my $depth = 5; my $edges = $curve->fractal($depth);

As you can see in the above example, generators in their simplest form are syntactically no more than nested array references and a few numbers. The example specifies four distances (the four inner array references) that will be used to replace any distance. The numbers are relative to the length of the replaced distance and have the same orientation.

  • From (0, 0) to (1/3, 0).
  • From (1/3, 0) to (1/2, sqrt(5)/6).
  • and so on
The next step taken is to create a new Math::Fractal::Curve object which we seed with a starting distance using the line() method. The last step required to generate a list of distances that represent a von-Koch Curve to the 5th recursion.

Great, so what? -or- Imager to the rescue

Now we have a large array of array refs that each hold four numbers. That did not take us much closer to the pretty picture I gave as an example above. We'll need some drawing to realize that. Luckily, Arnar Mar Hrafnkelsson wrote the excellent Imager module to do the hard work!

# append to the other part of the script use Imager; # Generate sensible filename for image. my $filename = sprintf('Koch-Depth%02i.png', $depth); # Image dimensions my $max_x = 1000; my $max_y = 400; my $img = Imager->new(xsize => $max_x, ysize => $max_y); my $color = Imager::Color->new( 0, 0, 255 ); # blue # Scale dimensions by 200. @$_ = map $_*200, @$_ foreach @$edges; foreach (@$edges) { $img->line( color => $color, x1 => $max_x / 2 + $_->[0], # start y1 => $max_y - 50 - $_->[1], x2 => $max_x / 2 + $_->[2], # end y2 => $max_y - 50 - $_->[3], ); } $img->write(file=>$filename) or die $img->errstr;

No deep thinking required to understand the above code. We scale the distances to be large enough to be drawn conveniently. The call to Imager's line() method may look more complicated than it really is. All the maths is just moving the fractal to the center of the image.

More'o'That

The above example demonstrates the bare minimum needed to get started with letting your computer plot some fractals, but it has a few limitations and does not demonstrate the full power of the module.
One problem that arises when recursing 8, 9, or even 10 times is the memory footprint of the program. All edges will be stored in memory and holding 4**10 array references scares the hell out of my gigabyte of RAM.
It isn't hard to do a depth-first search on the fractal tree while generating it using some of the other methods of the module. Such a routine has been used for generating this image.
Furthermore, Math::Fractal::Curve can create fractals that don't strictly qualify as such. This is possible by assigning an anonymous subroutine that returns a generator structure as the Math::Fractal::Curve object's generator.

References

MathWorld
Kenneth J. Falconer, "Fractal Geometry. Mathematical Foundations and Applications", (c) 1990 at Jon Wiley & Sons Ltd., Chichester
Math::Fractal::DLA
Math::Fractal::Mandelbrot
Math::Fractal::Curve

Replies are listed 'Best First'.
Nicely done
by Dragonfly (Priest) on Sep 23, 2003 at 20:59 UTC
    Just out of curiosity, I noticed you're outputting to a png file - is there a to plot to a screen device instead, so you can watch the plotting as it outputs? That'd be cool.

    - Mark Beihoffer, Network Architect

      I am not aware of anything like that in *consoles*. You can, however, use the module in a Tk Application and draw on a Tk::Canvas object much like I did to the Imager object. No significant changes to the code required -- except, well, Tk. Steffen

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://287793]
Approved by herveus
Front-paged by krisahoch
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (1)
As of 2024-04-25 02:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found