/* 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 * @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"; } } }