1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17/**
18 * @author Denis M. Kishenko
19 * @version $Revision$
20 */
21
22package java.awt.geom;
23
24import java.awt.Rectangle;
25import java.awt.Shape;
26
27/**
28 * The Class RectangularShape represents a Shape whose data is (at least
29 * partially) described by a rectangular frame. This includes shapes which are
30 * obviously rectangular (such as Rectangle2D) as well as shapes like Arc2D
31 * which are largely determined by the rectangle they fit inside.
32 *
33 * @since Android 1.0
34 */
35public abstract class RectangularShape implements Shape, Cloneable {
36
37    /**
38     * Instantiates a new rectangular shape.
39     */
40    protected RectangularShape() {
41    }
42
43    /**
44     * Gets the x coordinate of the upper left corner of the rectangle.
45     *
46     * @return the x coordinate of the upper left corner of the rectangle.
47     */
48    public abstract double getX();
49
50    /**
51     * Gets the y coordinate of the upper left corner of the rectangle.
52     *
53     * @return the y coordinate of the upper left corner of the rectangle.
54     */
55    public abstract double getY();
56
57    /**
58     * Gets the width of the rectangle.
59     *
60     * @return the width of the rectangle.
61     */
62    public abstract double getWidth();
63
64    /**
65     * Gets the height of the rectangle.
66     *
67     * @return the height of the rectangle.
68     */
69    public abstract double getHeight();
70
71    /**
72     * Checks if this is an empty rectangle: one with zero as its width or
73     * height.
74     *
75     * @return true, if the width or height is empty.
76     */
77    public abstract boolean isEmpty();
78
79    /**
80     * Sets the data for the bounding rectangle in terms of double values.
81     *
82     * @param x
83     *            the x coordinate of the upper left corner of the rectangle.
84     * @param y
85     *            the y coordinate of the upper left corner of the rectangle.
86     * @param w
87     *            the width of the rectangle.
88     * @param h
89     *            the height of the rectangle.
90     */
91    public abstract void setFrame(double x, double y, double w, double h);
92
93    /**
94     * Gets the minimum x value of the bounding rectangle (the x coordinate of
95     * the upper left corner of the rectangle).
96     *
97     * @return the minimum x value of the bounding rectangle.
98     */
99    public double getMinX() {
100        return getX();
101    }
102
103    /**
104     * Gets the minimum y value of the bounding rectangle (the y coordinate of
105     * the upper left corner of the rectangle).
106     *
107     * @return the minimum y value of the bounding rectangle.
108     */
109    public double getMinY() {
110        return getY();
111    }
112
113    /**
114     * Gets the maximum x value of the bounding rectangle (the x coordinate of
115     * the upper left corner of the rectangle plus the rectangle's width).
116     *
117     * @return the maximum x value of the bounding rectangle.
118     */
119    public double getMaxX() {
120        return getX() + getWidth();
121    }
122
123    /**
124     * Gets the maximum y value of the bounding rectangle (the y coordinate of
125     * the upper left corner of the rectangle plus the rectangle's height).
126     *
127     * @return the maximum y value of the bounding rectangle.
128     */
129    public double getMaxY() {
130        return getY() + getHeight();
131    }
132
133    /**
134     * Gets the x coordinate of the center of the rectangle.
135     *
136     * @return the x coordinate of the center of the rectangle.
137     */
138    public double getCenterX() {
139        return getX() + getWidth() / 2.0;
140    }
141
142    /**
143     * Gets the y coordinate of the center of the rectangle.
144     *
145     * @return the y coordinate of the center of the rectangle.
146     */
147    public double getCenterY() {
148        return getY() + getHeight() / 2.0;
149    }
150
151    /**
152     * Places the rectangle's size and location data in a new Rectangle2D object
153     * and returns it.
154     *
155     * @return the bounding rectangle as a new Rectangle2D object.
156     */
157    public Rectangle2D getFrame() {
158        return new Rectangle2D.Double(getX(), getY(), getWidth(), getHeight());
159    }
160
161    /**
162     * Sets the bounding rectangle in terms of a Point2D which gives its upper
163     * left corner and a Dimension2D object giving its width and height.
164     *
165     * @param loc
166     *            the new upper left corner coordinate.
167     * @param size
168     *            the new size dimensions.
169     */
170    public void setFrame(Point2D loc, Dimension2D size) {
171        setFrame(loc.getX(), loc.getY(), size.getWidth(), size.getHeight());
172    }
173
174    /**
175     * Sets the bounding rectangle to match the data contained in the specified
176     * Rectangle2D.
177     *
178     * @param r
179     *            the rectangle that gives the new frame data.
180     */
181    public void setFrame(Rectangle2D r) {
182        setFrame(r.getX(), r.getY(), r.getWidth(), r.getHeight());
183    }
184
185    /**
186     * Sets the framing rectangle given two opposite corners. Any two corners
187     * may be used in any order as long as they are diagonally opposite one
188     * another.
189     *
190     * @param x1
191     *            the x coordinate of one of the corner points.
192     * @param y1
193     *            the y coordinate of one of the corner points.
194     * @param x2
195     *            the x coordinate of the other corner point.
196     * @param y2
197     *            the y coordinate of the other corner point.
198     */
199    public void setFrameFromDiagonal(double x1, double y1, double x2, double y2) {
200        double rx, ry, rw, rh;
201        if (x1 < x2) {
202            rx = x1;
203            rw = x2 - x1;
204        } else {
205            rx = x2;
206            rw = x1 - x2;
207        }
208        if (y1 < y2) {
209            ry = y1;
210            rh = y2 - y1;
211        } else {
212            ry = y2;
213            rh = y1 - y2;
214        }
215        setFrame(rx, ry, rw, rh);
216    }
217
218    /**
219     * Sets the framing rectangle given two opposite corners. Any two corners
220     * may be used in any order as long as they are diagonally opposite one
221     * another.
222     *
223     * @param p1
224     *            one of the corner points.
225     * @param p2
226     *            the other corner point.
227     */
228    public void setFrameFromDiagonal(Point2D p1, Point2D p2) {
229        setFrameFromDiagonal(p1.getX(), p1.getY(), p2.getX(), p2.getY());
230    }
231
232    /**
233     * Sets the framing rectangle given the center point and one corner. Any
234     * corner may be used.
235     *
236     * @param centerX
237     *            the x coordinate of the center point.
238     * @param centerY
239     *            the y coordinate of the center point.
240     * @param cornerX
241     *            the x coordinate of one of the corner points.
242     * @param cornerY
243     *            the y coordinate of one of the corner points.
244     */
245    public void setFrameFromCenter(double centerX, double centerY, double cornerX, double cornerY) {
246        double width = Math.abs(cornerX - centerX);
247        double height = Math.abs(cornerY - centerY);
248        setFrame(centerX - width, centerY - height, width * 2.0, height * 2.0);
249    }
250
251    /**
252     * Sets the framing rectangle given the center point and one corner. Any
253     * corner may be used.
254     *
255     * @param center
256     *            the center point.
257     * @param corner
258     *            a corner point.
259     */
260    public void setFrameFromCenter(Point2D center, Point2D corner) {
261        setFrameFromCenter(center.getX(), center.getY(), corner.getX(), corner.getY());
262    }
263
264    public boolean contains(Point2D point) {
265        return contains(point.getX(), point.getY());
266    }
267
268    public boolean intersects(Rectangle2D rect) {
269        return intersects(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
270    }
271
272    public boolean contains(Rectangle2D rect) {
273        return contains(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
274    }
275
276    public Rectangle getBounds() {
277        int x1 = (int)Math.floor(getMinX());
278        int y1 = (int)Math.floor(getMinY());
279        int x2 = (int)Math.ceil(getMaxX());
280        int y2 = (int)Math.ceil(getMaxY());
281        return new Rectangle(x1, y1, x2 - x1, y2 - y1);
282    }
283
284    public PathIterator getPathIterator(AffineTransform t, double flatness) {
285        return new FlatteningPathIterator(getPathIterator(t), flatness);
286    }
287
288    @Override
289    public Object clone() {
290        try {
291            return super.clone();
292        } catch (CloneNotSupportedException e) {
293            throw new InternalError();
294        }
295    }
296
297}
298