]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/com/infomatiq/jsi/Rectangle.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / com / infomatiq / jsi / Rectangle.java
1 //   Rectangle.java\r
2 //   Java Spatial Index Library\r
3 //   Copyright (C) 2002-2005 Infomatiq Limited\r
4 //  \r
5 //  This library is free software; you can redistribute it and/or\r
6 //  modify it under the terms of the GNU Lesser General Public\r
7 //  License as published by the Free Software Foundation; either\r
8 //  version 2.1 of the License, or (at your option) any later version.\r
9 //  \r
10 //  This library is distributed in the hope that it will be useful,\r
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
13 //  Lesser General Public License for more details.\r
14 //  \r
15 //  You should have received a copy of the GNU Lesser General Public\r
16 //  License along with this library; if not, write to the Free Software\r
17 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA\r
18 \r
19 package com.infomatiq.jsi;\r
20 \r
21 \r
22 \r
23 /**\r
24  * Currently hardcoded to 2 dimensions, but could be extended.\r
25  * \r
26  * @author  aled@sourceforge.net\r
27  * @version 1.0b8\r
28  */\r
29 public class Rectangle {\r
30   \r
31   /**\r
32    * use primitives instead of arrays for the coordinates of the rectangle,\r
33    * to reduce memory requirements.\r
34    */\r
35   public float minX, minY, maxX, maxY;\r
36   \r
37   public Rectangle() {\r
38     minX = Float.MAX_VALUE;\r
39     minY = Float.MAX_VALUE;\r
40     maxX = -Float.MAX_VALUE;\r
41     maxY = -Float.MAX_VALUE;\r
42   }\r
43   \r
44   /**\r
45    * Constructor.\r
46    * \r
47    * @param x1 coordinate of any corner of the rectangle\r
48    * @param y1 (see x1)\r
49    * @param x2 coordinate of the opposite corner\r
50    * @param y2 (see x2)\r
51    */\r
52   public Rectangle(float x1, float y1, float x2, float y2) {\r
53     set(x1, y1, x2, y2);\r
54   }\r
55 \r
56  /**\r
57    * Sets the size of the rectangle.\r
58    * \r
59    * @param x1 coordinate of any corner of the rectangle\r
60    * @param y1 (see x1)\r
61    * @param x2 coordinate of the opposite corner\r
62    * @param y2 (see x2)\r
63    */\r
64   public void set(float x1, float y1, float x2, float y2) {\r
65     minX = Math.min(x1, x2);\r
66     maxX = Math.max(x1, x2);\r
67     minY = Math.min(y1, y2);\r
68     maxY = Math.max(y1, y2);\r
69   }\r
70   \r
71   /**\r
72    * Sets the size of this rectangle to equal the passed rectangle.\r
73    */\r
74   public void set(Rectangle r) {\r
75     minX = r.minX;\r
76     minY = r.minY;\r
77     maxX = r.maxX;\r
78     maxY = r.maxY;  \r
79   }\r
80    \r
81   /**\r
82    * Make a copy of this rectangle\r
83    * \r
84    * @return copy of this rectangle\r
85    */\r
86   public Rectangle copy() {\r
87     return new Rectangle(minX, minY, maxX, maxY); \r
88   }\r
89   \r
90   /**\r
91    * Determine whether an edge of this rectangle overlies the equivalent \r
92    * edge of the passed rectangle\r
93    */\r
94   public boolean edgeOverlaps(Rectangle r) {\r
95     return minX == r.minX || maxX == r.maxX || minY == r.minY || maxY == r.maxY;\r
96   }\r
97   \r
98   /**\r
99    * Determine whether this rectangle intersects the passed rectangle\r
100    * \r
101    * @param r The rectangle that might intersect this rectangle\r
102    * \r
103    * @return true if the rectangles intersect, false if they do not intersect\r
104    */\r
105   public boolean intersects(Rectangle r) {\r
106     return maxX >= r.minX && minX <= r.maxX && maxY >= r.minY && minY <= r.maxY;\r
107   }\r
108  \r
109   /**\r
110    * Determine whether or not two rectangles intersect\r
111    * \r
112    * @param r1MinX minimum X coordinate of rectangle 1\r
113    * @param r1MinY minimum Y coordinate of rectangle 1\r
114    * @param r1MaxX maximum X coordinate of rectangle 1\r
115    * @param r1MaxY maximum Y coordinate of rectangle 1\r
116    * @param r2MinX minimum X coordinate of rectangle 2\r
117    * @param r2MinY minimum Y coordinate of rectangle 2\r
118    * @param r2MaxX maximum X coordinate of rectangle 2\r
119    * @param r2MaxY maximum Y coordinate of rectangle 2\r
120    * \r
121    * @return true if r1 intersects r2, false otherwise.\r
122    */\r
123   static public boolean intersects(float r1MinX, float r1MinY, float r1MaxX, float r1MaxY,\r
124                                  float r2MinX, float r2MinY, float r2MaxX, float r2MaxY) { \r
125     return r1MaxX >= r2MinX && r1MinX <= r2MaxX && r1MaxY >= r2MinY && r1MinY <= r2MaxY;                           \r
126   }\r
127   \r
128   /**\r
129    * Determine whether this rectangle contains the passed rectangle\r
130    * \r
131    * @param r The rectangle that might be contained by this rectangle\r
132    * \r
133    * @return true if this rectangle contains the passed rectangle, false if\r
134    *         it does not\r
135    */\r
136   public boolean contains(Rectangle r) {\r
137     return maxX >= r.maxX && minX <= r.minX && maxY >= r.maxY && minY <= r.minY;   \r
138   }\r
139   \r
140   /**\r
141    * Determine whether or not one rectangle contains another.\r
142    * \r
143    * @param r1MinX minimum X coordinate of rectangle 1\r
144    * @param r1MinY minimum Y coordinate of rectangle 1\r
145    * @param r1MaxX maximum X coordinate of rectangle 1\r
146    * @param r1MaxY maximum Y coordinate of rectangle 1\r
147    * @param r2MinX minimum X coordinate of rectangle 2\r
148    * @param r2MinY minimum Y coordinate of rectangle 2\r
149    * @param r2MaxX maximum X coordinate of rectangle 2\r
150    * @param r2MaxY maximum Y coordinate of rectangle 2\r
151    * \r
152    * @return true if r1 contains r2, false otherwise.\r
153    */\r
154   static public boolean contains(float r1MinX, float r1MinY, float r1MaxX, float r1MaxY,\r
155                                  float r2MinX, float r2MinY, float r2MaxX, float r2MaxY) {\r
156     return r1MaxX >= r2MaxX && r1MinX <= r2MinX && r1MaxY >= r2MaxY && r1MinY <= r2MinY;                              \r
157   }\r
158  \r
159   /**\r
160    * Determine whether this rectangle is contained by the passed rectangle\r
161    * \r
162    * @param r The rectangle that might contain this rectangle\r
163    * \r
164    * @return true if the passed rectangle contains this rectangle, false if\r
165    *         it does not\r
166    */\r
167   public boolean containedBy(Rectangle r) {\r
168     return r.maxX >= maxX && r.minX <= minX && r.maxY >= maxY && r.minY <= minY;   \r
169   }\r
170   \r
171   /**\r
172    * Return the distance between this rectangle and the passed point.\r
173    * If the rectangle contains the point, the distance is zero.\r
174    * \r
175    * @param p Point to find the distance to\r
176    * \r
177    * @return distance beween this rectangle and the passed point.\r
178    */\r
179   public float distance(Point p) {\r
180     float distanceSquared = 0;\r
181     \r
182     float temp = minX - p.x;\r
183     if (temp < 0) {\r
184       temp = p.x - maxX;\r
185     }\r
186     \r
187     if (temp > 0) {\r
188       distanceSquared += (temp * temp);\r
189     }\r
190 \r
191     temp = minY - p.y;\r
192     if (temp < 0) {\r
193       temp = p.y - maxY;\r
194     }\r
195 \r
196     if (temp > 0) {\r
197       distanceSquared += (temp * temp);\r
198     }\r
199          \r
200     return (float) Math.sqrt(distanceSquared);\r
201   }\r
202   \r
203   /**\r
204    * Return the distance between a rectangle and a point.\r
205    * If the rectangle contains the point, the distance is zero.\r
206    * \r
207    * @param minX minimum X coordinate of rectangle\r
208    * @param minY minimum Y coordinate of rectangle\r
209    * @param maxX maximum X coordinate of rectangle\r
210    * @param maxY maximum Y coordinate of rectangle\r
211    * @param pX X coordinate of point\r
212    * @param pY Y coordinate of point\r
213    * \r
214    * @return distance beween this rectangle and the passed point.\r
215    */\r
216   static public float distance(float minX, float minY, float maxX, float maxY, float pX, float pY) {\r
217     return (float) Math.sqrt(distanceSq(minX, minY, maxX, maxY, pX, pY));\r
218   }\r
219   \r
220   static public float distanceSq(float minX, float minY, float maxX, float maxY, float pX, float pY) {\r
221     float distanceSqX = 0;\r
222     float distanceSqY = 0;\r
223     \r
224     if (minX > pX) {\r
225       distanceSqX = minX - pX;\r
226       distanceSqX *= distanceSqX;\r
227     } else if (pX > maxX) {\r
228       distanceSqX = pX - maxX;\r
229       distanceSqX *= distanceSqX;\r
230     }\r
231    \r
232     if (minY > pY) {\r
233       distanceSqY = minY - pY;\r
234       distanceSqY *= distanceSqY;\r
235     } else if (pY > maxY) {\r
236       distanceSqY = pY - maxY;\r
237       distanceSqY *= distanceSqY;\r
238     }\r
239    \r
240     return distanceSqX + distanceSqY;\r
241   }\r
242   \r
243   /**\r
244    * Return the distance between this rectangle and the passed rectangle.\r
245    * If the rectangles overlap, the distance is zero.\r
246    * \r
247    * @param r Rectangle to find the distance to\r
248    * \r
249    * @return distance between this rectangle and the passed rectangle\r
250    */\r
251 \r
252   public float distance(Rectangle r) {\r
253     float distanceSquared = 0;\r
254     float greatestMin = Math.max(minX, r.minX);\r
255     float leastMax    = Math.min(maxX, r.maxX);\r
256     if (greatestMin > leastMax) {\r
257       distanceSquared += ((greatestMin - leastMax) * (greatestMin - leastMax)); \r
258     }\r
259     greatestMin = Math.max(minY, r.minY);\r
260     leastMax    = Math.min(maxY, r.maxY);\r
261     if (greatestMin > leastMax) {\r
262       distanceSquared += ((greatestMin - leastMax) * (greatestMin - leastMax)); \r
263     }\r
264     return (float) Math.sqrt(distanceSquared);\r
265   }\r
266 \r
267   /**\r
268    * Calculate the area by which this rectangle would be enlarged if\r
269    * added to the passed rectangle. Neither rectangle is altered.\r
270    * \r
271    * @param r Rectangle to union with this rectangle, in order to \r
272    *          compute the difference in area of the union and the\r
273    *          original rectangle\r
274    * \r
275    * @return enlargement\r
276    */\r
277   public float enlargement(Rectangle r) {\r
278     float enlargedArea = (Math.max(maxX, r.maxX) - Math.min(minX, r.minX)) *\r
279                          (Math.max(maxY, r.maxY) - Math.min(minY, r.minY));\r
280                          \r
281     return enlargedArea - area();\r
282   }\r
283   \r
284   /**\r
285     * Calculate the area by which a rectangle would be enlarged if\r
286     * added to the passed rectangle..\r
287     * \r
288     * @param r1MinX minimum X coordinate of rectangle 1\r
289     * @param r1MinY minimum Y coordinate of rectangle 1\r
290     * @param r1MaxX maximum X coordinate of rectangle 1\r
291     * @param r1MaxY maximum Y coordinate of rectangle 1\r
292     * @param r2MinX minimum X coordinate of rectangle 2\r
293     * @param r2MinY minimum Y coordinate of rectangle 2\r
294     * @param r2MaxX maximum X coordinate of rectangle 2\r
295     * @param r2MaxY maximum Y coordinate of rectangle 2\r
296     * \r
297     * @return enlargement\r
298     */\r
299   static public float enlargement(float r1MinX, float r1MinY, float r1MaxX, float r1MaxY,\r
300                                   float r2MinX, float r2MinY, float r2MaxX, float r2MaxY) { \r
301     float r1Area = (r1MaxX - r1MinX) * (r1MaxY - r1MinY);                    \r
302     \r
303     if (r1Area == Float.POSITIVE_INFINITY) {\r
304       return 0; // cannot enlarge an infinite rectangle...\r
305     }\r
306     \r
307     if (r2MinX < r1MinX) r1MinX = r2MinX;   \r
308     if (r2MinY < r1MinY) r1MinY = r2MinY;   \r
309     if (r2MaxX > r1MaxX) r1MaxX = r2MaxX;                               \r
310     if (r2MaxY > r1MaxY) r1MaxY = r2MaxY;\r
311     \r
312     float r1r2UnionArea = (r1MaxX - r1MinX) * (r1MaxY - r1MinY);\r
313           \r
314     if (r1r2UnionArea == Float.POSITIVE_INFINITY) {\r
315       // if a finite rectangle is enlarged and becomes infinite,\r
316       // then the enlargement must be infinite.\r
317       return Float.POSITIVE_INFINITY;\r
318     }\r
319     return r1r2UnionArea - r1Area;                              \r
320   }\r
321   \r
322   /**\r
323    * Compute the area of this rectangle.\r
324    * \r
325    * @return The area of this rectangle\r
326    */\r
327   public float area() {\r
328     return (maxX - minX) * (maxY - minY);\r
329   }\r
330   \r
331   /**\r
332    * Compute the area of a rectangle.\r
333    * \r
334    * @param minX the minimum X coordinate of the rectangle\r
335    * @param minY the minimum Y coordinate of the rectangle\r
336    * @param maxX the maximum X coordinate of the rectangle\r
337    * @param maxY the maximum Y coordinate of the rectangle\r
338    * \r
339    * @return The area of the rectangle\r
340    */\r
341   static public float area(float minX, float minY, float maxX, float maxY) {\r
342     return (maxX - minX) * (maxY - minY);\r
343   }\r
344   \r
345   /**\r
346    * Computes the union of this rectangle and the passed rectangle, storing\r
347    * the result in this rectangle.\r
348    * \r
349    * @param r Rectangle to add to this rectangle\r
350    */\r
351   public void add(Rectangle r) {\r
352     if (r.minX < minX) minX = r.minX;\r
353     if (r.maxX > maxX) maxX = r.maxX;\r
354     if (r.minY < minY) minY = r.minY;\r
355     if (r.maxY > maxY) maxY = r.maxY;\r
356   }\r
357   \r
358   /**\r
359    * Computes the union of this rectangle and the passed point, storing\r
360    * the result in this rectangle.\r
361    * \r
362    * @param p Point to add to this rectangle\r
363    */\r
364   public void add(Point p) {\r
365     if (p.x < minX) minX = p.x;\r
366     if (p.x > maxX) maxX = p.x;\r
367     if (p.y < minY) minY = p.y;\r
368     if (p.y > maxY) maxY = p.y;\r
369   }\r
370   \r
371   /**\r
372    * Find the the union of this rectangle and the passed rectangle.\r
373    * Neither rectangle is altered\r
374    * \r
375    * @param r The rectangle to union with this rectangle\r
376    */\r
377   public Rectangle union(Rectangle r) {\r
378     Rectangle union = this.copy();\r
379     union.add(r);\r
380     return union; \r
381   }\r
382   \r
383   /**\r
384    * Determine whether this rectangle is equal to a given object.\r
385    * Equality is determined by the bounds of the rectangle.\r
386    * \r
387    * @param o The object to compare with this rectangle\r
388    */\r
389   public boolean equals(Object o) {\r
390     boolean equals = false;\r
391     if (o instanceof Rectangle) {\r
392       Rectangle r = (Rectangle) o;\r
393       if (minX == r.minX && minY == r.minY && maxX == r.maxX && maxY == r.maxY) {\r
394         equals = true;\r
395       }\r
396     } \r
397     return equals;       \r
398   }\r
399 \r
400   /** \r
401    * Determine whether this rectangle is the same as another object\r
402    * \r
403    * Note that two rectangles can be equal but not the same object, \r
404    * if they both have the same bounds.\r
405    * \r
406    * @param o The object to compare with this rectangle.\r
407    */  \r
408   public boolean sameObject(Object o) {\r
409     return super.equals(o); \r
410   }\r
411   \r
412   /**\r
413    * Return a string representation of this rectangle, in the form: \r
414    * (1.2, 3.4), (5.6, 7.8)\r
415    * \r
416    * @return String String representation of this rectangle.\r
417    */\r
418   public String toString() {\r
419     return "(" + minX + ", " + minY + "), (" + maxX + ", " + maxY + ")";\r
420   }\r
421   \r
422   /**\r
423    * Utility methods (not used by JSI); added to \r
424    * enable this to be used as a generic rectangle class \r
425    */\r
426   public float width() {\r
427     return maxX - minX;\r
428   }\r
429   \r
430   public float height() {\r
431     return maxY - minY;\r
432   }\r
433   \r
434   public float aspectRatio() {\r
435     return width() / height();\r
436   }\r
437   \r
438   public Point centre() {\r
439     return new Point((minX + maxX) / 2, (minY + maxY) / 2);\r
440   }\r
441   \r
442 }\r