Source of FernWindow.java


  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: