CIS191-s12/Project 10

From MCIS Wiki
< CIS191-s12
Revision as of 19:54, 4 April 2012 by Professor Peterson (Talk | contribs) (Polygon)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Simple Fractals

Due Wednesday, April 4

This program uses recursion to create simple fractal images.

Starter project:


The Point2 class contains the following methods:

   public Point2(double x, double y)
   public Point2 scale(double s)  // Multiply x and y by s
   public Point2 add(Point2 p)
   public Point2 interp(Point2 p, double t) //  interpolation
   public double dist(Point2 p) // Distance from here to point p
   public String toString()  // Return point in the form "(1.0,2.0)"

The "interp" method is interpolation - when the t argument is 0 it returns the coordinate of "this", when t is 1 it returns the coordinate of p, and when in between returns coordinates on the line between them. Each component uses the same formula: (1-t)*coordinate in this + t*coordinate in p. For example,

 Point2 a = new Point2(1,1);
 Point2 b = new Point2(2, 3);
 System.out.println(a.interp(b, .5));

would print (1.5, 2.0).


A shape is just an ArrayList of points. This class is provided for you. The static method regularShape creates a shape with a given number of sides whose first and last point have a y coordinate of 0. You can make other shapes by explicitly creating points.

Here is regularShape:

    public static Shape regularShape(int sides) {
        ArrayList<Point2> p = new ArrayList<Point2>();
        double dy=0;
        for (int i = 0; i < sides; i++) {
            double theta = (i+.5)*2*Math.PI/sides-Math.PI/2;
            double x = Math.cos(theta);
            double y = Math.sin(theta);
            if (i == 0) dy = -y;
            p.add(new Point2(x,y+dy));
        return new Shape(p);


This is a drawable polygon that is filled with a solid color. Coordinates are screen coordinates.

As in Shape, there is an ArrayList of points. There is also a color and some integer arrays that are needed to draw the polygon. The drawing code is provided. You need to fill in the constructor and the decorate methods to complete this class.

The constructor is the hard part - it takes a shape, an origin (the screen coordinate that (0,0) in the shape will be placed at, and the location of the first point. All other points in the shape translated according to the location of the first point.

For example, a square can be represented by (1,0), (1,2), (-1, 2), (-1, 0). Note that the "grab point" is at (0,0), the center of the base of the square. If you convert this to a polygon with origin of (1,2) and first point at (3,2), then the other points will go at (3,6), (-1, 6), and (-1, 2). That is, the square is stretched and moved.

If the origin is O, the first point is moved to P, and the shape has a first point of F, each point in the shape, SP, becomes a point in the polygon, PP, according to the following formula:

dp = the distance from O to P
ds = the distance from (0,0) to F
scale = dp/ds
dx = P.x - O.x
dy = P.y = O.y
sin = dy/dp
cos = dx /dp
PP.x = scale*(SP.x*cos-SP.y*sin)+O.x
PP.y = scale*(SP.x*sin+SP.y*cos)+O.y

Test this by drawing a single polygon.

The decorate method is declared as:

 public ArrayList<Polygon> decorate(Shape s, boolean closingEdge)

This creates a list of Polygon objects, each of which corresponds to an edge in the polygon. The boolean "closingEdge" determines whether a fractal should be generated for the edge connecting the last point in the polygon to the first one.

Have this method create a polygon for each edge, where the origin on the polygon is the midpoint of the edge and the first point is at the second of the two points.


Here are some test for you to check your code with:


This file:
package recursion;

public class Tests {
    public static void main(String[] args) {
    Point2 a = new Point2(1,1);
    Point2 b = new Point2(2,3);
    System.out.println("a = " + a + " b = " + b);
    System.out.println("a + b = " + a.add(b));
    System.out.println("a.dist(b) = " + a.dist(b));
    System.out.println("a.interp(b, .5) = " + a.interp(b, .5));
    System.out.println("a.interp(b, .1) = " + a.interp(b, .1));

Should print

a = (1.0,1.0) b = (2.0,3.0)
a + b = (3.0,4.0)
a.dist(b) = 2.23606797749979
a.interp(b, .5) = (1.5,2.0)
a.interp(b, .1) = (1.1,1.2000000000000002)


The following main program:

public class Recursion extends javax.swing.JFrame {
    public ArrayList<Polygon> world = new ArrayList<Polygon>();
    /** Creates new form Recursion */
    public Recursion() {
        ArrayList<Point2> a = new ArrayList<Point2>();
        a.add(new Point2(1,0));
        a.add(new Point2(0.5, -1));
        a.add(new Point2(0, 0));
        Shape s = new Shape(a);
        for (int i = 0; i < 400; i = i + 100) {
            world.add(new Polygon(s, new Point2(i, 100), new Point2(i+50, 100), Color.RED));
        world.add(new Polygon(s, new Point2(50, 120), new Point2(100, 200), Color.BLUE));
        world.add(new Polygon(s, new Point2(50, 400), new Point2(150, 440), Color.BLUE));
        Shape s1 = Shape.regularShape(5);
        world.add(new Polygon(s1, new Point2(300, 300), new Point2(310, 320), Color.GREEN));
        Polygon p = new Polygon(s1, new Point2(400, 150), new Point2(425, 150), Color.BLACK);
        world.addAll(p.decorate(s, true));
    public class MyPanel extends JPanel {

        public void paint(Graphics g) {
            for (Polygon p : world) {

Produces the following picture: