import java.awt.geom.GeneralPath; // combinations of lines and curves import java.awt.geom.AffineTransform; // translation, rotation, scale import java.awt.Shape; // general class for shapes // all imports below this line needed if you are implementing Shape import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.Rectangle; import java.awt.geom.PathIterator; import java.awt.geom.AffineTransform; /** A Coffee Cup (wrapper around a General Path, implements Shape) @author Phill Conrad @version for CS10, S09, UCSB, 05/06/2009 */ public class CoffeeCup implements Shape { private GeneralPath cup; /** * Constructor for objects of class CoffeeCup */ public CoffeeCup(double x, double y, double width, double height) { // Specify the upper left corner, and the // width and height of the original points used to p // plot the coffee cup final double ORIG_ULX = 100.0; final double ORIG_ULY = 100.0; final double ORIG_HEIGHT = 300.0; final double ORIG_WIDTH = 400.0; GeneralPath leftSide = new GeneralPath(); // left side of cup leftSide.moveTo(200,400); leftSide.lineTo(160,360); leftSide.lineTo(130,300); leftSide.lineTo(100,200); leftSide.lineTo(100,100); GeneralPath topAndBottom = new GeneralPath(); topAndBottom.moveTo(100,100); topAndBottom.lineTo(500,100); // top of cup topAndBottom.moveTo(200,400); topAndBottom.lineTo(400,400); // bottom of cup Shape rightSide = ShapeTransforms.horizontallyFlippedCopyOf(leftSide); // after flipping around the upper left hand corner of the // bounding box, we move this over to the right by 400 pixels rightSide = ShapeTransforms.translatedCopyOf(rightSide, 400.0, 0.0); // now we put the whole thing together ino a single path. GeneralPath wholeCup = new GeneralPath (); wholeCup.append(topAndBottom, false); wholeCup.append(leftSide, false); wholeCup.append(rightSide, false); // translate to the origin by subtracting the original upper left x and y // then translate to (x,y) by adding x and y Shape s = ShapeTransforms.translatedCopyOf(wholeCup, -ORIG_ULX + x, -ORIG_ULY + y); // scale to correct height and width s = ShapeTransforms.scaledCopyOf(s, width/ORIG_WIDTH, height/ORIG_HEIGHT) ; // Use the GeneralPath constructor that takes a shape and returns // it as a general path to set our instance variable cup this.cup = new GeneralPath(s); } // EVERYTHING BELOW THIS LINE IS JUST A WRAPPER AROUND // THE METHODS OF THE GENERAL PATH OBJECT. SINCE GENERAL PATH IS FINAL, // WE CAN'T INHERIT FROM IT. (OTHERWISE, THIS WOULDN'T BE NECESSARY) /** Tests if the specified coordinates are inside the boundary of the Shape. */ public boolean contains(double x, double y) { return cup.contains(x,y); } /** Tests if the interior of the Shape entirely contains the * specified rectangular area. */ public boolean contains(double x, double y, double w, double h) { return cup.contains(x,y,w,h); } /** Tests if a specified Point2D is inside the boundary of * the Shape. */ public boolean contains(Point2D p) { return cup.contains(p); } /** Tests if the interior of the Shape entirely contains the specified Rectangle2D. */ public boolean contains(Rectangle2D r) { return cup.contains(r); } /** Returns an integer Rectangle that completely encloses the * Shape. */ public Rectangle getBounds() { return cup.getBounds(); } /** Returns a high precision and more accurate bounding box * of the Shape than the getBounds method. */ public Rectangle2D getBounds2D() { return cup.getBounds2D(); } /** Returns an iterator object that iterates along the * Shape boundary and provides access to the geometry of * the Shape outline. */ public PathIterator getPathIterator(AffineTransform at) { return cup.getPathIterator( at); } /** Returns an iterator object that iterates along the * Shape boundary and provides access to a flattened view * of the Shape outline geometry. */ public PathIterator getPathIterator(AffineTransform at, double flatness) { return cup.getPathIterator( at, flatness); } /** Tests if the interior of the Shape intersects the * interior of a specified rectangular area. */ public boolean intersects(double x, double y, double w, double h) { return cup.intersects(x, y, w, h); } /** Tests if the interior of the Shape intersects the interior of * a specified Rectangle2D. */ public boolean intersects(Rectangle2D r) { return intersects(r); } }