CMPU 102 - Assignment 4 Due: by 11:59 PM on Thursday, September 29th

In this assignment, you will implement classes representing simple geometric shapes that can draw themselves on a two-dimensional surface.

\$Revision: 1.8 \$

## Basic classes and interfaces

The Canvas interface represents the drawing surface.  The Point class represents a single Cartesian point on the Canvas.  Each Point has an X and Y coordinate.  Just like in geometry, X coordinates increase in value to the right and decrease to the left, and Y coordinates increase in value going up and decrease in value going down:

Here are the methods for the Shape interface.  Each class that you write to represent a shape will implement this interface.

• public void setCenter(Point point) - change the position of the Shape by giving it a new center Point.

• public Point getCenter() - return the current center Point of the shape

• public void setColor(Color color) - set the shape's Color to the one given

• public void draw(Canvas canvas) - use the given Canvas object to draw the shape. The position of the shape will be determined by its current center Point.

• public boolean contains(Point point) - return true if the given Point is inside the shape, or return false if the given Point is outside the shape.

The Point class is extremely simple.  It has a constructor to initialize a new Point with specified X and Y coordinates, and methods getX and getY to return the value of those coordinates as double values.

The Canvas interface is what you will use in the draw method for each of your Shape classes in order to actually draw the Shape.  It has the following methods:

• public void drawCircle(Point center, double radius, Color color): Draw a circle on the Canvas whose size and position are determined by center (the center Point of the circle) and radius.  The color of the circle is specified by color.

• public void drawRectangle(Point upperLeft, double width, double height, Color color): Draw a rectangle on the Canvas.  The position of the rectangle is specified by the upperLeft point, which is the upper left corner of the rectangle.  The size of the rectangle is determined by width and height, and the color is determined by color.

• public void drawPolygon(Point[] points, Color color): Draw an arbitrary closed polygon determined by the given array of Point objects.  The color of the polygon is specified by color.

## CompositeShape

In addition to the simple Shape classes you will need to write, you must also complete a class called CompositeShape.  A CompositeShape is simply a collection of other Shape objects.  For example, you might define a CompositeShape composed of a rectangle and a circle to represent a picture of a tree: the rectangle being the trunk and the circle being the leaves.  Each child Shape is positioned at an offset from the CompositeShape's center, and when the position of the CompositeShape is changed, the position of each child Shape changes by the same amount.

The only methods you will need to implement in CompositeShape are draw and contains.  The draw method should simply draw all of the child Shapes in the order they were added to the CompositeShape.  The contains method should return true if it is passed a Point that is contained in any of the child Shapes, or false otherwise.

## ShapeFactory

In order to create actual Shape objects, you will add code to the static methods defined in the ShapeFactory class.  Each of the methods creates a particular kind of Shape, with a specified size.  By default, each new Shape should start out with its center at the Point representing the origin (0,0), and its color set to the color java.awt.Color.BLACK.

To help you get started, a Shape class called Rectangle is provided, and ShapeFactory's createRectangle method is implemented to use it.

Here are the methods defined in ShapeFactory, and how each of them should work:

• public static Shape createSquare(double widthAndHeight): Return a new Shape representing a square with the given width/height.  When drawn, the square should look like this:

• public static Shape createRectangle(double width, double height): Return a new Shape representing a rectangle with the given width and height.  When drawn, the rectangle should look like this:

• public static Shape createCircle(double radius): Return a new Shape representing a circle with the given radius.  When drawn, the circle should look like this:

• public static Shape createTriangle(double width, double height): Return a new Shape representing an isosceles triangle where width is the width of the triangle's base, and height is the height of the triangle.  When drawn, the triangle should look like this:

• public static CompositeShape createCompositeShape(): Return a new, empty CompositeShape object---in order words, a CompositeShape object that contains no child Shapes.

## Getting started

Start by importing the file shapes.zip into Eclipse using the same procedure you used in Lab 1: from the menu, choose "File->Import->Existing Projects into Workspace", click "Select archive file", select "shapes.zip" from the file selection dialog, and then click the "Finish" button.

Your main task for the project is to implement all of the methods in the ShapeFactory class.  Ths will involve writing one or more new classes (implementing the Shape interface), and also modifying the existing CompositeShape class.)

You may want to refer to the instructions for Creating a new class in Eclipse.

You will need to test your project carefully.  Add tests to the ShapeTest class to test the Shape classes you have written.  The class already contains some example tests on a rectangle that you can use as a model.  ShapeTest is a JUnit test case, so you can execute tests the same way as in Lab 2.  Be sure to:

• make sure each of your Shape classes is tested
• create as many Shape objects as you need to perform your tests; they should be added as fields of the ShapeTest class
• only put one assertion in each test method; that way when a test fails, it will be clear what the problem is

Note that it will not be very easy to test the draw method using JUnit, since it requires a Canvas to draw on.  So, to test the draw methods of your Shape classes, you can run the provided PictureDemo class.  It will show a window that looks something like this:

To test the contains and draw methods interactively, you can run the provided ContainsDemo class.  As you move the mouse, the shapes containing the location (point) of the mouse will be highlighted.

To run the main method for each of these demos, you may refer to the instructions for Running a main method in Eclipse.

## Hints and Tips

• What do rectangles and squares have in common?

• The contains method for triangles will be more complicated than for the other shapes.  For partial credit, or just to get started, you may treat a triangle as though it were a rectangle with the same width and height (only for the contains method).

• You can compute the square root of a double value by calling the Math.sqrt method.  For example:
```double value = 16.0;
System.out.println(Math.sqrt(value)); // prints "4.0"
```

## Something Fun

Once you have all of your Shape classes working correctly, try running the main method in the Invaders class.  Use the left and right arrow keys to move, and the space bar to fire.

## Submitting the project

To submit the project, type the following commands in a terminal window (hitting return after each command):

```cd
cd eclipse-workspace
submit102 shapes
```

You may submit as many times as you wish.  The final submission prior to the deadline will be graded.