Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
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
Page 3 of 7

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.
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:
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.
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.
Archived Discussions (Read only)