import objectdraw.*; import java.awt.*; /** * A recursive Broccoli structure. */ public class Broccoli { // dark green color for broccoli private static final Color BROCCOLI_COLOR = new Color(0, 135, 0); // How much broccoli shrinks each call private static final double SHRINK_FACTOR = 0.8; // How little a branch must be before broccoli stops expanding private static final double SIZE_SMALLEST_BRANCH = 20.0; // angle increment/decrement for left and right branches private static final double BRANCH_ANGLE_INC = Math.PI / 9.0; // stem of broccoli private AngLine stem; // branches of broccoli private Broccoli leftBranch, centerBranch, rightBranch; // length of stem private double stemLength; // Draw broccoli by recursively drawing branches public Broccoli(Location stemStartLocation, double stemLength, double stemAngle, DrawingCanvas canvas) { this.stemLength = stemLength; // Draw stem and color green stem = new AngLine(stemStartLocation, stemLength, stemAngle, canvas); stem.setColor(BROCCOLI_COLOR); // Big enough to keep growing if (stemLength > SIZE_SMALLEST_BRANCH) { // end of stem Location nextStartLocation = stem.getEnd(); leftBranch = new Broccoli(nextStartLocation, stemLength * SHRINK_FACTOR, stemAngle + BRANCH_ANGLE_INC, canvas); centerBranch = new Broccoli(nextStartLocation, stemLength * SHRINK_FACTOR, stemAngle, canvas); rightBranch = new Broccoli(nextStartLocation, stemLength * SHRINK_FACTOR, stemAngle - BRANCH_ANGLE_INC, canvas); } } // is a Location object "in" the Broccoli? public boolean contains(Location point) { if (stem.contains(point)) { return true; } if (stemLength > SIZE_SMALLEST_BRANCH) { return leftBranch.contains(point) || centerBranch.contains(point) || rightBranch.contains(point); } return false; } // move broccoli by offsets x and y public void move(double xPixels, double yPixels) { stem.move(xPixels, yPixels); if (stemLength > SIZE_SMALLEST_BRANCH) { leftBranch.move(xPixels, yPixels); centerBranch.move(xPixels, yPixels); rightBranch.move(xPixels, yPixels); } } }