Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Java Fun and Games: Explore the geometry of nature

Journey into the realm of fractals

  • Print
  • Feedback

Page 3 of 7

The fractal animator component reveals a pale yellow background.

Figure 1. The fractal animator component reveals a pale yellow background.

You might have noticed an oddity in the createGUI() source code. Specifically, I have included an (int) (size*1.15) expression to calculate the width of the fractal animator component. I did this to compensate for an equilateral triangle not looking equilateral on my LCD screen (at a resolution of 1024 by 768 pixels). You might need to adjust this expression for your display.

Koch snowflake

In 1904, Swedish mathematician Helge von Koch presented a paper that included a fractal curve known as the Koch snowflake (also known as the Koch star). The following algorithm recursively generates this fractal, which is based on an equilateral triangle:

  1. For each of the equilateral triangle's line segments, divide the line segment into three equal-length line segments.
  2. For each middle line segment, generate a smaller equilateral triangle whose base line segment replaces the middle line segment.
  3. Remove the base line segment from the previous step's equilateral triangle. Repeat steps 1 through 3 with this new equilateral triangle.

As you recursively repeat the above steps, the equilateral triangle morphs into a snowflake. Figure 2 reveals the original triangle on the left, the fractal after one iteration in the middle, and the fractal after two iterations on the right.

Each side of the original equilateral triangle approaches a limit known as the Koch curve.

Figure 2. Each side of the equilateral triangle approaches a limit known as the Koch curve. Click the thumbnail to view a full-sized image.

The Koch snowflake generator algorithm is described by a KSFractalGenerator class. Listing 4 is an excerpt of the KS applet. (See the Resources section for the Koch Snowflake applet, KS.java and KS.html.)

Listing 4. An excerpt of the Koch Snowflake applet

class KSFractalGenerator implements FractalGenerator {
     private final static double SIN60 = Math.sin (Math.PI/3.0);

     private final static int MAX_DEPTH = 4;

     private final static int OFFSET = 18;

     private Line2D line = new Line2D.Double (0.0, 0.0, 0.0, 0.0);

     private Stroke stroke = new BasicStroke (2.0f, BasicStroke.CAP_ROUND,
                                              BasicStroke.JOIN_ROUND);

     public void generate (Graphics2D g, int depth, int width, int
height)
     {
        // Precalculate height/5, width/2, and width/5 for speed.

        double h5 = height/5.0;
        double w2 = width/2.0;
        double w5 = width/5.0;

        ks (w2, h5-OFFSET, w5, 4.0*h5-OFFSET, depth, g); // left side
        ks (w5, 4.0*h5-OFFSET, 4.0*w5, 4.0*h5-OFFSET, depth, g); // bottom side
        ks (4.0*w5, 4.0*h5-OFFSET, w2, h5-OFFSET, depth, g); // right side
     }

     public int maxDepth ()
     {
        return MAX_DEPTH;
     }

     private void ks (double x1, double y1, double x2, double y2, int depth,
                      Graphics2D g)
     {
        if (depth <= 0)
        {
            g.setStroke (stroke);
            line.setLine (x1, y1, x2, y2);
            g.draw (line);
        }
        else
        {
            double x4 = x1*2.0/3.0+x2/3.0;
            double y4 = y1*2.0/3.0+y2/3.0;
            double x5 = x1/3.0+x2*2.0/3.0;
            double y5 = y1/3.0+y2*2.0/3.0;
            double x6 = (x4+x5)/2.0+(y4-y5)*SIN60;
            double y6 = (y4+y5)/2.0+(x5-x4)*SIN60;

            ks (x1, y1, x4, y4, depth-1, g);
            ks (x4, y4, x6, y6, depth-1, g);
            ks (x6, y6, x5, y5, depth-1, g);
            ks (x5, y5, x2, y2, depth-1, g);
        }
     }
}

The generate() method chooses the original triangle's endpoints so that they are relative to the drawing area's boundaries. It makes three calls to the private ks() method, to calculate the middle line segment on each side of the triangle. These calculations are somewhat tricky to grasp without visualizing them, so take a look at Figure 3.

  • Print
  • Feedback

Resources