Computer Science 252
Problem Solving with Java

Spring 2016, The College of Saint Rose

Broccoli BlueJ Project

Click here to download a BlueJ project for Broccoli.


Broccoli Source Code

The Java source code for Broccoli is below. Click on a file name to download it.


Broccoli.java

/**
 * Program to create a recursive graphics which looks like broccoli.
 * Written 11/4/99 by Kim Bruce
 * Modified 4/20/00 by Andrea Danyluk
 * 
 * Updated by Jim Teresco for CSC 252, The College of Saint Rose, Fall 2013
 * Code cleanup, Spring 2016
 * 
 * $Id: Broccoli.java 2924 2016-03-31 00:40:33Z terescoj $
 */

import objectdraw.*;
import java.awt.*;

public class Broccoli extends WindowController {
    
    // some named constants for the first broccoli part
    private static final double STEM_X = 200;
    private static final double STEM_Y = 350;
    private static final double STEM_LENGTH = 80;

    // dragging support
    private Location lastLocation;
    private boolean dragging;
    
    // Broccoli object to be drawn and moved
    private BroccoliBranch plant;

    // In begin, we just create the broccoli
    public void begin() {

        plant = new BroccoliBranch(new Location(STEM_X,STEM_Y), STEM_LENGTH, Math.PI/2.0, canvas);
    }

    // Get ready to move broccoli
    public void onMousePress(Location pt) {
        
        dragging = plant.contains(pt);
        lastLocation = pt;
    }

    // Drag the broccoli around
    public void onMouseDrag(Location pt) {
        
        if (dragging) {
            plant.move(pt.getX()-lastLocation.getX(), 
                       pt.getY()-lastLocation.getY());
            lastLocation = pt;
        }
    }
}


AngLine.java

/*
 * AngLine.java     Jonathan Kallay 7/14/99
 * (c) 1999 Williams College
 */
import java.awt.*;
import objectdraw.*;

/**
 * AngLine is an implementation of a drawable line object.
 *
 * @author Jonathan Kallay
 * @version 1.0 last update 8/25/99
 * 
 * Updated by Jim Teresco for CSC 252, The College of Saint Rose, Fall 2013
 * 
 * $Id: AngLine.java 2244 2013-11-06 04:54:22Z terescoj $
 */
public class AngLine extends Line implements LineInterface {
    private double length;
    private double angle;

    /**
     * Creates a new AngLine object.
     * @param start the starting point of the line.
     * @param dest the destination point of the line.
     * @param c the canvas in which the line is created.
     */
    public AngLine(Location start, double length, double radianAngle, DrawingCanvas canvas){
        super(start,new Location(start.getX() + length*Math.cos(radianAngle),
                start.getY() - length*Math.sin(radianAngle)),canvas);
        this.length = length;
        angle = radianAngle;
    }

    public Location getDest() {
        return new Location(start.getX() + length*Math.cos(angle),
            start.getY() - length*Math.sin(angle));
    }

}


BroccoliBranch.java

/*
 * Class to recursively draw broccoli
 * 
 * From Williams College, CSC 134
 * 
 * Updated by Jim Teresco for CSC 252, The College of Saint Rose, Fall 2013
 * Code cleanup, Spring 2016
 * 
 * $Id: BroccoliBranch.java 2924 2016-03-31 00:40:33Z terescoj $ 
 */
import objectdraw.*;
import java.awt.*;

public class BroccoliBranch {

    // How much broccoli shrinks each call
    private static final double TOP_FRACT = 0.8;
    // How little a branch must be before broccoli stops expanding
    private static final double GROWTH_LIMIT = 20.0;
    // The size (width and height) of a flower
    private static final int FLOWER_SIZE = 3;

    // branches of broccoli: our recursive data structure
    // note that in this case this not one "next", but three!
    // these will be null if we are at the base case
    private BroccoliBranch left, center, right;

    // stem of broccoli-- every BroccoliBranch has one
    private AngLine stem;

    // Flower of broccoli plant, null except in base case (and that's how we'll tell)
    private FilledOval flower;

    /**
     * Draw broccoli by recursively drawing branches (and eventually flower)
     */
    public BroccoliBranch(Location startLocation, double size, double direction, DrawingCanvas canvas) {

        // Draw stem and color green (we always have this)
        stem = new AngLine(startLocation,size,direction,canvas);
        stem.setColor(Color.green);

        Location destLocation = stem.getDest(); // end of stem

        if (size > GROWTH_LIMIT) {  // we're big enough to keep growing
            left = new BroccoliBranch(destLocation, size * TOP_FRACT,
                direction + Math.PI/9.0, canvas);
            center = new BroccoliBranch(destLocation, size * TOP_FRACT,
                direction, canvas);
            right = new BroccoliBranch(destLocation, size * TOP_FRACT,
                direction - Math.PI/9.0, canvas);
        } 
        else {  
            // draw flower when small enough -- note this will be null except
            // in the base case, and will be used to determine the base for
            // recursive methods
            flower = new FilledOval(destLocation,FLOWER_SIZE,FLOWER_SIZE,canvas);
            flower.setColor(Color.yellow);
        }
    }

    // standard move method, but this one's recursive
    public void move(double x, double y) {

        stem.move(x,y);     // move stem in all cases

        if (flower == null)  {
            // not the base case, so move rest of broccoli - three branches
            left.move(x,y);
            center.move(x,y);
            right.move(x,y);
        } 
        else {
            // move flower only, it's the base case
            flower.move(x,y);
        }
    }
    
    // contains, also needs recursion here
    public boolean contains(Location point) {
    
        // first, check stem, since we always know we have one
        if (stem.contains(point)) return true;
        
        // ok, stem didn't contain the point, so we keep checking
        // do base case next: if flower is not null, it's the only hope we
        // have to contain the point, so it would be our answer
        if (flower != null) {
            return flower.contains(point);
        }
        
        // we must be in a recursive case, so we need to try all three branches
        return left.contains(point) || center.contains(point) || right.contains(point);
        
    }
    
}

LineInterface.java

import objectdraw.*;
/*
 * Interface for objects that have an endpoint
 * 
 * Updated by Jim Teresco for CSC 252, The College of Saint Rose, Fall 2013
 * 
 * $Id: LineInterface.java 2924 2016-03-31 00:40:33Z terescoj $
 */

public interface LineInterface {

    // Return endpoint
    public Location getDest();
}