/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @author Denis M. Kishenko * Dumbed-down for JavaME by CG 20121006 */ package java.awt.geom; import java.util.NoSuchElementException; 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; public static class Float extends Rectangle2D { public float x; public float y; public float width; public float height; public Float() { } public Float(float x, float y, float width, float height) { setRect(x, y, width, height); } 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.0f || height <= 0.0f; } public void setRect(float x, float y, float width, float height) { this.x = x; this.y = y; this.width = width; this.height = height; } public void setRect(double x, double y, double width, double height) { this.x = (float)x; this.y = (float)y; this.width = (float)width; this.height = (float)height; } 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 px, double py) { int code = 0; if (width <= 0.0f) { code |= OUT_LEFT | OUT_RIGHT; } else if (px < x) { code |= OUT_LEFT; } else if (px > x + width) { code |= OUT_RIGHT; } if (height <= 0.0f) { code |= OUT_TOP | OUT_BOTTOM; } else if (py < y) { code |= OUT_TOP; } else if (py > y + height) { code |= OUT_BOTTOM; } return code; } public Rectangle2D getBounds2D() { return new Float(x, y, width, height); } public Rectangle2D createIntersection(Rectangle2D r) { Rectangle2D dst; if (r instanceof Double) { dst = new Rectangle2D.Double(); } else { dst = new Rectangle2D.Float(); } Rectangle2D.intersect(this, r, dst); return dst; } public Rectangle2D createUnion(Rectangle2D r) { Rectangle2D dst; if (r instanceof Double) { dst = new Rectangle2D.Double(); } else { dst = new Rectangle2D.Float(); } Rectangle2D.union(this, r, dst); return dst; } public String toString() { // The output format based on 1.5 release behaviour. It could be obtained in the following way // System.out.println(new Rectangle2D.Float().toString()) return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ } } public static class Double extends Rectangle2D { public double x; public double y; public double width; public double height; public Double() { } public Double(double x, double y, double width, double height) { setRect(x, y, width, height); } 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.0 || height <= 0.0; } public void setRect(double x, double y, double width, double height) { this.x = x; this.y = y; this.width = width; this.height = height; } 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 px, double py) { int code = 0; if (width <= 0.0) { code |= OUT_LEFT | OUT_RIGHT; } else if (px < x) { code |= OUT_LEFT; } else if (px > x + width) { code |= OUT_RIGHT; } if (height <= 0.0) { code |= OUT_TOP | OUT_BOTTOM; } else if (py < y) { code |= OUT_TOP; } else if (py > y + height) { code |= OUT_BOTTOM; } return code; } public Rectangle2D getBounds2D() { return new Double(x, y, width, height); } public Rectangle2D createIntersection(Rectangle2D r) { Rectangle2D dst = new Rectangle2D.Double(); Rectangle2D.intersect(this, r, dst); return dst; } public Rectangle2D createUnion(Rectangle2D r) { Rectangle2D dest = new Rectangle2D.Double(); Rectangle2D.union(this, r, dest); return dest; } public String toString() { // The output format based on 1.5 release behaviour. It could be obtained in the following way // System.out.println(new Rectangle2D.Double().toString()) return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ } } /* * Rectangle2D path iterator */ class Iterator implements PathIterator { /** * The x coordinate of left-upper rectangle corner */ double x; /** * The y coordinate of left-upper rectangle corner */ double y; /** * The width of rectangle */ double width; /** * The height of rectangle */ double height; /** * The path iterator transformation */ AffineTransform t; /** * The current segmenet index */ int index; /** * Constructs a new Rectangle2D.Iterator for given rectangle and transformation * @param r - the source Rectangle2D object * @param at - the AffineTransform object to apply rectangle path */ Iterator(Rectangle2D r, AffineTransform at) { this.x = r.getX(); this.y = r.getY(); this.width = r.getWidth(); this.height = r.getHeight(); this.t = at; if (width < 0.0 || height < 0.0) { index = 6; } } public int getWindingRule() { return WIND_NON_ZERO; } public boolean isDone() { return index > 5; } public void next() { index++; } public int currentSegment(double[] coords) { if (isDone()) { throw new NoSuchElementException("Iterator out of bounds"); } if (index == 5) { return SEG_CLOSE; } int type; if (index == 0) { type = SEG_MOVETO; coords[0] = x; coords[1] = y; } else { type = SEG_LINETO; switch(index) { case 1: coords[0] = x + width; coords[1] = y; break; case 2: coords[0] = x + width; coords[1] = y + height; break; case 3: coords[0] = x; coords[1] = y + height; break; case 4: coords[0] = x; coords[1] = y; break; } } if (t != null) { t.transform(coords, 0, coords, 0, 1); } return type; } public int currentSegment(float[] coords) { if (isDone()) { throw new NoSuchElementException("Iterator out of bounds"); } if (index == 5) { return SEG_CLOSE; } int type; if (index == 0) { coords[0] = (float)x; coords[1] = (float)y; type = SEG_MOVETO; } else { type = SEG_LINETO; switch(index) { case 1: coords[0] = (float)(x + width); coords[1] = (float)y; break; case 2: coords[0] = (float)(x + width); coords[1] = (float)(y + height); break; case 3: coords[0] = (float)x; coords[1] = (float)(y + height); break; case 4: coords[0] = (float)x; coords[1] = (float)y; break; } } if (t != null) { t.transform(coords, 0, coords, 0, 1); } return type; } } protected Rectangle2D() { } public abstract void setRect(double x, double y, double width, double height); public abstract int outcode(double x, double y); public abstract Rectangle2D createIntersection(Rectangle2D r); public abstract Rectangle2D createUnion(Rectangle2D r); public void setRect(Rectangle2D r) { setRect(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } public void setFrame(double x, double y, double width, double height) { setRect(x, y, width, height); } public Rectangle2D getBounds2D() { return (Rectangle2D)clone(); } public boolean intersectsLine(double x1, double y1, double x2, double y2) { double rx1 = getX(); double ry1 = getY(); double rx2 = rx1 + getWidth(); double ry2 = ry1 + getHeight(); return (rx1 <= x1 && x1 <= rx2 && ry1 <= y1 && y1 <= ry2) || (rx1 <= x2 && x2 <= rx2 && ry1 <= y2 && y2 <= ry2) || Line2D.linesIntersect(rx1, ry1, rx2, ry2, x1, y1, x2, y2) || Line2D.linesIntersect(rx2, ry1, rx1, ry2, x1, y1, x2, y2); } public boolean intersectsLine(Line2D l) { return intersectsLine(l.getX1(), l.getY1(), l.getX2(), l.getY2()); } public int outcode(Point2D p) { return outcode(p.getX(), p.getY()); } public boolean contains(double x, double y) { if (isEmpty()) { return false; } double x1 = getX(); double y1 = getY(); double x2 = x1 + getWidth(); double y2 = y1 + getHeight(); return x1 <= x && x < x2 && y1 <= y && y < y2; } public boolean intersects(double x, double y, double width, double height) { if (isEmpty() || width <= 0.0 || height <= 0.0) { return false; } double x1 = getX(); double y1 = getY(); double x2 = x1 + getWidth(); double y2 = y1 + getHeight(); return x + width > x1 && x < x2 && y + height > y1 && y < y2; } public boolean contains(double x, double y, double width, double height) { if (isEmpty() || width <= 0.0 || height <= 0.0) { return false; } double x1 = getX(); double y1 = getY(); double x2 = x1 + getWidth(); double y2 = y1 + getHeight(); return x1 <= x && x + width <= x2 && y1 <= y && y + height <= y2; } public static void intersect(Rectangle2D src1, Rectangle2D src2, Rectangle2D dst) { double x1 = Math.max(src1.getMinX(), src2.getMinX()); double y1 = Math.max(src1.getMinY(), src2.getMinY()); double x2 = Math.min(src1.getMaxX(), src2.getMaxX()); double y2 = Math.min(src1.getMaxY(), src2.getMaxY()); dst.setFrame(x1, y1, x2 - x1, y2 - y1); } public static void union(Rectangle2D src1, Rectangle2D src2, Rectangle2D dst) { double x1 = Math.min(src1.getMinX(), src2.getMinX()); double y1 = Math.min(src1.getMinY(), src2.getMinY()); double x2 = Math.max(src1.getMaxX(), src2.getMaxX()); double y2 = Math.max(src1.getMaxY(), src2.getMaxY()); dst.setFrame(x1, y1, x2 - x1, y2 - y1); } public void add(double x, double y) { double x1 = Math.min(getMinX(), x); double y1 = Math.min(getMinY(), y); double x2 = Math.max(getMaxX(), x); double y2 = Math.max(getMaxY(), y); setRect(x1, y1, x2 - x1, y2 - y1); } public void add(Point2D p) { add(p.getX(), p.getY()); } public void add(Rectangle2D r) { union(this, r, this); } public PathIterator getPathIterator(AffineTransform t) { return new Iterator(this, t); } public PathIterator getPathIterator(AffineTransform t, double flatness) { return new Iterator(this, t); } public int hashCode() { /* Apache HashCode hash = new HashCode(); hash.append(getX()); hash.append(getY()); hash.append(getWidth()); hash.append(getHeight()); return hash.hashCode(); */ // Mika, for the time being long hash = java.lang.Double.doubleToLongBits(getX()); hash = hash * 32767 + java.lang.Double.doubleToLongBits(getY()); hash = hash * 32767 + java.lang.Double.doubleToLongBits(getWidth()); hash = hash * 32767 + java.lang.Double.doubleToLongBits(getHeight()); return (int) hash; } public boolean equals(Object obj) { if (obj == this) { return true; } if (obj instanceof Rectangle2D) { Rectangle2D r = (Rectangle2D)obj; return getX() == r.getX() && getY() == r.getY() && getWidth() == r.getWidth() && getHeight() == r.getHeight(); } return false; } }