Fractal curve — Sierpinski arrowhead
Yesterday I wrote about the Koch curve, and today I’m writing about the Sierpinski arrowhead curve. The two fractal curves have a lot in common.
Wikipedia has some good illustrations.
The Sierpinski arrowhead curve draws an equilateral triangle with a bunch of triangular holes in it. It can be described with two substituting production rules: (A –> B-A-B) and (B –> A+B+A). A and B recurse and at the bottom do the same thing — draw a line. Plus and minus (+ and -) mean turn 60 degrees either left or right. The terminating point of the Sierpinski arrowhead curve is always the same provided you recurse an even number of times and you halve the length of the line at each recursion. If you recurse to an odd depth (order is odd) then you end up turned 60 degrees, at a different point in the triangle.
This is easy to describe in code. Given these drawing functions:
void draw_line( double distance); void turn( int angle_in_degrees);
The code to draw an (approximate) Sierpinski arrowhead curve looks like this.
void curve( unsigned order, double length, int angle)
{
if ( 0 == order ) {
draw_line( length);
} else {
curve( order - 1, length / 2, - angle);
turn( + angle);
curve( order - 1, length / 2, + angle);
turn( + angle);
curve( order - 1, length / 2, - angle);
}
}
void sierpinski_arrowhead_curve( unsigned order, double length)
{
// If order is even we can just draw the curve.
if ( 0 == (order & 1) ) {
curve( order, length, +60);
}
else /* order is odd */ {
turn( +60);
curve( order, length, -60);
turn( +60);
}
}
The number of line segments is (3 ** order), and there is exactly one turn between any two adjacent lines. If you negate the starting angle you flip the triangle upside down.
You can also make a star or a hexagon.
void sierpinski_arrowhead_star( unsigned order, double length)
{
sierpinski_arrowhead_curve( order, length);
turn( -60);
sierpinski_arrowhead_curve( order, length);
turn( -60);
sierpinski_arrowhead_curve( order, length);
turn( -60);
sierpinski_arrowhead_curve( order, length);
turn( -60);
sierpinski_arrowhead_curve( order, length);
turn( -60);
sierpinski_arrowhead_curve( order, length);
turn( -60); /* full circle, back where we started */
}
void sierpinski_arrowhead_hexagon( unsigned order, double length)
{
sierpinski_arrowhead_curve( order, length);
turn( +60);
sierpinski_arrowhead_curve( order, length);
turn( +60);
sierpinski_arrowhead_curve( order, length);
turn( +60);
sierpinski_arrowhead_curve( order, length);
turn( +60);
sierpinski_arrowhead_curve( order, length);
turn( +60);
sierpinski_arrowhead_curve( order, length);
turn( +60); /* full circle, back where we started */
}
Disclaimer: I haven’t tested these functions. I’m just coding into the wild blue here.
Comments
Leave a Reply