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