home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 11.6 KB | 472 lines |
- /*
- * @(#)RoundRectangle2D.java 1.6 98/03/18
- *
- * Copyright 1997, 1998 by Sun Microsystems, Inc.,
- * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
- * All rights reserved.
- *
- * This software is the confidential and proprietary information
- * of Sun Microsystems, Inc. ("Confidential Information"). You
- * shall not disclose such Confidential Information and shall use
- * it only in accordance with the terms of the license agreement
- * you entered into with Sun.
- */
-
- package java.awt.geom;
-
- /**
- * A rectangle with rounded corners defined by a location (x, y), a
- * dimension (w x h), and the width and height of an arc to round the
- * corners with.
- * <p>
- * This class is only the abstract superclass for all objects which
- * store a 2D rounded rectangle.
- * The actual storage representation of the coordinates is left to
- * the subclass.
- *
- * @version 10 Feb 1997
- * @author Jim Graham
- */
- public abstract class RoundRectangle2D extends RectangularShape {
- /**
- * A rectangle with rounded corners all specified in float coordinates.
- */
- public static class Float extends RoundRectangle2D {
- /**
- * The x coordinate of the rectangle.
- */
- public float x;
-
- /**
- * The y coordinate of the rectangle.
- */
- public float y;
-
- /**
- * The width of the rectangle.
- */
- public float width;
-
- /**
- * The height of the rectangle.
- */
- public float height;
-
- /**
- * The width of the arc that rounds off the corners.
- */
- public float arcwidth;
-
- /**
- * The height of the arc that rounds off the corners.
- */
- public float archeight;
-
- /**
- * Constructs a new rounded rectangle, initialized to location (0.0, 0.0),
- * size (0.0, 0.0), and corner arcs of radius 0.0.
- */
- public Float() {
- }
-
- /**
- * Constructs and initializes a rectangle from the specified coordinates.
- * @param x the x coordinate
- * @param y the y coordinate
- * @param width the width of the rectangle
- * @param height the height of the rectangle
- */
- public Float(float x, float y, float w, float h,
- float arcw, float arch) {
- setRoundRect(x, y, w, h, arcw, arch);
- }
-
- /**
- * Returns the X coordinate of the rounded rectangle in double precision.
- */
- public double getX() {
- return (double) x;
- }
-
- /**
- * Returns the Y coordinate of the rounded rectangle in double precision.
- */
- public double getY() {
- return (double) y;
- }
-
- /**
- * Returns the width of the rounded rectangle in double precision.
- */
- public double getWidth() {
- return (double) width;
- }
-
- /**
- * Returns the height of the rounded rectangle in double precision.
- */
- public double getHeight() {
- return (double) height;
- }
-
- /**
- * Gets the width of the arc that rounds off the corners.
- */
- public double getArcWidth() {
- return (double) arcwidth;
- }
-
- /**
- * Gets the height of the arc that rounds off the corners.
- */
- public double getArcHeight() {
- return (double) archeight;
- }
-
- /**
- * Determines whether the rounded rectangle is empty.
- */
- public boolean isEmpty() {
- return (width <= 0.0f) || (height <= 0.0f);
- }
-
- /**
- * Sets the location, size, and arc radii of this rectangle to the
- * specified float values.
- */
- public void setRoundRect(float x, float y, float w, float h,
- float arcw, float arch) {
- this.x = x;
- this.y = y;
- this.width = w;
- this.height = h;
- this.arcwidth = arcw;
- this.archeight = arch;
- }
-
- /**
- * Sets the location, size, and arc radii of this rectangle to the
- * specified double values.
- */
- public void setRoundRect(double x, double y, double w, double h,
- double arcw, double arch) {
- this.x = (float) x;
- this.y = (float) y;
- this.width = (float) w;
- this.height = (float) h;
- this.arcwidth = (float) arcw;
- this.archeight = (float) arch;
- }
-
- /**
- * Sets this rounded rectangle to be the same as the specified
- * RoundRectangle.
- */
- public void setRoundRect(RoundRectangle2D rr) {
- this.x = (float) rr.getX();
- this.y = (float) rr.getY();
- this.width = (float) rr.getWidth();
- this.height = (float) rr.getHeight();
- this.arcwidth = (float) rr.getArcWidth();
- this.archeight = (float) rr.getArcHeight();
- }
-
- /**
- * Return the high precision bounding box of the shape.
- */
- public Rectangle2D getBounds2D() {
- return new Rectangle2D.Float(x, y, width, height);
- }
- }
-
- /**
- * A rectangle with rounded corners all specified in double coordinates.
- */
- public static class Double extends RoundRectangle2D {
- /**
- * The x coordinate of the rectangle.
- */
- public double x;
-
- /**
- * The y coordinate of the rectangle.
- */
- public double y;
-
- /**
- * The width of the rectangle.
- */
- public double width;
-
- /**
- * The height of the rectangle.
- */
- public double height;
-
- /**
- * The width of the arc that rounds off the corners.
- */
- public double arcwidth;
-
- /**
- * The height of the arc that rounds off the corners.
- */
- public double archeight;
-
- /**
- * Constructs a new rounded rectangle,
- * initialized to location (0.0, 0.0),
- * size (0.0, 0.0),
- * and corner arcs of radius 0.0.
- */
- public Double() {
- }
-
- /**
- * Constructs and initializes a rectangle from the
- * specified coordinates.
- * @param x the x coordinate
- * @param y the y coordinate
- * @param width the width of the rectangle
- * @param height the height of the rectangle
- */
- public Double(double x, double y, double w, double h,
- double arcw, double arch) {
- setRoundRect(x, y, w, h, arcw, arch);
- }
-
- /**
- * Returns the X coordinate of the rounded rectangle in
- * double precision.
- */
- public double getX() {
- return x;
- }
-
- /**
- * Returns the Y coordinate of the rounded rectangle in
- * double precision.
- */
- public double getY() {
- return y;
- }
-
- /**
- * Returns the width of the rounded rectangle in
- * double precision.
- */
- public double getWidth() {
- return width;
- }
-
- /**
- * Returns the height of the rounded rectangle in double precision.
- */
- public double getHeight() {
- return height;
- }
-
- /**
- * Gets the width of the arc that rounds off the corners.
- */
- public double getArcWidth() {
- return arcwidth;
- }
-
- /**
- * Gets the height of the arc that rounds off the corners.
- */
- public double getArcHeight() {
- return archeight;
- }
-
- /**
- * Determines whether the rounded rectangle is empty.
- */
- public boolean isEmpty() {
- return (width <= 0.0f) || (height <= 0.0f);
- }
-
- /**
- * Sets the location, size, and arc radii of this rectangle to the
- * specified double values.
- */
- public void setRoundRect(double x, double y, double w, double h,
- double arcw, double arch) {
- this.x = x;
- this.y = y;
- this.width = w;
- this.height = h;
- this.arcwidth = arcw;
- this.archeight = arch;
- }
-
- /**
- * Sets this rounded rectangle to be the same as the specified
- * RoundRectangle.
- */
- public void setRoundRect(RoundRectangle2D rr) {
- this.x = rr.getX();
- this.y = rr.getY();
- this.width = rr.getWidth();
- this.height = rr.getHeight();
- this.arcwidth = rr.getArcWidth();
- this.archeight = rr.getArcHeight();
- }
-
- /**
- * Return the high precision bounding box of the shape.
- */
- public Rectangle2D getBounds2D() {
- return new Rectangle2D.Double(x, y, width, height);
- }
- }
-
- protected RoundRectangle2D() {
- }
-
- /**
- * Gets the width of the arc that rounds off the corners.
- */
- public abstract double getArcWidth();
-
- /**
- * Gets the height of the arc that rounds off the corners.
- */
- public abstract double getArcHeight();
-
- /**
- * Sets the location, size, and corner radii of this rounded
- * rectangle to the specified double values.
- */
- public abstract void setRoundRect(double x, double y, double w, double h,
- double arcWidth, double arcHeight);
-
- /**
- * Sets this rounded rectangle to be the same as the specified
- * RoundRectangle.
- */
- public void setRoundRect(RoundRectangle2D rr) {
- setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
- rr.getArcWidth(), rr.getArcHeight());
- }
-
- /**
- * Sets the location and size of the outer bounds of this shape
- * to the specified rectangular values.
- */
- public void setBounds(double x, double y, double w, double h) {
- setRoundRect(x, y, w, h, getArcWidth(), getArcHeight());
- }
-
- /**
- * Test if a given coordinate is inside the boundary of the shape.
- */
- public boolean contains(double x, double y) {
- if (isEmpty()) {
- return false;
- }
- double rrx0 = getX();
- double rry0 = getY();
- double rrx1 = rrx0 + getWidth();
- double rry1 = rry0 + getHeight();
- // Check for trivial rejection - point is outside bounding rectangle
- if (x < rrx0 || y < rry0 || x >= rrx1 || y >= rry1) {
- return false;
- }
- double aw = Math.min(getWidth(), Math.abs(getArcWidth())) / 2.0;
- double ah = Math.min(getHeight(), Math.abs(getArcHeight())) / 2.0;
- // Check which corner point is in and do circular containment
- // test - otherwise simple acceptance
- if (x >= (rrx0 += aw) && x < (rrx0 = rrx1 - aw)) {
- return true;
- }
- if (y >= (rry0 += ah) && y < (rry0 = rry1 - ah)) {
- return true;
- }
- x = (x - rrx0) / aw;
- y = (y - rry0) / ah;
- return (x * x + y * y <= 1.0);
- }
-
- private int classify(double coord, double left, double right,
- double arcsize) {
- if (coord < left) {
- return 0;
- } else if (coord < left + arcsize) {
- return 1;
- } else if (coord < right - arcsize) {
- return 2;
- } else if (coord < right) {
- return 3;
- } else {
- return 4;
- }
- }
-
- /**
- * Test if the interior of the Shape intersects the interior of a given
- * set of rectangular coordinates.
- */
- public boolean intersects(double x, double y, double w, double h) {
- if (isEmpty() || w <= 0 || h <= 0) {
- return false;
- }
- double rrx0 = getX();
- double rry0 = getY();
- double rrx1 = rrx0 + getWidth();
- double rry1 = rry0 + getHeight();
- // Check for trivial rejection - bounding rectangles do not intersect
- if (x + w <= rrx0 || x >= rrx1 || y + h <= rry0 || y >= rry1) {
- return false;
- }
- double aw = Math.min(getWidth(), Math.abs(getArcWidth())) / 2.0;
- double ah = Math.min(getHeight(), Math.abs(getArcHeight())) / 2.0;
- int x0class = classify(x, rrx0, rrx1, aw);
- int x1class = classify(x + w, rrx0, rrx1, aw);
- int y0class = classify(y, rry0, rry1, ah);
- int y1class = classify(y + h, rry0, rry1, ah);
- // Trivially accept if any point is inside inner rectangle
- if (x0class == 2 || x1class == 2 || y0class == 2 || y1class == 2) {
- return true;
- }
- // Trivially accept if either edge spans inner rectangle
- if ((x0class < 2 && x1class > 2) || (y0class < 2 && y1class > 2)) {
- return true;
- }
- // Since neither edge spans the center, then one of the corners
- // must be in one of the rounded edges. We detect this case if
- // a [xy]0class is 3 or a [xy]1class is 1. One of those two cases
- // must be true for each direction.
- // We now find a "nearest point" to test for being inside a rounded
- // corner.
- x = (x1class == 1) ? (x = x + w - (rrx0 + aw)) : (x = x - (rrx1 - aw));
- y = (y1class == 1) ? (y = y + h - (rry0 + ah)) : (y = y - (rry1 - ah));
- x = x / aw;
- y = y / ah;
- return (x * x + y * y <= 1.0);
- }
-
- /**
- * Test if the interior of the Shape entirely contains the given
- * set of rectangular coordinates.
- */
- public boolean contains(double x, double y, double w, double h) {
- if (isEmpty() || w <= 0 || h <= 0) {
- return false;
- }
- return (contains(x, y) &&
- contains(x + w, y) &&
- contains(x, y + h) &&
- contains(x + w, y + h));
- }
-
- /**
- * Return an iteration object that defines the boundary of the
- * shape.
- */
- public PathIterator getPathIterator(AffineTransform at) {
- return new RoundRectIterator(this, at);
- }
- }
-