All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.lwjgl.util.Rectangle Maven / Gradle / Ivy

There is a newer version: 2.9.3
Show newest version
/* 
 * Copyright (c) 2002-2008 LWJGL Project
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are 
 * met:
 * 
 * * Redistributions of source code must retain the above copyright 
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'LWJGL' nor the names of 
 *   its contributors may be used to endorse or promote products derived 
 *   from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.lwjgl.util;

import java.io.Serializable;

/**
 * A 2D integer Rectangle class which looks remarkably like an AWT one.
 * @author $Author$
 * @version $Revision$
 * $Id$
 */
public final class Rectangle implements ReadableRectangle, WritableRectangle, Serializable {

	static final long serialVersionUID = 1L;

	/** Rectangle's bounds */
	private int x, y, width, height;

	/**
	 * Constructor for Rectangle.
	 */
	public Rectangle() {
		super();
	}
	/**
	 * Constructor for Rectangle.
	 */
	public Rectangle(int x, int y, int w, int h) {
		this.x = x;
		this.y = y;
		this.width = w;
		this.height = h;
	}
	/**
	 * Constructor for Rectangle.
	 */
	public Rectangle(ReadablePoint p, ReadableDimension d) {
		x = p.getX();
		y = p.getY();
		width = d.getWidth();
		height = d.getHeight();
	}
	/**
	 * Constructor for Rectangle.
	 */
	public Rectangle(ReadableRectangle r) {
		x = r.getX();
		y = r.getY();
		width = r.getWidth();
		height = r.getHeight();
	}

	public void setLocation(int x, int y) {
		this.x = x;
		this.y = y;
	}

	public void setLocation(ReadablePoint p) {
		this.x = p.getX();
		this.y = p.getY();
	}

	public void setSize(int w, int h) {
		this.width = w;
		this.height = h;
	}

	public void setSize(ReadableDimension d) {
		this.width = d.getWidth();
		this.height = d.getHeight();
	}

	public void setBounds(int x, int y, int w, int h) {
		this.x = x;
		this.y = y;
		this.width = w;
		this.height = h;
	}

	public void setBounds(ReadablePoint p, ReadableDimension d) {
		x = p.getX();
		y = p.getY();
		width = d.getWidth();
		height = d.getHeight();
	}

	public void setBounds(ReadableRectangle r) {
		x = r.getX();
		y = r.getY();
		width = r.getWidth();
		height = r.getHeight();
	}
	
	/* (Overrides)
	 * @see com.shavenpuppy.jglib.ReadableRectangle#getBounds(com.shavenpuppy.jglib.Rectangle)
	 */
	public void getBounds(WritableRectangle dest) {
		dest.setBounds(x, y, width, height);
	}
	
	/* (Overrides)
	 * @see com.shavenpuppy.jglib.ReadablePoint#getLocation(com.shavenpuppy.jglib.Point)
	 */
	public void getLocation(WritablePoint dest) {
		dest.setLocation(x, y);
	}
	
	/* (Overrides)
	 * @see com.shavenpuppy.jglib.ReadableDimension#getSize(com.shavenpuppy.jglib.Dimension)
	 */
	public void getSize(WritableDimension dest) {
		dest.setSize(width, height);
	}

	/**
	 * Translate the rectangle by an amount.
	 * @param x The translation amount on the x axis
   * @param y The translation amount on the y axis
	 */
	public void translate(int x, int y) {
		this.x += x;
		this.y += y;
	}

	/**
	 * Translate the rectangle by an amount.
	 * @param point The translation amount
	 */
	public void translate(ReadablePoint point) {
		this.x += point.getX();
		this.y += point.getY();
	}

	/**
	 * Un-translate the rectangle by an amount.
	 * @param point The translation amount
	 */
	public void untranslate(ReadablePoint point) {
		this.x -= point.getX();
		this.y -= point.getY();
	}

	/**
	 * Checks whether or not this Rectangle contains the 
	 * specified Point.
	 * @param p the Point to test
	 * @return    true if the Point 
	 *            (xy) is inside this 
	 * 		  Rectangle; 
	 *            false otherwise.
	 */
	public boolean contains(ReadablePoint p) {
		return contains(p.getX(), p.getY());
	}

	/**
	 * Checks whether or not this Rectangle contains the 
	 * point at the specified location
	 * (xy).
	 * @param X the specified x coordinate
   * @param Y the specified y coordinate
	 * @return    true if the point 
	 *            (xy) is inside this 
	 *		  Rectangle; 
	 *            false otherwise.
	 */
	public boolean contains(int X, int Y) {
		int w = this.width;
		int h = this.height;
		if ((w | h) < 0) {
			// At least one of the dimensions is negative...
			return false;
		}
		// Note: if either dimension is zero, tests below must return false...
		int x = this.x;
		int y = this.y;
		if (X < x || Y < y) {
			return false;
		}
		w += x;
		h += y;
		//    overflow || intersect
		return ((w < x || w > X) && (h < y || h > Y));
	}

	/**
	 * Checks whether or not this Rectangle entirely contains 
	 * the specified Rectangle.
	 * @param     r   the specified Rectangle
	 * @return    true if the Rectangle 
	 *            is contained entirely inside this Rectangle; 
	 *            false otherwise.
	 */
	public boolean contains(ReadableRectangle r) {
		return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
	}

	/**
	 * Checks whether this Rectangle entirely contains 
	 * the Rectangle
	 * at the specified location (XY) with the
	 * specified dimensions (WH).
   * @param X the specified x coordinate
   * @param Y the specified y coordinate
	 * @param     W   the width of the Rectangle
	 * @param     H   the height of the Rectangle
	 * @return    true if the Rectangle specified by
	 *            (XYWH)
	 *            is entirely enclosed inside this Rectangle; 
	 *            false otherwise.
	 */
	public boolean contains(int X, int Y, int W, int H) {
		int w = this.width;
		int h = this.height;
		if ((w | h | W | H) < 0) {
			// At least one of the dimensions is negative...
			return false;
		}
		// Note: if any dimension is zero, tests below must return false...
		int x = this.x;
		int y = this.y;
		if (X < x || Y < y) {
			return false;
		}
		w += x;
		W += X;
		if (W <= X) {
			// X+W overflowed or W was zero, return false if...
			// either original w or W was zero or
			// x+w did not overflow or
			// the overflowed x+w is smaller than the overflowed X+W
			if (w >= x || W > w)
				return false;
		} else {
			// X+W did not overflow and W was not zero, return false if...
			// original w was zero or
			// x+w did not overflow and x+w is smaller than X+W
			if (w >= x && W > w)
				return false;
		}
		h += y;
		H += Y;
		if (H <= Y) {
			if (h >= y || H > h)
				return false;
		} else {
			if (h >= y && H > h)
				return false;
		}
		return true;
	}

	/**
	 * Determines whether or not this Rectangle and the specified 
	 * Rectangle intersect. Two rectangles intersect if 
	 * their intersection is nonempty. 
	 *
	 * @param r the specified Rectangle
	 * @return    true if the specified Rectangle 
	 *            and this Rectangle intersect; 
	 *            false otherwise.
	 */
	public boolean intersects(ReadableRectangle r) {
		int tw = this.width;
		int th = this.height;
		int rw = r.getWidth();
		int rh = r.getHeight();
		if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
			return false;
		}
		int tx = this.x;
		int ty = this.y;
		int rx = r.getX();
		int ry = r.getY();
		rw += rx;
		rh += ry;
		tw += tx;
		th += ty;
		//      overflow || intersect
		return ((rw < rx || rw > tx) && (rh < ry || rh > ty) && (tw < tx || tw > rx) && (th < ty || th > ry));
	}

	/**
	 * Computes the intersection of this Rectangle with the 
	 * specified Rectangle. Returns a new Rectangle 
	 * that represents the intersection of the two rectangles.
	 * If the two rectangles do not intersect, the result will be
	 * an empty rectangle.
	 *
	 * @param     r   the specified Rectangle
	 * @return    the largest Rectangle contained in both the 
	 *            specified Rectangle and in 
	 *		  this Rectangle; or if the rectangles
	 *            do not intersect, an empty rectangle.
	 */
	public Rectangle intersection(ReadableRectangle r, Rectangle dest) {
		int tx1 = this.x;
		int ty1 = this.y;
		int rx1 = r.getX();
		int ry1 = r.getY();
		long tx2 = tx1;
		tx2 += this.width;
		long ty2 = ty1;
		ty2 += this.height;
		long rx2 = rx1;
		rx2 += r.getWidth();
		long ry2 = ry1;
		ry2 += r.getHeight();
		if (tx1 < rx1)
			tx1 = rx1;
		if (ty1 < ry1)
			ty1 = ry1;
		if (tx2 > rx2)
			tx2 = rx2;
		if (ty2 > ry2)
			ty2 = ry2;
		tx2 -= tx1;
		ty2 -= ty1;
		// tx2,ty2 will never overflow (they will never be
		// larger than the smallest of the two source w,h)
		// they might underflow, though...
		if (tx2 < Integer.MIN_VALUE)
			tx2 = Integer.MIN_VALUE;
		if (ty2 < Integer.MIN_VALUE)
			ty2 = Integer.MIN_VALUE;
		if (dest == null)
			dest = new Rectangle(tx1, ty1, (int) tx2, (int) ty2);
		else
			dest.setBounds(tx1, ty1, (int) tx2, (int) ty2);
		return dest;
		
	}

	/**
	 * Computes the union of this Rectangle with the 
	 * specified Rectangle. Returns a new 
	 * Rectangle that 
	 * represents the union of the two rectangles
	 * @param r the specified Rectangle
	 * @return    the smallest Rectangle containing both 
	 *		  the specified Rectangle and this 
	 *		  Rectangle.
	 */
	public WritableRectangle union(ReadableRectangle r, WritableRectangle dest) {
		int x1 = Math.min(x, r.getX());
		int x2 = Math.max(x + width, r.getX() + r.getWidth());
		int y1 = Math.min(y, r.getY());
		int y2 = Math.max(y + height, r.getY() + r.getHeight());
		dest.setBounds(x1, y1, x2 - x1, y2 - y1);
		return dest;
	}

	/**
	 * Adds a point, specified by the integer arguments newx
	 * and newy, to this Rectangle. The 
	 * resulting Rectangle is
	 * the smallest Rectangle that contains both the 
	 * original Rectangle and the specified point.
	 * 

* After adding a point, a call to contains with the * added point as an argument does not necessarily return * true. The contains method does not * return true for points on the right or bottom * edges of a Rectangle. Therefore, if the added point * falls on the right or bottom edge of the enlarged * Rectangle, contains returns * false for that point. * @param newx the x coordinates of the new point * @param newy the y coordinates of the new point */ public void add(int newx, int newy) { int x1 = Math.min(x, newx); int x2 = Math.max(x + width, newx); int y1 = Math.min(y, newy); int y2 = Math.max(y + height, newy); x = x1; y = y1; width = x2 - x1; height = y2 - y1; } /** * Adds the specified Point to this * Rectangle. The resulting Rectangle * is the smallest Rectangle that contains both the * original Rectangle and the specified * Point. *

* After adding a Point, a call to contains * with the added Point as an argument does not * necessarily return true. The contains * method does not return true for points on the right * or bottom edges of a Rectangle. Therefore if the added * Point falls on the right or bottom edge of the * enlarged Rectangle, contains returns * false for that Point. * @param pt the new Point to add to this * Rectangle */ public void add(ReadablePoint pt) { add(pt.getX(), pt.getY()); } /** * Adds a Rectangle to this Rectangle. * The resulting Rectangle is the union of the two * rectangles. * @param r the specified Rectangle */ public void add(ReadableRectangle r) { int x1 = Math.min(x, r.getX()); int x2 = Math.max(x + width, r.getX() + r.getWidth()); int y1 = Math.min(y, r.getY()); int y2 = Math.max(y + height, r.getY() + r.getHeight()); x = x1; y = y1; width = x2 - x1; height = y2 - y1; } /** * Resizes the Rectangle both horizontally and vertically. *

* This method modifies the Rectangle so that it is * h units larger on both the left and right side, * and v units larger at both the top and bottom. *

* The new Rectangle has (x - h, * y - v) as its top-left corner, a * width of * width + 2h, * and a height of * height + 2v. *

* If negative values are supplied for h and * v, the size of the Rectangle * decreases accordingly. * The grow method does not check whether the resulting * values of width and height are * non-negative. * @param h the horizontal expansion * @param v the vertical expansion */ public void grow(int h, int v) { x -= h; y -= v; width += h * 2; height += v * 2; } /** * Determines whether or not this Rectangle is empty. A * Rectangle is empty if its width or its height is less * than or equal to zero. * @return true if this Rectangle is empty; * false otherwise. */ public boolean isEmpty() { return (width <= 0) || (height <= 0); } /** * Checks whether two rectangles are equal. *

* The result is true if and only if the argument is not * null and is a Rectangle object that has the * same top-left corner, width, and height as this Rectangle. * @param obj the Object to compare with * this Rectangle * @return true if the objects are equal; * false otherwise. */ public boolean equals(Object obj) { if (obj instanceof Rectangle) { Rectangle r = (Rectangle) obj; return ((x == r.x) && (y == r.y) && (width == r.width) && (height == r.height)); } return super.equals(obj); } /** * Debugging * @return a String */ public String toString() { return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "]"; } /** * Gets the height. * @return Returns a int */ public int getHeight() { return height; } /** * Sets the height. * @param height The height to set */ public void setHeight(int height) { this.height = height; } /** * Gets the width. * @return Returns a int */ public int getWidth() { return width; } /** * Sets the width. * @param width The width to set */ public void setWidth(int width) { this.width = width; } /** * Gets the x. * @return Returns a int */ public int getX() { return x; } /** * Sets the x. * @param x The x to set */ public void setX(int x) { this.x = x; } /** * Gets the y. * @return Returns a int */ public int getY() { return y; } /** * Sets the y. * @param y The y to set */ public void setY(int y) { this.y = y; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy