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 7 of 7

The zoom-in logic is guarded by an expression, and the same is true for the zoom-out logic. The level < 31 expression prevents a program crash that arises when the increments (calculated in paintComponent()) become too small. The level != 0 expression prevents zooming out of the starting level (level 0), which results in an exception arising from an empty stack (which I use to remember clicked locations for zoom out).

Fractal trivia
Interesting facts about the Mandelbrot set abound. Consider the following:
  • Its area is unknown (but is quite small)
  • Its border is an infinitely-long fractal.
  • The barnacle-covered pear shape occurs an infinite number of times.
  • All of the black areas are connected.
  • It can be used to (inefficiently) calculate Pi.
  • No color intersects another color.
  • It has infinite detail -- you can zoom in forever.
Unfortunately, my applet (as currently written) does not let you continually zoom into the Mandelbrot set. How would you solve this problem?

Mountain ridgeline

Fractals play a significant role in today's terrain-generation software. Whether you are looking at a mountain or a cloud, chances are that the object is fractal based. For example, a Mountain ridgeline can be generated by a fractal that is similar to the Koch snowflake. My Mountain ridgeline fractal relies on the midpoint displacement algorithm, which begins with a horizontal line segment:

  1. Calculate the line segment's midpoint.
  2. Move the midpoint up or down by a randomly selected distance.
  3. At the midpoint, divide the line segment into two line segments. Repeat all three steps for each line segment.

Figure 8 reveals the midpoint displacement algorithm at work. The original line segment appears at the top of the figure and the middle part shows the algorithm after one iteration (depth 1 recursion). Note that the midpoint has been displaced upwards, and the bottom part (depth 2 recursion) displaces one midpoint up and displaces the other midpoint down.

The midpoint displacement algorithm at work.

Figure 8. The midpoint displacement algorithm at work.

As with the algorithms for generating the Koch snowflake and Sierpinski triangle, the generator algorithm for the Mountain ridgeline fractal is described by a FractalGenerator class -- MRFractalGenerator. The MRFractalGenerator class in Listing 8 is excerpted from the Mountain Ridgeline applet. (See the Resources section for MR.java and MR.html.)

Listing 8. The MRFractalGenerator class

class MRFractalGenerator implements FractalGenerator
{
     private final static int MAX_DEPTH = 8;

     private Color violet = new Color (191, 64, 251);

     private int [] heights;

     public void generate (Graphics2D g, int depth, int width, int  
height)
     {
        g.setPaint (new GradientPaint (0, 0, violet, 0, height,
Color.yellow));
        g.fill (new Rectangle (0, 0, width, height));

        if (depth == MAX_DEPTH)
        {
            heights = new int [width];
            for (int i = 0; i <heights.length; i++)
                 heights [i] = height/2;
        }

        g.setColor (Color.black);
        mr (0, height/2, width-1, height/2, depth, g);

        if (depth == MAX_DEPTH)
        {
            for (int i = 0; i < width; i++)
                 g.drawLine (i, heights [i], i, height-1);
            heights = null;
        }
     }

     public int maxDepth ()
     {
        return MAX_DEPTH;
     }

     private void mr (int x1, int y1, int x2, int y2, int depth,
Graphics2D g)
     {
        if (depth <= 0 || x1 == x2)
        {
            g.drawLine (x1, y1, x2, y2);
            return;
        }

        int midx = (x1+x2)/2;
        int midy = (y1+y2)/2;

        int len = (int) Math.sqrt ((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));

        if (rnd (2) == 0)
            midy -= rnd (x2-x1)/3;
        else
            midy += rnd (x2-x1)/3;

        if (heights != null)
            heights [midx] = midy;

        mr (x1, y1, midx, midy, depth-1, g);
        mr (midx, midy, x2, y2, depth-1, g);
     }

     private int rnd (int limit)
     {
        return (int) (Math.random ()*limit);
     }
}

Let's review this class. For starters, I predefine the Color object violet for use in a violet-to-yellow gradient that simulates a sunrise or sunset. I also predefine a heights array variable to store integers that help to present the mountain ridge in black silhouette (and in front of the sunrise/sunset), but only after the maximum depth has been reached. Figure 9 reveals the result.

A mountain ridgeline in black silhouette.

Figure 9. A mountain ridgeline in black silhouette.

The recursive mr() method generates the fractal at a specific depth. If the depth is 0 or the line segment's horizontal coordinates are identical (either serves as the recursion-stopping condition), this method draws the line segment and begins to unwind the recursion. Otherwise, mr() calculates the line segment's midpoint and displaces the midpoint by one third of the segment's length -- and so the recursion continues.

Calculating maximum depth
The MR.html file specifies 360 as the applet's width. Because this results in the fractal animator component having a width of 202, 8 is the lowest possible value for the MAX_DEPTH constant. When the maximum depth is less than 8, vertical streaks appear in or above the black silhouette because not all of the entries in the heights array have been set to the actual heights of the silhouette -- the heights entry at index 201 never changes from its height/2 default.

Conclusion

In addition to their entertainment value, fractals have practical uses. For example, this article showed how you might use fractal algorithms to develop the graphical interface for computer games. You can also use fractals for common application use cases like image compression and music generation. Researchers are also using fractals in the fields of seismology and human biology (where they aid in the understanding of biological systems that exhibit fractal properties -- such as the lungs and bronchial system). See the Resources section to learn more about fractals and their uses.

About the author

Read more about Core Java in JavaWorld's Core Java section.


Friesen is a freelance software developer and educator who specializes in Java technology. Check out his Website to discover all of his published Java articles and more.
  • Print
  • Feedback

Resources