AhmadLang / Java, How To Program, 2004
.pdf
5 |
{ |
|
|
|
|
|
|
|
|
|
|
|
6 |
public |
static |
void |
|
main( |
String |
args[] |
) |
||||
7 |
{ |
|
|
|
|
|
|
|
|
|
|
|
8 |
int |
startPeg |
= |
|
1 |
; |
// |
value |
1 |
used |
to indicate startPeg in output |
|
9 |
int |
endPeg |
= |
3 |
; |
|
|
// |
value |
3 |
used |
to indicate endPeg in output |
10 |
int |
tempPeg |
|
= |
2 |
; |
|
// |
value |
2 |
used |
to indicate tempPeg in output |
11int totalDisks = 3; // number of disks
12TowersOfHanoi towersOfHanoi = new TowersOfHanoi( totalDisks );
14// initial nonrecursive call: move all disks.
15towersOfHanoi.solveTowers( totalDisks, startPeg, endPeg, tempPeg );
16} // end main
17} // end class TowersOfHanoiTest
1--> 3
1--> 2
3--> 2
1--> 3
2--> 1
2--> 3
1--> 3
[Page 763 (continued)]
15.9. Fractals
A fractal is a geometric figure that often can be generated from a pattern repeated recursively an infinite number of times (Fig. 15.17). The figure is modified by applying the pattern to each segment of the original figure. Real geometric figures do not have their patterns repeated an infinite number of times, but after several repetitions appear as they would if repeated infinitely. We will look at a few such approximations in this section. [Note: We will refer to our geometric figures as fractals, even though they are approximations.] Although these figures had been studied before the 20th century, it was the Polish mathematician Benoit Mandelbrot who introduced the term "fractal" in the 1970s, along with the specifics of how a fractal is created and the practical applications of fractals. Mandelbrot's fractal geometry provides mathematical models for many complex forms found in nature, such as mountains, clouds and coastlines. Fractals have many uses in mathematics and science. Fractals can be used to better understand systems or patterns that appear in nature (e.g., ecosystems), in the human body (e.g., in the folds of the brain), or in the universe (e.g., galaxy clusters). Drawing fractals has become a popular art form. Fractals have a self-similar propertywhen subdivided into parts, each resembles a reduced-size copy of the whole. Many fractals yield an exact copy of the original when a portion of the original image is magnifiedsuch a fractal is said to be strictly self similar. Links are provided in Section 15.12 for various Web sites that discuss and demonstrate fractals.
[Page 764]
Figure 15.17. Koch Curve fractal.
[View full size image]
triangle rather than a line. The same pattern is applied to each side of the triangle, resulting in an image that looks like an enclosed snowflake. We have chosen to focus on the Koch Curve for simplicity. We will be moving on shortly to another fractal, but if the reader wishes to learn more about the Koch Curve and Koch Snowflake, see the links in Section 15.12.
We now demonstrate the use of recursion to draw fractals by writing a program to create a strictly selfsimilar fractal. We call this the "Lo fractal," named for Sin Han Lo, a Deitel & Associates colleague who created it. The fractal will eventually resemble one-half of a feather (see the outputs in Fig. 15.24). The base case, or fractal level of 0, begins as a line between two points, A and B (Fig. 15.18). To create the next higher level, we find the midpoint (C) of the line. To calculate the location of point C, use the following formula: [Note: The x and y to the left of each letter refer to the x-coordinate and y- coordinate of that point, respectively. For instance, xA refers to the x-coordinate of point A, while yC refers to the y-coordinate of point C. In our diagrams we denote the point by its letter, followed by two numbers representing the x- and y-coordinates.]
Figure 15.18'. "Lo fractal" at level 0.
(This item is displayed on page 766 in the print version)
[View full size image]
To create this fractal, we also must find a point D that lies left of segment AC and creates an isosceles right triangle ADC. To calculate the location of point D, use the following formulas:
We continue the example in Fig. 15.18 by moving on to the next level (from level 0 to level 1) as follows: First, add points C and D (as in Fig. 15.19). Then, remove the original line and add segments DA, DC and DB. The remaining lines curve at an angle, causing our fractal to look like a feather. For the next level of the fractal, this algorithm is repeated on each of the three lines in level 1. For each line, the formulas above are applied, where the former point D is now considered to be point A, while the other end of each line is considered to be point B. Figure 15.20 contains the line from level 0 (now a dashed line) and the three added lines from level 1. We have changed point D to be point A, and the
original points A, C and B to B1, B2 and B3 (the numbers are used to differentiate the various points).
The preceding formulas have been used to find the new points C and D on each line. These points are also numbered 13 to keep track of which point is associated with each line. The points C1 and D1, for instance, represent points C and D associated with the line formed from points A to B1. To achieve level 2, the three lines in Fig. 15.20 are removed and replaced with new lines from the C and D points just added. Figure 15.21 shows the new lines (the lines from level 2 are shown as dashed lines for your convenience). Figure 15.22 shows level 2 without the dashed lines from level 1. Once this process has been repeated several times, the fractal created will begin to look like one-half of a feather, as shown in the output of Fig. 15.24. We will discuss the code for this application shortly.
[Page 766]
Figure 15.19. Determining points C and D for level 1 of "Lo fractal."
[View full size image]
Figure 15.20. "Lo fractal" at level 1, with C and D points determined for level 2. [Note: The fractal at level 0 is included as a dashed line as a reminder of where the line was located in relation to the current fractal.
(This item is displayed on page 767 in the print version)
[View full size image]
4import java.awt.FlowLayout;
5import java.awt.event.ActionEvent;
6import java.awt.event.ActionListener;
7import javax.swing.JFrame;
8import javax.swing.JButton;
9import javax.swing.JLabel;
10import javax.swing.JPanel;
11import javax.swing.JColorChooser;
12
13public class Fractal extends JFrame
14{
15 private final int WIDTH = 400; // define width of GUI
16private final int HEIGHT = 480; // define height of GUI
17private final int MIN_LEVEL = 0;
18private Color color = Color.BLUE;
19
20private JButton changeColorJButton, increaseLevelJButton,
21decreaseLevelJButton;
22private JLabel levelJLabel;
23private FractalJPanel drawSpace;
24private JPanel mainJPanel, controlJPanel;
25
26// set up GUI
27public Fractal()
28{
29super( "Fractal" );
31// set up control panel
32controlJPanel = new JPanel();
33controlJPanel.setLayout( new FlowLayout() );
35// set up color button and register listener
36changeColorJButton = new JButton( "Color" );
37controlJPanel.add( changeColorJButton );
38changeColorJButton.addActionListener(
39new ActionListener() // anonymous inner class
40{
41 |
// |
process changeColorJButton event |
42 |
public void actionPerformed( ActionEvent event ) |
|
43 |
{ |
|
44 |
|
color = JColorChooser.showDialog( |
45 |
|
Fractal.this, "Choose a color", color ); |
46 |
|
|
47 |
|
// set default color, if no color is returned |
48 |
|
if ( color == null ) |
49 |
|
color = Color.BLUE; |
50 |
|
|
51 |
|
drawSpace.setColor( color ); |
52 |
} |
// end method actionPerformed |
53} // end anonymous inner class
54); // end addActionListener
55
56 // set up decrease level button to add to control panel and
57// register listener
58decreaseLevelJButton = new JButton( "Decrease Level" );
59controlJPanel.add( decreaseLevelJButton );
60decreaseLevelJButton.addActionListener(
61new ActionListener() // anonymous inner class
62{
63 |
// |
process decreaseLevelJButton |
event |
||
64 |
public void actionPerformed( ActionEvent event ) |
||||
65 |
{ |
|
|
|
|
66 |
|
int level = drawSpace.getLevel(); |
|||
67 |
|
level--; // decrease level by |
one |
||
68 |
|
|
|
|
|
69 |
|
// modify level if possible |
|
||
70 |
|
if |
( |
level >= MIN_LEVEL ) |
|
71 |
|
{ |
|
|
|
72 |
|
|
levelJLabel.setText( "Level: " + level ); |
||
73 |
|
|
drawSpace.setLevel( level ); |
||
74 |
|
|
repaint(); |
|
|
75 |
|
} |
// |
end if |
|
76 |
} |
// |
end |
method actionPerformed |
|
77} // end anonymous inner class
78); // end addActionListener
79
80// set up increase level button to add to control panel
81// and register listener
82increaseLevelJButton = new JButton( "Increase Level" );
83controlJPanel.add( increaseLevelJButton );
84increaseLevelJButton.addActionListener(
85new ActionListener() // anonymous inner class
86{
87 |
// |
process increaseLevelJButton |
event |
||
88 |
public void actionPerformed( ActionEvent event ) |
||||
89 |
{ |
|
|
|
|
90 |
|
int level = drawSpace.getLevel(); |
|||
91 |
|
level++; // increase level by |
one |
||
92 |
|
|
|
|
|
93 |
|
// modify level if possible |
|
||
94 |
|
if |
( |
level >= MIN_LEVEL ) |
|
95 |
|
{ |
|
|
|
96 |
|
|
levelJLabel.setText( "Level: " + level ); |
||
97 |
|
|
drawSpace.setLevel( level ); |
||
98 |
|
|
repaint(); |
|
|
99 |
|
} |
// |
end if |
|
100 |
} |
// |
end |
method actionPerformed |
|
101} // end anonymous inner class
102); // end addActionListener
103
104// set up levelJLabel to add to controlJPanel
105levelJLabel = new JLabel( "Level: 0" );
106controlJPanel.add( levelJLabel );
107
108 drawSpace = new FractalJPanel( 0 );
109
110// create mainJPanel to contain controlJPanel and drawSpace
111mainJPanel = new JPanel();
112mainJPanel.add( controlJPanel );
113mainJPanel.add( drawSpace );
114
115 add( mainJPanel ); // add JPanel to JFrame
116
117setSize( WIDTH, HEIGHT ); // set size of JFrame
118setVisible( true ); // display JFrame
119} // end Fractal constructor
120
121public static void main( String args[] )
122{
123Fractal demo = new Fractal();
124demo.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
125} // end main
126} // end class Fractal
Figure 15.24. Drawing "Lo fractal" using recursion.
(This item is displayed on pages 771 - 773 in the print version)
1 // Fig. 15.24: FractalJPanel.java
2 // FractalJPanel demonstrates recursive drawing of a fractal.
3import java.awt.Graphics;
4import java.awt.Color;
5import java.awt.Dimension;
6import javax.swing.JPanel;
8public class FractalJPanel extends JPanel
9{
10private Color color; // stores color used to draw fractal
11 |
private |
int level; |
// |
stores |
|
current level of fractal |
||||
12 |
|
|
|
|
|
|
|
|
|
|
13 |
private |
final |
int |
WIDTH |
= |
400; |
|
// |
defines |
width of JPanel |
14 |
private |
final |
int |
HEIGHT |
= |
400 |
; |
// |
defines |
height of JPanel |
15 |
|
|
|
|
|
|
|
|
|
|
16// set the initial fractal level to the value specified
17// and set up JPanel specifications
[View full size image]
