public class FernWindow extends JFrame
1:
2: import java.util.Scanner;
3: import java.awt.*;
4: import javax.swing.*;
5:
6: /**
7: * A collection of methods for drawing ferns.
8: *
9: * @author Mark Young
10: */
11: public class FernWindow extends JFrame {
12:
13: // ---------- Here is the program part -------------------------------- //
14:
15: /** default width for a fern window */
16: public static final int DEFAULT_WIDTH = 800;
17: /** default height for a fern window */
18: public static final int DEFAULT_HEIGHT = 600;
19:
20: // here is the program -- the class is below
21: public static void main(String[] args) {
22: Scanner kbd = new Scanner(System.in);
23:
24: // introduce yourself
25: System.out.println("\n\n"
26: + "Fern Drawing Program\n"
27: + "--------------------\n\n");
28:
29: // get window parameters (all windows the same size)
30: System.out.print("How big should the windows be (width height)? ");
31: int width = kbd.nextInt();
32: int height = kbd.nextInt();
33: kbd.nextLine();
34: if (width <= 0) width = DEFAULT_WIDTH;
35: if (height <= 0) height = DEFAULT_HEIGHT;
36:
37: // repeat
38: String resp;
39: do
40: {
41: // get root location
42: System.out.println();
43: System.out.print("Where should the root of the fern be? ");
44: int x = kbd.nextInt();
45: int y = kbd.nextInt();
46: kbd.nextLine();
47:
48: // get angle of growth
49: System.out.print("What angle should the fern grow at "
50: + "(180 = straight up)? ");
51: int angle = kbd.nextInt();
52: kbd.nextLine();
53:
54: // get fern size
55: System.out.print("And what height should the fern be? ");
56: int size = kbd.nextInt();
57: kbd.nextLine();
58:
59: // draw that fern in a new window
60: FernWindow win = new FernWindow(width, height, x, y, angle, size);
61: win.setVisible(true);
62:
63: // ask if there's more
64: System.out.print("another (y/n)> ");
65: resp = kbd.nextLine().toUpperCase();
66: } while (resp.startsWith("Y"));
67: System.exit(0);
68: }
69:
70: // ---------- below is the class -------------------------------------- //
71:
72: /** the part of the window we draw in */
73: private Graphics canvas;
74: /** the x-coordinate of the fern's root */
75: private double rootX;
76: /** the y-coordinate of the fern's root */
77: private double rootY;
78: /** the angle the fern grows away from its root (180 = straight up) */
79: private double rootAngle;
80: /** the root-to-tip length of the fern (it'll actually be a bit shorter) */
81: private double fullSize;
82:
83: /**
84: * Create a window for a fern to be drawn in.
85: *
86: * @param width the outer width of the window
87: * @param height the outer height of the window
88: * @param x the x-coordinate of the fern's root
89: * @param y the y-coordinate of the fern's root
90: * @param angle the angle the fern grows from its root
91: * @param size the nominal size of the fern
92: */
93: public FernWindow(int width, int height,
94: double x, double y, double angle, double size) {
95: super("A Fern by MYoung");
96: setSize(width, height);
97: setBackground(Color.BLACK);
98: rootX = x;
99: rootY = y;
100: rootAngle = angle;
101: fullSize = size;
102: }
103:
104: /**
105: * Respond to the computer's request to paint the window.
106: * This method called by the computer when the window gets shown.
107: *
108: * @param g the canvas to draw on -- provided by the computer.
109: */
110: public void paint(Graphics g) {
111: // use the canvas the computer provides
112: canvas = g;
113:
114: // choose a darkish green pen
115: canvas.setColor(new Color(0, 127, 0));
116:
117: // draw the fern
118: drawFern(rootX, rootY, rootAngle, fullSize);
119: }
120:
121: /**
122: * Draw a fern on my own canvas.
123: * This is a recursive method. You should understand how it works.
124: *
125: * @param x the x-coordinate of the fern's root
126: * @param y the y-coordinate of the fern's root
127: * @param angle the angle the fern grows from its root
128: * @param size the nominal size of the fern
129: */
130: public void drawFern(double x, double y, double angle, double size) {
131: // draw the stem and note where it ends
132: double length = size * 0.5;
133: double[] end = drawStem(x, y, angle, length);
134:
135: // if the fern is big...
136: if (size > 1.0) {
137: // ...draw smaller ferns for the fronds
138: double smaller = size * 0.4;
139: drawFern(end[0], end[1], angle + 60, smaller);
140: drawFern(end[0], end[1], angle, smaller);
141: drawFern(end[0], end[1], angle - 60, smaller);
142: }
143: }
144:
145: /**
146: * Draw the stem of a fern, returning the coordinates of its upper end.
147: * (You do not need to understand how this method works.)
148: *
149: * @param x the x-coordinate of the stem's root
150: * @param y the y-coordinate of the stem's root
151: * @param angle the angle the stem grows from its root
152: * @param length the length of the stem
153: * @return an array with the x and y coordinates of the stem's top
154: * in its two cells
155: */
156: public double[] drawStem(double x, double y, double angle, double length) {
157: // convert from degrees to radians for the sin & cos functions
158: double radians = Math.toRadians(angle);
159:
160: // figure out (and remember) where the line should end
161: double[] end = new double[2];
162: end[0] = x + Math.sin(radians) * length;
163: end[1] = y + Math.cos(radians) * length;
164:
165: // draw the line
166: drawLine(x, y, end[0], end[1]);
167:
168: // return the end-point
169: return end;
170: }
171:
172: /**
173: * Draw a line on my convas.
174: * (You do not need to understand how this method works.)
175: *
176: * @param x1 the x-coordinate of the start of the line
177: * @param y1 the y-coordinate of the start of the line
178: * @param x2 the x-coordinate of the end of the line
179: * @param y2 the y-coordinate of the end of the line
180: */
181: public void drawLine(double x1, double y1, double x2, double y2) {
182: // round off the start/end coordinates...
183: int startX = (int)Math.round(x1);
184: int startY = (int)Math.round(y1);
185: int endX = (int)Math.round(x2);
186: int endY = (int)Math.round(y2);
187:
188: // ... because the canvas expects to be given integer coordinates
189: canvas.drawLine(startX, startY, endX, endY);
190: }
191:
192: }
193: