Source of FernWindow.java


  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: }