/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.gef.draw2d.geometry; import org.eclipse.draw2d.geometry.Rectangle; /** * @author Frank Shaka */ public class PrecisionRectangle { /** Double value for height */ public double height; /** Double value for width */ public double width; /** Double value for X */ public double x; /** Double value for Y */ public double y; /** * */ public PrecisionRectangle() { this(0, 0, 0, 0); } public PrecisionRectangle(double x, double y, double width, double height) { this.x = x; this.y = y; this.width = width; this.height = height; } public PrecisionRectangle(PrecisionRectangle rect) { this(rect.x, rect.y, rect.width, rect.height); } /** * Constructs a new PrecisionRectangle from the given integer Rectangle. * * @param rect * the base rectangle */ public PrecisionRectangle(Rectangle rect) { this(rect.x, rect.y, rect.width, rect.height); } public PrecisionRectangle(PrecisionPoint loc, PrecisionDimension size) { this(loc.x, loc.y, size.width, size.height); } public PrecisionRectangle(PrecisionPoint p1, PrecisionPoint p2) { x = Math.min(p1.x, p2.x); y = Math.min(p1.y, p2.y); width = Math.abs(p1.x - p2.x); height = Math.abs(p1.y - p2.y); } public boolean contains(PrecisionPoint p) { return contains(p.x, p.y); } public boolean contains(PrecisionRectangle r) { return this.x <= r.x && this.y <= r.y && right() >= r.right() && bottom() >= r.bottom(); } public boolean contains(double x, double y) { return y >= this.y && y < this.y + this.height && x >= this.x && x < this.x + this.width; } public PrecisionRectangle intersect(PrecisionRectangle rect) { double x1 = Math.max(x, rect.x); double x2 = Math.min(x + width, rect.x + rect.width); double y1 = Math.max(y, rect.y); double y2 = Math.min(y + height, rect.y + rect.height); if (((x2 - x1) < 0) || ((y2 - y1) < 0)) return setBounds(0, 0, 0, 0); // no intersection else { return setBounds(x1, y1, x2 - x1, y2 - y1); } } public boolean intersects(Rectangle rect) { return intersects(rect.x, rect.y, rect.width, rect.height); } public boolean intersects(PrecisionRectangle rect) { return intersects(rect.x, rect.y, rect.width, rect.height); } public boolean intersects(double x, double y, double width, double height) { return x < this.x + this.width && y < this.y + this.height && x + width > this.x && y + height > this.y; } public PrecisionRectangle crop(PrecisionInsets insets) { x += insets.left; y += insets.top; width -= insets.getWidth(); height -= insets.getHeight(); return this; } public PrecisionRectangle expand(double h, double v) { return shrink(-h, -v); } public PrecisionRectangle expand(PrecisionInsets insets) { x -= insets.left; y -= insets.top; height += insets.getHeight(); width += insets.getWidth(); return this; } public PrecisionRectangle getExpanded(double h, double v) { return new PrecisionRectangle(this).expand(h, v); } public PrecisionRectangle getExpanded(PrecisionInsets insets) { return new PrecisionRectangle(this).expand(insets); } public PrecisionRectangle shrink(double h, double v) { x += h; width -= (h + h); y += v; height -= (v + v); return this; } /** * @see Rectangle#equals(Object) */ public boolean equals(Object o) { if (o instanceof PrecisionRectangle) { PrecisionRectangle pr = (PrecisionRectangle) o; return super.equals(o) && Math.abs(pr.x - x) < 0.000000001 && Math.abs(pr.y - y) < 0.000000001 && Math.abs(pr.width - width) < 0.000000001 && Math.abs(pr.height - height) < 0.00000001; } return super.equals(o); } public PrecisionRectangle scale(double factor) { x *= factor; y *= factor; width *= factor; height *= factor; return this; } /** * @see org.eclipse.draw2d.geometry.Rectangle#performTranslate(int, int) */ public PrecisionRectangle translate(double dx, double dy) { x += dx; y += dy; return this; } public PrecisionRectangle translate(PrecisionDimension d) { return translate(d.width, d.height); } public PrecisionRectangle translate(PrecisionPoint p) { return translate(p.x, p.y); } public double right() { return x + width; } public double bottom() { return y + height; } public PrecisionPoint getLocation() { return new PrecisionPoint(x, y); } public PrecisionPoint getTopLeft() { return new PrecisionPoint(x, y); } public PrecisionPoint getTopRight() { return new PrecisionPoint(x + width, y); } public PrecisionPoint getBottomLeft() { return new PrecisionPoint(x, y + height); } public PrecisionPoint getBottomRight() { return new PrecisionPoint(x + width, y + height); } public PrecisionDimension getSize() { return new PrecisionDimension(width, height); } public PrecisionPoint getCenter() { return new PrecisionPoint(x + width / 2, y + height / 2); } public Rectangle toDraw2DRectangle() { return toDraw2DRectangle(x, y, width, height); } public static Rectangle toDraw2DRectangle(double x, double y, double width, double height) { int intX = (int) Math.floor(x + 0.000000001); int intY = (int) Math.floor(y + 0.000000001); int intWidth = (int) Math.floor(width + x + 0.000000001) - intX; int intHeight = (int) Math.floor(height + y + 0.000000001) - intY; return new Rectangle(intX, intY, intWidth, intHeight); } public Rectangle getInnerBounds() { return getInnerBounds(x, y, width, height); } public Rectangle getOuterBounds() { return getOuterBounds(x, y, width, height); } public static Rectangle getInnerBounds(double x, double y, double width, double height) { int intX = (int) Math.ceil(x); int intY = (int) Math.ceil(y); int intWidth = (int) Math.floor(width + x) - intX; int intHeight = (int) Math.floor(height + y) - intY; return new Rectangle(intX, intY, intWidth, intHeight); } public static Rectangle getOuterBounds(double x, double y, double width, double height) { int intX = (int) Math.floor(x); int intY = (int) Math.floor(y); int intWidth = (int) Math.ceil(width + x) - intX; int intHeight = (int) Math.ceil(height + y) - intY; return new Rectangle(intX, intY, intWidth, intHeight); } public PrecisionRectangle setSize(PrecisionDimension d) { return setSize(d.width, d.height); } public PrecisionRectangle setSize(double w, double h) { this.width = w; this.height = h; return this; } public PrecisionRectangle setLocation(PrecisionPoint p) { return setLocation(p.x, p.y); } public PrecisionRectangle setLocation(double x, double y) { this.x = x; this.y = y; return this; } public PrecisionRectangle setBounds(PrecisionRectangle r) { return setBounds(r.x, r.y, r.width, r.height); } public PrecisionRectangle setBounds(Rectangle r) { return setBounds(r.x, r.y, r.width, r.height); } public PrecisionRectangle setBounds(double x, double y, double w, double h) { this.x = x; this.y = y; this.width = w; this.height = h; return this; } public PrecisionInsets getInsets(double x, double y) { return new PrecisionInsets(y - this.y, x - this.x, bottom() - y, right() - x); } public PrecisionInsets getInsets(PrecisionPoint p) { return getInsets(p.x, p.y); } public PrecisionRectangle union(PrecisionPoint p) { if (p == null) return this; return union(p.x, p.y); } public PrecisionRectangle union(double x1, double y1) { if (x1 < x) { width += (x - x1); x = x1; } else { double right = x + width; if (x1 >= right) { right = x1; width = right - x; } } if (y1 < y) { height += (y - y1); y = y1; } else { double bottom = y + height; if (y1 >= bottom) { bottom = y1; height = bottom - y; } } return this; } public PrecisionRectangle union(PrecisionRectangle r) { if (r == null) return this; return union(r.x, r.y, r.width, r.height); } public PrecisionRectangle union(double x, double y, double w, double h) { double right = Math.max(this.x + this.width, x + w); double bottom = Math.max(this.y + this.height, y + h); this.x = Math.min(this.x, x); this.y = Math.min(this.y, y); this.width = right - this.x; this.height = bottom - this.y; return this; } public PrecisionRectangle resize(double w, double h) { this.width += w; this.height += h; return this; } public PrecisionRectangle getCopy() { return new PrecisionRectangle(this.x, this.y, this.width, this.height); } public PrecisionRectangle getResize(double w, double h) { return getCopy().resize(w, h); } public String toString() { return "PrecisionRectangle(" + x + "," + y + "," + width + "," + height + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ } }