Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

AhmadLang / Java, How To Program, 2004

.pdf
Скачиваний:
626
Добавлен:
31.05.2015
Размер:
51.82 Mб
Скачать

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]

As an example, let us look at a popular strictly self-similar fractal known as the Koch Curve (Fig. 15.17). This fractal is formed by removing the middle third of each line in the drawing and replacing it

with two lines that form a point, such that if the middle third of the original line remained, an equilateral triangle would be formed. Formulas for creating fractals often involve removing all or part of the previous fractal image. This pattern has already been determined for this fractalin this section we focus not on how to determine what formulas are needed for a specific fractal, but how to use those formulas within a recursive solution. Most formulas can be used to create fractals, but not all fractals will resemble objects in nature.

We start with a straight line (Fig. 15.17, Part a) and apply the pattern, creating a triangle from the middle third (Fig. 15.17, Part b). We then apply the pattern again to each straight line, resulting in Fig. 15.17, Part c. Each time the pattern is applied, we say that the fractal is at a new level, or depth (sometimes the term order is also used). Fractals can be displayed at many levelsfor instance, a fractal at level 3 has had three iterations of the pattern applied (Fig. 15.17, Part d). After only a few iterations, this fractal begins to look the same, like a portion of a snowflake (Fig. 15.17, Parts e and f). The applications of the pattern are now too small for the human eye to see a difference. Since this is a strictly self-similar fractal, each portion of the fractal contains an exact copy of the fractal. In Part f of Fig. 15.17, for example, we have highlighted a portion of the fractal with a dashed red box. If the image in this box were increased in size, it would look exactly like the entire fractal of Part f.

[Page 765]

There is a similar fractal, the Koch Snowflake, which is the same as the Koch Curve but begins with a

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]

Figure 15.21. "Lo fractal" at level 2, with dashed lines from level 1 provided.

(This item is displayed on page 767 in the print version)

[View full size image]

Figure 15.22. "Lo fractal" at level 2.

(This item is displayed on page 768 in the print version)

[View full size image]

Figure 15.23. Demonstrating the fractal user interface.

(This item is displayed on pages 768 - 770 in the print version)

1

//

Fig. 15.23: Fractal.java

2

//

Demonstrates user interface for drawing a fractal.

3

import java.awt.Color;

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

18public FractalJPanel( int currentLevel )

19{

20color = Color.BLUE; // initialize drawing color to blue

21level = currentLevel; // set initial fractal level

22setBackground( Color.WHITE );

23setPreferredSize( new Dimension( WIDTH, HEIGHT ) );

24} // end FractalJPanel constructor

25

26// draw fractal recursively

27public void drawFractal( int level, int xA, int yA, int xB,

28int yB, Graphics g )

29{

30// base case: draw a line connecting two given points

31if ( level == 0 )

32g.drawLine( xA, yA, xB, yB );

33else // recursion step: determine new points, draw next level

34{

35// calculate midpoint between (xA, yA) and (xB, yB)

36

int

xC

=

(

xA

+

xB

)

/

2;

37

int

yC

=

(

yA

+

yB

)

/

2;

38

 

 

 

 

 

 

 

 

 

 

39// calculate the fourth point (xD, yD) which forms an

40// isosceles right triangle between (xA, yA) and (xC, yC)

41// where the right angle is at (xD, yD)

42

int

xD

=

xA

+

(

xC

-

xA

)

/

2

-

(

yC

-

yA

)

/

2;

43

int

yD

=

yA

+

(

yC

-

yA

)

/

2

+

(

xC

-

xA

)

/

2;

44

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

45// recursively draw the Fractal

46drawFractal( level - 1, xD, yD, xA, yA, g );

47drawFractal( level - 1, xD, yD, xC, yC, g );

48drawFractal( level - 1, xD, yD, xB, yB, g );

49} // end else

50} // end method drawFractal

51

52// start the drawing of fractal

53public void paintComponent( Graphics g )

54{

55super .paintComponent( g );

56

57// draw fractal pattern

58g.setColor( color );

59drawFractal( level, 100, 90, 290, 200, g );

60} // end method paintComponent

61

62// set the drawing color to c

63public void setColor( Color c )

64{

65color = c;

66} // end method setColor

67

68// set the new level of recursion

69public void setLevel( int currentLevel )

70{

71level = currentLevel;

72} // end method setLevel

73

74// returns level of recursion

75public int getLevel()

76{

77return level;

78} // end method getLevel

79} // end class FractalJPanel

[View full size image]

[View full size image]