1 | /* Rectangle2D.java -- generic rectangles in 2-D space
|
---|
2 | Copyright (C) 2000, 2001, 2002 Free Software Foundation
|
---|
3 |
|
---|
4 | This file is part of GNU Classpath.
|
---|
5 |
|
---|
6 | GNU Classpath is free software; you can redistribute it and/or modify
|
---|
7 | it under the terms of the GNU General Public License as published by
|
---|
8 | the Free Software Foundation; either version 2, or (at your option)
|
---|
9 | any later version.
|
---|
10 |
|
---|
11 | GNU Classpath is distributed in the hope that it will be useful, but
|
---|
12 | WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
14 | General Public License for more details.
|
---|
15 |
|
---|
16 | You should have received a copy of the GNU General Public License
|
---|
17 | along with GNU Classpath; see the file COPYING. If not, write to the
|
---|
18 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
---|
19 | 02111-1307 USA.
|
---|
20 |
|
---|
21 | Linking this library statically or dynamically with other modules is
|
---|
22 | making a combined work based on this library. Thus, the terms and
|
---|
23 | conditions of the GNU General Public License cover the whole
|
---|
24 | combination.
|
---|
25 |
|
---|
26 | As a special exception, the copyright holders of this library give you
|
---|
27 | permission to link this library with independent modules to produce an
|
---|
28 | executable, regardless of the license terms of these independent
|
---|
29 | modules, and to copy and distribute the resulting executable under
|
---|
30 | terms of your choice, provided that you also meet, for each linked
|
---|
31 | independent module, the terms and conditions of the license of that
|
---|
32 | module. An independent module is a module which is not derived from
|
---|
33 | or based on this library. If you modify this library, you may extend
|
---|
34 | this exception to your version of the library, but you are not
|
---|
35 | obligated to do so. If you do not wish to do so, delete this
|
---|
36 | exception statement from your version. */
|
---|
37 |
|
---|
38 |
|
---|
39 | package java.awt.geom;
|
---|
40 |
|
---|
41 | import java.util.NoSuchElementException;
|
---|
42 |
|
---|
43 | /**
|
---|
44 | * This class describes a rectangle by a point (x,y) and dimension (w x h).
|
---|
45 | * The actual storage is left up to subclasses.
|
---|
46 | *
|
---|
47 | * <p>It is valid for a rectangle to have negative width or height; but it
|
---|
48 | * is considered to have no area or internal points. Therefore, the behavior
|
---|
49 | * in methods like <code>contains</code> or <code>intersects</code> is
|
---|
50 | * undefined unless the rectangle has positive width and height.
|
---|
51 | *
|
---|
52 | * @author Tom Tromey <tromey@cygnus.com>
|
---|
53 | * @author Eric Blake <ebb9@email.byu.edu>
|
---|
54 | * @since 1.2
|
---|
55 | * @status updated to 1.4
|
---|
56 | */
|
---|
57 | public abstract class Rectangle2D extends RectangularShape
|
---|
58 | {
|
---|
59 | /**
|
---|
60 | * The point lies left of the rectangle (p.x < r.x).
|
---|
61 | *
|
---|
62 | * @see #outcode()
|
---|
63 | */
|
---|
64 | public static final int OUT_LEFT = 1;
|
---|
65 |
|
---|
66 | /**
|
---|
67 | * The point lies above the rectangle (p.y < r.y).
|
---|
68 | *
|
---|
69 | * @see #outcode()
|
---|
70 | */
|
---|
71 | public static final int OUT_TOP = 2;
|
---|
72 |
|
---|
73 | /**
|
---|
74 | * The point lies right of the rectangle (p.x > r.maxX).
|
---|
75 | *
|
---|
76 | * @see #outcode()
|
---|
77 | */
|
---|
78 | public static final int OUT_RIGHT = 4;
|
---|
79 |
|
---|
80 | /**
|
---|
81 | * The point lies below of the rectangle (p.y > r.maxY).
|
---|
82 | *
|
---|
83 | * @see #outcode()
|
---|
84 | */
|
---|
85 | public static final int OUT_BOTTOM = 8;
|
---|
86 |
|
---|
87 | /**
|
---|
88 | * Default constructor.
|
---|
89 | */
|
---|
90 | protected Rectangle2D()
|
---|
91 | {
|
---|
92 | }
|
---|
93 |
|
---|
94 | /**
|
---|
95 | * Set the bounding box of this rectangle.
|
---|
96 | *
|
---|
97 | * @param x the new X coordinate
|
---|
98 | * @param y the new Y coordinate
|
---|
99 | * @param w the new width
|
---|
100 | * @param h the new height
|
---|
101 | */
|
---|
102 | public abstract void setRect(double x, double y, double w, double h);
|
---|
103 |
|
---|
104 | /**
|
---|
105 | * Set the bounding box of this rectangle from the given one.
|
---|
106 | *
|
---|
107 | * @param r rectangle to copy
|
---|
108 | * @throws NullPointerException if r is null
|
---|
109 | */
|
---|
110 | public void setRect(Rectangle2D r)
|
---|
111 | {
|
---|
112 | setRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
---|
113 | }
|
---|
114 |
|
---|
115 | /**
|
---|
116 | * Tests if the specified line intersects the interior of this rectangle.
|
---|
117 | *
|
---|
118 | * @param x1 the first x coordinate of line segment
|
---|
119 | * @param y1 the first y coordinate of line segment
|
---|
120 | * @param x2 the second x coordinate of line segment
|
---|
121 | * @param y2 the second y coordinate of line segment
|
---|
122 | * @return true if the line intersects the rectangle
|
---|
123 | */
|
---|
124 | public boolean intersectsLine(double x1, double y1, double x2, double y2)
|
---|
125 | {
|
---|
126 | double x = getX();
|
---|
127 | double y = getY();
|
---|
128 | double w = getWidth();
|
---|
129 | double h = getHeight();
|
---|
130 | if (w <= 0 || h <= 0)
|
---|
131 | return false;
|
---|
132 |
|
---|
133 | if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h)
|
---|
134 | return true;
|
---|
135 | if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h)
|
---|
136 | return true;
|
---|
137 |
|
---|
138 | double x3 = x + w;
|
---|
139 | double y3 = y + h;
|
---|
140 |
|
---|
141 | return (Line2D.linesIntersect(x1, y1, x2, y2, x, y, x, y3)
|
---|
142 | || Line2D.linesIntersect(x1, y1, x2, y2, x, y3, x3, y3)
|
---|
143 | || Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x3, y)
|
---|
144 | || Line2D.linesIntersect(x1, y1, x2, y2, x3, y, x, y));
|
---|
145 | }
|
---|
146 |
|
---|
147 | /**
|
---|
148 | * Tests if the specified line intersects the interior of this rectangle.
|
---|
149 | *
|
---|
150 | * @param l the line segment
|
---|
151 | * @return true if the line intersects the rectangle
|
---|
152 | * @throws NullPointerException if l is null
|
---|
153 | */
|
---|
154 | public boolean intersectsLine(Line2D l)
|
---|
155 | {
|
---|
156 | return intersectsLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
|
---|
157 | }
|
---|
158 |
|
---|
159 | /**
|
---|
160 | * Determine where the point lies with respect to this rectangle. The
|
---|
161 | * result will be the binary OR of the appropriate bit masks.
|
---|
162 | *
|
---|
163 | * @param x the x coordinate to check
|
---|
164 | * @param y the y coordinate to check
|
---|
165 | * @return the binary OR of the result
|
---|
166 | * @see #OUT_LEFT
|
---|
167 | * @see #OUT_TOP
|
---|
168 | * @see #OUT_RIGHT
|
---|
169 | * @see #OUT_BOTTOM
|
---|
170 | */
|
---|
171 | public abstract int outcode(double x, double y);
|
---|
172 |
|
---|
173 | /**
|
---|
174 | * Determine where the point lies with respect to this rectangle. The
|
---|
175 | * result will be the binary OR of the appropriate bit masks.
|
---|
176 | *
|
---|
177 | * @param p the point to check
|
---|
178 | * @return the binary OR of the result
|
---|
179 | * @throws NullPointerException if p is null
|
---|
180 | * @see #OUT_LEFT
|
---|
181 | * @see #OUT_TOP
|
---|
182 | * @see #OUT_RIGHT
|
---|
183 | * @see #OUT_BOTTOM
|
---|
184 | */
|
---|
185 | public int outcode(Point2D p)
|
---|
186 | {
|
---|
187 | return outcode(p.getX(), p.getY());
|
---|
188 | }
|
---|
189 |
|
---|
190 | /**
|
---|
191 | * Set the bounding box of this rectangle.
|
---|
192 | *
|
---|
193 | * @param x the new X coordinate
|
---|
194 | * @param y the new Y coordinate
|
---|
195 | * @param w the new width
|
---|
196 | * @param h the new height
|
---|
197 | */
|
---|
198 | public void setFrame(double x, double y, double w, double h)
|
---|
199 | {
|
---|
200 | setRect(x, y, w, h);
|
---|
201 | }
|
---|
202 |
|
---|
203 | /**
|
---|
204 | * Returns the bounds of this rectangle. A pretty useless method, as this
|
---|
205 | * is already a rectangle.
|
---|
206 | *
|
---|
207 | * @return a copy of this rectangle
|
---|
208 | */
|
---|
209 | public Rectangle2D getBounds2D()
|
---|
210 | {
|
---|
211 | return (Rectangle2D) clone();
|
---|
212 | }
|
---|
213 |
|
---|
214 | /**
|
---|
215 | * Test if the given point is contained in the rectangle.
|
---|
216 | *
|
---|
217 | * @param x the x coordinate of the point
|
---|
218 | * @param y the y coordinate of the point
|
---|
219 | * @return true if (x,y) is in the rectangle
|
---|
220 | */
|
---|
221 | public boolean contains(double x, double y)
|
---|
222 | {
|
---|
223 | double mx = getX();
|
---|
224 | double my = getY();
|
---|
225 | double w = getWidth();
|
---|
226 | double h = getHeight();
|
---|
227 | return w > 0 && h > 0 && x >= mx && x < mx + w && y >= my && y < my + h;
|
---|
228 | }
|
---|
229 |
|
---|
230 | /**
|
---|
231 | * Tests if the given rectangle intersects this one. In other words, test if
|
---|
232 | * the two rectangles share at least one internal point.
|
---|
233 | *
|
---|
234 | * @param x the x coordinate of the other rectangle
|
---|
235 | * @param y the y coordinate of the other rectangle
|
---|
236 | * @param w the width of the other rectangle
|
---|
237 | * @param h the height of the other rectangle
|
---|
238 | * @return true if the rectangles intersect
|
---|
239 | */
|
---|
240 | public boolean intersects(double x, double y, double w, double h)
|
---|
241 | {
|
---|
242 | double mx = getX();
|
---|
243 | double my = getY();
|
---|
244 | double mw = getWidth();
|
---|
245 | double mh = getHeight();
|
---|
246 | return w > 0 && h > 0 && mw > 0 && mh > 0
|
---|
247 | && x < mx + mw && x + w > mx && y < my + mh && y + h > my;
|
---|
248 | }
|
---|
249 |
|
---|
250 | /**
|
---|
251 | * Tests if this rectangle contains the given one. In other words, test if
|
---|
252 | * this rectangle contains all points in the given one.
|
---|
253 | *
|
---|
254 | * @param x the x coordinate of the other rectangle
|
---|
255 | * @param y the y coordinate of the other rectangle
|
---|
256 | * @param w the width of the other rectangle
|
---|
257 | * @param h the height of the other rectangle
|
---|
258 | * @return true if this rectangle contains the other
|
---|
259 | */
|
---|
260 | public boolean contains(double x, double y, double w, double h)
|
---|
261 | {
|
---|
262 | double mx = getX();
|
---|
263 | double my = getY();
|
---|
264 | double mw = getWidth();
|
---|
265 | double mh = getHeight();
|
---|
266 | return w > 0 && h > 0 && mw > 0 && mh > 0
|
---|
267 | && x >= mx && x + w <= mx + mw && y >= my && y + h <= my + mh;
|
---|
268 | }
|
---|
269 |
|
---|
270 | /**
|
---|
271 | * Return a new rectangle which is the intersection of this and the given
|
---|
272 | * one. The result will be empty if there is no intersection.
|
---|
273 | *
|
---|
274 | * @param r the rectangle to be intersected
|
---|
275 | * @return the intersection
|
---|
276 | * @throws NullPointerException if r is null
|
---|
277 | */
|
---|
278 | public abstract Rectangle2D createIntersection(Rectangle2D r);
|
---|
279 |
|
---|
280 | /**
|
---|
281 | * Intersects a pair of rectangles, and places the result in the
|
---|
282 | * destination; this can be used to avoid object creation. This method
|
---|
283 | * even works when the destination is also a source, although you stand
|
---|
284 | * to lose the original data.
|
---|
285 | *
|
---|
286 | * @param src1 the first source
|
---|
287 | * @param src2 the second source
|
---|
288 | * @param dest the destination for the intersection
|
---|
289 | * @throws NullPointerException if any rectangle is null
|
---|
290 | */
|
---|
291 | public static void intersect(Rectangle2D src1, Rectangle2D src2,
|
---|
292 | Rectangle2D dest)
|
---|
293 | {
|
---|
294 | double x = Math.max(src1.getX(), src2.getX());
|
---|
295 | double y = Math.max(src1.getY(), src2.getY());
|
---|
296 | double maxx = Math.min(src1.getMaxX(), src2.getMaxX());
|
---|
297 | double maxy = Math.min(src1.getMaxY(), src2.getMaxY());
|
---|
298 | dest.setRect(x, y, maxx - x, maxy - y);
|
---|
299 | }
|
---|
300 |
|
---|
301 | /**
|
---|
302 | * Return a new rectangle which is the union of this and the given one.
|
---|
303 | *
|
---|
304 | * @param r the rectangle to be merged
|
---|
305 | * @return the union
|
---|
306 | * @throws NullPointerException if r is null
|
---|
307 | */
|
---|
308 | public abstract Rectangle2D createUnion(Rectangle2D r);
|
---|
309 |
|
---|
310 | /**
|
---|
311 | * Joins a pair of rectangles, and places the result in the destination;
|
---|
312 | * this can be used to avoid object creation. This method even works when
|
---|
313 | * the destination is also a source, although you stand to lose the
|
---|
314 | * original data.
|
---|
315 | *
|
---|
316 | * @param src1 the first source
|
---|
317 | * @param src2 the second source
|
---|
318 | * @param dest the destination for the union
|
---|
319 | * @throws NullPointerException if any rectangle is null
|
---|
320 | */
|
---|
321 | public static void union(Rectangle2D src1, Rectangle2D src2,
|
---|
322 | Rectangle2D dest)
|
---|
323 | {
|
---|
324 | double x = Math.min(src1.getX(), src2.getX());
|
---|
325 | double y = Math.min(src1.getY(), src2.getY());
|
---|
326 | double maxx = Math.max(src1.getMaxX(), src2.getMaxX());
|
---|
327 | double maxy = Math.max(src1.getMaxY(), src2.getMaxY());
|
---|
328 | dest.setRect(x, y, maxx - x, maxy - y);
|
---|
329 | }
|
---|
330 |
|
---|
331 | /**
|
---|
332 | * Modifies this rectangle so that it represents the smallest rectangle
|
---|
333 | * that contains both the existing rectangle and the specified point.
|
---|
334 | * However, if the point falls on one of the two borders which are not
|
---|
335 | * inside the rectangle, a subsequent call to <code>contains</code> may
|
---|
336 | * return false.
|
---|
337 | *
|
---|
338 | * @param x the X coordinate of the point to add to this rectangle
|
---|
339 | * @param y the Y coordinate of the point to add to this rectangle
|
---|
340 | */
|
---|
341 | public void add(double newx, double newy)
|
---|
342 | {
|
---|
343 | double minx = Math.min(getX(), newx);
|
---|
344 | double maxx = Math.max(getMaxX(), newx);
|
---|
345 | double miny = Math.min(getY(), newy);
|
---|
346 | double maxy = Math.max(getMaxY(), newy);
|
---|
347 | setRect(minx, miny, maxx - minx, maxy - miny);
|
---|
348 | }
|
---|
349 |
|
---|
350 | /**
|
---|
351 | * Modifies this rectangle so that it represents the smallest rectangle
|
---|
352 | * that contains both the existing rectangle and the specified point.
|
---|
353 | * However, if the point falls on one of the two borders which are not
|
---|
354 | * inside the rectangle, a subsequent call to <code>contains</code> may
|
---|
355 | * return false.
|
---|
356 | *
|
---|
357 | * @param p the point to add to this rectangle
|
---|
358 | * @throws NullPointerException if p is null
|
---|
359 | */
|
---|
360 | public void add(Point2D p)
|
---|
361 | {
|
---|
362 | add(p.getX(), p.getY());
|
---|
363 | }
|
---|
364 |
|
---|
365 | /**
|
---|
366 | * Modifies this rectangle so that it represents the smallest rectangle
|
---|
367 | * that contains both the existing rectangle and the specified rectangle.
|
---|
368 | *
|
---|
369 | * @param r the rectangle to add to this rectangle
|
---|
370 | * @throws NullPointerException if r is null
|
---|
371 | * @see #union(Rectangle2D)
|
---|
372 | */
|
---|
373 | public void add(Rectangle2D r)
|
---|
374 | {
|
---|
375 | union(this, r, this);
|
---|
376 | }
|
---|
377 |
|
---|
378 | /**
|
---|
379 | * Return an iterator along the shape boundary. If the optional transform
|
---|
380 | * is provided, the iterator is transformed accordingly. Each call returns
|
---|
381 | * a new object, independent from others in use. This iterator is thread
|
---|
382 | * safe; modifications to the rectangle do not affect the results of this
|
---|
383 | * path instance.
|
---|
384 | *
|
---|
385 | * @param transform an optional transform to apply to the iterator
|
---|
386 | * @return a new iterator over the boundary
|
---|
387 | * @since 1.2
|
---|
388 | */
|
---|
389 | public PathIterator getPathIterator(final AffineTransform at)
|
---|
390 | {
|
---|
391 | final double minx = getX();
|
---|
392 | final double miny = getY();
|
---|
393 | final double maxx = minx + getWidth();
|
---|
394 | final double maxy = miny + getHeight();
|
---|
395 | return new PathIterator()
|
---|
396 | {
|
---|
397 | /** Current coordinate. */
|
---|
398 | private int current = (maxx >= minx && maxy >= miny) ? 6 : 0;
|
---|
399 |
|
---|
400 | public int getWindingRule()
|
---|
401 | {
|
---|
402 | return WIND_EVEN_ODD;
|
---|
403 | }
|
---|
404 |
|
---|
405 | public boolean isDone()
|
---|
406 | {
|
---|
407 | return current > 5;
|
---|
408 | }
|
---|
409 |
|
---|
410 | public void next()
|
---|
411 | {
|
---|
412 | current++;
|
---|
413 | }
|
---|
414 |
|
---|
415 | public int currentSegment(float[] coords)
|
---|
416 | {
|
---|
417 | switch (current)
|
---|
418 | {
|
---|
419 | case 1:
|
---|
420 | coords[0] = (float) maxx;
|
---|
421 | coords[1] = (float) miny;
|
---|
422 | break;
|
---|
423 | case 2:
|
---|
424 | coords[0] = (float) maxx;
|
---|
425 | coords[1] = (float) maxy;
|
---|
426 | break;
|
---|
427 | case 3:
|
---|
428 | coords[0] = (float) minx;
|
---|
429 | coords[1] = (float) maxy;
|
---|
430 | break;
|
---|
431 | case 0:
|
---|
432 | case 4:
|
---|
433 | coords[0] = (float) minx;
|
---|
434 | coords[1] = (float) miny;
|
---|
435 | break;
|
---|
436 | case 5:
|
---|
437 | return SEG_CLOSE;
|
---|
438 | default:
|
---|
439 | throw new NoSuchElementException("rect iterator out of bounds");
|
---|
440 | }
|
---|
441 | if (at != null)
|
---|
442 | at.transform(coords, 0, coords, 0, 1);
|
---|
443 | return current == 0 ? SEG_MOVETO : SEG_LINETO;
|
---|
444 | }
|
---|
445 |
|
---|
446 | public int currentSegment(double[] coords)
|
---|
447 | {
|
---|
448 | switch (current)
|
---|
449 | {
|
---|
450 | case 1:
|
---|
451 | coords[0] = maxx;
|
---|
452 | coords[1] = miny;
|
---|
453 | break;
|
---|
454 | case 2:
|
---|
455 | coords[0] = maxx;
|
---|
456 | coords[1] = maxy;
|
---|
457 | break;
|
---|
458 | case 3:
|
---|
459 | coords[0] = minx;
|
---|
460 | coords[1] = maxy;
|
---|
461 | break;
|
---|
462 | case 0:
|
---|
463 | case 4:
|
---|
464 | coords[0] = minx;
|
---|
465 | coords[1] = miny;
|
---|
466 | break;
|
---|
467 | case 5:
|
---|
468 | return SEG_CLOSE;
|
---|
469 | default:
|
---|
470 | throw new NoSuchElementException("rect iterator out of bounds");
|
---|
471 | }
|
---|
472 | if (at != null)
|
---|
473 | at.transform(coords, 0, coords, 0, 1);
|
---|
474 | return current == 0 ? SEG_MOVETO : SEG_LINETO;
|
---|
475 | }
|
---|
476 | };
|
---|
477 | }
|
---|
478 |
|
---|
479 | /**
|
---|
480 | * Return an iterator along the shape boundary. If the optional transform
|
---|
481 | * is provided, the iterator is transformed accordingly. Each call returns
|
---|
482 | * a new object, independent from others in use. This iterator is thread
|
---|
483 | * safe; modifications to the rectangle do not affect the results of this
|
---|
484 | * path instance. As the rectangle is already flat, the flatness parameter
|
---|
485 | * is ignored.
|
---|
486 | *
|
---|
487 | * @param transform an optional transform to apply to the iterator
|
---|
488 | * @param double the maximum distance for deviation from the real boundary
|
---|
489 | * @return a new iterator over the boundary
|
---|
490 | * @since 1.2
|
---|
491 | */
|
---|
492 | public PathIterator getPathIterator(AffineTransform at, double flatness)
|
---|
493 | {
|
---|
494 | return getPathIterator(at);
|
---|
495 | }
|
---|
496 |
|
---|
497 | /**
|
---|
498 | * Return the hashcode for this rectangle. The formula is not documented, but
|
---|
499 | * appears to be the same as:
|
---|
500 | * <pre>
|
---|
501 | * long l = Double.doubleToLongBits(getX())
|
---|
502 | * + 37 * Double.doubleToLongBits(getY())
|
---|
503 | * + 43 * Double.doubleToLongBits(getWidth())
|
---|
504 | * + 47 * Double.doubleToLongBits(getHeight());
|
---|
505 | * return (int) ((l >> 32) ^ l);
|
---|
506 | * </pre>
|
---|
507 | *
|
---|
508 | * @return the hashcode
|
---|
509 | */
|
---|
510 | public int hashCode()
|
---|
511 | {
|
---|
512 | // Talk about a fun time reverse engineering this one!
|
---|
513 | long l = java.lang.Double.doubleToLongBits(getX())
|
---|
514 | + 37 * java.lang.Double.doubleToLongBits(getY())
|
---|
515 | + 43 * java.lang.Double.doubleToLongBits(getWidth())
|
---|
516 | + 47 * java.lang.Double.doubleToLongBits(getHeight());
|
---|
517 | return (int) ((l >> 32) ^ l);
|
---|
518 | }
|
---|
519 |
|
---|
520 | /**
|
---|
521 | * Tests this rectangle for equality against the specified object. This
|
---|
522 | * will be true if an only if the specified object is an instance of
|
---|
523 | * Rectangle2D with the same coordinates and dimensions.
|
---|
524 | *
|
---|
525 | * @param obj the object to test against for equality
|
---|
526 | * @return true if the specified object is equal to this one
|
---|
527 | */
|
---|
528 | public boolean equals(Object obj)
|
---|
529 | {
|
---|
530 | if (! (obj instanceof Rectangle2D))
|
---|
531 | return false;
|
---|
532 | Rectangle2D r = (Rectangle2D) obj;
|
---|
533 | return r.getX() == getX() && r.getY() == getY()
|
---|
534 | && r.getWidth() == getWidth() && r.getHeight() == getHeight();
|
---|
535 | }
|
---|
536 |
|
---|
537 | /**
|
---|
538 | * This class defines a rectangle in <code>double</code> precision.
|
---|
539 | *
|
---|
540 | * @author Eric Blake <ebb9@email.byu.edu>
|
---|
541 | * @since 1.2
|
---|
542 | * @status updated to 1.4
|
---|
543 | */
|
---|
544 | public static class Double extends Rectangle2D
|
---|
545 | {
|
---|
546 | /** The x coordinate of the lower left corner. */
|
---|
547 | public double x;
|
---|
548 |
|
---|
549 | /** The y coordinate of the lower left corner. */
|
---|
550 | public double y;
|
---|
551 |
|
---|
552 | /** The width of the rectangle. */
|
---|
553 | public double width;
|
---|
554 |
|
---|
555 | /** The height of the rectangle. */
|
---|
556 | public double height;
|
---|
557 |
|
---|
558 | /**
|
---|
559 | * Create a rectangle at (0,0) with width 0 and height 0.
|
---|
560 | */
|
---|
561 | public Double()
|
---|
562 | {
|
---|
563 | }
|
---|
564 |
|
---|
565 | /**
|
---|
566 | * Create a rectangle with the given values.
|
---|
567 | *
|
---|
568 | * @param x the x coordinate
|
---|
569 | * @param y the y coordinate
|
---|
570 | * @param w the width
|
---|
571 | * @param h the height
|
---|
572 | */
|
---|
573 | public Double(double x, double y, double w, double h)
|
---|
574 | {
|
---|
575 | this.x = x;
|
---|
576 | this.y = y;
|
---|
577 | width = w;
|
---|
578 | height = h;
|
---|
579 | }
|
---|
580 |
|
---|
581 | /**
|
---|
582 | * Return the X coordinate.
|
---|
583 | *
|
---|
584 | * @return the value of x
|
---|
585 | */
|
---|
586 | public double getX()
|
---|
587 | {
|
---|
588 | return x;
|
---|
589 | }
|
---|
590 |
|
---|
591 | /**
|
---|
592 | * Return the Y coordinate.
|
---|
593 | *
|
---|
594 | * @return the value of y
|
---|
595 | */
|
---|
596 | public double getY()
|
---|
597 | {
|
---|
598 | return y;
|
---|
599 | }
|
---|
600 |
|
---|
601 | /**
|
---|
602 | * Return the width.
|
---|
603 | *
|
---|
604 | * @return the value of width
|
---|
605 | */
|
---|
606 | public double getWidth()
|
---|
607 | {
|
---|
608 | return width;
|
---|
609 | }
|
---|
610 |
|
---|
611 | /**
|
---|
612 | * Return the height.
|
---|
613 | *
|
---|
614 | * @return the value of height
|
---|
615 | */
|
---|
616 | public double getHeight()
|
---|
617 | {
|
---|
618 | return height;
|
---|
619 | }
|
---|
620 |
|
---|
621 | /**
|
---|
622 | * Test if the rectangle is empty.
|
---|
623 | *
|
---|
624 | * @return true if width or height is not positive
|
---|
625 | */
|
---|
626 | public boolean isEmpty()
|
---|
627 | {
|
---|
628 | return width <= 0 || height <= 0;
|
---|
629 | }
|
---|
630 |
|
---|
631 | /**
|
---|
632 | * Set the contents of this rectangle to those specified.
|
---|
633 | *
|
---|
634 | * @param x the x coordinate
|
---|
635 | * @param y the y coordinate
|
---|
636 | * @param w the width
|
---|
637 | * @param h the height
|
---|
638 | */
|
---|
639 | public void setRect(double x, double y, double w, double h)
|
---|
640 | {
|
---|
641 | this.x = x;
|
---|
642 | this.y = y;
|
---|
643 | width = w;
|
---|
644 | height = h;
|
---|
645 | }
|
---|
646 |
|
---|
647 | /**
|
---|
648 | * Set the contents of this rectangle to those specified.
|
---|
649 | *
|
---|
650 | * @param r the rectangle to copy
|
---|
651 | * @throws NullPointerException if r is null
|
---|
652 | */
|
---|
653 | public void setRect(Rectangle2D r)
|
---|
654 | {
|
---|
655 | x = r.getX();
|
---|
656 | y = r.getY();
|
---|
657 | width = r.getWidth();
|
---|
658 | height = r.getHeight();
|
---|
659 | }
|
---|
660 |
|
---|
661 | /**
|
---|
662 | * Determine where the point lies with respect to this rectangle. The
|
---|
663 | * result will be the binary OR of the appropriate bit masks.
|
---|
664 | *
|
---|
665 | * @param x the x coordinate to check
|
---|
666 | * @param y the y coordinate to check
|
---|
667 | * @return the binary OR of the result
|
---|
668 | * @see #OUT_LEFT
|
---|
669 | * @see #OUT_TOP
|
---|
670 | * @see #OUT_RIGHT
|
---|
671 | * @see #OUT_BOTTOM
|
---|
672 | * @since 1.2
|
---|
673 | */
|
---|
674 | public int outcode(double x, double y)
|
---|
675 | {
|
---|
676 | int result = 0;
|
---|
677 | if (width <= 0)
|
---|
678 | result |= OUT_LEFT | OUT_RIGHT;
|
---|
679 | else if (x < this.x)
|
---|
680 | result |= OUT_LEFT;
|
---|
681 | else if (x > this.x + width)
|
---|
682 | result |= OUT_RIGHT;
|
---|
683 | if (height <= 0)
|
---|
684 | result |= OUT_BOTTOM | OUT_TOP;
|
---|
685 | else if (y < this.y) // Remember that +y heads top-to-bottom.
|
---|
686 | result |= OUT_TOP;
|
---|
687 | else if (y > this.y + height)
|
---|
688 | result |= OUT_BOTTOM;
|
---|
689 | return result;
|
---|
690 | }
|
---|
691 |
|
---|
692 | /**
|
---|
693 | * Returns the bounds of this rectangle. A pretty useless method, as this
|
---|
694 | * is already a rectangle.
|
---|
695 | *
|
---|
696 | * @return a copy of this rectangle
|
---|
697 | */
|
---|
698 | public Rectangle2D getBounds2D()
|
---|
699 | {
|
---|
700 | return new Double(x, y, width, height);
|
---|
701 | }
|
---|
702 |
|
---|
703 | /**
|
---|
704 | * Return a new rectangle which is the intersection of this and the given
|
---|
705 | * one. The result will be empty if there is no intersection.
|
---|
706 | *
|
---|
707 | * @param r the rectangle to be intersected
|
---|
708 | * @return the intersection
|
---|
709 | * @throws NullPointerException if r is null
|
---|
710 | */
|
---|
711 | public Rectangle2D createIntersection(Rectangle2D r)
|
---|
712 | {
|
---|
713 | Double res = new Double();
|
---|
714 | intersect(this, r, res);
|
---|
715 | return res;
|
---|
716 | }
|
---|
717 |
|
---|
718 | /**
|
---|
719 | * Return a new rectangle which is the union of this and the given one.
|
---|
720 | *
|
---|
721 | * @param r the rectangle to be merged
|
---|
722 | * @return the union
|
---|
723 | * @throws NullPointerException if r is null
|
---|
724 | */
|
---|
725 | public Rectangle2D createUnion(Rectangle2D r)
|
---|
726 | {
|
---|
727 | Double res = new Double();
|
---|
728 | union(this, r, res);
|
---|
729 | return res;
|
---|
730 | }
|
---|
731 |
|
---|
732 | /**
|
---|
733 | * Returns a string representation of this rectangle. This is in the form
|
---|
734 | * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
|
---|
735 | * + ",h=" + height + ']'</code>.
|
---|
736 | *
|
---|
737 | * @return a string representation of this rectangle
|
---|
738 | */
|
---|
739 | public String toString()
|
---|
740 | {
|
---|
741 | return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
|
---|
742 | + ",h=" + height + ']';
|
---|
743 | }
|
---|
744 | } // class Double
|
---|
745 |
|
---|
746 | /**
|
---|
747 | * This class defines a rectangle in <code>float</code> precision.
|
---|
748 | *
|
---|
749 | * @author Eric Blake <ebb9@email.byu.edu>
|
---|
750 | * @since 1.2
|
---|
751 | * @status updated to 1.4
|
---|
752 | */
|
---|
753 | public static class Float extends Rectangle2D
|
---|
754 | {
|
---|
755 | /** The x coordinate of the lower left corner. */
|
---|
756 | public float x;
|
---|
757 |
|
---|
758 | /** The y coordinate of the lower left corner. */
|
---|
759 | public float y;
|
---|
760 |
|
---|
761 | /** The width of the rectangle. */
|
---|
762 | public float width;
|
---|
763 |
|
---|
764 | /** The height of the rectangle. */
|
---|
765 | public float height;
|
---|
766 |
|
---|
767 | /**
|
---|
768 | * Create a rectangle at (0,0) with width 0 and height 0.
|
---|
769 | */
|
---|
770 | public Float()
|
---|
771 | {
|
---|
772 | }
|
---|
773 |
|
---|
774 | /**
|
---|
775 | * Create a rectangle with the given values.
|
---|
776 | *
|
---|
777 | * @param x the x coordinate
|
---|
778 | * @param y the y coordinate
|
---|
779 | * @param w the width
|
---|
780 | * @param h the height
|
---|
781 | */
|
---|
782 | public Float(float x, float y, float w, float h)
|
---|
783 | {
|
---|
784 | this.x = x;
|
---|
785 | this.y = y;
|
---|
786 | width = w;
|
---|
787 | height = h;
|
---|
788 | }
|
---|
789 |
|
---|
790 | /**
|
---|
791 | * Create a rectangle with the given values.
|
---|
792 | *
|
---|
793 | * @param x the x coordinate
|
---|
794 | * @param y the y coordinate
|
---|
795 | * @param w the width
|
---|
796 | * @param h the height
|
---|
797 | */
|
---|
798 | Float(double x, double y, double w, double h)
|
---|
799 | {
|
---|
800 | this.x = (float) x;
|
---|
801 | this.y = (float) y;
|
---|
802 | width = (float) w;
|
---|
803 | height = (float) h;
|
---|
804 | }
|
---|
805 |
|
---|
806 | /**
|
---|
807 | * Return the X coordinate.
|
---|
808 | *
|
---|
809 | * @return the value of x
|
---|
810 | */
|
---|
811 | public double getX()
|
---|
812 | {
|
---|
813 | return x;
|
---|
814 | }
|
---|
815 |
|
---|
816 | /**
|
---|
817 | * Return the Y coordinate.
|
---|
818 | *
|
---|
819 | * @return the value of y
|
---|
820 | */
|
---|
821 | public double getY()
|
---|
822 | {
|
---|
823 | return y;
|
---|
824 | }
|
---|
825 |
|
---|
826 | /**
|
---|
827 | * Return the width.
|
---|
828 | *
|
---|
829 | * @return the value of width
|
---|
830 | */
|
---|
831 | public double getWidth()
|
---|
832 | {
|
---|
833 | return width;
|
---|
834 | }
|
---|
835 |
|
---|
836 | /**
|
---|
837 | * Return the height.
|
---|
838 | *
|
---|
839 | * @return the value of height
|
---|
840 | */
|
---|
841 | public double getHeight()
|
---|
842 | {
|
---|
843 | return height;
|
---|
844 | }
|
---|
845 |
|
---|
846 | /**
|
---|
847 | * Test if the rectangle is empty.
|
---|
848 | *
|
---|
849 | * @return true if width or height is not positive
|
---|
850 | */
|
---|
851 | public boolean isEmpty()
|
---|
852 | {
|
---|
853 | return width <= 0 || height <= 0;
|
---|
854 | }
|
---|
855 |
|
---|
856 | /**
|
---|
857 | * Set the contents of this rectangle to those specified.
|
---|
858 | *
|
---|
859 | * @param x the x coordinate
|
---|
860 | * @param y the y coordinate
|
---|
861 | * @param w the width
|
---|
862 | * @param h the height
|
---|
863 | */
|
---|
864 | public void setRect(float x, float y, float w, float h)
|
---|
865 | {
|
---|
866 | this.x = x;
|
---|
867 | this.y = y;
|
---|
868 | width = w;
|
---|
869 | height = h;
|
---|
870 | }
|
---|
871 |
|
---|
872 | /**
|
---|
873 | * Set the contents of this rectangle to those specified.
|
---|
874 | *
|
---|
875 | * @param x the x coordinate
|
---|
876 | * @param y the y coordinate
|
---|
877 | * @param w the width
|
---|
878 | * @param h the height
|
---|
879 | */
|
---|
880 | public void setRect(double x, double y, double w, double h)
|
---|
881 | {
|
---|
882 | this.x = (float) x;
|
---|
883 | this.y = (float) y;
|
---|
884 | width = (float) w;
|
---|
885 | height = (float) h;
|
---|
886 | }
|
---|
887 |
|
---|
888 | /**
|
---|
889 | * Set the contents of this rectangle to those specified.
|
---|
890 | *
|
---|
891 | * @param r the rectangle to copy
|
---|
892 | * @throws NullPointerException if r is null
|
---|
893 | */
|
---|
894 | public void setRect(Rectangle2D r)
|
---|
895 | {
|
---|
896 | x = (float) r.getX();
|
---|
897 | y = (float) r.getY();
|
---|
898 | width = (float) r.getWidth();
|
---|
899 | height = (float) r.getHeight();
|
---|
900 | }
|
---|
901 |
|
---|
902 | /**
|
---|
903 | * Determine where the point lies with respect to this rectangle. The
|
---|
904 | * result will be the binary OR of the appropriate bit masks.
|
---|
905 | *
|
---|
906 | * @param x the x coordinate to check
|
---|
907 | * @param y the y coordinate to check
|
---|
908 | * @return the binary OR of the result
|
---|
909 | * @see #OUT_LEFT
|
---|
910 | * @see #OUT_TOP
|
---|
911 | * @see #OUT_RIGHT
|
---|
912 | * @see #OUT_BOTTOM
|
---|
913 | * @since 1.2
|
---|
914 | */
|
---|
915 | public int outcode(double x, double y)
|
---|
916 | {
|
---|
917 | int result = 0;
|
---|
918 | if (width <= 0)
|
---|
919 | result |= OUT_LEFT | OUT_RIGHT;
|
---|
920 | else if (x < this.x)
|
---|
921 | result |= OUT_LEFT;
|
---|
922 | else if (x > this.x + width)
|
---|
923 | result |= OUT_RIGHT;
|
---|
924 | if (height <= 0)
|
---|
925 | result |= OUT_BOTTOM | OUT_TOP;
|
---|
926 | else if (y < this.y) // Remember that +y heads top-to-bottom.
|
---|
927 | result |= OUT_TOP;
|
---|
928 | else if (y > this.y + height)
|
---|
929 | result |= OUT_BOTTOM;
|
---|
930 | return result;
|
---|
931 | }
|
---|
932 |
|
---|
933 | /**
|
---|
934 | * Returns the bounds of this rectangle. A pretty useless method, as this
|
---|
935 | * is already a rectangle.
|
---|
936 | *
|
---|
937 | * @return a copy of this rectangle
|
---|
938 | */
|
---|
939 | public Rectangle2D getBounds2D()
|
---|
940 | {
|
---|
941 | return new Float(x, y, width, height);
|
---|
942 | }
|
---|
943 |
|
---|
944 | /**
|
---|
945 | * Return a new rectangle which is the intersection of this and the given
|
---|
946 | * one. The result will be empty if there is no intersection.
|
---|
947 | *
|
---|
948 | * @param r the rectangle to be intersected
|
---|
949 | * @return the intersection
|
---|
950 | * @throws NullPointerException if r is null
|
---|
951 | */
|
---|
952 | public Rectangle2D createIntersection(Rectangle2D r)
|
---|
953 | {
|
---|
954 | Float res = new Float();
|
---|
955 | intersect(this, r, res);
|
---|
956 | return res;
|
---|
957 | }
|
---|
958 |
|
---|
959 | /**
|
---|
960 | * Return a new rectangle which is the union of this and the given one.
|
---|
961 | *
|
---|
962 | * @param r the rectangle to be merged
|
---|
963 | * @return the union
|
---|
964 | * @throws NullPointerException if r is null
|
---|
965 | */
|
---|
966 | public Rectangle2D createUnion(Rectangle2D r)
|
---|
967 | {
|
---|
968 | Float res = new Float();
|
---|
969 | union(this, r, res);
|
---|
970 | return res;
|
---|
971 | }
|
---|
972 |
|
---|
973 | /**
|
---|
974 | * Returns a string representation of this rectangle. This is in the form
|
---|
975 | * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
|
---|
976 | * + ",h=" + height + ']'</code>.
|
---|
977 | *
|
---|
978 | * @return a string representation of this rectangle
|
---|
979 | */
|
---|
980 | public String toString()
|
---|
981 | {
|
---|
982 | return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
|
---|
983 | + ",h=" + height + ']';
|
---|
984 | }
|
---|
985 | } // class Float
|
---|
986 | } // class Rectangle2D
|
---|