Rectangular Shapes

Many of the objectdraw shapes are very similar in the way they work. Rects, ovals, rounded rects, arcs, and visible images are all defined by the rectangular space that they take up on the screen. More specifically, they all have a Location that is their top left corner, and a width and a height by which they extend from there.

These shapes all implement Drawable2DInterface and Resizable2DInterface, which means that they also implement DrawableLocationInterface and DrawableInterface. The Text class is very similar to these in that it also implements the Drawable2DInterface, but not the Resizable2DInterface.

Table of Contents

1. Rects, Ovals, RoundedRects, and Arcs

Your browser doesn't do Java.
CreateRect.java
The FramedRect, FilledRect, FramedOval, FilledOval, FramedRoundedRect, FilledRoundedRect, FramedArc, FilledArc, and VisibleImage are all known as rectangular shapes, because their size is determined from a rectangular area on the screen. This area is defined by an (x, y) point that is the top left corner of the rectangle, plus a width and height by which the rectangle extends from there.

The simplest two shapes to make are the Rect and Oval classes, for which these four pieces of information are all that is needed:

public FramedRect(double x, double y, double width, double height, DrawingCanvas canvas)
public FramedRect(Location topLeft, double width, double height, DrawingCanvas canvas)
public FramedOval(double x, double y, double width, double height, DrawingCanvas canvas)
public FramedOval(Location topLeft, double width, double height, DrawingCanvas canvas)

There are also versions of these constructors that take a Color parameter as well, just before the canvas. The filled versions of these shapes have the same constructors as well. The Arc and RoundedRect classes have slightly different constructors, as discussed in another section below.

Your browser doesn't do Java.
DrawOval.java
If is also possible to define a rectangle not by a point with a width and height, but merely by two points that will be opposite corners of the rectangle:

public FramedRect(Location corner1, Location corner2, DrawingCanvas canvas)

The corner1 and corner2 locations can be any two points at all; they do not need to be the top left and bottom right. You can try clicking and dragging in the applet to the right to see a demonstration of this.

2. Getting information about a rectangular object

To show that these shapes all have this in common, they all implement the Drawable2DInterface, which lists methods that they all have for getting the position of the top left corner and the width and height of the rectangle:

public int getX();
public int getY();
public Location getLocation();
public int getWidth();
public int getHeight();

If you ever want to get the exact value of the x, y, width and height, there are methods getDoubleX(), getDoubleWidth(), and so on that will return them as decimal numbers. However, it is very rare that you will ever need that.

The other method available for working with rectangular objects asks if one overlaps another:

public boolean overlaps(Drawable2DInterface other);

By "overlaps", we just mean that some portion of the rectangle bounding one shape intersects with the rectangle bounding the other. It is possible for ovals or arcs to "overlap" in this sense without actually visibly touching on the screen. Also, note that this doesn't mean anything about the front-to-back drawing order.

3. Moving and resizing rectangular objects

Your browser doesn't do Java.
ResizeImage.java
These rectangular shapes also all implement the Resizable2DInterface, which says that they have methods for changing their width and height:

public void setSize(double width, double height);
public void setWidth(double w);
public void setHeight(double h);

When you resize an object, its top left corner stays at the same place, and the bottom right corner moves as the shape gets larger or smaller. Since you often want the shape to, say, stay centered around the same point, resizing is often combined with moving:

int widthIncrease = newWidth - rect.getWidth();
rect.setWidth(newWidth);
rect.move(rect.getX() - widthIncrease / 2, rect.getY());

4. Special features of the Arc classes

You can think of an Arc as being just a slice of an Oval. You control what particular slice it is by passing two additional parameters to the constructor: one saying what angle the slice starts at, and one saying what angle it stops at:

public FramedArc(double x, double y, double width, double height, double startAngle, double arcAngle, DrawingCanvas canvas)

This is just one of the possible constructors; you can also use the Location, width, height constructor, or the two-Location constructor, and you can always put a Color in just before the canvas.

Angles are measured in degrees, with 0° at the right side, 90° at the top, and so on, as is usual in math. The arcAngle can be positive or negative; you can think of it as what is added to the startAngle to get the ending angle. So, these two lines make arcs that both go from 135° to 180° and align exactly:

new FilledArc(10, 10, 100, 100, 135, 45, Color.RED, canvas);
new FramedArc(new Location(10, 10), new Location(110, 110), 180, 45, canvas);

The Arc classes also have methods to get and set the starting angle and arc angle:

public double getArcAngle()
public double getStartAngle()
public void setStartAngle(double a)
public void setArcAngle(double a)

Your browser doesn't do Java.
PieChart.java
Because the FilledArc makes a shape that looks like a slice of pie, one common use of them is to make pie charts. If I wanted a pie chart of the numbers one, two, and three, I could make it like this:

double total = one + two + three;
double angle = 0;

FilledArc slice1 = new FilledArc(0, 0, canvas.getWidth(), canvas.getHeight(),
        angle, 360 * (one / total), Color.RED, canvas);
angle += 360 * (one / total);
FilledArc slice2 = new FilledArc(0, 0, canvas.getWidth(), canvas.getHeight(),
        angle, 360 * (two / total), Color.GREEN, canvas);
angle += 360 * (two / total);
FilledArc slice2 = new FilledArc(0, 0, canvas.getWidth(), canvas.getHeight(),
        angle, 360 * (three / total), Color.BLUE, canvas);

5. Special features of the RoundedRect classes

You can think of RoundedRect as a hybrid of an oval and a rectangle - it has straight sides, but the corners are rounded off. The degree of this rounding is given by an extra parameter describing the width and height of the rounding. The rounded part at each corner is a quarter of an ellipse; the whole ellipse that they form would have the width and height that you specified.

Another way to think about it is this: if you were to pass along 0 for the width and height of the corners, a RoundedRect would end up looking just like a Rect; if you were to pass along the same width as the whole RoundedRect for its corners, the corners would take up the whole thing, making it an Oval.

public FramedRoundedRect(double x, double y, double width, double height, double arcWidth, double arcHeight, DrawingCanvas canvas)

As with arcs, there are all the other constructors you would expect, with different combinations of Locations and with and without a Color just before the canvas. All that is different about the RoundedRect constructors is the insertion of the two corner dimensions.

As you would expect, there are also method to get and set the corner size:

public int getArcHeight()
public int getArcWidth()
public double getDoubleArcHeight()
public double getDoubleArcWidth()
public void setArcHeight(double a)
public void setArcWidth(double a)

RoundedRects are often used to display text in, because with a small corner size they look a bit classier than a Rect while still having a roughly rectangular shape.

6. Complete specification of rectangular shapes

Here is a complete list of all the possible constructors for the various rectangular shapes:

// The same sets of parameters also work for FilledRect, FramedOval, and FilledOval
public FramedRect(double x, double y, double width, double height, Color c, DrawingCanvas canvas)
public FramedRect(double x, double y, double width, double height, DrawingCanvas canvas)
public FramedRect(Location point, double width, double height, Color c, DrawingCanvas canvas)
public FramedRect(Location point, double width, double height, DrawingCanvas canvas)
public FramedRect(Location corner1, Location corner2, Color c, DrawingCanvas canvas)
public FramedRect(Location corner1, Location corner2, DrawingCanvas canvas)

// The same sets of parameters also work for FilledArc
public FramedArc(double x, double y, double width, double height, double startAngle, double arcAngle, Color c, DrawingCanvas canvas)
public FramedArc(double x, double y, double width, double height, double startAngle, double arcAngle, DrawingCanvas canvas)
public FramedArc(Location point, double width, double height, double startAngle, double arcAngle, Color c, DrawingCanvas canvas)
public FramedArc(Location point, double width, double height, double startAngle, double arcAngle, DrawingCanvas canvas)
public FramedArc(Location corner1, Location corner2, double startAngle, double arcAngle, Color c, DrawingCanvas canvas)
public FramedArc(Location corner1, Location corner2, double startAngle, double arcAngle, DrawingCanvas canvas)

// The same sets of parameters also work for FilledRoundedRect
public FramedRoundedRect(double x, double y, double width, double height, double arcWidth, double arcHeight, Color c, DrawingCanvas canvas)
public FramedRoundedRect(double x, double y, double width, double height, double arcWidth, double arcHeight, DrawingCanvas canvas)
public FramedRoundedRect(Location point, double width, double height, double arcWidth, double arcHeight, Color c, DrawingCanvas canvas)
public FramedRoundedRect(Location point, double width, double height, double arcWidth, double arcHeight, DrawingCanvas canvas)
public FramedRoundedRect(Location corner1, Location corner2, double arcWidth, double arcHeight, Color c, DrawingCanvas canvas)
public FramedRoundedRect(Location corner1, Location corner2, double arcWidth, double arcHeight, DrawingCanvas canvas)

public VisibleImage(Image image, double x, double y, double width, double height, DrawingCanvas canvas)
public VisibleImage(Image image, double x, double y, DrawingCanvas canvas)
public VisibleImage(Image image, Location point, double width, double height, DrawingCanvas canvas)
public VisibleImage(Image image, Location point, DrawingCanvas canvas)

All of these shapes implement the Drawable2DInterface and the Resizable2DInterface, which means that they all have these methods:

public int getX();
public int getY();
public double getDoubleX();
public double getDoubleY();
public Location getLocation();

public int getWidth();
public int getHeight();
public double getDoubleWidth();
public double getDoubleHeight();
public boolean overlaps(Drawable2DInterface other);
public Rectangle2D getBounds();

public void setSize(double width, double height);
public void setWidth(double w);
public void setHeight(double h);

The framed classes implement the DrawableStrokeInterface, which means that they all have these methods:

public double getLineWidth();
public void setLineWidth(double width);
public BasicStroke getStroke();
public void setStroke(BasicStroke stroke);

These methods are specific to the Arc classes:

public double getArcAngle()
public double getStartAngle()
public void setStartAngle(double a)
public void setArcAngle(double a)

These methods are specific to the RoundedRect classes:

public int getArcHeight()
public int getArcWidth()
public double getDoubleArcHeight()
public double getDoubleArcWidth()
public void setArcHeight(double a)
public void setArcWidth(double a)

These methods are specific to the VisibleImage class:

public Image getImage()
public void setImage(Image image)
public int getImageWidth()
public int getImageHeight()