| /* Copyright (C) 2000 Free Software Foundation |
| |
| This file is part of libjava. |
| |
| This software is copyrighted work licensed under the terms of the |
| Libjava License. Please consult the file "LIBJAVA_LICENSE" for |
| details. */ |
| |
| package java.awt.geom; |
| |
| /** |
| * @author Tom Tromey <tromey@cygnus.com> |
| * @date April 16, 2000 |
| */ |
| |
| public abstract class Rectangle2D extends RectangularShape |
| { |
| public static final int OUT_LEFT = 1; |
| public static final int OUT_TOP = 2; |
| public static final int OUT_RIGHT = 4; |
| public static final int OUT_BOTTOM = 8; |
| |
| protected Rectangle2D () |
| { |
| } |
| |
| /** Set the bounding box of this rectangle. |
| * @param x X coordinate |
| * @param y Y coordinate |
| * @param w Width |
| * @param h Height |
| */ |
| public abstract void setRect (double x, double y, double w, double h); |
| |
| /** Set the bounding box of this rectangle. |
| * @param r Bounding rectangle. |
| */ |
| public void setRect (Rectangle2D r) |
| { |
| setRect (r.getX (), r.getY (), r.getWidth (), r.getHeight ()); |
| } |
| |
| /** Returns true if line segment intersects interior of this |
| * rectangle. |
| * @param x1 X coordinate of first end of line segment |
| * @param y1 Y coordinate of first end of line segment |
| * @param x2 X coordinate of second end of line segment |
| * @param y1 Y coordinate of segment end of line segment |
| */ |
| public boolean intersectsLine (double x1, double y1, double x2, double y2) |
| { |
| int o1 = outcode (x1, y1); |
| int o2 = outcode (x2, y2); |
| |
| double mx = getX (); |
| double my = getY (); |
| double mx2 = getWidth (); |
| double my2 = getHeight (); |
| x1 -= mx; |
| x2 -= mx; |
| y1 -= my; |
| y2 -= my; |
| |
| // Here we handle all lines that stay entirely on one side of the |
| // rectangle. We also handle some lines that intersect the |
| // rectangle. All vertical and horizontal lines are handled here. |
| int xor = o1 ^ o2; |
| int or = o1 | o2; |
| if ((xor & (OUT_BOTTOM | OUT_TOP)) == 0) |
| { |
| if ((or & (OUT_BOTTOM | OUT_TOP)) != 0) |
| return false; |
| return ((o1 & (OUT_LEFT | OUT_RIGHT)) != 0 |
| || (o2 & (OUT_LEFT | OUT_RIGHT)) != 0); |
| } |
| else if ((xor & (OUT_LEFT | OUT_RIGHT)) == 0) |
| { |
| if ((or & (OUT_LEFT | OUT_RIGHT)) != 0) |
| return false; |
| return ((o1 & (OUT_BOTTOM | OUT_TOP)) != 0 |
| || (o2 & (OUT_BOTTOM | OUT_TOP)) != 0); |
| } |
| |
| double dx = x2 - x1; |
| double dy = y2 - y1; |
| |
| double t1l = - x1 / dx; |
| double t1h = (mx2 - x1) / dx; |
| |
| if (t1l >= t1h) |
| return false; |
| double t2l = - y1 / dy; |
| double t2h = (my2 - y1) / dy; |
| |
| if (t2l >= t2h || t2l >= t1h || t2h < t1l) |
| return false; |
| return true; |
| } |
| |
| /** Return true if line segment intersects interior of this |
| * rectangle. |
| * @param l The line segment |
| */ |
| // public boolean intersectsLine (Line2D l) |
| // { |
| // } |
| |
| public abstract int outcode (double x, double y); |
| |
| public int outcode (Point2D p) |
| { |
| return outcode (p.getX (), p.getY ()); |
| } |
| |
| /** Set bounding frame for this rectangle. |
| * @param x X coordinate |
| * @param y Y coordinate |
| * @param w Width |
| * @param h Height |
| */ |
| public void setFrame (double x, double y, double w, double h) |
| { |
| setRect (x, y, w, h); |
| } |
| |
| public Rectangle2D getBounds2D () |
| { |
| // FIXME. |
| return (Rectangle2D) clone (); |
| } |
| |
| public boolean contains (double x, double y) |
| { |
| double mx = getX (); |
| double mw = getWidth (); |
| if (x < mx || x >= mx + mw) |
| return false; |
| double my = getY (); |
| double mh = getHeight (); |
| return y >= my && y < my + mh; |
| } |
| |
| public boolean intersects (double x, double y, double w, double h) |
| { |
| double mx = getX (); |
| double mw = getWidth (); |
| if (x < mx || x >= mx + mw || x + w < mx || x + w >= mx + mw) |
| return false; |
| double my = getY (); |
| double mh = getHeight (); |
| return y >= my && y < my + mh && y + h >= my && y + h < my + mh; |
| } |
| |
| public boolean contains (double x, double y, double w, double h) |
| { |
| return contains (x, y) && contains (x + w, y + h); |
| } |
| |
| public abstract Rectangle2D createIntersection (Rectangle2D r); |
| |
| public static void intersect (Rectangle2D src1, Rectangle2D src2, |
| Rectangle2D dest) |
| { |
| double x1l = src1.getMinX (); |
| double x2l = src2.getMinX (); |
| double nxl = Math.max (x1l, x2l); |
| double x1h = src1.getMaxX (); |
| double x2h = src2.getMaxX (); |
| double nxh = Math.min (x1h, x2h); |
| if (nxh < nxl) |
| nxh = nxl; |
| double y1l = src1.getMinY (); |
| double y2l = src2.getMinY (); |
| double nyl = Math.max (y1l, y2l); |
| double y1h = src1.getMaxY (); |
| double y2h = src2.getMaxY (); |
| double nyh = Math.min (y1h, y2h); |
| if (nyh < nyl) |
| nyh = nyl; |
| dest.setFrameFromDiagonal (nxl, nyl, nxh, nyh); |
| } |
| |
| public abstract Rectangle2D createUnion (Rectangle2D r); |
| |
| public static void union (Rectangle2D src1, Rectangle2D src2, |
| Rectangle2D dest) |
| { |
| double x1l = src1.getMinX (); |
| double x2l = src2.getMinX (); |
| double nxl = Math.max (x1l, x2l); |
| double x1h = src1.getMaxX (); |
| double x2h = src2.getMaxX (); |
| double nxh = Math.min (x1h, x2h); |
| double y1l = src1.getMinY (); |
| double y2l = src2.getMinY (); |
| double nyl = Math.max (y1l, y2l); |
| double y1h = src1.getMaxY (); |
| double y2h = src2.getMaxY (); |
| double nyh = Math.min (y1h, y2h); |
| dest.setFrameFromDiagonal (nxl, nyl, nxh, nyh); |
| } |
| |
| public void add (double newx, double newy) |
| { |
| double minx = Math.min (getMinX (), newx); |
| double maxx = Math.max (getMaxX (), newx); |
| double miny = Math.min (getMinY (), newy); |
| double maxy = Math.max (getMaxY (), newy); |
| setFrameFromDiagonal (minx, miny, maxx, maxy); |
| } |
| |
| public void add (Point2D p) |
| { |
| add (p.getX (), p.getY ()); |
| } |
| |
| public void add (Rectangle2D r) |
| { |
| add (r.getMinX (), r.getMinY ()); |
| add (r.getMaxX (), r.getMaxY ()); |
| } |
| |
| public PathIterator getPathIterator (AffineTransform at) |
| { |
| // We know the superclass just ignores the flatness parameter. |
| return getPathIterator (at, 0); |
| } |
| |
| public static class Double extends Rectangle2D |
| { |
| public double height; |
| public double width; |
| public double x; |
| public double y; |
| |
| public Double () |
| { |
| height = width = x = y = 0; |
| } |
| |
| public Double (double x, double y, double w, double h) |
| { |
| this.x = x; |
| this.y = y; |
| this.width = w; |
| this.height = h; |
| } |
| |
| public double getX () |
| { |
| return x; |
| } |
| |
| public double getY () |
| { |
| return y; |
| } |
| |
| public double getWidth () |
| { |
| return width; |
| } |
| |
| public double getHeight () |
| { |
| return height; |
| } |
| |
| public boolean isEmpty () |
| { |
| return width <= 0 || height <= 0; |
| } |
| |
| public void setRect (double x, double y, double w, double h) |
| { |
| this.x = x; |
| this.y = y; |
| this.width = w; |
| this.height = h; |
| } |
| |
| public void setRect (Rectangle2D r) |
| { |
| this.x = r.getX (); |
| this.y = r.getY (); |
| this.width = r.getWidth (); |
| this.height = r.getHeight (); |
| } |
| |
| public int outcode (double x, double y) |
| { |
| int code = 0; |
| if (x < this.x) |
| code |= OUT_LEFT; |
| else if (x >= this.x + this.width) |
| code |= OUT_RIGHT; |
| if (y < this.y) |
| code |= OUT_TOP; |
| else if (y >= this.y + this.height) |
| code |= OUT_BOTTOM; |
| return code; |
| } |
| |
| public Rectangle2D getBounds2D () |
| { |
| return new Rectangle2D.Double (x, y, width, height); |
| } |
| |
| public Rectangle2D createIntersection (Rectangle2D r) |
| { |
| Double res = new Double (); |
| intersect (this, r, res); |
| return res; |
| } |
| |
| public Rectangle2D createUnion (Rectangle2D r) |
| { |
| Double res = new Double (); |
| union (this, r, res); |
| return res; |
| } |
| |
| public String toString () |
| { |
| return "fixme"; |
| } |
| } |
| |
| public static class Float extends Rectangle2D |
| { |
| public float height; |
| public float width; |
| public float x; |
| public float y; |
| |
| public Float () |
| { |
| height = width = x = y = 0; |
| } |
| |
| public Float (float x, float y, float w, float h) |
| { |
| this.x = x; |
| this.y = y; |
| this.width = w; |
| this.height = h; |
| } |
| |
| public double getX () |
| { |
| return x; |
| } |
| |
| public double getY () |
| { |
| return y; |
| } |
| |
| public double getWidth () |
| { |
| return width; |
| } |
| |
| public double getHeight () |
| { |
| return height; |
| } |
| |
| public boolean isEmpty () |
| { |
| return width <= 0 || height <= 0; |
| } |
| |
| public void setRect (double x, double y, double w, double h) |
| { |
| this.x = (float) x; |
| this.y = (float) y; |
| this.width = (float) w; |
| this.height = (float) h; |
| } |
| |
| public void setRect (Rectangle2D r) |
| { |
| this.x = (float) r.getX (); |
| this.y = (float) r.getY (); |
| this.width = (float) r.getWidth (); |
| this.height = (float) r.getHeight (); |
| } |
| |
| public int outcode (double x, double y) |
| { |
| int code = 0; |
| if (x < this.x) |
| code |= OUT_LEFT; |
| else if (x >= this.x + this.width) |
| code |= OUT_RIGHT; |
| if (y < this.y) |
| code |= OUT_TOP; |
| else if (y >= this.y + this.height) |
| code |= OUT_BOTTOM; |
| return code; |
| } |
| |
| public Rectangle2D getBounds2D () |
| { |
| return new Rectangle2D.Float (x, y, width, height); |
| } |
| |
| public Rectangle2D createIntersection (Rectangle2D r) |
| { |
| Float res = new Float (); |
| intersect (this, r, res); |
| return res; |
| } |
| |
| public Rectangle2D createUnion (Rectangle2D r) |
| { |
| Float res = new Float (); |
| union (this, r, res); |
| return res; |
| } |
| |
| public String toString () |
| { |
| return "fixme"; |
| } |
| } |
| } |